From 1ae7ede6684182b5ad8acbb139a4f32b357f61c8 Mon Sep 17 00:00:00 2001 From: Sasha Levin Date: Sun, 17 Jul 2022 21:29:45 -0400 Subject: [PATCH] Fixes for 5.15 Signed-off-by: Sasha Levin --- ...-add-quirk-for-fiero-sc-01-fw-v1.0.0.patch | 187 ++ ...-usb-audio-add-quirk-for-fiero-sc-01.patch | 142 ++ ...dd-quirks-for-macrosilicon-ms2100-ms.patch | 105 + ...e-the-correct-clock-source-for-cec-o.patch | 34 + ...0-rt711-rt711-sdca-initialize-workqu.patch | 121 ++ ...-event-generation-for-low-power-mux-.patch | 48 + ...lise-kcontrol-data-for-mux-demux-con.patch | 59 + ..._wm5102-fix-gpio-related-probe-order.patch | 55 + ...dw-handle-errors-on-card-registratio.patch | 107 + ...-fix-event-generation-for-out1-demux.patch | 46 + ...x-event-generation-for-rate-controls.patch | 51 + ...f-by-one-in-range-control-validation.patch | 45 + ...im-soundwire-codecs-disable-pm_runti.patch | 304 +++ ...soc-rockchip-i2s-switch-bclk-to-gpio.patch | 303 +++ ...c-rt7-sdw-harden-jack_detect_handler.patch | 70 + ...1-fix-calibrate-mutex-initialization.patch | 60 + ...fix-kernel-null-pointer-dereference-.patch | 47 + ...sdw-fix-calibrate-mutex-initializati.patch | 70 + ...da-loader-clarify-the-cl_dsp_init-fl.patch | 54 + ...x-event-generation-for-some-controls.patch | 70 + queue-5.15/asoc-wm5110-fix-dre-control.patch | 56 + ...rename-btrfs_bio-to-btrfs_io_context.patch | 1893 +++++++++++++++++ ...-fix-a-leaked-bioc-in-read_zone_info.patch | 61 + ...pmac32-cpufreq-fix-refcount-leak-bug.patch | 38 + ...sfb-device-registration-when-removin.patch | 67 + ...fb-add-sysfb_disable-helper-function.patch | 159 ++ ...ake-sysfb_create_simplefb-return-a-p.patch | 130 ++ ...-undefine-mask_ack-for-level-trigger.patch | 41 + ...sock_nonblock-type-for-kernel_accept.patch | 47 + ...net-sfp-fix-memory-leak-in-sfp_probe.patch | 39 + ...sible-refcount-leak-in-tipc_sk_creat.patch | 34 + ...filter-do-not-skip-all-hooks-with-0-.patch | 104 + ...t-print-header-length-mismatch-on-i2.patch | 50 + ...ion-when-disconnect-a-recovering-ctr.patch | 143 ++ ...i-phison-e16-has-bogus-namespace-ids.patch | 38 + ...fail-a-request-when-sending-it-faile.patch | 45 + ...ix-potential-null-dereference-in-asp.patch | 42 + ...p-wmi-ignore-sanitization-mode-event.patch | 49 + ...spapr-correct-bitmap-allocation-size.patch | 112 + ...-can-xilinx_can-limit-canfd-brp-to-2.patch | 48 + ...i_sas-limit-max-hw-sectors-for-v3-hw.patch | 53 + queue-5.15/series | 48 + ...dling-don-t-use-bug_on-for-debugging.patch | 54 + ...-ixp4xx-npe-fix-unused-match-warning.patch | 45 + ...mlx5-initialize-cvq-vringh-only-once.patch | 96 + ...use-tie-vduse-mgmtdev-and-its-device.patch | 134 ++ ...d-missing-pm-calls-to-freeze-restore.patch | 81 + ...io-restore-guest-page-size-on-resume.patch | 44 + .../x86-clear-.brk-area-at-early-boot.patch | 43 + 49 files changed, 5772 insertions(+) create mode 100644 queue-5.15/alsa-usb-audio-add-quirk-for-fiero-sc-01-fw-v1.0.0.patch create mode 100644 queue-5.15/alsa-usb-audio-add-quirk-for-fiero-sc-01.patch create mode 100644 queue-5.15/alsa-usb-audio-add-quirks-for-macrosilicon-ms2100-ms.patch create mode 100644 queue-5.15/arm-dts-stm32-use-the-correct-clock-source-for-cec-o.patch create mode 100644 queue-5.15/asoc-codecs-rt700-rt711-rt711-sdca-initialize-workqu.patch create mode 100644 queue-5.15/asoc-cs47l15-fix-event-generation-for-low-power-mux-.patch create mode 100644 queue-5.15/asoc-dapm-initialise-kcontrol-data-for-mux-demux-con.patch create mode 100644 queue-5.15/asoc-intel-bytcr_wm5102-fix-gpio-related-probe-order.patch create mode 100644 queue-5.15/asoc-intel-sof_sdw-handle-errors-on-card-registratio.patch create mode 100644 queue-5.15/asoc-madera-fix-event-generation-for-out1-demux.patch create mode 100644 queue-5.15/asoc-madera-fix-event-generation-for-rate-controls.patch create mode 100644 queue-5.15/asoc-ops-fix-off-by-one-in-range-control-validation.patch create mode 100644 queue-5.15/asoc-realtek-maxim-soundwire-codecs-disable-pm_runti.patch create mode 100644 queue-5.15/asoc-rockchip-i2s-switch-bclk-to-gpio.patch create mode 100644 queue-5.15/asoc-rt7-sdw-harden-jack_detect_handler.patch create mode 100644 queue-5.15/asoc-rt711-fix-calibrate-mutex-initialization.patch create mode 100644 queue-5.15/asoc-rt711-sdca-fix-kernel-null-pointer-dereference-.patch create mode 100644 queue-5.15/asoc-rt711-sdca-sdw-fix-calibrate-mutex-initializati.patch create mode 100644 queue-5.15/asoc-sof-intel-hda-loader-clarify-the-cl_dsp_init-fl.patch create mode 100644 queue-5.15/asoc-wcd938x-fix-event-generation-for-some-controls.patch create mode 100644 queue-5.15/asoc-wm5110-fix-dre-control.patch create mode 100644 queue-5.15/btrfs-rename-btrfs_bio-to-btrfs_io_context.patch create mode 100644 queue-5.15/btrfs-zoned-fix-a-leaked-bioc-in-read_zone_info.patch create mode 100644 queue-5.15/cpufreq-pmac32-cpufreq-fix-refcount-leak-bug.patch create mode 100644 queue-5.15/fbdev-disable-sysfb-device-registration-when-removin.patch create mode 100644 queue-5.15/firmware-sysfb-add-sysfb_disable-helper-function.patch create mode 100644 queue-5.15/firmware-sysfb-make-sysfb_create_simplefb-return-a-p.patch create mode 100644 queue-5.15/irqchip-or1k-pic-undefine-mask_ack-for-level-trigger.patch create mode 100644 queue-5.15/ksmbd-use-sock_nonblock-type-for-kernel_accept.patch create mode 100644 queue-5.15/net-sfp-fix-memory-leak-in-sfp_probe.patch create mode 100644 queue-5.15/net-tipc-fix-possible-refcount-leak-in-tipc_sk_creat.patch create mode 100644 queue-5.15/netfilter-br_netfilter-do-not-skip-all-hooks-with-0-.patch create mode 100644 queue-5.15/nfc-nxp-nci-don-t-print-header-length-mismatch-on-i2.patch create mode 100644 queue-5.15/nvme-fix-regression-when-disconnect-a-recovering-ctr.patch create mode 100644 queue-5.15/nvme-pci-phison-e16-has-bogus-namespace-ids.patch create mode 100644 queue-5.15/nvme-tcp-always-fail-a-request-when-sending-it-faile.patch create mode 100644 queue-5.15/pinctrl-aspeed-fix-potential-null-dereference-in-asp.patch create mode 100644 queue-5.15/platform-x86-hp-wmi-ignore-sanitization-mode-event.patch create mode 100644 queue-5.15/powerpc-xive-spapr-correct-bitmap-allocation-size.patch create mode 100644 queue-5.15/revert-can-xilinx_can-limit-canfd-brp-to-2.patch create mode 100644 queue-5.15/scsi-hisi_sas-limit-max-hw-sectors-for-v3-hw.patch create mode 100644 queue-5.15/signal-handling-don-t-use-bug_on-for-debugging.patch create mode 100644 queue-5.15/soc-ixp4xx-npe-fix-unused-match-warning.patch create mode 100644 queue-5.15/vdpa-mlx5-initialize-cvq-vringh-only-once.patch create mode 100644 queue-5.15/vduse-tie-vduse-mgmtdev-and-its-device.patch create mode 100644 queue-5.15/virtio_mmio-add-missing-pm-calls-to-freeze-restore.patch create mode 100644 queue-5.15/virtio_mmio-restore-guest-page-size-on-resume.patch create mode 100644 queue-5.15/x86-clear-.brk-area-at-early-boot.patch 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 index 00000000000..1353f6a41c7 --- /dev/null +++ b/queue-5.15/alsa-usb-audio-add-quirk-for-fiero-sc-01-fw-v1.0.0.patch @@ -0,0 +1,187 @@ +From 68538a5164672f666b511ac4373127567dcd233b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Link: https://lore.kernel.org/r/20220627100041.2861494-2-sdoregor@sdore.me +Signed-off-by: Takashi Iwai +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..ba0f54b2ce0 --- /dev/null +++ b/queue-5.15/alsa-usb-audio-add-quirk-for-fiero-sc-01.patch @@ -0,0 +1,142 @@ +From cb088248614f70acffbf4888ed4bb0c18808567b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 27 Jun 2022 13:00:34 +0300 +Subject: ALSA: usb-audio: Add quirk for Fiero SC-01 + +From: Egor Vorontsov + +[ 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 +Link: https://lore.kernel.org/r/20220627100041.2861494-1-sdoregor@sdore.me +Signed-off-by: Takashi Iwai +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..270bc1198d7 --- /dev/null +++ b/queue-5.15/alsa-usb-audio-add-quirks-for-macrosilicon-ms2100-ms.patch @@ -0,0 +1,105 @@ +From 1243fe374284bf21189f357e8027f1b786a60b1e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 24 Jun 2022 15:07:57 +0100 +Subject: ALSA: usb-audio: Add quirks for MacroSilicon MS2100/MS2106 devices + +From: John Veness + +[ 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 +Link: https://lore.kernel.org/r/20220624140757.28758-1-john-linux@pelago.org.uk +Signed-off-by: Takashi Iwai +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..b4286e019f6 --- /dev/null +++ b/queue-5.15/arm-dts-stm32-use-the-correct-clock-source-for-cec-o.patch @@ -0,0 +1,34 @@ +From ff577d205087119955bf09082195b19de4266386 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ Upstream commit 78ece8cce1ba0c3f3e5a7c6c1b914b3794f04c44 ] + +The peripheral clock of CEC is not LSE but CEC. + +Signed-off-by: Gabriel Fernandez +Signed-off-by: Alexandre Torgue +Signed-off-by: Sasha Levin +--- + 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 = ; +- 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 index 00000000000..cbdbeeabcbc --- /dev/null +++ b/queue-5.15/asoc-codecs-rt700-rt711-rt711-sdca-initialize-workqu.patch @@ -0,0 +1,121 @@ +From ddae663e399501cc4b5a9f82f52b4357b37a7751 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 6 Jun 2022 15:37:51 -0500 +Subject: ASoC: codecs: rt700/rt711/rt711-sdca: initialize workqueues in probe + +From: Pierre-Louis Bossart + +[ 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 +Reviewed-by: Rander Wang +Reviewed-by: Bard Liao +Link: https://lore.kernel.org/r/20220606203752.144159-7-pierre-louis.bossart@linux.intel.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..2260c7a9ef7 --- /dev/null +++ b/queue-5.15/asoc-cs47l15-fix-event-generation-for-low-power-mux-.patch @@ -0,0 +1,48 @@ +From 8fade53e2218517ee8c9ae1da85b66aac317f91d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 23 Jun 2022 11:51:17 +0100 +Subject: ASoC: cs47l15: Fix event generation for low power mux control + +From: Charles Keepax + +[ 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 +Link: https://lore.kernel.org/r/20220623105120.1981154-3-ckeepax@opensource.cirrus.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..2beb3aa8294 --- /dev/null +++ b/queue-5.15/asoc-dapm-initialise-kcontrol-data-for-mux-demux-con.patch @@ -0,0 +1,59 @@ +From 32ca059537a81e8d62c16be868fe34b83bbfaa16 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 23 Jun 2022 11:51:15 +0100 +Subject: ASoC: dapm: Initialise kcontrol data for mux/demux controls + +From: Charles Keepax + +[ 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 +Link: https://lore.kernel.org/r/20220623105120.1981154-1-ckeepax@opensource.cirrus.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..bb7fff51568 --- /dev/null +++ b/queue-5.15/asoc-intel-bytcr_wm5102-fix-gpio-related-probe-order.patch @@ -0,0 +1,55 @@ +From a7a1baebe351486fe23369eb351d1be975041cdd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 12 Jun 2022 17:56:52 +0200 +Subject: ASoC: Intel: bytcr_wm5102: Fix GPIO related probe-ordering problem + +From: Hans de Goede + +[ 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 +Acked-by: Pierre-Louis Bossart +Link: https://lore.kernel.org/r/20220612155652.107310-1-hdegoede@redhat.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..23c83ad7b78 --- /dev/null +++ b/queue-5.15/asoc-intel-sof_sdw-handle-errors-on-card-registratio.patch @@ -0,0 +1,107 @@ +From d9deb1e27bd982c4e86fc0f3e8093c04910d0ea5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 6 Jun 2022 15:37:48 -0500 +Subject: ASoC: Intel: sof_sdw: handle errors on card registration + +From: Pierre-Louis Bossart + +[ 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 +Reviewed-by: Rander Wang +Reviewed-by: Bard Liao +Link: https://lore.kernel.org/r/20220606203752.144159-4-pierre-louis.bossart@linux.intel.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..647218618a2 --- /dev/null +++ b/queue-5.15/asoc-madera-fix-event-generation-for-out1-demux.patch @@ -0,0 +1,46 @@ +From 7757a78c05a29089cf4aae2fd1a4f7d6b4a6038c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 23 Jun 2022 11:51:18 +0100 +Subject: ASoC: madera: Fix event generation for OUT1 demux + +From: Charles Keepax + +[ 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 +Link: https://lore.kernel.org/r/20220623105120.1981154-4-ckeepax@opensource.cirrus.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..9c4379b72f5 --- /dev/null +++ b/queue-5.15/asoc-madera-fix-event-generation-for-rate-controls.patch @@ -0,0 +1,51 @@ +From 3c22074af1fab78446835a1beb8fddac6d622205 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 23 Jun 2022 11:51:19 +0100 +Subject: ASoC: madera: Fix event generation for rate controls + +From: Charles Keepax + +[ 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 +Link: https://lore.kernel.org/r/20220623105120.1981154-5-ckeepax@opensource.cirrus.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..96f17b1f626 --- /dev/null +++ b/queue-5.15/asoc-ops-fix-off-by-one-in-range-control-validation.patch @@ -0,0 +1,45 @@ +From a92fdabd42a92a18e75fb0682821960445ddfd89 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 4 Jun 2022 11:52:46 +0100 +Subject: ASoC: ops: Fix off by one in range control validation + +From: Mark Brown + +[ 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 +Link: https://lore.kernel.org/r/20220604105246.4055214-1-broonie@kernel.org +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..58d7cd22af8 --- /dev/null +++ b/queue-5.15/asoc-realtek-maxim-soundwire-codecs-disable-pm_runti.patch @@ -0,0 +1,304 @@ +From c6b40e92bffea13ede08cf910c9b8600b474d5fe Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 6 Jun 2022 15:37:46 -0500 +Subject: ASoC: Realtek/Maxim SoundWire codecs: disable pm_runtime on remove + +From: Pierre-Louis Bossart + +[ 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 +Reviewed-by: Rander Wang +Reviewed-by: Bard Liao +Link: https://lore.kernel.org/r/20220606203752.144159-2-pierre-louis.bossart@linux.intel.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + 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 + #include + #include ++#include + #include + #include + #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 + #include + #include ++#include + + #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 + #include + #include ++#include + #include + #include + #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 + #include + #include ++#include + #include + #include + #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 + #include + #include ++#include + #include + #include + #include +@@ -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 index 00000000000..eb8f22394b5 --- /dev/null +++ b/queue-5.15/asoc-rockchip-i2s-switch-bclk-to-gpio.patch @@ -0,0 +1,303 @@ +From ecfe8072e38aa8aab29b15f94503adfcbd2829d8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 15 Jun 2022 04:56:43 +0000 +Subject: ASoC: rockchip: i2s: switch BCLK to GPIO + +From: Judy Hsiao + +[ 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 +Link: https://lore.kernel.org/r/20220615045643.3137287-1-judyhsiao@chromium.org +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + 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 + #include + #include ++#include + #include + #include + #include +@@ -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 index 00000000000..edf138b9f84 --- /dev/null +++ b/queue-5.15/asoc-rt7-sdw-harden-jack_detect_handler.patch @@ -0,0 +1,70 @@ +From 1174070ef74196b89e044ee21e8af7502861f5d5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 6 Jun 2022 15:37:50 -0500 +Subject: ASoC: rt7*-sdw: harden jack_detect_handler + +From: Pierre-Louis Bossart + +[ 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 +Reviewed-by: Rander Wang +Reviewed-by: Bard Liao +Link: https://lore.kernel.org/r/20220606203752.144159-6-pierre-louis.bossart@linux.intel.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..b03f648c2f5 --- /dev/null +++ b/queue-5.15/asoc-rt711-fix-calibrate-mutex-initialization.patch @@ -0,0 +1,60 @@ +From 57ac9d49cff349fcc6e3691d8e4247a3ab556902 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 6 Jun 2022 15:37:49 -0500 +Subject: ASoC: rt711: fix calibrate mutex initialization + +From: Pierre-Louis Bossart + +[ Upstream commit 08bb5dc6ce02374169213cea772b1c297eaf32d5 ] + +Follow the same flow as rt711-sdca and initialize all mutexes at probe +time. + +Signed-off-by: Pierre-Louis Bossart +Reviewed-by: Rander Wang +Reviewed-by: Bard Liao +Link: https://lore.kernel.org/r/20220606203752.144159-5-pierre-louis.bossart@linux.intel.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..a2a8af6c863 --- /dev/null +++ b/queue-5.15/asoc-rt711-sdca-fix-kernel-null-pointer-dereference-.patch @@ -0,0 +1,47 @@ +From 8802191da8a5cc76f190b62005557e8bb68af3a8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Jun 2022 17:07:19 +0800 +Subject: ASoC: rt711-sdca: fix kernel NULL pointer dereference when IO error + +From: Shuming Fan + +[ 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 +Link: https://lore.kernel.org/r/20220621090719.30558-1-shumingf@realtek.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..1ca17790117 --- /dev/null +++ b/queue-5.15/asoc-rt711-sdca-sdw-fix-calibrate-mutex-initializati.patch @@ -0,0 +1,70 @@ +From f07e7000daecd4f9dba7134fd414648d1b3d4e54 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 6 Jun 2022 15:37:47 -0500 +Subject: ASoC: rt711-sdca-sdw: fix calibrate mutex initialization + +From: Pierre-Louis Bossart + +[ 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 +Reviewed-by: Rander Wang +Reviewed-by: Bard Liao +Link: https://lore.kernel.org/r/20220606203752.144159-3-pierre-louis.bossart@linux.intel.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..b3ca5c2390f --- /dev/null +++ b/queue-5.15/asoc-sof-intel-hda-loader-clarify-the-cl_dsp_init-fl.patch @@ -0,0 +1,54 @@ +From d2f2f30b576f9a1c2e636ee7518605eebf4162a8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 9 Jun 2022 11:59:49 +0300 +Subject: ASoC: SOF: Intel: hda-loader: Clarify the cl_dsp_init() flow + +From: Peter Ujfalusi + +[ 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 +Reviewed-by: Pierre-Louis Bossart +Reviewed-by: Bard Liao +Reviewed-by: Ranjani Sridharan +Link: https://lore.kernel.org/r/20220609085949.29062-4-peter.ujfalusi@linux.intel.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..72eb0669099 --- /dev/null +++ b/queue-5.15/asoc-wcd938x-fix-event-generation-for-some-controls.patch @@ -0,0 +1,70 @@ +From f98bc8e4b9b40b0172343f066b256d9d7c123884 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 3 Jun 2022 14:25:26 +0200 +Subject: ASoC: wcd938x: Fix event generation for some controls + +From: Mark Brown + +[ 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 +Reported-by: kernel test robot +Link: https://lore.kernel.org/r/20220603122526.3914942-1-broonie@kernel.org +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..807754c33b9 --- /dev/null +++ b/queue-5.15/asoc-wm5110-fix-dre-control.patch @@ -0,0 +1,56 @@ +From 9239ef84aef8f7c3c949a1b672817dea71ffafc9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Jun 2022 11:20:39 +0100 +Subject: ASoC: wm5110: Fix DRE control + +From: Charles Keepax + +[ 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 +Link: https://lore.kernel.org/r/20220621102041.1713504-2-ckeepax@opensource.cirrus.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..187527784f8 --- /dev/null +++ b/queue-5.15/btrfs-rename-btrfs_bio-to-btrfs_io_context.patch @@ -0,0 +1,1893 @@ +From 959faf7f65fc576f30572ca677db35b724ffd3b3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 15 Sep 2021 15:17:16 +0800 +Subject: btrfs: rename btrfs_bio to btrfs_io_context + +From: Qu Wenruo + +[ 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 +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..69a9c7e72e3 --- /dev/null +++ b/queue-5.15/btrfs-zoned-fix-a-leaked-bioc-in-read_zone_info.patch @@ -0,0 +1,61 @@ +From a851a2fccaa299509aaf5bd4184188debebb737c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 30 Jun 2022 18:03:19 +0200 +Subject: btrfs: zoned: fix a leaked bioc in read_zone_info + +From: Christoph Hellwig + +[ 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 +Signed-off-by: Christoph Hellwig +[ update changelog ] +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..58ee737ac66 --- /dev/null +++ b/queue-5.15/cpufreq-pmac32-cpufreq-fix-refcount-leak-bug.patch @@ -0,0 +1,38 @@ +From 4f4144b0ff472eda5693e1e9022a3a7215afa249 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 18 Jun 2022 10:25:45 +0800 +Subject: cpufreq: pmac32-cpufreq: Fix refcount leak bug + +From: Liang He + +[ 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 +Signed-off-by: Viresh Kumar +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..f449fa30040 --- /dev/null +++ b/queue-5.15/fbdev-disable-sysfb-device-registration-when-removin.patch @@ -0,0 +1,67 @@ +From dc1aed1a19a7f681a8d969a46675fabcc6e241bc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 Jun 2022 20:23:36 +0200 +Subject: fbdev: Disable sysfb device registration when removing conflicting + FBs + +From: Javier Martinez Canillas + +[ 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 +Signed-off-by: Javier Martinez Canillas +Reviewed-by: Daniel Vetter +Link: https://patchwork.freedesktop.org/patch/msgid/20220607182338.344270-4-javierm@redhat.com +Signed-off-by: Sasha Levin +--- + 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 + #include + #include ++#include + #include + #include + #include +@@ -1786,6 +1787,17 @@ int remove_conflicting_framebuffers(struct apertures_struct *a, + do_free = true; + } + ++ /* ++ * If a driver asked to unregister a platform device registered by ++ * sysfb, then can be assumed that this is a driver for a display ++ * that is set up by the system firmware and has a generic driver. ++ * ++ * Drivers for devices that don't have a generic driver will never ++ * ask for this, so let's assume that a real driver for the display ++ * was already probed and prevent sysfb to register devices later. ++ */ ++ sysfb_disable(); ++ + mutex_lock(®istration_lock); + do_remove_conflicting_framebuffers(a, name, primary); + mutex_unlock(®istration_lock); +-- +2.35.1 + 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 index 00000000000..b07a5b37447 --- /dev/null +++ b/queue-5.15/firmware-sysfb-add-sysfb_disable-helper-function.patch @@ -0,0 +1,159 @@ +From 69fbbff9b4b8049858e04b8bd88a14d49a7c78e4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 Jun 2022 20:23:35 +0200 +Subject: firmware: sysfb: Add sysfb_disable() helper function + +From: Javier Martinez Canillas + +[ 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 +Signed-off-by: Javier Martinez Canillas +Reviewed-by: Daniel Vetter +Link: https://patchwork.freedesktop.org/patch/msgid/20220607182338.344270-3-javierm@redhat.com +Signed-off-by: Sasha Levin +--- + .../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 + #include + ++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 index 00000000000..45ac79ce0c6 --- /dev/null +++ b/queue-5.15/firmware-sysfb-make-sysfb_create_simplefb-return-a-p.patch @@ -0,0 +1,130 @@ +From c7266280c5e3653d9646fcdb9137d3495ffaef58 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 Jun 2022 20:23:34 +0200 +Subject: firmware: sysfb: Make sysfb_create_simplefb() return a pdev pointer + +From: Javier Martinez Canillas + +[ 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 +Reviewed-by: Daniel Vetter +Reviewed-by: Thomas Zimmermann +Link: https://patchwork.freedesktop.org/patch/msgid/20220607182338.344270-2-javierm@redhat.com +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..3006792b5b5 --- /dev/null +++ b/queue-5.15/irqchip-or1k-pic-undefine-mask_ack-for-level-trigger.patch @@ -0,0 +1,41 @@ +From bb479c18ec230301ef183c3505edeec524aeecd9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 15 Jun 2022 08:54:26 +0900 +Subject: irqchip: or1k-pic: Undefine mask_ack for level triggered hardware + +From: Stafford Horne + +[ 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 +Signed-off-by: Stafford Horne +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..c024e38ce8a --- /dev/null +++ b/queue-5.15/ksmbd-use-sock_nonblock-type-for-kernel_accept.patch @@ -0,0 +1,47 @@ +From 3440377f258c61273dcff759fec038fe74b0215b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 2 Jun 2022 10:07:38 +0900 +Subject: ksmbd: use SOCK_NONBLOCK type for kernel_accept() + +From: Namjae Jeon + +[ 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 +Signed-off-by: Namjae Jeon +Reviewed-by: Hyunchul Lee +Signed-off-by: Steve French +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..806d804cf3b --- /dev/null +++ b/queue-5.15/net-sfp-fix-memory-leak-in-sfp_probe.patch @@ -0,0 +1,39 @@ +From 92b4f4cefc39e0003ce8d5dc0b850ead97a472f1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 29 Jun 2022 15:55:50 +0800 +Subject: net: sfp: fix memory leak in sfp_probe() + +From: Jianglei Nie + +[ 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 +Reviewed-by: Russell King (Oracle) +Link: https://lore.kernel.org/r/20220629075550.2152003-1-niejianglei2021@163.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..af9a67d3e11 --- /dev/null +++ b/queue-5.15/net-tipc-fix-possible-refcount-leak-in-tipc_sk_creat.patch @@ -0,0 +1,34 @@ +From cc1332e0d51d416dbee1bb7c49373e96d0d15c42 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 29 Jun 2022 14:34:18 +0800 +Subject: net: tipc: fix possible refcount leak in tipc_sk_create() + +From: Hangyu Hua + +[ Upstream commit 00aff3590fc0a73bddd3b743863c14e76fd35c0c ] + +Free sk in case tipc_sk_insert() fails. + +Signed-off-by: Hangyu Hua +Reviewed-by: Tung Nguyen +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..3c1612f54ab --- /dev/null +++ b/queue-5.15/netfilter-br_netfilter-do-not-skip-all-hooks-with-0-.patch @@ -0,0 +1,104 @@ +From d0a451ca4b4ec984db526266b45481c496fe797c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Jun 2022 18:26:03 +0200 +Subject: netfilter: br_netfilter: do not skip all hooks with 0 priority + +From: Florian Westphal + +[ 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 +Signed-off-by: Florian Westphal +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..3c5e7ff0779 --- /dev/null +++ b/queue-5.15/nfc-nxp-nci-don-t-print-header-length-mismatch-on-i2.patch @@ -0,0 +1,50 @@ +From 7fbe0be79fe4735cf9f07b9bbd3df5cc00343af3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Reviewed-by: Krzysztof Kozlowski +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..bafc1528bfc --- /dev/null +++ b/queue-5.15/nvme-fix-regression-when-disconnect-a-recovering-ctr.patch @@ -0,0 +1,143 @@ +From 3ac80bf6c50429607abeebe584cbaf47f5b7a838 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 23 Jun 2022 14:45:39 +0800 +Subject: nvme: fix regression when disconnect a recovering ctrl + +From: Ruozhu Li + +[ 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 +Reviewed-by: Sagi Grimberg +Signed-off-by: Christoph Hellwig +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..d6aea7b0d2f --- /dev/null +++ b/queue-5.15/nvme-pci-phison-e16-has-bogus-namespace-ids.patch @@ -0,0 +1,38 @@ +From 9479a48a8342ba4da5b0311fb811b8967d2b8912 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 5 Jul 2022 10:21:02 -0700 +Subject: nvme-pci: phison e16 has bogus namespace ids + +From: Keith Busch + +[ Upstream commit 73029c9b23cf1213e5f54c2b59efce08665199e7 ] + +Add the quirk. + +Link: https://bugzilla.kernel.org/show_bug.cgi?id=216049 +Reported-by: Chris Egolf +Signed-off-by: Keith Busch +Reviewed-by: Chaitanya Kulkarni +Signed-off-by: Christoph Hellwig +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..0d3757f5d33 --- /dev/null +++ b/queue-5.15/nvme-tcp-always-fail-a-request-when-sending-it-faile.patch @@ -0,0 +1,45 @@ +From e4b13b32648eb37995bf85899971aa237c368a79 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 26 Jun 2022 12:24:51 +0300 +Subject: nvme-tcp: always fail a request when sending it failed + +From: Sagi Grimberg + +[ 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 +Signed-off-by: Sagi Grimberg +Signed-off-by: Christoph Hellwig +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..22122e63c73 --- /dev/null +++ b/queue-5.15/pinctrl-aspeed-fix-potential-null-dereference-in-asp.patch @@ -0,0 +1,42 @@ +From 25bdb74c11e73c78cf69ab342755f5b5bf18b6ea Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 21 Apr 2022 10:26:59 +0800 +Subject: pinctrl: aspeed: Fix potential NULL dereference in + aspeed_pinmux_set_mux() + +From: Haowen Bai + +[ 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 +Link: https://lore.kernel.org/r/1650508019-22554-1-git-send-email-baihaowen@meizu.com +Signed-off-by: Linus Walleij +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..777fd31d939 --- /dev/null +++ b/queue-5.15/platform-x86-hp-wmi-ignore-sanitization-mode-event.patch @@ -0,0 +1,49 @@ +From a7050edeb08f3614e166b14f58cbafb29f005ff3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 28 Jun 2022 20:37:26 +0800 +Subject: platform/x86: hp-wmi: Ignore Sanitization Mode event + +From: Kai-Heng Feng + +[ 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 +Signed-off-by: Kai-Heng Feng +Link: https://lore.kernel.org/r/20220628123726.250062-1-kai.heng.feng@canonical.com +Reviewed-by: Hans de Goede +Signed-off-by: Hans de Goede +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..35086c692ba --- /dev/null +++ b/queue-5.15/powerpc-xive-spapr-correct-bitmap-allocation-size.patch @@ -0,0 +1,112 @@ +From caa371f56002075dd67f999c3ede635e24d5742c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Reviewed-by: Cédric Le Goater +Signed-off-by: Michael Ellerman +Link: https://lore.kernel.org/r/20220623182509.3985625-1-nathanl@linux.ibm.com +Signed-off-by: Sasha Levin +--- + 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 + #include + #include ++#include + #include + #include + #include +@@ -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 index 00000000000..b3f0cd77c66 --- /dev/null +++ b/queue-5.15/revert-can-xilinx_can-limit-canfd-brp-to-2.patch @@ -0,0 +1,48 @@ +From 2db154b1f9f5e94fcfceb41092012550600b4f31 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 9 Jun 2022 13:54:32 +0530 +Subject: Revert "can: xilinx_can: Limit CANFD brp to 2" + +From: Srinivas Neeli + +[ 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 +Signed-off-by: Marc Kleine-Budde +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..e43f089986e --- /dev/null +++ b/queue-5.15/scsi-hisi_sas-limit-max-hw-sectors-for-v3-hw.patch @@ -0,0 +1,53 @@ +From 9f6c0d7d93a5ddd568606ceb02d94ef7b7b107ef Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 23 Jun 2022 20:41:59 +0800 +Subject: scsi: hisi_sas: Limit max hw sectors for v3 HW + +From: John Garry + +[ 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 +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/series b/queue-5.15/series index 6a2f5466fea..2692774cb2f 100644 --- a/queue-5.15/series +++ b/queue-5.15/series @@ -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 index 00000000000..621e14d2a58 --- /dev/null +++ b/queue-5.15/signal-handling-don-t-use-bug_on-for-debugging.patch @@ -0,0 +1,54 @@ +From 220df8c3af3bfb79c2cb4e9f1d981354df08f3f3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 6 Jul 2022 12:20:59 -0700 +Subject: signal handling: don't use BUG_ON() for debugging + +From: Linus Torvalds + +[ 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 +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..0f73ab96427 --- /dev/null +++ b/queue-5.15/soc-ixp4xx-npe-fix-unused-match-warning.patch @@ -0,0 +1,45 @@ +From e4c36672f2c3b550355c81390a24f12d95887624 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 26 Jun 2022 09:43:15 +0200 +Subject: soc: ixp4xx/npe: Fix unused match warning + +From: Linus Walleij + +[ 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 +Link: https://lore.kernel.org/r/20220626074315.61209-1-linus.walleij@linaro.org' +Signed-off-by: Arnd Bergmann +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..7c45e914dc6 --- /dev/null +++ b/queue-5.15/vdpa-mlx5-initialize-cvq-vringh-only-once.patch @@ -0,0 +1,96 @@ +From ed2ff6afd8dadd6a2eaabc14e55a2e51e2b10904 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Message-Id: <20220613075958.511064-2-elic@nvidia.com> +Signed-off-by: Michael S. Tsirkin +Acked-by: Jason Wang +Acked-by: Eugenio Pérez +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..e8572b0cc57 --- /dev/null +++ b/queue-5.15/vduse-tie-vduse-mgmtdev-and-its-device.patch @@ -0,0 +1,134 @@ +From 9f7b96b82981ff1f5118ad1679ca2d29b36c4448 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 13 Jun 2022 22:52:23 +0300 +Subject: vduse: Tie vduse mgmtdev and its device + +From: Parav Pandit + +[ 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 +Message-Id: <20220613195223.473966-1-parav@nvidia.com> +Signed-off-by: Michael S. Tsirkin +Reviewed-by: Xie Yongji +Acked-by: Jason Wang +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..597a9e6b36d --- /dev/null +++ b/queue-5.15/virtio_mmio-add-missing-pm-calls-to-freeze-restore.patch @@ -0,0 +1,81 @@ +From d55d5cde1a8d431ac7025f37abed9fa3fd7e3a51 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Jun 2022 13:06:20 +0200 +Subject: virtio_mmio: Add missing PM calls to freeze/restore + +From: Stephan Gerhold + +[ 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 +Message-Id: <20220621110621.3638025-2-stephan.gerhold@kernkonzept.com> +Signed-off-by: Michael S. Tsirkin +Signed-off-by: Sasha Levin +--- + 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 + #include + #include ++#include + #include + #include + #include +@@ -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 index 00000000000..b56d35168a4 --- /dev/null +++ b/queue-5.15/virtio_mmio-restore-guest-page-size-on-resume.patch @@ -0,0 +1,44 @@ +From f40298bbc7d8f82c9fabc092b4348fc6c339ac4e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Jun 2022 13:06:21 +0200 +Subject: virtio_mmio: Restore guest page size on resume + +From: Stephan Gerhold + +[ 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 +Message-Id: <20220621110621.3638025-3-stephan.gerhold@kernkonzept.com> +Signed-off-by: Michael S. Tsirkin +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..fe2e83d3f48 --- /dev/null +++ b/queue-5.15/x86-clear-.brk-area-at-early-boot.patch @@ -0,0 +1,43 @@ +From 70b2534eb4141b760ced46b21940a23e7dae3e3f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 30 Jun 2022 09:14:40 +0200 +Subject: x86: Clear .brk area at early boot + +From: Juergen Gross + +[ 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 +Signed-off-by: Borislav Petkov +Link: https://lore.kernel.org/r/20220630071441.28576-3-jgross@suse.com +Signed-off-by: Sasha Levin +--- + 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 + -- 2.47.3