]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
Fixes for 5.15
authorSasha Levin <sashal@kernel.org>
Mon, 18 Jul 2022 01:29:45 +0000 (21:29 -0400)
committerSasha Levin <sashal@kernel.org>
Mon, 18 Jul 2022 01:29:45 +0000 (21:29 -0400)
Signed-off-by: Sasha Levin <sashal@kernel.org>
49 files changed:
queue-5.15/alsa-usb-audio-add-quirk-for-fiero-sc-01-fw-v1.0.0.patch [new file with mode: 0644]
queue-5.15/alsa-usb-audio-add-quirk-for-fiero-sc-01.patch [new file with mode: 0644]
queue-5.15/alsa-usb-audio-add-quirks-for-macrosilicon-ms2100-ms.patch [new file with mode: 0644]
queue-5.15/arm-dts-stm32-use-the-correct-clock-source-for-cec-o.patch [new file with mode: 0644]
queue-5.15/asoc-codecs-rt700-rt711-rt711-sdca-initialize-workqu.patch [new file with mode: 0644]
queue-5.15/asoc-cs47l15-fix-event-generation-for-low-power-mux-.patch [new file with mode: 0644]
queue-5.15/asoc-dapm-initialise-kcontrol-data-for-mux-demux-con.patch [new file with mode: 0644]
queue-5.15/asoc-intel-bytcr_wm5102-fix-gpio-related-probe-order.patch [new file with mode: 0644]
queue-5.15/asoc-intel-sof_sdw-handle-errors-on-card-registratio.patch [new file with mode: 0644]
queue-5.15/asoc-madera-fix-event-generation-for-out1-demux.patch [new file with mode: 0644]
queue-5.15/asoc-madera-fix-event-generation-for-rate-controls.patch [new file with mode: 0644]
queue-5.15/asoc-ops-fix-off-by-one-in-range-control-validation.patch [new file with mode: 0644]
queue-5.15/asoc-realtek-maxim-soundwire-codecs-disable-pm_runti.patch [new file with mode: 0644]
queue-5.15/asoc-rockchip-i2s-switch-bclk-to-gpio.patch [new file with mode: 0644]
queue-5.15/asoc-rt7-sdw-harden-jack_detect_handler.patch [new file with mode: 0644]
queue-5.15/asoc-rt711-fix-calibrate-mutex-initialization.patch [new file with mode: 0644]
queue-5.15/asoc-rt711-sdca-fix-kernel-null-pointer-dereference-.patch [new file with mode: 0644]
queue-5.15/asoc-rt711-sdca-sdw-fix-calibrate-mutex-initializati.patch [new file with mode: 0644]
queue-5.15/asoc-sof-intel-hda-loader-clarify-the-cl_dsp_init-fl.patch [new file with mode: 0644]
queue-5.15/asoc-wcd938x-fix-event-generation-for-some-controls.patch [new file with mode: 0644]
queue-5.15/asoc-wm5110-fix-dre-control.patch [new file with mode: 0644]
queue-5.15/btrfs-rename-btrfs_bio-to-btrfs_io_context.patch [new file with mode: 0644]
queue-5.15/btrfs-zoned-fix-a-leaked-bioc-in-read_zone_info.patch [new file with mode: 0644]
queue-5.15/cpufreq-pmac32-cpufreq-fix-refcount-leak-bug.patch [new file with mode: 0644]
queue-5.15/fbdev-disable-sysfb-device-registration-when-removin.patch [new file with mode: 0644]
queue-5.15/firmware-sysfb-add-sysfb_disable-helper-function.patch [new file with mode: 0644]
queue-5.15/firmware-sysfb-make-sysfb_create_simplefb-return-a-p.patch [new file with mode: 0644]
queue-5.15/irqchip-or1k-pic-undefine-mask_ack-for-level-trigger.patch [new file with mode: 0644]
queue-5.15/ksmbd-use-sock_nonblock-type-for-kernel_accept.patch [new file with mode: 0644]
queue-5.15/net-sfp-fix-memory-leak-in-sfp_probe.patch [new file with mode: 0644]
queue-5.15/net-tipc-fix-possible-refcount-leak-in-tipc_sk_creat.patch [new file with mode: 0644]
queue-5.15/netfilter-br_netfilter-do-not-skip-all-hooks-with-0-.patch [new file with mode: 0644]
queue-5.15/nfc-nxp-nci-don-t-print-header-length-mismatch-on-i2.patch [new file with mode: 0644]
queue-5.15/nvme-fix-regression-when-disconnect-a-recovering-ctr.patch [new file with mode: 0644]
queue-5.15/nvme-pci-phison-e16-has-bogus-namespace-ids.patch [new file with mode: 0644]
queue-5.15/nvme-tcp-always-fail-a-request-when-sending-it-faile.patch [new file with mode: 0644]
queue-5.15/pinctrl-aspeed-fix-potential-null-dereference-in-asp.patch [new file with mode: 0644]
queue-5.15/platform-x86-hp-wmi-ignore-sanitization-mode-event.patch [new file with mode: 0644]
queue-5.15/powerpc-xive-spapr-correct-bitmap-allocation-size.patch [new file with mode: 0644]
queue-5.15/revert-can-xilinx_can-limit-canfd-brp-to-2.patch [new file with mode: 0644]
queue-5.15/scsi-hisi_sas-limit-max-hw-sectors-for-v3-hw.patch [new file with mode: 0644]
queue-5.15/series
queue-5.15/signal-handling-don-t-use-bug_on-for-debugging.patch [new file with mode: 0644]
queue-5.15/soc-ixp4xx-npe-fix-unused-match-warning.patch [new file with mode: 0644]
queue-5.15/vdpa-mlx5-initialize-cvq-vringh-only-once.patch [new file with mode: 0644]
queue-5.15/vduse-tie-vduse-mgmtdev-and-its-device.patch [new file with mode: 0644]
queue-5.15/virtio_mmio-add-missing-pm-calls-to-freeze-restore.patch [new file with mode: 0644]
queue-5.15/virtio_mmio-restore-guest-page-size-on-resume.patch [new file with mode: 0644]
queue-5.15/x86-clear-.brk-area-at-early-boot.patch [new file with mode: 0644]

diff --git a/queue-5.15/alsa-usb-audio-add-quirk-for-fiero-sc-01-fw-v1.0.0.patch b/queue-5.15/alsa-usb-audio-add-quirk-for-fiero-sc-01-fw-v1.0.0.patch
new file mode 100644 (file)
index 0000000..1353f6a
--- /dev/null
@@ -0,0 +1,187 @@
+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
+
diff --git a/queue-5.15/alsa-usb-audio-add-quirk-for-fiero-sc-01.patch b/queue-5.15/alsa-usb-audio-add-quirk-for-fiero-sc-01.patch
new file mode 100644 (file)
index 0000000..ba0f54b
--- /dev/null
@@ -0,0 +1,142 @@
+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
+
diff --git a/queue-5.15/alsa-usb-audio-add-quirks-for-macrosilicon-ms2100-ms.patch b/queue-5.15/alsa-usb-audio-add-quirks-for-macrosilicon-ms2100-ms.patch
new file mode 100644 (file)
index 0000000..270bc11
--- /dev/null
@@ -0,0 +1,105 @@
+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
+
diff --git a/queue-5.15/arm-dts-stm32-use-the-correct-clock-source-for-cec-o.patch b/queue-5.15/arm-dts-stm32-use-the-correct-clock-source-for-cec-o.patch
new file mode 100644 (file)
index 0000000..b4286e0
--- /dev/null
@@ -0,0 +1,34 @@
+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
+
diff --git a/queue-5.15/asoc-codecs-rt700-rt711-rt711-sdca-initialize-workqu.patch b/queue-5.15/asoc-codecs-rt700-rt711-rt711-sdca-initialize-workqu.patch
new file mode 100644 (file)
index 0000000..cbdbeea
--- /dev/null
@@ -0,0 +1,121 @@
+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
+
diff --git a/queue-5.15/asoc-cs47l15-fix-event-generation-for-low-power-mux-.patch b/queue-5.15/asoc-cs47l15-fix-event-generation-for-low-power-mux-.patch
new file mode 100644 (file)
index 0000000..2260c7a
--- /dev/null
@@ -0,0 +1,48 @@
+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
+
diff --git a/queue-5.15/asoc-dapm-initialise-kcontrol-data-for-mux-demux-con.patch b/queue-5.15/asoc-dapm-initialise-kcontrol-data-for-mux-demux-con.patch
new file mode 100644 (file)
index 0000000..2beb3aa
--- /dev/null
@@ -0,0 +1,59 @@
+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
+
diff --git a/queue-5.15/asoc-intel-bytcr_wm5102-fix-gpio-related-probe-order.patch b/queue-5.15/asoc-intel-bytcr_wm5102-fix-gpio-related-probe-order.patch
new file mode 100644 (file)
index 0000000..bb7fff5
--- /dev/null
@@ -0,0 +1,55 @@
+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
+
diff --git a/queue-5.15/asoc-intel-sof_sdw-handle-errors-on-card-registratio.patch b/queue-5.15/asoc-intel-sof_sdw-handle-errors-on-card-registratio.patch
new file mode 100644 (file)
index 0000000..23c83ad
--- /dev/null
@@ -0,0 +1,107 @@
+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
+
diff --git a/queue-5.15/asoc-madera-fix-event-generation-for-out1-demux.patch b/queue-5.15/asoc-madera-fix-event-generation-for-out1-demux.patch
new file mode 100644 (file)
index 0000000..6472186
--- /dev/null
@@ -0,0 +1,46 @@
+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
+
diff --git a/queue-5.15/asoc-madera-fix-event-generation-for-rate-controls.patch b/queue-5.15/asoc-madera-fix-event-generation-for-rate-controls.patch
new file mode 100644 (file)
index 0000000..9c4379b
--- /dev/null
@@ -0,0 +1,51 @@
+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
+
diff --git a/queue-5.15/asoc-ops-fix-off-by-one-in-range-control-validation.patch b/queue-5.15/asoc-ops-fix-off-by-one-in-range-control-validation.patch
new file mode 100644 (file)
index 0000000..96f17b1
--- /dev/null
@@ -0,0 +1,45 @@
+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
+
diff --git a/queue-5.15/asoc-realtek-maxim-soundwire-codecs-disable-pm_runti.patch b/queue-5.15/asoc-realtek-maxim-soundwire-codecs-disable-pm_runti.patch
new file mode 100644 (file)
index 0000000..58d7cd2
--- /dev/null
@@ -0,0 +1,304 @@
+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
+
diff --git a/queue-5.15/asoc-rockchip-i2s-switch-bclk-to-gpio.patch b/queue-5.15/asoc-rockchip-i2s-switch-bclk-to-gpio.patch
new file mode 100644 (file)
index 0000000..eb8f223
--- /dev/null
@@ -0,0 +1,303 @@
+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
+
diff --git a/queue-5.15/asoc-rt7-sdw-harden-jack_detect_handler.patch b/queue-5.15/asoc-rt7-sdw-harden-jack_detect_handler.patch
new file mode 100644 (file)
index 0000000..edf138b
--- /dev/null
@@ -0,0 +1,70 @@
+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
+
diff --git a/queue-5.15/asoc-rt711-fix-calibrate-mutex-initialization.patch b/queue-5.15/asoc-rt711-fix-calibrate-mutex-initialization.patch
new file mode 100644 (file)
index 0000000..b03f648
--- /dev/null
@@ -0,0 +1,60 @@
+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
+
diff --git a/queue-5.15/asoc-rt711-sdca-fix-kernel-null-pointer-dereference-.patch b/queue-5.15/asoc-rt711-sdca-fix-kernel-null-pointer-dereference-.patch
new file mode 100644 (file)
index 0000000..a2a8af6
--- /dev/null
@@ -0,0 +1,47 @@
+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
+
diff --git a/queue-5.15/asoc-rt711-sdca-sdw-fix-calibrate-mutex-initializati.patch b/queue-5.15/asoc-rt711-sdca-sdw-fix-calibrate-mutex-initializati.patch
new file mode 100644 (file)
index 0000000..1ca1779
--- /dev/null
@@ -0,0 +1,70 @@
+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
+
diff --git a/queue-5.15/asoc-sof-intel-hda-loader-clarify-the-cl_dsp_init-fl.patch b/queue-5.15/asoc-sof-intel-hda-loader-clarify-the-cl_dsp_init-fl.patch
new file mode 100644 (file)
index 0000000..b3ca5c2
--- /dev/null
@@ -0,0 +1,54 @@
+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
+
diff --git a/queue-5.15/asoc-wcd938x-fix-event-generation-for-some-controls.patch b/queue-5.15/asoc-wcd938x-fix-event-generation-for-some-controls.patch
new file mode 100644 (file)
index 0000000..72eb066
--- /dev/null
@@ -0,0 +1,70 @@
+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
+
diff --git a/queue-5.15/asoc-wm5110-fix-dre-control.patch b/queue-5.15/asoc-wm5110-fix-dre-control.patch
new file mode 100644 (file)
index 0000000..807754c
--- /dev/null
@@ -0,0 +1,56 @@
+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
+
diff --git a/queue-5.15/btrfs-rename-btrfs_bio-to-btrfs_io_context.patch b/queue-5.15/btrfs-rename-btrfs_bio-to-btrfs_io_context.patch
new file mode 100644 (file)
index 0000000..1875277
--- /dev/null
@@ -0,0 +1,1893 @@
+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
+
diff --git a/queue-5.15/btrfs-zoned-fix-a-leaked-bioc-in-read_zone_info.patch b/queue-5.15/btrfs-zoned-fix-a-leaked-bioc-in-read_zone_info.patch
new file mode 100644 (file)
index 0000000..69a9c7e
--- /dev/null
@@ -0,0 +1,61 @@
+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
+
diff --git a/queue-5.15/cpufreq-pmac32-cpufreq-fix-refcount-leak-bug.patch b/queue-5.15/cpufreq-pmac32-cpufreq-fix-refcount-leak-bug.patch
new file mode 100644 (file)
index 0000000..58ee737
--- /dev/null
@@ -0,0 +1,38 @@
+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
+
diff --git a/queue-5.15/fbdev-disable-sysfb-device-registration-when-removin.patch b/queue-5.15/fbdev-disable-sysfb-device-registration-when-removin.patch
new file mode 100644 (file)
index 0000000..f449fa3
--- /dev/null
@@ -0,0 +1,67 @@
+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(&registration_lock);
+       do_remove_conflicting_framebuffers(a, name, primary);
+       mutex_unlock(&registration_lock);
+-- 
+2.35.1
+
diff --git a/queue-5.15/firmware-sysfb-add-sysfb_disable-helper-function.patch b/queue-5.15/firmware-sysfb-add-sysfb_disable-helper-function.patch
new file mode 100644 (file)
index 0000000..b07a5b3
--- /dev/null
@@ -0,0 +1,159 @@
+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
+
diff --git a/queue-5.15/firmware-sysfb-make-sysfb_create_simplefb-return-a-p.patch b/queue-5.15/firmware-sysfb-make-sysfb_create_simplefb-return-a-p.patch
new file mode 100644 (file)
index 0000000..45ac79c
--- /dev/null
@@ -0,0 +1,130 @@
+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
+
diff --git a/queue-5.15/irqchip-or1k-pic-undefine-mask_ack-for-level-trigger.patch b/queue-5.15/irqchip-or1k-pic-undefine-mask_ack-for-level-trigger.patch
new file mode 100644 (file)
index 0000000..3006792
--- /dev/null
@@ -0,0 +1,41 @@
+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
+
diff --git a/queue-5.15/ksmbd-use-sock_nonblock-type-for-kernel_accept.patch b/queue-5.15/ksmbd-use-sock_nonblock-type-for-kernel_accept.patch
new file mode 100644 (file)
index 0000000..c024e38
--- /dev/null
@@ -0,0 +1,47 @@
+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
+
diff --git a/queue-5.15/net-sfp-fix-memory-leak-in-sfp_probe.patch b/queue-5.15/net-sfp-fix-memory-leak-in-sfp_probe.patch
new file mode 100644 (file)
index 0000000..806d804
--- /dev/null
@@ -0,0 +1,39 @@
+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
+
diff --git a/queue-5.15/net-tipc-fix-possible-refcount-leak-in-tipc_sk_creat.patch b/queue-5.15/net-tipc-fix-possible-refcount-leak-in-tipc_sk_creat.patch
new file mode 100644 (file)
index 0000000..af9a67d
--- /dev/null
@@ -0,0 +1,34 @@
+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
+
diff --git a/queue-5.15/netfilter-br_netfilter-do-not-skip-all-hooks-with-0-.patch b/queue-5.15/netfilter-br_netfilter-do-not-skip-all-hooks-with-0-.patch
new file mode 100644 (file)
index 0000000..3c1612f
--- /dev/null
@@ -0,0 +1,104 @@
+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
+
diff --git a/queue-5.15/nfc-nxp-nci-don-t-print-header-length-mismatch-on-i2.patch b/queue-5.15/nfc-nxp-nci-don-t-print-header-length-mismatch-on-i2.patch
new file mode 100644 (file)
index 0000000..3c5e7ff
--- /dev/null
@@ -0,0 +1,50 @@
+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
+
diff --git a/queue-5.15/nvme-fix-regression-when-disconnect-a-recovering-ctr.patch b/queue-5.15/nvme-fix-regression-when-disconnect-a-recovering-ctr.patch
new file mode 100644 (file)
index 0000000..bafc152
--- /dev/null
@@ -0,0 +1,143 @@
+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
+
diff --git a/queue-5.15/nvme-pci-phison-e16-has-bogus-namespace-ids.patch b/queue-5.15/nvme-pci-phison-e16-has-bogus-namespace-ids.patch
new file mode 100644 (file)
index 0000000..d6aea7b
--- /dev/null
@@ -0,0 +1,38 @@
+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
+
diff --git a/queue-5.15/nvme-tcp-always-fail-a-request-when-sending-it-faile.patch b/queue-5.15/nvme-tcp-always-fail-a-request-when-sending-it-faile.patch
new file mode 100644 (file)
index 0000000..0d3757f
--- /dev/null
@@ -0,0 +1,45 @@
+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
+
diff --git a/queue-5.15/pinctrl-aspeed-fix-potential-null-dereference-in-asp.patch b/queue-5.15/pinctrl-aspeed-fix-potential-null-dereference-in-asp.patch
new file mode 100644 (file)
index 0000000..22122e6
--- /dev/null
@@ -0,0 +1,42 @@
+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
+
diff --git a/queue-5.15/platform-x86-hp-wmi-ignore-sanitization-mode-event.patch b/queue-5.15/platform-x86-hp-wmi-ignore-sanitization-mode-event.patch
new file mode 100644 (file)
index 0000000..777fd31
--- /dev/null
@@ -0,0 +1,49 @@
+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
+
diff --git a/queue-5.15/powerpc-xive-spapr-correct-bitmap-allocation-size.patch b/queue-5.15/powerpc-xive-spapr-correct-bitmap-allocation-size.patch
new file mode 100644 (file)
index 0000000..35086c6
--- /dev/null
@@ -0,0 +1,112 @@
+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
+
diff --git a/queue-5.15/revert-can-xilinx_can-limit-canfd-brp-to-2.patch b/queue-5.15/revert-can-xilinx_can-limit-canfd-brp-to-2.patch
new file mode 100644 (file)
index 0000000..b3f0cd7
--- /dev/null
@@ -0,0 +1,48 @@
+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
+
diff --git a/queue-5.15/scsi-hisi_sas-limit-max-hw-sectors-for-v3-hw.patch b/queue-5.15/scsi-hisi_sas-limit-max-hw-sectors-for-v3-hw.patch
new file mode 100644 (file)
index 0000000..e43f089
--- /dev/null
@@ -0,0 +1,53 @@
+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
+
index 6a2f5466fea66d75bcda7ea5b13f2e5c2ee6dc4f..2692774cb2f019199916c56113a4211c98bcc7af 100644 (file)
@@ -108,3 +108,51 @@ kvm-x86-fully-initialize-struct-kvm_lapic_irq-in-kvm.patch
 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
diff --git a/queue-5.15/signal-handling-don-t-use-bug_on-for-debugging.patch b/queue-5.15/signal-handling-don-t-use-bug_on-for-debugging.patch
new file mode 100644 (file)
index 0000000..621e14d
--- /dev/null
@@ -0,0 +1,54 @@
+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
+
diff --git a/queue-5.15/soc-ixp4xx-npe-fix-unused-match-warning.patch b/queue-5.15/soc-ixp4xx-npe-fix-unused-match-warning.patch
new file mode 100644 (file)
index 0000000..0f73ab9
--- /dev/null
@@ -0,0 +1,45 @@
+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
+
diff --git a/queue-5.15/vdpa-mlx5-initialize-cvq-vringh-only-once.patch b/queue-5.15/vdpa-mlx5-initialize-cvq-vringh-only-once.patch
new file mode 100644 (file)
index 0000000..7c45e91
--- /dev/null
@@ -0,0 +1,96 @@
+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
+
diff --git a/queue-5.15/vduse-tie-vduse-mgmtdev-and-its-device.patch b/queue-5.15/vduse-tie-vduse-mgmtdev-and-its-device.patch
new file mode 100644 (file)
index 0000000..e8572b0
--- /dev/null
@@ -0,0 +1,134 @@
+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
+
diff --git a/queue-5.15/virtio_mmio-add-missing-pm-calls-to-freeze-restore.patch b/queue-5.15/virtio_mmio-add-missing-pm-calls-to-freeze-restore.patch
new file mode 100644 (file)
index 0000000..597a9e6
--- /dev/null
@@ -0,0 +1,81 @@
+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
+
diff --git a/queue-5.15/virtio_mmio-restore-guest-page-size-on-resume.patch b/queue-5.15/virtio_mmio-restore-guest-page-size-on-resume.patch
new file mode 100644 (file)
index 0000000..b56d351
--- /dev/null
@@ -0,0 +1,44 @@
+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
+
diff --git a/queue-5.15/x86-clear-.brk-area-at-early-boot.patch b/queue-5.15/x86-clear-.brk-area-at-early-boot.patch
new file mode 100644 (file)
index 0000000..fe2e83d
--- /dev/null
@@ -0,0 +1,43 @@
+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
+