--- /dev/null
+From 68538a5164672f666b511ac4373127567dcd233b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 27 Jun 2022 13:00:35 +0300
+Subject: ALSA: usb-audio: Add quirk for Fiero SC-01 (fw v1.0.0)
+
+From: Egor Vorontsov <sdoregor@sdore.me>
+
+[ Upstream commit 2307a0e1ca0b5c1337b37ac6302f96e017ebac3c ]
+
+The patch applies the same quirks used for SC-01 at firmware v1.1.0 to
+the ones running v1.0.0, with respect to hard-coded sample rates.
+
+I got two more units and successfully tested the patch series with both
+firmwares.
+
+The support is now complete (not accounting ASIO).
+
+Signed-off-by: Egor Vorontsov <sdoregor@sdore.me>
+Link: https://lore.kernel.org/r/20220627100041.2861494-2-sdoregor@sdore.me
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/usb/quirks-table.h | 132 +++++++++++++++++++++++++++++++++++++++
+ sound/usb/quirks.c | 4 ++
+ 2 files changed, 136 insertions(+)
+
+diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h
+index 7067d314fecd..f93201a830b5 100644
+--- a/sound/usb/quirks-table.h
++++ b/sound/usb/quirks-table.h
+@@ -4167,6 +4167,138 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+ }
+ }
+ },
++{
++ /*
++ * Fiero SC-01 (firmware v1.0.0 @ 48 kHz)
++ */
++ USB_DEVICE(0x2b53, 0x0023),
++ .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
++ .vendor_name = "Fiero",
++ .product_name = "SC-01",
++ .ifnum = QUIRK_ANY_INTERFACE,
++ .type = QUIRK_COMPOSITE,
++ .data = &(const struct snd_usb_audio_quirk[]) {
++ {
++ .ifnum = 0,
++ .type = QUIRK_AUDIO_STANDARD_INTERFACE
++ },
++ /* Playback */
++ {
++ .ifnum = 1,
++ .type = QUIRK_AUDIO_FIXED_ENDPOINT,
++ .data = &(const struct audioformat) {
++ .formats = SNDRV_PCM_FMTBIT_S32_LE,
++ .channels = 2,
++ .fmt_bits = 24,
++ .iface = 1,
++ .altsetting = 1,
++ .altset_idx = 1,
++ .endpoint = 0x01,
++ .ep_attr = USB_ENDPOINT_XFER_ISOC |
++ USB_ENDPOINT_SYNC_ASYNC,
++ .rates = SNDRV_PCM_RATE_48000,
++ .rate_min = 48000,
++ .rate_max = 48000,
++ .nr_rates = 1,
++ .rate_table = (unsigned int[]) { 48000 },
++ .clock = 0x29
++ }
++ },
++ /* Capture */
++ {
++ .ifnum = 2,
++ .type = QUIRK_AUDIO_FIXED_ENDPOINT,
++ .data = &(const struct audioformat) {
++ .formats = SNDRV_PCM_FMTBIT_S32_LE,
++ .channels = 2,
++ .fmt_bits = 24,
++ .iface = 2,
++ .altsetting = 1,
++ .altset_idx = 1,
++ .endpoint = 0x82,
++ .ep_attr = USB_ENDPOINT_XFER_ISOC |
++ USB_ENDPOINT_SYNC_ASYNC |
++ USB_ENDPOINT_USAGE_IMPLICIT_FB,
++ .rates = SNDRV_PCM_RATE_48000,
++ .rate_min = 48000,
++ .rate_max = 48000,
++ .nr_rates = 1,
++ .rate_table = (unsigned int[]) { 48000 },
++ .clock = 0x29
++ }
++ },
++ {
++ .ifnum = -1
++ }
++ }
++ }
++},
++{
++ /*
++ * Fiero SC-01 (firmware v1.0.0 @ 96 kHz)
++ */
++ USB_DEVICE(0x2b53, 0x0024),
++ .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
++ .vendor_name = "Fiero",
++ .product_name = "SC-01",
++ .ifnum = QUIRK_ANY_INTERFACE,
++ .type = QUIRK_COMPOSITE,
++ .data = &(const struct snd_usb_audio_quirk[]) {
++ {
++ .ifnum = 0,
++ .type = QUIRK_AUDIO_STANDARD_INTERFACE
++ },
++ /* Playback */
++ {
++ .ifnum = 1,
++ .type = QUIRK_AUDIO_FIXED_ENDPOINT,
++ .data = &(const struct audioformat) {
++ .formats = SNDRV_PCM_FMTBIT_S32_LE,
++ .channels = 2,
++ .fmt_bits = 24,
++ .iface = 1,
++ .altsetting = 1,
++ .altset_idx = 1,
++ .endpoint = 0x01,
++ .ep_attr = USB_ENDPOINT_XFER_ISOC |
++ USB_ENDPOINT_SYNC_ASYNC,
++ .rates = SNDRV_PCM_RATE_96000,
++ .rate_min = 96000,
++ .rate_max = 96000,
++ .nr_rates = 1,
++ .rate_table = (unsigned int[]) { 96000 },
++ .clock = 0x29
++ }
++ },
++ /* Capture */
++ {
++ .ifnum = 2,
++ .type = QUIRK_AUDIO_FIXED_ENDPOINT,
++ .data = &(const struct audioformat) {
++ .formats = SNDRV_PCM_FMTBIT_S32_LE,
++ .channels = 2,
++ .fmt_bits = 24,
++ .iface = 2,
++ .altsetting = 1,
++ .altset_idx = 1,
++ .endpoint = 0x82,
++ .ep_attr = USB_ENDPOINT_XFER_ISOC |
++ USB_ENDPOINT_SYNC_ASYNC |
++ USB_ENDPOINT_USAGE_IMPLICIT_FB,
++ .rates = SNDRV_PCM_RATE_96000,
++ .rate_min = 96000,
++ .rate_max = 96000,
++ .nr_rates = 1,
++ .rate_table = (unsigned int[]) { 96000 },
++ .clock = 0x29
++ }
++ },
++ {
++ .ifnum = -1
++ }
++ }
++ }
++},
+ {
+ /*
+ * Fiero SC-01 (firmware v1.1.0)
+diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
+index 51138350f03c..968d90caeefa 100644
+--- a/sound/usb/quirks.c
++++ b/sound/usb/quirks.c
+@@ -1915,6 +1915,10 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = {
+ QUIRK_FLAG_ALIGN_TRANSFER),
+ DEVICE_FLG(0x1224, 0x2a25, /* Jieli Technology USB PHY 2.0 */
+ QUIRK_FLAG_GET_SAMPLE_RATE),
++ DEVICE_FLG(0x2b53, 0x0023, /* Fiero SC-01 (firmware v1.0.0 @ 48 kHz) */
++ QUIRK_FLAG_GENERIC_IMPLICIT_FB),
++ DEVICE_FLG(0x2b53, 0x0024, /* Fiero SC-01 (firmware v1.0.0 @ 96 kHz) */
++ QUIRK_FLAG_GENERIC_IMPLICIT_FB),
+ DEVICE_FLG(0x2b53, 0x0031, /* Fiero SC-01 (firmware v1.1.0) */
+ QUIRK_FLAG_GENERIC_IMPLICIT_FB),
+
+--
+2.35.1
+
--- /dev/null
+From cb088248614f70acffbf4888ed4bb0c18808567b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 27 Jun 2022 13:00:34 +0300
+Subject: ALSA: usb-audio: Add quirk for Fiero SC-01
+
+From: Egor Vorontsov <sdoregor@sdore.me>
+
+[ Upstream commit 4fb7c24f69c48fdc02ea7858dbd5a60ff08bf7e5 ]
+
+Fiero SC-01 is a USB sound card with two mono inputs and a single
+stereo output. The inputs are composed into a single stereo stream.
+
+The device uses a vendor-provided driver on Windows and does not work
+at all without it. The driver mostly provides ASIO functionality, but
+also alters the way the sound card is queried for sample rates and
+clocks.
+
+ALSA queries those failing with an EPIPE (same as Windows 10 does).
+Presumably, the vendor-provided driver does not query it at all, simply
+matching by VID:PID. Thus, I consider this a buggy firmware and adhere
+to a set of fixed endpoint quirks instead.
+
+The soundcard has an internal clock. Implicit feedback mode is required
+for the playback.
+
+I have updated my device to v1.1.0 from a Windows 10 VM using a vendor-
+provided binary prior to the development, hoping for it to just begin
+working. The device provides no obvious way to downgrade the firmware,
+and regardless, there's no binary available for v1.0.0 anyway.
+
+Thus, I will be getting another unit to extend the patch with support
+for that. Expected to be a simple copy-paste of the existing one,
+though.
+
+There were no previous reports of that device in context of Linux
+anywhere. Other issues have been reported though, but that's out of the
+scope.
+
+Signed-off-by: Egor Vorontsov <sdoregor@sdore.me>
+Link: https://lore.kernel.org/r/20220627100041.2861494-1-sdoregor@sdore.me
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/usb/quirks-table.h | 68 ++++++++++++++++++++++++++++++++++++++++
+ sound/usb/quirks.c | 2 ++
+ 2 files changed, 70 insertions(+)
+
+diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h
+index 853da162fd18..7067d314fecd 100644
+--- a/sound/usb/quirks-table.h
++++ b/sound/usb/quirks-table.h
+@@ -4167,6 +4167,74 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+ }
+ }
+ },
++{
++ /*
++ * Fiero SC-01 (firmware v1.1.0)
++ */
++ USB_DEVICE(0x2b53, 0x0031),
++ .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
++ .vendor_name = "Fiero",
++ .product_name = "SC-01",
++ .ifnum = QUIRK_ANY_INTERFACE,
++ .type = QUIRK_COMPOSITE,
++ .data = &(const struct snd_usb_audio_quirk[]) {
++ {
++ .ifnum = 0,
++ .type = QUIRK_AUDIO_STANDARD_INTERFACE
++ },
++ /* Playback */
++ {
++ .ifnum = 1,
++ .type = QUIRK_AUDIO_FIXED_ENDPOINT,
++ .data = &(const struct audioformat) {
++ .formats = SNDRV_PCM_FMTBIT_S32_LE,
++ .channels = 2,
++ .fmt_bits = 24,
++ .iface = 1,
++ .altsetting = 1,
++ .altset_idx = 1,
++ .endpoint = 0x01,
++ .ep_attr = USB_ENDPOINT_XFER_ISOC |
++ USB_ENDPOINT_SYNC_ASYNC,
++ .rates = SNDRV_PCM_RATE_48000 |
++ SNDRV_PCM_RATE_96000,
++ .rate_min = 48000,
++ .rate_max = 96000,
++ .nr_rates = 2,
++ .rate_table = (unsigned int[]) { 48000, 96000 },
++ .clock = 0x29
++ }
++ },
++ /* Capture */
++ {
++ .ifnum = 2,
++ .type = QUIRK_AUDIO_FIXED_ENDPOINT,
++ .data = &(const struct audioformat) {
++ .formats = SNDRV_PCM_FMTBIT_S32_LE,
++ .channels = 2,
++ .fmt_bits = 24,
++ .iface = 2,
++ .altsetting = 1,
++ .altset_idx = 1,
++ .endpoint = 0x82,
++ .ep_attr = USB_ENDPOINT_XFER_ISOC |
++ USB_ENDPOINT_SYNC_ASYNC |
++ USB_ENDPOINT_USAGE_IMPLICIT_FB,
++ .rates = SNDRV_PCM_RATE_48000 |
++ SNDRV_PCM_RATE_96000,
++ .rate_min = 48000,
++ .rate_max = 96000,
++ .nr_rates = 2,
++ .rate_table = (unsigned int[]) { 48000, 96000 },
++ .clock = 0x29
++ }
++ },
++ {
++ .ifnum = -1
++ }
++ }
++ }
++},
+
+ #undef USB_DEVICE_VENDOR_SPEC
+ #undef USB_AUDIO_DEVICE
+diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
+index a7bcae0a2c75..51138350f03c 100644
+--- a/sound/usb/quirks.c
++++ b/sound/usb/quirks.c
+@@ -1915,6 +1915,8 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = {
+ QUIRK_FLAG_ALIGN_TRANSFER),
+ DEVICE_FLG(0x1224, 0x2a25, /* Jieli Technology USB PHY 2.0 */
+ QUIRK_FLAG_GET_SAMPLE_RATE),
++ DEVICE_FLG(0x2b53, 0x0031, /* Fiero SC-01 (firmware v1.1.0) */
++ QUIRK_FLAG_GENERIC_IMPLICIT_FB),
+
+ /* Vendor matches */
+ VENDOR_FLG(0x045e, /* MS Lifecam */
+--
+2.35.1
+
--- /dev/null
+From 1243fe374284bf21189f357e8027f1b786a60b1e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 24 Jun 2022 15:07:57 +0100
+Subject: ALSA: usb-audio: Add quirks for MacroSilicon MS2100/MS2106 devices
+
+From: John Veness <john-linux@pelago.org.uk>
+
+[ Upstream commit 6e2c9105e0b743c92a157389d40f00b81bdd09fe ]
+
+Treat the claimed 96kHz 1ch in the descriptors as 48kHz 2ch, so that
+the audio stream doesn't sound mono. Also fix initial stream
+alignment, so that left and right channels are in the correct order.
+
+Signed-off-by: John Veness <john-linux@pelago.org.uk>
+Link: https://lore.kernel.org/r/20220624140757.28758-1-john-linux@pelago.org.uk
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/usb/quirks-table.h | 48 ++++++++++++++++++++++++++++++++++++++++
+ sound/usb/quirks.c | 3 +++
+ 2 files changed, 51 insertions(+)
+
+diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h
+index 4f56e1784932..853da162fd18 100644
+--- a/sound/usb/quirks-table.h
++++ b/sound/usb/quirks-table.h
+@@ -3802,6 +3802,54 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+ }
+ },
+
++/*
++ * MacroSilicon MS2100/MS2106 based AV capture cards
++ *
++ * These claim 96kHz 1ch in the descriptors, but are actually 48kHz 2ch.
++ * They also need QUIRK_FLAG_ALIGN_TRANSFER, which makes one wonder if
++ * they pretend to be 96kHz mono as a workaround for stereo being broken
++ * by that...
++ *
++ * They also have an issue with initial stream alignment that causes the
++ * channels to be swapped and out of phase, which is dealt with in quirks.c.
++ */
++{
++ USB_AUDIO_DEVICE(0x534d, 0x0021),
++ .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
++ .vendor_name = "MacroSilicon",
++ .product_name = "MS210x",
++ .ifnum = QUIRK_ANY_INTERFACE,
++ .type = QUIRK_COMPOSITE,
++ .data = &(const struct snd_usb_audio_quirk[]) {
++ {
++ .ifnum = 2,
++ .type = QUIRK_AUDIO_STANDARD_MIXER,
++ },
++ {
++ .ifnum = 3,
++ .type = QUIRK_AUDIO_FIXED_ENDPOINT,
++ .data = &(const struct audioformat) {
++ .formats = SNDRV_PCM_FMTBIT_S16_LE,
++ .channels = 2,
++ .iface = 3,
++ .altsetting = 1,
++ .altset_idx = 1,
++ .attributes = 0,
++ .endpoint = 0x82,
++ .ep_attr = USB_ENDPOINT_XFER_ISOC |
++ USB_ENDPOINT_SYNC_ASYNC,
++ .rates = SNDRV_PCM_RATE_CONTINUOUS,
++ .rate_min = 48000,
++ .rate_max = 48000,
++ }
++ },
++ {
++ .ifnum = -1
++ }
++ }
++ }
++},
++
+ /*
+ * MacroSilicon MS2109 based HDMI capture cards
+ *
+diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
+index 12ce69b04f63..a7bcae0a2c75 100644
+--- a/sound/usb/quirks.c
++++ b/sound/usb/quirks.c
+@@ -1478,6 +1478,7 @@ void snd_usb_set_format_quirk(struct snd_usb_substream *subs,
+ case USB_ID(0x041e, 0x3f19): /* E-Mu 0204 USB */
+ set_format_emu_quirk(subs, fmt);
+ break;
++ case USB_ID(0x534d, 0x0021): /* MacroSilicon MS2100/MS2106 */
+ case USB_ID(0x534d, 0x2109): /* MacroSilicon MS2109 */
+ subs->stream_offset_adj = 2;
+ break;
+@@ -1908,6 +1909,8 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = {
+ QUIRK_FLAG_IGNORE_CTL_ERROR),
+ DEVICE_FLG(0x413c, 0xa506, /* Dell AE515 sound bar */
+ QUIRK_FLAG_GET_SAMPLE_RATE),
++ DEVICE_FLG(0x534d, 0x0021, /* MacroSilicon MS2100/MS2106 */
++ QUIRK_FLAG_ALIGN_TRANSFER),
+ DEVICE_FLG(0x534d, 0x2109, /* MacroSilicon MS2109 */
+ QUIRK_FLAG_ALIGN_TRANSFER),
+ DEVICE_FLG(0x1224, 0x2a25, /* Jieli Technology USB PHY 2.0 */
+--
+2.35.1
+
--- /dev/null
+From ff577d205087119955bf09082195b19de4266386 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 24 Jun 2022 11:27:13 +0200
+Subject: ARM: dts: stm32: use the correct clock source for CEC on stm32mp151
+
+From: Gabriel Fernandez <gabriel.fernandez@foss.st.com>
+
+[ Upstream commit 78ece8cce1ba0c3f3e5a7c6c1b914b3794f04c44 ]
+
+The peripheral clock of CEC is not LSE but CEC.
+
+Signed-off-by: Gabriel Fernandez <gabriel.fernandez@foss.st.com>
+Signed-off-by: Alexandre Torgue <alexandre.torgue@foss.st.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm/boot/dts/stm32mp151.dtsi | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/arch/arm/boot/dts/stm32mp151.dtsi b/arch/arm/boot/dts/stm32mp151.dtsi
+index a9b65b3bfda5..e0d483318798 100644
+--- a/arch/arm/boot/dts/stm32mp151.dtsi
++++ b/arch/arm/boot/dts/stm32mp151.dtsi
+@@ -553,7 +553,7 @@
+ compatible = "st,stm32-cec";
+ reg = <0x40016000 0x400>;
+ interrupts = <GIC_SPI 94 IRQ_TYPE_LEVEL_HIGH>;
+- clocks = <&rcc CEC_K>, <&clk_lse>;
++ clocks = <&rcc CEC_K>, <&rcc CEC>;
+ clock-names = "cec", "hdmi-cec";
+ status = "disabled";
+ };
+--
+2.35.1
+
--- /dev/null
+From ddae663e399501cc4b5a9f82f52b4357b37a7751 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 6 Jun 2022 15:37:51 -0500
+Subject: ASoC: codecs: rt700/rt711/rt711-sdca: initialize workqueues in probe
+
+From: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
+
+[ Upstream commit ba98d7d8b60ba410aa03834f6aa48fd3b2e68478 ]
+
+The workqueues are initialized in the io_init functions, which isn't
+quite right. In some tests, this leads to warnings throw from
+__queue_delayed_work()
+
+WARN_ON_FUNCTION_MISMATCH(timer->function, delayed_work_timer_fn);
+
+Move all the initializations to the probe functions.
+
+Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
+Reviewed-by: Rander Wang <rander.wang@intel.com>
+Reviewed-by: Bard Liao <yung-chuan.liao@linux.intel.com>
+Link: https://lore.kernel.org/r/20220606203752.144159-7-pierre-louis.bossart@linux.intel.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/codecs/rt700.c | 12 +++++-------
+ sound/soc/codecs/rt711-sdca.c | 10 +++-------
+ sound/soc/codecs/rt711.c | 12 +++++-------
+ 3 files changed, 13 insertions(+), 21 deletions(-)
+
+diff --git a/sound/soc/codecs/rt700.c b/sound/soc/codecs/rt700.c
+index c70fe8b06e6d..e049d672ccfd 100644
+--- a/sound/soc/codecs/rt700.c
++++ b/sound/soc/codecs/rt700.c
+@@ -1124,6 +1124,11 @@ int rt700_init(struct device *dev, struct regmap *sdw_regmap,
+
+ mutex_init(&rt700->disable_irq_lock);
+
++ INIT_DELAYED_WORK(&rt700->jack_detect_work,
++ rt700_jack_detect_handler);
++ INIT_DELAYED_WORK(&rt700->jack_btn_check_work,
++ rt700_btn_check_handler);
++
+ /*
+ * Mark hw_init to false
+ * HW init will be performed when device reports present
+@@ -1218,13 +1223,6 @@ int rt700_io_init(struct device *dev, struct sdw_slave *slave)
+ /* Finish Initial Settings, set power to D3 */
+ regmap_write(rt700->regmap, RT700_SET_AUDIO_POWER_STATE, AC_PWRST_D3);
+
+- if (!rt700->first_hw_init) {
+- INIT_DELAYED_WORK(&rt700->jack_detect_work,
+- rt700_jack_detect_handler);
+- INIT_DELAYED_WORK(&rt700->jack_btn_check_work,
+- rt700_btn_check_handler);
+- }
+-
+ /*
+ * if set_jack callback occurred early than io_init,
+ * we set up the jack detection function now
+diff --git a/sound/soc/codecs/rt711-sdca.c b/sound/soc/codecs/rt711-sdca.c
+index 2950cde029f7..60aef52b3fe4 100644
+--- a/sound/soc/codecs/rt711-sdca.c
++++ b/sound/soc/codecs/rt711-sdca.c
+@@ -1417,6 +1417,9 @@ int rt711_sdca_init(struct device *dev, struct regmap *regmap,
+ mutex_init(&rt711->calibrate_mutex);
+ mutex_init(&rt711->disable_irq_lock);
+
++ INIT_DELAYED_WORK(&rt711->jack_detect_work, rt711_sdca_jack_detect_handler);
++ INIT_DELAYED_WORK(&rt711->jack_btn_check_work, rt711_sdca_btn_check_handler);
++
+ /*
+ * Mark hw_init to false
+ * HW init will be performed when device reports present
+@@ -1548,13 +1551,6 @@ int rt711_sdca_io_init(struct device *dev, struct sdw_slave *slave)
+ rt711_sdca_index_update_bits(rt711, RT711_VENDOR_HDA_CTL,
+ RT711_PUSH_BTN_INT_CTL0, 0x20, 0x00);
+
+- if (!rt711->first_hw_init) {
+- INIT_DELAYED_WORK(&rt711->jack_detect_work,
+- rt711_sdca_jack_detect_handler);
+- INIT_DELAYED_WORK(&rt711->jack_btn_check_work,
+- rt711_sdca_btn_check_handler);
+- }
+-
+ /* calibration */
+ ret = rt711_sdca_calibration(rt711);
+ if (ret < 0)
+diff --git a/sound/soc/codecs/rt711.c b/sound/soc/codecs/rt711.c
+index 344bfbc5683d..51a98e730fc8 100644
+--- a/sound/soc/codecs/rt711.c
++++ b/sound/soc/codecs/rt711.c
+@@ -1202,6 +1202,10 @@ int rt711_init(struct device *dev, struct regmap *sdw_regmap,
+ mutex_init(&rt711->calibrate_mutex);
+ mutex_init(&rt711->disable_irq_lock);
+
++ INIT_DELAYED_WORK(&rt711->jack_detect_work, rt711_jack_detect_handler);
++ INIT_DELAYED_WORK(&rt711->jack_btn_check_work, rt711_btn_check_handler);
++ INIT_WORK(&rt711->calibration_work, rt711_calibration_work);
++
+ /*
+ * Mark hw_init to false
+ * HW init will be performed when device reports present
+@@ -1309,14 +1313,8 @@ int rt711_io_init(struct device *dev, struct sdw_slave *slave)
+
+ if (rt711->first_hw_init)
+ rt711_calibration(rt711);
+- else {
+- INIT_DELAYED_WORK(&rt711->jack_detect_work,
+- rt711_jack_detect_handler);
+- INIT_DELAYED_WORK(&rt711->jack_btn_check_work,
+- rt711_btn_check_handler);
+- INIT_WORK(&rt711->calibration_work, rt711_calibration_work);
++ else
+ schedule_work(&rt711->calibration_work);
+- }
+
+ /*
+ * if set_jack callback occurred early than io_init,
+--
+2.35.1
+
--- /dev/null
+From 8fade53e2218517ee8c9ae1da85b66aac317f91d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 23 Jun 2022 11:51:17 +0100
+Subject: ASoC: cs47l15: Fix event generation for low power mux control
+
+From: Charles Keepax <ckeepax@opensource.cirrus.com>
+
+[ Upstream commit 7f103af4a10f375b9b346b4d0b730f6a66b8c451 ]
+
+cs47l15_in1_adc_put always returns zero regardless of if the control
+value was updated. This results in missing notifications to user-space
+of the control change. Update the handling to return 1 when the value is
+changed.
+
+Signed-off-by: Charles Keepax <ckeepax@opensource.cirrus.com>
+Link: https://lore.kernel.org/r/20220623105120.1981154-3-ckeepax@opensource.cirrus.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/codecs/cs47l15.c | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/sound/soc/codecs/cs47l15.c b/sound/soc/codecs/cs47l15.c
+index 1ee83160b83f..ac9ccdea15b5 100644
+--- a/sound/soc/codecs/cs47l15.c
++++ b/sound/soc/codecs/cs47l15.c
+@@ -122,6 +122,9 @@ static int cs47l15_in1_adc_put(struct snd_kcontrol *kcontrol,
+ snd_soc_kcontrol_component(kcontrol);
+ struct cs47l15 *cs47l15 = snd_soc_component_get_drvdata(component);
+
++ if (!!ucontrol->value.integer.value[0] == cs47l15->in1_lp_mode)
++ return 0;
++
+ switch (ucontrol->value.integer.value[0]) {
+ case 0:
+ /* Set IN1 to normal mode */
+@@ -150,7 +153,7 @@ static int cs47l15_in1_adc_put(struct snd_kcontrol *kcontrol,
+ break;
+ }
+
+- return 0;
++ return 1;
+ }
+
+ static const struct snd_kcontrol_new cs47l15_snd_controls[] = {
+--
+2.35.1
+
--- /dev/null
+From 32ca059537a81e8d62c16be868fe34b83bbfaa16 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 23 Jun 2022 11:51:15 +0100
+Subject: ASoC: dapm: Initialise kcontrol data for mux/demux controls
+
+From: Charles Keepax <ckeepax@opensource.cirrus.com>
+
+[ Upstream commit 11d7a12f7f50baa5af9090b131c9b03af59503e7 ]
+
+DAPM keeps a copy of the current value of mux/demux controls,
+however this value is only initialised in the case of autodisable
+controls. This leads to false notification events when first
+modifying a DAPM kcontrol that has a non-zero default.
+
+Autodisable controls are left as they are, since they already
+initialise the value, and there would be more work required to
+support autodisable muxes where the first option isn't disabled
+and/or that isn't the default.
+
+Technically this issue could affect mixer/switch elements as well,
+although not on any of the devices I am currently running. There
+is also a little more work to do to address the issue there due to
+that side supporting stereo controls, so that has not been tackled
+in this patch.
+
+Signed-off-by: Charles Keepax <ckeepax@opensource.cirrus.com>
+Link: https://lore.kernel.org/r/20220623105120.1981154-1-ckeepax@opensource.cirrus.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/soc-dapm.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
+index 47b85ba5b7d6..b957049bae33 100644
+--- a/sound/soc/soc-dapm.c
++++ b/sound/soc/soc-dapm.c
+@@ -62,6 +62,8 @@ struct snd_soc_dapm_widget *
+ snd_soc_dapm_new_control_unlocked(struct snd_soc_dapm_context *dapm,
+ const struct snd_soc_dapm_widget *widget);
+
++static unsigned int soc_dapm_read(struct snd_soc_dapm_context *dapm, int reg);
++
+ /* dapm power sequences - make this per codec in the future */
+ static int dapm_up_seq[] = {
+ [snd_soc_dapm_pre] = 1,
+@@ -442,6 +444,9 @@ static int dapm_kcontrol_data_alloc(struct snd_soc_dapm_widget *widget,
+
+ snd_soc_dapm_add_path(widget->dapm, data->widget,
+ widget, NULL, NULL);
++ } else if (e->reg != SND_SOC_NOPM) {
++ data->value = soc_dapm_read(widget->dapm, e->reg) &
++ (e->mask << e->shift_l);
+ }
+ break;
+ default:
+--
+2.35.1
+
--- /dev/null
+From a7a1baebe351486fe23369eb351d1be975041cdd Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 12 Jun 2022 17:56:52 +0200
+Subject: ASoC: Intel: bytcr_wm5102: Fix GPIO related probe-ordering problem
+
+From: Hans de Goede <hdegoede@redhat.com>
+
+[ Upstream commit 4e07479eab8a044cc9542414ccb4aeb8eb033bde ]
+
+The "wlf,spkvdd-ena" GPIO needed by the bytcr_wm5102 driver
+is made available through a gpio-lookup table.
+
+This gpio-lookup table is registered by drivers/mfd/arizona-spi.c, which
+may get probed after the bytcr_wm5102 driver.
+
+If the gpio-lookup table has not registered yet then the gpiod_get()
+will return -ENOENT. Treat -ENOENT as -EPROBE_DEFER to still keep
+things working in this case.
+
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Acked-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
+Link: https://lore.kernel.org/r/20220612155652.107310-1-hdegoede@redhat.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/intel/boards/bytcr_wm5102.c | 13 +++++++++++--
+ 1 file changed, 11 insertions(+), 2 deletions(-)
+
+diff --git a/sound/soc/intel/boards/bytcr_wm5102.c b/sound/soc/intel/boards/bytcr_wm5102.c
+index 580d5fddae5a..bb669d58eb8b 100644
+--- a/sound/soc/intel/boards/bytcr_wm5102.c
++++ b/sound/soc/intel/boards/bytcr_wm5102.c
+@@ -421,8 +421,17 @@ static int snd_byt_wm5102_mc_probe(struct platform_device *pdev)
+ priv->spkvdd_en_gpio = gpiod_get(codec_dev, "wlf,spkvdd-ena", GPIOD_OUT_LOW);
+ put_device(codec_dev);
+
+- if (IS_ERR(priv->spkvdd_en_gpio))
+- return dev_err_probe(dev, PTR_ERR(priv->spkvdd_en_gpio), "getting spkvdd-GPIO\n");
++ if (IS_ERR(priv->spkvdd_en_gpio)) {
++ ret = PTR_ERR(priv->spkvdd_en_gpio);
++ /*
++ * The spkvdd gpio-lookup is registered by: drivers/mfd/arizona-spi.c,
++ * so -ENOENT means that arizona-spi hasn't probed yet.
++ */
++ if (ret == -ENOENT)
++ ret = -EPROBE_DEFER;
++
++ return dev_err_probe(dev, ret, "getting spkvdd-GPIO\n");
++ }
+
+ /* override platform name, if required */
+ byt_wm5102_card.dev = dev;
+--
+2.35.1
+
--- /dev/null
+From d9deb1e27bd982c4e86fc0f3e8093c04910d0ea5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 6 Jun 2022 15:37:48 -0500
+Subject: ASoC: Intel: sof_sdw: handle errors on card registration
+
+From: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
+
+[ Upstream commit fe154c4ff376bc31041c6441958a08243df09c99 ]
+
+If the card registration fails, typically because of deferred probes,
+the device properties added for headset codecs are not removed, which
+leads to kernel oopses in driver bind/unbind tests.
+
+We already clean-up the device properties when the card is removed,
+this code can be moved as a helper and called upon card registration
+errors.
+
+Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
+Reviewed-by: Rander Wang <rander.wang@intel.com>
+Reviewed-by: Bard Liao <yung-chuan.liao@linux.intel.com>
+Link: https://lore.kernel.org/r/20220606203752.144159-4-pierre-louis.bossart@linux.intel.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/intel/boards/sof_sdw.c | 51 ++++++++++++++++++--------------
+ 1 file changed, 29 insertions(+), 22 deletions(-)
+
+diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c
+index 0bf3e56e1d58..abe39a0ef14b 100644
+--- a/sound/soc/intel/boards/sof_sdw.c
++++ b/sound/soc/intel/boards/sof_sdw.c
+@@ -1323,6 +1323,33 @@ static struct snd_soc_card card_sof_sdw = {
+ .late_probe = sof_sdw_card_late_probe,
+ };
+
++static void mc_dailink_exit_loop(struct snd_soc_card *card)
++{
++ struct snd_soc_dai_link *link;
++ int ret;
++ int i, j;
++
++ for (i = 0; i < ARRAY_SIZE(codec_info_list); i++) {
++ if (!codec_info_list[i].exit)
++ continue;
++ /*
++ * We don't need to call .exit function if there is no matched
++ * dai link found.
++ */
++ for_each_card_prelinks(card, j, link) {
++ if (!strcmp(link->codecs[0].dai_name,
++ codec_info_list[i].dai_name)) {
++ ret = codec_info_list[i].exit(card, link);
++ if (ret)
++ dev_warn(card->dev,
++ "codec exit failed %d\n",
++ ret);
++ break;
++ }
++ }
++ }
++}
++
+ static int mc_probe(struct platform_device *pdev)
+ {
+ struct snd_soc_card *card = &card_sof_sdw;
+@@ -1387,6 +1414,7 @@ static int mc_probe(struct platform_device *pdev)
+ ret = devm_snd_soc_register_card(&pdev->dev, card);
+ if (ret) {
+ dev_err(card->dev, "snd_soc_register_card failed %d\n", ret);
++ mc_dailink_exit_loop(card);
+ return ret;
+ }
+
+@@ -1398,29 +1426,8 @@ static int mc_probe(struct platform_device *pdev)
+ static int mc_remove(struct platform_device *pdev)
+ {
+ struct snd_soc_card *card = platform_get_drvdata(pdev);
+- struct snd_soc_dai_link *link;
+- int ret;
+- int i, j;
+
+- for (i = 0; i < ARRAY_SIZE(codec_info_list); i++) {
+- if (!codec_info_list[i].exit)
+- continue;
+- /*
+- * We don't need to call .exit function if there is no matched
+- * dai link found.
+- */
+- for_each_card_prelinks(card, j, link) {
+- if (!strcmp(link->codecs[0].dai_name,
+- codec_info_list[i].dai_name)) {
+- ret = codec_info_list[i].exit(card, link);
+- if (ret)
+- dev_warn(&pdev->dev,
+- "codec exit failed %d\n",
+- ret);
+- break;
+- }
+- }
+- }
++ mc_dailink_exit_loop(card);
+
+ return 0;
+ }
+--
+2.35.1
+
--- /dev/null
+From 7757a78c05a29089cf4aae2fd1a4f7d6b4a6038c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 23 Jun 2022 11:51:18 +0100
+Subject: ASoC: madera: Fix event generation for OUT1 demux
+
+From: Charles Keepax <ckeepax@opensource.cirrus.com>
+
+[ Upstream commit e3cabbef3db8269207a6b8808f510137669f8deb ]
+
+madera_out1_demux_put returns the value of
+snd_soc_dapm_mux_update_power, which returns a 1 if a path was found for
+the kcontrol. This is obviously different to the expected return a 1 if
+the control was updated value. This results in spurious notifications to
+user-space. Update the handling to only return a 1 when the value is
+changed.
+
+Signed-off-by: Charles Keepax <ckeepax@opensource.cirrus.com>
+Link: https://lore.kernel.org/r/20220623105120.1981154-4-ckeepax@opensource.cirrus.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/codecs/madera.c | 8 +++++++-
+ 1 file changed, 7 insertions(+), 1 deletion(-)
+
+diff --git a/sound/soc/codecs/madera.c b/sound/soc/codecs/madera.c
+index f4ed7e04673f..d3e7a591b5a8 100644
+--- a/sound/soc/codecs/madera.c
++++ b/sound/soc/codecs/madera.c
+@@ -618,7 +618,13 @@ int madera_out1_demux_put(struct snd_kcontrol *kcontrol,
+ end:
+ snd_soc_dapm_mutex_unlock(dapm);
+
+- return snd_soc_dapm_mux_update_power(dapm, kcontrol, mux, e, NULL);
++ ret = snd_soc_dapm_mux_update_power(dapm, kcontrol, mux, e, NULL);
++ if (ret < 0) {
++ dev_err(madera->dev, "Failed to update demux power state: %d\n", ret);
++ return ret;
++ }
++
++ return change;
+ }
+ EXPORT_SYMBOL_GPL(madera_out1_demux_put);
+
+--
+2.35.1
+
--- /dev/null
+From 3c22074af1fab78446835a1beb8fddac6d622205 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 23 Jun 2022 11:51:19 +0100
+Subject: ASoC: madera: Fix event generation for rate controls
+
+From: Charles Keepax <ckeepax@opensource.cirrus.com>
+
+[ Upstream commit 980555e95f7cabdc9c80a07107622b097ba23703 ]
+
+madera_adsp_rate_put always returns zero regardless of if the control
+value was updated. This results in missing notifications to user-space
+of the control change. Update the handling to return 1 when the
+value is changed.
+
+Signed-off-by: Charles Keepax <ckeepax@opensource.cirrus.com>
+Link: https://lore.kernel.org/r/20220623105120.1981154-5-ckeepax@opensource.cirrus.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/codecs/madera.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/sound/soc/codecs/madera.c b/sound/soc/codecs/madera.c
+index d3e7a591b5a8..fd4fa1d5d2d1 100644
+--- a/sound/soc/codecs/madera.c
++++ b/sound/soc/codecs/madera.c
+@@ -899,7 +899,7 @@ static int madera_adsp_rate_put(struct snd_kcontrol *kcontrol,
+ struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
+ const int adsp_num = e->shift_l;
+ const unsigned int item = ucontrol->value.enumerated.item[0];
+- int ret;
++ int ret = 0;
+
+ if (item >= e->items)
+ return -EINVAL;
+@@ -916,10 +916,10 @@ static int madera_adsp_rate_put(struct snd_kcontrol *kcontrol,
+ "Cannot change '%s' while in use by active audio paths\n",
+ kcontrol->id.name);
+ ret = -EBUSY;
+- } else {
++ } else if (priv->adsp_rate_cache[adsp_num] != e->values[item]) {
+ /* Volatile register so defer until the codec is powered up */
+ priv->adsp_rate_cache[adsp_num] = e->values[item];
+- ret = 0;
++ ret = 1;
+ }
+
+ mutex_unlock(&priv->rate_lock);
+--
+2.35.1
+
--- /dev/null
+From a92fdabd42a92a18e75fb0682821960445ddfd89 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 4 Jun 2022 11:52:46 +0100
+Subject: ASoC: ops: Fix off by one in range control validation
+
+From: Mark Brown <broonie@kernel.org>
+
+[ Upstream commit 5871321fb4558c55bf9567052b618ff0be6b975e ]
+
+We currently report that range controls accept a range of 0..(max-min) but
+accept writes in the range 0..(max-min+1). Remove that extra +1.
+
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Link: https://lore.kernel.org/r/20220604105246.4055214-1-broonie@kernel.org
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/soc-ops.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/sound/soc/soc-ops.c b/sound/soc/soc-ops.c
+index f32ba64c5dda..e73360e9de8f 100644
+--- a/sound/soc/soc-ops.c
++++ b/sound/soc/soc-ops.c
+@@ -526,7 +526,7 @@ int snd_soc_put_volsw_range(struct snd_kcontrol *kcontrol,
+ return -EINVAL;
+ if (mc->platform_max && tmp > mc->platform_max)
+ return -EINVAL;
+- if (tmp > mc->max - mc->min + 1)
++ if (tmp > mc->max - mc->min)
+ return -EINVAL;
+
+ if (invert)
+@@ -547,7 +547,7 @@ int snd_soc_put_volsw_range(struct snd_kcontrol *kcontrol,
+ return -EINVAL;
+ if (mc->platform_max && tmp > mc->platform_max)
+ return -EINVAL;
+- if (tmp > mc->max - mc->min + 1)
++ if (tmp > mc->max - mc->min)
+ return -EINVAL;
+
+ if (invert)
+--
+2.35.1
+
--- /dev/null
+From c6b40e92bffea13ede08cf910c9b8600b474d5fe Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 6 Jun 2022 15:37:46 -0500
+Subject: ASoC: Realtek/Maxim SoundWire codecs: disable pm_runtime on remove
+
+From: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
+
+[ Upstream commit ac63716da3070f8cb6baaba3a058a0c7f22aeb5b ]
+
+When binding/unbinding codec drivers, the following warnings are
+thrown:
+
+[ 107.266879] rt715-sdca sdw:3:025d:0714:01: Unbalanced pm_runtime_enable!
+[ 306.879700] rt711-sdca sdw:0:025d:0711:01: Unbalanced pm_runtime_enable!
+
+Add a remove callback for all Realtek/Maxim SoundWire codecs and remove this
+warning.
+
+Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
+Reviewed-by: Rander Wang <rander.wang@intel.com>
+Reviewed-by: Bard Liao <yung-chuan.liao@linux.intel.com>
+Link: https://lore.kernel.org/r/20220606203752.144159-2-pierre-louis.bossart@linux.intel.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/codecs/max98373-sdw.c | 12 +++++++++++-
+ sound/soc/codecs/rt1308-sdw.c | 11 +++++++++++
+ sound/soc/codecs/rt1316-sdw.c | 11 +++++++++++
+ sound/soc/codecs/rt5682-sdw.c | 5 ++++-
+ sound/soc/codecs/rt700-sdw.c | 6 +++++-
+ sound/soc/codecs/rt711-sdca-sdw.c | 6 +++++-
+ sound/soc/codecs/rt711-sdw.c | 6 +++++-
+ sound/soc/codecs/rt715-sdca-sdw.c | 12 ++++++++++++
+ sound/soc/codecs/rt715-sdw.c | 12 ++++++++++++
+ 9 files changed, 76 insertions(+), 5 deletions(-)
+
+diff --git a/sound/soc/codecs/max98373-sdw.c b/sound/soc/codecs/max98373-sdw.c
+index dc520effc61c..12323d4b5bfa 100644
+--- a/sound/soc/codecs/max98373-sdw.c
++++ b/sound/soc/codecs/max98373-sdw.c
+@@ -862,6 +862,16 @@ static int max98373_sdw_probe(struct sdw_slave *slave,
+ return max98373_init(slave, regmap);
+ }
+
++static int max98373_sdw_remove(struct sdw_slave *slave)
++{
++ struct max98373_priv *max98373 = dev_get_drvdata(&slave->dev);
++
++ if (max98373->first_hw_init)
++ pm_runtime_disable(&slave->dev);
++
++ return 0;
++}
++
+ #if defined(CONFIG_OF)
+ static const struct of_device_id max98373_of_match[] = {
+ { .compatible = "maxim,max98373", },
+@@ -893,7 +903,7 @@ static struct sdw_driver max98373_sdw_driver = {
+ .pm = &max98373_pm,
+ },
+ .probe = max98373_sdw_probe,
+- .remove = NULL,
++ .remove = max98373_sdw_remove,
+ .ops = &max98373_slave_ops,
+ .id_table = max98373_id,
+ };
+diff --git a/sound/soc/codecs/rt1308-sdw.c b/sound/soc/codecs/rt1308-sdw.c
+index f716668de640..8472d855c325 100644
+--- a/sound/soc/codecs/rt1308-sdw.c
++++ b/sound/soc/codecs/rt1308-sdw.c
+@@ -683,6 +683,16 @@ static int rt1308_sdw_probe(struct sdw_slave *slave,
+ return 0;
+ }
+
++static int rt1308_sdw_remove(struct sdw_slave *slave)
++{
++ struct rt1308_sdw_priv *rt1308 = dev_get_drvdata(&slave->dev);
++
++ if (rt1308->first_hw_init)
++ pm_runtime_disable(&slave->dev);
++
++ return 0;
++}
++
+ static const struct sdw_device_id rt1308_id[] = {
+ SDW_SLAVE_ENTRY_EXT(0x025d, 0x1308, 0x2, 0, 0),
+ {},
+@@ -742,6 +752,7 @@ static struct sdw_driver rt1308_sdw_driver = {
+ .pm = &rt1308_pm,
+ },
+ .probe = rt1308_sdw_probe,
++ .remove = rt1308_sdw_remove,
+ .ops = &rt1308_slave_ops,
+ .id_table = rt1308_id,
+ };
+diff --git a/sound/soc/codecs/rt1316-sdw.c b/sound/soc/codecs/rt1316-sdw.c
+index 09b4914bba1b..09cf3ca86fa4 100644
+--- a/sound/soc/codecs/rt1316-sdw.c
++++ b/sound/soc/codecs/rt1316-sdw.c
+@@ -675,6 +675,16 @@ static int rt1316_sdw_probe(struct sdw_slave *slave,
+ return rt1316_sdw_init(&slave->dev, regmap, slave);
+ }
+
++static int rt1316_sdw_remove(struct sdw_slave *slave)
++{
++ struct rt1316_sdw_priv *rt1316 = dev_get_drvdata(&slave->dev);
++
++ if (rt1316->first_hw_init)
++ pm_runtime_disable(&slave->dev);
++
++ return 0;
++}
++
+ static const struct sdw_device_id rt1316_id[] = {
+ SDW_SLAVE_ENTRY_EXT(0x025d, 0x1316, 0x3, 0x1, 0),
+ {},
+@@ -734,6 +744,7 @@ static struct sdw_driver rt1316_sdw_driver = {
+ .pm = &rt1316_pm,
+ },
+ .probe = rt1316_sdw_probe,
++ .remove = rt1316_sdw_remove,
+ .ops = &rt1316_slave_ops,
+ .id_table = rt1316_id,
+ };
+diff --git a/sound/soc/codecs/rt5682-sdw.c b/sound/soc/codecs/rt5682-sdw.c
+index 31a4f286043e..a030c9987b92 100644
+--- a/sound/soc/codecs/rt5682-sdw.c
++++ b/sound/soc/codecs/rt5682-sdw.c
+@@ -719,9 +719,12 @@ static int rt5682_sdw_remove(struct sdw_slave *slave)
+ {
+ struct rt5682_priv *rt5682 = dev_get_drvdata(&slave->dev);
+
+- if (rt5682 && rt5682->hw_init)
++ if (rt5682->hw_init)
+ cancel_delayed_work_sync(&rt5682->jack_detect_work);
+
++ if (rt5682->first_hw_init)
++ pm_runtime_disable(&slave->dev);
++
+ return 0;
+ }
+
+diff --git a/sound/soc/codecs/rt700-sdw.c b/sound/soc/codecs/rt700-sdw.c
+index bda594899664..f7439e40ca8b 100644
+--- a/sound/soc/codecs/rt700-sdw.c
++++ b/sound/soc/codecs/rt700-sdw.c
+@@ -13,6 +13,7 @@
+ #include <linux/soundwire/sdw_type.h>
+ #include <linux/soundwire/sdw_registers.h>
+ #include <linux/module.h>
++#include <linux/pm_runtime.h>
+ #include <linux/regmap.h>
+ #include <sound/soc.h>
+ #include "rt700.h"
+@@ -463,11 +464,14 @@ static int rt700_sdw_remove(struct sdw_slave *slave)
+ {
+ struct rt700_priv *rt700 = dev_get_drvdata(&slave->dev);
+
+- if (rt700 && rt700->hw_init) {
++ if (rt700->hw_init) {
+ cancel_delayed_work_sync(&rt700->jack_detect_work);
+ cancel_delayed_work_sync(&rt700->jack_btn_check_work);
+ }
+
++ if (rt700->first_hw_init)
++ pm_runtime_disable(&slave->dev);
++
+ return 0;
+ }
+
+diff --git a/sound/soc/codecs/rt711-sdca-sdw.c b/sound/soc/codecs/rt711-sdca-sdw.c
+index aaf5af153d3f..c722a2b0041f 100644
+--- a/sound/soc/codecs/rt711-sdca-sdw.c
++++ b/sound/soc/codecs/rt711-sdca-sdw.c
+@@ -11,6 +11,7 @@
+ #include <linux/mod_devicetable.h>
+ #include <linux/soundwire/sdw_registers.h>
+ #include <linux/module.h>
++#include <linux/pm_runtime.h>
+
+ #include "rt711-sdca.h"
+ #include "rt711-sdca-sdw.h"
+@@ -364,11 +365,14 @@ static int rt711_sdca_sdw_remove(struct sdw_slave *slave)
+ {
+ struct rt711_sdca_priv *rt711 = dev_get_drvdata(&slave->dev);
+
+- if (rt711 && rt711->hw_init) {
++ if (rt711->hw_init) {
+ cancel_delayed_work_sync(&rt711->jack_detect_work);
+ cancel_delayed_work_sync(&rt711->jack_btn_check_work);
+ }
+
++ if (rt711->first_hw_init)
++ pm_runtime_disable(&slave->dev);
++
+ return 0;
+ }
+
+diff --git a/sound/soc/codecs/rt711-sdw.c b/sound/soc/codecs/rt711-sdw.c
+index bda2cc9439c9..f49c94baa37c 100644
+--- a/sound/soc/codecs/rt711-sdw.c
++++ b/sound/soc/codecs/rt711-sdw.c
+@@ -13,6 +13,7 @@
+ #include <linux/soundwire/sdw_type.h>
+ #include <linux/soundwire/sdw_registers.h>
+ #include <linux/module.h>
++#include <linux/pm_runtime.h>
+ #include <linux/regmap.h>
+ #include <sound/soc.h>
+ #include "rt711.h"
+@@ -464,12 +465,15 @@ static int rt711_sdw_remove(struct sdw_slave *slave)
+ {
+ struct rt711_priv *rt711 = dev_get_drvdata(&slave->dev);
+
+- if (rt711 && rt711->hw_init) {
++ if (rt711->hw_init) {
+ cancel_delayed_work_sync(&rt711->jack_detect_work);
+ cancel_delayed_work_sync(&rt711->jack_btn_check_work);
+ cancel_work_sync(&rt711->calibration_work);
+ }
+
++ if (rt711->first_hw_init)
++ pm_runtime_disable(&slave->dev);
++
+ return 0;
+ }
+
+diff --git a/sound/soc/codecs/rt715-sdca-sdw.c b/sound/soc/codecs/rt715-sdca-sdw.c
+index a5c673f43d82..0f4354eafef2 100644
+--- a/sound/soc/codecs/rt715-sdca-sdw.c
++++ b/sound/soc/codecs/rt715-sdca-sdw.c
+@@ -13,6 +13,7 @@
+ #include <linux/soundwire/sdw_type.h>
+ #include <linux/soundwire/sdw_registers.h>
+ #include <linux/module.h>
++#include <linux/pm_runtime.h>
+ #include <linux/regmap.h>
+ #include <sound/soc.h>
+ #include "rt715-sdca.h"
+@@ -195,6 +196,16 @@ static int rt715_sdca_sdw_probe(struct sdw_slave *slave,
+ return rt715_sdca_init(&slave->dev, mbq_regmap, regmap, slave);
+ }
+
++static int rt715_sdca_sdw_remove(struct sdw_slave *slave)
++{
++ struct rt715_sdca_priv *rt715 = dev_get_drvdata(&slave->dev);
++
++ if (rt715->first_hw_init)
++ pm_runtime_disable(&slave->dev);
++
++ return 0;
++}
++
+ static const struct sdw_device_id rt715_sdca_id[] = {
+ SDW_SLAVE_ENTRY_EXT(0x025d, 0x715, 0x3, 0x1, 0),
+ SDW_SLAVE_ENTRY_EXT(0x025d, 0x714, 0x3, 0x1, 0),
+@@ -269,6 +280,7 @@ static struct sdw_driver rt715_sdw_driver = {
+ .pm = &rt715_pm,
+ },
+ .probe = rt715_sdca_sdw_probe,
++ .remove = rt715_sdca_sdw_remove,
+ .ops = &rt715_sdca_slave_ops,
+ .id_table = rt715_sdca_id,
+ };
+diff --git a/sound/soc/codecs/rt715-sdw.c b/sound/soc/codecs/rt715-sdw.c
+index a7b21b03c08b..b047bf87a100 100644
+--- a/sound/soc/codecs/rt715-sdw.c
++++ b/sound/soc/codecs/rt715-sdw.c
+@@ -14,6 +14,7 @@
+ #include <linux/soundwire/sdw_type.h>
+ #include <linux/soundwire/sdw_registers.h>
+ #include <linux/module.h>
++#include <linux/pm_runtime.h>
+ #include <linux/of.h>
+ #include <linux/regmap.h>
+ #include <sound/soc.h>
+@@ -514,6 +515,16 @@ static int rt715_sdw_probe(struct sdw_slave *slave,
+ return 0;
+ }
+
++static int rt715_sdw_remove(struct sdw_slave *slave)
++{
++ struct rt715_priv *rt715 = dev_get_drvdata(&slave->dev);
++
++ if (rt715->first_hw_init)
++ pm_runtime_disable(&slave->dev);
++
++ return 0;
++}
++
+ static const struct sdw_device_id rt715_id[] = {
+ SDW_SLAVE_ENTRY_EXT(0x025d, 0x714, 0x2, 0, 0),
+ SDW_SLAVE_ENTRY_EXT(0x025d, 0x715, 0x2, 0, 0),
+@@ -575,6 +586,7 @@ static struct sdw_driver rt715_sdw_driver = {
+ .pm = &rt715_pm,
+ },
+ .probe = rt715_sdw_probe,
++ .remove = rt715_sdw_remove,
+ .ops = &rt715_slave_ops,
+ .id_table = rt715_id,
+ };
+--
+2.35.1
+
--- /dev/null
+From ecfe8072e38aa8aab29b15f94503adfcbd2829d8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 15 Jun 2022 04:56:43 +0000
+Subject: ASoC: rockchip: i2s: switch BCLK to GPIO
+
+From: Judy Hsiao <judyhsiao@chromium.org>
+
+[ Upstream commit a5450aba737dae3ee1a64b282e609d8375d6700c ]
+
+We discoverd that the state of BCLK on, LRCLK off and SD_MODE on
+may cause the speaker melting issue. Removing LRCLK while BCLK
+is present can cause unexpected output behavior including a large
+DC output voltage as described in the Max98357a datasheet.
+
+In order to:
+ 1. prevent BCLK from turning on by other component.
+ 2. keep BCLK and LRCLK being present at the same time
+
+This patch switches BCLK to GPIO func before LRCLK output, and
+configures BCLK func back during LRCLK is output.
+
+Without this fix, BCLK is turned on 11 ms earlier than LRCK by the
+da7219.
+With this fix, BCLK is turned on only 0.4 ms earlier than LRCK by
+the rockchip codec.
+
+Signed-off-by: Judy Hsiao <judyhsiao@chromium.org>
+Link: https://lore.kernel.org/r/20220615045643.3137287-1-judyhsiao@chromium.org
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/rockchip/rockchip_i2s.c | 160 ++++++++++++++++++++++++------
+ 1 file changed, 129 insertions(+), 31 deletions(-)
+
+diff --git a/sound/soc/rockchip/rockchip_i2s.c b/sound/soc/rockchip/rockchip_i2s.c
+index 2880a0537646..bde0ceaf100d 100644
+--- a/sound/soc/rockchip/rockchip_i2s.c
++++ b/sound/soc/rockchip/rockchip_i2s.c
+@@ -13,6 +13,7 @@
+ #include <linux/of_gpio.h>
+ #include <linux/of_device.h>
+ #include <linux/clk.h>
++#include <linux/pinctrl/consumer.h>
+ #include <linux/pm_runtime.h>
+ #include <linux/regmap.h>
+ #include <linux/spinlock.h>
+@@ -55,8 +56,40 @@ struct rk_i2s_dev {
+ const struct rk_i2s_pins *pins;
+ unsigned int bclk_ratio;
+ spinlock_t lock; /* tx/rx lock */
++ struct pinctrl *pinctrl;
++ struct pinctrl_state *bclk_on;
++ struct pinctrl_state *bclk_off;
+ };
+
++static int i2s_pinctrl_select_bclk_on(struct rk_i2s_dev *i2s)
++{
++ int ret = 0;
++
++ if (!IS_ERR(i2s->pinctrl) && !IS_ERR_OR_NULL(i2s->bclk_on))
++ ret = pinctrl_select_state(i2s->pinctrl,
++ i2s->bclk_on);
++
++ if (ret)
++ dev_err(i2s->dev, "bclk enable failed %d\n", ret);
++
++ return ret;
++}
++
++static int i2s_pinctrl_select_bclk_off(struct rk_i2s_dev *i2s)
++{
++
++ int ret = 0;
++
++ if (!IS_ERR(i2s->pinctrl) && !IS_ERR_OR_NULL(i2s->bclk_off))
++ ret = pinctrl_select_state(i2s->pinctrl,
++ i2s->bclk_off);
++
++ if (ret)
++ dev_err(i2s->dev, "bclk disable failed %d\n", ret);
++
++ return ret;
++}
++
+ static int i2s_runtime_suspend(struct device *dev)
+ {
+ struct rk_i2s_dev *i2s = dev_get_drvdata(dev);
+@@ -93,38 +126,49 @@ static inline struct rk_i2s_dev *to_info(struct snd_soc_dai *dai)
+ return snd_soc_dai_get_drvdata(dai);
+ }
+
+-static void rockchip_snd_txctrl(struct rk_i2s_dev *i2s, int on)
++static int rockchip_snd_txctrl(struct rk_i2s_dev *i2s, int on)
+ {
+ unsigned int val = 0;
+ int retry = 10;
++ int ret = 0;
+
+ spin_lock(&i2s->lock);
+ if (on) {
+- regmap_update_bits(i2s->regmap, I2S_DMACR,
+- I2S_DMACR_TDE_ENABLE, I2S_DMACR_TDE_ENABLE);
++ ret = regmap_update_bits(i2s->regmap, I2S_DMACR,
++ I2S_DMACR_TDE_ENABLE, I2S_DMACR_TDE_ENABLE);
++ if (ret < 0)
++ goto end;
+
+- regmap_update_bits(i2s->regmap, I2S_XFER,
+- I2S_XFER_TXS_START | I2S_XFER_RXS_START,
+- I2S_XFER_TXS_START | I2S_XFER_RXS_START);
++ ret = regmap_update_bits(i2s->regmap, I2S_XFER,
++ I2S_XFER_TXS_START | I2S_XFER_RXS_START,
++ I2S_XFER_TXS_START | I2S_XFER_RXS_START);
++ if (ret < 0)
++ goto end;
+
+ i2s->tx_start = true;
+ } else {
+ i2s->tx_start = false;
+
+- regmap_update_bits(i2s->regmap, I2S_DMACR,
+- I2S_DMACR_TDE_ENABLE, I2S_DMACR_TDE_DISABLE);
++ ret = regmap_update_bits(i2s->regmap, I2S_DMACR,
++ I2S_DMACR_TDE_ENABLE, I2S_DMACR_TDE_DISABLE);
++ if (ret < 0)
++ goto end;
+
+ if (!i2s->rx_start) {
+- regmap_update_bits(i2s->regmap, I2S_XFER,
+- I2S_XFER_TXS_START |
+- I2S_XFER_RXS_START,
+- I2S_XFER_TXS_STOP |
+- I2S_XFER_RXS_STOP);
++ ret = regmap_update_bits(i2s->regmap, I2S_XFER,
++ I2S_XFER_TXS_START |
++ I2S_XFER_RXS_START,
++ I2S_XFER_TXS_STOP |
++ I2S_XFER_RXS_STOP);
++ if (ret < 0)
++ goto end;
+
+ udelay(150);
+- regmap_update_bits(i2s->regmap, I2S_CLR,
+- I2S_CLR_TXC | I2S_CLR_RXC,
+- I2S_CLR_TXC | I2S_CLR_RXC);
++ ret = regmap_update_bits(i2s->regmap, I2S_CLR,
++ I2S_CLR_TXC | I2S_CLR_RXC,
++ I2S_CLR_TXC | I2S_CLR_RXC);
++ if (ret < 0)
++ goto end;
+
+ regmap_read(i2s->regmap, I2S_CLR, &val);
+
+@@ -139,44 +183,57 @@ static void rockchip_snd_txctrl(struct rk_i2s_dev *i2s, int on)
+ }
+ }
+ }
++end:
+ spin_unlock(&i2s->lock);
++ if (ret < 0)
++ dev_err(i2s->dev, "lrclk update failed\n");
++
++ return ret;
+ }
+
+-static void rockchip_snd_rxctrl(struct rk_i2s_dev *i2s, int on)
++static int rockchip_snd_rxctrl(struct rk_i2s_dev *i2s, int on)
+ {
+ unsigned int val = 0;
+ int retry = 10;
++ int ret = 0;
+
+ spin_lock(&i2s->lock);
+ if (on) {
+- regmap_update_bits(i2s->regmap, I2S_DMACR,
++ ret = regmap_update_bits(i2s->regmap, I2S_DMACR,
+ I2S_DMACR_RDE_ENABLE, I2S_DMACR_RDE_ENABLE);
++ if (ret < 0)
++ goto end;
+
+- regmap_update_bits(i2s->regmap, I2S_XFER,
++ ret = regmap_update_bits(i2s->regmap, I2S_XFER,
+ I2S_XFER_TXS_START | I2S_XFER_RXS_START,
+ I2S_XFER_TXS_START | I2S_XFER_RXS_START);
++ if (ret < 0)
++ goto end;
+
+ i2s->rx_start = true;
+ } else {
+ i2s->rx_start = false;
+
+- regmap_update_bits(i2s->regmap, I2S_DMACR,
++ ret = regmap_update_bits(i2s->regmap, I2S_DMACR,
+ I2S_DMACR_RDE_ENABLE, I2S_DMACR_RDE_DISABLE);
++ if (ret < 0)
++ goto end;
+
+ if (!i2s->tx_start) {
+- regmap_update_bits(i2s->regmap, I2S_XFER,
++ ret = regmap_update_bits(i2s->regmap, I2S_XFER,
+ I2S_XFER_TXS_START |
+ I2S_XFER_RXS_START,
+ I2S_XFER_TXS_STOP |
+ I2S_XFER_RXS_STOP);
+-
++ if (ret < 0)
++ goto end;
+ udelay(150);
+- regmap_update_bits(i2s->regmap, I2S_CLR,
++ ret = regmap_update_bits(i2s->regmap, I2S_CLR,
+ I2S_CLR_TXC | I2S_CLR_RXC,
+ I2S_CLR_TXC | I2S_CLR_RXC);
+-
++ if (ret < 0)
++ goto end;
+ regmap_read(i2s->regmap, I2S_CLR, &val);
+-
+ /* Should wait for clear operation to finish */
+ while (val) {
+ regmap_read(i2s->regmap, I2S_CLR, &val);
+@@ -188,7 +245,12 @@ static void rockchip_snd_rxctrl(struct rk_i2s_dev *i2s, int on)
+ }
+ }
+ }
++end:
+ spin_unlock(&i2s->lock);
++ if (ret < 0)
++ dev_err(i2s->dev, "lrclk update failed\n");
++
++ return ret;
+ }
+
+ static int rockchip_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
+@@ -426,17 +488,26 @@ static int rockchip_i2s_trigger(struct snd_pcm_substream *substream,
+ case SNDRV_PCM_TRIGGER_RESUME:
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
+- rockchip_snd_rxctrl(i2s, 1);
++ ret = rockchip_snd_rxctrl(i2s, 1);
+ else
+- rockchip_snd_txctrl(i2s, 1);
++ ret = rockchip_snd_txctrl(i2s, 1);
++ /* Do not turn on bclk if lrclk open fails. */
++ if (ret < 0)
++ return ret;
++ i2s_pinctrl_select_bclk_on(i2s);
+ break;
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ case SNDRV_PCM_TRIGGER_STOP:
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+- if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
+- rockchip_snd_rxctrl(i2s, 0);
+- else
+- rockchip_snd_txctrl(i2s, 0);
++ if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
++ if (!i2s->tx_start)
++ i2s_pinctrl_select_bclk_off(i2s);
++ ret = rockchip_snd_rxctrl(i2s, 0);
++ } else {
++ if (!i2s->rx_start)
++ i2s_pinctrl_select_bclk_off(i2s);
++ ret = rockchip_snd_txctrl(i2s, 0);
++ }
+ break;
+ default:
+ ret = -EINVAL;
+@@ -737,6 +808,33 @@ static int rockchip_i2s_probe(struct platform_device *pdev)
+ }
+
+ i2s->bclk_ratio = 64;
++ i2s->pinctrl = devm_pinctrl_get(&pdev->dev);
++ if (IS_ERR(i2s->pinctrl))
++ dev_err(&pdev->dev, "failed to find i2s pinctrl\n");
++
++ i2s->bclk_on = pinctrl_lookup_state(i2s->pinctrl,
++ "bclk_on");
++ if (IS_ERR_OR_NULL(i2s->bclk_on))
++ dev_err(&pdev->dev, "failed to find i2s default state\n");
++ else
++ dev_dbg(&pdev->dev, "find i2s bclk state\n");
++
++ i2s->bclk_off = pinctrl_lookup_state(i2s->pinctrl,
++ "bclk_off");
++ if (IS_ERR_OR_NULL(i2s->bclk_off))
++ dev_err(&pdev->dev, "failed to find i2s gpio state\n");
++ else
++ dev_dbg(&pdev->dev, "find i2s bclk_off state\n");
++
++ i2s_pinctrl_select_bclk_off(i2s);
++
++ i2s->playback_dma_data.addr = res->start + I2S_TXDR;
++ i2s->playback_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
++ i2s->playback_dma_data.maxburst = 4;
++
++ i2s->capture_dma_data.addr = res->start + I2S_RXDR;
++ i2s->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
++ i2s->capture_dma_data.maxburst = 4;
+
+ dev_set_drvdata(&pdev->dev, i2s);
+
+--
+2.35.1
+
--- /dev/null
+From 1174070ef74196b89e044ee21e8af7502861f5d5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 6 Jun 2022 15:37:50 -0500
+Subject: ASoC: rt7*-sdw: harden jack_detect_handler
+
+From: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
+
+[ Upstream commit 0484271ab0ce50649329fa9dc23c50853c5b26a4 ]
+
+Realtek headset codec drivers typically check if the card is
+instantiated before proceeding with the jack detection.
+
+The rt700, rt711 and rt711-sdca are however missing a check on the
+card pointer, which can lead to NULL dereferences encountered in
+driver bind/unbind tests.
+
+Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
+Reviewed-by: Rander Wang <rander.wang@intel.com>
+Reviewed-by: Bard Liao <yung-chuan.liao@linux.intel.com>
+Link: https://lore.kernel.org/r/20220606203752.144159-6-pierre-louis.bossart@linux.intel.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/codecs/rt700.c | 2 +-
+ sound/soc/codecs/rt711-sdca.c | 2 +-
+ sound/soc/codecs/rt711.c | 2 +-
+ 3 files changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/sound/soc/codecs/rt700.c b/sound/soc/codecs/rt700.c
+index 614a40247679..c70fe8b06e6d 100644
+--- a/sound/soc/codecs/rt700.c
++++ b/sound/soc/codecs/rt700.c
+@@ -162,7 +162,7 @@ static void rt700_jack_detect_handler(struct work_struct *work)
+ if (!rt700->hs_jack)
+ return;
+
+- if (!rt700->component->card->instantiated)
++ if (!rt700->component->card || !rt700->component->card->instantiated)
+ return;
+
+ reg = RT700_VERB_GET_PIN_SENSE | RT700_HP_OUT;
+diff --git a/sound/soc/codecs/rt711-sdca.c b/sound/soc/codecs/rt711-sdca.c
+index 66555cb5d1e4..2950cde029f7 100644
+--- a/sound/soc/codecs/rt711-sdca.c
++++ b/sound/soc/codecs/rt711-sdca.c
+@@ -294,7 +294,7 @@ static void rt711_sdca_jack_detect_handler(struct work_struct *work)
+ if (!rt711->hs_jack)
+ return;
+
+- if (!rt711->component->card->instantiated)
++ if (!rt711->component->card || !rt711->component->card->instantiated)
+ return;
+
+ /* SDW_SCP_SDCA_INT_SDCA_0 is used for jack detection */
+diff --git a/sound/soc/codecs/rt711.c b/sound/soc/codecs/rt711.c
+index 6e9b532a6271..344bfbc5683d 100644
+--- a/sound/soc/codecs/rt711.c
++++ b/sound/soc/codecs/rt711.c
+@@ -242,7 +242,7 @@ static void rt711_jack_detect_handler(struct work_struct *work)
+ if (!rt711->hs_jack)
+ return;
+
+- if (!rt711->component->card->instantiated)
++ if (!rt711->component->card || !rt711->component->card->instantiated)
+ return;
+
+ reg = RT711_VERB_GET_PIN_SENSE | RT711_HP_OUT;
+--
+2.35.1
+
--- /dev/null
+From 57ac9d49cff349fcc6e3691d8e4247a3ab556902 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 6 Jun 2022 15:37:49 -0500
+Subject: ASoC: rt711: fix calibrate mutex initialization
+
+From: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
+
+[ Upstream commit 08bb5dc6ce02374169213cea772b1c297eaf32d5 ]
+
+Follow the same flow as rt711-sdca and initialize all mutexes at probe
+time.
+
+Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
+Reviewed-by: Rander Wang <rander.wang@intel.com>
+Reviewed-by: Bard Liao <yung-chuan.liao@linux.intel.com>
+Link: https://lore.kernel.org/r/20220606203752.144159-5-pierre-louis.bossart@linux.intel.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/codecs/rt711-sdw.c | 3 +++
+ sound/soc/codecs/rt711.c | 2 +-
+ 2 files changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/sound/soc/codecs/rt711-sdw.c b/sound/soc/codecs/rt711-sdw.c
+index f49c94baa37c..4fe68bcf2a7c 100644
+--- a/sound/soc/codecs/rt711-sdw.c
++++ b/sound/soc/codecs/rt711-sdw.c
+@@ -474,6 +474,9 @@ static int rt711_sdw_remove(struct sdw_slave *slave)
+ if (rt711->first_hw_init)
+ pm_runtime_disable(&slave->dev);
+
++ mutex_destroy(&rt711->calibrate_mutex);
++ mutex_destroy(&rt711->disable_irq_lock);
++
+ return 0;
+ }
+
+diff --git a/sound/soc/codecs/rt711.c b/sound/soc/codecs/rt711.c
+index fafb0ba8349f..6e9b532a6271 100644
+--- a/sound/soc/codecs/rt711.c
++++ b/sound/soc/codecs/rt711.c
+@@ -1199,6 +1199,7 @@ int rt711_init(struct device *dev, struct regmap *sdw_regmap,
+ rt711->sdw_regmap = sdw_regmap;
+ rt711->regmap = regmap;
+
++ mutex_init(&rt711->calibrate_mutex);
+ mutex_init(&rt711->disable_irq_lock);
+
+ /*
+@@ -1313,7 +1314,6 @@ int rt711_io_init(struct device *dev, struct sdw_slave *slave)
+ rt711_jack_detect_handler);
+ INIT_DELAYED_WORK(&rt711->jack_btn_check_work,
+ rt711_btn_check_handler);
+- mutex_init(&rt711->calibrate_mutex);
+ INIT_WORK(&rt711->calibration_work, rt711_calibration_work);
+ schedule_work(&rt711->calibration_work);
+ }
+--
+2.35.1
+
--- /dev/null
+From 8802191da8a5cc76f190b62005557e8bb68af3a8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 21 Jun 2022 17:07:19 +0800
+Subject: ASoC: rt711-sdca: fix kernel NULL pointer dereference when IO error
+
+From: Shuming Fan <shumingf@realtek.com>
+
+[ Upstream commit 1df793d479bef546569fc2e409ff8bb3f0fb8e99 ]
+
+The initial settings will be written before the codec probe function.
+But, the rt711->component doesn't be assigned yet.
+If IO error happened during initial settings operations, it will cause the kernel panic.
+This patch changed component->dev to slave->dev to fix this issue.
+
+Signed-off-by: Shuming Fan <shumingf@realtek.com>
+Link: https://lore.kernel.org/r/20220621090719.30558-1-shumingf@realtek.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/codecs/rt711-sdca.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/sound/soc/codecs/rt711-sdca.c b/sound/soc/codecs/rt711-sdca.c
+index 60aef52b3fe4..3b5df3ea2f60 100644
+--- a/sound/soc/codecs/rt711-sdca.c
++++ b/sound/soc/codecs/rt711-sdca.c
+@@ -34,7 +34,7 @@ static int rt711_sdca_index_write(struct rt711_sdca_priv *rt711,
+
+ ret = regmap_write(regmap, addr, value);
+ if (ret < 0)
+- dev_err(rt711->component->dev,
++ dev_err(&rt711->slave->dev,
+ "Failed to set private value: %06x <= %04x ret=%d\n",
+ addr, value, ret);
+
+@@ -50,7 +50,7 @@ static int rt711_sdca_index_read(struct rt711_sdca_priv *rt711,
+
+ ret = regmap_read(regmap, addr, value);
+ if (ret < 0)
+- dev_err(rt711->component->dev,
++ dev_err(&rt711->slave->dev,
+ "Failed to get private value: %06x => %04x ret=%d\n",
+ addr, *value, ret);
+
+--
+2.35.1
+
--- /dev/null
+From f07e7000daecd4f9dba7134fd414648d1b3d4e54 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 6 Jun 2022 15:37:47 -0500
+Subject: ASoC: rt711-sdca-sdw: fix calibrate mutex initialization
+
+From: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
+
+[ Upstream commit ed0a7fb29c9fd4f53eeb37d1fe2354df7a038047 ]
+
+In codec driver bind/unbind test, the following warning is thrown:
+
+DEBUG_LOCKS_WARN_ON(lock->magic != lock)
+...
+[ 699.182495] rt711_sdca_jack_init+0x1b/0x1d0 [snd_soc_rt711_sdca]
+[ 699.182498] rt711_sdca_set_jack_detect+0x3b/0x90 [snd_soc_rt711_sdca]
+[ 699.182500] snd_soc_component_set_jack+0x24/0x50 [snd_soc_core]
+
+A quick check in the code shows that the 'calibrate_mutex' used by
+this driver are not initialized at probe time. Moving the
+initialization to the probe removes the issue.
+
+BugLink: https://github.com/thesofproject/linux/issues/3644
+Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
+Reviewed-by: Rander Wang <rander.wang@intel.com>
+Reviewed-by: Bard Liao <yung-chuan.liao@linux.intel.com>
+Link: https://lore.kernel.org/r/20220606203752.144159-3-pierre-louis.bossart@linux.intel.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/codecs/rt711-sdca-sdw.c | 3 +++
+ sound/soc/codecs/rt711-sdca.c | 2 +-
+ 2 files changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/sound/soc/codecs/rt711-sdca-sdw.c b/sound/soc/codecs/rt711-sdca-sdw.c
+index c722a2b0041f..a085b2f530aa 100644
+--- a/sound/soc/codecs/rt711-sdca-sdw.c
++++ b/sound/soc/codecs/rt711-sdca-sdw.c
+@@ -373,6 +373,9 @@ static int rt711_sdca_sdw_remove(struct sdw_slave *slave)
+ if (rt711->first_hw_init)
+ pm_runtime_disable(&slave->dev);
+
++ mutex_destroy(&rt711->calibrate_mutex);
++ mutex_destroy(&rt711->disable_irq_lock);
++
+ return 0;
+ }
+
+diff --git a/sound/soc/codecs/rt711-sdca.c b/sound/soc/codecs/rt711-sdca.c
+index c15fb98eac86..66555cb5d1e4 100644
+--- a/sound/soc/codecs/rt711-sdca.c
++++ b/sound/soc/codecs/rt711-sdca.c
+@@ -1414,6 +1414,7 @@ int rt711_sdca_init(struct device *dev, struct regmap *regmap,
+ rt711->regmap = regmap;
+ rt711->mbq_regmap = mbq_regmap;
+
++ mutex_init(&rt711->calibrate_mutex);
+ mutex_init(&rt711->disable_irq_lock);
+
+ /*
+@@ -1552,7 +1553,6 @@ int rt711_sdca_io_init(struct device *dev, struct sdw_slave *slave)
+ rt711_sdca_jack_detect_handler);
+ INIT_DELAYED_WORK(&rt711->jack_btn_check_work,
+ rt711_sdca_btn_check_handler);
+- mutex_init(&rt711->calibrate_mutex);
+ }
+
+ /* calibration */
+--
+2.35.1
+
--- /dev/null
+From d2f2f30b576f9a1c2e636ee7518605eebf4162a8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 9 Jun 2022 11:59:49 +0300
+Subject: ASoC: SOF: Intel: hda-loader: Clarify the cl_dsp_init() flow
+
+From: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
+
+[ Upstream commit bbfef046c6613404c01aeb9e9928bebb78dd327a ]
+
+Update the comment for the cl_dsp_init() to clarify what is done by the
+function and use the chip->init_core_mask instead of BIT(0) when
+unstalling/running the init core.
+
+Complements: 2a68ff846164 ("ASoC: SOF: Intel: hda: Revisit IMR boot sequence")
+Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
+Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
+Reviewed-by: Bard Liao <yung-chuan.liao@linux.intel.com>
+Reviewed-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
+Link: https://lore.kernel.org/r/20220609085949.29062-4-peter.ujfalusi@linux.intel.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/sof/intel/hda-loader.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/sound/soc/sof/intel/hda-loader.c b/sound/soc/sof/intel/hda-loader.c
+index 14469e087b00..ee09393d42cb 100644
+--- a/sound/soc/sof/intel/hda-loader.c
++++ b/sound/soc/sof/intel/hda-loader.c
+@@ -80,9 +80,9 @@ static struct hdac_ext_stream *cl_stream_prepare(struct snd_sof_dev *sdev, unsig
+ }
+
+ /*
+- * first boot sequence has some extra steps. core 0 waits for power
+- * status on core 1, so power up core 1 also momentarily, keep it in
+- * reset/stall and then turn it off
++ * first boot sequence has some extra steps.
++ * power on all host managed cores and only unstall/run the boot core to boot the
++ * DSP then turn off all non boot cores (if any) is powered on.
+ */
+ static int cl_dsp_init(struct snd_sof_dev *sdev, int stream_tag)
+ {
+@@ -117,7 +117,7 @@ static int cl_dsp_init(struct snd_sof_dev *sdev, int stream_tag)
+ ((stream_tag - 1) << 9)));
+
+ /* step 3: unset core 0 reset state & unstall/run core 0 */
+- ret = hda_dsp_core_run(sdev, BIT(0));
++ ret = hda_dsp_core_run(sdev, chip->init_core_mask);
+ if (ret < 0) {
+ if (hda->boot_iteration == HDA_FW_BOOT_ATTEMPTS)
+ dev_err(sdev->dev,
+--
+2.35.1
+
--- /dev/null
+From f98bc8e4b9b40b0172343f066b256d9d7c123884 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 3 Jun 2022 14:25:26 +0200
+Subject: ASoC: wcd938x: Fix event generation for some controls
+
+From: Mark Brown <broonie@kernel.org>
+
+[ Upstream commit 10e7ff0047921e32b919ecee7be706dd33c107f8 ]
+
+Currently wcd938x_*_put() unconditionally report that the value of the
+control changed, resulting in spurious events being generated. Return 0 in
+that case instead as we should. There is still an issue in the compander
+control which is a bit more complex.
+
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Reported-by: kernel test robot <lkp@intel.com>
+Link: https://lore.kernel.org/r/20220603122526.3914942-1-broonie@kernel.org
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/codecs/wcd938x.c | 12 ++++++++++++
+ 1 file changed, 12 insertions(+)
+
+diff --git a/sound/soc/codecs/wcd938x.c b/sound/soc/codecs/wcd938x.c
+index 4480c118ed5d..8cdc45e669f2 100644
+--- a/sound/soc/codecs/wcd938x.c
++++ b/sound/soc/codecs/wcd938x.c
+@@ -2517,6 +2517,9 @@ static int wcd938x_tx_mode_put(struct snd_kcontrol *kcontrol,
+ struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
+ int path = e->shift_l;
+
++ if (wcd938x->tx_mode[path] == ucontrol->value.enumerated.item[0])
++ return 0;
++
+ wcd938x->tx_mode[path] = ucontrol->value.enumerated.item[0];
+
+ return 1;
+@@ -2539,6 +2542,9 @@ static int wcd938x_rx_hph_mode_put(struct snd_kcontrol *kcontrol,
+ struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
+ struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
+
++ if (wcd938x->hph_mode == ucontrol->value.enumerated.item[0])
++ return 0;
++
+ wcd938x->hph_mode = ucontrol->value.enumerated.item[0];
+
+ return 1;
+@@ -2630,6 +2636,9 @@ static int wcd938x_ldoh_put(struct snd_kcontrol *kcontrol,
+ struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
+ struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
+
++ if (wcd938x->ldoh == ucontrol->value.integer.value[0])
++ return 0;
++
+ wcd938x->ldoh = ucontrol->value.integer.value[0];
+
+ return 1;
+@@ -2652,6 +2661,9 @@ static int wcd938x_bcs_put(struct snd_kcontrol *kcontrol,
+ struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
+ struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
+
++ if (wcd938x->bcs_dis == ucontrol->value.integer.value[0])
++ return 0;
++
+ wcd938x->bcs_dis = ucontrol->value.integer.value[0];
+
+ return 1;
+--
+2.35.1
+
--- /dev/null
+From 9239ef84aef8f7c3c949a1b672817dea71ffafc9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 21 Jun 2022 11:20:39 +0100
+Subject: ASoC: wm5110: Fix DRE control
+
+From: Charles Keepax <ckeepax@opensource.cirrus.com>
+
+[ Upstream commit 0bc0ae9a5938d512fd5d44f11c9c04892dcf4961 ]
+
+The DRE controls on wm5110 should return a value of 1 if the DRE state
+is actually changed, update to fix this.
+
+Signed-off-by: Charles Keepax <ckeepax@opensource.cirrus.com>
+Link: https://lore.kernel.org/r/20220621102041.1713504-2-ckeepax@opensource.cirrus.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/codecs/wm5110.c | 8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+
+diff --git a/sound/soc/codecs/wm5110.c b/sound/soc/codecs/wm5110.c
+index 5c2d45d05c97..7c6e01720d65 100644
+--- a/sound/soc/codecs/wm5110.c
++++ b/sound/soc/codecs/wm5110.c
+@@ -413,6 +413,7 @@ static int wm5110_put_dre(struct snd_kcontrol *kcontrol,
+ unsigned int rnew = (!!ucontrol->value.integer.value[1]) << mc->rshift;
+ unsigned int lold, rold;
+ unsigned int lena, rena;
++ bool change = false;
+ int ret;
+
+ snd_soc_dapm_mutex_lock(dapm);
+@@ -440,8 +441,8 @@ static int wm5110_put_dre(struct snd_kcontrol *kcontrol,
+ goto err;
+ }
+
+- ret = regmap_update_bits(arizona->regmap, ARIZONA_DRE_ENABLE,
+- mask, lnew | rnew);
++ ret = regmap_update_bits_check(arizona->regmap, ARIZONA_DRE_ENABLE,
++ mask, lnew | rnew, &change);
+ if (ret) {
+ dev_err(arizona->dev, "Failed to set DRE: %d\n", ret);
+ goto err;
+@@ -454,6 +455,9 @@ static int wm5110_put_dre(struct snd_kcontrol *kcontrol,
+ if (!rnew && rold)
+ wm5110_clear_pga_volume(arizona, mc->rshift);
+
++ if (change)
++ ret = 1;
++
+ err:
+ snd_soc_dapm_mutex_unlock(dapm);
+
+--
+2.35.1
+
--- /dev/null
+From 959faf7f65fc576f30572ca677db35b724ffd3b3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 15 Sep 2021 15:17:16 +0800
+Subject: btrfs: rename btrfs_bio to btrfs_io_context
+
+From: Qu Wenruo <wqu@suse.com>
+
+[ Upstream commit 4c6646117912397d026d70c04d92ec1599522e9f ]
+
+The structure btrfs_bio is used by two different sites:
+
+- bio->bi_private for mirror based profiles
+ For those profiles (SINGLE/DUP/RAID1*/RAID10), this structures records
+ how many mirrors are still pending, and save the original endio
+ function of the bio.
+
+- RAID56 code
+ In that case, RAID56 only utilize the stripes info, and no long uses
+ that to trace the pending mirrors.
+
+So btrfs_bio is not always bind to a bio, and contains more info for IO
+context, thus renaming it will make the naming less confusing.
+
+Signed-off-by: Qu Wenruo <wqu@suse.com>
+Reviewed-by: David Sterba <dsterba@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/btrfs/check-integrity.c | 2 +-
+ fs/btrfs/extent-tree.c | 19 ++-
+ fs/btrfs/extent_io.c | 18 +--
+ fs/btrfs/extent_map.c | 4 +-
+ fs/btrfs/raid56.c | 127 +++++++++---------
+ fs/btrfs/raid56.h | 8 +-
+ fs/btrfs/reada.c | 26 ++--
+ fs/btrfs/scrub.c | 115 ++++++++--------
+ fs/btrfs/volumes.c | 267 ++++++++++++++++++-------------------
+ fs/btrfs/volumes.h | 38 ++++--
+ fs/btrfs/zoned.c | 16 +--
+ 11 files changed, 325 insertions(+), 315 deletions(-)
+
+diff --git a/fs/btrfs/check-integrity.c b/fs/btrfs/check-integrity.c
+index 86816088927f..81b11124b67a 100644
+--- a/fs/btrfs/check-integrity.c
++++ b/fs/btrfs/check-integrity.c
+@@ -1455,7 +1455,7 @@ static int btrfsic_map_block(struct btrfsic_state *state, u64 bytenr, u32 len,
+ struct btrfs_fs_info *fs_info = state->fs_info;
+ int ret;
+ u64 length;
+- struct btrfs_bio *multi = NULL;
++ struct btrfs_io_context *multi = NULL;
+ struct btrfs_device *device;
+
+ length = len;
+diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
+index f11616f61dd6..e3514f9a4e8d 100644
+--- a/fs/btrfs/extent-tree.c
++++ b/fs/btrfs/extent-tree.c
+@@ -1266,7 +1266,7 @@ static int btrfs_issue_discard(struct block_device *bdev, u64 start, u64 len,
+ return ret;
+ }
+
+-static int do_discard_extent(struct btrfs_bio_stripe *stripe, u64 *bytes)
++static int do_discard_extent(struct btrfs_io_stripe *stripe, u64 *bytes)
+ {
+ struct btrfs_device *dev = stripe->dev;
+ struct btrfs_fs_info *fs_info = dev->fs_info;
+@@ -1313,22 +1313,21 @@ int btrfs_discard_extent(struct btrfs_fs_info *fs_info, u64 bytenr,
+ u64 discarded_bytes = 0;
+ u64 end = bytenr + num_bytes;
+ u64 cur = bytenr;
+- struct btrfs_bio *bbio = NULL;
+-
++ struct btrfs_io_context *bioc = NULL;
+
+ /*
+- * Avoid races with device replace and make sure our bbio has devices
++ * Avoid races with device replace and make sure our bioc has devices
+ * associated to its stripes that don't go away while we are discarding.
+ */
+ btrfs_bio_counter_inc_blocked(fs_info);
+ while (cur < end) {
+- struct btrfs_bio_stripe *stripe;
++ struct btrfs_io_stripe *stripe;
+ int i;
+
+ num_bytes = end - cur;
+ /* Tell the block device(s) that the sectors can be discarded */
+ ret = btrfs_map_block(fs_info, BTRFS_MAP_DISCARD, cur,
+- &num_bytes, &bbio, 0);
++ &num_bytes, &bioc, 0);
+ /*
+ * Error can be -ENOMEM, -ENOENT (no such chunk mapping) or
+ * -EOPNOTSUPP. For any such error, @num_bytes is not updated,
+@@ -1337,8 +1336,8 @@ int btrfs_discard_extent(struct btrfs_fs_info *fs_info, u64 bytenr,
+ if (ret < 0)
+ goto out;
+
+- stripe = bbio->stripes;
+- for (i = 0; i < bbio->num_stripes; i++, stripe++) {
++ stripe = bioc->stripes;
++ for (i = 0; i < bioc->num_stripes; i++, stripe++) {
+ u64 bytes;
+ struct btrfs_device *device = stripe->dev;
+
+@@ -1361,7 +1360,7 @@ int btrfs_discard_extent(struct btrfs_fs_info *fs_info, u64 bytenr,
+ * And since there are two loops, explicitly
+ * go to out to avoid confusion.
+ */
+- btrfs_put_bbio(bbio);
++ btrfs_put_bioc(bioc);
+ goto out;
+ }
+
+@@ -1372,7 +1371,7 @@ int btrfs_discard_extent(struct btrfs_fs_info *fs_info, u64 bytenr,
+ */
+ ret = 0;
+ }
+- btrfs_put_bbio(bbio);
++ btrfs_put_bioc(bioc);
+ cur += num_bytes;
+ }
+ out:
+diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
+index 059bd0753e27..b791e280af0c 100644
+--- a/fs/btrfs/extent_io.c
++++ b/fs/btrfs/extent_io.c
+@@ -2290,7 +2290,7 @@ int repair_io_failure(struct btrfs_fs_info *fs_info, u64 ino, u64 start,
+ struct btrfs_device *dev;
+ u64 map_length = 0;
+ u64 sector;
+- struct btrfs_bio *bbio = NULL;
++ struct btrfs_io_context *bioc = NULL;
+ int ret;
+
+ ASSERT(!(fs_info->sb->s_flags & SB_RDONLY));
+@@ -2304,7 +2304,7 @@ int repair_io_failure(struct btrfs_fs_info *fs_info, u64 ino, u64 start,
+ map_length = length;
+
+ /*
+- * Avoid races with device replace and make sure our bbio has devices
++ * Avoid races with device replace and make sure our bioc has devices
+ * associated to its stripes that don't go away while we are doing the
+ * read repair operation.
+ */
+@@ -2317,28 +2317,28 @@ int repair_io_failure(struct btrfs_fs_info *fs_info, u64 ino, u64 start,
+ * stripe's dev and sector.
+ */
+ ret = btrfs_map_block(fs_info, BTRFS_MAP_READ, logical,
+- &map_length, &bbio, 0);
++ &map_length, &bioc, 0);
+ if (ret) {
+ btrfs_bio_counter_dec(fs_info);
+ bio_put(bio);
+ return -EIO;
+ }
+- ASSERT(bbio->mirror_num == 1);
++ ASSERT(bioc->mirror_num == 1);
+ } else {
+ ret = btrfs_map_block(fs_info, BTRFS_MAP_WRITE, logical,
+- &map_length, &bbio, mirror_num);
++ &map_length, &bioc, mirror_num);
+ if (ret) {
+ btrfs_bio_counter_dec(fs_info);
+ bio_put(bio);
+ return -EIO;
+ }
+- BUG_ON(mirror_num != bbio->mirror_num);
++ BUG_ON(mirror_num != bioc->mirror_num);
+ }
+
+- sector = bbio->stripes[bbio->mirror_num - 1].physical >> 9;
++ sector = bioc->stripes[bioc->mirror_num - 1].physical >> 9;
+ bio->bi_iter.bi_sector = sector;
+- dev = bbio->stripes[bbio->mirror_num - 1].dev;
+- btrfs_put_bbio(bbio);
++ dev = bioc->stripes[bioc->mirror_num - 1].dev;
++ btrfs_put_bioc(bioc);
+ if (!dev || !dev->bdev ||
+ !test_bit(BTRFS_DEV_STATE_WRITEABLE, &dev->dev_state)) {
+ btrfs_bio_counter_dec(fs_info);
+diff --git a/fs/btrfs/extent_map.c b/fs/btrfs/extent_map.c
+index 4a8e02f7b6c7..5a36add21305 100644
+--- a/fs/btrfs/extent_map.c
++++ b/fs/btrfs/extent_map.c
+@@ -360,7 +360,7 @@ static void extent_map_device_set_bits(struct extent_map *em, unsigned bits)
+ int i;
+
+ for (i = 0; i < map->num_stripes; i++) {
+- struct btrfs_bio_stripe *stripe = &map->stripes[i];
++ struct btrfs_io_stripe *stripe = &map->stripes[i];
+ struct btrfs_device *device = stripe->dev;
+
+ set_extent_bits_nowait(&device->alloc_state, stripe->physical,
+@@ -375,7 +375,7 @@ static void extent_map_device_clear_bits(struct extent_map *em, unsigned bits)
+ int i;
+
+ for (i = 0; i < map->num_stripes; i++) {
+- struct btrfs_bio_stripe *stripe = &map->stripes[i];
++ struct btrfs_io_stripe *stripe = &map->stripes[i];
+ struct btrfs_device *device = stripe->dev;
+
+ __clear_extent_bit(&device->alloc_state, stripe->physical,
+diff --git a/fs/btrfs/raid56.c b/fs/btrfs/raid56.c
+index d8d268ca8aa7..893d93e3c516 100644
+--- a/fs/btrfs/raid56.c
++++ b/fs/btrfs/raid56.c
+@@ -61,7 +61,7 @@ enum btrfs_rbio_ops {
+
+ struct btrfs_raid_bio {
+ struct btrfs_fs_info *fs_info;
+- struct btrfs_bio *bbio;
++ struct btrfs_io_context *bioc;
+
+ /* while we're doing rmw on a stripe
+ * we put it into a hash table so we can
+@@ -271,7 +271,7 @@ static void cache_rbio_pages(struct btrfs_raid_bio *rbio)
+ */
+ static int rbio_bucket(struct btrfs_raid_bio *rbio)
+ {
+- u64 num = rbio->bbio->raid_map[0];
++ u64 num = rbio->bioc->raid_map[0];
+
+ /*
+ * we shift down quite a bit. We're using byte
+@@ -559,8 +559,7 @@ static int rbio_can_merge(struct btrfs_raid_bio *last,
+ test_bit(RBIO_CACHE_BIT, &cur->flags))
+ return 0;
+
+- if (last->bbio->raid_map[0] !=
+- cur->bbio->raid_map[0])
++ if (last->bioc->raid_map[0] != cur->bioc->raid_map[0])
+ return 0;
+
+ /* we can't merge with different operations */
+@@ -673,7 +672,7 @@ static noinline int lock_stripe_add(struct btrfs_raid_bio *rbio)
+
+ spin_lock_irqsave(&h->lock, flags);
+ list_for_each_entry(cur, &h->hash_list, hash_list) {
+- if (cur->bbio->raid_map[0] != rbio->bbio->raid_map[0])
++ if (cur->bioc->raid_map[0] != rbio->bioc->raid_map[0])
+ continue;
+
+ spin_lock(&cur->bio_list_lock);
+@@ -838,7 +837,7 @@ static void __free_raid_bio(struct btrfs_raid_bio *rbio)
+ }
+ }
+
+- btrfs_put_bbio(rbio->bbio);
++ btrfs_put_bioc(rbio->bioc);
+ kfree(rbio);
+ }
+
+@@ -906,7 +905,7 @@ static void raid_write_end_io(struct bio *bio)
+
+ /* OK, we have read all the stripes we need to. */
+ max_errors = (rbio->operation == BTRFS_RBIO_PARITY_SCRUB) ?
+- 0 : rbio->bbio->max_errors;
++ 0 : rbio->bioc->max_errors;
+ if (atomic_read(&rbio->error) > max_errors)
+ err = BLK_STS_IOERR;
+
+@@ -961,12 +960,12 @@ static unsigned long rbio_nr_pages(unsigned long stripe_len, int nr_stripes)
+ * this does not allocate any pages for rbio->pages.
+ */
+ static struct btrfs_raid_bio *alloc_rbio(struct btrfs_fs_info *fs_info,
+- struct btrfs_bio *bbio,
++ struct btrfs_io_context *bioc,
+ u64 stripe_len)
+ {
+ struct btrfs_raid_bio *rbio;
+ int nr_data = 0;
+- int real_stripes = bbio->num_stripes - bbio->num_tgtdevs;
++ int real_stripes = bioc->num_stripes - bioc->num_tgtdevs;
+ int num_pages = rbio_nr_pages(stripe_len, real_stripes);
+ int stripe_npages = DIV_ROUND_UP(stripe_len, PAGE_SIZE);
+ void *p;
+@@ -987,7 +986,7 @@ static struct btrfs_raid_bio *alloc_rbio(struct btrfs_fs_info *fs_info,
+ spin_lock_init(&rbio->bio_list_lock);
+ INIT_LIST_HEAD(&rbio->stripe_cache);
+ INIT_LIST_HEAD(&rbio->hash_list);
+- rbio->bbio = bbio;
++ rbio->bioc = bioc;
+ rbio->fs_info = fs_info;
+ rbio->stripe_len = stripe_len;
+ rbio->nr_pages = num_pages;
+@@ -1015,9 +1014,9 @@ static struct btrfs_raid_bio *alloc_rbio(struct btrfs_fs_info *fs_info,
+ CONSUME_ALLOC(rbio->finish_pbitmap, BITS_TO_LONGS(stripe_npages));
+ #undef CONSUME_ALLOC
+
+- if (bbio->map_type & BTRFS_BLOCK_GROUP_RAID5)
++ if (bioc->map_type & BTRFS_BLOCK_GROUP_RAID5)
+ nr_data = real_stripes - 1;
+- else if (bbio->map_type & BTRFS_BLOCK_GROUP_RAID6)
++ else if (bioc->map_type & BTRFS_BLOCK_GROUP_RAID6)
+ nr_data = real_stripes - 2;
+ else
+ BUG();
+@@ -1077,10 +1076,10 @@ static int rbio_add_io_page(struct btrfs_raid_bio *rbio,
+ struct bio *last = bio_list->tail;
+ int ret;
+ struct bio *bio;
+- struct btrfs_bio_stripe *stripe;
++ struct btrfs_io_stripe *stripe;
+ u64 disk_start;
+
+- stripe = &rbio->bbio->stripes[stripe_nr];
++ stripe = &rbio->bioc->stripes[stripe_nr];
+ disk_start = stripe->physical + (page_index << PAGE_SHIFT);
+
+ /* if the device is missing, just fail this stripe */
+@@ -1155,7 +1154,7 @@ static void index_rbio_pages(struct btrfs_raid_bio *rbio)
+ int i = 0;
+
+ start = bio->bi_iter.bi_sector << 9;
+- stripe_offset = start - rbio->bbio->raid_map[0];
++ stripe_offset = start - rbio->bioc->raid_map[0];
+ page_index = stripe_offset >> PAGE_SHIFT;
+
+ if (bio_flagged(bio, BIO_CLONED))
+@@ -1179,7 +1178,7 @@ static void index_rbio_pages(struct btrfs_raid_bio *rbio)
+ */
+ static noinline void finish_rmw(struct btrfs_raid_bio *rbio)
+ {
+- struct btrfs_bio *bbio = rbio->bbio;
++ struct btrfs_io_context *bioc = rbio->bioc;
+ void **pointers = rbio->finish_pointers;
+ int nr_data = rbio->nr_data;
+ int stripe;
+@@ -1284,11 +1283,11 @@ static noinline void finish_rmw(struct btrfs_raid_bio *rbio)
+ }
+ }
+
+- if (likely(!bbio->num_tgtdevs))
++ if (likely(!bioc->num_tgtdevs))
+ goto write_data;
+
+ for (stripe = 0; stripe < rbio->real_stripes; stripe++) {
+- if (!bbio->tgtdev_map[stripe])
++ if (!bioc->tgtdev_map[stripe])
+ continue;
+
+ for (pagenr = 0; pagenr < rbio->stripe_npages; pagenr++) {
+@@ -1302,7 +1301,7 @@ static noinline void finish_rmw(struct btrfs_raid_bio *rbio)
+ }
+
+ ret = rbio_add_io_page(rbio, &bio_list, page,
+- rbio->bbio->tgtdev_map[stripe],
++ rbio->bioc->tgtdev_map[stripe],
+ pagenr, rbio->stripe_len);
+ if (ret)
+ goto cleanup;
+@@ -1339,12 +1338,12 @@ static int find_bio_stripe(struct btrfs_raid_bio *rbio,
+ {
+ u64 physical = bio->bi_iter.bi_sector;
+ int i;
+- struct btrfs_bio_stripe *stripe;
++ struct btrfs_io_stripe *stripe;
+
+ physical <<= 9;
+
+- for (i = 0; i < rbio->bbio->num_stripes; i++) {
+- stripe = &rbio->bbio->stripes[i];
++ for (i = 0; i < rbio->bioc->num_stripes; i++) {
++ stripe = &rbio->bioc->stripes[i];
+ if (in_range(physical, stripe->physical, rbio->stripe_len) &&
+ stripe->dev->bdev && bio->bi_bdev == stripe->dev->bdev) {
+ return i;
+@@ -1365,7 +1364,7 @@ static int find_logical_bio_stripe(struct btrfs_raid_bio *rbio,
+ int i;
+
+ for (i = 0; i < rbio->nr_data; i++) {
+- u64 stripe_start = rbio->bbio->raid_map[i];
++ u64 stripe_start = rbio->bioc->raid_map[i];
+
+ if (in_range(logical, stripe_start, rbio->stripe_len))
+ return i;
+@@ -1456,7 +1455,7 @@ static void raid_rmw_end_io(struct bio *bio)
+ if (!atomic_dec_and_test(&rbio->stripes_pending))
+ return;
+
+- if (atomic_read(&rbio->error) > rbio->bbio->max_errors)
++ if (atomic_read(&rbio->error) > rbio->bioc->max_errors)
+ goto cleanup;
+
+ /*
+@@ -1538,8 +1537,8 @@ static int raid56_rmw_stripe(struct btrfs_raid_bio *rbio)
+ }
+
+ /*
+- * the bbio may be freed once we submit the last bio. Make sure
+- * not to touch it after that
++ * The bioc may be freed once we submit the last bio. Make sure not to
++ * touch it after that.
+ */
+ atomic_set(&rbio->stripes_pending, bios_to_read);
+ while ((bio = bio_list_pop(&bio_list))) {
+@@ -1720,16 +1719,16 @@ static void btrfs_raid_unplug(struct blk_plug_cb *cb, bool from_schedule)
+ * our main entry point for writes from the rest of the FS.
+ */
+ int raid56_parity_write(struct btrfs_fs_info *fs_info, struct bio *bio,
+- struct btrfs_bio *bbio, u64 stripe_len)
++ struct btrfs_io_context *bioc, u64 stripe_len)
+ {
+ struct btrfs_raid_bio *rbio;
+ struct btrfs_plug_cb *plug = NULL;
+ struct blk_plug_cb *cb;
+ int ret;
+
+- rbio = alloc_rbio(fs_info, bbio, stripe_len);
++ rbio = alloc_rbio(fs_info, bioc, stripe_len);
+ if (IS_ERR(rbio)) {
+- btrfs_put_bbio(bbio);
++ btrfs_put_bioc(bioc);
+ return PTR_ERR(rbio);
+ }
+ bio_list_add(&rbio->bio_list, bio);
+@@ -1842,7 +1841,7 @@ static void __raid_recover_end_io(struct btrfs_raid_bio *rbio)
+ }
+
+ /* all raid6 handling here */
+- if (rbio->bbio->map_type & BTRFS_BLOCK_GROUP_RAID6) {
++ if (rbio->bioc->map_type & BTRFS_BLOCK_GROUP_RAID6) {
+ /*
+ * single failure, rebuild from parity raid5
+ * style
+@@ -1874,8 +1873,8 @@ static void __raid_recover_end_io(struct btrfs_raid_bio *rbio)
+ * here due to a crc mismatch and we can't give them the
+ * data they want
+ */
+- if (rbio->bbio->raid_map[failb] == RAID6_Q_STRIPE) {
+- if (rbio->bbio->raid_map[faila] ==
++ if (rbio->bioc->raid_map[failb] == RAID6_Q_STRIPE) {
++ if (rbio->bioc->raid_map[faila] ==
+ RAID5_P_STRIPE) {
+ err = BLK_STS_IOERR;
+ goto cleanup;
+@@ -1887,7 +1886,7 @@ static void __raid_recover_end_io(struct btrfs_raid_bio *rbio)
+ goto pstripe;
+ }
+
+- if (rbio->bbio->raid_map[failb] == RAID5_P_STRIPE) {
++ if (rbio->bioc->raid_map[failb] == RAID5_P_STRIPE) {
+ raid6_datap_recov(rbio->real_stripes,
+ PAGE_SIZE, faila, pointers);
+ } else {
+@@ -2006,7 +2005,7 @@ static void raid_recover_end_io(struct bio *bio)
+ if (!atomic_dec_and_test(&rbio->stripes_pending))
+ return;
+
+- if (atomic_read(&rbio->error) > rbio->bbio->max_errors)
++ if (atomic_read(&rbio->error) > rbio->bioc->max_errors)
+ rbio_orig_end_io(rbio, BLK_STS_IOERR);
+ else
+ __raid_recover_end_io(rbio);
+@@ -2074,7 +2073,7 @@ static int __raid56_parity_recover(struct btrfs_raid_bio *rbio)
+ * were up to date, or we might have no bios to read because
+ * the devices were gone.
+ */
+- if (atomic_read(&rbio->error) <= rbio->bbio->max_errors) {
++ if (atomic_read(&rbio->error) <= rbio->bioc->max_errors) {
+ __raid_recover_end_io(rbio);
+ return 0;
+ } else {
+@@ -2083,8 +2082,8 @@ static int __raid56_parity_recover(struct btrfs_raid_bio *rbio)
+ }
+
+ /*
+- * the bbio may be freed once we submit the last bio. Make sure
+- * not to touch it after that
++ * The bioc may be freed once we submit the last bio. Make sure not to
++ * touch it after that.
+ */
+ atomic_set(&rbio->stripes_pending, bios_to_read);
+ while ((bio = bio_list_pop(&bio_list))) {
+@@ -2117,21 +2116,21 @@ static int __raid56_parity_recover(struct btrfs_raid_bio *rbio)
+ * of the drive.
+ */
+ int raid56_parity_recover(struct btrfs_fs_info *fs_info, struct bio *bio,
+- struct btrfs_bio *bbio, u64 stripe_len,
++ struct btrfs_io_context *bioc, u64 stripe_len,
+ int mirror_num, int generic_io)
+ {
+ struct btrfs_raid_bio *rbio;
+ int ret;
+
+ if (generic_io) {
+- ASSERT(bbio->mirror_num == mirror_num);
++ ASSERT(bioc->mirror_num == mirror_num);
+ btrfs_io_bio(bio)->mirror_num = mirror_num;
+ }
+
+- rbio = alloc_rbio(fs_info, bbio, stripe_len);
++ rbio = alloc_rbio(fs_info, bioc, stripe_len);
+ if (IS_ERR(rbio)) {
+ if (generic_io)
+- btrfs_put_bbio(bbio);
++ btrfs_put_bioc(bioc);
+ return PTR_ERR(rbio);
+ }
+
+@@ -2142,11 +2141,11 @@ int raid56_parity_recover(struct btrfs_fs_info *fs_info, struct bio *bio,
+ rbio->faila = find_logical_bio_stripe(rbio, bio);
+ if (rbio->faila == -1) {
+ btrfs_warn(fs_info,
+- "%s could not find the bad stripe in raid56 so that we cannot recover any more (bio has logical %llu len %llu, bbio has map_type %llu)",
++"%s could not find the bad stripe in raid56 so that we cannot recover any more (bio has logical %llu len %llu, bioc has map_type %llu)",
+ __func__, bio->bi_iter.bi_sector << 9,
+- (u64)bio->bi_iter.bi_size, bbio->map_type);
++ (u64)bio->bi_iter.bi_size, bioc->map_type);
+ if (generic_io)
+- btrfs_put_bbio(bbio);
++ btrfs_put_bioc(bioc);
+ kfree(rbio);
+ return -EIO;
+ }
+@@ -2155,7 +2154,7 @@ int raid56_parity_recover(struct btrfs_fs_info *fs_info, struct bio *bio,
+ btrfs_bio_counter_inc_noblocked(fs_info);
+ rbio->generic_bio_cnt = 1;
+ } else {
+- btrfs_get_bbio(bbio);
++ btrfs_get_bioc(bioc);
+ }
+
+ /*
+@@ -2214,7 +2213,7 @@ static void read_rebuild_work(struct btrfs_work *work)
+ /*
+ * The following code is used to scrub/replace the parity stripe
+ *
+- * Caller must have already increased bio_counter for getting @bbio.
++ * Caller must have already increased bio_counter for getting @bioc.
+ *
+ * Note: We need make sure all the pages that add into the scrub/replace
+ * raid bio are correct and not be changed during the scrub/replace. That
+@@ -2223,14 +2222,14 @@ static void read_rebuild_work(struct btrfs_work *work)
+
+ struct btrfs_raid_bio *
+ raid56_parity_alloc_scrub_rbio(struct btrfs_fs_info *fs_info, struct bio *bio,
+- struct btrfs_bio *bbio, u64 stripe_len,
++ struct btrfs_io_context *bioc, u64 stripe_len,
+ struct btrfs_device *scrub_dev,
+ unsigned long *dbitmap, int stripe_nsectors)
+ {
+ struct btrfs_raid_bio *rbio;
+ int i;
+
+- rbio = alloc_rbio(fs_info, bbio, stripe_len);
++ rbio = alloc_rbio(fs_info, bioc, stripe_len);
+ if (IS_ERR(rbio))
+ return NULL;
+ bio_list_add(&rbio->bio_list, bio);
+@@ -2242,12 +2241,12 @@ raid56_parity_alloc_scrub_rbio(struct btrfs_fs_info *fs_info, struct bio *bio,
+ rbio->operation = BTRFS_RBIO_PARITY_SCRUB;
+
+ /*
+- * After mapping bbio with BTRFS_MAP_WRITE, parities have been sorted
++ * After mapping bioc with BTRFS_MAP_WRITE, parities have been sorted
+ * to the end position, so this search can start from the first parity
+ * stripe.
+ */
+ for (i = rbio->nr_data; i < rbio->real_stripes; i++) {
+- if (bbio->stripes[i].dev == scrub_dev) {
++ if (bioc->stripes[i].dev == scrub_dev) {
+ rbio->scrubp = i;
+ break;
+ }
+@@ -2260,7 +2259,7 @@ raid56_parity_alloc_scrub_rbio(struct btrfs_fs_info *fs_info, struct bio *bio,
+ bitmap_copy(rbio->dbitmap, dbitmap, stripe_nsectors);
+
+ /*
+- * We have already increased bio_counter when getting bbio, record it
++ * We have already increased bio_counter when getting bioc, record it
+ * so we can free it at rbio_orig_end_io().
+ */
+ rbio->generic_bio_cnt = 1;
+@@ -2275,10 +2274,10 @@ void raid56_add_scrub_pages(struct btrfs_raid_bio *rbio, struct page *page,
+ int stripe_offset;
+ int index;
+
+- ASSERT(logical >= rbio->bbio->raid_map[0]);
+- ASSERT(logical + PAGE_SIZE <= rbio->bbio->raid_map[0] +
++ ASSERT(logical >= rbio->bioc->raid_map[0]);
++ ASSERT(logical + PAGE_SIZE <= rbio->bioc->raid_map[0] +
+ rbio->stripe_len * rbio->nr_data);
+- stripe_offset = (int)(logical - rbio->bbio->raid_map[0]);
++ stripe_offset = (int)(logical - rbio->bioc->raid_map[0]);
+ index = stripe_offset >> PAGE_SHIFT;
+ rbio->bio_pages[index] = page;
+ }
+@@ -2312,7 +2311,7 @@ static int alloc_rbio_essential_pages(struct btrfs_raid_bio *rbio)
+ static noinline void finish_parity_scrub(struct btrfs_raid_bio *rbio,
+ int need_check)
+ {
+- struct btrfs_bio *bbio = rbio->bbio;
++ struct btrfs_io_context *bioc = rbio->bioc;
+ void **pointers = rbio->finish_pointers;
+ unsigned long *pbitmap = rbio->finish_pbitmap;
+ int nr_data = rbio->nr_data;
+@@ -2335,7 +2334,7 @@ static noinline void finish_parity_scrub(struct btrfs_raid_bio *rbio,
+ else
+ BUG();
+
+- if (bbio->num_tgtdevs && bbio->tgtdev_map[rbio->scrubp]) {
++ if (bioc->num_tgtdevs && bioc->tgtdev_map[rbio->scrubp]) {
+ is_replace = 1;
+ bitmap_copy(pbitmap, rbio->dbitmap, rbio->stripe_npages);
+ }
+@@ -2435,7 +2434,7 @@ static noinline void finish_parity_scrub(struct btrfs_raid_bio *rbio,
+
+ page = rbio_stripe_page(rbio, rbio->scrubp, pagenr);
+ ret = rbio_add_io_page(rbio, &bio_list, page,
+- bbio->tgtdev_map[rbio->scrubp],
++ bioc->tgtdev_map[rbio->scrubp],
+ pagenr, rbio->stripe_len);
+ if (ret)
+ goto cleanup;
+@@ -2483,7 +2482,7 @@ static inline int is_data_stripe(struct btrfs_raid_bio *rbio, int stripe)
+ */
+ static void validate_rbio_for_parity_scrub(struct btrfs_raid_bio *rbio)
+ {
+- if (atomic_read(&rbio->error) > rbio->bbio->max_errors)
++ if (atomic_read(&rbio->error) > rbio->bioc->max_errors)
+ goto cleanup;
+
+ if (rbio->faila >= 0 || rbio->failb >= 0) {
+@@ -2504,7 +2503,7 @@ static void validate_rbio_for_parity_scrub(struct btrfs_raid_bio *rbio)
+ * the data, so the capability of the repair is declined.
+ * (In the case of RAID5, we can not repair anything)
+ */
+- if (dfail > rbio->bbio->max_errors - 1)
++ if (dfail > rbio->bioc->max_errors - 1)
+ goto cleanup;
+
+ /*
+@@ -2625,8 +2624,8 @@ static void raid56_parity_scrub_stripe(struct btrfs_raid_bio *rbio)
+ }
+
+ /*
+- * the bbio may be freed once we submit the last bio. Make sure
+- * not to touch it after that
++ * The bioc may be freed once we submit the last bio. Make sure not to
++ * touch it after that.
+ */
+ atomic_set(&rbio->stripes_pending, bios_to_read);
+ while ((bio = bio_list_pop(&bio_list))) {
+@@ -2671,11 +2670,11 @@ void raid56_parity_submit_scrub_rbio(struct btrfs_raid_bio *rbio)
+
+ struct btrfs_raid_bio *
+ raid56_alloc_missing_rbio(struct btrfs_fs_info *fs_info, struct bio *bio,
+- struct btrfs_bio *bbio, u64 length)
++ struct btrfs_io_context *bioc, u64 length)
+ {
+ struct btrfs_raid_bio *rbio;
+
+- rbio = alloc_rbio(fs_info, bbio, length);
++ rbio = alloc_rbio(fs_info, bioc, length);
+ if (IS_ERR(rbio))
+ return NULL;
+
+@@ -2695,7 +2694,7 @@ raid56_alloc_missing_rbio(struct btrfs_fs_info *fs_info, struct bio *bio,
+ }
+
+ /*
+- * When we get bbio, we have already increased bio_counter, record it
++ * When we get bioc, we have already increased bio_counter, record it
+ * so we can free it at rbio_orig_end_io()
+ */
+ rbio->generic_bio_cnt = 1;
+diff --git a/fs/btrfs/raid56.h b/fs/btrfs/raid56.h
+index 2503485db859..838d3a5e07ef 100644
+--- a/fs/btrfs/raid56.h
++++ b/fs/btrfs/raid56.h
+@@ -31,24 +31,24 @@ struct btrfs_raid_bio;
+ struct btrfs_device;
+
+ int raid56_parity_recover(struct btrfs_fs_info *fs_info, struct bio *bio,
+- struct btrfs_bio *bbio, u64 stripe_len,
++ struct btrfs_io_context *bioc, u64 stripe_len,
+ int mirror_num, int generic_io);
+ int raid56_parity_write(struct btrfs_fs_info *fs_info, struct bio *bio,
+- struct btrfs_bio *bbio, u64 stripe_len);
++ struct btrfs_io_context *bioc, u64 stripe_len);
+
+ void raid56_add_scrub_pages(struct btrfs_raid_bio *rbio, struct page *page,
+ u64 logical);
+
+ struct btrfs_raid_bio *
+ raid56_parity_alloc_scrub_rbio(struct btrfs_fs_info *fs_info, struct bio *bio,
+- struct btrfs_bio *bbio, u64 stripe_len,
++ struct btrfs_io_context *bioc, u64 stripe_len,
+ struct btrfs_device *scrub_dev,
+ unsigned long *dbitmap, int stripe_nsectors);
+ void raid56_parity_submit_scrub_rbio(struct btrfs_raid_bio *rbio);
+
+ struct btrfs_raid_bio *
+ raid56_alloc_missing_rbio(struct btrfs_fs_info *fs_info, struct bio *bio,
+- struct btrfs_bio *bbio, u64 length);
++ struct btrfs_io_context *bioc, u64 length);
+ void raid56_submit_missing_rbio(struct btrfs_raid_bio *rbio);
+
+ int btrfs_alloc_stripe_hash_table(struct btrfs_fs_info *info);
+diff --git a/fs/btrfs/reada.c b/fs/btrfs/reada.c
+index 06713a8fe26b..eb96fdc3be25 100644
+--- a/fs/btrfs/reada.c
++++ b/fs/btrfs/reada.c
+@@ -227,7 +227,7 @@ int btree_readahead_hook(struct extent_buffer *eb, int err)
+ }
+
+ static struct reada_zone *reada_find_zone(struct btrfs_device *dev, u64 logical,
+- struct btrfs_bio *bbio)
++ struct btrfs_io_context *bioc)
+ {
+ struct btrfs_fs_info *fs_info = dev->fs_info;
+ int ret;
+@@ -275,11 +275,11 @@ static struct reada_zone *reada_find_zone(struct btrfs_device *dev, u64 logical,
+ kref_init(&zone->refcnt);
+ zone->elems = 0;
+ zone->device = dev; /* our device always sits at index 0 */
+- for (i = 0; i < bbio->num_stripes; ++i) {
++ for (i = 0; i < bioc->num_stripes; ++i) {
+ /* bounds have already been checked */
+- zone->devs[i] = bbio->stripes[i].dev;
++ zone->devs[i] = bioc->stripes[i].dev;
+ }
+- zone->ndevs = bbio->num_stripes;
++ zone->ndevs = bioc->num_stripes;
+
+ spin_lock(&fs_info->reada_lock);
+ ret = radix_tree_insert(&dev->reada_zones,
+@@ -309,7 +309,7 @@ static struct reada_extent *reada_find_extent(struct btrfs_fs_info *fs_info,
+ int ret;
+ struct reada_extent *re = NULL;
+ struct reada_extent *re_exist = NULL;
+- struct btrfs_bio *bbio = NULL;
++ struct btrfs_io_context *bioc = NULL;
+ struct btrfs_device *dev;
+ struct btrfs_device *prev_dev;
+ u64 length;
+@@ -345,28 +345,28 @@ static struct reada_extent *reada_find_extent(struct btrfs_fs_info *fs_info,
+ */
+ length = fs_info->nodesize;
+ ret = btrfs_map_block(fs_info, BTRFS_MAP_GET_READ_MIRRORS, logical,
+- &length, &bbio, 0);
+- if (ret || !bbio || length < fs_info->nodesize)
++ &length, &bioc, 0);
++ if (ret || !bioc || length < fs_info->nodesize)
+ goto error;
+
+- if (bbio->num_stripes > BTRFS_MAX_MIRRORS) {
++ if (bioc->num_stripes > BTRFS_MAX_MIRRORS) {
+ btrfs_err(fs_info,
+ "readahead: more than %d copies not supported",
+ BTRFS_MAX_MIRRORS);
+ goto error;
+ }
+
+- real_stripes = bbio->num_stripes - bbio->num_tgtdevs;
++ real_stripes = bioc->num_stripes - bioc->num_tgtdevs;
+ for (nzones = 0; nzones < real_stripes; ++nzones) {
+ struct reada_zone *zone;
+
+- dev = bbio->stripes[nzones].dev;
++ dev = bioc->stripes[nzones].dev;
+
+ /* cannot read ahead on missing device. */
+ if (!dev->bdev)
+ continue;
+
+- zone = reada_find_zone(dev, logical, bbio);
++ zone = reada_find_zone(dev, logical, bioc);
+ if (!zone)
+ continue;
+
+@@ -464,7 +464,7 @@ static struct reada_extent *reada_find_extent(struct btrfs_fs_info *fs_info,
+ if (!have_zone)
+ goto error;
+
+- btrfs_put_bbio(bbio);
++ btrfs_put_bioc(bioc);
+ return re;
+
+ error:
+@@ -488,7 +488,7 @@ static struct reada_extent *reada_find_extent(struct btrfs_fs_info *fs_info,
+ kref_put(&zone->refcnt, reada_zone_release);
+ spin_unlock(&fs_info->reada_lock);
+ }
+- btrfs_put_bbio(bbio);
++ btrfs_put_bioc(bioc);
+ kfree(re);
+ return re_exist;
+ }
+diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c
+index 6f2787b21530..0785d9d645fc 100644
+--- a/fs/btrfs/scrub.c
++++ b/fs/btrfs/scrub.c
+@@ -57,7 +57,7 @@ struct scrub_ctx;
+
+ struct scrub_recover {
+ refcount_t refs;
+- struct btrfs_bio *bbio;
++ struct btrfs_io_context *bioc;
+ u64 map_length;
+ };
+
+@@ -254,7 +254,7 @@ static void scrub_put_ctx(struct scrub_ctx *sctx);
+ static inline int scrub_is_page_on_raid56(struct scrub_page *spage)
+ {
+ return spage->recover &&
+- (spage->recover->bbio->map_type & BTRFS_BLOCK_GROUP_RAID56_MASK);
++ (spage->recover->bioc->map_type & BTRFS_BLOCK_GROUP_RAID56_MASK);
+ }
+
+ static void scrub_pending_bio_inc(struct scrub_ctx *sctx)
+@@ -798,7 +798,7 @@ static inline void scrub_put_recover(struct btrfs_fs_info *fs_info,
+ {
+ if (refcount_dec_and_test(&recover->refs)) {
+ btrfs_bio_counter_dec(fs_info);
+- btrfs_put_bbio(recover->bbio);
++ btrfs_put_bioc(recover->bioc);
+ kfree(recover);
+ }
+ }
+@@ -1027,8 +1027,7 @@ static int scrub_handle_errored_block(struct scrub_block *sblock_to_check)
+ sblock_other = sblocks_for_recheck + mirror_index;
+ } else {
+ struct scrub_recover *r = sblock_bad->pagev[0]->recover;
+- int max_allowed = r->bbio->num_stripes -
+- r->bbio->num_tgtdevs;
++ int max_allowed = r->bioc->num_stripes - r->bioc->num_tgtdevs;
+
+ if (mirror_index >= max_allowed)
+ break;
+@@ -1218,14 +1217,14 @@ static int scrub_handle_errored_block(struct scrub_block *sblock_to_check)
+ return 0;
+ }
+
+-static inline int scrub_nr_raid_mirrors(struct btrfs_bio *bbio)
++static inline int scrub_nr_raid_mirrors(struct btrfs_io_context *bioc)
+ {
+- if (bbio->map_type & BTRFS_BLOCK_GROUP_RAID5)
++ if (bioc->map_type & BTRFS_BLOCK_GROUP_RAID5)
+ return 2;
+- else if (bbio->map_type & BTRFS_BLOCK_GROUP_RAID6)
++ else if (bioc->map_type & BTRFS_BLOCK_GROUP_RAID6)
+ return 3;
+ else
+- return (int)bbio->num_stripes;
++ return (int)bioc->num_stripes;
+ }
+
+ static inline void scrub_stripe_index_and_offset(u64 logical, u64 map_type,
+@@ -1269,7 +1268,7 @@ static int scrub_setup_recheck_block(struct scrub_block *original_sblock,
+ u64 flags = original_sblock->pagev[0]->flags;
+ u64 have_csum = original_sblock->pagev[0]->have_csum;
+ struct scrub_recover *recover;
+- struct btrfs_bio *bbio;
++ struct btrfs_io_context *bioc;
+ u64 sublen;
+ u64 mapped_length;
+ u64 stripe_offset;
+@@ -1288,7 +1287,7 @@ static int scrub_setup_recheck_block(struct scrub_block *original_sblock,
+ while (length > 0) {
+ sublen = min_t(u64, length, fs_info->sectorsize);
+ mapped_length = sublen;
+- bbio = NULL;
++ bioc = NULL;
+
+ /*
+ * With a length of sectorsize, each returned stripe represents
+@@ -1296,27 +1295,27 @@ static int scrub_setup_recheck_block(struct scrub_block *original_sblock,
+ */
+ btrfs_bio_counter_inc_blocked(fs_info);
+ ret = btrfs_map_sblock(fs_info, BTRFS_MAP_GET_READ_MIRRORS,
+- logical, &mapped_length, &bbio);
+- if (ret || !bbio || mapped_length < sublen) {
+- btrfs_put_bbio(bbio);
++ logical, &mapped_length, &bioc);
++ if (ret || !bioc || mapped_length < sublen) {
++ btrfs_put_bioc(bioc);
+ btrfs_bio_counter_dec(fs_info);
+ return -EIO;
+ }
+
+ recover = kzalloc(sizeof(struct scrub_recover), GFP_NOFS);
+ if (!recover) {
+- btrfs_put_bbio(bbio);
++ btrfs_put_bioc(bioc);
+ btrfs_bio_counter_dec(fs_info);
+ return -ENOMEM;
+ }
+
+ refcount_set(&recover->refs, 1);
+- recover->bbio = bbio;
++ recover->bioc = bioc;
+ recover->map_length = mapped_length;
+
+ BUG_ON(page_index >= SCRUB_MAX_PAGES_PER_BLOCK);
+
+- nmirrors = min(scrub_nr_raid_mirrors(bbio), BTRFS_MAX_MIRRORS);
++ nmirrors = min(scrub_nr_raid_mirrors(bioc), BTRFS_MAX_MIRRORS);
+
+ for (mirror_index = 0; mirror_index < nmirrors;
+ mirror_index++) {
+@@ -1348,17 +1347,17 @@ static int scrub_setup_recheck_block(struct scrub_block *original_sblock,
+ sctx->fs_info->csum_size);
+
+ scrub_stripe_index_and_offset(logical,
+- bbio->map_type,
+- bbio->raid_map,
++ bioc->map_type,
++ bioc->raid_map,
+ mapped_length,
+- bbio->num_stripes -
+- bbio->num_tgtdevs,
++ bioc->num_stripes -
++ bioc->num_tgtdevs,
+ mirror_index,
+ &stripe_index,
+ &stripe_offset);
+- spage->physical = bbio->stripes[stripe_index].physical +
++ spage->physical = bioc->stripes[stripe_index].physical +
+ stripe_offset;
+- spage->dev = bbio->stripes[stripe_index].dev;
++ spage->dev = bioc->stripes[stripe_index].dev;
+
+ BUG_ON(page_index >= original_sblock->page_count);
+ spage->physical_for_dev_replace =
+@@ -1401,7 +1400,7 @@ static int scrub_submit_raid56_bio_wait(struct btrfs_fs_info *fs_info,
+ bio->bi_end_io = scrub_bio_wait_endio;
+
+ mirror_num = spage->sblock->pagev[0]->mirror_num;
+- ret = raid56_parity_recover(fs_info, bio, spage->recover->bbio,
++ ret = raid56_parity_recover(fs_info, bio, spage->recover->bioc,
+ spage->recover->map_length,
+ mirror_num, 0);
+ if (ret)
+@@ -2203,7 +2202,7 @@ static void scrub_missing_raid56_pages(struct scrub_block *sblock)
+ struct btrfs_fs_info *fs_info = sctx->fs_info;
+ u64 length = sblock->page_count * PAGE_SIZE;
+ u64 logical = sblock->pagev[0]->logical;
+- struct btrfs_bio *bbio = NULL;
++ struct btrfs_io_context *bioc = NULL;
+ struct bio *bio;
+ struct btrfs_raid_bio *rbio;
+ int ret;
+@@ -2211,19 +2210,19 @@ static void scrub_missing_raid56_pages(struct scrub_block *sblock)
+
+ btrfs_bio_counter_inc_blocked(fs_info);
+ ret = btrfs_map_sblock(fs_info, BTRFS_MAP_GET_READ_MIRRORS, logical,
+- &length, &bbio);
+- if (ret || !bbio || !bbio->raid_map)
+- goto bbio_out;
++ &length, &bioc);
++ if (ret || !bioc || !bioc->raid_map)
++ goto bioc_out;
+
+ if (WARN_ON(!sctx->is_dev_replace ||
+- !(bbio->map_type & BTRFS_BLOCK_GROUP_RAID56_MASK))) {
++ !(bioc->map_type & BTRFS_BLOCK_GROUP_RAID56_MASK))) {
+ /*
+ * We shouldn't be scrubbing a missing device. Even for dev
+ * replace, we should only get here for RAID 5/6. We either
+ * managed to mount something with no mirrors remaining or
+ * there's a bug in scrub_remap_extent()/btrfs_map_block().
+ */
+- goto bbio_out;
++ goto bioc_out;
+ }
+
+ bio = btrfs_io_bio_alloc(0);
+@@ -2231,7 +2230,7 @@ static void scrub_missing_raid56_pages(struct scrub_block *sblock)
+ bio->bi_private = sblock;
+ bio->bi_end_io = scrub_missing_raid56_end_io;
+
+- rbio = raid56_alloc_missing_rbio(fs_info, bio, bbio, length);
++ rbio = raid56_alloc_missing_rbio(fs_info, bio, bioc, length);
+ if (!rbio)
+ goto rbio_out;
+
+@@ -2249,9 +2248,9 @@ static void scrub_missing_raid56_pages(struct scrub_block *sblock)
+
+ rbio_out:
+ bio_put(bio);
+-bbio_out:
++bioc_out:
+ btrfs_bio_counter_dec(fs_info);
+- btrfs_put_bbio(bbio);
++ btrfs_put_bioc(bioc);
+ spin_lock(&sctx->stat_lock);
+ sctx->stat.malloc_errors++;
+ spin_unlock(&sctx->stat_lock);
+@@ -2826,7 +2825,7 @@ static void scrub_parity_check_and_repair(struct scrub_parity *sparity)
+ struct btrfs_fs_info *fs_info = sctx->fs_info;
+ struct bio *bio;
+ struct btrfs_raid_bio *rbio;
+- struct btrfs_bio *bbio = NULL;
++ struct btrfs_io_context *bioc = NULL;
+ u64 length;
+ int ret;
+
+@@ -2838,16 +2837,16 @@ static void scrub_parity_check_and_repair(struct scrub_parity *sparity)
+
+ btrfs_bio_counter_inc_blocked(fs_info);
+ ret = btrfs_map_sblock(fs_info, BTRFS_MAP_WRITE, sparity->logic_start,
+- &length, &bbio);
+- if (ret || !bbio || !bbio->raid_map)
+- goto bbio_out;
++ &length, &bioc);
++ if (ret || !bioc || !bioc->raid_map)
++ goto bioc_out;
+
+ bio = btrfs_io_bio_alloc(0);
+ bio->bi_iter.bi_sector = sparity->logic_start >> 9;
+ bio->bi_private = sparity;
+ bio->bi_end_io = scrub_parity_bio_endio;
+
+- rbio = raid56_parity_alloc_scrub_rbio(fs_info, bio, bbio,
++ rbio = raid56_parity_alloc_scrub_rbio(fs_info, bio, bioc,
+ length, sparity->scrub_dev,
+ sparity->dbitmap,
+ sparity->nsectors);
+@@ -2860,9 +2859,9 @@ static void scrub_parity_check_and_repair(struct scrub_parity *sparity)
+
+ rbio_out:
+ bio_put(bio);
+-bbio_out:
++bioc_out:
+ btrfs_bio_counter_dec(fs_info);
+- btrfs_put_bbio(bbio);
++ btrfs_put_bioc(bioc);
+ bitmap_or(sparity->ebitmap, sparity->ebitmap, sparity->dbitmap,
+ sparity->nsectors);
+ spin_lock(&sctx->stat_lock);
+@@ -2901,7 +2900,7 @@ static noinline_for_stack int scrub_raid56_parity(struct scrub_ctx *sctx,
+ struct btrfs_root *root = fs_info->extent_root;
+ struct btrfs_root *csum_root = fs_info->csum_root;
+ struct btrfs_extent_item *extent;
+- struct btrfs_bio *bbio = NULL;
++ struct btrfs_io_context *bioc = NULL;
+ u64 flags;
+ int ret;
+ int slot;
+@@ -3044,22 +3043,22 @@ static noinline_for_stack int scrub_raid56_parity(struct scrub_ctx *sctx,
+ extent_len);
+
+ mapped_length = extent_len;
+- bbio = NULL;
++ bioc = NULL;
+ ret = btrfs_map_block(fs_info, BTRFS_MAP_READ,
+- extent_logical, &mapped_length, &bbio,
++ extent_logical, &mapped_length, &bioc,
+ 0);
+ if (!ret) {
+- if (!bbio || mapped_length < extent_len)
++ if (!bioc || mapped_length < extent_len)
+ ret = -EIO;
+ }
+ if (ret) {
+- btrfs_put_bbio(bbio);
++ btrfs_put_bioc(bioc);
+ goto out;
+ }
+- extent_physical = bbio->stripes[0].physical;
+- extent_mirror_num = bbio->mirror_num;
+- extent_dev = bbio->stripes[0].dev;
+- btrfs_put_bbio(bbio);
++ extent_physical = bioc->stripes[0].physical;
++ extent_mirror_num = bioc->mirror_num;
++ extent_dev = bioc->stripes[0].dev;
++ btrfs_put_bioc(bioc);
+
+ ret = btrfs_lookup_csums_range(csum_root,
+ extent_logical,
+@@ -4311,20 +4310,20 @@ static void scrub_remap_extent(struct btrfs_fs_info *fs_info,
+ int *extent_mirror_num)
+ {
+ u64 mapped_length;
+- struct btrfs_bio *bbio = NULL;
++ struct btrfs_io_context *bioc = NULL;
+ int ret;
+
+ mapped_length = extent_len;
+ ret = btrfs_map_block(fs_info, BTRFS_MAP_READ, extent_logical,
+- &mapped_length, &bbio, 0);
+- if (ret || !bbio || mapped_length < extent_len ||
+- !bbio->stripes[0].dev->bdev) {
+- btrfs_put_bbio(bbio);
++ &mapped_length, &bioc, 0);
++ if (ret || !bioc || mapped_length < extent_len ||
++ !bioc->stripes[0].dev->bdev) {
++ btrfs_put_bioc(bioc);
+ return;
+ }
+
+- *extent_physical = bbio->stripes[0].physical;
+- *extent_mirror_num = bbio->mirror_num;
+- *extent_dev = bbio->stripes[0].dev;
+- btrfs_put_bbio(bbio);
++ *extent_physical = bioc->stripes[0].physical;
++ *extent_mirror_num = bioc->mirror_num;
++ *extent_dev = bioc->stripes[0].dev;
++ btrfs_put_bioc(bioc);
+ }
+diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
+index 89ce0b449c22..2a93d80be9bf 100644
+--- a/fs/btrfs/volumes.c
++++ b/fs/btrfs/volumes.c
+@@ -251,7 +251,7 @@ static void btrfs_dev_stat_print_on_load(struct btrfs_device *device);
+ static int __btrfs_map_block(struct btrfs_fs_info *fs_info,
+ enum btrfs_map_op op,
+ u64 logical, u64 *length,
+- struct btrfs_bio **bbio_ret,
++ struct btrfs_io_context **bioc_ret,
+ int mirror_num, int need_raid_map);
+
+ /*
+@@ -5868,7 +5868,7 @@ static int find_live_mirror(struct btrfs_fs_info *fs_info,
+ }
+
+ /* Bubble-sort the stripe set to put the parity/syndrome stripes last */
+-static void sort_parity_stripes(struct btrfs_bio *bbio, int num_stripes)
++static void sort_parity_stripes(struct btrfs_io_context *bioc, int num_stripes)
+ {
+ int i;
+ int again = 1;
+@@ -5877,52 +5877,53 @@ static void sort_parity_stripes(struct btrfs_bio *bbio, int num_stripes)
+ again = 0;
+ for (i = 0; i < num_stripes - 1; i++) {
+ /* Swap if parity is on a smaller index */
+- if (bbio->raid_map[i] > bbio->raid_map[i + 1]) {
+- swap(bbio->stripes[i], bbio->stripes[i + 1]);
+- swap(bbio->raid_map[i], bbio->raid_map[i + 1]);
++ if (bioc->raid_map[i] > bioc->raid_map[i + 1]) {
++ swap(bioc->stripes[i], bioc->stripes[i + 1]);
++ swap(bioc->raid_map[i], bioc->raid_map[i + 1]);
+ again = 1;
+ }
+ }
+ }
+ }
+
+-static struct btrfs_bio *alloc_btrfs_bio(int total_stripes, int real_stripes)
++static struct btrfs_io_context *alloc_btrfs_io_context(int total_stripes,
++ int real_stripes)
+ {
+- struct btrfs_bio *bbio = kzalloc(
+- /* the size of the btrfs_bio */
+- sizeof(struct btrfs_bio) +
+- /* plus the variable array for the stripes */
+- sizeof(struct btrfs_bio_stripe) * (total_stripes) +
+- /* plus the variable array for the tgt dev */
++ struct btrfs_io_context *bioc = kzalloc(
++ /* The size of btrfs_io_context */
++ sizeof(struct btrfs_io_context) +
++ /* Plus the variable array for the stripes */
++ sizeof(struct btrfs_io_stripe) * (total_stripes) +
++ /* Plus the variable array for the tgt dev */
+ sizeof(int) * (real_stripes) +
+ /*
+- * plus the raid_map, which includes both the tgt dev
+- * and the stripes
++ * Plus the raid_map, which includes both the tgt dev
++ * and the stripes.
+ */
+ sizeof(u64) * (total_stripes),
+ GFP_NOFS|__GFP_NOFAIL);
+
+- atomic_set(&bbio->error, 0);
+- refcount_set(&bbio->refs, 1);
++ atomic_set(&bioc->error, 0);
++ refcount_set(&bioc->refs, 1);
+
+- bbio->tgtdev_map = (int *)(bbio->stripes + total_stripes);
+- bbio->raid_map = (u64 *)(bbio->tgtdev_map + real_stripes);
++ bioc->tgtdev_map = (int *)(bioc->stripes + total_stripes);
++ bioc->raid_map = (u64 *)(bioc->tgtdev_map + real_stripes);
+
+- return bbio;
++ return bioc;
+ }
+
+-void btrfs_get_bbio(struct btrfs_bio *bbio)
++void btrfs_get_bioc(struct btrfs_io_context *bioc)
+ {
+- WARN_ON(!refcount_read(&bbio->refs));
+- refcount_inc(&bbio->refs);
++ WARN_ON(!refcount_read(&bioc->refs));
++ refcount_inc(&bioc->refs);
+ }
+
+-void btrfs_put_bbio(struct btrfs_bio *bbio)
++void btrfs_put_bioc(struct btrfs_io_context *bioc)
+ {
+- if (!bbio)
++ if (!bioc)
+ return;
+- if (refcount_dec_and_test(&bbio->refs))
+- kfree(bbio);
++ if (refcount_dec_and_test(&bioc->refs))
++ kfree(bioc);
+ }
+
+ /* can REQ_OP_DISCARD be sent with other REQ like REQ_OP_WRITE? */
+@@ -5932,11 +5933,11 @@ void btrfs_put_bbio(struct btrfs_bio *bbio)
+ */
+ static int __btrfs_map_block_for_discard(struct btrfs_fs_info *fs_info,
+ u64 logical, u64 *length_ret,
+- struct btrfs_bio **bbio_ret)
++ struct btrfs_io_context **bioc_ret)
+ {
+ struct extent_map *em;
+ struct map_lookup *map;
+- struct btrfs_bio *bbio;
++ struct btrfs_io_context *bioc;
+ u64 length = *length_ret;
+ u64 offset;
+ u64 stripe_nr;
+@@ -5955,8 +5956,8 @@ static int __btrfs_map_block_for_discard(struct btrfs_fs_info *fs_info,
+ int ret = 0;
+ int i;
+
+- /* discard always return a bbio */
+- ASSERT(bbio_ret);
++ /* Discard always returns a bioc. */
++ ASSERT(bioc_ret);
+
+ em = btrfs_get_chunk_map(fs_info, logical, length);
+ if (IS_ERR(em))
+@@ -6019,26 +6020,25 @@ static int __btrfs_map_block_for_discard(struct btrfs_fs_info *fs_info,
+ &stripe_index);
+ }
+
+- bbio = alloc_btrfs_bio(num_stripes, 0);
+- if (!bbio) {
++ bioc = alloc_btrfs_io_context(num_stripes, 0);
++ if (!bioc) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ for (i = 0; i < num_stripes; i++) {
+- bbio->stripes[i].physical =
++ bioc->stripes[i].physical =
+ map->stripes[stripe_index].physical +
+ stripe_offset + stripe_nr * map->stripe_len;
+- bbio->stripes[i].dev = map->stripes[stripe_index].dev;
++ bioc->stripes[i].dev = map->stripes[stripe_index].dev;
+
+ if (map->type & (BTRFS_BLOCK_GROUP_RAID0 |
+ BTRFS_BLOCK_GROUP_RAID10)) {
+- bbio->stripes[i].length = stripes_per_dev *
++ bioc->stripes[i].length = stripes_per_dev *
+ map->stripe_len;
+
+ if (i / sub_stripes < remaining_stripes)
+- bbio->stripes[i].length +=
+- map->stripe_len;
++ bioc->stripes[i].length += map->stripe_len;
+
+ /*
+ * Special for the first stripe and
+@@ -6049,19 +6049,17 @@ static int __btrfs_map_block_for_discard(struct btrfs_fs_info *fs_info,
+ * off end_off
+ */
+ if (i < sub_stripes)
+- bbio->stripes[i].length -=
+- stripe_offset;
++ bioc->stripes[i].length -= stripe_offset;
+
+ if (stripe_index >= last_stripe &&
+ stripe_index <= (last_stripe +
+ sub_stripes - 1))
+- bbio->stripes[i].length -=
+- stripe_end_offset;
++ bioc->stripes[i].length -= stripe_end_offset;
+
+ if (i == sub_stripes - 1)
+ stripe_offset = 0;
+ } else {
+- bbio->stripes[i].length = length;
++ bioc->stripes[i].length = length;
+ }
+
+ stripe_index++;
+@@ -6071,9 +6069,9 @@ static int __btrfs_map_block_for_discard(struct btrfs_fs_info *fs_info,
+ }
+ }
+
+- *bbio_ret = bbio;
+- bbio->map_type = map->type;
+- bbio->num_stripes = num_stripes;
++ *bioc_ret = bioc;
++ bioc->map_type = map->type;
++ bioc->num_stripes = num_stripes;
+ out:
+ free_extent_map(em);
+ return ret;
+@@ -6097,7 +6095,7 @@ static int get_extra_mirror_from_replace(struct btrfs_fs_info *fs_info,
+ u64 srcdev_devid, int *mirror_num,
+ u64 *physical)
+ {
+- struct btrfs_bio *bbio = NULL;
++ struct btrfs_io_context *bioc = NULL;
+ int num_stripes;
+ int index_srcdev = 0;
+ int found = 0;
+@@ -6106,20 +6104,20 @@ static int get_extra_mirror_from_replace(struct btrfs_fs_info *fs_info,
+ int ret = 0;
+
+ ret = __btrfs_map_block(fs_info, BTRFS_MAP_GET_READ_MIRRORS,
+- logical, &length, &bbio, 0, 0);
++ logical, &length, &bioc, 0, 0);
+ if (ret) {
+- ASSERT(bbio == NULL);
++ ASSERT(bioc == NULL);
+ return ret;
+ }
+
+- num_stripes = bbio->num_stripes;
++ num_stripes = bioc->num_stripes;
+ if (*mirror_num > num_stripes) {
+ /*
+ * BTRFS_MAP_GET_READ_MIRRORS does not contain this mirror,
+ * that means that the requested area is not left of the left
+ * cursor
+ */
+- btrfs_put_bbio(bbio);
++ btrfs_put_bioc(bioc);
+ return -EIO;
+ }
+
+@@ -6129,7 +6127,7 @@ static int get_extra_mirror_from_replace(struct btrfs_fs_info *fs_info,
+ * pointer to the one of the target drive.
+ */
+ for (i = 0; i < num_stripes; i++) {
+- if (bbio->stripes[i].dev->devid != srcdev_devid)
++ if (bioc->stripes[i].dev->devid != srcdev_devid)
+ continue;
+
+ /*
+@@ -6137,15 +6135,15 @@ static int get_extra_mirror_from_replace(struct btrfs_fs_info *fs_info,
+ * mirror with the lowest physical address
+ */
+ if (found &&
+- physical_of_found <= bbio->stripes[i].physical)
++ physical_of_found <= bioc->stripes[i].physical)
+ continue;
+
+ index_srcdev = i;
+ found = 1;
+- physical_of_found = bbio->stripes[i].physical;
++ physical_of_found = bioc->stripes[i].physical;
+ }
+
+- btrfs_put_bbio(bbio);
++ btrfs_put_bioc(bioc);
+
+ ASSERT(found);
+ if (!found)
+@@ -6176,12 +6174,12 @@ static bool is_block_group_to_copy(struct btrfs_fs_info *fs_info, u64 logical)
+ }
+
+ static void handle_ops_on_dev_replace(enum btrfs_map_op op,
+- struct btrfs_bio **bbio_ret,
++ struct btrfs_io_context **bioc_ret,
+ struct btrfs_dev_replace *dev_replace,
+ u64 logical,
+ int *num_stripes_ret, int *max_errors_ret)
+ {
+- struct btrfs_bio *bbio = *bbio_ret;
++ struct btrfs_io_context *bioc = *bioc_ret;
+ u64 srcdev_devid = dev_replace->srcdev->devid;
+ int tgtdev_indexes = 0;
+ int num_stripes = *num_stripes_ret;
+@@ -6211,17 +6209,17 @@ static void handle_ops_on_dev_replace(enum btrfs_map_op op,
+ */
+ index_where_to_add = num_stripes;
+ for (i = 0; i < num_stripes; i++) {
+- if (bbio->stripes[i].dev->devid == srcdev_devid) {
++ if (bioc->stripes[i].dev->devid == srcdev_devid) {
+ /* write to new disk, too */
+- struct btrfs_bio_stripe *new =
+- bbio->stripes + index_where_to_add;
+- struct btrfs_bio_stripe *old =
+- bbio->stripes + i;
++ struct btrfs_io_stripe *new =
++ bioc->stripes + index_where_to_add;
++ struct btrfs_io_stripe *old =
++ bioc->stripes + i;
+
+ new->physical = old->physical;
+ new->length = old->length;
+ new->dev = dev_replace->tgtdev;
+- bbio->tgtdev_map[i] = index_where_to_add;
++ bioc->tgtdev_map[i] = index_where_to_add;
+ index_where_to_add++;
+ max_errors++;
+ tgtdev_indexes++;
+@@ -6241,30 +6239,29 @@ static void handle_ops_on_dev_replace(enum btrfs_map_op op,
+ * full copy of the source drive.
+ */
+ for (i = 0; i < num_stripes; i++) {
+- if (bbio->stripes[i].dev->devid == srcdev_devid) {
++ if (bioc->stripes[i].dev->devid == srcdev_devid) {
+ /*
+ * In case of DUP, in order to keep it simple,
+ * only add the mirror with the lowest physical
+ * address
+ */
+ if (found &&
+- physical_of_found <=
+- bbio->stripes[i].physical)
++ physical_of_found <= bioc->stripes[i].physical)
+ continue;
+ index_srcdev = i;
+ found = 1;
+- physical_of_found = bbio->stripes[i].physical;
++ physical_of_found = bioc->stripes[i].physical;
+ }
+ }
+ if (found) {
+- struct btrfs_bio_stripe *tgtdev_stripe =
+- bbio->stripes + num_stripes;
++ struct btrfs_io_stripe *tgtdev_stripe =
++ bioc->stripes + num_stripes;
+
+ tgtdev_stripe->physical = physical_of_found;
+ tgtdev_stripe->length =
+- bbio->stripes[index_srcdev].length;
++ bioc->stripes[index_srcdev].length;
+ tgtdev_stripe->dev = dev_replace->tgtdev;
+- bbio->tgtdev_map[index_srcdev] = num_stripes;
++ bioc->tgtdev_map[index_srcdev] = num_stripes;
+
+ tgtdev_indexes++;
+ num_stripes++;
+@@ -6273,8 +6270,8 @@ static void handle_ops_on_dev_replace(enum btrfs_map_op op,
+
+ *num_stripes_ret = num_stripes;
+ *max_errors_ret = max_errors;
+- bbio->num_tgtdevs = tgtdev_indexes;
+- *bbio_ret = bbio;
++ bioc->num_tgtdevs = tgtdev_indexes;
++ *bioc_ret = bioc;
+ }
+
+ static bool need_full_stripe(enum btrfs_map_op op)
+@@ -6377,7 +6374,7 @@ int btrfs_get_io_geometry(struct btrfs_fs_info *fs_info, struct extent_map *em,
+ static int __btrfs_map_block(struct btrfs_fs_info *fs_info,
+ enum btrfs_map_op op,
+ u64 logical, u64 *length,
+- struct btrfs_bio **bbio_ret,
++ struct btrfs_io_context **bioc_ret,
+ int mirror_num, int need_raid_map)
+ {
+ struct extent_map *em;
+@@ -6392,7 +6389,7 @@ static int __btrfs_map_block(struct btrfs_fs_info *fs_info,
+ int num_stripes;
+ int max_errors = 0;
+ int tgtdev_indexes = 0;
+- struct btrfs_bio *bbio = NULL;
++ struct btrfs_io_context *bioc = NULL;
+ struct btrfs_dev_replace *dev_replace = &fs_info->dev_replace;
+ int dev_replace_is_ongoing = 0;
+ int num_alloc_stripes;
+@@ -6401,7 +6398,7 @@ static int __btrfs_map_block(struct btrfs_fs_info *fs_info,
+ u64 raid56_full_stripe_start = (u64)-1;
+ struct btrfs_io_geometry geom;
+
+- ASSERT(bbio_ret);
++ ASSERT(bioc_ret);
+ ASSERT(op != BTRFS_MAP_DISCARD);
+
+ em = btrfs_get_chunk_map(fs_info, logical, *length);
+@@ -6545,20 +6542,20 @@ static int __btrfs_map_block(struct btrfs_fs_info *fs_info,
+ tgtdev_indexes = num_stripes;
+ }
+
+- bbio = alloc_btrfs_bio(num_alloc_stripes, tgtdev_indexes);
+- if (!bbio) {
++ bioc = alloc_btrfs_io_context(num_alloc_stripes, tgtdev_indexes);
++ if (!bioc) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ for (i = 0; i < num_stripes; i++) {
+- bbio->stripes[i].physical = map->stripes[stripe_index].physical +
++ bioc->stripes[i].physical = map->stripes[stripe_index].physical +
+ stripe_offset + stripe_nr * map->stripe_len;
+- bbio->stripes[i].dev = map->stripes[stripe_index].dev;
++ bioc->stripes[i].dev = map->stripes[stripe_index].dev;
+ stripe_index++;
+ }
+
+- /* build raid_map */
++ /* Build raid_map */
+ if (map->type & BTRFS_BLOCK_GROUP_RAID56_MASK && need_raid_map &&
+ (need_full_stripe(op) || mirror_num > 1)) {
+ u64 tmp;
+@@ -6570,15 +6567,15 @@ static int __btrfs_map_block(struct btrfs_fs_info *fs_info,
+ /* Fill in the logical address of each stripe */
+ tmp = stripe_nr * data_stripes;
+ for (i = 0; i < data_stripes; i++)
+- bbio->raid_map[(i+rot) % num_stripes] =
++ bioc->raid_map[(i + rot) % num_stripes] =
+ em->start + (tmp + i) * map->stripe_len;
+
+- bbio->raid_map[(i+rot) % map->num_stripes] = RAID5_P_STRIPE;
++ bioc->raid_map[(i + rot) % map->num_stripes] = RAID5_P_STRIPE;
+ if (map->type & BTRFS_BLOCK_GROUP_RAID6)
+- bbio->raid_map[(i+rot+1) % num_stripes] =
++ bioc->raid_map[(i + rot + 1) % num_stripes] =
+ RAID6_Q_STRIPE;
+
+- sort_parity_stripes(bbio, num_stripes);
++ sort_parity_stripes(bioc, num_stripes);
+ }
+
+ if (need_full_stripe(op))
+@@ -6586,15 +6583,15 @@ static int __btrfs_map_block(struct btrfs_fs_info *fs_info,
+
+ if (dev_replace_is_ongoing && dev_replace->tgtdev != NULL &&
+ need_full_stripe(op)) {
+- handle_ops_on_dev_replace(op, &bbio, dev_replace, logical,
++ handle_ops_on_dev_replace(op, &bioc, dev_replace, logical,
+ &num_stripes, &max_errors);
+ }
+
+- *bbio_ret = bbio;
+- bbio->map_type = map->type;
+- bbio->num_stripes = num_stripes;
+- bbio->max_errors = max_errors;
+- bbio->mirror_num = mirror_num;
++ *bioc_ret = bioc;
++ bioc->map_type = map->type;
++ bioc->num_stripes = num_stripes;
++ bioc->max_errors = max_errors;
++ bioc->mirror_num = mirror_num;
+
+ /*
+ * this is the case that REQ_READ && dev_replace_is_ongoing &&
+@@ -6603,9 +6600,9 @@ static int __btrfs_map_block(struct btrfs_fs_info *fs_info,
+ */
+ if (patch_the_first_stripe_for_dev_replace && num_stripes > 0) {
+ WARN_ON(num_stripes > 1);
+- bbio->stripes[0].dev = dev_replace->tgtdev;
+- bbio->stripes[0].physical = physical_to_patch_in_first_stripe;
+- bbio->mirror_num = map->num_stripes + 1;
++ bioc->stripes[0].dev = dev_replace->tgtdev;
++ bioc->stripes[0].physical = physical_to_patch_in_first_stripe;
++ bioc->mirror_num = map->num_stripes + 1;
+ }
+ out:
+ if (dev_replace_is_ongoing) {
+@@ -6619,40 +6616,40 @@ static int __btrfs_map_block(struct btrfs_fs_info *fs_info,
+
+ int btrfs_map_block(struct btrfs_fs_info *fs_info, enum btrfs_map_op op,
+ u64 logical, u64 *length,
+- struct btrfs_bio **bbio_ret, int mirror_num)
++ struct btrfs_io_context **bioc_ret, int mirror_num)
+ {
+ if (op == BTRFS_MAP_DISCARD)
+ return __btrfs_map_block_for_discard(fs_info, logical,
+- length, bbio_ret);
++ length, bioc_ret);
+
+- return __btrfs_map_block(fs_info, op, logical, length, bbio_ret,
++ return __btrfs_map_block(fs_info, op, logical, length, bioc_ret,
+ mirror_num, 0);
+ }
+
+ /* For Scrub/replace */
+ int btrfs_map_sblock(struct btrfs_fs_info *fs_info, enum btrfs_map_op op,
+ u64 logical, u64 *length,
+- struct btrfs_bio **bbio_ret)
++ struct btrfs_io_context **bioc_ret)
+ {
+- return __btrfs_map_block(fs_info, op, logical, length, bbio_ret, 0, 1);
++ return __btrfs_map_block(fs_info, op, logical, length, bioc_ret, 0, 1);
+ }
+
+-static inline void btrfs_end_bbio(struct btrfs_bio *bbio, struct bio *bio)
++static inline void btrfs_end_bioc(struct btrfs_io_context *bioc, struct bio *bio)
+ {
+- bio->bi_private = bbio->private;
+- bio->bi_end_io = bbio->end_io;
++ bio->bi_private = bioc->private;
++ bio->bi_end_io = bioc->end_io;
+ bio_endio(bio);
+
+- btrfs_put_bbio(bbio);
++ btrfs_put_bioc(bioc);
+ }
+
+ static void btrfs_end_bio(struct bio *bio)
+ {
+- struct btrfs_bio *bbio = bio->bi_private;
++ struct btrfs_io_context *bioc = bio->bi_private;
+ int is_orig_bio = 0;
+
+ if (bio->bi_status) {
+- atomic_inc(&bbio->error);
++ atomic_inc(&bioc->error);
+ if (bio->bi_status == BLK_STS_IOERR ||
+ bio->bi_status == BLK_STS_TARGET) {
+ struct btrfs_device *dev = btrfs_io_bio(bio)->device;
+@@ -6670,22 +6667,22 @@ static void btrfs_end_bio(struct bio *bio)
+ }
+ }
+
+- if (bio == bbio->orig_bio)
++ if (bio == bioc->orig_bio)
+ is_orig_bio = 1;
+
+- btrfs_bio_counter_dec(bbio->fs_info);
++ btrfs_bio_counter_dec(bioc->fs_info);
+
+- if (atomic_dec_and_test(&bbio->stripes_pending)) {
++ if (atomic_dec_and_test(&bioc->stripes_pending)) {
+ if (!is_orig_bio) {
+ bio_put(bio);
+- bio = bbio->orig_bio;
++ bio = bioc->orig_bio;
+ }
+
+- btrfs_io_bio(bio)->mirror_num = bbio->mirror_num;
++ btrfs_io_bio(bio)->mirror_num = bioc->mirror_num;
+ /* only send an error to the higher layers if it is
+ * beyond the tolerance of the btrfs bio
+ */
+- if (atomic_read(&bbio->error) > bbio->max_errors) {
++ if (atomic_read(&bioc->error) > bioc->max_errors) {
+ bio->bi_status = BLK_STS_IOERR;
+ } else {
+ /*
+@@ -6695,18 +6692,18 @@ static void btrfs_end_bio(struct bio *bio)
+ bio->bi_status = BLK_STS_OK;
+ }
+
+- btrfs_end_bbio(bbio, bio);
++ btrfs_end_bioc(bioc, bio);
+ } else if (!is_orig_bio) {
+ bio_put(bio);
+ }
+ }
+
+-static void submit_stripe_bio(struct btrfs_bio *bbio, struct bio *bio,
++static void submit_stripe_bio(struct btrfs_io_context *bioc, struct bio *bio,
+ u64 physical, struct btrfs_device *dev)
+ {
+- struct btrfs_fs_info *fs_info = bbio->fs_info;
++ struct btrfs_fs_info *fs_info = bioc->fs_info;
+
+- bio->bi_private = bbio;
++ bio->bi_private = bioc;
+ btrfs_io_bio(bio)->device = dev;
+ bio->bi_end_io = btrfs_end_bio;
+ bio->bi_iter.bi_sector = physical >> 9;
+@@ -6736,20 +6733,20 @@ static void submit_stripe_bio(struct btrfs_bio *bbio, struct bio *bio,
+ btrfsic_submit_bio(bio);
+ }
+
+-static void bbio_error(struct btrfs_bio *bbio, struct bio *bio, u64 logical)
++static void bioc_error(struct btrfs_io_context *bioc, struct bio *bio, u64 logical)
+ {
+- atomic_inc(&bbio->error);
+- if (atomic_dec_and_test(&bbio->stripes_pending)) {
++ atomic_inc(&bioc->error);
++ if (atomic_dec_and_test(&bioc->stripes_pending)) {
+ /* Should be the original bio. */
+- WARN_ON(bio != bbio->orig_bio);
++ WARN_ON(bio != bioc->orig_bio);
+
+- btrfs_io_bio(bio)->mirror_num = bbio->mirror_num;
++ btrfs_io_bio(bio)->mirror_num = bioc->mirror_num;
+ bio->bi_iter.bi_sector = logical >> 9;
+- if (atomic_read(&bbio->error) > bbio->max_errors)
++ if (atomic_read(&bioc->error) > bioc->max_errors)
+ bio->bi_status = BLK_STS_IOERR;
+ else
+ bio->bi_status = BLK_STS_OK;
+- btrfs_end_bbio(bbio, bio);
++ btrfs_end_bioc(bioc, bio);
+ }
+ }
+
+@@ -6764,35 +6761,35 @@ blk_status_t btrfs_map_bio(struct btrfs_fs_info *fs_info, struct bio *bio,
+ int ret;
+ int dev_nr;
+ int total_devs;
+- struct btrfs_bio *bbio = NULL;
++ struct btrfs_io_context *bioc = NULL;
+
+ length = bio->bi_iter.bi_size;
+ map_length = length;
+
+ btrfs_bio_counter_inc_blocked(fs_info);
+ ret = __btrfs_map_block(fs_info, btrfs_op(bio), logical,
+- &map_length, &bbio, mirror_num, 1);
++ &map_length, &bioc, mirror_num, 1);
+ if (ret) {
+ btrfs_bio_counter_dec(fs_info);
+ return errno_to_blk_status(ret);
+ }
+
+- total_devs = bbio->num_stripes;
+- bbio->orig_bio = first_bio;
+- bbio->private = first_bio->bi_private;
+- bbio->end_io = first_bio->bi_end_io;
+- bbio->fs_info = fs_info;
+- atomic_set(&bbio->stripes_pending, bbio->num_stripes);
++ total_devs = bioc->num_stripes;
++ bioc->orig_bio = first_bio;
++ bioc->private = first_bio->bi_private;
++ bioc->end_io = first_bio->bi_end_io;
++ bioc->fs_info = fs_info;
++ atomic_set(&bioc->stripes_pending, bioc->num_stripes);
+
+- if ((bbio->map_type & BTRFS_BLOCK_GROUP_RAID56_MASK) &&
++ if ((bioc->map_type & BTRFS_BLOCK_GROUP_RAID56_MASK) &&
+ ((btrfs_op(bio) == BTRFS_MAP_WRITE) || (mirror_num > 1))) {
+ /* In this case, map_length has been set to the length of
+ a single stripe; not the whole write */
+ if (btrfs_op(bio) == BTRFS_MAP_WRITE) {
+- ret = raid56_parity_write(fs_info, bio, bbio,
++ ret = raid56_parity_write(fs_info, bio, bioc,
+ map_length);
+ } else {
+- ret = raid56_parity_recover(fs_info, bio, bbio,
++ ret = raid56_parity_recover(fs_info, bio, bioc,
+ map_length, mirror_num, 1);
+ }
+
+@@ -6808,12 +6805,12 @@ blk_status_t btrfs_map_bio(struct btrfs_fs_info *fs_info, struct bio *bio,
+ }
+
+ for (dev_nr = 0; dev_nr < total_devs; dev_nr++) {
+- dev = bbio->stripes[dev_nr].dev;
++ dev = bioc->stripes[dev_nr].dev;
+ if (!dev || !dev->bdev || test_bit(BTRFS_DEV_STATE_MISSING,
+ &dev->dev_state) ||
+ (btrfs_op(first_bio) == BTRFS_MAP_WRITE &&
+ !test_bit(BTRFS_DEV_STATE_WRITEABLE, &dev->dev_state))) {
+- bbio_error(bbio, first_bio, logical);
++ bioc_error(bioc, first_bio, logical);
+ continue;
+ }
+
+@@ -6822,7 +6819,7 @@ blk_status_t btrfs_map_bio(struct btrfs_fs_info *fs_info, struct bio *bio,
+ else
+ bio = first_bio;
+
+- submit_stripe_bio(bbio, bio, bbio->stripes[dev_nr].physical, dev);
++ submit_stripe_bio(bioc, bio, bioc->stripes[dev_nr].physical, dev);
+ }
+ btrfs_bio_counter_dec(fs_info);
+ return BLK_STS_OK;
+diff --git a/fs/btrfs/volumes.h b/fs/btrfs/volumes.h
+index 30288b728bbb..dfd7457709b3 100644
+--- a/fs/btrfs/volumes.h
++++ b/fs/btrfs/volumes.h
+@@ -306,11 +306,11 @@ struct btrfs_fs_devices {
+ /*
+ * we need the mirror number and stripe index to be passed around
+ * the call chain while we are processing end_io (especially errors).
+- * Really, what we need is a btrfs_bio structure that has this info
++ * Really, what we need is a btrfs_io_context structure that has this info
+ * and is properly sized with its stripe array, but we're not there
+ * quite yet. We have our own btrfs bioset, and all of the bios
+ * we allocate are actually btrfs_io_bios. We'll cram as much of
+- * struct btrfs_bio as we can into this over time.
++ * struct btrfs_io_context as we can into this over time.
+ */
+ struct btrfs_io_bio {
+ unsigned int mirror_num;
+@@ -339,13 +339,29 @@ static inline void btrfs_io_bio_free_csum(struct btrfs_io_bio *io_bio)
+ }
+ }
+
+-struct btrfs_bio_stripe {
++struct btrfs_io_stripe {
+ struct btrfs_device *dev;
+ u64 physical;
+ u64 length; /* only used for discard mappings */
+ };
+
+-struct btrfs_bio {
++/*
++ * Context for IO subsmission for device stripe.
++ *
++ * - Track the unfinished mirrors for mirror based profiles
++ * Mirror based profiles are SINGLE/DUP/RAID1/RAID10.
++ *
++ * - Contain the logical -> physical mapping info
++ * Used by submit_stripe_bio() for mapping logical bio
++ * into physical device address.
++ *
++ * - Contain device replace info
++ * Used by handle_ops_on_dev_replace() to copy logical bios
++ * into the new device.
++ *
++ * - Contain RAID56 full stripe logical bytenrs
++ */
++struct btrfs_io_context {
+ refcount_t refs;
+ atomic_t stripes_pending;
+ struct btrfs_fs_info *fs_info;
+@@ -365,7 +381,7 @@ struct btrfs_bio {
+ * so raid_map[0] is the start of our full stripe
+ */
+ u64 *raid_map;
+- struct btrfs_bio_stripe stripes[];
++ struct btrfs_io_stripe stripes[];
+ };
+
+ struct btrfs_device_info {
+@@ -400,11 +416,11 @@ struct map_lookup {
+ int num_stripes;
+ int sub_stripes;
+ int verified_stripes; /* For mount time dev extent verification */
+- struct btrfs_bio_stripe stripes[];
++ struct btrfs_io_stripe stripes[];
+ };
+
+ #define map_lookup_size(n) (sizeof(struct map_lookup) + \
+- (sizeof(struct btrfs_bio_stripe) * (n)))
++ (sizeof(struct btrfs_io_stripe) * (n)))
+
+ struct btrfs_balance_args;
+ struct btrfs_balance_progress;
+@@ -457,14 +473,14 @@ static inline enum btrfs_map_op btrfs_op(struct bio *bio)
+ }
+ }
+
+-void btrfs_get_bbio(struct btrfs_bio *bbio);
+-void btrfs_put_bbio(struct btrfs_bio *bbio);
++void btrfs_get_bioc(struct btrfs_io_context *bioc);
++void btrfs_put_bioc(struct btrfs_io_context *bioc);
+ int btrfs_map_block(struct btrfs_fs_info *fs_info, enum btrfs_map_op op,
+ u64 logical, u64 *length,
+- struct btrfs_bio **bbio_ret, int mirror_num);
++ struct btrfs_io_context **bioc_ret, int mirror_num);
+ int btrfs_map_sblock(struct btrfs_fs_info *fs_info, enum btrfs_map_op op,
+ u64 logical, u64 *length,
+- struct btrfs_bio **bbio_ret);
++ struct btrfs_io_context **bioc_ret);
+ int btrfs_get_io_geometry(struct btrfs_fs_info *fs_info, struct extent_map *map,
+ enum btrfs_map_op op, u64 logical,
+ struct btrfs_io_geometry *io_geom);
+diff --git a/fs/btrfs/zoned.c b/fs/btrfs/zoned.c
+index 3bc2f92cd197..ce4eeffc4f12 100644
+--- a/fs/btrfs/zoned.c
++++ b/fs/btrfs/zoned.c
+@@ -1502,27 +1502,27 @@ int btrfs_zoned_issue_zeroout(struct btrfs_device *device, u64 physical, u64 len
+ static int read_zone_info(struct btrfs_fs_info *fs_info, u64 logical,
+ struct blk_zone *zone)
+ {
+- struct btrfs_bio *bbio = NULL;
++ struct btrfs_io_context *bioc = NULL;
+ u64 mapped_length = PAGE_SIZE;
+ unsigned int nofs_flag;
+ int nmirrors;
+ int i, ret;
+
+ ret = btrfs_map_sblock(fs_info, BTRFS_MAP_GET_READ_MIRRORS, logical,
+- &mapped_length, &bbio);
+- if (ret || !bbio || mapped_length < PAGE_SIZE) {
+- btrfs_put_bbio(bbio);
++ &mapped_length, &bioc);
++ if (ret || !bioc || mapped_length < PAGE_SIZE) {
++ btrfs_put_bioc(bioc);
+ return -EIO;
+ }
+
+- if (bbio->map_type & BTRFS_BLOCK_GROUP_RAID56_MASK)
++ if (bioc->map_type & BTRFS_BLOCK_GROUP_RAID56_MASK)
+ return -EINVAL;
+
+ nofs_flag = memalloc_nofs_save();
+- nmirrors = (int)bbio->num_stripes;
++ nmirrors = (int)bioc->num_stripes;
+ for (i = 0; i < nmirrors; i++) {
+- u64 physical = bbio->stripes[i].physical;
+- struct btrfs_device *dev = bbio->stripes[i].dev;
++ u64 physical = bioc->stripes[i].physical;
++ struct btrfs_device *dev = bioc->stripes[i].dev;
+
+ /* Missing device */
+ if (!dev->bdev)
+--
+2.35.1
+
--- /dev/null
+From a851a2fccaa299509aaf5bd4184188debebb737c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 30 Jun 2022 18:03:19 +0200
+Subject: btrfs: zoned: fix a leaked bioc in read_zone_info
+
+From: Christoph Hellwig <hch@lst.de>
+
+[ Upstream commit 2963457829decf0c824a443238d251151ed18ff5 ]
+
+The bioc would leak on the normal completion path and also on the RAID56
+check (but that one won't happen in practice due to the invalid
+combination with zoned mode).
+
+Fixes: 7db1c5d14dcd ("btrfs: zoned: support dev-replace in zoned filesystems")
+CC: stable@vger.kernel.org # 5.16+
+Reviewed-by: Anand Jain <anand.jain@oracle.com>
+Signed-off-by: Christoph Hellwig <hch@lst.de>
+[ update changelog ]
+Reviewed-by: David Sterba <dsterba@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/btrfs/zoned.c | 13 ++++++++-----
+ 1 file changed, 8 insertions(+), 5 deletions(-)
+
+diff --git a/fs/btrfs/zoned.c b/fs/btrfs/zoned.c
+index ce4eeffc4f12..574769f921a2 100644
+--- a/fs/btrfs/zoned.c
++++ b/fs/btrfs/zoned.c
+@@ -1511,12 +1511,14 @@ static int read_zone_info(struct btrfs_fs_info *fs_info, u64 logical,
+ ret = btrfs_map_sblock(fs_info, BTRFS_MAP_GET_READ_MIRRORS, logical,
+ &mapped_length, &bioc);
+ if (ret || !bioc || mapped_length < PAGE_SIZE) {
+- btrfs_put_bioc(bioc);
+- return -EIO;
++ ret = -EIO;
++ goto out_put_bioc;
+ }
+
+- if (bioc->map_type & BTRFS_BLOCK_GROUP_RAID56_MASK)
+- return -EINVAL;
++ if (bioc->map_type & BTRFS_BLOCK_GROUP_RAID56_MASK) {
++ ret = -EINVAL;
++ goto out_put_bioc;
++ }
+
+ nofs_flag = memalloc_nofs_save();
+ nmirrors = (int)bioc->num_stripes;
+@@ -1535,7 +1537,8 @@ static int read_zone_info(struct btrfs_fs_info *fs_info, u64 logical,
+ break;
+ }
+ memalloc_nofs_restore(nofs_flag);
+-
++out_put_bioc:
++ btrfs_put_bioc(bioc);
+ return ret;
+ }
+
+--
+2.35.1
+
--- /dev/null
+From 4f4144b0ff472eda5693e1e9022a3a7215afa249 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 18 Jun 2022 10:25:45 +0800
+Subject: cpufreq: pmac32-cpufreq: Fix refcount leak bug
+
+From: Liang He <windhl@126.com>
+
+[ Upstream commit ccd7567d4b6cf187fdfa55f003a9e461ee629e36 ]
+
+In pmac_cpufreq_init_MacRISC3(), we need to add corresponding
+of_node_put() for the three node pointers whose refcount have
+been incremented by of_find_node_by_name().
+
+Signed-off-by: Liang He <windhl@126.com>
+Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/cpufreq/pmac32-cpufreq.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/drivers/cpufreq/pmac32-cpufreq.c b/drivers/cpufreq/pmac32-cpufreq.c
+index 4f20c6a9108d..8e41fe9ee870 100644
+--- a/drivers/cpufreq/pmac32-cpufreq.c
++++ b/drivers/cpufreq/pmac32-cpufreq.c
+@@ -470,6 +470,10 @@ static int pmac_cpufreq_init_MacRISC3(struct device_node *cpunode)
+ if (slew_done_gpio_np)
+ slew_done_gpio = read_gpio(slew_done_gpio_np);
+
++ of_node_put(volt_gpio_np);
++ of_node_put(freq_gpio_np);
++ of_node_put(slew_done_gpio_np);
++
+ /* If we use the frequency GPIOs, calculate the min/max speeds based
+ * on the bus frequencies
+ */
+--
+2.35.1
+
--- /dev/null
+From dc1aed1a19a7f681a8d969a46675fabcc6e241bc Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 7 Jun 2022 20:23:36 +0200
+Subject: fbdev: Disable sysfb device registration when removing conflicting
+ FBs
+
+From: Javier Martinez Canillas <javierm@redhat.com>
+
+[ Upstream commit ee7a69aa38d87a3bbced7b8245c732c05ed0c6ec ]
+
+The platform devices registered by sysfb match with firmware-based DRM or
+fbdev drivers, that are used to have early graphics using a framebuffer
+provided by the system firmware.
+
+DRM or fbdev drivers later are probed and remove conflicting framebuffers,
+leading to these platform devices for generic drivers to be unregistered.
+
+But the current solution has a race, since the sysfb_init() function could
+be called after a DRM or fbdev driver is probed and request to unregister
+the devices for drivers with conflicting framebuffes.
+
+To prevent this, disable any future sysfb platform device registration by
+calling sysfb_disable(), if a driver requests to remove the conflicting
+framebuffers.
+
+Suggested-by: Daniel Vetter <daniel.vetter@ffwll.ch>
+Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
+Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
+Link: https://patchwork.freedesktop.org/patch/msgid/20220607182338.344270-4-javierm@redhat.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/video/fbdev/core/fbmem.c | 12 ++++++++++++
+ 1 file changed, 12 insertions(+)
+
+diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c
+index 6d7868cc1fca..528c87ff14d8 100644
+--- a/drivers/video/fbdev/core/fbmem.c
++++ b/drivers/video/fbdev/core/fbmem.c
+@@ -19,6 +19,7 @@
+ #include <linux/kernel.h>
+ #include <linux/major.h>
+ #include <linux/slab.h>
++#include <linux/sysfb.h>
+ #include <linux/mm.h>
+ #include <linux/mman.h>
+ #include <linux/vt.h>
+@@ -1786,6 +1787,17 @@ int remove_conflicting_framebuffers(struct apertures_struct *a,
+ do_free = true;
+ }
+
++ /*
++ * If a driver asked to unregister a platform device registered by
++ * sysfb, then can be assumed that this is a driver for a display
++ * that is set up by the system firmware and has a generic driver.
++ *
++ * Drivers for devices that don't have a generic driver will never
++ * ask for this, so let's assume that a real driver for the display
++ * was already probed and prevent sysfb to register devices later.
++ */
++ sysfb_disable();
++
+ mutex_lock(®istration_lock);
+ do_remove_conflicting_framebuffers(a, name, primary);
+ mutex_unlock(®istration_lock);
+--
+2.35.1
+
--- /dev/null
+From 69fbbff9b4b8049858e04b8bd88a14d49a7c78e4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 7 Jun 2022 20:23:35 +0200
+Subject: firmware: sysfb: Add sysfb_disable() helper function
+
+From: Javier Martinez Canillas <javierm@redhat.com>
+
+[ Upstream commit bde376e9de3c0bc55eedc8956b0f114c05531595 ]
+
+This can be used by subsystems to unregister a platform device registered
+by sysfb and also to disable future platform device registration in sysfb.
+
+Suggested-by: Daniel Vetter <daniel.vetter@ffwll.ch>
+Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
+Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
+Link: https://patchwork.freedesktop.org/patch/msgid/20220607182338.344270-3-javierm@redhat.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../driver-api/firmware/other_interfaces.rst | 6 +++
+ drivers/firmware/sysfb.c | 54 ++++++++++++++++---
+ include/linux/sysfb.h | 12 +++++
+ 3 files changed, 66 insertions(+), 6 deletions(-)
+
+diff --git a/Documentation/driver-api/firmware/other_interfaces.rst b/Documentation/driver-api/firmware/other_interfaces.rst
+index b81794e0cfbb..06ac89adaafb 100644
+--- a/Documentation/driver-api/firmware/other_interfaces.rst
++++ b/Documentation/driver-api/firmware/other_interfaces.rst
+@@ -13,6 +13,12 @@ EDD Interfaces
+ .. kernel-doc:: drivers/firmware/edd.c
+ :internal:
+
++Generic System Framebuffers Interface
++-------------------------------------
++
++.. kernel-doc:: drivers/firmware/sysfb.c
++ :export:
++
+ Intel Stratix10 SoC Service Layer
+ ---------------------------------
+ Some features of the Intel Stratix10 SoC require a level of privilege
+diff --git a/drivers/firmware/sysfb.c b/drivers/firmware/sysfb.c
+index b032f40a92de..1f276f108cc9 100644
+--- a/drivers/firmware/sysfb.c
++++ b/drivers/firmware/sysfb.c
+@@ -34,21 +34,59 @@
+ #include <linux/screen_info.h>
+ #include <linux/sysfb.h>
+
++static struct platform_device *pd;
++static DEFINE_MUTEX(disable_lock);
++static bool disabled;
++
++static bool sysfb_unregister(void)
++{
++ if (IS_ERR_OR_NULL(pd))
++ return false;
++
++ platform_device_unregister(pd);
++ pd = NULL;
++
++ return true;
++}
++
++/**
++ * sysfb_disable() - disable the Generic System Framebuffers support
++ *
++ * This disables the registration of system framebuffer devices that match the
++ * generic drivers that make use of the system framebuffer set up by firmware.
++ *
++ * It also unregisters a device if this was already registered by sysfb_init().
++ *
++ * Context: The function can sleep. A @disable_lock mutex is acquired to serialize
++ * against sysfb_init(), that registers a system framebuffer device.
++ */
++void sysfb_disable(void)
++{
++ mutex_lock(&disable_lock);
++ sysfb_unregister();
++ disabled = true;
++ mutex_unlock(&disable_lock);
++}
++EXPORT_SYMBOL_GPL(sysfb_disable);
++
+ static __init int sysfb_init(void)
+ {
+ struct screen_info *si = &screen_info;
+ struct simplefb_platform_data mode;
+- struct platform_device *pd;
+ const char *name;
+ bool compatible;
+- int ret;
++ int ret = 0;
++
++ mutex_lock(&disable_lock);
++ if (disabled)
++ goto unlock_mutex;
+
+ /* try to create a simple-framebuffer device */
+ compatible = sysfb_parse_mode(si, &mode);
+ if (compatible) {
+ pd = sysfb_create_simplefb(si, &mode);
+ if (!IS_ERR(pd))
+- return 0;
++ goto unlock_mutex;
+ }
+
+ /* if the FB is incompatible, create a legacy framebuffer device */
+@@ -60,8 +98,10 @@ static __init int sysfb_init(void)
+ name = "platform-framebuffer";
+
+ pd = platform_device_alloc(name, 0);
+- if (!pd)
+- return -ENOMEM;
++ if (!pd) {
++ ret = -ENOMEM;
++ goto unlock_mutex;
++ }
+
+ sysfb_apply_efi_quirks(pd);
+
+@@ -73,9 +113,11 @@ static __init int sysfb_init(void)
+ if (ret)
+ goto err;
+
+- return 0;
++ goto unlock_mutex;
+ err:
+ platform_device_put(pd);
++unlock_mutex:
++ mutex_unlock(&disable_lock);
+ return ret;
+ }
+
+diff --git a/include/linux/sysfb.h b/include/linux/sysfb.h
+index 708152e9037b..8ba8b5be5567 100644
+--- a/include/linux/sysfb.h
++++ b/include/linux/sysfb.h
+@@ -55,6 +55,18 @@ struct efifb_dmi_info {
+ int flags;
+ };
+
++#ifdef CONFIG_SYSFB
++
++void sysfb_disable(void);
++
++#else /* CONFIG_SYSFB */
++
++static inline void sysfb_disable(void)
++{
++}
++
++#endif /* CONFIG_SYSFB */
++
+ #ifdef CONFIG_EFI
+
+ extern struct efifb_dmi_info efifb_dmi_list[];
+--
+2.35.1
+
--- /dev/null
+From c7266280c5e3653d9646fcdb9137d3495ffaef58 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 7 Jun 2022 20:23:34 +0200
+Subject: firmware: sysfb: Make sysfb_create_simplefb() return a pdev pointer
+
+From: Javier Martinez Canillas <javierm@redhat.com>
+
+[ Upstream commit 9e121040e54abef9ed5542e5fdfa87911cd96204 ]
+
+This function just returned 0 on success or an errno code on error, but it
+could be useful for sysfb_init() callers to have a pointer to the device.
+
+Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
+Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
+Reviewed-by: Thomas Zimmermann <tzimmermann@suse.de>
+Link: https://patchwork.freedesktop.org/patch/msgid/20220607182338.344270-2-javierm@redhat.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/firmware/sysfb.c | 4 ++--
+ drivers/firmware/sysfb_simplefb.c | 16 ++++++++--------
+ include/linux/sysfb.h | 10 +++++-----
+ 3 files changed, 15 insertions(+), 15 deletions(-)
+
+diff --git a/drivers/firmware/sysfb.c b/drivers/firmware/sysfb.c
+index 2bfbb05f7d89..b032f40a92de 100644
+--- a/drivers/firmware/sysfb.c
++++ b/drivers/firmware/sysfb.c
+@@ -46,8 +46,8 @@ static __init int sysfb_init(void)
+ /* try to create a simple-framebuffer device */
+ compatible = sysfb_parse_mode(si, &mode);
+ if (compatible) {
+- ret = sysfb_create_simplefb(si, &mode);
+- if (!ret)
++ pd = sysfb_create_simplefb(si, &mode);
++ if (!IS_ERR(pd))
+ return 0;
+ }
+
+diff --git a/drivers/firmware/sysfb_simplefb.c b/drivers/firmware/sysfb_simplefb.c
+index 757cc8b9f3de..eac51c2a27ba 100644
+--- a/drivers/firmware/sysfb_simplefb.c
++++ b/drivers/firmware/sysfb_simplefb.c
+@@ -57,8 +57,8 @@ __init bool sysfb_parse_mode(const struct screen_info *si,
+ return false;
+ }
+
+-__init int sysfb_create_simplefb(const struct screen_info *si,
+- const struct simplefb_platform_data *mode)
++__init struct platform_device *sysfb_create_simplefb(const struct screen_info *si,
++ const struct simplefb_platform_data *mode)
+ {
+ struct platform_device *pd;
+ struct resource res;
+@@ -76,7 +76,7 @@ __init int sysfb_create_simplefb(const struct screen_info *si,
+ base |= (u64)si->ext_lfb_base << 32;
+ if (!base || (u64)(resource_size_t)base != base) {
+ printk(KERN_DEBUG "sysfb: inaccessible VRAM base\n");
+- return -EINVAL;
++ return ERR_PTR(-EINVAL);
+ }
+
+ /*
+@@ -93,7 +93,7 @@ __init int sysfb_create_simplefb(const struct screen_info *si,
+ length = mode->height * mode->stride;
+ if (length > size) {
+ printk(KERN_WARNING "sysfb: VRAM smaller than advertised\n");
+- return -EINVAL;
++ return ERR_PTR(-EINVAL);
+ }
+ length = PAGE_ALIGN(length);
+
+@@ -104,11 +104,11 @@ __init int sysfb_create_simplefb(const struct screen_info *si,
+ res.start = base;
+ res.end = res.start + length - 1;
+ if (res.end <= res.start)
+- return -EINVAL;
++ return ERR_PTR(-EINVAL);
+
+ pd = platform_device_alloc("simple-framebuffer", 0);
+ if (!pd)
+- return -ENOMEM;
++ return ERR_PTR(-ENOMEM);
+
+ sysfb_apply_efi_quirks(pd);
+
+@@ -124,10 +124,10 @@ __init int sysfb_create_simplefb(const struct screen_info *si,
+ if (ret)
+ goto err_put_device;
+
+- return 0;
++ return pd;
+
+ err_put_device:
+ platform_device_put(pd);
+
+- return ret;
++ return ERR_PTR(ret);
+ }
+diff --git a/include/linux/sysfb.h b/include/linux/sysfb.h
+index b0dcfa26d07b..708152e9037b 100644
+--- a/include/linux/sysfb.h
++++ b/include/linux/sysfb.h
+@@ -72,8 +72,8 @@ static inline void sysfb_apply_efi_quirks(struct platform_device *pd)
+
+ bool sysfb_parse_mode(const struct screen_info *si,
+ struct simplefb_platform_data *mode);
+-int sysfb_create_simplefb(const struct screen_info *si,
+- const struct simplefb_platform_data *mode);
++struct platform_device *sysfb_create_simplefb(const struct screen_info *si,
++ const struct simplefb_platform_data *mode);
+
+ #else /* CONFIG_SYSFB_SIMPLE */
+
+@@ -83,10 +83,10 @@ static inline bool sysfb_parse_mode(const struct screen_info *si,
+ return false;
+ }
+
+-static inline int sysfb_create_simplefb(const struct screen_info *si,
+- const struct simplefb_platform_data *mode)
++static inline struct platform_device *sysfb_create_simplefb(const struct screen_info *si,
++ const struct simplefb_platform_data *mode)
+ {
+- return -EINVAL;
++ return ERR_PTR(-EINVAL);
+ }
+
+ #endif /* CONFIG_SYSFB_SIMPLE */
+--
+2.35.1
+
--- /dev/null
+From bb479c18ec230301ef183c3505edeec524aeecd9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 15 Jun 2022 08:54:26 +0900
+Subject: irqchip: or1k-pic: Undefine mask_ack for level triggered hardware
+
+From: Stafford Horne <shorne@gmail.com>
+
+[ Upstream commit 8520501346ed8d1c4a6dfa751cb57328a9c843f1 ]
+
+The mask_ack operation clears the interrupt by writing to the PICSR
+register. This we don't want for level triggered interrupt because
+it does not actually clear the interrupt on the source hardware.
+
+This was causing issues in qemu with multi core setups where
+interrupts would continue to fire even though they had been cleared in
+PICSR.
+
+Just remove the mask_ack operation.
+
+Acked-by: Marc Zyngier <maz@kernel.org>
+Signed-off-by: Stafford Horne <shorne@gmail.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/irqchip/irq-or1k-pic.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+diff --git a/drivers/irqchip/irq-or1k-pic.c b/drivers/irqchip/irq-or1k-pic.c
+index 03d2366118dd..d5f1fabc45d7 100644
+--- a/drivers/irqchip/irq-or1k-pic.c
++++ b/drivers/irqchip/irq-or1k-pic.c
+@@ -66,7 +66,6 @@ static struct or1k_pic_dev or1k_pic_level = {
+ .name = "or1k-PIC-level",
+ .irq_unmask = or1k_pic_unmask,
+ .irq_mask = or1k_pic_mask,
+- .irq_mask_ack = or1k_pic_mask_ack,
+ },
+ .handle = handle_level_irq,
+ .flags = IRQ_LEVEL | IRQ_NOPROBE,
+--
+2.35.1
+
--- /dev/null
+From 3440377f258c61273dcff759fec038fe74b0215b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 2 Jun 2022 10:07:38 +0900
+Subject: ksmbd: use SOCK_NONBLOCK type for kernel_accept()
+
+From: Namjae Jeon <linkinjeon@kernel.org>
+
+[ Upstream commit fe0fde09e1cb83effcf8fafa372533f438d93a1a ]
+
+I found that normally it is O_NONBLOCK but there are different value
+for some arch.
+
+/include/linux/net.h:
+#ifndef SOCK_NONBLOCK
+#define SOCK_NONBLOCK O_NONBLOCK
+#endif
+
+/arch/alpha/include/asm/socket.h:
+#define SOCK_NONBLOCK 0x40000000
+
+Use SOCK_NONBLOCK instead of O_NONBLOCK for kernel_accept().
+
+Suggested-by: David Howells <dhowells@redhat.com>
+Signed-off-by: Namjae Jeon <linkinjeon@kerne.org>
+Reviewed-by: Hyunchul Lee <hyc.lee@gmail.com>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/ksmbd/transport_tcp.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/fs/ksmbd/transport_tcp.c b/fs/ksmbd/transport_tcp.c
+index 82a1429bbe12..755329c295ca 100644
+--- a/fs/ksmbd/transport_tcp.c
++++ b/fs/ksmbd/transport_tcp.c
+@@ -230,7 +230,7 @@ static int ksmbd_kthread_fn(void *p)
+ break;
+ }
+ ret = kernel_accept(iface->ksmbd_socket, &client_sk,
+- O_NONBLOCK);
++ SOCK_NONBLOCK);
+ mutex_unlock(&iface->sock_release_lock);
+ if (ret) {
+ if (ret == -EAGAIN)
+--
+2.35.1
+
--- /dev/null
+From 92b4f4cefc39e0003ce8d5dc0b850ead97a472f1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 29 Jun 2022 15:55:50 +0800
+Subject: net: sfp: fix memory leak in sfp_probe()
+
+From: Jianglei Nie <niejianglei2021@163.com>
+
+[ Upstream commit 0a18d802d65cf662644fd1d369c86d84a5630652 ]
+
+sfp_probe() allocates a memory chunk from sfp with sfp_alloc(). When
+devm_add_action() fails, sfp is not freed, which leads to a memory leak.
+
+We should use devm_add_action_or_reset() instead of devm_add_action().
+
+Signed-off-by: Jianglei Nie <niejianglei2021@163.com>
+Reviewed-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
+Link: https://lore.kernel.org/r/20220629075550.2152003-1-niejianglei2021@163.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/phy/sfp.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/net/phy/sfp.c b/drivers/net/phy/sfp.c
+index 90dfefc1f5f8..028a5df5c538 100644
+--- a/drivers/net/phy/sfp.c
++++ b/drivers/net/phy/sfp.c
+@@ -2504,7 +2504,7 @@ static int sfp_probe(struct platform_device *pdev)
+
+ platform_set_drvdata(pdev, sfp);
+
+- err = devm_add_action(sfp->dev, sfp_cleanup, sfp);
++ err = devm_add_action_or_reset(sfp->dev, sfp_cleanup, sfp);
+ if (err < 0)
+ return err;
+
+--
+2.35.1
+
--- /dev/null
+From cc1332e0d51d416dbee1bb7c49373e96d0d15c42 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 29 Jun 2022 14:34:18 +0800
+Subject: net: tipc: fix possible refcount leak in tipc_sk_create()
+
+From: Hangyu Hua <hbh25y@gmail.com>
+
+[ Upstream commit 00aff3590fc0a73bddd3b743863c14e76fd35c0c ]
+
+Free sk in case tipc_sk_insert() fails.
+
+Signed-off-by: Hangyu Hua <hbh25y@gmail.com>
+Reviewed-by: Tung Nguyen <tung.q.nguyen@dektech.com.au>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/tipc/socket.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/net/tipc/socket.c b/net/tipc/socket.c
+index 17f8c523e33b..43509c7e90fc 100644
+--- a/net/tipc/socket.c
++++ b/net/tipc/socket.c
+@@ -502,6 +502,7 @@ static int tipc_sk_create(struct net *net, struct socket *sock,
+ sock_init_data(sock, sk);
+ tipc_set_sk_state(sk, TIPC_OPEN);
+ if (tipc_sk_insert(tsk)) {
++ sk_free(sk);
+ pr_warn("Socket create failed; port number exhausted\n");
+ return -EINVAL;
+ }
+--
+2.35.1
+
--- /dev/null
+From d0a451ca4b4ec984db526266b45481c496fe797c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 21 Jun 2022 18:26:03 +0200
+Subject: netfilter: br_netfilter: do not skip all hooks with 0 priority
+
+From: Florian Westphal <fw@strlen.de>
+
+[ Upstream commit c2577862eeb0be94f151f2f1fff662b028061b00 ]
+
+When br_netfilter module is loaded, skbs may be diverted to the
+ipv4/ipv6 hooks, just like as if we were routing.
+
+Unfortunately, bridge filter hooks with priority 0 may be skipped
+in this case.
+
+Example:
+1. an nftables bridge ruleset is loaded, with a prerouting
+ hook that has priority 0.
+2. interface is added to the bridge.
+3. no tcp packet is ever seen by the bridge prerouting hook.
+4. flush the ruleset
+5. load the bridge ruleset again.
+6. tcp packets are processed as expected.
+
+After 1) the only registered hook is the bridge prerouting hook, but its
+not called yet because the bridge hasn't been brought up yet.
+
+After 2), hook order is:
+ 0 br_nf_pre_routing // br_netfilter internal hook
+ 0 chain bridge f prerouting // nftables bridge ruleset
+
+The packet is diverted to br_nf_pre_routing.
+If call-iptables is off, the nftables bridge ruleset is called as expected.
+
+But if its enabled, br_nf_hook_thresh() will skip it because it assumes
+that all 0-priority hooks had been called previously in bridge context.
+
+To avoid this, check for the br_nf_pre_routing hook itself, we need to
+resume directly after it, even if this hook has a priority of 0.
+
+Unfortunately, this still results in different packet flow.
+With this fix, the eval order after in 3) is:
+1. br_nf_pre_routing
+2. ip(6)tables (if enabled)
+3. nftables bridge
+
+but after 5 its the much saner:
+1. nftables bridge
+2. br_nf_pre_routing
+3. ip(6)tables (if enabled)
+
+Unfortunately I don't see a solution here:
+It would be possible to move br_nf_pre_routing to a higher priority
+so that it will be called later in the pipeline, but this also impacts
+ebtables evaluation order, and would still result in this very ordering
+problem for all nftables-bridge hooks with the same priority as the
+br_nf_pre_routing one.
+
+Searching back through the git history I don't think this has
+ever behaved in any other way, hence, no fixes-tag.
+
+Reported-by: Radim Hrazdil <rhrazdil@redhat.com>
+Signed-off-by: Florian Westphal <fw@strlen.de>
+Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bridge/br_netfilter_hooks.c | 21 ++++++++++++++++++---
+ 1 file changed, 18 insertions(+), 3 deletions(-)
+
+diff --git a/net/bridge/br_netfilter_hooks.c b/net/bridge/br_netfilter_hooks.c
+index 68c0d0f92890..10a2c7bca719 100644
+--- a/net/bridge/br_netfilter_hooks.c
++++ b/net/bridge/br_netfilter_hooks.c
+@@ -1012,9 +1012,24 @@ int br_nf_hook_thresh(unsigned int hook, struct net *net,
+ return okfn(net, sk, skb);
+
+ ops = nf_hook_entries_get_hook_ops(e);
+- for (i = 0; i < e->num_hook_entries &&
+- ops[i]->priority <= NF_BR_PRI_BRNF; i++)
+- ;
++ for (i = 0; i < e->num_hook_entries; i++) {
++ /* These hooks have already been called */
++ if (ops[i]->priority < NF_BR_PRI_BRNF)
++ continue;
++
++ /* These hooks have not been called yet, run them. */
++ if (ops[i]->priority > NF_BR_PRI_BRNF)
++ break;
++
++ /* take a closer look at NF_BR_PRI_BRNF. */
++ if (ops[i]->hook == br_nf_pre_routing) {
++ /* This hook diverted the skb to this function,
++ * hooks after this have not been run yet.
++ */
++ i++;
++ break;
++ }
++ }
+
+ nf_hook_state_init(&state, hook, NFPROTO_BRIDGE, indev, outdev,
+ sk, net, okfn);
+--
+2.35.1
+
--- /dev/null
+From 7fbe0be79fe4735cf9f07b9bbd3df5cc00343af3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 27 Jun 2022 19:06:43 +0200
+Subject: NFC: nxp-nci: don't print header length mismatch on i2c error
+
+From: Michael Walle <michael@walle.cc>
+
+[ Upstream commit 9577fc5fdc8b07b891709af6453545db405e24ad ]
+
+Don't print a misleading header length mismatch error if the i2c call
+returns an error. Instead just return the error code without any error
+message.
+
+Signed-off-by: Michael Walle <michael@walle.cc>
+Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/nfc/nxp-nci/i2c.c | 8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/nfc/nxp-nci/i2c.c b/drivers/nfc/nxp-nci/i2c.c
+index e8f3b35afbee..ae2ba08d8ac3 100644
+--- a/drivers/nfc/nxp-nci/i2c.c
++++ b/drivers/nfc/nxp-nci/i2c.c
+@@ -122,7 +122,9 @@ static int nxp_nci_i2c_fw_read(struct nxp_nci_i2c_phy *phy,
+ skb_put_data(*skb, &header, NXP_NCI_FW_HDR_LEN);
+
+ r = i2c_master_recv(client, skb_put(*skb, frame_len), frame_len);
+- if (r != frame_len) {
++ if (r < 0) {
++ goto fw_read_exit_free_skb;
++ } else if (r != frame_len) {
+ nfc_err(&client->dev,
+ "Invalid frame length: %u (expected %zu)\n",
+ r, frame_len);
+@@ -166,7 +168,9 @@ static int nxp_nci_i2c_nci_read(struct nxp_nci_i2c_phy *phy,
+ return 0;
+
+ r = i2c_master_recv(client, skb_put(*skb, header.plen), header.plen);
+- if (r != header.plen) {
++ if (r < 0) {
++ goto nci_read_exit_free_skb;
++ } else if (r != header.plen) {
+ nfc_err(&client->dev,
+ "Invalid frame payload length: %u (expected %u)\n",
+ r, header.plen);
+--
+2.35.1
+
--- /dev/null
+From 3ac80bf6c50429607abeebe584cbaf47f5b7a838 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 23 Jun 2022 14:45:39 +0800
+Subject: nvme: fix regression when disconnect a recovering ctrl
+
+From: Ruozhu Li <liruozhu@huawei.com>
+
+[ Upstream commit f7f70f4aa09dc43d7455c060143e86a017c30548 ]
+
+We encountered a problem that the disconnect command hangs.
+After analyzing the log and stack, we found that the triggering
+process is as follows:
+CPU0 CPU1
+ nvme_rdma_error_recovery_work
+ nvme_rdma_teardown_io_queues
+nvme_do_delete_ctrl nvme_stop_queues
+ nvme_remove_namespaces
+ --clear ctrl->namespaces
+ nvme_start_queues
+ --no ns in ctrl->namespaces
+ nvme_ns_remove return(because ctrl is deleting)
+ blk_freeze_queue
+ blk_mq_freeze_queue_wait
+ --wait for ns to unquiesce to clean infligt IO, hang forever
+
+This problem was not found in older kernels because we will flush
+err work in nvme_stop_ctrl before nvme_remove_namespaces.It does not
+seem to be modified for functional reasons, the patch can be revert
+to solve the problem.
+
+Revert commit 794a4cb3d2f7 ("nvme: remove the .stop_ctrl callout")
+
+Signed-off-by: Ruozhu Li <liruozhu@huawei.com>
+Reviewed-by: Sagi Grimberg <sagi@grimberg.me>
+Signed-off-by: Christoph Hellwig <hch@lst.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/nvme/host/core.c | 2 ++
+ drivers/nvme/host/nvme.h | 1 +
+ drivers/nvme/host/rdma.c | 12 +++++++++---
+ drivers/nvme/host/tcp.c | 10 +++++++---
+ 4 files changed, 19 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
+index 19054b791c67..29b56ea01132 100644
+--- a/drivers/nvme/host/core.c
++++ b/drivers/nvme/host/core.c
+@@ -4385,6 +4385,8 @@ void nvme_stop_ctrl(struct nvme_ctrl *ctrl)
+ nvme_stop_failfast_work(ctrl);
+ flush_work(&ctrl->async_event_work);
+ cancel_work_sync(&ctrl->fw_act_work);
++ if (ctrl->ops->stop_ctrl)
++ ctrl->ops->stop_ctrl(ctrl);
+ }
+ EXPORT_SYMBOL_GPL(nvme_stop_ctrl);
+
+diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h
+index 72bcd7e5716e..75a7e7baa1fc 100644
+--- a/drivers/nvme/host/nvme.h
++++ b/drivers/nvme/host/nvme.h
+@@ -495,6 +495,7 @@ struct nvme_ctrl_ops {
+ void (*free_ctrl)(struct nvme_ctrl *ctrl);
+ void (*submit_async_event)(struct nvme_ctrl *ctrl);
+ void (*delete_ctrl)(struct nvme_ctrl *ctrl);
++ void (*stop_ctrl)(struct nvme_ctrl *ctrl);
+ int (*get_address)(struct nvme_ctrl *ctrl, char *buf, int size);
+ };
+
+diff --git a/drivers/nvme/host/rdma.c b/drivers/nvme/host/rdma.c
+index d51f52e296f5..2db9c166a1b7 100644
+--- a/drivers/nvme/host/rdma.c
++++ b/drivers/nvme/host/rdma.c
+@@ -1049,6 +1049,14 @@ static void nvme_rdma_teardown_io_queues(struct nvme_rdma_ctrl *ctrl,
+ }
+ }
+
++static void nvme_rdma_stop_ctrl(struct nvme_ctrl *nctrl)
++{
++ struct nvme_rdma_ctrl *ctrl = to_rdma_ctrl(nctrl);
++
++ cancel_work_sync(&ctrl->err_work);
++ cancel_delayed_work_sync(&ctrl->reconnect_work);
++}
++
+ static void nvme_rdma_free_ctrl(struct nvme_ctrl *nctrl)
+ {
+ struct nvme_rdma_ctrl *ctrl = to_rdma_ctrl(nctrl);
+@@ -2230,9 +2238,6 @@ static const struct blk_mq_ops nvme_rdma_admin_mq_ops = {
+
+ static void nvme_rdma_shutdown_ctrl(struct nvme_rdma_ctrl *ctrl, bool shutdown)
+ {
+- cancel_work_sync(&ctrl->err_work);
+- cancel_delayed_work_sync(&ctrl->reconnect_work);
+-
+ nvme_rdma_teardown_io_queues(ctrl, shutdown);
+ blk_mq_quiesce_queue(ctrl->ctrl.admin_q);
+ if (shutdown)
+@@ -2282,6 +2287,7 @@ static const struct nvme_ctrl_ops nvme_rdma_ctrl_ops = {
+ .submit_async_event = nvme_rdma_submit_async_event,
+ .delete_ctrl = nvme_rdma_delete_ctrl,
+ .get_address = nvmf_get_address,
++ .stop_ctrl = nvme_rdma_stop_ctrl,
+ };
+
+ /*
+diff --git a/drivers/nvme/host/tcp.c b/drivers/nvme/host/tcp.c
+index 1821d38e620e..20138e132558 100644
+--- a/drivers/nvme/host/tcp.c
++++ b/drivers/nvme/host/tcp.c
+@@ -2163,9 +2163,6 @@ static void nvme_tcp_error_recovery_work(struct work_struct *work)
+
+ static void nvme_tcp_teardown_ctrl(struct nvme_ctrl *ctrl, bool shutdown)
+ {
+- cancel_work_sync(&to_tcp_ctrl(ctrl)->err_work);
+- cancel_delayed_work_sync(&to_tcp_ctrl(ctrl)->connect_work);
+-
+ nvme_tcp_teardown_io_queues(ctrl, shutdown);
+ blk_mq_quiesce_queue(ctrl->admin_q);
+ if (shutdown)
+@@ -2205,6 +2202,12 @@ static void nvme_reset_ctrl_work(struct work_struct *work)
+ nvme_tcp_reconnect_or_remove(ctrl);
+ }
+
++static void nvme_tcp_stop_ctrl(struct nvme_ctrl *ctrl)
++{
++ cancel_work_sync(&to_tcp_ctrl(ctrl)->err_work);
++ cancel_delayed_work_sync(&to_tcp_ctrl(ctrl)->connect_work);
++}
++
+ static void nvme_tcp_free_ctrl(struct nvme_ctrl *nctrl)
+ {
+ struct nvme_tcp_ctrl *ctrl = to_tcp_ctrl(nctrl);
+@@ -2528,6 +2531,7 @@ static const struct nvme_ctrl_ops nvme_tcp_ctrl_ops = {
+ .submit_async_event = nvme_tcp_submit_async_event,
+ .delete_ctrl = nvme_tcp_delete_ctrl,
+ .get_address = nvmf_get_address,
++ .stop_ctrl = nvme_tcp_stop_ctrl,
+ };
+
+ static bool
+--
+2.35.1
+
--- /dev/null
+From 9479a48a8342ba4da5b0311fb811b8967d2b8912 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 5 Jul 2022 10:21:02 -0700
+Subject: nvme-pci: phison e16 has bogus namespace ids
+
+From: Keith Busch <kbusch@kernel.org>
+
+[ Upstream commit 73029c9b23cf1213e5f54c2b59efce08665199e7 ]
+
+Add the quirk.
+
+Link: https://bugzilla.kernel.org/show_bug.cgi?id=216049
+Reported-by: Chris Egolf <cegolf@ugholf.net>
+Signed-off-by: Keith Busch <kbusch@kernel.org>
+Reviewed-by: Chaitanya Kulkarni <kch@nvidia.com>
+Signed-off-by: Christoph Hellwig <hch@lst.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/nvme/host/pci.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c
+index c3db9f12dac3..d820131d39b2 100644
+--- a/drivers/nvme/host/pci.c
++++ b/drivers/nvme/host/pci.c
+@@ -3337,7 +3337,8 @@ static const struct pci_device_id nvme_id_table[] = {
+ NVME_QUIRK_DISABLE_WRITE_ZEROES|
+ NVME_QUIRK_IGNORE_DEV_SUBNQN, },
+ { PCI_DEVICE(0x1987, 0x5016), /* Phison E16 */
+- .driver_data = NVME_QUIRK_IGNORE_DEV_SUBNQN, },
++ .driver_data = NVME_QUIRK_IGNORE_DEV_SUBNQN |
++ NVME_QUIRK_BOGUS_NID, },
+ { PCI_DEVICE(0x1b4b, 0x1092), /* Lexar 256 GB SSD */
+ .driver_data = NVME_QUIRK_NO_NS_DESC_LIST |
+ NVME_QUIRK_IGNORE_DEV_SUBNQN, },
+--
+2.35.1
+
--- /dev/null
+From e4b13b32648eb37995bf85899971aa237c368a79 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 26 Jun 2022 12:24:51 +0300
+Subject: nvme-tcp: always fail a request when sending it failed
+
+From: Sagi Grimberg <sagi@grimberg.me>
+
+[ Upstream commit 41d07df7de841bfbc32725ce21d933ad358f2844 ]
+
+queue stoppage and inflight requests cancellation is fully fenced from
+io_work and thus failing a request from this context. Hence we don't
+need to try to guess from the socket retcode if this failure is because
+the queue is about to be torn down or not.
+
+We are perfectly safe to just fail it, the request will not be cancelled
+later on.
+
+This solves possible very long shutdown delays when the users issues a
+'nvme disconnect-all'
+
+Reported-by: Daniel Wagner <dwagner@suse.de>
+Signed-off-by: Sagi Grimberg <sagi@grimberg.me>
+Signed-off-by: Christoph Hellwig <hch@lst.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/nvme/host/tcp.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+diff --git a/drivers/nvme/host/tcp.c b/drivers/nvme/host/tcp.c
+index 10882d3d554c..1821d38e620e 100644
+--- a/drivers/nvme/host/tcp.c
++++ b/drivers/nvme/host/tcp.c
+@@ -1162,8 +1162,7 @@ static int nvme_tcp_try_send(struct nvme_tcp_queue *queue)
+ } else if (ret < 0) {
+ dev_err(queue->ctrl->ctrl.device,
+ "failed to send request %d\n", ret);
+- if (ret != -EPIPE && ret != -ECONNRESET)
+- nvme_tcp_fail_request(queue->request);
++ nvme_tcp_fail_request(queue->request);
+ nvme_tcp_done_send_req(queue);
+ }
+ return ret;
+--
+2.35.1
+
--- /dev/null
+From 25bdb74c11e73c78cf69ab342755f5b5bf18b6ea Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 21 Apr 2022 10:26:59 +0800
+Subject: pinctrl: aspeed: Fix potential NULL dereference in
+ aspeed_pinmux_set_mux()
+
+From: Haowen Bai <baihaowen@meizu.com>
+
+[ Upstream commit 84a85d3fef2e75b1fe9fc2af6f5267122555a1ed ]
+
+pdesc could be null but still dereference pdesc->name and it will lead to
+a null pointer access. So we move a null check before dereference.
+
+Signed-off-by: Haowen Bai <baihaowen@meizu.com>
+Link: https://lore.kernel.org/r/1650508019-22554-1-git-send-email-baihaowen@meizu.com
+Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/pinctrl/aspeed/pinctrl-aspeed.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/pinctrl/aspeed/pinctrl-aspeed.c b/drivers/pinctrl/aspeed/pinctrl-aspeed.c
+index c94e24aadf92..83d47ff1cea8 100644
+--- a/drivers/pinctrl/aspeed/pinctrl-aspeed.c
++++ b/drivers/pinctrl/aspeed/pinctrl-aspeed.c
+@@ -236,11 +236,11 @@ int aspeed_pinmux_set_mux(struct pinctrl_dev *pctldev, unsigned int function,
+ const struct aspeed_sig_expr **funcs;
+ const struct aspeed_sig_expr ***prios;
+
+- pr_debug("Muxing pin %s for %s\n", pdesc->name, pfunc->name);
+-
+ if (!pdesc)
+ return -EINVAL;
+
++ pr_debug("Muxing pin %s for %s\n", pdesc->name, pfunc->name);
++
+ prios = pdesc->prios;
+
+ if (!prios)
+--
+2.35.1
+
--- /dev/null
+From a7050edeb08f3614e166b14f58cbafb29f005ff3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 28 Jun 2022 20:37:26 +0800
+Subject: platform/x86: hp-wmi: Ignore Sanitization Mode event
+
+From: Kai-Heng Feng <kai.heng.feng@canonical.com>
+
+[ Upstream commit 9ab762a84b8094540c18a170e5ddd6488632c456 ]
+
+After system resume the hp-wmi driver may complain:
+[ 702.620180] hp_wmi: Unknown event_id - 23 - 0x0
+
+According to HP it means 'Sanitization Mode' and it's harmless to just
+ignore the event.
+
+Cc: Jorge Lopez <jorge.lopez2@hp.com>
+Signed-off-by: Kai-Heng Feng <kai.heng.feng@canonical.com>
+Link: https://lore.kernel.org/r/20220628123726.250062-1-kai.heng.feng@canonical.com
+Reviewed-by: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/platform/x86/hp-wmi.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c
+index 027a1467d009..1cd168e32810 100644
+--- a/drivers/platform/x86/hp-wmi.c
++++ b/drivers/platform/x86/hp-wmi.c
+@@ -63,6 +63,7 @@ enum hp_wmi_event_ids {
+ HPWMI_BACKLIT_KB_BRIGHTNESS = 0x0D,
+ HPWMI_PEAKSHIFT_PERIOD = 0x0F,
+ HPWMI_BATTERY_CHARGE_PERIOD = 0x10,
++ HPWMI_SANITIZATION_MODE = 0x17,
+ };
+
+ struct bios_args {
+@@ -638,6 +639,8 @@ static void hp_wmi_notify(u32 value, void *context)
+ break;
+ case HPWMI_BATTERY_CHARGE_PERIOD:
+ break;
++ case HPWMI_SANITIZATION_MODE:
++ break;
+ default:
+ pr_info("Unknown event_id - %d - 0x%x\n", event_id, event_data);
+ break;
+--
+2.35.1
+
--- /dev/null
+From caa371f56002075dd67f999c3ede635e24d5742c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 23 Jun 2022 13:25:09 -0500
+Subject: powerpc/xive/spapr: correct bitmap allocation size
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Nathan Lynch <nathanl@linux.ibm.com>
+
+[ Upstream commit 19fc5bb93c6bbdce8292b4d7eed04e2fa118d2fe ]
+
+kasan detects access beyond the end of the xibm->bitmap allocation:
+
+BUG: KASAN: slab-out-of-bounds in _find_first_zero_bit+0x40/0x140
+Read of size 8 at addr c00000001d1d0118 by task swapper/0/1
+
+CPU: 0 PID: 1 Comm: swapper/0 Not tainted 5.19.0-rc2-00001-g90df023b36dd #28
+Call Trace:
+[c00000001d98f770] [c0000000012baab8] dump_stack_lvl+0xac/0x108 (unreliable)
+[c00000001d98f7b0] [c00000000068faac] print_report+0x37c/0x710
+[c00000001d98f880] [c0000000006902c0] kasan_report+0x110/0x354
+[c00000001d98f950] [c000000000692324] __asan_load8+0xa4/0xe0
+[c00000001d98f970] [c0000000011c6ed0] _find_first_zero_bit+0x40/0x140
+[c00000001d98f9b0] [c0000000000dbfbc] xive_spapr_get_ipi+0xcc/0x260
+[c00000001d98fa70] [c0000000000d6d28] xive_setup_cpu_ipi+0x1e8/0x450
+[c00000001d98fb30] [c000000004032a20] pSeries_smp_probe+0x5c/0x118
+[c00000001d98fb60] [c000000004018b44] smp_prepare_cpus+0x944/0x9ac
+[c00000001d98fc90] [c000000004009f9c] kernel_init_freeable+0x2d4/0x640
+[c00000001d98fd90] [c0000000000131e8] kernel_init+0x28/0x1d0
+[c00000001d98fe10] [c00000000000cd54] ret_from_kernel_thread+0x5c/0x64
+
+Allocated by task 0:
+ kasan_save_stack+0x34/0x70
+ __kasan_kmalloc+0xb4/0xf0
+ __kmalloc+0x268/0x540
+ xive_spapr_init+0x4d0/0x77c
+ pseries_init_irq+0x40/0x27c
+ init_IRQ+0x44/0x84
+ start_kernel+0x2a4/0x538
+ start_here_common+0x1c/0x20
+
+The buggy address belongs to the object at c00000001d1d0118
+ which belongs to the cache kmalloc-8 of size 8
+The buggy address is located 0 bytes inside of
+ 8-byte region [c00000001d1d0118, c00000001d1d0120)
+
+The buggy address belongs to the physical page:
+page:c00c000000074740 refcount:1 mapcount:0 mapping:0000000000000000 index:0xc00000001d1d0558 pfn:0x1d1d
+flags: 0x7ffff000000200(slab|node=0|zone=0|lastcpupid=0x7ffff)
+raw: 007ffff000000200 c00000001d0003c8 c00000001d0003c8 c00000001d010480
+raw: c00000001d1d0558 0000000001e1000a 00000001ffffffff 0000000000000000
+page dumped because: kasan: bad access detected
+
+Memory state around the buggy address:
+ c00000001d1d0000: fc 00 fc fc fc fc fc fc fc fc fc fc fc fc fc fc
+ c00000001d1d0080: fc fc 00 fc fc fc fc fc fc fc fc fc fc fc fc fc
+>c00000001d1d0100: fc fc fc 02 fc fc fc fc fc fc fc fc fc fc fc fc
+ ^
+ c00000001d1d0180: fc fc fc fc 04 fc fc fc fc fc fc fc fc fc fc fc
+ c00000001d1d0200: fc fc fc fc fc 04 fc fc fc fc fc fc fc fc fc fc
+
+This happens because the allocation uses the wrong unit (bits) when it
+should pass (BITS_TO_LONGS(count) * sizeof(long)) or equivalent. With small
+numbers of bits, the allocated object can be smaller than sizeof(long),
+which results in invalid accesses.
+
+Use bitmap_zalloc() to allocate and initialize the irq bitmap, paired with
+bitmap_free() for consistency.
+
+Signed-off-by: Nathan Lynch <nathanl@linux.ibm.com>
+Reviewed-by: Cédric Le Goater <clg@kaod.org>
+Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
+Link: https://lore.kernel.org/r/20220623182509.3985625-1-nathanl@linux.ibm.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/powerpc/sysdev/xive/spapr.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/arch/powerpc/sysdev/xive/spapr.c b/arch/powerpc/sysdev/xive/spapr.c
+index a82f32fbe772..583b2c6df390 100644
+--- a/arch/powerpc/sysdev/xive/spapr.c
++++ b/arch/powerpc/sysdev/xive/spapr.c
+@@ -13,6 +13,7 @@
+ #include <linux/of.h>
+ #include <linux/slab.h>
+ #include <linux/spinlock.h>
++#include <linux/bitmap.h>
+ #include <linux/cpumask.h>
+ #include <linux/mm.h>
+ #include <linux/delay.h>
+@@ -55,7 +56,7 @@ static int xive_irq_bitmap_add(int base, int count)
+ spin_lock_init(&xibm->lock);
+ xibm->base = base;
+ xibm->count = count;
+- xibm->bitmap = kzalloc(xibm->count, GFP_KERNEL);
++ xibm->bitmap = bitmap_zalloc(xibm->count, GFP_KERNEL);
+ if (!xibm->bitmap) {
+ kfree(xibm);
+ return -ENOMEM;
+@@ -73,7 +74,7 @@ static void xive_irq_bitmap_remove_all(void)
+
+ list_for_each_entry_safe(xibm, tmp, &xive_irq_bitmaps, list) {
+ list_del(&xibm->list);
+- kfree(xibm->bitmap);
++ bitmap_free(xibm->bitmap);
+ kfree(xibm);
+ }
+ }
+--
+2.35.1
+
--- /dev/null
+From 2db154b1f9f5e94fcfceb41092012550600b4f31 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 9 Jun 2022 13:54:32 +0530
+Subject: Revert "can: xilinx_can: Limit CANFD brp to 2"
+
+From: Srinivas Neeli <srinivas.neeli@xilinx.com>
+
+[ Upstream commit c6da4590fe819dfe28a4f8037a8dc1e056542fb4 ]
+
+This reverts commit 05ca14fdb6fe65614e0652d03e44b02748d25af7.
+
+On early silicon engineering samples observed bit shrinking issue when
+we use brp as 1. Hence updated brp_min as 2. As in production silicon
+this issue is fixed, so reverting the patch.
+
+Link: https://lore.kernel.org/all/20220609082433.1191060-2-srinivas.neeli@xilinx.com
+Signed-off-by: Srinivas Neeli <srinivas.neeli@xilinx.com>
+Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/can/xilinx_can.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/can/xilinx_can.c b/drivers/net/can/xilinx_can.c
+index 262b783d1df8..a2e751f0ae0b 100644
+--- a/drivers/net/can/xilinx_can.c
++++ b/drivers/net/can/xilinx_can.c
+@@ -259,7 +259,7 @@ static const struct can_bittiming_const xcan_bittiming_const_canfd2 = {
+ .tseg2_min = 1,
+ .tseg2_max = 128,
+ .sjw_max = 128,
+- .brp_min = 2,
++ .brp_min = 1,
+ .brp_max = 256,
+ .brp_inc = 1,
+ };
+@@ -272,7 +272,7 @@ static const struct can_bittiming_const xcan_data_bittiming_const_canfd2 = {
+ .tseg2_min = 1,
+ .tseg2_max = 16,
+ .sjw_max = 16,
+- .brp_min = 2,
++ .brp_min = 1,
+ .brp_max = 256,
+ .brp_inc = 1,
+ };
+--
+2.35.1
+
--- /dev/null
+From 9f6c0d7d93a5ddd568606ceb02d94ef7b7b107ef Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 23 Jun 2022 20:41:59 +0800
+Subject: scsi: hisi_sas: Limit max hw sectors for v3 HW
+
+From: John Garry <john.garry@huawei.com>
+
+[ Upstream commit fce54ed027577517df1e74b7d54dc2b1bd536887 ]
+
+If the controller is behind an IOMMU then the IOMMU IOVA caching range can
+affect performance, as discussed in [0].
+
+Limit the max HW sectors to not exceed this limit. We need to hardcode the
+value until a proper DMA mapping API is available.
+
+[0] https://lore.kernel.org/linux-iommu/20210129092120.1482-1-thunder.leizhen@huawei.com/
+
+Link: https://lore.kernel.org/r/1655988119-223714-1-git-send-email-john.garry@huawei.com
+Signed-off-by: John Garry <john.garry@huawei.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
+index 1f5e0688c0c8..15c7451fb30f 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
+@@ -2758,6 +2758,7 @@ static int slave_configure_v3_hw(struct scsi_device *sdev)
+ struct hisi_hba *hisi_hba = shost_priv(shost);
+ struct device *dev = hisi_hba->dev;
+ int ret = sas_slave_configure(sdev);
++ unsigned int max_sectors;
+
+ if (ret)
+ return ret;
+@@ -2775,6 +2776,12 @@ static int slave_configure_v3_hw(struct scsi_device *sdev)
+ }
+ }
+
++ /* Set according to IOMMU IOVA caching limit */
++ max_sectors = min_t(size_t, queue_max_hw_sectors(sdev->request_queue),
++ (PAGE_SIZE * 32) >> SECTOR_SHIFT);
++
++ blk_queue_max_hw_sectors(sdev->request_queue, max_sectors);
++
+ return 0;
+ }
+
+--
+2.35.1
+
net-tls-check-for-errors-in-tls_device_init.patch
acpi-video-fix-acpi_video_handles_brightness_key_pre.patch
mm-sysctl-fix-missing-numa_stat-when-config_hugetlb_.patch
+btrfs-rename-btrfs_bio-to-btrfs_io_context.patch
+btrfs-zoned-fix-a-leaked-bioc-in-read_zone_info.patch
+ksmbd-use-sock_nonblock-type-for-kernel_accept.patch
+powerpc-xive-spapr-correct-bitmap-allocation-size.patch
+vdpa-mlx5-initialize-cvq-vringh-only-once.patch
+vduse-tie-vduse-mgmtdev-and-its-device.patch
+virtio_mmio-add-missing-pm-calls-to-freeze-restore.patch
+virtio_mmio-restore-guest-page-size-on-resume.patch
+netfilter-br_netfilter-do-not-skip-all-hooks-with-0-.patch
+scsi-hisi_sas-limit-max-hw-sectors-for-v3-hw.patch
+cpufreq-pmac32-cpufreq-fix-refcount-leak-bug.patch
+platform-x86-hp-wmi-ignore-sanitization-mode-event.patch
+firmware-sysfb-make-sysfb_create_simplefb-return-a-p.patch
+firmware-sysfb-add-sysfb_disable-helper-function.patch
+fbdev-disable-sysfb-device-registration-when-removin.patch
+net-tipc-fix-possible-refcount-leak-in-tipc_sk_creat.patch
+nfc-nxp-nci-don-t-print-header-length-mismatch-on-i2.patch
+nvme-tcp-always-fail-a-request-when-sending-it-faile.patch
+nvme-fix-regression-when-disconnect-a-recovering-ctr.patch
+net-sfp-fix-memory-leak-in-sfp_probe.patch
+asoc-ops-fix-off-by-one-in-range-control-validation.patch
+pinctrl-aspeed-fix-potential-null-dereference-in-asp.patch
+asoc-realtek-maxim-soundwire-codecs-disable-pm_runti.patch
+asoc-rt711-sdca-sdw-fix-calibrate-mutex-initializati.patch
+asoc-intel-sof_sdw-handle-errors-on-card-registratio.patch
+asoc-rt711-fix-calibrate-mutex-initialization.patch
+asoc-rt7-sdw-harden-jack_detect_handler.patch
+asoc-codecs-rt700-rt711-rt711-sdca-initialize-workqu.patch
+asoc-sof-intel-hda-loader-clarify-the-cl_dsp_init-fl.patch
+asoc-wcd938x-fix-event-generation-for-some-controls.patch
+asoc-intel-bytcr_wm5102-fix-gpio-related-probe-order.patch
+asoc-rockchip-i2s-switch-bclk-to-gpio.patch
+asoc-wm5110-fix-dre-control.patch
+asoc-rt711-sdca-fix-kernel-null-pointer-dereference-.patch
+asoc-dapm-initialise-kcontrol-data-for-mux-demux-con.patch
+asoc-cs47l15-fix-event-generation-for-low-power-mux-.patch
+asoc-madera-fix-event-generation-for-out1-demux.patch
+asoc-madera-fix-event-generation-for-rate-controls.patch
+irqchip-or1k-pic-undefine-mask_ack-for-level-trigger.patch
+x86-clear-.brk-area-at-early-boot.patch
+soc-ixp4xx-npe-fix-unused-match-warning.patch
+arm-dts-stm32-use-the-correct-clock-source-for-cec-o.patch
+revert-can-xilinx_can-limit-canfd-brp-to-2.patch
+alsa-usb-audio-add-quirks-for-macrosilicon-ms2100-ms.patch
+alsa-usb-audio-add-quirk-for-fiero-sc-01.patch
+alsa-usb-audio-add-quirk-for-fiero-sc-01-fw-v1.0.0.patch
+nvme-pci-phison-e16-has-bogus-namespace-ids.patch
+signal-handling-don-t-use-bug_on-for-debugging.patch
--- /dev/null
+From 220df8c3af3bfb79c2cb4e9f1d981354df08f3f3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 6 Jul 2022 12:20:59 -0700
+Subject: signal handling: don't use BUG_ON() for debugging
+
+From: Linus Torvalds <torvalds@linux-foundation.org>
+
+[ Upstream commit a382f8fee42ca10c9bfce0d2352d4153f931f5dc ]
+
+These are indeed "should not happen" situations, but it turns out recent
+changes made the 'task_is_stopped_or_trace()' case trigger (fix for that
+exists, is pending more testing), and the BUG_ON() makes it
+unnecessarily hard to actually debug for no good reason.
+
+It's been that way for a long time, but let's make it clear: BUG_ON() is
+not good for debugging, and should never be used in situations where you
+could just say "this shouldn't happen, but we can continue".
+
+Use WARN_ON_ONCE() instead to make sure it gets logged, and then just
+continue running. Instead of making the system basically unusuable
+because you crashed the machine while potentially holding some very core
+locks (eg this function is commonly called while holding 'tasklist_lock'
+for writing).
+
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/signal.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/kernel/signal.c b/kernel/signal.c
+index d831f0aec56e..c7dbb19219b9 100644
+--- a/kernel/signal.c
++++ b/kernel/signal.c
+@@ -2027,12 +2027,12 @@ bool do_notify_parent(struct task_struct *tsk, int sig)
+ bool autoreap = false;
+ u64 utime, stime;
+
+- BUG_ON(sig == -1);
++ WARN_ON_ONCE(sig == -1);
+
+- /* do_notify_parent_cldstop should have been called instead. */
+- BUG_ON(task_is_stopped_or_traced(tsk));
++ /* do_notify_parent_cldstop should have been called instead. */
++ WARN_ON_ONCE(task_is_stopped_or_traced(tsk));
+
+- BUG_ON(!tsk->ptrace &&
++ WARN_ON_ONCE(!tsk->ptrace &&
+ (tsk->group_leader != tsk || !thread_group_empty(tsk)));
+
+ /* Wake up all pidfd waiters */
+--
+2.35.1
+
--- /dev/null
+From e4c36672f2c3b550355c81390a24f12d95887624 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 26 Jun 2022 09:43:15 +0200
+Subject: soc: ixp4xx/npe: Fix unused match warning
+
+From: Linus Walleij <linus.walleij@linaro.org>
+
+[ Upstream commit 620f83b8326ce9706b1118334f0257ae028ce045 ]
+
+The kernel test robot found this inconsistency:
+
+ drivers/soc/ixp4xx/ixp4xx-npe.c:737:34: warning:
+ 'ixp4xx_npe_of_match' defined but not used [-Wunused-const-variable=]
+ 737 | static const struct of_device_id ixp4xx_npe_of_match[] = {
+
+This is because the match is enclosed in the of_match_ptr()
+which compiles into NULL when OF is disabled and this
+is unnecessary.
+
+Fix it by dropping of_match_ptr() around the match.
+
+Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
+Link: https://lore.kernel.org/r/20220626074315.61209-1-linus.walleij@linaro.org'
+Signed-off-by: Arnd Bergmann <arnd@arndb.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/soc/ixp4xx/ixp4xx-npe.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/soc/ixp4xx/ixp4xx-npe.c b/drivers/soc/ixp4xx/ixp4xx-npe.c
+index f490c4ca51f5..a0159805d061 100644
+--- a/drivers/soc/ixp4xx/ixp4xx-npe.c
++++ b/drivers/soc/ixp4xx/ixp4xx-npe.c
+@@ -743,7 +743,7 @@ static const struct of_device_id ixp4xx_npe_of_match[] = {
+ static struct platform_driver ixp4xx_npe_driver = {
+ .driver = {
+ .name = "ixp4xx-npe",
+- .of_match_table = of_match_ptr(ixp4xx_npe_of_match),
++ .of_match_table = ixp4xx_npe_of_match,
+ },
+ .probe = ixp4xx_npe_probe,
+ .remove = ixp4xx_npe_remove,
+--
+2.35.1
+
--- /dev/null
+From ed2ff6afd8dadd6a2eaabc14e55a2e51e2b10904 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 13 Jun 2022 10:59:58 +0300
+Subject: vdpa/mlx5: Initialize CVQ vringh only once
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Eli Cohen <elic@nvidia.com>
+
+[ Upstream commit ace9252446ec615cd79a5f77d90edb25c0b9d024 ]
+
+Currently, CVQ vringh is initialized inside setup_virtqueues() which is
+called every time a memory update is done. This is undesirable since it
+resets all the context of the vring, including the available and used
+indices.
+
+Move the initialization to mlx5_vdpa_set_status() when
+VIRTIO_CONFIG_S_DRIVER_OK is set.
+
+Signed-off-by: Eli Cohen <elic@nvidia.com>
+Message-Id: <20220613075958.511064-2-elic@nvidia.com>
+Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
+Acked-by: Jason Wang <jasowang@redhat.com>
+Acked-by: Eugenio Pérez <eperezma@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/vdpa/mlx5/net/mlx5_vnet.c | 31 ++++++++++++++++++++-----------
+ 1 file changed, 20 insertions(+), 11 deletions(-)
+
+diff --git a/drivers/vdpa/mlx5/net/mlx5_vnet.c b/drivers/vdpa/mlx5/net/mlx5_vnet.c
+index 467a349dc26c..e748c00789f0 100644
+--- a/drivers/vdpa/mlx5/net/mlx5_vnet.c
++++ b/drivers/vdpa/mlx5/net/mlx5_vnet.c
+@@ -1898,7 +1898,6 @@ static int verify_driver_features(struct mlx5_vdpa_dev *mvdev, u64 features)
+ static int setup_virtqueues(struct mlx5_vdpa_dev *mvdev)
+ {
+ struct mlx5_vdpa_net *ndev = to_mlx5_vdpa_ndev(mvdev);
+- struct mlx5_control_vq *cvq = &mvdev->cvq;
+ int err;
+ int i;
+
+@@ -1908,16 +1907,6 @@ static int setup_virtqueues(struct mlx5_vdpa_dev *mvdev)
+ goto err_vq;
+ }
+
+- if (mvdev->actual_features & BIT_ULL(VIRTIO_NET_F_CTRL_VQ)) {
+- err = vringh_init_iotlb(&cvq->vring, mvdev->actual_features,
+- MLX5_CVQ_MAX_ENT, false,
+- (struct vring_desc *)(uintptr_t)cvq->desc_addr,
+- (struct vring_avail *)(uintptr_t)cvq->driver_addr,
+- (struct vring_used *)(uintptr_t)cvq->device_addr);
+- if (err)
+- goto err_vq;
+- }
+-
+ return 0;
+
+ err_vq:
+@@ -2184,6 +2173,21 @@ static void clear_vqs_ready(struct mlx5_vdpa_net *ndev)
+ ndev->mvdev.cvq.ready = false;
+ }
+
++static int setup_cvq_vring(struct mlx5_vdpa_dev *mvdev)
++{
++ struct mlx5_control_vq *cvq = &mvdev->cvq;
++ int err = 0;
++
++ if (mvdev->actual_features & BIT_ULL(VIRTIO_NET_F_CTRL_VQ))
++ err = vringh_init_iotlb(&cvq->vring, mvdev->actual_features,
++ MLX5_CVQ_MAX_ENT, false,
++ (struct vring_desc *)(uintptr_t)cvq->desc_addr,
++ (struct vring_avail *)(uintptr_t)cvq->driver_addr,
++ (struct vring_used *)(uintptr_t)cvq->device_addr);
++
++ return err;
++}
++
+ static void mlx5_vdpa_set_status(struct vdpa_device *vdev, u8 status)
+ {
+ struct mlx5_vdpa_dev *mvdev = to_mvdev(vdev);
+@@ -2194,6 +2198,11 @@ static void mlx5_vdpa_set_status(struct vdpa_device *vdev, u8 status)
+
+ if ((status ^ ndev->mvdev.status) & VIRTIO_CONFIG_S_DRIVER_OK) {
+ if (status & VIRTIO_CONFIG_S_DRIVER_OK) {
++ err = setup_cvq_vring(mvdev);
++ if (err) {
++ mlx5_vdpa_warn(mvdev, "failed to setup control VQ vring\n");
++ goto err_setup;
++ }
+ err = setup_driver(mvdev);
+ if (err) {
+ mlx5_vdpa_warn(mvdev, "failed to setup driver\n");
+--
+2.35.1
+
--- /dev/null
+From 9f7b96b82981ff1f5118ad1679ca2d29b36c4448 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 13 Jun 2022 22:52:23 +0300
+Subject: vduse: Tie vduse mgmtdev and its device
+
+From: Parav Pandit <parav@nvidia.com>
+
+[ Upstream commit 0e0348ac3f0a6e6606f1aa5acb1803ada913aa3d ]
+
+vduse devices are not backed by any real devices such as PCI. Hence it
+doesn't have any parent device linked to it.
+
+Kernel driver model in [1] suggests to avoid an empty device
+release callback.
+
+Hence tie the mgmtdevice object's life cycle to an allocate dummy struct
+device instead of static one.
+
+[1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/core-api/kobject.rst?h=v5.18-rc7#n284
+
+Signed-off-by: Parav Pandit <parav@nvidia.com>
+Message-Id: <20220613195223.473966-1-parav@nvidia.com>
+Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
+Reviewed-by: Xie Yongji <xieyongji@bytedance.com>
+Acked-by: Jason Wang <jasowang@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/vdpa/vdpa_user/vduse_dev.c | 60 ++++++++++++++++++------------
+ 1 file changed, 37 insertions(+), 23 deletions(-)
+
+diff --git a/drivers/vdpa/vdpa_user/vduse_dev.c b/drivers/vdpa/vdpa_user/vduse_dev.c
+index 9270398caf15..73e67fa88972 100644
+--- a/drivers/vdpa/vdpa_user/vduse_dev.c
++++ b/drivers/vdpa/vdpa_user/vduse_dev.c
+@@ -1466,16 +1466,12 @@ static char *vduse_devnode(struct device *dev, umode_t *mode)
+ return kasprintf(GFP_KERNEL, "vduse/%s", dev_name(dev));
+ }
+
+-static void vduse_mgmtdev_release(struct device *dev)
+-{
+-}
+-
+-static struct device vduse_mgmtdev = {
+- .init_name = "vduse",
+- .release = vduse_mgmtdev_release,
++struct vduse_mgmt_dev {
++ struct vdpa_mgmt_dev mgmt_dev;
++ struct device dev;
+ };
+
+-static struct vdpa_mgmt_dev mgmt_dev;
++static struct vduse_mgmt_dev *vduse_mgmt;
+
+ static int vduse_dev_init_vdpa(struct vduse_dev *dev, const char *name)
+ {
+@@ -1500,7 +1496,7 @@ static int vduse_dev_init_vdpa(struct vduse_dev *dev, const char *name)
+ }
+ set_dma_ops(&vdev->vdpa.dev, &vduse_dev_dma_ops);
+ vdev->vdpa.dma_dev = &vdev->vdpa.dev;
+- vdev->vdpa.mdev = &mgmt_dev;
++ vdev->vdpa.mdev = &vduse_mgmt->mgmt_dev;
+
+ return 0;
+ }
+@@ -1545,34 +1541,52 @@ static struct virtio_device_id id_table[] = {
+ { 0 },
+ };
+
+-static struct vdpa_mgmt_dev mgmt_dev = {
+- .device = &vduse_mgmtdev,
+- .id_table = id_table,
+- .ops = &vdpa_dev_mgmtdev_ops,
+-};
++static void vduse_mgmtdev_release(struct device *dev)
++{
++ struct vduse_mgmt_dev *mgmt_dev;
++
++ mgmt_dev = container_of(dev, struct vduse_mgmt_dev, dev);
++ kfree(mgmt_dev);
++}
+
+ static int vduse_mgmtdev_init(void)
+ {
+ int ret;
+
+- ret = device_register(&vduse_mgmtdev);
+- if (ret)
++ vduse_mgmt = kzalloc(sizeof(*vduse_mgmt), GFP_KERNEL);
++ if (!vduse_mgmt)
++ return -ENOMEM;
++
++ ret = dev_set_name(&vduse_mgmt->dev, "vduse");
++ if (ret) {
++ kfree(vduse_mgmt);
+ return ret;
++ }
+
+- ret = vdpa_mgmtdev_register(&mgmt_dev);
++ vduse_mgmt->dev.release = vduse_mgmtdev_release;
++
++ ret = device_register(&vduse_mgmt->dev);
+ if (ret)
+- goto err;
++ goto dev_reg_err;
+
+- return 0;
+-err:
+- device_unregister(&vduse_mgmtdev);
++ vduse_mgmt->mgmt_dev.id_table = id_table;
++ vduse_mgmt->mgmt_dev.ops = &vdpa_dev_mgmtdev_ops;
++ vduse_mgmt->mgmt_dev.device = &vduse_mgmt->dev;
++ ret = vdpa_mgmtdev_register(&vduse_mgmt->mgmt_dev);
++ if (ret)
++ device_unregister(&vduse_mgmt->dev);
++
++ return ret;
++
++dev_reg_err:
++ put_device(&vduse_mgmt->dev);
+ return ret;
+ }
+
+ static void vduse_mgmtdev_exit(void)
+ {
+- vdpa_mgmtdev_unregister(&mgmt_dev);
+- device_unregister(&vduse_mgmtdev);
++ vdpa_mgmtdev_unregister(&vduse_mgmt->mgmt_dev);
++ device_unregister(&vduse_mgmt->dev);
+ }
+
+ static int vduse_init(void)
+--
+2.35.1
+
--- /dev/null
+From d55d5cde1a8d431ac7025f37abed9fa3fd7e3a51 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 21 Jun 2022 13:06:20 +0200
+Subject: virtio_mmio: Add missing PM calls to freeze/restore
+
+From: Stephan Gerhold <stephan.gerhold@kernkonzept.com>
+
+[ Upstream commit ed7ac37fde33ccd84e4bd2b9363c191f925364c7 ]
+
+Most virtio drivers provide freeze/restore callbacks to finish up
+device usage before suspend and to reinitialize the virtio device after
+resume. However, these callbacks are currently only called when using
+virtio_pci. virtio_mmio does not have any PM ops defined.
+
+This causes problems for example after suspend to disk (hibernation),
+since the virtio devices might lose their state after the VMM is
+restarted. Calling virtio_device_freeze()/restore() ensures that
+the virtio devices are re-initialized correctly.
+
+Fix this by implementing the dev_pm_ops for virtio_mmio,
+similar to virtio_pci_common.
+
+Signed-off-by: Stephan Gerhold <stephan.gerhold@kernkonzept.com>
+Message-Id: <20220621110621.3638025-2-stephan.gerhold@kernkonzept.com>
+Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/virtio/virtio_mmio.c | 23 +++++++++++++++++++++++
+ 1 file changed, 23 insertions(+)
+
+diff --git a/drivers/virtio/virtio_mmio.c b/drivers/virtio/virtio_mmio.c
+index 1dd396d4bebb..7522832529dd 100644
+--- a/drivers/virtio/virtio_mmio.c
++++ b/drivers/virtio/virtio_mmio.c
+@@ -62,6 +62,7 @@
+ #include <linux/list.h>
+ #include <linux/module.h>
+ #include <linux/platform_device.h>
++#include <linux/pm.h>
+ #include <linux/slab.h>
+ #include <linux/spinlock.h>
+ #include <linux/virtio.h>
+@@ -543,6 +544,25 @@ static const struct virtio_config_ops virtio_mmio_config_ops = {
+ .get_shm_region = vm_get_shm_region,
+ };
+
++#ifdef CONFIG_PM_SLEEP
++static int virtio_mmio_freeze(struct device *dev)
++{
++ struct virtio_mmio_device *vm_dev = dev_get_drvdata(dev);
++
++ return virtio_device_freeze(&vm_dev->vdev);
++}
++
++static int virtio_mmio_restore(struct device *dev)
++{
++ struct virtio_mmio_device *vm_dev = dev_get_drvdata(dev);
++
++ return virtio_device_restore(&vm_dev->vdev);
++}
++
++static const struct dev_pm_ops virtio_mmio_pm_ops = {
++ SET_SYSTEM_SLEEP_PM_OPS(virtio_mmio_freeze, virtio_mmio_restore)
++};
++#endif
+
+ static void virtio_mmio_release_dev(struct device *_d)
+ {
+@@ -786,6 +806,9 @@ static struct platform_driver virtio_mmio_driver = {
+ .name = "virtio-mmio",
+ .of_match_table = virtio_mmio_match,
+ .acpi_match_table = ACPI_PTR(virtio_mmio_acpi_match),
++#ifdef CONFIG_PM_SLEEP
++ .pm = &virtio_mmio_pm_ops,
++#endif
+ },
+ };
+
+--
+2.35.1
+
--- /dev/null
+From f40298bbc7d8f82c9fabc092b4348fc6c339ac4e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 21 Jun 2022 13:06:21 +0200
+Subject: virtio_mmio: Restore guest page size on resume
+
+From: Stephan Gerhold <stephan.gerhold@kernkonzept.com>
+
+[ Upstream commit e0c2ce8217955537dd5434baeba061f209797119 ]
+
+Virtio devices might lose their state when the VMM is restarted
+after a suspend to disk (hibernation) cycle. This means that the
+guest page size register must be restored for the virtio_mmio legacy
+interface, since otherwise the virtio queues are not functional.
+
+This is particularly problematic for QEMU that currently still defaults
+to using the legacy interface for virtio_mmio. Write the guest page
+size register again in virtio_mmio_restore() to make legacy virtio_mmio
+devices work correctly after hibernation.
+
+Signed-off-by: Stephan Gerhold <stephan.gerhold@kernkonzept.com>
+Message-Id: <20220621110621.3638025-3-stephan.gerhold@kernkonzept.com>
+Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/virtio/virtio_mmio.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/drivers/virtio/virtio_mmio.c b/drivers/virtio/virtio_mmio.c
+index 7522832529dd..fe696aafaed8 100644
+--- a/drivers/virtio/virtio_mmio.c
++++ b/drivers/virtio/virtio_mmio.c
+@@ -556,6 +556,9 @@ static int virtio_mmio_restore(struct device *dev)
+ {
+ struct virtio_mmio_device *vm_dev = dev_get_drvdata(dev);
+
++ if (vm_dev->version == 1)
++ writel(PAGE_SIZE, vm_dev->base + VIRTIO_MMIO_GUEST_PAGE_SIZE);
++
+ return virtio_device_restore(&vm_dev->vdev);
+ }
+
+--
+2.35.1
+
--- /dev/null
+From 70b2534eb4141b760ced46b21940a23e7dae3e3f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 30 Jun 2022 09:14:40 +0200
+Subject: x86: Clear .brk area at early boot
+
+From: Juergen Gross <jgross@suse.com>
+
+[ Upstream commit 38fa5479b41376dc9d7f57e71c83514285a25ca0 ]
+
+The .brk section has the same properties as .bss: it is an alloc-only
+section and should be cleared before being used.
+
+Not doing so is especially a problem for Xen PV guests, as the
+hypervisor will validate page tables (check for writable page tables
+and hypervisor private bits) before accepting them to be used.
+
+Make sure .brk is initially zero by letting clear_bss() clear the brk
+area, too.
+
+Signed-off-by: Juergen Gross <jgross@suse.com>
+Signed-off-by: Borislav Petkov <bp@suse.de>
+Link: https://lore.kernel.org/r/20220630071441.28576-3-jgross@suse.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/kernel/head64.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c
+index de01903c3735..5036104d5470 100644
+--- a/arch/x86/kernel/head64.c
++++ b/arch/x86/kernel/head64.c
+@@ -418,6 +418,8 @@ static void __init clear_bss(void)
+ {
+ memset(__bss_start, 0,
+ (unsigned long) __bss_stop - (unsigned long) __bss_start);
++ memset(__brk_base, 0,
++ (unsigned long) __brk_limit - (unsigned long) __brk_base);
+ }
+
+ static unsigned long get_cmd_line_ptr(void)
+--
+2.35.1
+