]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
5.4-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 3 Nov 2020 14:44:38 +0000 (15:44 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 3 Nov 2020 14:44:38 +0000 (15:44 +0100)
added patches:
acpi-button-fix-handling-lid-state-changes-when-input-device-closed.patch
acpi-cpufreq-honor-_psd-table-setting-on-new-amd-cpus.patch
acpi-debug-don-t-allow-debugging-when-acpi-is-disabled.patch
acpi-ec-pm-drop-ec_no_wakeup-check-from-acpi_ec_dispatch_gpe.patch
acpi-ec-pm-flush-ec-work-unconditionally-after-wakeup.patch
acpi-extlog-check-for-rdmsr-failure.patch
acpi-video-use-acpi-backlight-for-hp-635-notebook.patch
btrfs-cleanup-cow-block-on-error.patch
btrfs-fix-readahead-hang-and-use-after-free-after-removing-a-device.patch
btrfs-fix-use-after-free-on-readahead-extent-after-failure-to-create-it.patch
btrfs-improve-device-scanning-messages.patch
btrfs-qgroup-fix-wrong-qgroup-metadata-reserve-for-delayed-inode.patch
btrfs-reschedule-if-necessary-when-logging-directory-items.patch
btrfs-send-orphanize-first-all-conflicting-inodes-when-processing-references.patch
btrfs-send-recompute-reference-path-after-orphanization-of-a-directory.patch
btrfs-tree-checker-fix-false-alert-caused-by-legacy-btrfs-root-item.patch
btrfs-tree-checker-validate-number-of-chunk-stripes-and-parity.patch
btrfs-use-kvzalloc-to-allocate-clone_roots-in-btrfs_ioctl_send.patch
dmaengine-dma-jz4780-fix-race-in-jz4780_dma_tx_status.patch
drm-i915-force-vt-d-workarounds-when-running-as-a-guest-os.patch
extcon-ptn5150-fix-usage-of-atomic-gpio-with-sleeping-gpio-chips.patch
fs-don-t-invalidate-page-buffers-in-block_write_full_page.patch
hid-wacom-avoid-entering-wacom_wac_pen_report-for-pad-battery.patch
iio-adc-gyroadc-fix-leak-of-device-node-iterator.patch
iio-adc-ti-adc0832-fix-alignment-issue-with-timestamp.patch
iio-adc-ti-adc12138-fix-alignment-issue-with-timestamp.patch
iio-gyro-itg3200-fix-timestamp-alignment-and-prevent-data-leak.patch
iio-light-si1145-fix-timestamp-alignment-and-prevent-data-leak.patch
leds-bcm6328-bcm6358-use-devres-led-registering-function.patch
media-uvcvideo-fix-uvc_ctrl_fixup_xu_info-not-having-any-effect.patch
mips-dec-restore-bootmem-reservation-for-firmware-working-memory-area.patch
nfs-fix-nfs_path-in-case-of-a-rename-retry.patch
nfsd-add-missing-nfsv2-.pc_func-methods.patch
nfsv4-wait-for-stateid-updates-after-close-open_downgrade.patch
nfsv4.2-support-exchgid4_flag_supp_fence_ops-4.2-exchange_id-flag.patch
pci-acpi-whitelist-hotplug-ports-for-d3-if-power-managed-by-acpi.patch
pm-runtime-remove-link-state-checks-in-rpm_get-put_supplier.patch
powerpc-drmem-make-lmb_size-64-bit.patch
powerpc-fix-undetected-data-corruption-with-p9n-dd2.1-vsx-ci-load-emulation.patch
powerpc-memhotplug-make-lmb-size-64bit.patch
powerpc-powermac-fix-low_sleep_handler-with-kuap-and-kuep.patch
powerpc-powernv-elog-fix-race-while-processing-opal-error-log-event.patch
powerpc-rtas-restrict-rtas-requests-from-userspace.patch
powerpc-warn-about-use-of-smt_snooze_delay.patch
s390-stp-add-locking-to-sysfs-functions.patch
scsi-mptfusion-fix-null-pointer-dereferences-in-mptscsih_remove.patch
scsi-qla2xxx-fix-crash-on-session-cleanup-with-unload.patch
ubifs-dent-fix-some-potential-memory-leaks-while-iterating-entries.patch
ubifs-don-t-parse-authentication-mount-options-in-remount-process.patch
ubifs-fix-a-memleak-after-dumping-authentication-mount-options.patch
ubifs-journal-make-sure-to-not-dirty-twice-for-auth-nodes.patch
ubifs-mount_ubifs-release-authentication-resource-in-error-handling-path.patch
ubifs-xattr-fix-some-potential-memory-leaks-while-iterating-entries.patch
udf-fix-memory-leak-when-mounting.patch
usb-cdc-acm-fix-cooldown-mechanism.patch
usb-dwc3-core-add-phy-cleanup-for-probe-error-handling.patch
usb-dwc3-core-don-t-trigger-runtime-pm-when-remove-driver.patch
usb-dwc3-ep0-fix-zlp-for-out-ep0-requests.patch
usb-dwc3-gadget-check-mps-of-the-request-length.patch
usb-dwc3-gadget-end_transfer-before-clear_stall-command.patch
usb-dwc3-gadget-resume-pending-requests-after-clear_stall.patch
usb-dwc3-pci-allow-elkhart-lake-to-utilize-dsm-method-for-pm-functionality.patch
usb-host-fsl-mph-dr-of-check-return-of-dma_set_mask.patch
usb-typec-tcpm-reset-hard_reset_count-for-any-disconnect.patch
usb-xhci-workaround-for-s3-issue-on-amd-snps-3.0-xhc.patch
vt-keyboard-extend-func_buf_lock-to-readers.patch
vt-keyboard-simplify-vt_kdgkbsent.patch
w1-mxc_w1-fix-timeout-resolution-problem-leading-to-bus-error.patch

69 files changed:
queue-5.4/acpi-button-fix-handling-lid-state-changes-when-input-device-closed.patch [new file with mode: 0644]
queue-5.4/acpi-cpufreq-honor-_psd-table-setting-on-new-amd-cpus.patch [new file with mode: 0644]
queue-5.4/acpi-debug-don-t-allow-debugging-when-acpi-is-disabled.patch [new file with mode: 0644]
queue-5.4/acpi-ec-pm-drop-ec_no_wakeup-check-from-acpi_ec_dispatch_gpe.patch [new file with mode: 0644]
queue-5.4/acpi-ec-pm-flush-ec-work-unconditionally-after-wakeup.patch [new file with mode: 0644]
queue-5.4/acpi-extlog-check-for-rdmsr-failure.patch [new file with mode: 0644]
queue-5.4/acpi-video-use-acpi-backlight-for-hp-635-notebook.patch [new file with mode: 0644]
queue-5.4/btrfs-cleanup-cow-block-on-error.patch [new file with mode: 0644]
queue-5.4/btrfs-fix-readahead-hang-and-use-after-free-after-removing-a-device.patch [new file with mode: 0644]
queue-5.4/btrfs-fix-use-after-free-on-readahead-extent-after-failure-to-create-it.patch [new file with mode: 0644]
queue-5.4/btrfs-improve-device-scanning-messages.patch [new file with mode: 0644]
queue-5.4/btrfs-qgroup-fix-wrong-qgroup-metadata-reserve-for-delayed-inode.patch [new file with mode: 0644]
queue-5.4/btrfs-reschedule-if-necessary-when-logging-directory-items.patch [new file with mode: 0644]
queue-5.4/btrfs-send-orphanize-first-all-conflicting-inodes-when-processing-references.patch [new file with mode: 0644]
queue-5.4/btrfs-send-recompute-reference-path-after-orphanization-of-a-directory.patch [new file with mode: 0644]
queue-5.4/btrfs-tree-checker-fix-false-alert-caused-by-legacy-btrfs-root-item.patch [new file with mode: 0644]
queue-5.4/btrfs-tree-checker-validate-number-of-chunk-stripes-and-parity.patch [new file with mode: 0644]
queue-5.4/btrfs-use-kvzalloc-to-allocate-clone_roots-in-btrfs_ioctl_send.patch [new file with mode: 0644]
queue-5.4/dmaengine-dma-jz4780-fix-race-in-jz4780_dma_tx_status.patch [new file with mode: 0644]
queue-5.4/drm-i915-force-vt-d-workarounds-when-running-as-a-guest-os.patch [new file with mode: 0644]
queue-5.4/extcon-ptn5150-fix-usage-of-atomic-gpio-with-sleeping-gpio-chips.patch [new file with mode: 0644]
queue-5.4/fs-don-t-invalidate-page-buffers-in-block_write_full_page.patch [new file with mode: 0644]
queue-5.4/hid-wacom-avoid-entering-wacom_wac_pen_report-for-pad-battery.patch [new file with mode: 0644]
queue-5.4/iio-adc-gyroadc-fix-leak-of-device-node-iterator.patch [new file with mode: 0644]
queue-5.4/iio-adc-ti-adc0832-fix-alignment-issue-with-timestamp.patch [new file with mode: 0644]
queue-5.4/iio-adc-ti-adc12138-fix-alignment-issue-with-timestamp.patch [new file with mode: 0644]
queue-5.4/iio-gyro-itg3200-fix-timestamp-alignment-and-prevent-data-leak.patch [new file with mode: 0644]
queue-5.4/iio-light-si1145-fix-timestamp-alignment-and-prevent-data-leak.patch [new file with mode: 0644]
queue-5.4/leds-bcm6328-bcm6358-use-devres-led-registering-function.patch [new file with mode: 0644]
queue-5.4/media-uvcvideo-fix-uvc_ctrl_fixup_xu_info-not-having-any-effect.patch [new file with mode: 0644]
queue-5.4/mips-dec-restore-bootmem-reservation-for-firmware-working-memory-area.patch [new file with mode: 0644]
queue-5.4/nfs-fix-nfs_path-in-case-of-a-rename-retry.patch [new file with mode: 0644]
queue-5.4/nfsd-add-missing-nfsv2-.pc_func-methods.patch [new file with mode: 0644]
queue-5.4/nfsv4-wait-for-stateid-updates-after-close-open_downgrade.patch [new file with mode: 0644]
queue-5.4/nfsv4.2-support-exchgid4_flag_supp_fence_ops-4.2-exchange_id-flag.patch [new file with mode: 0644]
queue-5.4/pci-acpi-whitelist-hotplug-ports-for-d3-if-power-managed-by-acpi.patch [new file with mode: 0644]
queue-5.4/pm-runtime-remove-link-state-checks-in-rpm_get-put_supplier.patch [new file with mode: 0644]
queue-5.4/powerpc-drmem-make-lmb_size-64-bit.patch [new file with mode: 0644]
queue-5.4/powerpc-fix-undetected-data-corruption-with-p9n-dd2.1-vsx-ci-load-emulation.patch [new file with mode: 0644]
queue-5.4/powerpc-memhotplug-make-lmb-size-64bit.patch [new file with mode: 0644]
queue-5.4/powerpc-powermac-fix-low_sleep_handler-with-kuap-and-kuep.patch [new file with mode: 0644]
queue-5.4/powerpc-powernv-elog-fix-race-while-processing-opal-error-log-event.patch [new file with mode: 0644]
queue-5.4/powerpc-rtas-restrict-rtas-requests-from-userspace.patch [new file with mode: 0644]
queue-5.4/powerpc-warn-about-use-of-smt_snooze_delay.patch [new file with mode: 0644]
queue-5.4/s390-stp-add-locking-to-sysfs-functions.patch [new file with mode: 0644]
queue-5.4/scsi-mptfusion-fix-null-pointer-dereferences-in-mptscsih_remove.patch [new file with mode: 0644]
queue-5.4/scsi-qla2xxx-fix-crash-on-session-cleanup-with-unload.patch [new file with mode: 0644]
queue-5.4/series
queue-5.4/ubifs-dent-fix-some-potential-memory-leaks-while-iterating-entries.patch [new file with mode: 0644]
queue-5.4/ubifs-don-t-parse-authentication-mount-options-in-remount-process.patch [new file with mode: 0644]
queue-5.4/ubifs-fix-a-memleak-after-dumping-authentication-mount-options.patch [new file with mode: 0644]
queue-5.4/ubifs-journal-make-sure-to-not-dirty-twice-for-auth-nodes.patch [new file with mode: 0644]
queue-5.4/ubifs-mount_ubifs-release-authentication-resource-in-error-handling-path.patch [new file with mode: 0644]
queue-5.4/ubifs-xattr-fix-some-potential-memory-leaks-while-iterating-entries.patch [new file with mode: 0644]
queue-5.4/udf-fix-memory-leak-when-mounting.patch [new file with mode: 0644]
queue-5.4/usb-cdc-acm-fix-cooldown-mechanism.patch [new file with mode: 0644]
queue-5.4/usb-dwc3-core-add-phy-cleanup-for-probe-error-handling.patch [new file with mode: 0644]
queue-5.4/usb-dwc3-core-don-t-trigger-runtime-pm-when-remove-driver.patch [new file with mode: 0644]
queue-5.4/usb-dwc3-ep0-fix-zlp-for-out-ep0-requests.patch [new file with mode: 0644]
queue-5.4/usb-dwc3-gadget-check-mps-of-the-request-length.patch [new file with mode: 0644]
queue-5.4/usb-dwc3-gadget-end_transfer-before-clear_stall-command.patch [new file with mode: 0644]
queue-5.4/usb-dwc3-gadget-resume-pending-requests-after-clear_stall.patch [new file with mode: 0644]
queue-5.4/usb-dwc3-pci-allow-elkhart-lake-to-utilize-dsm-method-for-pm-functionality.patch [new file with mode: 0644]
queue-5.4/usb-host-fsl-mph-dr-of-check-return-of-dma_set_mask.patch [new file with mode: 0644]
queue-5.4/usb-typec-tcpm-reset-hard_reset_count-for-any-disconnect.patch [new file with mode: 0644]
queue-5.4/usb-xhci-workaround-for-s3-issue-on-amd-snps-3.0-xhc.patch [new file with mode: 0644]
queue-5.4/vt-keyboard-extend-func_buf_lock-to-readers.patch [new file with mode: 0644]
queue-5.4/vt-keyboard-simplify-vt_kdgkbsent.patch [new file with mode: 0644]
queue-5.4/w1-mxc_w1-fix-timeout-resolution-problem-leading-to-bus-error.patch [new file with mode: 0644]

diff --git a/queue-5.4/acpi-button-fix-handling-lid-state-changes-when-input-device-closed.patch b/queue-5.4/acpi-button-fix-handling-lid-state-changes-when-input-device-closed.patch
new file mode 100644 (file)
index 0000000..7df6176
--- /dev/null
@@ -0,0 +1,88 @@
+From 21988a8e51479ceffe7b0568b170effabb708dfe Mon Sep 17 00:00:00 2001
+From: "dmitry.torokhov@gmail.com" <dmitry.torokhov@gmail.com>
+Date: Sun, 4 Oct 2020 22:11:25 -0700
+Subject: ACPI: button: fix handling lid state changes when input device closed
+
+From: dmitry.torokhov@gmail.com <dmitry.torokhov@gmail.com>
+
+commit 21988a8e51479ceffe7b0568b170effabb708dfe upstream.
+
+The original intent of 84d3f6b76447 was to delay evaluating lid state until
+all drivers have been loaded, with input device being opened from userspace
+serving as a signal for this condition. Let's ensure that state updates
+happen even if userspace closed (or in the future inhibited) input device.
+
+Note that if we go through suspend/resume cycle we assume the system has
+been fully initialized even if LID input device has not been opened yet.
+
+This has a side-effect of fixing access to input->users outside of
+input->mutex protections by the way of eliminating said accesses and using
+driver private flag.
+
+Fixes: 84d3f6b76447 ("ACPI / button: Delay acpi_lid_initialize_state() until first user space open")
+Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
+Reviewed-by: Hans de Goede <hdegoede@redhat.com>
+Cc: 4.15+ <stable@vger.kernel.org> # 4.15+
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/acpi/button.c |   13 +++++++------
+ 1 file changed, 7 insertions(+), 6 deletions(-)
+
+--- a/drivers/acpi/button.c
++++ b/drivers/acpi/button.c
+@@ -136,6 +136,7 @@ struct acpi_button {
+       int last_state;
+       ktime_t last_time;
+       bool suspended;
++      bool lid_state_initialized;
+ };
+ static BLOCKING_NOTIFIER_HEAD(acpi_lid_notifier);
+@@ -391,6 +392,8 @@ static int acpi_lid_update_state(struct
+ static void acpi_lid_initialize_state(struct acpi_device *device)
+ {
++      struct acpi_button *button = acpi_driver_data(device);
++
+       switch (lid_init_state) {
+       case ACPI_BUTTON_LID_INIT_OPEN:
+               (void)acpi_lid_notify_state(device, 1);
+@@ -402,13 +405,14 @@ static void acpi_lid_initialize_state(st
+       default:
+               break;
+       }
++
++      button->lid_state_initialized = true;
+ }
+ static void acpi_button_notify(struct acpi_device *device, u32 event)
+ {
+       struct acpi_button *button = acpi_driver_data(device);
+       struct input_dev *input;
+-      int users;
+       switch (event) {
+       case ACPI_FIXED_HARDWARE_EVENT:
+@@ -417,10 +421,7 @@ static void acpi_button_notify(struct ac
+       case ACPI_BUTTON_NOTIFY_STATUS:
+               input = button->input;
+               if (button->type == ACPI_BUTTON_TYPE_LID) {
+-                      mutex_lock(&button->input->mutex);
+-                      users = button->input->users;
+-                      mutex_unlock(&button->input->mutex);
+-                      if (users)
++                      if (button->lid_state_initialized)
+                               acpi_lid_update_state(device, true);
+               } else {
+                       int keycode;
+@@ -465,7 +466,7 @@ static int acpi_button_resume(struct dev
+       struct acpi_button *button = acpi_driver_data(device);
+       button->suspended = false;
+-      if (button->type == ACPI_BUTTON_TYPE_LID && button->input->users) {
++      if (button->type == ACPI_BUTTON_TYPE_LID) {
+               button->last_state = !!acpi_lid_evaluate_state(device);
+               button->last_time = ktime_get();
+               acpi_lid_initialize_state(device);
diff --git a/queue-5.4/acpi-cpufreq-honor-_psd-table-setting-on-new-amd-cpus.patch b/queue-5.4/acpi-cpufreq-honor-_psd-table-setting-on-new-amd-cpus.patch
new file mode 100644 (file)
index 0000000..f4226b9
--- /dev/null
@@ -0,0 +1,37 @@
+From 5368512abe08a28525d9b24abbfc2a72493e8dba Mon Sep 17 00:00:00 2001
+From: Wei Huang <wei.huang2@amd.com>
+Date: Sun, 18 Oct 2020 22:57:41 -0500
+Subject: acpi-cpufreq: Honor _PSD table setting on new AMD CPUs
+
+From: Wei Huang <wei.huang2@amd.com>
+
+commit 5368512abe08a28525d9b24abbfc2a72493e8dba upstream.
+
+acpi-cpufreq has a old quirk that overrides the _PSD table supplied by
+BIOS on AMD CPUs. However the _PSD table of new AMD CPUs (Family 19h+)
+now accurately reports the P-state dependency of CPU cores. Hence this
+quirk needs to be fixed in order to support new CPUs' frequency control.
+
+Fixes: acd316248205 ("acpi-cpufreq: Add quirk to disable _PSD usage on all AMD CPUs")
+Signed-off-by: Wei Huang <wei.huang2@amd.com>
+[ rjw: Subject edit ]
+Cc: 3.10+ <stable@vger.kernel.org> # 3.10+
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/cpufreq/acpi-cpufreq.c |    3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/cpufreq/acpi-cpufreq.c
++++ b/drivers/cpufreq/acpi-cpufreq.c
+@@ -688,7 +688,8 @@ static int acpi_cpufreq_cpu_init(struct
+               cpumask_copy(policy->cpus, topology_core_cpumask(cpu));
+       }
+-      if (check_amd_hwpstate_cpu(cpu) && !acpi_pstate_strict) {
++      if (check_amd_hwpstate_cpu(cpu) && boot_cpu_data.x86 < 0x19 &&
++          !acpi_pstate_strict) {
+               cpumask_clear(policy->cpus);
+               cpumask_set_cpu(cpu, policy->cpus);
+               cpumask_copy(data->freqdomain_cpus,
diff --git a/queue-5.4/acpi-debug-don-t-allow-debugging-when-acpi-is-disabled.patch b/queue-5.4/acpi-debug-don-t-allow-debugging-when-acpi-is-disabled.patch
new file mode 100644 (file)
index 0000000..e605918
--- /dev/null
@@ -0,0 +1,68 @@
+From 0fada277147ffc6d694aa32162f51198d4f10d94 Mon Sep 17 00:00:00 2001
+From: Jamie Iles <jamie@nuviainc.com>
+Date: Mon, 12 Oct 2020 14:04:46 +0100
+Subject: ACPI: debug: don't allow debugging when ACPI is disabled
+
+From: Jamie Iles <jamie@nuviainc.com>
+
+commit 0fada277147ffc6d694aa32162f51198d4f10d94 upstream.
+
+If ACPI is disabled then loading the acpi_dbg module will result in the
+following splat when lock debugging is enabled.
+
+  DEBUG_LOCKS_WARN_ON(lock->magic != lock)
+  WARNING: CPU: 0 PID: 1 at kernel/locking/mutex.c:938 __mutex_lock+0xa10/0x1290
+  Kernel panic - not syncing: panic_on_warn set ...
+  CPU: 0 PID: 1 Comm: swapper/0 Not tainted 5.9.0-rc8+ #103
+  Hardware name: linux,dummy-virt (DT)
+  Call trace:
+   dump_backtrace+0x0/0x4d8
+   show_stack+0x34/0x48
+   dump_stack+0x174/0x1f8
+   panic+0x360/0x7a0
+   __warn+0x244/0x2ec
+   report_bug+0x240/0x398
+   bug_handler+0x50/0xc0
+   call_break_hook+0x160/0x1d8
+   brk_handler+0x30/0xc0
+   do_debug_exception+0x184/0x340
+   el1_dbg+0x48/0xb0
+   el1_sync_handler+0x170/0x1c8
+   el1_sync+0x80/0x100
+   __mutex_lock+0xa10/0x1290
+   mutex_lock_nested+0x6c/0xc0
+   acpi_register_debugger+0x40/0x88
+   acpi_aml_init+0xc4/0x114
+   do_one_initcall+0x24c/0xb10
+   kernel_init_freeable+0x690/0x728
+   kernel_init+0x20/0x1e8
+   ret_from_fork+0x10/0x18
+
+This is because acpi_debugger.lock has not been initialized as
+acpi_debugger_init() is not called when ACPI is disabled.  Fail module
+loading to avoid this and any subsequent problems that might arise by
+trying to debug AML when ACPI is disabled.
+
+Fixes: 8cfb0cdf07e2 ("ACPI / debugger: Add IO interface to access debugger functionalities")
+Reviewed-by: Hanjun Guo <guohanjun@huawei.com>
+Signed-off-by: Jamie Iles <jamie@nuviainc.com>
+Cc: 4.10+ <stable@vger.kernel.org> # 4.10+
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/acpi/acpi_dbg.c |    3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/drivers/acpi/acpi_dbg.c
++++ b/drivers/acpi/acpi_dbg.c
+@@ -749,6 +749,9 @@ int __init acpi_aml_init(void)
+ {
+       int ret;
++      if (acpi_disabled)
++              return -ENODEV;
++
+       /* Initialize AML IO interface */
+       mutex_init(&acpi_aml_io.lock);
+       init_waitqueue_head(&acpi_aml_io.wait);
diff --git a/queue-5.4/acpi-ec-pm-drop-ec_no_wakeup-check-from-acpi_ec_dispatch_gpe.patch b/queue-5.4/acpi-ec-pm-drop-ec_no_wakeup-check-from-acpi_ec_dispatch_gpe.patch
new file mode 100644 (file)
index 0000000..1fc5d60
--- /dev/null
@@ -0,0 +1,36 @@
+From e0e9ce390d7bc6a705653d4a8aa4ea92c9a65e53 Mon Sep 17 00:00:00 2001
+From: "Rafael J. Wysocki" <rafael.j.wysocki@intel.com>
+Date: Mon, 5 Oct 2020 19:13:46 +0200
+Subject: ACPI: EC: PM: Drop ec_no_wakeup check from acpi_ec_dispatch_gpe()
+
+From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+
+commit e0e9ce390d7bc6a705653d4a8aa4ea92c9a65e53 upstream.
+
+It turns out that in some cases there are EC events to flush in
+acpi_ec_dispatch_gpe() even though the ec_no_wakeup kernel parameter
+is set and the EC GPE is disabled while sleeping, so drop the
+ec_no_wakeup check that prevents those events from being processed
+from acpi_ec_dispatch_gpe().
+
+Reported-by: Todd Brandt <todd.e.brandt@linux.intel.com>
+Cc: 5.4+ <stable@vger.kernel.org> # 5.4+
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/acpi/ec.c |    3 ---
+ 1 file changed, 3 deletions(-)
+
+--- a/drivers/acpi/ec.c
++++ b/drivers/acpi/ec.c
+@@ -1968,9 +1968,6 @@ bool acpi_ec_dispatch_gpe(void)
+       if (acpi_any_gpe_status_set(first_ec->gpe))
+               return true;
+-      if (ec_no_wakeup)
+-              return false;
+-
+       /*
+        * Dispatch the EC GPE in-band, but do not report wakeup in any case
+        * to allow the caller to process events properly after that.
diff --git a/queue-5.4/acpi-ec-pm-flush-ec-work-unconditionally-after-wakeup.patch b/queue-5.4/acpi-ec-pm-flush-ec-work-unconditionally-after-wakeup.patch
new file mode 100644 (file)
index 0000000..d339f34
--- /dev/null
@@ -0,0 +1,46 @@
+From 5e92442bb4121562231e6daf8a2d1306cb5f8805 Mon Sep 17 00:00:00 2001
+From: "Rafael J. Wysocki" <rafael.j.wysocki@intel.com>
+Date: Mon, 5 Oct 2020 19:13:15 +0200
+Subject: ACPI: EC: PM: Flush EC work unconditionally after wakeup
+
+From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+
+commit 5e92442bb4121562231e6daf8a2d1306cb5f8805 upstream.
+
+Commit 607b9df63057 ("ACPI: EC: PM: Avoid flushing EC work when EC
+GPE is inactive") has been reported to cause some power button wakeup
+events to be missed on some systems, so modify acpi_ec_dispatch_gpe()
+to call acpi_ec_flush_work() unconditionally to effectively reverse
+the changes made by that commit.
+
+Also note that the problem which prompted commit 607b9df63057 is not
+reproducible any more on the affected machine.
+
+Fixes: 607b9df63057 ("ACPI: EC: PM: Avoid flushing EC work when EC GPE is inactive")
+Reported-by: Raymond Tan <raymond.tan@intel.com>
+Cc: 5.4+ <stable@vger.kernel.org> # 5.4+
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/acpi/ec.c |    7 +++----
+ 1 file changed, 3 insertions(+), 4 deletions(-)
+
+--- a/drivers/acpi/ec.c
++++ b/drivers/acpi/ec.c
+@@ -1976,12 +1976,11 @@ bool acpi_ec_dispatch_gpe(void)
+        * to allow the caller to process events properly after that.
+        */
+       ret = acpi_dispatch_gpe(NULL, first_ec->gpe);
+-      if (ret == ACPI_INTERRUPT_HANDLED) {
++      if (ret == ACPI_INTERRUPT_HANDLED)
+               pm_pr_dbg("EC GPE dispatched\n");
+-              /* Flush the event and query workqueues. */
+-              acpi_ec_flush_work();
+-      }
++      /* Flush the event and query workqueues. */
++      acpi_ec_flush_work();
+       return false;
+ }
diff --git a/queue-5.4/acpi-extlog-check-for-rdmsr-failure.patch b/queue-5.4/acpi-extlog-check-for-rdmsr-failure.patch
new file mode 100644 (file)
index 0000000..77ab16e
--- /dev/null
@@ -0,0 +1,42 @@
+From 7cecb47f55e00282f972a1e0b09136c8cd938221 Mon Sep 17 00:00:00 2001
+From: Ben Hutchings <ben@decadent.org.uk>
+Date: Sun, 27 Sep 2020 22:50:42 +0100
+Subject: ACPI / extlog: Check for RDMSR failure
+
+From: Ben Hutchings <ben@decadent.org.uk>
+
+commit 7cecb47f55e00282f972a1e0b09136c8cd938221 upstream.
+
+extlog_init() uses rdmsrl() to read an MSR, which on older CPUs
+provokes a error message at boot:
+
+    unchecked MSR access error: RDMSR from 0x179 at rIP: 0xcd047307 (native_read_msr+0x7/0x40)
+
+Use rdmsrl_safe() instead, and return -ENODEV if it fails.
+
+Reported-by: jim@photojim.ca
+References: https://bugs.debian.org/971058
+Cc: All applicable <stable@vger.kernel.org>
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/acpi/acpi_extlog.c |    6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+--- a/drivers/acpi/acpi_extlog.c
++++ b/drivers/acpi/acpi_extlog.c
+@@ -223,9 +223,9 @@ static int __init extlog_init(void)
+       u64 cap;
+       int rc;
+-      rdmsrl(MSR_IA32_MCG_CAP, cap);
+-
+-      if (!(cap & MCG_ELOG_P) || !extlog_get_l1addr())
++      if (rdmsrl_safe(MSR_IA32_MCG_CAP, &cap) ||
++          !(cap & MCG_ELOG_P) ||
++          !extlog_get_l1addr())
+               return -ENODEV;
+       if (edac_get_report_status() == EDAC_REPORTING_FORCE) {
diff --git a/queue-5.4/acpi-video-use-acpi-backlight-for-hp-635-notebook.patch b/queue-5.4/acpi-video-use-acpi-backlight-for-hp-635-notebook.patch
new file mode 100644 (file)
index 0000000..a705a93
--- /dev/null
@@ -0,0 +1,42 @@
+From b226faab4e7890bbbccdf794e8b94276414f9058 Mon Sep 17 00:00:00 2001
+From: Alex Hung <alex.hung@canonical.com>
+Date: Sun, 13 Sep 2020 16:34:03 -0600
+Subject: ACPI: video: use ACPI backlight for HP 635 Notebook
+
+From: Alex Hung <alex.hung@canonical.com>
+
+commit b226faab4e7890bbbccdf794e8b94276414f9058 upstream.
+
+The default backlight interface is AMD's radeon_bl0 which does not
+work on this system, so use the ACPI backlight interface on it
+instead.
+
+BugLink: https://bugs.launchpad.net/bugs/1894667
+Cc: All applicable <stable@vger.kernel.org>
+Signed-off-by: Alex Hung <alex.hung@canonical.com>
+[ rjw: Changelog edits ]
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/acpi/video_detect.c |    9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+--- a/drivers/acpi/video_detect.c
++++ b/drivers/acpi/video_detect.c
+@@ -282,6 +282,15 @@ static const struct dmi_system_id video_
+               DMI_MATCH(DMI_PRODUCT_NAME, "530U4E/540U4E"),
+               },
+       },
++      /* https://bugs.launchpad.net/bugs/1894667 */
++      {
++       .callback = video_detect_force_video,
++       .ident = "HP 635 Notebook",
++       .matches = {
++              DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
++              DMI_MATCH(DMI_PRODUCT_NAME, "HP 635 Notebook PC"),
++              },
++      },
+       /* Non win8 machines which need native backlight nevertheless */
+       {
diff --git a/queue-5.4/btrfs-cleanup-cow-block-on-error.patch b/queue-5.4/btrfs-cleanup-cow-block-on-error.patch
new file mode 100644 (file)
index 0000000..2d04200
--- /dev/null
@@ -0,0 +1,135 @@
+From 572c83acdcdafeb04e70aa46be1fa539310be20c Mon Sep 17 00:00:00 2001
+From: Josef Bacik <josef@toxicpanda.com>
+Date: Tue, 29 Sep 2020 08:53:54 -0400
+Subject: btrfs: cleanup cow block on error
+
+From: Josef Bacik <josef@toxicpanda.com>
+
+commit 572c83acdcdafeb04e70aa46be1fa539310be20c upstream.
+
+In fstest btrfs/064 a transaction abort in __btrfs_cow_block could lead
+to a system lockup. It gets stuck trying to write back inodes, and the
+write back thread was trying to lock an extent buffer:
+
+  $ cat /proc/2143497/stack
+  [<0>] __btrfs_tree_lock+0x108/0x250
+  [<0>] lock_extent_buffer_for_io+0x35e/0x3a0
+  [<0>] btree_write_cache_pages+0x15a/0x3b0
+  [<0>] do_writepages+0x28/0xb0
+  [<0>] __writeback_single_inode+0x54/0x5c0
+  [<0>] writeback_sb_inodes+0x1e8/0x510
+  [<0>] wb_writeback+0xcc/0x440
+  [<0>] wb_workfn+0xd7/0x650
+  [<0>] process_one_work+0x236/0x560
+  [<0>] worker_thread+0x55/0x3c0
+  [<0>] kthread+0x13a/0x150
+  [<0>] ret_from_fork+0x1f/0x30
+
+This is because we got an error while COWing a block, specifically here
+
+        if (test_bit(BTRFS_ROOT_SHAREABLE, &root->state)) {
+                ret = btrfs_reloc_cow_block(trans, root, buf, cow);
+                if (ret) {
+                        btrfs_abort_transaction(trans, ret);
+                        return ret;
+                }
+        }
+
+  [16402.241552] BTRFS: Transaction aborted (error -2)
+  [16402.242362] WARNING: CPU: 1 PID: 2563188 at fs/btrfs/ctree.c:1074 __btrfs_cow_block+0x376/0x540
+  [16402.249469] CPU: 1 PID: 2563188 Comm: fsstress Not tainted 5.9.0-rc6+ #8
+  [16402.249936] Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.13.0-2.fc32 04/01/2014
+  [16402.250525] RIP: 0010:__btrfs_cow_block+0x376/0x540
+  [16402.252417] RSP: 0018:ffff9cca40e578b0 EFLAGS: 00010282
+  [16402.252787] RAX: 0000000000000025 RBX: 0000000000000002 RCX: ffff9132bbd19388
+  [16402.253278] RDX: 00000000ffffffd8 RSI: 0000000000000027 RDI: ffff9132bbd19380
+  [16402.254063] RBP: ffff9132b41a49c0 R08: 0000000000000000 R09: 0000000000000000
+  [16402.254887] R10: 0000000000000000 R11: ffff91324758b080 R12: ffff91326ef17ce0
+  [16402.255694] R13: ffff91325fc0f000 R14: ffff91326ef176b0 R15: ffff9132815e2000
+  [16402.256321] FS:  00007f542c6d7b80(0000) GS:ffff9132bbd00000(0000) knlGS:0000000000000000
+  [16402.256973] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+  [16402.257374] CR2: 00007f127b83f250 CR3: 0000000133480002 CR4: 0000000000370ee0
+  [16402.257867] Call Trace:
+  [16402.258072]  btrfs_cow_block+0x109/0x230
+  [16402.258356]  btrfs_search_slot+0x530/0x9d0
+  [16402.258655]  btrfs_lookup_file_extent+0x37/0x40
+  [16402.259155]  __btrfs_drop_extents+0x13c/0xd60
+  [16402.259628]  ? btrfs_block_rsv_migrate+0x4f/0xb0
+  [16402.259949]  btrfs_replace_file_extents+0x190/0x820
+  [16402.260873]  btrfs_clone+0x9ae/0xc00
+  [16402.261139]  btrfs_extent_same_range+0x66/0x90
+  [16402.261771]  btrfs_remap_file_range+0x353/0x3b1
+  [16402.262333]  vfs_dedupe_file_range_one.part.0+0xd5/0x140
+  [16402.262821]  vfs_dedupe_file_range+0x189/0x220
+  [16402.263150]  do_vfs_ioctl+0x552/0x700
+  [16402.263662]  __x64_sys_ioctl+0x62/0xb0
+  [16402.264023]  do_syscall_64+0x33/0x40
+  [16402.264364]  entry_SYSCALL_64_after_hwframe+0x44/0xa9
+  [16402.264862] RIP: 0033:0x7f542c7d15cb
+  [16402.266901] RSP: 002b:00007ffd35944ea8 EFLAGS: 00000246 ORIG_RAX: 0000000000000010
+  [16402.267627] RAX: ffffffffffffffda RBX: 00000000009d1968 RCX: 00007f542c7d15cb
+  [16402.268298] RDX: 00000000009d2490 RSI: 00000000c0189436 RDI: 0000000000000003
+  [16402.268958] RBP: 00000000009d2520 R08: 0000000000000036 R09: 00000000009d2e64
+  [16402.269726] R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000002
+  [16402.270659] R13: 000000000001f000 R14: 00000000009d1970 R15: 00000000009d2e80
+  [16402.271498] irq event stamp: 0
+  [16402.271846] hardirqs last  enabled at (0): [<0000000000000000>] 0x0
+  [16402.272497] hardirqs last disabled at (0): [<ffffffff910dbf59>] copy_process+0x6b9/0x1ba0
+  [16402.273343] softirqs last  enabled at (0): [<ffffffff910dbf59>] copy_process+0x6b9/0x1ba0
+  [16402.273905] softirqs last disabled at (0): [<0000000000000000>] 0x0
+  [16402.274338] ---[ end trace 737874a5a41a8236 ]---
+  [16402.274669] BTRFS: error (device dm-9) in __btrfs_cow_block:1074: errno=-2 No such entry
+  [16402.276179] BTRFS info (device dm-9): forced readonly
+  [16402.277046] BTRFS: error (device dm-9) in btrfs_replace_file_extents:2723: errno=-2 No such entry
+  [16402.278744] BTRFS: error (device dm-9) in __btrfs_cow_block:1074: errno=-2 No such entry
+  [16402.279968] BTRFS: error (device dm-9) in __btrfs_cow_block:1074: errno=-2 No such entry
+  [16402.280582] BTRFS info (device dm-9): balance: ended with status: -30
+
+The problem here is that as soon as we allocate the new block it is
+locked and marked dirty in the btree inode.  This means that we could
+attempt to writeback this block and need to lock the extent buffer.
+However we're not unlocking it here and thus we deadlock.
+
+Fix this by unlocking the cow block if we have any errors inside of
+__btrfs_cow_block, and also free it so we do not leak it.
+
+CC: stable@vger.kernel.org # 4.4+
+Reviewed-by: Filipe Manana <fdmanana@suse.com>
+Signed-off-by: Josef Bacik <josef@toxicpanda.com>
+Reviewed-by: David Sterba <dsterba@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/btrfs/ctree.c |    6 ++++++
+ 1 file changed, 6 insertions(+)
+
+--- a/fs/btrfs/ctree.c
++++ b/fs/btrfs/ctree.c
+@@ -1103,6 +1103,8 @@ static noinline int __btrfs_cow_block(st
+       ret = update_ref_for_cow(trans, root, buf, cow, &last_ref);
+       if (ret) {
++              btrfs_tree_unlock(cow);
++              free_extent_buffer(cow);
+               btrfs_abort_transaction(trans, ret);
+               return ret;
+       }
+@@ -1110,6 +1112,8 @@ static noinline int __btrfs_cow_block(st
+       if (test_bit(BTRFS_ROOT_REF_COWS, &root->state)) {
+               ret = btrfs_reloc_cow_block(trans, root, buf, cow);
+               if (ret) {
++                      btrfs_tree_unlock(cow);
++                      free_extent_buffer(cow);
+                       btrfs_abort_transaction(trans, ret);
+                       return ret;
+               }
+@@ -1142,6 +1146,8 @@ static noinline int __btrfs_cow_block(st
+               if (last_ref) {
+                       ret = tree_mod_log_free_eb(buf);
+                       if (ret) {
++                              btrfs_tree_unlock(cow);
++                              free_extent_buffer(cow);
+                               btrfs_abort_transaction(trans, ret);
+                               return ret;
+                       }
diff --git a/queue-5.4/btrfs-fix-readahead-hang-and-use-after-free-after-removing-a-device.patch b/queue-5.4/btrfs-fix-readahead-hang-and-use-after-free-after-removing-a-device.patch
new file mode 100644 (file)
index 0000000..f48c70a
--- /dev/null
@@ -0,0 +1,678 @@
+From 66d204a16c94f24ad08290a7663ab67e7fc04e82 Mon Sep 17 00:00:00 2001
+From: Filipe Manana <fdmanana@suse.com>
+Date: Mon, 12 Oct 2020 11:55:24 +0100
+Subject: btrfs: fix readahead hang and use-after-free after removing a device
+
+From: Filipe Manana <fdmanana@suse.com>
+
+commit 66d204a16c94f24ad08290a7663ab67e7fc04e82 upstream.
+
+Very sporadically I had test case btrfs/069 from fstests hanging (for
+years, it is not a recent regression), with the following traces in
+dmesg/syslog:
+
+  [162301.160628] BTRFS info (device sdc): dev_replace from /dev/sdd (devid 2) to /dev/sdg started
+  [162301.181196] BTRFS info (device sdc): scrub: finished on devid 4 with status: 0
+  [162301.287162] BTRFS info (device sdc): dev_replace from /dev/sdd (devid 2) to /dev/sdg finished
+  [162513.513792] INFO: task btrfs-transacti:1356167 blocked for more than 120 seconds.
+  [162513.514318]       Not tainted 5.9.0-rc6-btrfs-next-69 #1
+  [162513.514522] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
+  [162513.514747] task:btrfs-transacti state:D stack:    0 pid:1356167 ppid:     2 flags:0x00004000
+  [162513.514751] Call Trace:
+  [162513.514761]  __schedule+0x5ce/0xd00
+  [162513.514765]  ? _raw_spin_unlock_irqrestore+0x3c/0x60
+  [162513.514771]  schedule+0x46/0xf0
+  [162513.514844]  wait_current_trans+0xde/0x140 [btrfs]
+  [162513.514850]  ? finish_wait+0x90/0x90
+  [162513.514864]  start_transaction+0x37c/0x5f0 [btrfs]
+  [162513.514879]  transaction_kthread+0xa4/0x170 [btrfs]
+  [162513.514891]  ? btrfs_cleanup_transaction+0x660/0x660 [btrfs]
+  [162513.514894]  kthread+0x153/0x170
+  [162513.514897]  ? kthread_stop+0x2c0/0x2c0
+  [162513.514902]  ret_from_fork+0x22/0x30
+  [162513.514916] INFO: task fsstress:1356184 blocked for more than 120 seconds.
+  [162513.515192]       Not tainted 5.9.0-rc6-btrfs-next-69 #1
+  [162513.515431] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
+  [162513.515680] task:fsstress        state:D stack:    0 pid:1356184 ppid:1356177 flags:0x00004000
+  [162513.515682] Call Trace:
+  [162513.515688]  __schedule+0x5ce/0xd00
+  [162513.515691]  ? _raw_spin_unlock_irqrestore+0x3c/0x60
+  [162513.515697]  schedule+0x46/0xf0
+  [162513.515712]  wait_current_trans+0xde/0x140 [btrfs]
+  [162513.515716]  ? finish_wait+0x90/0x90
+  [162513.515729]  start_transaction+0x37c/0x5f0 [btrfs]
+  [162513.515743]  btrfs_attach_transaction_barrier+0x1f/0x50 [btrfs]
+  [162513.515753]  btrfs_sync_fs+0x61/0x1c0 [btrfs]
+  [162513.515758]  ? __ia32_sys_fdatasync+0x20/0x20
+  [162513.515761]  iterate_supers+0x87/0xf0
+  [162513.515765]  ksys_sync+0x60/0xb0
+  [162513.515768]  __do_sys_sync+0xa/0x10
+  [162513.515771]  do_syscall_64+0x33/0x80
+  [162513.515774]  entry_SYSCALL_64_after_hwframe+0x44/0xa9
+  [162513.515781] RIP: 0033:0x7f5238f50bd7
+  [162513.515782] Code: Bad RIP value.
+  [162513.515784] RSP: 002b:00007fff67b978e8 EFLAGS: 00000206 ORIG_RAX: 00000000000000a2
+  [162513.515786] RAX: ffffffffffffffda RBX: 000055b1fad2c560 RCX: 00007f5238f50bd7
+  [162513.515788] RDX: 00000000ffffffff RSI: 000000000daf0e74 RDI: 000000000000003a
+  [162513.515789] RBP: 0000000000000032 R08: 000000000000000a R09: 00007f5239019be0
+  [162513.515791] R10: fffffffffffff24f R11: 0000000000000206 R12: 000000000000003a
+  [162513.515792] R13: 00007fff67b97950 R14: 00007fff67b97906 R15: 000055b1fad1a340
+  [162513.515804] INFO: task fsstress:1356185 blocked for more than 120 seconds.
+  [162513.516064]       Not tainted 5.9.0-rc6-btrfs-next-69 #1
+  [162513.516329] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
+  [162513.516617] task:fsstress        state:D stack:    0 pid:1356185 ppid:1356177 flags:0x00000000
+  [162513.516620] Call Trace:
+  [162513.516625]  __schedule+0x5ce/0xd00
+  [162513.516628]  ? _raw_spin_unlock_irqrestore+0x3c/0x60
+  [162513.516634]  schedule+0x46/0xf0
+  [162513.516647]  wait_current_trans+0xde/0x140 [btrfs]
+  [162513.516650]  ? finish_wait+0x90/0x90
+  [162513.516662]  start_transaction+0x4d7/0x5f0 [btrfs]
+  [162513.516679]  btrfs_setxattr_trans+0x3c/0x100 [btrfs]
+  [162513.516686]  __vfs_setxattr+0x66/0x80
+  [162513.516691]  __vfs_setxattr_noperm+0x70/0x200
+  [162513.516697]  vfs_setxattr+0x6b/0x120
+  [162513.516703]  setxattr+0x125/0x240
+  [162513.516709]  ? lock_acquire+0xb1/0x480
+  [162513.516712]  ? mnt_want_write+0x20/0x50
+  [162513.516721]  ? rcu_read_lock_any_held+0x8e/0xb0
+  [162513.516723]  ? preempt_count_add+0x49/0xa0
+  [162513.516725]  ? __sb_start_write+0x19b/0x290
+  [162513.516727]  ? preempt_count_add+0x49/0xa0
+  [162513.516732]  path_setxattr+0xba/0xd0
+  [162513.516739]  __x64_sys_setxattr+0x27/0x30
+  [162513.516741]  do_syscall_64+0x33/0x80
+  [162513.516743]  entry_SYSCALL_64_after_hwframe+0x44/0xa9
+  [162513.516745] RIP: 0033:0x7f5238f56d5a
+  [162513.516746] Code: Bad RIP value.
+  [162513.516748] RSP: 002b:00007fff67b97868 EFLAGS: 00000202 ORIG_RAX: 00000000000000bc
+  [162513.516750] RAX: ffffffffffffffda RBX: 0000000000000001 RCX: 00007f5238f56d5a
+  [162513.516751] RDX: 000055b1fbb0d5a0 RSI: 00007fff67b978a0 RDI: 000055b1fbb0d470
+  [162513.516753] RBP: 000055b1fbb0d5a0 R08: 0000000000000001 R09: 00007fff67b97700
+  [162513.516754] R10: 0000000000000004 R11: 0000000000000202 R12: 0000000000000004
+  [162513.516756] R13: 0000000000000024 R14: 0000000000000001 R15: 00007fff67b978a0
+  [162513.516767] INFO: task fsstress:1356196 blocked for more than 120 seconds.
+  [162513.517064]       Not tainted 5.9.0-rc6-btrfs-next-69 #1
+  [162513.517365] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
+  [162513.517763] task:fsstress        state:D stack:    0 pid:1356196 ppid:1356177 flags:0x00004000
+  [162513.517780] Call Trace:
+  [162513.517786]  __schedule+0x5ce/0xd00
+  [162513.517789]  ? _raw_spin_unlock_irqrestore+0x3c/0x60
+  [162513.517796]  schedule+0x46/0xf0
+  [162513.517810]  wait_current_trans+0xde/0x140 [btrfs]
+  [162513.517814]  ? finish_wait+0x90/0x90
+  [162513.517829]  start_transaction+0x37c/0x5f0 [btrfs]
+  [162513.517845]  btrfs_attach_transaction_barrier+0x1f/0x50 [btrfs]
+  [162513.517857]  btrfs_sync_fs+0x61/0x1c0 [btrfs]
+  [162513.517862]  ? __ia32_sys_fdatasync+0x20/0x20
+  [162513.517865]  iterate_supers+0x87/0xf0
+  [162513.517869]  ksys_sync+0x60/0xb0
+  [162513.517872]  __do_sys_sync+0xa/0x10
+  [162513.517875]  do_syscall_64+0x33/0x80
+  [162513.517878]  entry_SYSCALL_64_after_hwframe+0x44/0xa9
+  [162513.517881] RIP: 0033:0x7f5238f50bd7
+  [162513.517883] Code: Bad RIP value.
+  [162513.517885] RSP: 002b:00007fff67b978e8 EFLAGS: 00000206 ORIG_RAX: 00000000000000a2
+  [162513.517887] RAX: ffffffffffffffda RBX: 000055b1fad2c560 RCX: 00007f5238f50bd7
+  [162513.517889] RDX: 0000000000000000 RSI: 000000007660add2 RDI: 0000000000000053
+  [162513.517891] RBP: 0000000000000032 R08: 0000000000000067 R09: 00007f5239019be0
+  [162513.517893] R10: fffffffffffff24f R11: 0000000000000206 R12: 0000000000000053
+  [162513.517895] R13: 00007fff67b97950 R14: 00007fff67b97906 R15: 000055b1fad1a340
+  [162513.517908] INFO: task fsstress:1356197 blocked for more than 120 seconds.
+  [162513.518298]       Not tainted 5.9.0-rc6-btrfs-next-69 #1
+  [162513.518672] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
+  [162513.519157] task:fsstress        state:D stack:    0 pid:1356197 ppid:1356177 flags:0x00000000
+  [162513.519160] Call Trace:
+  [162513.519165]  __schedule+0x5ce/0xd00
+  [162513.519168]  ? _raw_spin_unlock_irqrestore+0x3c/0x60
+  [162513.519174]  schedule+0x46/0xf0
+  [162513.519190]  wait_current_trans+0xde/0x140 [btrfs]
+  [162513.519193]  ? finish_wait+0x90/0x90
+  [162513.519206]  start_transaction+0x4d7/0x5f0 [btrfs]
+  [162513.519222]  btrfs_create+0x57/0x200 [btrfs]
+  [162513.519230]  lookup_open+0x522/0x650
+  [162513.519246]  path_openat+0x2b8/0xa50
+  [162513.519270]  do_filp_open+0x91/0x100
+  [162513.519275]  ? find_held_lock+0x32/0x90
+  [162513.519280]  ? lock_acquired+0x33b/0x470
+  [162513.519285]  ? do_raw_spin_unlock+0x4b/0xc0
+  [162513.519287]  ? _raw_spin_unlock+0x29/0x40
+  [162513.519295]  do_sys_openat2+0x20d/0x2d0
+  [162513.519300]  do_sys_open+0x44/0x80
+  [162513.519304]  do_syscall_64+0x33/0x80
+  [162513.519307]  entry_SYSCALL_64_after_hwframe+0x44/0xa9
+  [162513.519309] RIP: 0033:0x7f5238f4a903
+  [162513.519310] Code: Bad RIP value.
+  [162513.519312] RSP: 002b:00007fff67b97758 EFLAGS: 00000246 ORIG_RAX: 0000000000000055
+  [162513.519314] RAX: ffffffffffffffda RBX: 00000000ffffffff RCX: 00007f5238f4a903
+  [162513.519316] RDX: 0000000000000000 RSI: 00000000000001b6 RDI: 000055b1fbb0d470
+  [162513.519317] RBP: 00007fff67b978c0 R08: 0000000000000001 R09: 0000000000000002
+  [162513.519319] R10: 00007fff67b974f7 R11: 0000000000000246 R12: 0000000000000013
+  [162513.519320] R13: 00000000000001b6 R14: 00007fff67b97906 R15: 000055b1fad1c620
+  [162513.519332] INFO: task btrfs:1356211 blocked for more than 120 seconds.
+  [162513.519727]       Not tainted 5.9.0-rc6-btrfs-next-69 #1
+  [162513.520115] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
+  [162513.520508] task:btrfs           state:D stack:    0 pid:1356211 ppid:1356178 flags:0x00004002
+  [162513.520511] Call Trace:
+  [162513.520516]  __schedule+0x5ce/0xd00
+  [162513.520519]  ? _raw_spin_unlock_irqrestore+0x3c/0x60
+  [162513.520525]  schedule+0x46/0xf0
+  [162513.520544]  btrfs_scrub_pause+0x11f/0x180 [btrfs]
+  [162513.520548]  ? finish_wait+0x90/0x90
+  [162513.520562]  btrfs_commit_transaction+0x45a/0xc30 [btrfs]
+  [162513.520574]  ? start_transaction+0xe0/0x5f0 [btrfs]
+  [162513.520596]  btrfs_dev_replace_finishing+0x6d8/0x711 [btrfs]
+  [162513.520619]  btrfs_dev_replace_by_ioctl.cold+0x1cc/0x1fd [btrfs]
+  [162513.520639]  btrfs_ioctl+0x2a25/0x36f0 [btrfs]
+  [162513.520643]  ? do_sigaction+0xf3/0x240
+  [162513.520645]  ? find_held_lock+0x32/0x90
+  [162513.520648]  ? do_sigaction+0xf3/0x240
+  [162513.520651]  ? lock_acquired+0x33b/0x470
+  [162513.520655]  ? _raw_spin_unlock_irq+0x24/0x50
+  [162513.520657]  ? lockdep_hardirqs_on+0x7d/0x100
+  [162513.520660]  ? _raw_spin_unlock_irq+0x35/0x50
+  [162513.520662]  ? do_sigaction+0xf3/0x240
+  [162513.520671]  ? __x64_sys_ioctl+0x83/0xb0
+  [162513.520672]  __x64_sys_ioctl+0x83/0xb0
+  [162513.520677]  do_syscall_64+0x33/0x80
+  [162513.520679]  entry_SYSCALL_64_after_hwframe+0x44/0xa9
+  [162513.520681] RIP: 0033:0x7fc3cd307d87
+  [162513.520682] Code: Bad RIP value.
+  [162513.520684] RSP: 002b:00007ffe30a56bb8 EFLAGS: 00000202 ORIG_RAX: 0000000000000010
+  [162513.520686] RAX: ffffffffffffffda RBX: 0000000000000004 RCX: 00007fc3cd307d87
+  [162513.520687] RDX: 00007ffe30a57a30 RSI: 00000000ca289435 RDI: 0000000000000003
+  [162513.520689] RBP: 0000000000000000 R08: 0000000000000000 R09: 0000000000000000
+  [162513.520690] R10: 0000000000000008 R11: 0000000000000202 R12: 0000000000000003
+  [162513.520692] R13: 0000557323a212e0 R14: 00007ffe30a5a520 R15: 0000000000000001
+  [162513.520703]
+                 Showing all locks held in the system:
+  [162513.520712] 1 lock held by khungtaskd/54:
+  [162513.520713]  #0: ffffffffb40a91a0 (rcu_read_lock){....}-{1:2}, at: debug_show_all_locks+0x15/0x197
+  [162513.520728] 1 lock held by in:imklog/596:
+  [162513.520729]  #0: ffff8f3f0d781400 (&f->f_pos_lock){+.+.}-{3:3}, at: __fdget_pos+0x4d/0x60
+  [162513.520782] 1 lock held by btrfs-transacti/1356167:
+  [162513.520784]  #0: ffff8f3d810cc848 (&fs_info->transaction_kthread_mutex){+.+.}-{3:3}, at: transaction_kthread+0x4a/0x170 [btrfs]
+  [162513.520798] 1 lock held by btrfs/1356190:
+  [162513.520800]  #0: ffff8f3d57644470 (sb_writers#15){.+.+}-{0:0}, at: mnt_want_write_file+0x22/0x60
+  [162513.520805] 1 lock held by fsstress/1356184:
+  [162513.520806]  #0: ffff8f3d576440e8 (&type->s_umount_key#62){++++}-{3:3}, at: iterate_supers+0x6f/0xf0
+  [162513.520811] 3 locks held by fsstress/1356185:
+  [162513.520812]  #0: ffff8f3d57644470 (sb_writers#15){.+.+}-{0:0}, at: mnt_want_write+0x20/0x50
+  [162513.520815]  #1: ffff8f3d80a650b8 (&type->i_mutex_dir_key#10){++++}-{3:3}, at: vfs_setxattr+0x50/0x120
+  [162513.520820]  #2: ffff8f3d57644690 (sb_internal#2){.+.+}-{0:0}, at: start_transaction+0x40e/0x5f0 [btrfs]
+  [162513.520833] 1 lock held by fsstress/1356196:
+  [162513.520834]  #0: ffff8f3d576440e8 (&type->s_umount_key#62){++++}-{3:3}, at: iterate_supers+0x6f/0xf0
+  [162513.520838] 3 locks held by fsstress/1356197:
+  [162513.520839]  #0: ffff8f3d57644470 (sb_writers#15){.+.+}-{0:0}, at: mnt_want_write+0x20/0x50
+  [162513.520843]  #1: ffff8f3d506465e8 (&type->i_mutex_dir_key#10){++++}-{3:3}, at: path_openat+0x2a7/0xa50
+  [162513.520846]  #2: ffff8f3d57644690 (sb_internal#2){.+.+}-{0:0}, at: start_transaction+0x40e/0x5f0 [btrfs]
+  [162513.520858] 2 locks held by btrfs/1356211:
+  [162513.520859]  #0: ffff8f3d810cde30 (&fs_info->dev_replace.lock_finishing_cancel_unmount){+.+.}-{3:3}, at: btrfs_dev_replace_finishing+0x52/0x711 [btrfs]
+  [162513.520877]  #1: ffff8f3d57644690 (sb_internal#2){.+.+}-{0:0}, at: start_transaction+0x40e/0x5f0 [btrfs]
+
+This was weird because the stack traces show that a transaction commit,
+triggered by a device replace operation, is blocking trying to pause any
+running scrubs but there are no stack traces of blocked tasks doing a
+scrub.
+
+After poking around with drgn, I noticed there was a scrub task that was
+constantly running and blocking for shorts periods of time:
+
+  >>> t = find_task(prog, 1356190)
+  >>> prog.stack_trace(t)
+  #0  __schedule+0x5ce/0xcfc
+  #1  schedule+0x46/0xe4
+  #2  schedule_timeout+0x1df/0x475
+  #3  btrfs_reada_wait+0xda/0x132
+  #4  scrub_stripe+0x2a8/0x112f
+  #5  scrub_chunk+0xcd/0x134
+  #6  scrub_enumerate_chunks+0x29e/0x5ee
+  #7  btrfs_scrub_dev+0x2d5/0x91b
+  #8  btrfs_ioctl+0x7f5/0x36e7
+  #9  __x64_sys_ioctl+0x83/0xb0
+  #10 do_syscall_64+0x33/0x77
+  #11 entry_SYSCALL_64+0x7c/0x156
+
+Which corresponds to:
+
+int btrfs_reada_wait(void *handle)
+{
+    struct reada_control *rc = handle;
+    struct btrfs_fs_info *fs_info = rc->fs_info;
+
+    while (atomic_read(&rc->elems)) {
+        if (!atomic_read(&fs_info->reada_works_cnt))
+            reada_start_machine(fs_info);
+        wait_event_timeout(rc->wait, atomic_read(&rc->elems) == 0,
+                          (HZ + 9) / 10);
+    }
+(...)
+
+So the counter "rc->elems" was set to 1 and never decreased to 0, causing
+the scrub task to loop forever in that function. Then I used the following
+script for drgn to check the readahead requests:
+
+  $ cat dump_reada.py
+  import sys
+  import drgn
+  from drgn import NULL, Object, cast, container_of, execscript, \
+      reinterpret, sizeof
+  from drgn.helpers.linux import *
+
+  mnt_path = b"/home/fdmanana/btrfs-tests/scratch_1"
+
+  mnt = None
+  for mnt in for_each_mount(prog, dst = mnt_path):
+      pass
+
+  if mnt is None:
+      sys.stderr.write(f'Error: mount point {mnt_path} not found\n')
+      sys.exit(1)
+
+  fs_info = cast('struct btrfs_fs_info *', mnt.mnt.mnt_sb.s_fs_info)
+
+  def dump_re(re):
+      nzones = re.nzones.value_()
+      print(f're at {hex(re.value_())}')
+      print(f'\t logical {re.logical.value_()}')
+      print(f'\t refcnt {re.refcnt.value_()}')
+      print(f'\t nzones {nzones}')
+      for i in range(nzones):
+          dev = re.zones[i].device
+          name = dev.name.str.string_()
+          print(f'\t\t dev id {dev.devid.value_()} name {name}')
+      print()
+
+  for _, e in radix_tree_for_each(fs_info.reada_tree):
+      re = cast('struct reada_extent *', e)
+      dump_re(re)
+
+  $ drgn dump_reada.py
+  re at 0xffff8f3da9d25ad8
+          logical 38928384
+          refcnt 1
+          nzones 1
+                 dev id 0 name b'/dev/sdd'
+  $
+
+So there was one readahead extent with a single zone corresponding to the
+source device of that last device replace operation logged in dmesg/syslog.
+Also the ID of that zone's device was 0 which is a special value set in
+the source device of a device replace operation when the operation finishes
+(constant BTRFS_DEV_REPLACE_DEVID set at btrfs_dev_replace_finishing()),
+confirming again that device /dev/sdd was the source of a device replace
+operation.
+
+Normally there should be as many zones in the readahead extent as there are
+devices, and I wasn't expecting the extent to be in a block group with a
+'single' profile, so I went and confirmed with the following drgn script
+that there weren't any single profile block groups:
+
+  $ cat dump_block_groups.py
+  import sys
+  import drgn
+  from drgn import NULL, Object, cast, container_of, execscript, \
+      reinterpret, sizeof
+  from drgn.helpers.linux import *
+
+  mnt_path = b"/home/fdmanana/btrfs-tests/scratch_1"
+
+  mnt = None
+  for mnt in for_each_mount(prog, dst = mnt_path):
+      pass
+
+  if mnt is None:
+      sys.stderr.write(f'Error: mount point {mnt_path} not found\n')
+      sys.exit(1)
+
+  fs_info = cast('struct btrfs_fs_info *', mnt.mnt.mnt_sb.s_fs_info)
+
+  BTRFS_BLOCK_GROUP_DATA = (1 << 0)
+  BTRFS_BLOCK_GROUP_SYSTEM = (1 << 1)
+  BTRFS_BLOCK_GROUP_METADATA = (1 << 2)
+  BTRFS_BLOCK_GROUP_RAID0 = (1 << 3)
+  BTRFS_BLOCK_GROUP_RAID1 = (1 << 4)
+  BTRFS_BLOCK_GROUP_DUP = (1 << 5)
+  BTRFS_BLOCK_GROUP_RAID10 = (1 << 6)
+  BTRFS_BLOCK_GROUP_RAID5 = (1 << 7)
+  BTRFS_BLOCK_GROUP_RAID6 = (1 << 8)
+  BTRFS_BLOCK_GROUP_RAID1C3 = (1 << 9)
+  BTRFS_BLOCK_GROUP_RAID1C4 = (1 << 10)
+
+  def bg_flags_string(bg):
+      flags = bg.flags.value_()
+      ret = ''
+      if flags & BTRFS_BLOCK_GROUP_DATA:
+          ret = 'data'
+      if flags & BTRFS_BLOCK_GROUP_METADATA:
+          if len(ret) > 0:
+              ret += '|'
+          ret += 'meta'
+      if flags & BTRFS_BLOCK_GROUP_SYSTEM:
+          if len(ret) > 0:
+              ret += '|'
+          ret += 'system'
+      if flags & BTRFS_BLOCK_GROUP_RAID0:
+          ret += ' raid0'
+      elif flags & BTRFS_BLOCK_GROUP_RAID1:
+          ret += ' raid1'
+      elif flags & BTRFS_BLOCK_GROUP_DUP:
+          ret += ' dup'
+      elif flags & BTRFS_BLOCK_GROUP_RAID10:
+          ret += ' raid10'
+      elif flags & BTRFS_BLOCK_GROUP_RAID5:
+          ret += ' raid5'
+      elif flags & BTRFS_BLOCK_GROUP_RAID6:
+          ret += ' raid6'
+      elif flags & BTRFS_BLOCK_GROUP_RAID1C3:
+          ret += ' raid1c3'
+      elif flags & BTRFS_BLOCK_GROUP_RAID1C4:
+          ret += ' raid1c4'
+      else:
+          ret += ' single'
+
+      return ret
+
+  def dump_bg(bg):
+      print()
+      print(f'block group at {hex(bg.value_())}')
+      print(f'\t start {bg.start.value_()} length {bg.length.value_()}')
+      print(f'\t flags {bg.flags.value_()} - {bg_flags_string(bg)}')
+
+  bg_root = fs_info.block_group_cache_tree.address_of_()
+  for bg in rbtree_inorder_for_each_entry('struct btrfs_block_group', bg_root, 'cache_node'):
+      dump_bg(bg)
+
+  $ drgn dump_block_groups.py
+
+  block group at 0xffff8f3d673b0400
+         start 22020096 length 16777216
+         flags 258 - system raid6
+
+  block group at 0xffff8f3d53ddb400
+         start 38797312 length 536870912
+         flags 260 - meta raid6
+
+  block group at 0xffff8f3d5f4d9c00
+         start 575668224 length 2147483648
+         flags 257 - data raid6
+
+  block group at 0xffff8f3d08189000
+         start 2723151872 length 67108864
+         flags 258 - system raid6
+
+  block group at 0xffff8f3db70ff000
+         start 2790260736 length 1073741824
+         flags 260 - meta raid6
+
+  block group at 0xffff8f3d5f4dd800
+         start 3864002560 length 67108864
+         flags 258 - system raid6
+
+  block group at 0xffff8f3d67037000
+         start 3931111424 length 2147483648
+         flags 257 - data raid6
+  $
+
+So there were only 2 reasons left for having a readahead extent with a
+single zone: reada_find_zone(), called when creating a readahead extent,
+returned NULL either because we failed to find the corresponding block
+group or because a memory allocation failed. With some additional and
+custom tracing I figured out that on every further ocurrence of the
+problem the block group had just been deleted when we were looping to
+create the zones for the readahead extent (at reada_find_extent()), so we
+ended up with only one zone in the readahead extent, corresponding to a
+device that ends up getting replaced.
+
+So after figuring that out it became obvious why the hang happens:
+
+1) Task A starts a scrub on any device of the filesystem, except for
+   device /dev/sdd;
+
+2) Task B starts a device replace with /dev/sdd as the source device;
+
+3) Task A calls btrfs_reada_add() from scrub_stripe() and it is currently
+   starting to scrub a stripe from block group X. This call to
+   btrfs_reada_add() is the one for the extent tree. When btrfs_reada_add()
+   calls reada_add_block(), it passes the logical address of the extent
+   tree's root node as its 'logical' argument - a value of 38928384;
+
+4) Task A then enters reada_find_extent(), called from reada_add_block().
+   It finds there isn't any existing readahead extent for the logical
+   address 38928384, so it proceeds to the path of creating a new one.
+
+   It calls btrfs_map_block() to find out which stripes exist for the block
+   group X. On the first iteration of the for loop that iterates over the
+   stripes, it finds the stripe for device /dev/sdd, so it creates one
+   zone for that device and adds it to the readahead extent. Before getting
+   into the second iteration of the loop, the cleanup kthread deletes block
+   group X because it was empty. So in the iterations for the remaining
+   stripes it does not add more zones to the readahead extent, because the
+   calls to reada_find_zone() returned NULL because they couldn't find
+   block group X anymore.
+
+   As a result the new readahead extent has a single zone, corresponding to
+   the device /dev/sdd;
+
+4) Before task A returns to btrfs_reada_add() and queues the readahead job
+   for the readahead work queue, task B finishes the device replace and at
+   btrfs_dev_replace_finishing() swaps the device /dev/sdd with the new
+   device /dev/sdg;
+
+5) Task A returns to reada_add_block(), which increments the counter
+   "->elems" of the reada_control structure allocated at btrfs_reada_add().
+
+   Then it returns back to btrfs_reada_add() and calls
+   reada_start_machine(). This queues a job in the readahead work queue to
+   run the function reada_start_machine_worker(), which calls
+   __reada_start_machine().
+
+   At __reada_start_machine() we take the device list mutex and for each
+   device found in the current device list, we call
+   reada_start_machine_dev() to start the readahead work. However at this
+   point the device /dev/sdd was already freed and is not in the device
+   list anymore.
+
+   This means the corresponding readahead for the extent at 38928384 is
+   never started, and therefore the "->elems" counter of the reada_control
+   structure allocated at btrfs_reada_add() never goes down to 0, causing
+   the call to btrfs_reada_wait(), done by the scrub task, to wait forever.
+
+Note that the readahead request can be made either after the device replace
+started or before it started, however in pratice it is very unlikely that a
+device replace is able to start after a readahead request is made and is
+able to complete before the readahead request completes - maybe only on a
+very small and nearly empty filesystem.
+
+This hang however is not the only problem we can have with readahead and
+device removals. When the readahead extent has other zones other than the
+one corresponding to the device that is being removed (either by a device
+replace or a device remove operation), we risk having a use-after-free on
+the device when dropping the last reference of the readahead extent.
+
+For example if we create a readahead extent with two zones, one for the
+device /dev/sdd and one for the device /dev/sde:
+
+1) Before the readahead worker starts, the device /dev/sdd is removed,
+   and the corresponding btrfs_device structure is freed. However the
+   readahead extent still has the zone pointing to the device structure;
+
+2) When the readahead worker starts, it only finds device /dev/sde in the
+   current device list of the filesystem;
+
+3) It starts the readahead work, at reada_start_machine_dev(), using the
+   device /dev/sde;
+
+4) Then when it finishes reading the extent from device /dev/sde, it calls
+   __readahead_hook() which ends up dropping the last reference on the
+   readahead extent through the last call to reada_extent_put();
+
+5) At reada_extent_put() it iterates over each zone of the readahead extent
+   and attempts to delete an element from the device's 'reada_extents'
+   radix tree, resulting in a use-after-free, as the device pointer of the
+   zone for /dev/sdd is now stale. We can also access the device after
+   dropping the last reference of a zone, through reada_zone_release(),
+   also called by reada_extent_put().
+
+And a device remove suffers the same problem, however since it shrinks the
+device size down to zero before removing the device, it is very unlikely to
+still have readahead requests not completed by the time we free the device,
+the only possibility is if the device has a very little space allocated.
+
+While the hang problem is exclusive to scrub, since it is currently the
+only user of btrfs_reada_add() and btrfs_reada_wait(), the use-after-free
+problem affects any path that triggers readhead, which includes
+btree_readahead_hook() and __readahead_hook() (a readahead worker can
+trigger readahed for the children of a node) for example - any path that
+ends up calling reada_add_block() can trigger the use-after-free after a
+device is removed.
+
+So fix this by waiting for any readahead requests for a device to complete
+before removing a device, ensuring that while waiting for existing ones no
+new ones can be made.
+
+This problem has been around for a very long time - the readahead code was
+added in 2011, device remove exists since 2008 and device replace was
+introduced in 2013, hard to pick a specific commit for a git Fixes tag.
+
+CC: stable@vger.kernel.org # 4.4+
+Reviewed-by: Josef Bacik <josef@toxicpanda.com>
+Signed-off-by: Filipe Manana <fdmanana@suse.com>
+Reviewed-by: David Sterba <dsterba@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/btrfs/ctree.h       |    2 ++
+ fs/btrfs/dev-replace.c |    5 +++++
+ fs/btrfs/reada.c       |   45 +++++++++++++++++++++++++++++++++++++++++++++
+ fs/btrfs/volumes.c     |    3 +++
+ fs/btrfs/volumes.h     |    1 +
+ 5 files changed, 56 insertions(+)
+
+--- a/fs/btrfs/ctree.h
++++ b/fs/btrfs/ctree.h
+@@ -3404,6 +3404,8 @@ struct reada_control *btrfs_reada_add(st
+ int btrfs_reada_wait(void *handle);
+ void btrfs_reada_detach(void *handle);
+ int btree_readahead_hook(struct extent_buffer *eb, int err);
++void btrfs_reada_remove_dev(struct btrfs_device *dev);
++void btrfs_reada_undo_remove_dev(struct btrfs_device *dev);
+ static inline int is_fstree(u64 rootid)
+ {
+--- a/fs/btrfs/dev-replace.c
++++ b/fs/btrfs/dev-replace.c
+@@ -631,6 +631,9 @@ static int btrfs_dev_replace_finishing(s
+       }
+       btrfs_wait_ordered_roots(fs_info, U64_MAX, 0, (u64)-1);
++      if (!scrub_ret)
++              btrfs_reada_remove_dev(src_device);
++
+       /*
+        * We have to use this loop approach because at this point src_device
+        * has to be available for transaction commit to complete, yet new
+@@ -639,6 +642,7 @@ static int btrfs_dev_replace_finishing(s
+       while (1) {
+               trans = btrfs_start_transaction(root, 0);
+               if (IS_ERR(trans)) {
++                      btrfs_reada_undo_remove_dev(src_device);
+                       mutex_unlock(&dev_replace->lock_finishing_cancel_unmount);
+                       return PTR_ERR(trans);
+               }
+@@ -689,6 +693,7 @@ error:
+               up_write(&dev_replace->rwsem);
+               mutex_unlock(&fs_info->chunk_mutex);
+               mutex_unlock(&fs_info->fs_devices->device_list_mutex);
++              btrfs_reada_undo_remove_dev(src_device);
+               btrfs_rm_dev_replace_blocked(fs_info);
+               if (tgt_device)
+                       btrfs_destroy_dev_replace_tgtdev(tgt_device);
+--- a/fs/btrfs/reada.c
++++ b/fs/btrfs/reada.c
+@@ -421,6 +421,9 @@ static struct reada_extent *reada_find_e
+               if (!dev->bdev)
+                       continue;
++              if (test_bit(BTRFS_DEV_STATE_NO_READA, &dev->dev_state))
++                      continue;
++
+               if (dev_replace_is_ongoing &&
+                   dev == fs_info->dev_replace.tgtdev) {
+                       /*
+@@ -1014,3 +1017,45 @@ void btrfs_reada_detach(void *handle)
+       kref_put(&rc->refcnt, reada_control_release);
+ }
++
++/*
++ * Before removing a device (device replace or device remove ioctls), call this
++ * function to wait for all existing readahead requests on the device and to
++ * make sure no one queues more readahead requests for the device.
++ *
++ * Must be called without holding neither the device list mutex nor the device
++ * replace semaphore, otherwise it will deadlock.
++ */
++void btrfs_reada_remove_dev(struct btrfs_device *dev)
++{
++      struct btrfs_fs_info *fs_info = dev->fs_info;
++
++      /* Serialize with readahead extent creation at reada_find_extent(). */
++      spin_lock(&fs_info->reada_lock);
++      set_bit(BTRFS_DEV_STATE_NO_READA, &dev->dev_state);
++      spin_unlock(&fs_info->reada_lock);
++
++      /*
++       * There might be readahead requests added to the radix trees which
++       * were not yet added to the readahead work queue. We need to start
++       * them and wait for their completion, otherwise we can end up with
++       * use-after-free problems when dropping the last reference on the
++       * readahead extents and their zones, as they need to access the
++       * device structure.
++       */
++      reada_start_machine(fs_info);
++      btrfs_flush_workqueue(fs_info->readahead_workers);
++}
++
++/*
++ * If when removing a device (device replace or device remove ioctls) an error
++ * happens after calling btrfs_reada_remove_dev(), call this to undo what that
++ * function did. This is safe to call even if btrfs_reada_remove_dev() was not
++ * called before.
++ */
++void btrfs_reada_undo_remove_dev(struct btrfs_device *dev)
++{
++      spin_lock(&dev->fs_info->reada_lock);
++      clear_bit(BTRFS_DEV_STATE_NO_READA, &dev->dev_state);
++      spin_unlock(&dev->fs_info->reada_lock);
++}
+--- a/fs/btrfs/volumes.c
++++ b/fs/btrfs/volumes.c
+@@ -2208,6 +2208,8 @@ int btrfs_rm_device(struct btrfs_fs_info
+       mutex_unlock(&uuid_mutex);
+       ret = btrfs_shrink_device(device, 0);
++      if (!ret)
++              btrfs_reada_remove_dev(device);
+       mutex_lock(&uuid_mutex);
+       if (ret)
+               goto error_undo;
+@@ -2294,6 +2296,7 @@ out:
+       return ret;
+ error_undo:
++      btrfs_reada_undo_remove_dev(device);
+       if (test_bit(BTRFS_DEV_STATE_WRITEABLE, &device->dev_state)) {
+               mutex_lock(&fs_info->chunk_mutex);
+               list_add(&device->dev_alloc_list,
+--- a/fs/btrfs/volumes.h
++++ b/fs/btrfs/volumes.h
+@@ -56,6 +56,7 @@ struct btrfs_io_geometry {
+ #define BTRFS_DEV_STATE_MISSING               (2)
+ #define BTRFS_DEV_STATE_REPLACE_TGT   (3)
+ #define BTRFS_DEV_STATE_FLUSH_SENT    (4)
++#define BTRFS_DEV_STATE_NO_READA      (5)
+ struct btrfs_device {
+       struct list_head dev_list; /* device_list_mutex */
diff --git a/queue-5.4/btrfs-fix-use-after-free-on-readahead-extent-after-failure-to-create-it.patch b/queue-5.4/btrfs-fix-use-after-free-on-readahead-extent-after-failure-to-create-it.patch
new file mode 100644 (file)
index 0000000..3435a0d
--- /dev/null
@@ -0,0 +1,139 @@
+From 83bc1560e02e25c6439341352024ebe8488f4fbd Mon Sep 17 00:00:00 2001
+From: Filipe Manana <fdmanana@suse.com>
+Date: Mon, 12 Oct 2020 11:55:23 +0100
+Subject: btrfs: fix use-after-free on readahead extent after failure to create it
+
+From: Filipe Manana <fdmanana@suse.com>
+
+commit 83bc1560e02e25c6439341352024ebe8488f4fbd upstream.
+
+If we fail to find suitable zones for a new readahead extent, we end up
+leaving a stale pointer in the global readahead extents radix tree
+(fs_info->reada_tree), which can trigger the following trace later on:
+
+  [13367.696354] BUG: kernel NULL pointer dereference, address: 00000000000000b0
+  [13367.696802] #PF: supervisor read access in kernel mode
+  [13367.697249] #PF: error_code(0x0000) - not-present page
+  [13367.697721] PGD 0 P4D 0
+  [13367.698171] Oops: 0000 [#1] PREEMPT SMP DEBUG_PAGEALLOC PTI
+  [13367.698632] CPU: 6 PID: 851214 Comm: btrfs Tainted: G        W         5.9.0-rc6-btrfs-next-69 #1
+  [13367.699100] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.13.0-0-gf21b5a4aeb02-prebuilt.qemu.org 04/01/2014
+  [13367.700069] RIP: 0010:__lock_acquire+0x20a/0x3970
+  [13367.700562] Code: ff 1f 0f b7 c0 48 0f (...)
+  [13367.701609] RSP: 0018:ffffb14448f57790 EFLAGS: 00010046
+  [13367.702140] RAX: 0000000000000000 RBX: 29b935140c15e8cf RCX: 0000000000000000
+  [13367.702698] RDX: 0000000000000002 RSI: ffffffffb3d66bd0 RDI: 0000000000000046
+  [13367.703240] RBP: ffff8a52ba8ac040 R08: 00000c2866ad9288 R09: 0000000000000001
+  [13367.703783] R10: 0000000000000001 R11: 00000000b66d9b53 R12: ffff8a52ba8ac9b0
+  [13367.704330] R13: 0000000000000000 R14: ffff8a532b6333e8 R15: 0000000000000000
+  [13367.704880] FS:  00007fe1df6b5700(0000) GS:ffff8a5376600000(0000) knlGS:0000000000000000
+  [13367.705438] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+  [13367.705995] CR2: 00000000000000b0 CR3: 000000022cca8004 CR4: 00000000003706e0
+  [13367.706565] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
+  [13367.707127] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
+  [13367.707686] Call Trace:
+  [13367.708246]  ? ___slab_alloc+0x395/0x740
+  [13367.708820]  ? reada_add_block+0xae/0xee0 [btrfs]
+  [13367.709383]  lock_acquire+0xb1/0x480
+  [13367.709955]  ? reada_add_block+0xe0/0xee0 [btrfs]
+  [13367.710537]  ? reada_add_block+0xae/0xee0 [btrfs]
+  [13367.711097]  ? rcu_read_lock_sched_held+0x5d/0x90
+  [13367.711659]  ? kmem_cache_alloc_trace+0x8d2/0x990
+  [13367.712221]  ? lock_acquired+0x33b/0x470
+  [13367.712784]  _raw_spin_lock+0x34/0x80
+  [13367.713356]  ? reada_add_block+0xe0/0xee0 [btrfs]
+  [13367.713966]  reada_add_block+0xe0/0xee0 [btrfs]
+  [13367.714529]  ? btrfs_root_node+0x15/0x1f0 [btrfs]
+  [13367.715077]  btrfs_reada_add+0x117/0x170 [btrfs]
+  [13367.715620]  scrub_stripe+0x21e/0x10d0 [btrfs]
+  [13367.716141]  ? kvm_sched_clock_read+0x5/0x10
+  [13367.716657]  ? __lock_acquire+0x41e/0x3970
+  [13367.717184]  ? scrub_chunk+0x60/0x140 [btrfs]
+  [13367.717697]  ? find_held_lock+0x32/0x90
+  [13367.718254]  ? scrub_chunk+0x60/0x140 [btrfs]
+  [13367.718773]  ? lock_acquired+0x33b/0x470
+  [13367.719278]  ? scrub_chunk+0xcd/0x140 [btrfs]
+  [13367.719786]  scrub_chunk+0xcd/0x140 [btrfs]
+  [13367.720291]  scrub_enumerate_chunks+0x270/0x5c0 [btrfs]
+  [13367.720787]  ? finish_wait+0x90/0x90
+  [13367.721281]  btrfs_scrub_dev+0x1ee/0x620 [btrfs]
+  [13367.721762]  ? rcu_read_lock_any_held+0x8e/0xb0
+  [13367.722235]  ? preempt_count_add+0x49/0xa0
+  [13367.722710]  ? __sb_start_write+0x19b/0x290
+  [13367.723192]  btrfs_ioctl+0x7f5/0x36f0 [btrfs]
+  [13367.723660]  ? __fget_files+0x101/0x1d0
+  [13367.724118]  ? find_held_lock+0x32/0x90
+  [13367.724559]  ? __fget_files+0x101/0x1d0
+  [13367.724982]  ? __x64_sys_ioctl+0x83/0xb0
+  [13367.725399]  __x64_sys_ioctl+0x83/0xb0
+  [13367.725802]  do_syscall_64+0x33/0x80
+  [13367.726188]  entry_SYSCALL_64_after_hwframe+0x44/0xa9
+  [13367.726574] RIP: 0033:0x7fe1df7add87
+  [13367.726948] Code: 00 00 00 48 8b 05 09 91 (...)
+  [13367.727763] RSP: 002b:00007fe1df6b4d48 EFLAGS: 00000246 ORIG_RAX: 0000000000000010
+  [13367.728179] RAX: ffffffffffffffda RBX: 000055ce1fb596a0 RCX: 00007fe1df7add87
+  [13367.728604] RDX: 000055ce1fb596a0 RSI: 00000000c400941b RDI: 0000000000000003
+  [13367.729021] RBP: 0000000000000000 R08: 00007fe1df6b5700 R09: 0000000000000000
+  [13367.729431] R10: 00007fe1df6b5700 R11: 0000000000000246 R12: 00007ffd922b07de
+  [13367.729842] R13: 00007ffd922b07df R14: 00007fe1df6b4e40 R15: 0000000000802000
+  [13367.730275] Modules linked in: btrfs blake2b_generic xor (...)
+  [13367.732638] CR2: 00000000000000b0
+  [13367.733166] ---[ end trace d298b6805556acd9 ]---
+
+What happens is the following:
+
+1) At reada_find_extent() we don't find any existing readahead extent for
+   the metadata extent starting at logical address X;
+
+2) So we proceed to create a new one. We then call btrfs_map_block() to get
+   information about which stripes contain extent X;
+
+3) After that we iterate over the stripes and create only one zone for the
+   readahead extent - only one because reada_find_zone() returned NULL for
+   all iterations except for one, either because a memory allocation failed
+   or it couldn't find the block group of the extent (it may have just been
+   deleted);
+
+4) We then add the new readahead extent to the readahead extents radix
+   tree at fs_info->reada_tree;
+
+5) Then we iterate over each zone of the new readahead extent, and find
+   that the device used for that zone no longer exists, because it was
+   removed or it was the source device of a device replace operation.
+   Since this left 'have_zone' set to 0, after finishing the loop we jump
+   to the 'error' label, call kfree() on the new readahead extent and
+   return without removing it from the radix tree at fs_info->reada_tree;
+
+6) Any future call to reada_find_extent() for the logical address X will
+   find the stale pointer in the readahead extents radix tree, increment
+   its reference counter, which can trigger the use-after-free right
+   away or return it to the caller reada_add_block() that results in the
+   use-after-free of the example trace above.
+
+So fix this by making sure we delete the readahead extent from the radix
+tree if we fail to setup zones for it (when 'have_zone = 0').
+
+Fixes: 319450211842ba ("btrfs: reada: bypass adding extent when all zone failed")
+CC: stable@vger.kernel.org # 4.9+
+Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
+Reviewed-by: Josef Bacik <josef@toxicpanda.com>
+Signed-off-by: Filipe Manana <fdmanana@suse.com>
+Reviewed-by: David Sterba <dsterba@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/btrfs/reada.c |    2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/fs/btrfs/reada.c
++++ b/fs/btrfs/reada.c
+@@ -445,6 +445,8 @@ static struct reada_extent *reada_find_e
+               }
+               have_zone = 1;
+       }
++      if (!have_zone)
++              radix_tree_delete(&fs_info->reada_tree, index);
+       spin_unlock(&fs_info->reada_lock);
+       up_read(&fs_info->dev_replace.rwsem);
diff --git a/queue-5.4/btrfs-improve-device-scanning-messages.patch b/queue-5.4/btrfs-improve-device-scanning-messages.patch
new file mode 100644 (file)
index 0000000..3766d00
--- /dev/null
@@ -0,0 +1,59 @@
+From 79dae17d8d44b2d15779e332180080af45df5352 Mon Sep 17 00:00:00 2001
+From: Anand Jain <anand.jain@oracle.com>
+Date: Thu, 3 Sep 2020 21:30:12 +0800
+Subject: btrfs: improve device scanning messages
+
+From: Anand Jain <anand.jain@oracle.com>
+
+commit 79dae17d8d44b2d15779e332180080af45df5352 upstream.
+
+Systems booting without the initramfs seems to scan an unusual kind
+of device path (/dev/root). And at a later time, the device is updated
+to the correct path. We generally print the process name and PID of the
+process scanning the device but we don't capture the same information if
+the device path is rescanned with a different pathname.
+
+The current message is too long, so drop the unnecessary UUID and add
+process name and PID.
+
+While at this also update the duplicate device warning to include the
+process name and PID so the messages are consistent
+
+CC: stable@vger.kernel.org # 4.19+
+Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=89721
+Signed-off-by: Anand Jain <anand.jain@oracle.com>
+Reviewed-by: David Sterba <dsterba@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/btrfs/volumes.c |   14 ++++++++------
+ 1 file changed, 8 insertions(+), 6 deletions(-)
+
+--- a/fs/btrfs/volumes.c
++++ b/fs/btrfs/volumes.c
+@@ -1123,16 +1123,18 @@ static noinline struct btrfs_device *dev
+                               bdput(path_bdev);
+                               mutex_unlock(&fs_devices->device_list_mutex);
+                               btrfs_warn_in_rcu(device->fs_info,
+-                      "duplicate device fsid:devid for %pU:%llu old:%s new:%s",
+-                                      disk_super->fsid, devid,
+-                                      rcu_str_deref(device->name), path);
++      "duplicate device %s devid %llu generation %llu scanned by %s (%d)",
++                                                path, devid, found_transid,
++                                                current->comm,
++                                                task_pid_nr(current));
+                               return ERR_PTR(-EEXIST);
+                       }
+                       bdput(path_bdev);
+                       btrfs_info_in_rcu(device->fs_info,
+-                              "device fsid %pU devid %llu moved old:%s new:%s",
+-                              disk_super->fsid, devid,
+-                              rcu_str_deref(device->name), path);
++      "devid %llu device path %s changed to %s scanned by %s (%d)",
++                                        devid, rcu_str_deref(device->name),
++                                        path, current->comm,
++                                        task_pid_nr(current));
+               }
+               name = rcu_string_strdup(path, GFP_NOFS);
diff --git a/queue-5.4/btrfs-qgroup-fix-wrong-qgroup-metadata-reserve-for-delayed-inode.patch b/queue-5.4/btrfs-qgroup-fix-wrong-qgroup-metadata-reserve-for-delayed-inode.patch
new file mode 100644 (file)
index 0000000..9bbba89
--- /dev/null
@@ -0,0 +1,66 @@
+From b4c5d8fdfff3e2b6c4fa4a5043e8946dff500f8c Mon Sep 17 00:00:00 2001
+From: Qu Wenruo <wqu@suse.com>
+Date: Fri, 24 Jul 2020 14:46:09 +0800
+Subject: btrfs: qgroup: fix wrong qgroup metadata reserve for delayed inode
+
+From: Qu Wenruo <wqu@suse.com>
+
+commit b4c5d8fdfff3e2b6c4fa4a5043e8946dff500f8c upstream.
+
+For delayed inode facility, qgroup metadata is reserved for it, and
+later freed.
+
+However we're freeing more bytes than we reserved.
+In btrfs_delayed_inode_reserve_metadata():
+
+       num_bytes = btrfs_calc_metadata_size(fs_info, 1);
+       ...
+               ret = btrfs_qgroup_reserve_meta_prealloc(root,
+                               fs_info->nodesize, true);
+               ...
+               if (!ret) {
+                       node->bytes_reserved = num_bytes;
+
+But in btrfs_delayed_inode_release_metadata():
+
+       if (qgroup_free)
+               btrfs_qgroup_free_meta_prealloc(node->root,
+                               node->bytes_reserved);
+       else
+               btrfs_qgroup_convert_reserved_meta(node->root,
+                               node->bytes_reserved);
+
+This means, we're always releasing more qgroup metadata rsv than we have
+reserved.
+
+This won't trigger selftest warning, as btrfs qgroup metadata rsv has
+extra protection against cases like quota enabled half-way.
+
+But we still need to fix this problem any way.
+
+This patch will use the same num_bytes for qgroup metadata rsv so we
+could handle it correctly.
+
+Fixes: f218ea6c4792 ("btrfs: delayed-inode: Remove wrong qgroup meta reservation calls")
+CC: stable@vger.kernel.org # 4.19+
+Reviewed-by: Josef Bacik <josef@toxicpanda.com>
+Signed-off-by: Qu Wenruo <wqu@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/btrfs/delayed-inode.c |    3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+--- a/fs/btrfs/delayed-inode.c
++++ b/fs/btrfs/delayed-inode.c
+@@ -627,8 +627,7 @@ static int btrfs_delayed_inode_reserve_m
+        */
+       if (!src_rsv || (!trans->bytes_reserved &&
+                        src_rsv->type != BTRFS_BLOCK_RSV_DELALLOC)) {
+-              ret = btrfs_qgroup_reserve_meta_prealloc(root,
+-                              fs_info->nodesize, true);
++              ret = btrfs_qgroup_reserve_meta_prealloc(root, num_bytes, true);
+               if (ret < 0)
+                       return ret;
+               ret = btrfs_block_rsv_add(root, dst_rsv, num_bytes,
diff --git a/queue-5.4/btrfs-reschedule-if-necessary-when-logging-directory-items.patch b/queue-5.4/btrfs-reschedule-if-necessary-when-logging-directory-items.patch
new file mode 100644 (file)
index 0000000..5feafbd
--- /dev/null
@@ -0,0 +1,111 @@
+From bb56f02f26fe23798edb1b2175707419b28c752a Mon Sep 17 00:00:00 2001
+From: Filipe Manana <fdmanana@suse.com>
+Date: Mon, 14 Sep 2020 15:27:50 +0100
+Subject: btrfs: reschedule if necessary when logging directory items
+
+From: Filipe Manana <fdmanana@suse.com>
+
+commit bb56f02f26fe23798edb1b2175707419b28c752a upstream.
+
+Logging directories with many entries can take a significant amount of
+time, and in some cases monopolize a cpu/core for a long time if the
+logging task doesn't happen to block often enough.
+
+Johannes and Lu Fengqi reported test case generic/041 triggering a soft
+lockup when the kernel has CONFIG_SOFTLOCKUP_DETECTOR=y. For this test
+case we log an inode with 3002 hard links, and because the test removed
+one hard link before fsyncing the file, the inode logging causes the
+parent directory do be logged as well, which has 6004 directory items to
+log (3002 BTRFS_DIR_ITEM_KEY items plus 3002 BTRFS_DIR_INDEX_KEY items),
+so it can take a significant amount of time and trigger the soft lockup.
+
+So just make tree-log.c:log_dir_items() reschedule when necessary,
+releasing the current search path before doing so and then resume from
+where it was before the reschedule.
+
+The stack trace produced when the soft lockup happens is the following:
+
+[10480.277653] watchdog: BUG: soft lockup - CPU#2 stuck for 22s! [xfs_io:28172]
+[10480.279418] Modules linked in: dm_thin_pool dm_persistent_data (...)
+[10480.284915] irq event stamp: 29646366
+[10480.285987] hardirqs last  enabled at (29646365): [<ffffffff85249b66>] __slab_alloc.constprop.0+0x56/0x60
+[10480.288482] hardirqs last disabled at (29646366): [<ffffffff8579b00d>] irqentry_enter+0x1d/0x50
+[10480.290856] softirqs last  enabled at (4612): [<ffffffff85a00323>] __do_softirq+0x323/0x56c
+[10480.293615] softirqs last disabled at (4483): [<ffffffff85800dbf>] asm_call_on_stack+0xf/0x20
+[10480.296428] CPU: 2 PID: 28172 Comm: xfs_io Not tainted 5.9.0-rc4-default+ #1248
+[10480.298948] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.12.0-59-gc9ba527-rebuilt.opensuse.org 04/01/2014
+[10480.302455] RIP: 0010:__slab_alloc.constprop.0+0x19/0x60
+[10480.304151] Code: 86 e8 31 75 21 00 66 66 2e 0f 1f 84 00 00 00 (...)
+[10480.309558] RSP: 0018:ffffadbe09397a58 EFLAGS: 00000282
+[10480.311179] RAX: ffff8a495ab92840 RBX: 0000000000000282 RCX: 0000000000000006
+[10480.313242] RDX: 0000000000000000 RSI: 0000000000000000 RDI: ffffffff85249b66
+[10480.315260] RBP: ffff8a497d04b740 R08: 0000000000000001 R09: 0000000000000001
+[10480.317229] R10: ffff8a497d044800 R11: ffff8a495ab93c40 R12: 0000000000000000
+[10480.319169] R13: 0000000000000000 R14: 0000000000000c40 R15: ffffffffc01daf70
+[10480.321104] FS:  00007fa1dc5c0e40(0000) GS:ffff8a497da00000(0000) knlGS:0000000000000000
+[10480.323559] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+[10480.325235] CR2: 00007fa1dc5befb8 CR3: 0000000004f8a006 CR4: 0000000000170ea0
+[10480.327259] Call Trace:
+[10480.328286]  ? overwrite_item+0x1f0/0x5a0 [btrfs]
+[10480.329784]  __kmalloc+0x831/0xa20
+[10480.331009]  ? btrfs_get_32+0xb0/0x1d0 [btrfs]
+[10480.332464]  overwrite_item+0x1f0/0x5a0 [btrfs]
+[10480.333948]  log_dir_items+0x2ee/0x570 [btrfs]
+[10480.335413]  log_directory_changes+0x82/0xd0 [btrfs]
+[10480.336926]  btrfs_log_inode+0xc9b/0xda0 [btrfs]
+[10480.338374]  ? init_once+0x20/0x20 [btrfs]
+[10480.339711]  btrfs_log_inode_parent+0x8d3/0xd10 [btrfs]
+[10480.341257]  ? dget_parent+0x97/0x2e0
+[10480.342480]  btrfs_log_dentry_safe+0x3a/0x50 [btrfs]
+[10480.343977]  btrfs_sync_file+0x24b/0x5e0 [btrfs]
+[10480.345381]  do_fsync+0x38/0x70
+[10480.346483]  __x64_sys_fsync+0x10/0x20
+[10480.347703]  do_syscall_64+0x2d/0x70
+[10480.348891]  entry_SYSCALL_64_after_hwframe+0x44/0xa9
+[10480.350444] RIP: 0033:0x7fa1dc80970b
+[10480.351642] Code: 0f 05 48 3d 00 f0 ff ff 77 45 c3 0f 1f 40 00 48 (...)
+[10480.356952] RSP: 002b:00007fffb3d081d0 EFLAGS: 00000293 ORIG_RAX: 000000000000004a
+[10480.359458] RAX: ffffffffffffffda RBX: 0000562d93d45e40 RCX: 00007fa1dc80970b
+[10480.361426] RDX: 0000562d93d44ab0 RSI: 0000562d93d45e60 RDI: 0000000000000003
+[10480.363367] RBP: 0000000000000001 R08: 0000000000000000 R09: 00007fa1dc7b2a40
+[10480.365317] R10: 0000562d93d0e366 R11: 0000000000000293 R12: 0000000000000001
+[10480.367299] R13: 0000562d93d45290 R14: 0000562d93d45e40 R15: 0000562d93d45e60
+
+Link: https://lore.kernel.org/linux-btrfs/20180713090216.GC575@fnst.localdomain/
+Reported-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
+CC: stable@vger.kernel.org # 4.4+
+Tested-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
+Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
+Signed-off-by: Filipe Manana <fdmanana@suse.com>
+Reviewed-by: David Sterba <dsterba@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/btrfs/tree-log.c |    8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+--- a/fs/btrfs/tree-log.c
++++ b/fs/btrfs/tree-log.c
+@@ -3639,6 +3639,7 @@ static noinline int log_dir_items(struct
+        * search and this search we'll not find the key again and can just
+        * bail.
+        */
++search:
+       ret = btrfs_search_slot(NULL, root, &min_key, path, 0, 0);
+       if (ret != 0)
+               goto done;
+@@ -3658,6 +3659,13 @@ static noinline int log_dir_items(struct
+                       if (min_key.objectid != ino || min_key.type != key_type)
+                               goto done;
++
++                      if (need_resched()) {
++                              btrfs_release_path(path);
++                              cond_resched();
++                              goto search;
++                      }
++
+                       ret = overwrite_item(trans, log, dst_path, src, i,
+                                            &min_key);
+                       if (ret) {
diff --git a/queue-5.4/btrfs-send-orphanize-first-all-conflicting-inodes-when-processing-references.patch b/queue-5.4/btrfs-send-orphanize-first-all-conflicting-inodes-when-processing-references.patch
new file mode 100644 (file)
index 0000000..af4cb8c
--- /dev/null
@@ -0,0 +1,273 @@
+From 98272bb77bf4cc20ed1ffca89832d713e70ebf09 Mon Sep 17 00:00:00 2001
+From: Filipe Manana <fdmanana@suse.com>
+Date: Mon, 21 Sep 2020 14:13:29 +0100
+Subject: btrfs: send, orphanize first all conflicting inodes when processing references
+
+From: Filipe Manana <fdmanana@suse.com>
+
+commit 98272bb77bf4cc20ed1ffca89832d713e70ebf09 upstream.
+
+When doing an incremental send it is possible that when processing the new
+references for an inode we end up issuing rename or link operations that
+have an invalid path, which contains the orphanized name of a directory
+before we actually orphanized it, causing the receiver to fail.
+
+The following reproducer triggers such scenario:
+
+  $ cat reproducer.sh
+  #!/bin/bash
+
+  mkfs.btrfs -f /dev/sdi >/dev/null
+  mount /dev/sdi /mnt/sdi
+
+  touch /mnt/sdi/a
+  touch /mnt/sdi/b
+  mkdir /mnt/sdi/testdir
+  # We want "a" to have a lower inode number then "testdir" (257 vs 259).
+  mv /mnt/sdi/a /mnt/sdi/testdir/a
+
+  # Filesystem looks like:
+  #
+  # .                           (ino 256)
+  # |----- testdir/             (ino 259)
+  # |          |----- a         (ino 257)
+  # |
+  # |----- b                    (ino 258)
+
+  btrfs subvolume snapshot -r /mnt/sdi /mnt/sdi/snap1
+  btrfs send -f /tmp/snap1.send /mnt/sdi/snap1
+
+  # Now rename 259 to "testdir_2", then change the name of 257 to
+  # "testdir" and make it a direct descendant of the root inode (256).
+  # Also create a new link for inode 257 with the old name of inode 258.
+  # By swapping the names and location of several inodes and create a
+  # nasty dependency chain of rename and link operations.
+  mv /mnt/sdi/testdir/a /mnt/sdi/a2
+  touch /mnt/sdi/testdir/a
+  mv /mnt/sdi/b /mnt/sdi/b2
+  ln /mnt/sdi/a2 /mnt/sdi/b
+  mv /mnt/sdi/testdir /mnt/sdi/testdir_2
+  mv /mnt/sdi/a2 /mnt/sdi/testdir
+
+  # Filesystem now looks like:
+  #
+  # .                            (ino 256)
+  # |----- testdir_2/            (ino 259)
+  # |          |----- a          (ino 260)
+  # |
+  # |----- testdir               (ino 257)
+  # |----- b                     (ino 257)
+  # |----- b2                    (ino 258)
+
+  btrfs subvolume snapshot -r /mnt/sdi /mnt/sdi/snap2
+  btrfs send -f /tmp/snap2.send -p /mnt/sdi/snap1 /mnt/sdi/snap2
+
+  mkfs.btrfs -f /dev/sdj >/dev/null
+  mount /dev/sdj /mnt/sdj
+
+  btrfs receive -f /tmp/snap1.send /mnt/sdj
+  btrfs receive -f /tmp/snap2.send /mnt/sdj
+
+  umount /mnt/sdi
+  umount /mnt/sdj
+
+When running the reproducer, the receive of the incremental send stream
+fails:
+
+  $ ./reproducer.sh
+  Create a readonly snapshot of '/mnt/sdi' in '/mnt/sdi/snap1'
+  At subvol /mnt/sdi/snap1
+  Create a readonly snapshot of '/mnt/sdi' in '/mnt/sdi/snap2'
+  At subvol /mnt/sdi/snap2
+  At subvol snap1
+  At snapshot snap2
+  ERROR: link b -> o259-6-0/a failed: No such file or directory
+
+The problem happens because of the following:
+
+1) Before we start iterating the list of new references for inode 257,
+   we generate its current path and store it at @valid_path, done at
+   the very beginning of process_recorded_refs(). The generated path
+   is "o259-6-0/a", containing the orphanized name for inode 259;
+
+2) Then we iterate over the list of new references, which has the
+   references "b" and "testdir" in that specific order;
+
+3) We process reference "b" first, because it is in the list before
+   reference "testdir". We then issue a link operation to create
+   the new reference "b" using a target path corresponding to the
+   content at @valid_path, which corresponds to "o259-6-0/a".
+   However we haven't yet orphanized inode 259, its name is still
+   "testdir", and not "o259-6-0". The orphanization of 259 did not
+   happen yet because we will process the reference named "testdir"
+   for inode 257 only in the next iteration of the loop that goes
+   over the list of new references.
+
+Fix the issue by having a preliminar iteration over all the new references
+at process_recorded_refs(). This iteration is responsible only for doing
+the orphanization of other inodes that have and old reference that
+conflicts with one of the new references of the inode we are currently
+processing. The emission of rename and link operations happen now in the
+next iteration of the new references.
+
+A test case for fstests will follow soon.
+
+CC: stable@vger.kernel.org # 4.4+
+Reviewed-by: Josef Bacik <josef@toxicpanda.com>
+Signed-off-by: Filipe Manana <fdmanana@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/btrfs/send.c |  127 ++++++++++++++++++++++++++++++++++++++------------------
+ 1 file changed, 87 insertions(+), 40 deletions(-)
+
+--- a/fs/btrfs/send.c
++++ b/fs/btrfs/send.c
+@@ -3880,52 +3880,56 @@ static int process_recorded_refs(struct
+                       goto out;
+       }
++      /*
++       * Before doing any rename and link operations, do a first pass on the
++       * new references to orphanize any unprocessed inodes that may have a
++       * reference that conflicts with one of the new references of the current
++       * inode. This needs to happen first because a new reference may conflict
++       * with the old reference of a parent directory, so we must make sure
++       * that the path used for link and rename commands don't use an
++       * orphanized name when an ancestor was not yet orphanized.
++       *
++       * Example:
++       *
++       * Parent snapshot:
++       *
++       * .                                                      (ino 256)
++       * |----- testdir/                                        (ino 259)
++       * |          |----- a                                    (ino 257)
++       * |
++       * |----- b                                               (ino 258)
++       *
++       * Send snapshot:
++       *
++       * .                                                      (ino 256)
++       * |----- testdir_2/                                      (ino 259)
++       * |          |----- a                                    (ino 260)
++       * |
++       * |----- testdir                                         (ino 257)
++       * |----- b                                               (ino 257)
++       * |----- b2                                              (ino 258)
++       *
++       * Processing the new reference for inode 257 with name "b" may happen
++       * before processing the new reference with name "testdir". If so, we
++       * must make sure that by the time we send a link command to create the
++       * hard link "b", inode 259 was already orphanized, since the generated
++       * path in "valid_path" already contains the orphanized name for 259.
++       * We are processing inode 257, so only later when processing 259 we do
++       * the rename operation to change its temporary (orphanized) name to
++       * "testdir_2".
++       */
+       list_for_each_entry(cur, &sctx->new_refs, list) {
+-              /*
+-               * We may have refs where the parent directory does not exist
+-               * yet. This happens if the parent directories inum is higher
+-               * than the current inum. To handle this case, we create the
+-               * parent directory out of order. But we need to check if this
+-               * did already happen before due to other refs in the same dir.
+-               */
+               ret = get_cur_inode_state(sctx, cur->dir, cur->dir_gen);
+               if (ret < 0)
+                       goto out;
+-              if (ret == inode_state_will_create) {
+-                      ret = 0;
+-                      /*
+-                       * First check if any of the current inodes refs did
+-                       * already create the dir.
+-                       */
+-                      list_for_each_entry(cur2, &sctx->new_refs, list) {
+-                              if (cur == cur2)
+-                                      break;
+-                              if (cur2->dir == cur->dir) {
+-                                      ret = 1;
+-                                      break;
+-                              }
+-                      }
+-
+-                      /*
+-                       * If that did not happen, check if a previous inode
+-                       * did already create the dir.
+-                       */
+-                      if (!ret)
+-                              ret = did_create_dir(sctx, cur->dir);
+-                      if (ret < 0)
+-                              goto out;
+-                      if (!ret) {
+-                              ret = send_create_inode(sctx, cur->dir);
+-                              if (ret < 0)
+-                                      goto out;
+-                      }
+-              }
++              if (ret == inode_state_will_create)
++                      continue;
+               /*
+-               * Check if this new ref would overwrite the first ref of
+-               * another unprocessed inode. If yes, orphanize the
+-               * overwritten inode. If we find an overwritten ref that is
+-               * not the first ref, simply unlink it.
++               * Check if this new ref would overwrite the first ref of another
++               * unprocessed inode. If yes, orphanize the overwritten inode.
++               * If we find an overwritten ref that is not the first ref,
++               * simply unlink it.
+                */
+               ret = will_overwrite_ref(sctx, cur->dir, cur->dir_gen,
+                               cur->name, cur->name_len,
+@@ -4002,6 +4006,49 @@ static int process_recorded_refs(struct
+                               if (ret < 0)
+                                       goto out;
+                       }
++              }
++
++      }
++
++      list_for_each_entry(cur, &sctx->new_refs, list) {
++              /*
++               * We may have refs where the parent directory does not exist
++               * yet. This happens if the parent directories inum is higher
++               * than the current inum. To handle this case, we create the
++               * parent directory out of order. But we need to check if this
++               * did already happen before due to other refs in the same dir.
++               */
++              ret = get_cur_inode_state(sctx, cur->dir, cur->dir_gen);
++              if (ret < 0)
++                      goto out;
++              if (ret == inode_state_will_create) {
++                      ret = 0;
++                      /*
++                       * First check if any of the current inodes refs did
++                       * already create the dir.
++                       */
++                      list_for_each_entry(cur2, &sctx->new_refs, list) {
++                              if (cur == cur2)
++                                      break;
++                              if (cur2->dir == cur->dir) {
++                                      ret = 1;
++                                      break;
++                              }
++                      }
++
++                      /*
++                       * If that did not happen, check if a previous inode
++                       * did already create the dir.
++                       */
++                      if (!ret)
++                              ret = did_create_dir(sctx, cur->dir);
++                      if (ret < 0)
++                              goto out;
++                      if (!ret) {
++                              ret = send_create_inode(sctx, cur->dir);
++                              if (ret < 0)
++                                      goto out;
++                      }
+               }
+               if (S_ISDIR(sctx->cur_inode_mode) && sctx->parent_root) {
diff --git a/queue-5.4/btrfs-send-recompute-reference-path-after-orphanization-of-a-directory.patch b/queue-5.4/btrfs-send-recompute-reference-path-after-orphanization-of-a-directory.patch
new file mode 100644 (file)
index 0000000..40bb114
--- /dev/null
@@ -0,0 +1,244 @@
+From 9c2b4e0347067396ceb3ae929d6888c81d610259 Mon Sep 17 00:00:00 2001
+From: Filipe Manana <fdmanana@suse.com>
+Date: Mon, 21 Sep 2020 14:13:30 +0100
+Subject: btrfs: send, recompute reference path after orphanization of a directory
+
+From: Filipe Manana <fdmanana@suse.com>
+
+commit 9c2b4e0347067396ceb3ae929d6888c81d610259 upstream.
+
+During an incremental send, when an inode has multiple new references we
+might end up emitting rename operations for orphanizations that have a
+source path that is no longer valid due to a previous orphanization of
+some directory inode. This causes the receiver to fail since it tries
+to rename a path that does not exists.
+
+Example reproducer:
+
+  $ cat reproducer.sh
+  #!/bin/bash
+
+  mkfs.btrfs -f /dev/sdi >/dev/null
+  mount /dev/sdi /mnt/sdi
+
+  touch /mnt/sdi/f1
+  touch /mnt/sdi/f2
+  mkdir /mnt/sdi/d1
+  mkdir /mnt/sdi/d1/d2
+
+  # Filesystem looks like:
+  #
+  # .                           (ino 256)
+  # |----- f1                   (ino 257)
+  # |----- f2                   (ino 258)
+  # |----- d1/                  (ino 259)
+  #        |----- d2/           (ino 260)
+
+  btrfs subvolume snapshot -r /mnt/sdi /mnt/sdi/snap1
+  btrfs send -f /tmp/snap1.send /mnt/sdi/snap1
+
+  # Now do a series of changes such that:
+  #
+  # *) inode 258 has one new hardlink and the previous name changed
+  #
+  # *) both names conflict with the old names of two other inodes:
+  #
+  #    1) the new name "d1" conflicts with the old name of inode 259,
+  #       under directory inode 256 (root)
+  #
+  #    2) the new name "d2" conflicts with the old name of inode 260
+  #       under directory inode 259
+  #
+  # *) inodes 259 and 260 now have the old names of inode 258
+  #
+  # *) inode 257 is now located under inode 260 - an inode with a number
+  #    smaller than the inode (258) for which we created a second hard
+  #    link and swapped its names with inodes 259 and 260
+  #
+  ln /mnt/sdi/f2 /mnt/sdi/d1/f2_link
+  mv /mnt/sdi/f1 /mnt/sdi/d1/d2/f1
+
+  # Swap d1 and f2.
+  mv /mnt/sdi/d1 /mnt/sdi/tmp
+  mv /mnt/sdi/f2 /mnt/sdi/d1
+  mv /mnt/sdi/tmp /mnt/sdi/f2
+
+  # Swap d2 and f2_link
+  mv /mnt/sdi/f2/d2 /mnt/sdi/tmp
+  mv /mnt/sdi/f2/f2_link /mnt/sdi/f2/d2
+  mv /mnt/sdi/tmp /mnt/sdi/f2/f2_link
+
+  # Filesystem now looks like:
+  #
+  # .                                (ino 256)
+  # |----- d1                        (ino 258)
+  # |----- f2/                       (ino 259)
+  #        |----- f2_link/           (ino 260)
+  #        |       |----- f1         (ino 257)
+  #        |
+  #        |----- d2                 (ino 258)
+
+  btrfs subvolume snapshot -r /mnt/sdi /mnt/sdi/snap2
+  btrfs send -f /tmp/snap2.send -p /mnt/sdi/snap1 /mnt/sdi/snap2
+
+  mkfs.btrfs -f /dev/sdj >/dev/null
+  mount /dev/sdj /mnt/sdj
+
+  btrfs receive -f /tmp/snap1.send /mnt/sdj
+  btrfs receive -f /tmp/snap2.send /mnt/sdj
+
+  umount /mnt/sdi
+  umount /mnt/sdj
+
+When executed the receive of the incremental stream fails:
+
+  $ ./reproducer.sh
+  Create a readonly snapshot of '/mnt/sdi' in '/mnt/sdi/snap1'
+  At subvol /mnt/sdi/snap1
+  Create a readonly snapshot of '/mnt/sdi' in '/mnt/sdi/snap2'
+  At subvol /mnt/sdi/snap2
+  At subvol snap1
+  At snapshot snap2
+  ERROR: rename d1/d2 -> o260-6-0 failed: No such file or directory
+
+This happens because:
+
+1) When processing inode 257 we end up computing the name for inode 259
+   because it is an ancestor in the send snapshot, and at that point it
+   still has its old name, "d1", from the parent snapshot because inode
+   259 was not yet processed. We then cache that name, which is valid
+   until we start processing inode 259 (or set the progress to 260 after
+   processing its references);
+
+2) Later we start processing inode 258 and collecting all its new
+   references into the list sctx->new_refs. The first reference in the
+   list happens to be the reference for name "d1" while the reference for
+   name "d2" is next (the last element of the list).
+   We compute the full path "d1/d2" for this second reference and store
+   it in the reference (its ->full_path member). The path used for the
+   new parent directory was "d1" and not "f2" because inode 259, the
+   new parent, was not yet processed;
+
+3) When we start processing the new references at process_recorded_refs()
+   we start with the first reference in the list, for the new name "d1".
+   Because there is a conflicting inode that was not yet processed, which
+   is directory inode 259, we orphanize it, renaming it from "d1" to
+   "o259-6-0";
+
+4) Then we start processing the new reference for name "d2", and we
+   realize it conflicts with the reference of inode 260 in the parent
+   snapshot. So we issue an orphanization operation for inode 260 by
+   emitting a rename operation with a destination path of "o260-6-0"
+   and a source path of "d1/d2" - this source path is the value we
+   stored in the reference earlier at step 2), corresponding to the
+   ->full_path member of the reference, however that path is no longer
+   valid due to the orphanization of the directory inode 259 in step 3).
+   This makes the receiver fail since the path does not exists, it should
+   have been "o259-6-0/d2".
+
+Fix this by recomputing the full path of a reference before emitting an
+orphanization if we previously orphanized any directory, since that
+directory could be a parent in the new path. This is a rare scenario so
+keeping it simple and not checking if that previously orphanized directory
+is in fact an ancestor of the inode we are trying to orphanize.
+
+A test case for fstests follows soon.
+
+CC: stable@vger.kernel.org # 4.4+
+Reviewed-by: Josef Bacik <josef@toxicpanda.com>
+Signed-off-by: Filipe Manana <fdmanana@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/btrfs/send.c |   72 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 72 insertions(+)
+
+--- a/fs/btrfs/send.c
++++ b/fs/btrfs/send.c
+@@ -3813,6 +3813,72 @@ static int update_ref_path(struct send_c
+ }
+ /*
++ * When processing the new references for an inode we may orphanize an existing
++ * directory inode because its old name conflicts with one of the new references
++ * of the current inode. Later, when processing another new reference of our
++ * inode, we might need to orphanize another inode, but the path we have in the
++ * reference reflects the pre-orphanization name of the directory we previously
++ * orphanized. For example:
++ *
++ * parent snapshot looks like:
++ *
++ * .                                     (ino 256)
++ * |----- f1                             (ino 257)
++ * |----- f2                             (ino 258)
++ * |----- d1/                            (ino 259)
++ *        |----- d2/                     (ino 260)
++ *
++ * send snapshot looks like:
++ *
++ * .                                     (ino 256)
++ * |----- d1                             (ino 258)
++ * |----- f2/                            (ino 259)
++ *        |----- f2_link/                (ino 260)
++ *        |       |----- f1              (ino 257)
++ *        |
++ *        |----- d2                      (ino 258)
++ *
++ * When processing inode 257 we compute the name for inode 259 as "d1", and we
++ * cache it in the name cache. Later when we start processing inode 258, when
++ * collecting all its new references we set a full path of "d1/d2" for its new
++ * reference with name "d2". When we start processing the new references we
++ * start by processing the new reference with name "d1", and this results in
++ * orphanizing inode 259, since its old reference causes a conflict. Then we
++ * move on the next new reference, with name "d2", and we find out we must
++ * orphanize inode 260, as its old reference conflicts with ours - but for the
++ * orphanization we use a source path corresponding to the path we stored in the
++ * new reference, which is "d1/d2" and not "o259-6-0/d2" - this makes the
++ * receiver fail since the path component "d1/" no longer exists, it was renamed
++ * to "o259-6-0/" when processing the previous new reference. So in this case we
++ * must recompute the path in the new reference and use it for the new
++ * orphanization operation.
++ */
++static int refresh_ref_path(struct send_ctx *sctx, struct recorded_ref *ref)
++{
++      char *name;
++      int ret;
++
++      name = kmemdup(ref->name, ref->name_len, GFP_KERNEL);
++      if (!name)
++              return -ENOMEM;
++
++      fs_path_reset(ref->full_path);
++      ret = get_cur_path(sctx, ref->dir, ref->dir_gen, ref->full_path);
++      if (ret < 0)
++              goto out;
++
++      ret = fs_path_add(ref->full_path, name, ref->name_len);
++      if (ret < 0)
++              goto out;
++
++      /* Update the reference's base name pointer. */
++      set_ref_path(ref, ref->full_path);
++out:
++      kfree(name);
++      return ret;
++}
++
++/*
+  * This does all the move/link/unlink/rmdir magic.
+  */
+ static int process_recorded_refs(struct send_ctx *sctx, int *pending_move)
+@@ -3946,6 +4012,12 @@ static int process_recorded_refs(struct
+                               struct name_cache_entry *nce;
+                               struct waiting_dir_move *wdm;
++                              if (orphanized_dir) {
++                                      ret = refresh_ref_path(sctx, cur);
++                                      if (ret < 0)
++                                              goto out;
++                              }
++
+                               ret = orphanize_inode(sctx, ow_inode, ow_gen,
+                                               cur->full_path);
+                               if (ret < 0)
diff --git a/queue-5.4/btrfs-tree-checker-fix-false-alert-caused-by-legacy-btrfs-root-item.patch b/queue-5.4/btrfs-tree-checker-fix-false-alert-caused-by-legacy-btrfs-root-item.patch
new file mode 100644 (file)
index 0000000..6b01669
--- /dev/null
@@ -0,0 +1,102 @@
+From 1465af12e254a68706e110846f59cf0f09683184 Mon Sep 17 00:00:00 2001
+From: Qu Wenruo <wqu@suse.com>
+Date: Tue, 22 Sep 2020 10:37:01 +0800
+Subject: btrfs: tree-checker: fix false alert caused by legacy btrfs root item
+
+From: Qu Wenruo <wqu@suse.com>
+
+commit 1465af12e254a68706e110846f59cf0f09683184 upstream.
+
+Commit 259ee7754b67 ("btrfs: tree-checker: Add ROOT_ITEM check")
+introduced btrfs root item size check, however btrfs root item has two
+versions, the legacy one which just ends before generation_v2 member, is
+smaller than current btrfs root item size.
+
+This caused btrfs kernel to reject valid but old tree root leaves.
+
+Fix this problem by also allowing legacy root item, since kernel can
+already handle them pretty well and upgrade to newer root item format
+when needed.
+
+Reported-by: Martin Steigerwald <martin@lichtvoll.de>
+Fixes: 259ee7754b67 ("btrfs: tree-checker: Add ROOT_ITEM check")
+CC: stable@vger.kernel.org # 5.4+
+Tested-By: Martin Steigerwald <martin@lichtvoll.de>
+Reviewed-by: Josef Bacik <josef@toxicpanda.com>
+Signed-off-by: Qu Wenruo <wqu@suse.com>
+Reviewed-by: David Sterba <dsterba@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/btrfs/tree-checker.c         |   17 ++++++++++++-----
+ include/uapi/linux/btrfs_tree.h |   14 ++++++++++++++
+ 2 files changed, 26 insertions(+), 5 deletions(-)
+
+--- a/fs/btrfs/tree-checker.c
++++ b/fs/btrfs/tree-checker.c
+@@ -869,7 +869,7 @@ static int check_root_item(struct extent
+                          int slot)
+ {
+       struct btrfs_fs_info *fs_info = leaf->fs_info;
+-      struct btrfs_root_item ri;
++      struct btrfs_root_item ri = { 0 };
+       const u64 valid_root_flags = BTRFS_ROOT_SUBVOL_RDONLY |
+                                    BTRFS_ROOT_SUBVOL_DEAD;
+@@ -889,14 +889,21 @@ static int check_root_item(struct extent
+               return -EUCLEAN;
+       }
+-      if (btrfs_item_size_nr(leaf, slot) != sizeof(ri)) {
++      if (btrfs_item_size_nr(leaf, slot) != sizeof(ri) &&
++          btrfs_item_size_nr(leaf, slot) != btrfs_legacy_root_item_size()) {
+               generic_err(leaf, slot,
+-                          "invalid root item size, have %u expect %zu",
+-                          btrfs_item_size_nr(leaf, slot), sizeof(ri));
++                          "invalid root item size, have %u expect %zu or %u",
++                          btrfs_item_size_nr(leaf, slot), sizeof(ri),
++                          btrfs_legacy_root_item_size());
+       }
++      /*
++       * For legacy root item, the members starting at generation_v2 will be
++       * all filled with 0.
++       * And since we allow geneartion_v2 as 0, it will still pass the check.
++       */
+       read_extent_buffer(leaf, &ri, btrfs_item_ptr_offset(leaf, slot),
+-                         sizeof(ri));
++                         btrfs_item_size_nr(leaf, slot));
+       /* Generation related */
+       if (btrfs_root_generation(&ri) >
+--- a/include/uapi/linux/btrfs_tree.h
++++ b/include/uapi/linux/btrfs_tree.h
+@@ -4,6 +4,11 @@
+ #include <linux/btrfs.h>
+ #include <linux/types.h>
++#ifdef __KERNEL__
++#include <linux/stddef.h>
++#else
++#include <stddef.h>
++#endif
+ /*
+  * This header contains the structure definitions and constants used
+@@ -651,6 +656,15 @@ struct btrfs_root_item {
+ } __attribute__ ((__packed__));
+ /*
++ * Btrfs root item used to be smaller than current size.  The old format ends
++ * at where member generation_v2 is.
++ */
++static inline __u32 btrfs_legacy_root_item_size(void)
++{
++      return offsetof(struct btrfs_root_item, generation_v2);
++}
++
++/*
+  * this is used for both forward and backward root refs
+  */
+ struct btrfs_root_ref {
diff --git a/queue-5.4/btrfs-tree-checker-validate-number-of-chunk-stripes-and-parity.patch b/queue-5.4/btrfs-tree-checker-validate-number-of-chunk-stripes-and-parity.patch
new file mode 100644 (file)
index 0000000..118c385
--- /dev/null
@@ -0,0 +1,64 @@
+From 85d07fbe09efd1c529ff3e025e2f0d2c6c96a1b7 Mon Sep 17 00:00:00 2001
+From: Daniel Xu <dxu@dxuuu.xyz>
+Date: Thu, 8 Oct 2020 18:09:10 -0700
+Subject: btrfs: tree-checker: validate number of chunk stripes and parity
+
+From: Daniel Xu <dxu@dxuuu.xyz>
+
+commit 85d07fbe09efd1c529ff3e025e2f0d2c6c96a1b7 upstream.
+
+If there's no parity and num_stripes < ncopies, a crafted image can
+trigger a division by zero in calc_stripe_length().
+
+The image was generated through fuzzing.
+
+CC: stable@vger.kernel.org # 5.4+
+Reviewed-by: Qu Wenruo <wqu@suse.com>
+Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=209587
+Signed-off-by: Daniel Xu <dxu@dxuuu.xyz>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/btrfs/tree-checker.c |   18 ++++++++++++++++++
+ 1 file changed, 18 insertions(+)
+
+--- a/fs/btrfs/tree-checker.c
++++ b/fs/btrfs/tree-checker.c
+@@ -577,18 +577,36 @@ int btrfs_check_chunk_valid(struct exten
+       u64 type;
+       u64 features;
+       bool mixed = false;
++      int raid_index;
++      int nparity;
++      int ncopies;
+       length = btrfs_chunk_length(leaf, chunk);
+       stripe_len = btrfs_chunk_stripe_len(leaf, chunk);
+       num_stripes = btrfs_chunk_num_stripes(leaf, chunk);
+       sub_stripes = btrfs_chunk_sub_stripes(leaf, chunk);
+       type = btrfs_chunk_type(leaf, chunk);
++      raid_index = btrfs_bg_flags_to_raid_index(type);
++      ncopies = btrfs_raid_array[raid_index].ncopies;
++      nparity = btrfs_raid_array[raid_index].nparity;
+       if (!num_stripes) {
+               chunk_err(leaf, chunk, logical,
+                         "invalid chunk num_stripes, have %u", num_stripes);
+               return -EUCLEAN;
+       }
++      if (num_stripes < ncopies) {
++              chunk_err(leaf, chunk, logical,
++                        "invalid chunk num_stripes < ncopies, have %u < %d",
++                        num_stripes, ncopies);
++              return -EUCLEAN;
++      }
++      if (nparity && num_stripes == nparity) {
++              chunk_err(leaf, chunk, logical,
++                        "invalid chunk num_stripes == nparity, have %u == %d",
++                        num_stripes, nparity);
++              return -EUCLEAN;
++      }
+       if (!IS_ALIGNED(logical, fs_info->sectorsize)) {
+               chunk_err(leaf, chunk, logical,
+               "invalid chunk logical, have %llu should aligned to %u",
diff --git a/queue-5.4/btrfs-use-kvzalloc-to-allocate-clone_roots-in-btrfs_ioctl_send.patch b/queue-5.4/btrfs-use-kvzalloc-to-allocate-clone_roots-in-btrfs_ioctl_send.patch
new file mode 100644 (file)
index 0000000..932f9a0
--- /dev/null
@@ -0,0 +1,37 @@
+From 8eb2fd00153a3a96a19c62ac9c6d48c2efebe5e8 Mon Sep 17 00:00:00 2001
+From: Denis Efremov <efremov@linux.com>
+Date: Mon, 21 Sep 2020 20:03:35 +0300
+Subject: btrfs: use kvzalloc() to allocate clone_roots in btrfs_ioctl_send()
+
+From: Denis Efremov <efremov@linux.com>
+
+commit 8eb2fd00153a3a96a19c62ac9c6d48c2efebe5e8 upstream.
+
+btrfs_ioctl_send() used open-coded kvzalloc implementation earlier.
+The code was accidentally replaced with kzalloc() call [1]. Restore
+the original code by using kvzalloc() to allocate sctx->clone_roots.
+
+[1] https://patchwork.kernel.org/patch/9757891/#20529627
+
+Fixes: 818e010bf9d0 ("btrfs: replace opencoded kvzalloc with the helper")
+CC: stable@vger.kernel.org # 4.14+
+Signed-off-by: Denis Efremov <efremov@linux.com>
+Reviewed-by: David Sterba <dsterba@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/btrfs/send.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/fs/btrfs/send.c
++++ b/fs/btrfs/send.c
+@@ -7352,7 +7352,7 @@ long btrfs_ioctl_send(struct file *mnt_f
+       alloc_size = sizeof(struct clone_root) * (arg->clone_sources_count + 1);
+-      sctx->clone_roots = kzalloc(alloc_size, GFP_KERNEL);
++      sctx->clone_roots = kvzalloc(alloc_size, GFP_KERNEL);
+       if (!sctx->clone_roots) {
+               ret = -ENOMEM;
+               goto out;
diff --git a/queue-5.4/dmaengine-dma-jz4780-fix-race-in-jz4780_dma_tx_status.patch b/queue-5.4/dmaengine-dma-jz4780-fix-race-in-jz4780_dma_tx_status.patch
new file mode 100644 (file)
index 0000000..97ddaff
--- /dev/null
@@ -0,0 +1,57 @@
+From baf6fd97b16ea8f981b8a8b04039596f32fc2972 Mon Sep 17 00:00:00 2001
+From: Paul Cercueil <paul@crapouillou.net>
+Date: Sun, 4 Oct 2020 16:03:07 +0200
+Subject: dmaengine: dma-jz4780: Fix race in jz4780_dma_tx_status
+
+From: Paul Cercueil <paul@crapouillou.net>
+
+commit baf6fd97b16ea8f981b8a8b04039596f32fc2972 upstream.
+
+The jz4780_dma_tx_status() function would check if a channel's cookie
+state was set to 'completed', and if not, it would enter the critical
+section. However, in that time frame, the jz4780_dma_chan_irq() function
+was able to set the cookie to 'completed', and clear the jzchan->vchan
+pointer, which was deferenced in the critical section of the first
+function.
+
+Fix this race by checking the channel's cookie state after entering the
+critical function and not before.
+
+Fixes: d894fc6046fe ("dmaengine: jz4780: add driver for the Ingenic JZ4780 DMA controller")
+Cc: stable@vger.kernel.org # v4.0
+Signed-off-by: Paul Cercueil <paul@crapouillou.net>
+Reported-by: Artur Rojek <contact@artur-rojek.eu>
+Tested-by: Artur Rojek <contact@artur-rojek.eu>
+Link: https://lore.kernel.org/r/20201004140307.885556-1-paul@crapouillou.net
+Signed-off-by: Vinod Koul <vkoul@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/dma/dma-jz4780.c |    7 ++++---
+ 1 file changed, 4 insertions(+), 3 deletions(-)
+
+--- a/drivers/dma/dma-jz4780.c
++++ b/drivers/dma/dma-jz4780.c
+@@ -639,11 +639,11 @@ static enum dma_status jz4780_dma_tx_sta
+       unsigned long flags;
+       unsigned long residue = 0;
++      spin_lock_irqsave(&jzchan->vchan.lock, flags);
++
+       status = dma_cookie_status(chan, cookie, txstate);
+       if ((status == DMA_COMPLETE) || (txstate == NULL))
+-              return status;
+-
+-      spin_lock_irqsave(&jzchan->vchan.lock, flags);
++              goto out_unlock_irqrestore;
+       vdesc = vchan_find_desc(&jzchan->vchan, cookie);
+       if (vdesc) {
+@@ -660,6 +660,7 @@ static enum dma_status jz4780_dma_tx_sta
+           && jzchan->desc->status & (JZ_DMA_DCS_AR | JZ_DMA_DCS_HLT))
+               status = DMA_ERROR;
++out_unlock_irqrestore:
+       spin_unlock_irqrestore(&jzchan->vchan.lock, flags);
+       return status;
+ }
diff --git a/queue-5.4/drm-i915-force-vt-d-workarounds-when-running-as-a-guest-os.patch b/queue-5.4/drm-i915-force-vt-d-workarounds-when-running-as-a-guest-os.patch
new file mode 100644 (file)
index 0000000..4ee6f34
--- /dev/null
@@ -0,0 +1,55 @@
+From 8195400f7ea95399f721ad21f4d663a62c65036f Mon Sep 17 00:00:00 2001
+From: Chris Wilson <chris@chris-wilson.co.uk>
+Date: Mon, 19 Oct 2020 11:15:23 +0100
+Subject: drm/i915: Force VT'd workarounds when running as a guest OS
+
+From: Chris Wilson <chris@chris-wilson.co.uk>
+
+commit 8195400f7ea95399f721ad21f4d663a62c65036f upstream.
+
+If i915.ko is being used as a passthrough device, it does not know if
+the host is using intel_iommu. Mixing the iommu and gfx causes a few
+issues (such as scanout overfetch) which we need to workaround inside
+the driver, so if we detect we are running under a hypervisor, also
+assume the device access is being virtualised.
+
+Reported-by: Stefan Fritsch <sf@sfritsch.de>
+Suggested-by: Stefan Fritsch <sf@sfritsch.de>
+Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
+Cc: Zhenyu Wang <zhenyuw@linux.intel.com>
+Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
+Cc: Stefan Fritsch <sf@sfritsch.de>
+Cc: stable@vger.kernel.org
+Tested-by: Stefan Fritsch <sf@sfritsch.de>
+Reviewed-by: Zhenyu Wang <zhenyuw@linux.intel.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20201019101523.4145-1-chris@chris-wilson.co.uk
+(cherry picked from commit f566fdcd6cc49a9d5b5d782f56e3e7cb243f01b8)
+Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/gpu/drm/i915/i915_drv.h |    6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+--- a/drivers/gpu/drm/i915/i915_drv.h
++++ b/drivers/gpu/drm/i915/i915_drv.h
+@@ -33,6 +33,8 @@
+ #include <uapi/drm/i915_drm.h>
+ #include <uapi/drm/drm_fourcc.h>
++#include <asm/hypervisor.h>
++
+ #include <linux/io-mapping.h>
+ #include <linux/i2c.h>
+ #include <linux/i2c-algo-bit.h>
+@@ -2197,7 +2199,9 @@ static inline bool intel_vtd_active(void
+       if (intel_iommu_gfx_mapped)
+               return true;
+ #endif
+-      return false;
++
++      /* Running as a guest, we assume the host is enforcing VT'd */
++      return !hypervisor_is_type(X86_HYPER_NATIVE);
+ }
+ static inline bool intel_scanout_needs_vtd_wa(struct drm_i915_private *dev_priv)
diff --git a/queue-5.4/extcon-ptn5150-fix-usage-of-atomic-gpio-with-sleeping-gpio-chips.patch b/queue-5.4/extcon-ptn5150-fix-usage-of-atomic-gpio-with-sleeping-gpio-chips.patch
new file mode 100644 (file)
index 0000000..dddb7d6
--- /dev/null
@@ -0,0 +1,57 @@
+From 6aaad58c872db062f7ea2761421ca748bd0931cc Mon Sep 17 00:00:00 2001
+From: Krzysztof Kozlowski <krzk@kernel.org>
+Date: Mon, 17 Aug 2020 09:00:00 +0200
+Subject: extcon: ptn5150: Fix usage of atomic GPIO with sleeping GPIO chips
+
+From: Krzysztof Kozlowski <krzk@kernel.org>
+
+commit 6aaad58c872db062f7ea2761421ca748bd0931cc upstream.
+
+The driver uses atomic version of gpiod_set_value() without any real
+reason.  It is called in a workqueue under mutex so it could sleep
+there.  Changing it to "can_sleep" flavor allows to use the driver with
+all GPIO chips.
+
+Fixes: 4ed754de2d66 ("extcon: Add support for ptn5150 extcon driver")
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Krzysztof Kozlowski <krzk@kernel.org>
+Reviewed-by: Vijai Kumar K <vijaikumar.kanagarajan@gmail.com>
+Signed-off-by: Chanwoo Choi <cw00.choi@samsung.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/extcon/extcon-ptn5150.c |    8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+--- a/drivers/extcon/extcon-ptn5150.c
++++ b/drivers/extcon/extcon-ptn5150.c
+@@ -127,7 +127,7 @@ static void ptn5150_irq_work(struct work
+                       case PTN5150_DFP_ATTACHED:
+                               extcon_set_state_sync(info->edev,
+                                               EXTCON_USB_HOST, false);
+-                              gpiod_set_value(info->vbus_gpiod, 0);
++                              gpiod_set_value_cansleep(info->vbus_gpiod, 0);
+                               extcon_set_state_sync(info->edev, EXTCON_USB,
+                                               true);
+                               break;
+@@ -138,9 +138,9 @@ static void ptn5150_irq_work(struct work
+                                       PTN5150_REG_CC_VBUS_DETECTION_MASK) >>
+                                       PTN5150_REG_CC_VBUS_DETECTION_SHIFT);
+                               if (vbus)
+-                                      gpiod_set_value(info->vbus_gpiod, 0);
++                                      gpiod_set_value_cansleep(info->vbus_gpiod, 0);
+                               else
+-                                      gpiod_set_value(info->vbus_gpiod, 1);
++                                      gpiod_set_value_cansleep(info->vbus_gpiod, 1);
+                               extcon_set_state_sync(info->edev,
+                                               EXTCON_USB_HOST, true);
+@@ -156,7 +156,7 @@ static void ptn5150_irq_work(struct work
+                                       EXTCON_USB_HOST, false);
+                       extcon_set_state_sync(info->edev,
+                                       EXTCON_USB, false);
+-                      gpiod_set_value(info->vbus_gpiod, 0);
++                      gpiod_set_value_cansleep(info->vbus_gpiod, 0);
+               }
+       }
diff --git a/queue-5.4/fs-don-t-invalidate-page-buffers-in-block_write_full_page.patch b/queue-5.4/fs-don-t-invalidate-page-buffers-in-block_write_full_page.patch
new file mode 100644 (file)
index 0000000..43fcb9d
--- /dev/null
@@ -0,0 +1,94 @@
+From 6dbf7bb555981fb5faf7b691e8f6169fc2b2e63b Mon Sep 17 00:00:00 2001
+From: Jan Kara <jack@suse.cz>
+Date: Fri, 4 Sep 2020 10:58:51 +0200
+Subject: fs: Don't invalidate page buffers in block_write_full_page()
+
+From: Jan Kara <jack@suse.cz>
+
+commit 6dbf7bb555981fb5faf7b691e8f6169fc2b2e63b upstream.
+
+If block_write_full_page() is called for a page that is beyond current
+inode size, it will truncate page buffers for the page and return 0.
+This logic has been added in 2.5.62 in commit 81eb69062588 ("fix ext3
+BUG due to race with truncate") in history.git tree to fix a problem
+with ext3 in data=ordered mode. This particular problem doesn't exist
+anymore because ext3 is long gone and ext4 handles ordered data
+differently. Also normally buffers are invalidated by truncate code and
+there's no need to specially handle this in ->writepage() code.
+
+This invalidation of page buffers in block_write_full_page() is causing
+issues to filesystems (e.g. ext4 or ocfs2) when block device is shrunk
+under filesystem's hands and metadata buffers get discarded while being
+tracked by the journalling layer. Although it is obviously "not
+supported" it can cause kernel crashes like:
+
+[ 7986.689400] BUG: unable to handle kernel NULL pointer dereference at
++0000000000000008
+[ 7986.697197] PGD 0 P4D 0
+[ 7986.699724] Oops: 0002 [#1] SMP PTI
+[ 7986.703200] CPU: 4 PID: 203778 Comm: jbd2/dm-3-8 Kdump: loaded Tainted: G
++O     --------- -  - 4.18.0-147.5.0.5.h126.eulerosv2r9.x86_64 #1
+[ 7986.716438] Hardware name: Huawei RH2288H V3/BC11HGSA0, BIOS 1.57 08/11/2015
+[ 7986.723462] RIP: 0010:jbd2_journal_grab_journal_head+0x1b/0x40 [jbd2]
+...
+[ 7986.810150] Call Trace:
+[ 7986.812595]  __jbd2_journal_insert_checkpoint+0x23/0x70 [jbd2]
+[ 7986.818408]  jbd2_journal_commit_transaction+0x155f/0x1b60 [jbd2]
+[ 7986.836467]  kjournald2+0xbd/0x270 [jbd2]
+
+which is not great. The crash happens because bh->b_private is suddently
+NULL although BH_JBD flag is still set (this is because
+block_invalidatepage() cleared BH_Mapped flag and subsequent bh lookup
+found buffer without BH_Mapped set, called init_page_buffers() which has
+rewritten bh->b_private). So just remove the invalidation in
+block_write_full_page().
+
+Note that the buffer cache invalidation when block device changes size
+is already careful to avoid similar problems by using
+invalidate_mapping_pages() which skips busy buffers so it was only this
+odd block_write_full_page() behavior that could tear down bdev buffers
+under filesystem's hands.
+
+Reported-by: Ye Bin <yebin10@huawei.com>
+Signed-off-by: Jan Kara <jack@suse.cz>
+Reviewed-by: Christoph Hellwig <hch@lst.de>
+CC: stable@vger.kernel.org
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/buffer.c |   16 ----------------
+ 1 file changed, 16 deletions(-)
+
+--- a/fs/buffer.c
++++ b/fs/buffer.c
+@@ -2739,16 +2739,6 @@ int nobh_writepage(struct page *page, ge
+       /* Is the page fully outside i_size? (truncate in progress) */
+       offset = i_size & (PAGE_SIZE-1);
+       if (page->index >= end_index+1 || !offset) {
+-              /*
+-               * The page may have dirty, unmapped buffers.  For example,
+-               * they may have been added in ext3_writepage().  Make them
+-               * freeable here, so the page does not leak.
+-               */
+-#if 0
+-              /* Not really sure about this  - do we need this ? */
+-              if (page->mapping->a_ops->invalidatepage)
+-                      page->mapping->a_ops->invalidatepage(page, offset);
+-#endif
+               unlock_page(page);
+               return 0; /* don't care */
+       }
+@@ -2943,12 +2933,6 @@ int block_write_full_page(struct page *p
+       /* Is the page fully outside i_size? (truncate in progress) */
+       offset = i_size & (PAGE_SIZE-1);
+       if (page->index >= end_index+1 || !offset) {
+-              /*
+-               * The page may have dirty, unmapped buffers.  For example,
+-               * they may have been added in ext3_writepage().  Make them
+-               * freeable here, so the page does not leak.
+-               */
+-              do_invalidatepage(page, 0, PAGE_SIZE);
+               unlock_page(page);
+               return 0; /* don't care */
+       }
diff --git a/queue-5.4/hid-wacom-avoid-entering-wacom_wac_pen_report-for-pad-battery.patch b/queue-5.4/hid-wacom-avoid-entering-wacom_wac_pen_report-for-pad-battery.patch
new file mode 100644 (file)
index 0000000..7de8bc3
--- /dev/null
@@ -0,0 +1,61 @@
+From d9216d753b2b1406b801243b12aaf00a5ce5b861 Mon Sep 17 00:00:00 2001
+From: Jason Gerecke <jason.gerecke@wacom.com>
+Date: Wed, 23 Sep 2020 13:14:56 -0700
+Subject: HID: wacom: Avoid entering wacom_wac_pen_report for pad / battery
+
+From: Jason Gerecke <jason.gerecke@wacom.com>
+
+commit d9216d753b2b1406b801243b12aaf00a5ce5b861 upstream.
+
+It has recently been reported that the "heartbeat" report from devices
+like the 2nd-gen Intuos Pro (PTH-460, PTH-660, PTH-860) or the 2nd-gen
+Bluetooth-enabled Intuos tablets (CTL-4100WL, CTL-6100WL) can cause the
+driver to send a spurious BTN_TOUCH=0 once per second in the middle of
+drawing. This can result in broken lines while drawing on Chrome OS.
+
+The source of the issue has been traced back to a change which modified
+the driver to only call `wacom_wac_pad_report()` once per report instead
+of once per collection. As part of this change, pad-handling code was
+removed from `wacom_wac_collection()` under the assumption that the
+`WACOM_PEN_FIELD` and `WACOM_TOUCH_FIELD` checks would not be satisfied
+when a pad or battery collection was being processed.
+
+To be clear, the macros `WACOM_PAD_FIELD` and `WACOM_PEN_FIELD` do not
+currently check exclusive conditions. In fact, most "pad" fields will
+also appear to be "pen" fields simply due to their presence inside of
+a Digitizer application collection. Because of this, the removal of
+the check from `wacom_wac_collection()` just causes pad / battery
+collections to instead trigger a call to `wacom_wac_pen_report()`
+instead. The pen report function in turn resets the tip switch state
+just prior to exiting, resulting in the observed BTN_TOUCH=0 symptom.
+
+To correct this, we restore a version of the `WACOM_PAD_FIELD` check
+in `wacom_wac_collection()` and return early. This effectively prevents
+pad / battery collections from being reported until the very end of the
+report as originally intended.
+
+Fixes: d4b8efeb46d9 ("HID: wacom: generic: Correct pad syncing")
+Cc: stable@vger.kernel.org # v4.17+
+Signed-off-by: Jason Gerecke <jason.gerecke@wacom.com>
+Reviewed-by: Ping Cheng <ping.cheng@wacom.com>
+Tested-by: Ping Cheng <ping.cheng@wacom.com>
+Signed-off-by: Jiri Kosina <jkosina@suse.cz>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/hid/wacom_wac.c |    4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+--- a/drivers/hid/wacom_wac.c
++++ b/drivers/hid/wacom_wac.c
+@@ -2773,7 +2773,9 @@ static int wacom_wac_collection(struct h
+       if (report->type != HID_INPUT_REPORT)
+               return -1;
+-      if (WACOM_PEN_FIELD(field) && wacom->wacom_wac.pen_input)
++      if (WACOM_PAD_FIELD(field))
++              return 0;
++      else if (WACOM_PEN_FIELD(field) && wacom->wacom_wac.pen_input)
+               wacom_wac_pen_report(hdev, report);
+       else if (WACOM_FINGER_FIELD(field) && wacom->wacom_wac.touch_input)
+               wacom_wac_finger_report(hdev, report);
diff --git a/queue-5.4/iio-adc-gyroadc-fix-leak-of-device-node-iterator.patch b/queue-5.4/iio-adc-gyroadc-fix-leak-of-device-node-iterator.patch
new file mode 100644 (file)
index 0000000..177a9e3
--- /dev/null
@@ -0,0 +1,98 @@
+From da4410d4078ba4ead9d6f1027d6db77c5a74ecee Mon Sep 17 00:00:00 2001
+From: Tobias Jordan <kernel@cdqe.de>
+Date: Sat, 26 Sep 2020 18:19:46 +0200
+Subject: iio: adc: gyroadc: fix leak of device node iterator
+
+From: Tobias Jordan <kernel@cdqe.de>
+
+commit da4410d4078ba4ead9d6f1027d6db77c5a74ecee upstream.
+
+Add missing of_node_put calls when exiting the for_each_child_of_node
+loop in rcar_gyroadc_parse_subdevs early.
+
+Also add goto-exception handling for the error paths in that loop.
+
+Fixes: 059c53b32329 ("iio: adc: Add Renesas GyroADC driver")
+Signed-off-by: Tobias Jordan <kernel@cdqe.de>
+Link: https://lore.kernel.org/r/20200926161946.GA10240@agrajag.zerfleddert.de
+Cc: <Stable@vger.kernel.org>
+Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/iio/adc/rcar-gyroadc.c |   21 +++++++++++++++------
+ 1 file changed, 15 insertions(+), 6 deletions(-)
+
+--- a/drivers/iio/adc/rcar-gyroadc.c
++++ b/drivers/iio/adc/rcar-gyroadc.c
+@@ -357,7 +357,7 @@ static int rcar_gyroadc_parse_subdevs(st
+                       num_channels = ARRAY_SIZE(rcar_gyroadc_iio_channels_3);
+                       break;
+               default:
+-                      return -EINVAL;
++                      goto err_e_inval;
+               }
+               /*
+@@ -374,7 +374,7 @@ static int rcar_gyroadc_parse_subdevs(st
+                               dev_err(dev,
+                                       "Failed to get child reg property of ADC \"%pOFn\".\n",
+                                       child);
+-                              return ret;
++                              goto err_of_node_put;
+                       }
+                       /* Channel number is too high. */
+@@ -382,7 +382,7 @@ static int rcar_gyroadc_parse_subdevs(st
+                               dev_err(dev,
+                                       "Only %i channels supported with %pOFn, but reg = <%i>.\n",
+                                       num_channels, child, reg);
+-                              return -EINVAL;
++                              goto err_e_inval;
+                       }
+               }
+@@ -391,7 +391,7 @@ static int rcar_gyroadc_parse_subdevs(st
+                       dev_err(dev,
+                               "Channel %i uses different ADC mode than the rest.\n",
+                               reg);
+-                      return -EINVAL;
++                      goto err_e_inval;
+               }
+               /* Channel is valid, grab the regulator. */
+@@ -401,7 +401,8 @@ static int rcar_gyroadc_parse_subdevs(st
+               if (IS_ERR(vref)) {
+                       dev_dbg(dev, "Channel %i 'vref' supply not connected.\n",
+                               reg);
+-                      return PTR_ERR(vref);
++                      ret = PTR_ERR(vref);
++                      goto err_of_node_put;
+               }
+               priv->vref[reg] = vref;
+@@ -425,8 +426,10 @@ static int rcar_gyroadc_parse_subdevs(st
+                * attached to the GyroADC at a time, so if we found it,
+                * we can stop parsing here.
+                */
+-              if (childmode == RCAR_GYROADC_MODE_SELECT_1_MB88101A)
++              if (childmode == RCAR_GYROADC_MODE_SELECT_1_MB88101A) {
++                      of_node_put(child);
+                       break;
++              }
+       }
+       if (first) {
+@@ -435,6 +438,12 @@ static int rcar_gyroadc_parse_subdevs(st
+       }
+       return 0;
++
++err_e_inval:
++      ret = -EINVAL;
++err_of_node_put:
++      of_node_put(child);
++      return ret;
+ }
+ static void rcar_gyroadc_deinit_supplies(struct iio_dev *indio_dev)
diff --git a/queue-5.4/iio-adc-ti-adc0832-fix-alignment-issue-with-timestamp.patch b/queue-5.4/iio-adc-ti-adc0832-fix-alignment-issue-with-timestamp.patch
new file mode 100644 (file)
index 0000000..ab8d6b3
--- /dev/null
@@ -0,0 +1,75 @@
+From 39e91f3be4cba51c1560bcda3a343ed1f64dc916 Mon Sep 17 00:00:00 2001
+From: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+Date: Wed, 22 Jul 2020 16:51:00 +0100
+Subject: iio:adc:ti-adc0832 Fix alignment issue with timestamp
+
+From: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+
+commit 39e91f3be4cba51c1560bcda3a343ed1f64dc916 upstream.
+
+One of a class of bugs pointed out by Lars in a recent review.
+iio_push_to_buffers_with_timestamp assumes the buffer used is aligned
+to the size of the timestamp (8 bytes).  This is not guaranteed in
+this driver which uses an array of smaller elements on the stack.
+
+We fix this issues by moving to a suitable structure in the iio_priv()
+data with alignment explicitly requested.  This data is allocated
+with kzalloc so no data can leak apart from previous readings.
+Note that previously no data could leak 'including' previous readings
+but I don't think it is an issue to potentially leak them like
+this now does.
+
+In this case the postioning of the timestamp is depends on what
+other channels are enabled. As such we cannot use a structure to
+make the alignment explicit as it would be missleading by suggesting
+only one possible location for the timestamp.
+
+Fixes: 815bbc87462a ("iio: ti-adc0832: add triggered buffer support")
+Reported-by: Lars-Peter Clausen <lars@metafoo.de>
+Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
+Cc: Akinobu Mita <akinobu.mita@gmail.com>
+Cc: <Stable@vger.kernel.org>
+Link: https://lore.kernel.org/r/20200722155103.979802-25-jic23@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/iio/adc/ti-adc0832.c |   11 ++++++++---
+ 1 file changed, 8 insertions(+), 3 deletions(-)
+
+--- a/drivers/iio/adc/ti-adc0832.c
++++ b/drivers/iio/adc/ti-adc0832.c
+@@ -28,6 +28,12 @@ struct adc0832 {
+       struct regulator *reg;
+       struct mutex lock;
+       u8 mux_bits;
++      /*
++       * Max size needed: 16x 1 byte ADC data + 8 bytes timestamp
++       * May be shorter if not all channels are enabled subject
++       * to the timestamp remaining 8 byte aligned.
++       */
++      u8 data[24] __aligned(8);
+       u8 tx_buf[2] ____cacheline_aligned;
+       u8 rx_buf[2];
+@@ -199,7 +205,6 @@ static irqreturn_t adc0832_trigger_handl
+       struct iio_poll_func *pf = p;
+       struct iio_dev *indio_dev = pf->indio_dev;
+       struct adc0832 *adc = iio_priv(indio_dev);
+-      u8 data[24] = { }; /* 16x 1 byte ADC data + 8 bytes timestamp */
+       int scan_index;
+       int i = 0;
+@@ -217,10 +222,10 @@ static irqreturn_t adc0832_trigger_handl
+                       goto out;
+               }
+-              data[i] = ret;
++              adc->data[i] = ret;
+               i++;
+       }
+-      iio_push_to_buffers_with_timestamp(indio_dev, data,
++      iio_push_to_buffers_with_timestamp(indio_dev, adc->data,
+                                          iio_get_time_ns(indio_dev));
+ out:
+       mutex_unlock(&adc->lock);
diff --git a/queue-5.4/iio-adc-ti-adc12138-fix-alignment-issue-with-timestamp.patch b/queue-5.4/iio-adc-ti-adc12138-fix-alignment-issue-with-timestamp.patch
new file mode 100644 (file)
index 0000000..bb44197
--- /dev/null
@@ -0,0 +1,87 @@
+From 293e809b2e8e608b65a949101aaf7c0bd1224247 Mon Sep 17 00:00:00 2001
+From: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+Date: Wed, 22 Jul 2020 16:51:01 +0100
+Subject: iio:adc:ti-adc12138 Fix alignment issue with timestamp
+
+From: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+
+commit 293e809b2e8e608b65a949101aaf7c0bd1224247 upstream.
+
+One of a class of bugs pointed out by Lars in a recent review.
+iio_push_to_buffers_with_timestamp assumes the buffer used is aligned
+to the size of the timestamp (8 bytes).  This is not guaranteed in
+this driver which uses an array of smaller elements on the stack.
+
+We move to a suitable structure in the iio_priv() data with alignment
+explicitly requested.  This data is allocated with kzalloc so no
+data can leak apart from previous readings. Note that previously
+no leak at all could occur, but previous readings should never
+be a problem.
+
+In this case the timestamp location depends on what other channels
+are enabled. As such we can't use a structure without misleading
+by suggesting only one possible timestamp location.
+
+Fixes: 50a6edb1b6e0 ("iio: adc: add ADC12130/ADC12132/ADC12138 ADC driver")
+Reported-by: Lars-Peter Clausen <lars@metafoo.de>
+Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
+Cc: Akinobu Mita <akinobu.mita@gmail.com>
+Cc: <Stable@vger.kernel.org>
+Link: https://lore.kernel.org/r/20200722155103.979802-26-jic23@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/iio/adc/ti-adc12138.c |   13 +++++++++----
+ 1 file changed, 9 insertions(+), 4 deletions(-)
+
+--- a/drivers/iio/adc/ti-adc12138.c
++++ b/drivers/iio/adc/ti-adc12138.c
+@@ -47,6 +47,12 @@ struct adc12138 {
+       struct completion complete;
+       /* The number of cclk periods for the S/H's acquisition time */
+       unsigned int acquisition_time;
++      /*
++       * Maximum size needed: 16x 2 bytes ADC data + 8 bytes timestamp.
++       * Less may be need if not all channels are enabled, as long as
++       * the 8 byte alignment of the timestamp is maintained.
++       */
++      __be16 data[20] __aligned(8);
+       u8 tx_buf[2] ____cacheline_aligned;
+       u8 rx_buf[2];
+@@ -329,7 +335,6 @@ static irqreturn_t adc12138_trigger_hand
+       struct iio_poll_func *pf = p;
+       struct iio_dev *indio_dev = pf->indio_dev;
+       struct adc12138 *adc = iio_priv(indio_dev);
+-      __be16 data[20] = { }; /* 16x 2 bytes ADC data + 8 bytes timestamp */
+       __be16 trash;
+       int ret;
+       int scan_index;
+@@ -345,7 +350,7 @@ static irqreturn_t adc12138_trigger_hand
+               reinit_completion(&adc->complete);
+               ret = adc12138_start_and_read_conv(adc, scan_chan,
+-                                                 i ? &data[i - 1] : &trash);
++                                      i ? &adc->data[i - 1] : &trash);
+               if (ret) {
+                       dev_warn(&adc->spi->dev,
+                                "failed to start conversion\n");
+@@ -362,7 +367,7 @@ static irqreturn_t adc12138_trigger_hand
+       }
+       if (i) {
+-              ret = adc12138_read_conv_data(adc, &data[i - 1]);
++              ret = adc12138_read_conv_data(adc, &adc->data[i - 1]);
+               if (ret) {
+                       dev_warn(&adc->spi->dev,
+                                "failed to get conversion data\n");
+@@ -370,7 +375,7 @@ static irqreturn_t adc12138_trigger_hand
+               }
+       }
+-      iio_push_to_buffers_with_timestamp(indio_dev, data,
++      iio_push_to_buffers_with_timestamp(indio_dev, adc->data,
+                                          iio_get_time_ns(indio_dev));
+ out:
+       mutex_unlock(&adc->lock);
diff --git a/queue-5.4/iio-gyro-itg3200-fix-timestamp-alignment-and-prevent-data-leak.patch b/queue-5.4/iio-gyro-itg3200-fix-timestamp-alignment-and-prevent-data-leak.patch
new file mode 100644 (file)
index 0000000..a793b3c
--- /dev/null
@@ -0,0 +1,60 @@
+From 10ab7cfd5522f0041028556dac864a003e158556 Mon Sep 17 00:00:00 2001
+From: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+Date: Wed, 22 Jul 2020 16:50:41 +0100
+Subject: iio:gyro:itg3200: Fix timestamp alignment and prevent data leak.
+
+From: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+
+commit 10ab7cfd5522f0041028556dac864a003e158556 upstream.
+
+One of a class of bugs pointed out by Lars in a recent review.
+iio_push_to_buffers_with_timestamp assumes the buffer used is aligned
+to the size of the timestamp (8 bytes).  This is not guaranteed in
+this driver which uses a 16 byte array of smaller elements on the stack.
+This is fixed by using an explicit c structure. As there are no
+holes in the structure, there is no possiblity of data leakage
+in this case.
+
+The explicit alignment of ts is not strictly necessary but potentially
+makes the code slightly less fragile.  It also removes the possibility
+of this being cut and paste into another driver where the alignment
+isn't already true.
+
+Fixes: 36e0371e7764 ("iio:itg3200: Use iio_push_to_buffers_with_timestamp()")
+Reported-by: Lars-Peter Clausen <lars@metafoo.de>
+Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
+Cc: <Stable@vger.kernel.org>
+Link: https://lore.kernel.org/r/20200722155103.979802-6-jic23@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/iio/gyro/itg3200_buffer.c |   13 ++++++++++---
+ 1 file changed, 10 insertions(+), 3 deletions(-)
+
+--- a/drivers/iio/gyro/itg3200_buffer.c
++++ b/drivers/iio/gyro/itg3200_buffer.c
+@@ -46,13 +46,20 @@ static irqreturn_t itg3200_trigger_handl
+       struct iio_poll_func *pf = p;
+       struct iio_dev *indio_dev = pf->indio_dev;
+       struct itg3200 *st = iio_priv(indio_dev);
+-      __be16 buf[ITG3200_SCAN_ELEMENTS + sizeof(s64)/sizeof(u16)];
++      /*
++       * Ensure correct alignment and padding including for the
++       * timestamp that may be inserted.
++       */
++      struct {
++              __be16 buf[ITG3200_SCAN_ELEMENTS];
++              s64 ts __aligned(8);
++      } scan;
+-      int ret = itg3200_read_all_channels(st->i2c, buf);
++      int ret = itg3200_read_all_channels(st->i2c, scan.buf);
+       if (ret < 0)
+               goto error_ret;
+-      iio_push_to_buffers_with_timestamp(indio_dev, buf, pf->timestamp);
++      iio_push_to_buffers_with_timestamp(indio_dev, &scan, pf->timestamp);
+       iio_trigger_notify_done(indio_dev->trig);
diff --git a/queue-5.4/iio-light-si1145-fix-timestamp-alignment-and-prevent-data-leak.patch b/queue-5.4/iio-light-si1145-fix-timestamp-alignment-and-prevent-data-leak.patch
new file mode 100644 (file)
index 0000000..956c6aa
--- /dev/null
@@ -0,0 +1,94 @@
+From 0456ecf34d466261970e0ff92b2b9c78a4908637 Mon Sep 17 00:00:00 2001
+From: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+Date: Wed, 22 Jul 2020 16:50:44 +0100
+Subject: iio:light:si1145: Fix timestamp alignment and prevent data leak.
+
+From: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+
+commit 0456ecf34d466261970e0ff92b2b9c78a4908637 upstream.
+
+One of a class of bugs pointed out by Lars in a recent review.
+iio_push_to_buffers_with_timestamp assumes the buffer used is aligned
+to the size of the timestamp (8 bytes).  This is not guaranteed in
+this driver which uses a 24 byte array of smaller elements on the stack.
+As Lars also noted this anti pattern can involve a leak of data to
+userspace and that indeed can happen here.  We close both issues by
+moving to a suitable array in the iio_priv() data with alignment
+explicitly requested.  This data is allocated with kzalloc so no
+data can leak appart from previous readings.
+
+Depending on the enabled channels, the  location of the timestamp
+can be at various aligned offsets through the buffer.  As such we
+any use of a structure to enforce this alignment would incorrectly
+suggest a single location for the timestamp.  Comments adjusted to
+express this clearly in the code.
+
+Fixes: ac45e57f1590 ("iio: light: Add driver for Silabs si1132, si1141/2/3 and si1145/6/7 ambient light, uv index and proximity sensors")
+Reported-by: Lars-Peter Clausen <lars@metafoo.de>
+Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
+Cc: Peter Meerwald-Stadler <pmeerw@pmeerw.net>
+Cc: <Stable@vger.kernel.org>
+Link: https://lore.kernel.org/r/20200722155103.979802-9-jic23@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/iio/light/si1145.c |   19 +++++++++++--------
+ 1 file changed, 11 insertions(+), 8 deletions(-)
+
+--- a/drivers/iio/light/si1145.c
++++ b/drivers/iio/light/si1145.c
+@@ -169,6 +169,7 @@ struct si1145_part_info {
+  * @part_info:        Part information
+  * @trig:     Pointer to iio trigger
+  * @meas_rate:        Value of MEAS_RATE register. Only set in HW in auto mode
++ * @buffer:   Used to pack data read from sensor.
+  */
+ struct si1145_data {
+       struct i2c_client *client;
+@@ -180,6 +181,14 @@ struct si1145_data {
+       bool autonomous;
+       struct iio_trigger *trig;
+       int meas_rate;
++      /*
++       * Ensure timestamp will be naturally aligned if present.
++       * Maximum buffer size (may be only partly used if not all
++       * channels are enabled):
++       *   6*2 bytes channels data + 4 bytes alignment +
++       *   8 bytes timestamp
++       */
++      u8 buffer[24] __aligned(8);
+ };
+ /**
+@@ -441,12 +450,6 @@ static irqreturn_t si1145_trigger_handle
+       struct iio_poll_func *pf = private;
+       struct iio_dev *indio_dev = pf->indio_dev;
+       struct si1145_data *data = iio_priv(indio_dev);
+-      /*
+-       * Maximum buffer size:
+-       *   6*2 bytes channels data + 4 bytes alignment +
+-       *   8 bytes timestamp
+-       */
+-      u8 buffer[24];
+       int i, j = 0;
+       int ret;
+       u8 irq_status = 0;
+@@ -479,7 +482,7 @@ static irqreturn_t si1145_trigger_handle
+               ret = i2c_smbus_read_i2c_block_data_or_emulated(
+                               data->client, indio_dev->channels[i].address,
+-                              sizeof(u16) * run, &buffer[j]);
++                              sizeof(u16) * run, &data->buffer[j]);
+               if (ret < 0)
+                       goto done;
+               j += run * sizeof(u16);
+@@ -494,7 +497,7 @@ static irqreturn_t si1145_trigger_handle
+                       goto done;
+       }
+-      iio_push_to_buffers_with_timestamp(indio_dev, buffer,
++      iio_push_to_buffers_with_timestamp(indio_dev, data->buffer,
+               iio_get_time_ns(indio_dev));
+ done:
diff --git a/queue-5.4/leds-bcm6328-bcm6358-use-devres-led-registering-function.patch b/queue-5.4/leds-bcm6328-bcm6358-use-devres-led-registering-function.patch
new file mode 100644 (file)
index 0000000..315a123
--- /dev/null
@@ -0,0 +1,53 @@
+From ff5c89d44453e7ad99502b04bf798a3fc32c758b Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Marek=20Beh=C3=BAn?= <marek.behun@nic.cz>
+Date: Fri, 18 Sep 2020 00:32:58 +0200
+Subject: leds: bcm6328, bcm6358: use devres LED registering function
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Marek Behún <marek.behun@nic.cz>
+
+commit ff5c89d44453e7ad99502b04bf798a3fc32c758b upstream.
+
+These two drivers do not provide remove method and use devres for
+allocation of other resources, yet they use led_classdev_register
+instead of the devres variant, devm_led_classdev_register.
+
+Fix this.
+
+Signed-off-by: Marek Behún <marek.behun@nic.cz>
+Cc: Álvaro Fernández Rojas <noltari@gmail.com>
+Cc: Kevin Cernekee <cernekee@gmail.com>
+Cc: Jaedon Shin <jaedon.shin@gmail.com>
+Signed-off-by: Pavel Machek <pavel@ucw.cz>
+Cc: stable@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/leds/leds-bcm6328.c |    2 +-
+ drivers/leds/leds-bcm6358.c |    2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/leds/leds-bcm6328.c
++++ b/drivers/leds/leds-bcm6328.c
+@@ -332,7 +332,7 @@ static int bcm6328_led(struct device *de
+       led->cdev.brightness_set = bcm6328_led_set;
+       led->cdev.blink_set = bcm6328_blink_set;
+-      rc = led_classdev_register(dev, &led->cdev);
++      rc = devm_led_classdev_register(dev, &led->cdev);
+       if (rc < 0)
+               return rc;
+--- a/drivers/leds/leds-bcm6358.c
++++ b/drivers/leds/leds-bcm6358.c
+@@ -137,7 +137,7 @@ static int bcm6358_led(struct device *de
+       led->cdev.brightness_set = bcm6358_led_set;
+-      rc = led_classdev_register(dev, &led->cdev);
++      rc = devm_led_classdev_register(dev, &led->cdev);
+       if (rc < 0)
+               return rc;
diff --git a/queue-5.4/media-uvcvideo-fix-uvc_ctrl_fixup_xu_info-not-having-any-effect.patch b/queue-5.4/media-uvcvideo-fix-uvc_ctrl_fixup_xu_info-not-having-any-effect.patch
new file mode 100644 (file)
index 0000000..4230554
--- /dev/null
@@ -0,0 +1,65 @@
+From 93df48d37c3f03886d84831992926333e7810640 Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Tue, 28 Jul 2020 13:22:08 +0200
+Subject: media: uvcvideo: Fix uvc_ctrl_fixup_xu_info() not having any effect
+
+From: Hans de Goede <hdegoede@redhat.com>
+
+commit 93df48d37c3f03886d84831992926333e7810640 upstream.
+
+uvc_ctrl_add_info() calls uvc_ctrl_get_flags() which will override
+the fixed-up flags set by uvc_ctrl_fixup_xu_info().
+
+uvc_ctrl_init_xu_ctrl() already calls uvc_ctrl_get_flags() before
+calling uvc_ctrl_add_info(), so the uvc_ctrl_get_flags() call in
+uvc_ctrl_add_info() is not necessary for xu ctrls.
+
+This commit moves the uvc_ctrl_get_flags() call for normal controls
+from uvc_ctrl_add_info() to uvc_ctrl_init_ctrl(), so that we no longer
+call uvc_ctrl_get_flags() twice for xu controls and so that we no longer
+override the fixed-up flags set by uvc_ctrl_fixup_xu_info().
+
+This fixes the xu motor controls not working properly on a Logitech
+046d:08cc, and presumably also on the other Logitech models which have
+a quirk for this in the uvc_ctrl_fixup_xu_info() function.
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/media/usb/uvc/uvc_ctrl.c |   14 +++++++-------
+ 1 file changed, 7 insertions(+), 7 deletions(-)
+
+--- a/drivers/media/usb/uvc/uvc_ctrl.c
++++ b/drivers/media/usb/uvc/uvc_ctrl.c
+@@ -2033,13 +2033,6 @@ static int uvc_ctrl_add_info(struct uvc_
+               goto done;
+       }
+-      /*
+-       * Retrieve control flags from the device. Ignore errors and work with
+-       * default flag values from the uvc_ctrl array when the device doesn't
+-       * properly implement GET_INFO on standard controls.
+-       */
+-      uvc_ctrl_get_flags(dev, ctrl, &ctrl->info);
+-
+       ctrl->initialized = 1;
+       uvc_trace(UVC_TRACE_CONTROL, "Added control %pUl/%u to device %s "
+@@ -2262,6 +2255,13 @@ static void uvc_ctrl_init_ctrl(struct uv
+               if (uvc_entity_match_guid(ctrl->entity, info->entity) &&
+                   ctrl->index == info->index) {
+                       uvc_ctrl_add_info(dev, ctrl, info);
++                      /*
++                       * Retrieve control flags from the device. Ignore errors
++                       * and work with default flag values from the uvc_ctrl
++                       * array when the device doesn't properly implement
++                       * GET_INFO on standard controls.
++                       */
++                      uvc_ctrl_get_flags(dev, ctrl, &ctrl->info);
+                       break;
+                }
+       }
diff --git a/queue-5.4/mips-dec-restore-bootmem-reservation-for-firmware-working-memory-area.patch b/queue-5.4/mips-dec-restore-bootmem-reservation-for-firmware-working-memory-area.patch
new file mode 100644 (file)
index 0000000..fcc436e
--- /dev/null
@@ -0,0 +1,140 @@
+From cf3af0a4d3b62ab48e0b90180ea161d0f5d4953f Mon Sep 17 00:00:00 2001
+From: "Maciej W. Rozycki" <macro@linux-mips.org>
+Date: Wed, 14 Oct 2020 22:34:56 +0100
+Subject: MIPS: DEC: Restore bootmem reservation for firmware working memory area
+
+From: Maciej W. Rozycki <macro@linux-mips.org>
+
+commit cf3af0a4d3b62ab48e0b90180ea161d0f5d4953f upstream.
+
+Fix a crash on DEC platforms starting with:
+
+VFS: Mounted root (nfs filesystem) on device 0:11.
+Freeing unused PROM memory: 124k freed
+BUG: Bad page state in process swapper  pfn:00001
+page:(ptrval) refcount:0 mapcount:-128 mapping:00000000 index:0x1 pfn:0x1
+flags: 0x0()
+raw: 00000000 00000100 00000122 00000000 00000001 00000000 ffffff7f 00000000
+page dumped because: nonzero mapcount
+Modules linked in:
+CPU: 0 PID: 1 Comm: swapper Not tainted 5.9.0-00858-g865c50e1d279 #1
+Stack : 8065dc48 0000000b 8065d2b8 9bc27dcc 80645bfc 9bc259a4 806a1b97 80703124
+        80710000 8064a900 00000001 80099574 806b116c 1000ec00 9bc27d88 806a6f30
+        00000000 00000000 80645bfc 00000000 31232039 80706ba4 2e392e35 8039f348
+        2d383538 00000070 0000000a 35363867 00000000 806c2830 80710000 806b0000
+        80710000 8064a900 00000001 81000000 00000000 00000000 8035af2c 80700000
+        ...
+Call Trace:
+[<8004bc5c>] show_stack+0x34/0x104
+[<8015675c>] bad_page+0xfc/0x128
+[<80157714>] free_pcppages_bulk+0x1f4/0x5dc
+[<801591cc>] free_unref_page+0xc0/0x130
+[<8015cb04>] free_reserved_area+0x144/0x1d8
+[<805abd78>] kernel_init+0x20/0x100
+[<80046070>] ret_from_kernel_thread+0x14/0x1c
+Disabling lock debugging due to kernel taint
+
+caused by an attempt to free bootmem space that as from
+commit b93ddc4f9156 ("mips: Reserve memory for the kernel image resources")
+has not been anymore reserved due to the removal of generic MIPS arch code
+that used to reserve all the memory from the beginning of RAM up to the
+kernel load address.
+
+This memory does need to be reserved on DEC platforms however as it is
+used by REX firmware as working area, as per the TURBOchannel firmware
+specification[1]:
+
+Table 2-2  REX Memory Regions
+-------------------------------------------------------------------------
+        Starting        Ending
+Region  Address         Address         Use
+-------------------------------------------------------------------------
+0       0xa0000000      0xa000ffff      Restart block, exception vectors,
+                                        REX stack and bss
+1       0xa0010000      0xa0017fff      Keyboard or tty drivers
+
+2       0xa0018000      0xa001f3ff 1)   CRT driver
+
+3       0xa0020000      0xa002ffff      boot, cnfg, init and t objects
+
+4       0xa0020000      0xa002ffff      64KB scratch space
+-------------------------------------------------------------------------
+1) Note that the last 3 Kbytes of region 2 are reserved for backward
+compatibility with previous system software.
+-------------------------------------------------------------------------
+
+(this table uses KSEG2 unmapped virtual addresses, which in the MIPS
+architecture are offset from physical addresses by a fixed value of
+0xa0000000 and therefore the regions referred do correspond to the
+beginning of the physical address space) and we call into the firmware
+on several occasions throughout the bootstrap process.  It is believed
+that pre-REX firmware used with non-TURBOchannel DEC platforms has the
+same requirements, as hinted by note #1 cited.
+
+Recreate the discarded reservation then, in DEC platform code, removing
+the crash.
+
+References:
+
+[1] "TURBOchannel Firmware Specification", On-line version,
+    EK-TCAAD-FS-004, Digital Equipment Corporation, January 1993,
+    Chapter 2 "System Module Firmware", p. 2-5
+
+Signed-off-by: Maciej W. Rozycki <macro@linux-mips.org>
+Fixes: b93ddc4f9156 ("mips: Reserve memory for the kernel image resources")
+Cc: stable@vger.kernel.org # v5.2+
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
+
+---
+ arch/mips/dec/setup.c |    9 ++++++++-
+ 1 file changed, 8 insertions(+), 1 deletion(-)
+
+--- a/arch/mips/dec/setup.c
++++ b/arch/mips/dec/setup.c
+@@ -6,7 +6,7 @@
+  * for more details.
+  *
+  * Copyright (C) 1998 Harald Koerfgen
+- * Copyright (C) 2000, 2001, 2002, 2003, 2005  Maciej W. Rozycki
++ * Copyright (C) 2000, 2001, 2002, 2003, 2005, 2020  Maciej W. Rozycki
+  */
+ #include <linux/console.h>
+ #include <linux/export.h>
+@@ -15,6 +15,7 @@
+ #include <linux/ioport.h>
+ #include <linux/irq.h>
+ #include <linux/irqnr.h>
++#include <linux/memblock.h>
+ #include <linux/param.h>
+ #include <linux/percpu-defs.h>
+ #include <linux/sched.h>
+@@ -22,6 +23,7 @@
+ #include <linux/types.h>
+ #include <linux/pm.h>
++#include <asm/addrspace.h>
+ #include <asm/bootinfo.h>
+ #include <asm/cpu.h>
+ #include <asm/cpu-features.h>
+@@ -29,7 +31,9 @@
+ #include <asm/irq.h>
+ #include <asm/irq_cpu.h>
+ #include <asm/mipsregs.h>
++#include <asm/page.h>
+ #include <asm/reboot.h>
++#include <asm/sections.h>
+ #include <asm/time.h>
+ #include <asm/traps.h>
+ #include <asm/wbflush.h>
+@@ -166,6 +170,9 @@ void __init plat_mem_setup(void)
+       ioport_resource.start = ~0UL;
+       ioport_resource.end = 0UL;
++
++      /* Stay away from the firmware working memory area for now. */
++      memblock_reserve(PHYS_OFFSET, __pa_symbol(&_text) - PHYS_OFFSET);
+ }
+ /*
diff --git a/queue-5.4/nfs-fix-nfs_path-in-case-of-a-rename-retry.patch b/queue-5.4/nfs-fix-nfs_path-in-case-of-a-rename-retry.patch
new file mode 100644 (file)
index 0000000..183c298
--- /dev/null
@@ -0,0 +1,58 @@
+From 247db73560bc3e5aef6db50c443c3c0db115bc93 Mon Sep 17 00:00:00 2001
+From: Ashish Sangwan <ashishsangwan2@gmail.com>
+Date: Mon, 5 Oct 2020 02:22:43 -0700
+Subject: NFS: fix nfs_path in case of a rename retry
+
+From: Ashish Sangwan <ashishsangwan2@gmail.com>
+
+commit 247db73560bc3e5aef6db50c443c3c0db115bc93 upstream.
+
+We are generating incorrect path in case of rename retry because
+we are restarting from wrong dentry. We should restart from the
+dentry which was received in the call to nfs_path.
+
+CC: stable@vger.kernel.org
+Signed-off-by: Ashish Sangwan <ashishsangwan2@gmail.com>
+Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/nfs/namespace.c |   12 ++++++++----
+ 1 file changed, 8 insertions(+), 4 deletions(-)
+
+--- a/fs/nfs/namespace.c
++++ b/fs/nfs/namespace.c
+@@ -31,9 +31,9 @@ int nfs_mountpoint_expiry_timeout = 500
+ /*
+  * nfs_path - reconstruct the path given an arbitrary dentry
+  * @base - used to return pointer to the end of devname part of path
+- * @dentry - pointer to dentry
++ * @dentry_in - pointer to dentry
+  * @buffer - result buffer
+- * @buflen - length of buffer
++ * @buflen_in - length of buffer
+  * @flags - options (see below)
+  *
+  * Helper function for constructing the server pathname
+@@ -48,15 +48,19 @@ int nfs_mountpoint_expiry_timeout = 500
+  *                   the original device (export) name
+  *                   (if unset, the original name is returned verbatim)
+  */
+-char *nfs_path(char **p, struct dentry *dentry, char *buffer, ssize_t buflen,
+-             unsigned flags)
++char *nfs_path(char **p, struct dentry *dentry_in, char *buffer,
++             ssize_t buflen_in, unsigned flags)
+ {
+       char *end;
+       int namelen;
+       unsigned seq;
+       const char *base;
++      struct dentry *dentry;
++      ssize_t buflen;
+ rename_retry:
++      buflen = buflen_in;
++      dentry = dentry_in;
+       end = buffer+buflen;
+       *--end = '\0';
+       buflen--;
diff --git a/queue-5.4/nfsd-add-missing-nfsv2-.pc_func-methods.patch b/queue-5.4/nfsd-add-missing-nfsv2-.pc_func-methods.patch
new file mode 100644 (file)
index 0000000..182496a
--- /dev/null
@@ -0,0 +1,72 @@
+From 6b3dccd48de8a4c650b01499a0b09d1e2279649e Mon Sep 17 00:00:00 2001
+From: Chuck Lever <chuck.lever@oracle.com>
+Date: Thu, 1 Oct 2020 18:58:56 -0400
+Subject: NFSD: Add missing NFSv2 .pc_func methods
+
+From: Chuck Lever <chuck.lever@oracle.com>
+
+commit 6b3dccd48de8a4c650b01499a0b09d1e2279649e upstream.
+
+There's no protection in nfsd_dispatch() against a NULL .pc_func
+helpers. A malicious NFS client can trigger a crash by invoking the
+unused/unsupported NFSv2 ROOT or WRITECACHE procedures.
+
+The current NFSD dispatcher does not support returning a void reply
+to a non-NULL procedure, so the reply to both of these is wrong, for
+the moment.
+
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Signed-off-by: J. Bruce Fields <bfields@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/nfsd/nfsproc.c |   16 ++++++++++++++++
+ 1 file changed, 16 insertions(+)
+
+--- a/fs/nfsd/nfsproc.c
++++ b/fs/nfsd/nfsproc.c
+@@ -118,6 +118,13 @@ done:
+       return nfsd_return_attrs(nfserr, resp);
+ }
++/* Obsolete, replaced by MNTPROC_MNT. */
++static __be32
++nfsd_proc_root(struct svc_rqst *rqstp)
++{
++      return nfs_ok;
++}
++
+ /*
+  * Look up a path name component
+  * Note: the dentry in the resp->fh may be negative if the file
+@@ -203,6 +210,13 @@ nfsd_proc_read(struct svc_rqst *rqstp)
+       return fh_getattr(&resp->fh, &resp->stat);
+ }
++/* Reserved */
++static __be32
++nfsd_proc_writecache(struct svc_rqst *rqstp)
++{
++      return nfs_ok;
++}
++
+ /*
+  * Write data to a file
+  * N.B. After this call resp->fh needs an fh_put
+@@ -617,6 +631,7 @@ static const struct svc_procedure nfsd_p
+               .pc_xdrressize = ST+AT,
+       },
+       [NFSPROC_ROOT] = {
++              .pc_func = nfsd_proc_root,
+               .pc_decode = nfssvc_decode_void,
+               .pc_encode = nfssvc_encode_void,
+               .pc_argsize = sizeof(struct nfsd_void),
+@@ -654,6 +669,7 @@ static const struct svc_procedure nfsd_p
+               .pc_xdrressize = ST+AT+1+NFSSVC_MAXBLKSIZE_V2/4,
+       },
+       [NFSPROC_WRITECACHE] = {
++              .pc_func = nfsd_proc_writecache,
+               .pc_decode = nfssvc_decode_void,
+               .pc_encode = nfssvc_encode_void,
+               .pc_argsize = sizeof(struct nfsd_void),
diff --git a/queue-5.4/nfsv4-wait-for-stateid-updates-after-close-open_downgrade.patch b/queue-5.4/nfsv4-wait-for-stateid-updates-after-close-open_downgrade.patch
new file mode 100644 (file)
index 0000000..34170a2
--- /dev/null
@@ -0,0 +1,231 @@
+From b4868b44c5628995fdd8ef2e24dda73cef963a75 Mon Sep 17 00:00:00 2001
+From: Benjamin Coddington <bcodding@redhat.com>
+Date: Fri, 25 Sep 2020 15:48:39 -0400
+Subject: NFSv4: Wait for stateid updates after CLOSE/OPEN_DOWNGRADE
+
+From: Benjamin Coddington <bcodding@redhat.com>
+
+commit b4868b44c5628995fdd8ef2e24dda73cef963a75 upstream.
+
+Since commit 0e0cb35b417f ("NFSv4: Handle NFS4ERR_OLD_STATEID in
+CLOSE/OPEN_DOWNGRADE") the following livelock may occur if a CLOSE races
+with the update of the nfs_state:
+
+Process 1           Process 2           Server
+=========           =========           ========
+ OPEN file
+                    OPEN file
+                                        Reply OPEN (1)
+                                        Reply OPEN (2)
+ Update state (1)
+ CLOSE file (1)
+                                        Reply OLD_STATEID (1)
+ CLOSE file (2)
+                                        Reply CLOSE (-1)
+                    Update state (2)
+                    wait for state change
+ OPEN file
+                    wake
+ CLOSE file
+ OPEN file
+                    wake
+ CLOSE file
+ ...
+                    ...
+
+We can avoid this situation by not issuing an immediate retry with a bumped
+seqid when CLOSE/OPEN_DOWNGRADE receives NFS4ERR_OLD_STATEID.  Instead,
+take the same approach used by OPEN and wait at least 5 seconds for
+outstanding stateid updates to complete if we can detect that we're out of
+sequence.
+
+Note that after this change it is still possible (though unlikely) that
+CLOSE waits a full 5 seconds, bumps the seqid, and retries -- and that
+attempt races with another OPEN at the same time.  In order to avoid this
+race (which would result in the livelock), update
+nfs_need_update_open_stateid() to handle the case where:
+ - the state is NFS_OPEN_STATE, and
+ - the stateid doesn't match the current open stateid
+
+Finally, nfs_need_update_open_stateid() is modified to be idempotent and
+renamed to better suit the purpose of signaling that the stateid passed
+is the next stateid in sequence.
+
+Fixes: 0e0cb35b417f ("NFSv4: Handle NFS4ERR_OLD_STATEID in CLOSE/OPEN_DOWNGRADE")
+Cc: stable@vger.kernel.org # v5.4+
+Signed-off-by: Benjamin Coddington <bcodding@redhat.com>
+Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/nfs/nfs4_fs.h   |    8 +++++
+ fs/nfs/nfs4proc.c  |   81 ++++++++++++++++++++++++++++++-----------------------
+ fs/nfs/nfs4trace.h |    1 
+ 3 files changed, 56 insertions(+), 34 deletions(-)
+
+--- a/fs/nfs/nfs4_fs.h
++++ b/fs/nfs/nfs4_fs.h
+@@ -570,6 +570,14 @@ static inline bool nfs4_stateid_is_newer
+       return (s32)(be32_to_cpu(s1->seqid) - be32_to_cpu(s2->seqid)) > 0;
+ }
++static inline bool nfs4_stateid_is_next(const nfs4_stateid *s1, const nfs4_stateid *s2)
++{
++      u32 seq1 = be32_to_cpu(s1->seqid);
++      u32 seq2 = be32_to_cpu(s2->seqid);
++
++      return seq2 == seq1 + 1U || (seq2 == 1U && seq1 == 0xffffffffU);
++}
++
+ static inline void nfs4_stateid_seqid_inc(nfs4_stateid *s1)
+ {
+       u32 seqid = be32_to_cpu(s1->seqid);
+--- a/fs/nfs/nfs4proc.c
++++ b/fs/nfs/nfs4proc.c
+@@ -1515,19 +1515,6 @@ static void nfs_state_log_update_open_st
+               wake_up_all(&state->waitq);
+ }
+-static void nfs_state_log_out_of_order_open_stateid(struct nfs4_state *state,
+-              const nfs4_stateid *stateid)
+-{
+-      u32 state_seqid = be32_to_cpu(state->open_stateid.seqid);
+-      u32 stateid_seqid = be32_to_cpu(stateid->seqid);
+-
+-      if (stateid_seqid == state_seqid + 1U ||
+-          (stateid_seqid == 1U && state_seqid == 0xffffffffU))
+-              nfs_state_log_update_open_stateid(state);
+-      else
+-              set_bit(NFS_STATE_CHANGE_WAIT, &state->flags);
+-}
+-
+ static void nfs_test_and_clear_all_open_stateid(struct nfs4_state *state)
+ {
+       struct nfs_client *clp = state->owner->so_server->nfs_client;
+@@ -1553,21 +1540,19 @@ static void nfs_test_and_clear_all_open_
+  * i.e. The stateid seqids have to be initialised to 1, and
+  * are then incremented on every state transition.
+  */
+-static bool nfs_need_update_open_stateid(struct nfs4_state *state,
++static bool nfs_stateid_is_sequential(struct nfs4_state *state,
+               const nfs4_stateid *stateid)
+ {
+-      if (test_bit(NFS_OPEN_STATE, &state->flags) == 0 ||
+-          !nfs4_stateid_match_other(stateid, &state->open_stateid)) {
++      if (test_bit(NFS_OPEN_STATE, &state->flags)) {
++              /* The common case - we're updating to a new sequence number */
++              if (nfs4_stateid_match_other(stateid, &state->open_stateid) &&
++                      nfs4_stateid_is_next(&state->open_stateid, stateid)) {
++                      return true;
++              }
++      } else {
++              /* This is the first OPEN in this generation */
+               if (stateid->seqid == cpu_to_be32(1))
+-                      nfs_state_log_update_open_stateid(state);
+-              else
+-                      set_bit(NFS_STATE_CHANGE_WAIT, &state->flags);
+-              return true;
+-      }
+-
+-      if (nfs4_stateid_is_newer(stateid, &state->open_stateid)) {
+-              nfs_state_log_out_of_order_open_stateid(state, stateid);
+-              return true;
++                      return true;
+       }
+       return false;
+ }
+@@ -1641,16 +1626,16 @@ static void nfs_set_open_stateid_locked(
+       int status = 0;
+       for (;;) {
+-              if (!nfs_need_update_open_stateid(state, stateid))
+-                      return;
+-              if (!test_bit(NFS_STATE_CHANGE_WAIT, &state->flags))
++              if (nfs_stateid_is_sequential(state, stateid))
+                       break;
++
+               if (status)
+                       break;
+               /* Rely on seqids for serialisation with NFSv4.0 */
+               if (!nfs4_has_session(NFS_SERVER(state->inode)->nfs_client))
+                       break;
++              set_bit(NFS_STATE_CHANGE_WAIT, &state->flags);
+               prepare_to_wait(&state->waitq, &wait, TASK_KILLABLE);
+               /*
+                * Ensure we process the state changes in the same order
+@@ -1661,6 +1646,7 @@ static void nfs_set_open_stateid_locked(
+               spin_unlock(&state->owner->so_lock);
+               rcu_read_unlock();
+               trace_nfs4_open_stateid_update_wait(state->inode, stateid, 0);
++
+               if (!signal_pending(current)) {
+                       if (schedule_timeout(5*HZ) == 0)
+                               status = -EAGAIN;
+@@ -3397,7 +3383,8 @@ static bool nfs4_refresh_open_old_statei
+       __be32 seqid_open;
+       u32 dst_seqid;
+       bool ret;
+-      int seq;
++      int seq, status = -EAGAIN;
++      DEFINE_WAIT(wait);
+       for (;;) {
+               ret = false;
+@@ -3409,15 +3396,41 @@ static bool nfs4_refresh_open_old_statei
+                               continue;
+                       break;
+               }
++
++              write_seqlock(&state->seqlock);
+               seqid_open = state->open_stateid.seqid;
+-              if (read_seqretry(&state->seqlock, seq))
+-                      continue;
+               dst_seqid = be32_to_cpu(dst->seqid);
+-              if ((s32)(dst_seqid - be32_to_cpu(seqid_open)) >= 0)
+-                      dst->seqid = cpu_to_be32(dst_seqid + 1);
+-              else
++
++              /* Did another OPEN bump the state's seqid?  try again: */
++              if ((s32)(be32_to_cpu(seqid_open) - dst_seqid) > 0) {
+                       dst->seqid = seqid_open;
++                      write_sequnlock(&state->seqlock);
++                      ret = true;
++                      break;
++              }
++
++              /* server says we're behind but we haven't seen the update yet */
++              set_bit(NFS_STATE_CHANGE_WAIT, &state->flags);
++              prepare_to_wait(&state->waitq, &wait, TASK_KILLABLE);
++              write_sequnlock(&state->seqlock);
++              trace_nfs4_close_stateid_update_wait(state->inode, dst, 0);
++
++              if (signal_pending(current))
++                      status = -EINTR;
++              else
++                      if (schedule_timeout(5*HZ) != 0)
++                              status = 0;
++
++              finish_wait(&state->waitq, &wait);
++
++              if (!status)
++                      continue;
++              if (status == -EINTR)
++                      break;
++
++              /* we slept the whole 5 seconds, we must have lost a seqid */
++              dst->seqid = cpu_to_be32(dst_seqid + 1);
+               ret = true;
+               break;
+       }
+--- a/fs/nfs/nfs4trace.h
++++ b/fs/nfs/nfs4trace.h
+@@ -1291,6 +1291,7 @@ DEFINE_NFS4_INODE_STATEID_EVENT(nfs4_set
+ DEFINE_NFS4_INODE_STATEID_EVENT(nfs4_delegreturn);
+ DEFINE_NFS4_INODE_STATEID_EVENT(nfs4_open_stateid_update);
+ DEFINE_NFS4_INODE_STATEID_EVENT(nfs4_open_stateid_update_wait);
++DEFINE_NFS4_INODE_STATEID_EVENT(nfs4_close_stateid_update_wait);
+ DECLARE_EVENT_CLASS(nfs4_getattr_event,
+               TP_PROTO(
diff --git a/queue-5.4/nfsv4.2-support-exchgid4_flag_supp_fence_ops-4.2-exchange_id-flag.patch b/queue-5.4/nfsv4.2-support-exchgid4_flag_supp_fence_ops-4.2-exchange_id-flag.patch
new file mode 100644 (file)
index 0000000..3e523ac
--- /dev/null
@@ -0,0 +1,71 @@
+From 8c39076c276be0b31982e44654e2c2357473258a Mon Sep 17 00:00:00 2001
+From: Olga Kornievskaia <kolga@netapp.com>
+Date: Fri, 16 Oct 2020 09:25:45 -0400
+Subject: NFSv4.2: support EXCHGID4_FLAG_SUPP_FENCE_OPS 4.2 EXCHANGE_ID flag
+
+From: Olga Kornievskaia <kolga@netapp.com>
+
+commit 8c39076c276be0b31982e44654e2c2357473258a upstream.
+
+RFC 7862 introduced a new flag that either client or server is
+allowed to set: EXCHGID4_FLAG_SUPP_FENCE_OPS.
+
+Client needs to update its bitmask to allow for this flag value.
+
+v2: changed minor version argument to unsigned int
+
+Signed-off-by: Olga Kornievskaia <kolga@netapp.com>
+CC: <stable@vger.kernel.org>
+Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/nfs/nfs4proc.c         |    9 ++++++---
+ include/uapi/linux/nfs4.h |    3 +++
+ 2 files changed, 9 insertions(+), 3 deletions(-)
+
+--- a/fs/nfs/nfs4proc.c
++++ b/fs/nfs/nfs4proc.c
+@@ -7859,9 +7859,11 @@ int nfs4_proc_secinfo(struct inode *dir,
+  * both PNFS and NON_PNFS flags set, and not having one of NON_PNFS, PNFS, or
+  * DS flags set.
+  */
+-static int nfs4_check_cl_exchange_flags(u32 flags)
++static int nfs4_check_cl_exchange_flags(u32 flags, u32 version)
+ {
+-      if (flags & ~EXCHGID4_FLAG_MASK_R)
++      if (version >= 2 && (flags & ~EXCHGID4_2_FLAG_MASK_R))
++              goto out_inval;
++      else if (version < 2 && (flags & ~EXCHGID4_FLAG_MASK_R))
+               goto out_inval;
+       if ((flags & EXCHGID4_FLAG_USE_PNFS_MDS) &&
+           (flags & EXCHGID4_FLAG_USE_NON_PNFS))
+@@ -8274,7 +8276,8 @@ static int _nfs4_proc_exchange_id(struct
+       if (status  != 0)
+               goto out;
+-      status = nfs4_check_cl_exchange_flags(resp->flags);
++      status = nfs4_check_cl_exchange_flags(resp->flags,
++                      clp->cl_mvops->minor_version);
+       if (status  != 0)
+               goto out;
+--- a/include/uapi/linux/nfs4.h
++++ b/include/uapi/linux/nfs4.h
+@@ -136,6 +136,8 @@
+ #define EXCHGID4_FLAG_UPD_CONFIRMED_REC_A     0x40000000
+ #define EXCHGID4_FLAG_CONFIRMED_R             0x80000000
++
++#define EXCHGID4_FLAG_SUPP_FENCE_OPS          0x00000004
+ /*
+  * Since the validity of these bits depends on whether
+  * they're set in the argument or response, have separate
+@@ -143,6 +145,7 @@
+  */
+ #define EXCHGID4_FLAG_MASK_A                  0x40070103
+ #define EXCHGID4_FLAG_MASK_R                  0x80070103
++#define EXCHGID4_2_FLAG_MASK_R                        0x80070107
+ #define SEQ4_STATUS_CB_PATH_DOWN              0x00000001
+ #define SEQ4_STATUS_CB_GSS_CONTEXTS_EXPIRING  0x00000002
diff --git a/queue-5.4/pci-acpi-whitelist-hotplug-ports-for-d3-if-power-managed-by-acpi.patch b/queue-5.4/pci-acpi-whitelist-hotplug-ports-for-d3-if-power-managed-by-acpi.patch
new file mode 100644 (file)
index 0000000..9625257
--- /dev/null
@@ -0,0 +1,65 @@
+From c6e331312ebfb52b7186e5d82d517d68b4d2f2d8 Mon Sep 17 00:00:00 2001
+From: Lukas Wunner <lukas@wunner.de>
+Date: Fri, 2 Oct 2020 07:10:12 +0200
+Subject: PCI/ACPI: Whitelist hotplug ports for D3 if power managed by ACPI
+
+From: Lukas Wunner <lukas@wunner.de>
+
+commit c6e331312ebfb52b7186e5d82d517d68b4d2f2d8 upstream.
+
+Recent laptops with dual AMD GPUs fail to suspend the discrete GPU, thus
+causing lockups on system sleep and high power consumption at runtime.
+The discrete GPU would normally be suspended to D3cold by turning off
+ACPI _PR3 Power Resources of the Root Port above the GPU.
+
+However on affected systems, the Root Port is hotplug-capable and
+pci_bridge_d3_possible() only allows hotplug ports to go to D3 if they
+belong to a Thunderbolt device or if the Root Port possesses a
+"HotPlugSupportInD3" ACPI property.  Neither is the case on affected
+laptops.  The reason for whitelisting only specific, known to work
+hotplug ports for D3 is that there have been reports of SkyLake Xeon-SP
+systems raising Hardware Error NMIs upon suspending their hotplug ports:
+https://lore.kernel.org/linux-pci/20170503180426.GA4058@otc-nc-03/
+
+But if a hotplug port is power manageable by ACPI (as can be detected
+through presence of Power Resources and corresponding _PS0 and _PS3
+methods) then it ought to be safe to suspend it to D3.  To this end,
+amend acpi_pci_bridge_d3() to whitelist such ports for D3.
+
+Link: https://gitlab.freedesktop.org/drm/amd/-/issues/1222
+Link: https://gitlab.freedesktop.org/drm/amd/-/issues/1252
+Link: https://gitlab.freedesktop.org/drm/amd/-/issues/1304
+Reported-and-tested-by: Arthur Borsboom <arthurborsboom@gmail.com>
+Reported-and-tested-by: matoro <matoro@airmail.cc>
+Reported-by: Aaron Zakhrov <aaron.zakhrov@gmail.com>
+Reported-by: Michal Rostecki <mrostecki@suse.com>
+Reported-by: Shai Coleman <git@shaicoleman.com>
+Signed-off-by: Lukas Wunner <lukas@wunner.de>
+Acked-by: Alex Deucher <alexander.deucher@amd.com>
+Cc: 5.4+ <stable@vger.kernel.org> # 5.4+
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/pci/pci-acpi.c |   10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+--- a/drivers/pci/pci-acpi.c
++++ b/drivers/pci/pci-acpi.c
+@@ -944,6 +944,16 @@ static bool acpi_pci_bridge_d3(struct pc
+       if (!dev->is_hotplug_bridge)
+               return false;
++      /* Assume D3 support if the bridge is power-manageable by ACPI. */
++      adev = ACPI_COMPANION(&dev->dev);
++      if (!adev && !pci_dev_is_added(dev)) {
++              adev = acpi_pci_find_companion(&dev->dev);
++              ACPI_COMPANION_SET(&dev->dev, adev);
++      }
++
++      if (adev && acpi_device_power_manageable(adev))
++              return true;
++
+       /*
+        * Look for a special _DSD property for the root port and if it
+        * is set we know the hierarchy behind it supports D3 just fine.
diff --git a/queue-5.4/pm-runtime-remove-link-state-checks-in-rpm_get-put_supplier.patch b/queue-5.4/pm-runtime-remove-link-state-checks-in-rpm_get-put_supplier.patch
new file mode 100644 (file)
index 0000000..bd77587
--- /dev/null
@@ -0,0 +1,84 @@
+From d12544fb2aa9944b180c35914031a8384ab082c1 Mon Sep 17 00:00:00 2001
+From: Xiang Chen <chenxiang66@hisilicon.com>
+Date: Tue, 22 Sep 2020 21:11:06 +0800
+Subject: PM: runtime: Remove link state checks in rpm_get/put_supplier()
+
+From: Xiang Chen <chenxiang66@hisilicon.com>
+
+commit d12544fb2aa9944b180c35914031a8384ab082c1 upstream.
+
+To support runtime PM for hisi SAS driver (the driver is in directory
+drivers/scsi/hisi_sas), we add device link between scsi_device->sdev_gendev
+(consumer device) and hisi_hba->dev(supplier device) with flags
+DL_FLAG_PM_RUNTIME | DL_FLAG_RPM_ACTIVE.
+
+After runtime suspended consumers and supplier, unload the dirver which
+causes a hung.
+
+We found that it called function device_release_driver_internal() to
+release the supplier device (hisi_hba->dev), as the device link was
+busy, it set the device link state to DL_STATE_SUPPLIER_UNBIND, and
+then it called device_release_driver_internal() to release the consumer
+device (scsi_device->sdev_gendev).
+
+Then it would try to call pm_runtime_get_sync() to resume the consumer
+device, but because consumer-supplier relation existed, it would try
+to resume the supplier first, but as the link state was already
+DL_STATE_SUPPLIER_UNBIND, so it skipped resuming the supplier and only
+resumed the consumer which hanged (it sends IOs to resume scsi_device
+while the SAS controller is suspended).
+
+Simple flow is as follows:
+
+device_release_driver_internal -> (supplier device)
+    if device_links_busy ->
+       device_links_unbind_consumers ->
+           ...
+           WRITE_ONCE(link->status, DL_STATE_SUPPLIER_UNBIND)
+           device_release_driver_internal (consumer device)
+    pm_runtime_get_sync -> (consumer device)
+       ...
+       __rpm_callback ->
+           rpm_get_suppliers ->
+               if link->state == DL_STATE_SUPPLIER_UNBIND -> skip the action of resuming the supplier
+               ...
+    pm_runtime_clean_up_links
+    ...
+
+Correct suspend/resume ordering between a supplier device and its consumer
+devices (resume the supplier device before resuming consumer devices, and
+suspend consumer devices before suspending the supplier device) should be
+guaranteed by runtime PM, but the state checks in rpm_get_supplier() and
+rpm_put_supplier() break this rule, so remove them.
+
+Signed-off-by: Xiang Chen <chenxiang66@hisilicon.com>
+[ rjw: Subject and changelog edits ]
+Cc: All applicable <stable@vger.kernel.org>
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/base/power/runtime.c |    5 +----
+ 1 file changed, 1 insertion(+), 4 deletions(-)
+
+--- a/drivers/base/power/runtime.c
++++ b/drivers/base/power/runtime.c
+@@ -291,8 +291,7 @@ static int rpm_get_suppliers(struct devi
+                               device_links_read_lock_held()) {
+               int retval;
+-              if (!(link->flags & DL_FLAG_PM_RUNTIME) ||
+-                  READ_ONCE(link->status) == DL_STATE_SUPPLIER_UNBIND)
++              if (!(link->flags & DL_FLAG_PM_RUNTIME))
+                       continue;
+               retval = pm_runtime_get_sync(link->supplier);
+@@ -312,8 +311,6 @@ static void rpm_put_suppliers(struct dev
+       list_for_each_entry_rcu(link, &dev->links.suppliers, c_node,
+                               device_links_read_lock_held()) {
+-              if (READ_ONCE(link->status) == DL_STATE_SUPPLIER_UNBIND)
+-                      continue;
+               while (refcount_dec_not_one(&link->rpm_active))
+                       pm_runtime_put(link->supplier);
diff --git a/queue-5.4/powerpc-drmem-make-lmb_size-64-bit.patch b/queue-5.4/powerpc-drmem-make-lmb_size-64-bit.patch
new file mode 100644 (file)
index 0000000..71f3de9
--- /dev/null
@@ -0,0 +1,45 @@
+From ec72024e35dddb88a81e40071c87ceb18b5ee835 Mon Sep 17 00:00:00 2001
+From: "Aneesh Kumar K.V" <aneesh.kumar@linux.ibm.com>
+Date: Wed, 7 Oct 2020 17:18:33 +0530
+Subject: powerpc/drmem: Make lmb_size 64 bit
+
+From: Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com>
+
+commit ec72024e35dddb88a81e40071c87ceb18b5ee835 upstream.
+
+Similar to commit 89c140bbaeee ("pseries: Fix 64 bit logical memory block panic")
+make sure different variables tracking lmb_size are updated to be 64 bit.
+
+This was found by code audit.
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com>
+Acked-by: Nathan Lynch <nathanl@linux.ibm.com>
+Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
+Link: https://lore.kernel.org/r/20201007114836.282468-2-aneesh.kumar@linux.ibm.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/powerpc/include/asm/drmem.h |    4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/arch/powerpc/include/asm/drmem.h
++++ b/arch/powerpc/include/asm/drmem.h
+@@ -20,7 +20,7 @@ struct drmem_lmb {
+ struct drmem_lmb_info {
+       struct drmem_lmb        *lmbs;
+       int                     n_lmbs;
+-      u32                     lmb_size;
++      u64                     lmb_size;
+ };
+ extern struct drmem_lmb_info *drmem_info;
+@@ -79,7 +79,7 @@ struct of_drconf_cell_v2 {
+ #define DRCONF_MEM_AI_INVALID 0x00000040
+ #define DRCONF_MEM_RESERVED   0x00000080
+-static inline u32 drmem_lmb_size(void)
++static inline u64 drmem_lmb_size(void)
+ {
+       return drmem_info->lmb_size;
+ }
diff --git a/queue-5.4/powerpc-fix-undetected-data-corruption-with-p9n-dd2.1-vsx-ci-load-emulation.patch b/queue-5.4/powerpc-fix-undetected-data-corruption-with-p9n-dd2.1-vsx-ci-load-emulation.patch
new file mode 100644 (file)
index 0000000..ddf884c
--- /dev/null
@@ -0,0 +1,53 @@
+From 1da4a0272c5469169f78cd76cf175ff984f52f06 Mon Sep 17 00:00:00 2001
+From: Michael Neuling <mikey@neuling.org>
+Date: Tue, 13 Oct 2020 15:37:40 +1100
+Subject: powerpc: Fix undetected data corruption with P9N DD2.1 VSX CI load emulation
+
+From: Michael Neuling <mikey@neuling.org>
+
+commit 1da4a0272c5469169f78cd76cf175ff984f52f06 upstream.
+
+__get_user_atomic_128_aligned() stores to kaddr using stvx which is a
+VMX store instruction, hence kaddr must be 16 byte aligned otherwise
+the store won't occur as expected.
+
+Unfortunately when we call __get_user_atomic_128_aligned() in
+p9_hmi_special_emu(), the buffer we pass as kaddr (ie. vbuf) isn't
+guaranteed to be 16B aligned. This means that the write to vbuf in
+__get_user_atomic_128_aligned() has the bottom bits of the address
+truncated. This results in other local variables being
+overwritten. Also vbuf will not contain the correct data which results
+in the userspace emulation being wrong and hence undetected user data
+corruption.
+
+In the past we've been mostly lucky as vbuf has ended up aligned but
+this is fragile and isn't always true. CONFIG_STACKPROTECTOR in
+particular can change the stack arrangement enough that our luck runs
+out.
+
+This issue only occurs on POWER9 Nimbus <= DD2.1 bare metal.
+
+The fix is to align vbuf to a 16 byte boundary.
+
+Fixes: 5080332c2c89 ("powerpc/64s: Add workaround for P9 vector CI load issue")
+Cc: stable@vger.kernel.org # v4.15+
+Signed-off-by: Michael Neuling <mikey@neuling.org>
+Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
+Link: https://lore.kernel.org/r/20201013043741.743413-1-mikey@neuling.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/powerpc/kernel/traps.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/arch/powerpc/kernel/traps.c
++++ b/arch/powerpc/kernel/traps.c
+@@ -877,7 +877,7 @@ static void p9_hmi_special_emu(struct pt
+ {
+       unsigned int ra, rb, t, i, sel, instr, rc;
+       const void __user *addr;
+-      u8 vbuf[16], *vdst;
++      u8 vbuf[16] __aligned(16), *vdst;
+       unsigned long ea, msr, msr_mask;
+       bool swap;
diff --git a/queue-5.4/powerpc-memhotplug-make-lmb-size-64bit.patch b/queue-5.4/powerpc-memhotplug-make-lmb-size-64bit.patch
new file mode 100644 (file)
index 0000000..c6a9a20
--- /dev/null
@@ -0,0 +1,119 @@
+From 301d2ea6572386245c5d2d2dc85c3b5a737b85ac Mon Sep 17 00:00:00 2001
+From: "Aneesh Kumar K.V" <aneesh.kumar@linux.ibm.com>
+Date: Wed, 7 Oct 2020 17:18:34 +0530
+Subject: powerpc/memhotplug: Make lmb size 64bit
+
+From: Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com>
+
+commit 301d2ea6572386245c5d2d2dc85c3b5a737b85ac upstream.
+
+Similar to commit 89c140bbaeee ("pseries: Fix 64 bit logical memory block panic")
+make sure different variables tracking lmb_size are updated to be 64 bit.
+
+This was found by code audit.
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com>
+Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
+Link: https://lore.kernel.org/r/20201007114836.282468-3-aneesh.kumar@linux.ibm.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/powerpc/platforms/pseries/hotplug-memory.c |   43 ++++++++++++++++--------
+ 1 file changed, 29 insertions(+), 14 deletions(-)
+
+--- a/arch/powerpc/platforms/pseries/hotplug-memory.c
++++ b/arch/powerpc/platforms/pseries/hotplug-memory.c
+@@ -279,7 +279,7 @@ static int dlpar_offline_lmb(struct drme
+       return dlpar_change_lmb_state(lmb, false);
+ }
+-static int pseries_remove_memblock(unsigned long base, unsigned int memblock_size)
++static int pseries_remove_memblock(unsigned long base, unsigned long memblock_size)
+ {
+       unsigned long block_sz, start_pfn;
+       int sections_per_block;
+@@ -310,10 +310,11 @@ out:
+ static int pseries_remove_mem_node(struct device_node *np)
+ {
+-      const __be32 *regs;
++      const __be32 *prop;
+       unsigned long base;
+-      unsigned int lmb_size;
++      unsigned long lmb_size;
+       int ret = -EINVAL;
++      int addr_cells, size_cells;
+       /*
+        * Check to see if we are actually removing memory
+@@ -324,12 +325,19 @@ static int pseries_remove_mem_node(struc
+       /*
+        * Find the base address and size of the memblock
+        */
+-      regs = of_get_property(np, "reg", NULL);
+-      if (!regs)
++      prop = of_get_property(np, "reg", NULL);
++      if (!prop)
+               return ret;
+-      base = be64_to_cpu(*(unsigned long *)regs);
+-      lmb_size = be32_to_cpu(regs[3]);
++      addr_cells = of_n_addr_cells(np);
++      size_cells = of_n_size_cells(np);
++
++      /*
++       * "reg" property represents (addr,size) tuple.
++       */
++      base = of_read_number(prop, addr_cells);
++      prop += addr_cells;
++      lmb_size = of_read_number(prop, size_cells);
+       pseries_remove_memblock(base, lmb_size);
+       return 0;
+@@ -620,7 +628,7 @@ static int dlpar_memory_remove_by_ic(u32
+ #else
+ static inline int pseries_remove_memblock(unsigned long base,
+-                                        unsigned int memblock_size)
++                                        unsigned long memblock_size)
+ {
+       return -EOPNOTSUPP;
+ }
+@@ -953,10 +961,11 @@ int dlpar_memory(struct pseries_hp_error
+ static int pseries_add_mem_node(struct device_node *np)
+ {
+-      const __be32 *regs;
++      const __be32 *prop;
+       unsigned long base;
+-      unsigned int lmb_size;
++      unsigned long lmb_size;
+       int ret = -EINVAL;
++      int addr_cells, size_cells;
+       /*
+        * Check to see if we are actually adding memory
+@@ -967,12 +976,18 @@ static int pseries_add_mem_node(struct d
+       /*
+        * Find the base and size of the memblock
+        */
+-      regs = of_get_property(np, "reg", NULL);
+-      if (!regs)
++      prop = of_get_property(np, "reg", NULL);
++      if (!prop)
+               return ret;
+-      base = be64_to_cpu(*(unsigned long *)regs);
+-      lmb_size = be32_to_cpu(regs[3]);
++      addr_cells = of_n_addr_cells(np);
++      size_cells = of_n_size_cells(np);
++      /*
++       * "reg" property represents (addr,size) tuple.
++       */
++      base = of_read_number(prop, addr_cells);
++      prop += addr_cells;
++      lmb_size = of_read_number(prop, size_cells);
+       /*
+        * Update memory region to represent the memory add
diff --git a/queue-5.4/powerpc-powermac-fix-low_sleep_handler-with-kuap-and-kuep.patch b/queue-5.4/powerpc-powermac-fix-low_sleep_handler-with-kuap-and-kuep.patch
new file mode 100644 (file)
index 0000000..e91ddce
--- /dev/null
@@ -0,0 +1,56 @@
+From 2c637d2df4ee4830e9d3eb2bd5412250522ce96e Mon Sep 17 00:00:00 2001
+From: Christophe Leroy <christophe.leroy@csgroup.eu>
+Date: Fri, 11 Sep 2020 10:29:15 +0000
+Subject: powerpc/powermac: Fix low_sleep_handler with KUAP and KUEP
+
+From: Christophe Leroy <christophe.leroy@csgroup.eu>
+
+commit 2c637d2df4ee4830e9d3eb2bd5412250522ce96e upstream.
+
+low_sleep_handler() has an hardcoded restore of segment registers
+that doesn't take KUAP and KUEP into account.
+
+Use head_32's load_segment_registers() routine instead.
+
+Fixes: a68c31fc01ef ("powerpc/32s: Implement Kernel Userspace Access Protection")
+Fixes: 31ed2b13c48d ("powerpc/32s: Implement Kernel Userspace Execution Prevention.")
+Cc: stable@vger.kernel.org
+Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu>
+Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
+Link: https://lore.kernel.org/r/21b05f7298c1b18f73e6e5b4cd5005aafa24b6da.1599820109.git.christophe.leroy@csgroup.eu
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/powerpc/kernel/head_32.S           |    2 +-
+ arch/powerpc/platforms/powermac/sleep.S |    9 +--------
+ 2 files changed, 2 insertions(+), 9 deletions(-)
+
+--- a/arch/powerpc/kernel/head_32.S
++++ b/arch/powerpc/kernel/head_32.S
+@@ -843,7 +843,7 @@ BEGIN_MMU_FTR_SECTION
+ END_MMU_FTR_SECTION_IFSET(MMU_FTR_USE_HIGH_BATS)
+       blr
+-load_segment_registers:
++_GLOBAL(load_segment_registers)
+       li      r0, NUM_USER_SEGMENTS /* load up user segment register values */
+       mtctr   r0              /* for context 0 */
+       li      r3, 0           /* Kp = 0, Ks = 0, VSID = 0 */
+--- a/arch/powerpc/platforms/powermac/sleep.S
++++ b/arch/powerpc/platforms/powermac/sleep.S
+@@ -293,14 +293,7 @@ grackle_wake_up:
+        * we do any r1 memory access as we are not sure they
+        * are in a sane state above the first 256Mb region
+        */
+-      li      r0,16           /* load up segment register values */
+-      mtctr   r0              /* for context 0 */
+-      lis     r3,0x2000       /* Ku = 1, VSID = 0 */
+-      li      r4,0
+-3:    mtsrin  r3,r4
+-      addi    r3,r3,0x111     /* increment VSID */
+-      addis   r4,r4,0x1000    /* address of next segment */
+-      bdnz    3b
++      bl      load_segment_registers
+       sync
+       isync
diff --git a/queue-5.4/powerpc-powernv-elog-fix-race-while-processing-opal-error-log-event.patch b/queue-5.4/powerpc-powernv-elog-fix-race-while-processing-opal-error-log-event.patch
new file mode 100644 (file)
index 0000000..3aea300
--- /dev/null
@@ -0,0 +1,128 @@
+From aea948bb80b478ddc2448f7359d574387521a52d Mon Sep 17 00:00:00 2001
+From: Mahesh Salgaonkar <mahesh@linux.ibm.com>
+Date: Tue, 6 Oct 2020 13:02:18 +0530
+Subject: powerpc/powernv/elog: Fix race while processing OPAL error log event.
+
+From: Mahesh Salgaonkar <mahesh@linux.ibm.com>
+
+commit aea948bb80b478ddc2448f7359d574387521a52d upstream.
+
+Every error log reported by OPAL is exported to userspace through a
+sysfs interface and notified using kobject_uevent(). The userspace
+daemon (opal_errd) then reads the error log and acknowledges the error
+log is saved safely to disk. Once acknowledged the kernel removes the
+respective sysfs file entry causing respective resources to be
+released including kobject.
+
+However it's possible the userspace daemon may already be scanning
+elog entries when a new sysfs elog entry is created by the kernel.
+User daemon may read this new entry and ack it even before kernel can
+notify userspace about it through kobject_uevent() call. If that
+happens then we have a potential race between
+elog_ack_store->kobject_put() and kobject_uevent which can lead to
+use-after-free of a kernfs object resulting in a kernel crash. eg:
+
+  BUG: Unable to handle kernel data access on read at 0x6b6b6b6b6b6b6bfb
+  Faulting instruction address: 0xc0000000008ff2a0
+  Oops: Kernel access of bad area, sig: 11 [#1]
+  LE PAGE_SIZE=64K MMU=Hash SMP NR_CPUS=2048 NUMA PowerNV
+  CPU: 27 PID: 805 Comm: irq/29-opal-elo Not tainted 5.9.0-rc2-gcc-8.2.0-00214-g6f56a67bcbb5-dirty #363
+  ...
+  NIP kobject_uevent_env+0xa0/0x910
+  LR  elog_event+0x1f4/0x2d0
+  Call Trace:
+    0x5deadbeef0000122 (unreliable)
+    elog_event+0x1f4/0x2d0
+    irq_thread_fn+0x4c/0xc0
+    irq_thread+0x1c0/0x2b0
+    kthread+0x1c4/0x1d0
+    ret_from_kernel_thread+0x5c/0x6c
+
+This patch fixes this race by protecting the sysfs file
+creation/notification by holding a reference count on kobject until we
+safely send kobject_uevent().
+
+The function create_elog_obj() returns the elog object which if used
+by caller function will end up in use-after-free problem again.
+However, the return value of create_elog_obj() function isn't being
+used today and there is no need as well. Hence change it to return
+void to make this fix complete.
+
+Fixes: 774fea1a38c6 ("powerpc/powernv: Read OPAL error log and export it through sysfs")
+Cc: stable@vger.kernel.org # v3.15+
+Reported-by: Oliver O'Halloran <oohall@gmail.com>
+Signed-off-by: Mahesh Salgaonkar <mahesh@linux.ibm.com>
+Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com>
+Reviewed-by: Oliver O'Halloran <oohall@gmail.com>
+Reviewed-by: Vasant Hegde <hegdevasant@linux.vnet.ibm.com>
+[mpe: Rework the logic to use a single return, reword comments, add oops]
+Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
+Link: https://lore.kernel.org/r/20201006122051.190176-1-mpe@ellerman.id.au
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/powerpc/platforms/powernv/opal-elog.c |   33 ++++++++++++++++++++++-------
+ 1 file changed, 26 insertions(+), 7 deletions(-)
+
+--- a/arch/powerpc/platforms/powernv/opal-elog.c
++++ b/arch/powerpc/platforms/powernv/opal-elog.c
+@@ -179,14 +179,14 @@ static ssize_t raw_attr_read(struct file
+       return count;
+ }
+-static struct elog_obj *create_elog_obj(uint64_t id, size_t size, uint64_t type)
++static void create_elog_obj(uint64_t id, size_t size, uint64_t type)
+ {
+       struct elog_obj *elog;
+       int rc;
+       elog = kzalloc(sizeof(*elog), GFP_KERNEL);
+       if (!elog)
+-              return NULL;
++              return;
+       elog->kobj.kset = elog_kset;
+@@ -219,18 +219,37 @@ static struct elog_obj *create_elog_obj(
+       rc = kobject_add(&elog->kobj, NULL, "0x%llx", id);
+       if (rc) {
+               kobject_put(&elog->kobj);
+-              return NULL;
++              return;
+       }
++      /*
++       * As soon as the sysfs file for this elog is created/activated there is
++       * a chance the opal_errd daemon (or any userspace) might read and
++       * acknowledge the elog before kobject_uevent() is called. If that
++       * happens then there is a potential race between
++       * elog_ack_store->kobject_put() and kobject_uevent() which leads to a
++       * use-after-free of a kernfs object resulting in a kernel crash.
++       *
++       * To avoid that, we need to take a reference on behalf of the bin file,
++       * so that our reference remains valid while we call kobject_uevent().
++       * We then drop our reference before exiting the function, leaving the
++       * bin file to drop the last reference (if it hasn't already).
++       */
++
++      /* Take a reference for the bin file */
++      kobject_get(&elog->kobj);
+       rc = sysfs_create_bin_file(&elog->kobj, &elog->raw_attr);
+-      if (rc) {
++      if (rc == 0) {
++              kobject_uevent(&elog->kobj, KOBJ_ADD);
++      } else {
++              /* Drop the reference taken for the bin file */
+               kobject_put(&elog->kobj);
+-              return NULL;
+       }
+-      kobject_uevent(&elog->kobj, KOBJ_ADD);
++      /* Drop our reference */
++      kobject_put(&elog->kobj);
+-      return elog;
++      return;
+ }
+ static irqreturn_t elog_event(int irq, void *data)
diff --git a/queue-5.4/powerpc-rtas-restrict-rtas-requests-from-userspace.patch b/queue-5.4/powerpc-rtas-restrict-rtas-requests-from-userspace.patch
new file mode 100644 (file)
index 0000000..dc60248
--- /dev/null
@@ -0,0 +1,264 @@
+From bd59380c5ba4147dcbaad3e582b55ccfd120b764 Mon Sep 17 00:00:00 2001
+From: Andrew Donnellan <ajd@linux.ibm.com>
+Date: Thu, 20 Aug 2020 14:45:12 +1000
+Subject: powerpc/rtas: Restrict RTAS requests from userspace
+
+From: Andrew Donnellan <ajd@linux.ibm.com>
+
+commit bd59380c5ba4147dcbaad3e582b55ccfd120b764 upstream.
+
+A number of userspace utilities depend on making calls to RTAS to retrieve
+information and update various things.
+
+The existing API through which we expose RTAS to userspace exposes more
+RTAS functionality than we actually need, through the sys_rtas syscall,
+which allows root (or anyone with CAP_SYS_ADMIN) to make any RTAS call they
+want with arbitrary arguments.
+
+Many RTAS calls take the address of a buffer as an argument, and it's up to
+the caller to specify the physical address of the buffer as an argument. We
+allocate a buffer (the "RMO buffer") in the Real Memory Area that RTAS can
+access, and then expose the physical address and size of this buffer in
+/proc/powerpc/rtas/rmo_buffer. Userspace is expected to read this address,
+poke at the buffer using /dev/mem, and pass an address in the RMO buffer to
+the RTAS call.
+
+However, there's nothing stopping the caller from specifying whatever
+address they want in the RTAS call, and it's easy to construct a series of
+RTAS calls that can overwrite arbitrary bytes (even without /dev/mem
+access).
+
+Additionally, there are some RTAS calls that do potentially dangerous
+things and for which there are no legitimate userspace use cases.
+
+In the past, this would not have been a particularly big deal as it was
+assumed that root could modify all system state freely, but with Secure
+Boot and lockdown we need to care about this.
+
+We can't fundamentally change the ABI at this point, however we can address
+this by implementing a filter that checks RTAS calls against a list
+of permitted calls and forces the caller to use addresses within the RMO
+buffer.
+
+The list is based off the list of calls that are used by the librtas
+userspace library, and has been tested with a number of existing userspace
+RTAS utilities. For compatibility with any applications we are not aware of
+that require other calls, the filter can be turned off at build time.
+
+Cc: stable@vger.kernel.org
+Reported-by: Daniel Axtens <dja@axtens.net>
+Signed-off-by: Andrew Donnellan <ajd@linux.ibm.com>
+Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
+Link: https://lore.kernel.org/r/20200820044512.7543-1-ajd@linux.ibm.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/powerpc/Kconfig       |   13 +++
+ arch/powerpc/kernel/rtas.c |  153 +++++++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 166 insertions(+)
+
+--- a/arch/powerpc/Kconfig
++++ b/arch/powerpc/Kconfig
+@@ -1024,6 +1024,19 @@ config FSL_RIO
+         Include support for RapidIO controller on Freescale embedded
+         processors (MPC8548, MPC8641, etc).
++config PPC_RTAS_FILTER
++      bool "Enable filtering of RTAS syscalls"
++      default y
++      depends on PPC_RTAS
++      help
++        The RTAS syscall API has security issues that could be used to
++        compromise system integrity. This option enforces restrictions on the
++        RTAS calls and arguments passed by userspace programs to mitigate
++        these issues.
++
++        Say Y unless you know what you are doing and the filter is causing
++        problems for you.
++
+ endmenu
+ config NONSTATIC_KERNEL
+--- a/arch/powerpc/kernel/rtas.c
++++ b/arch/powerpc/kernel/rtas.c
+@@ -940,6 +940,147 @@ struct pseries_errorlog *get_pseries_err
+       return NULL;
+ }
++#ifdef CONFIG_PPC_RTAS_FILTER
++
++/*
++ * The sys_rtas syscall, as originally designed, allows root to pass
++ * arbitrary physical addresses to RTAS calls. A number of RTAS calls
++ * can be abused to write to arbitrary memory and do other things that
++ * are potentially harmful to system integrity, and thus should only
++ * be used inside the kernel and not exposed to userspace.
++ *
++ * All known legitimate users of the sys_rtas syscall will only ever
++ * pass addresses that fall within the RMO buffer, and use a known
++ * subset of RTAS calls.
++ *
++ * Accordingly, we filter RTAS requests to check that the call is
++ * permitted, and that provided pointers fall within the RMO buffer.
++ * The rtas_filters list contains an entry for each permitted call,
++ * with the indexes of the parameters which are expected to contain
++ * addresses and sizes of buffers allocated inside the RMO buffer.
++ */
++struct rtas_filter {
++      const char *name;
++      int token;
++      /* Indexes into the args buffer, -1 if not used */
++      int buf_idx1;
++      int size_idx1;
++      int buf_idx2;
++      int size_idx2;
++
++      int fixed_size;
++};
++
++static struct rtas_filter rtas_filters[] __ro_after_init = {
++      { "ibm,activate-firmware", -1, -1, -1, -1, -1 },
++      { "ibm,configure-connector", -1, 0, -1, 1, -1, 4096 },  /* Special cased */
++      { "display-character", -1, -1, -1, -1, -1 },
++      { "ibm,display-message", -1, 0, -1, -1, -1 },
++      { "ibm,errinjct", -1, 2, -1, -1, -1, 1024 },
++      { "ibm,close-errinjct", -1, -1, -1, -1, -1 },
++      { "ibm,open-errinct", -1, -1, -1, -1, -1 },
++      { "ibm,get-config-addr-info2", -1, -1, -1, -1, -1 },
++      { "ibm,get-dynamic-sensor-state", -1, 1, -1, -1, -1 },
++      { "ibm,get-indices", -1, 2, 3, -1, -1 },
++      { "get-power-level", -1, -1, -1, -1, -1 },
++      { "get-sensor-state", -1, -1, -1, -1, -1 },
++      { "ibm,get-system-parameter", -1, 1, 2, -1, -1 },
++      { "get-time-of-day", -1, -1, -1, -1, -1 },
++      { "ibm,get-vpd", -1, 0, -1, 1, 2 },
++      { "ibm,lpar-perftools", -1, 2, 3, -1, -1 },
++      { "ibm,platform-dump", -1, 4, 5, -1, -1 },
++      { "ibm,read-slot-reset-state", -1, -1, -1, -1, -1 },
++      { "ibm,scan-log-dump", -1, 0, 1, -1, -1 },
++      { "ibm,set-dynamic-indicator", -1, 2, -1, -1, -1 },
++      { "ibm,set-eeh-option", -1, -1, -1, -1, -1 },
++      { "set-indicator", -1, -1, -1, -1, -1 },
++      { "set-power-level", -1, -1, -1, -1, -1 },
++      { "set-time-for-power-on", -1, -1, -1, -1, -1 },
++      { "ibm,set-system-parameter", -1, 1, -1, -1, -1 },
++      { "set-time-of-day", -1, -1, -1, -1, -1 },
++      { "ibm,suspend-me", -1, -1, -1, -1, -1 },
++      { "ibm,update-nodes", -1, 0, -1, -1, -1, 4096 },
++      { "ibm,update-properties", -1, 0, -1, -1, -1, 4096 },
++      { "ibm,physical-attestation", -1, 0, 1, -1, -1 },
++};
++
++static bool in_rmo_buf(u32 base, u32 end)
++{
++      return base >= rtas_rmo_buf &&
++              base < (rtas_rmo_buf + RTAS_RMOBUF_MAX) &&
++              base <= end &&
++              end >= rtas_rmo_buf &&
++              end < (rtas_rmo_buf + RTAS_RMOBUF_MAX);
++}
++
++static bool block_rtas_call(int token, int nargs,
++                          struct rtas_args *args)
++{
++      int i;
++
++      for (i = 0; i < ARRAY_SIZE(rtas_filters); i++) {
++              struct rtas_filter *f = &rtas_filters[i];
++              u32 base, size, end;
++
++              if (token != f->token)
++                      continue;
++
++              if (f->buf_idx1 != -1) {
++                      base = be32_to_cpu(args->args[f->buf_idx1]);
++                      if (f->size_idx1 != -1)
++                              size = be32_to_cpu(args->args[f->size_idx1]);
++                      else if (f->fixed_size)
++                              size = f->fixed_size;
++                      else
++                              size = 1;
++
++                      end = base + size - 1;
++                      if (!in_rmo_buf(base, end))
++                              goto err;
++              }
++
++              if (f->buf_idx2 != -1) {
++                      base = be32_to_cpu(args->args[f->buf_idx2]);
++                      if (f->size_idx2 != -1)
++                              size = be32_to_cpu(args->args[f->size_idx2]);
++                      else if (f->fixed_size)
++                              size = f->fixed_size;
++                      else
++                              size = 1;
++                      end = base + size - 1;
++
++                      /*
++                       * Special case for ibm,configure-connector where the
++                       * address can be 0
++                       */
++                      if (!strcmp(f->name, "ibm,configure-connector") &&
++                          base == 0)
++                              return false;
++
++                      if (!in_rmo_buf(base, end))
++                              goto err;
++              }
++
++              return false;
++      }
++
++err:
++      pr_err_ratelimited("sys_rtas: RTAS call blocked - exploit attempt?\n");
++      pr_err_ratelimited("sys_rtas: token=0x%x, nargs=%d (called by %s)\n",
++                         token, nargs, current->comm);
++      return true;
++}
++
++#else
++
++static bool block_rtas_call(int token, int nargs,
++                          struct rtas_args *args)
++{
++      return false;
++}
++
++#endif /* CONFIG_PPC_RTAS_FILTER */
++
+ /* We assume to be passed big endian arguments */
+ SYSCALL_DEFINE1(rtas, struct rtas_args __user *, uargs)
+ {
+@@ -977,6 +1118,9 @@ SYSCALL_DEFINE1(rtas, struct rtas_args _
+       args.rets = &args.args[nargs];
+       memset(args.rets, 0, nret * sizeof(rtas_arg_t));
++      if (block_rtas_call(token, nargs, &args))
++              return -EINVAL;
++
+       /* Need to handle ibm,suspend_me call specially */
+       if (token == ibm_suspend_me_token) {
+@@ -1038,6 +1182,9 @@ void __init rtas_initialize(void)
+       unsigned long rtas_region = RTAS_INSTANTIATE_MAX;
+       u32 base, size, entry;
+       int no_base, no_size, no_entry;
++#ifdef CONFIG_PPC_RTAS_FILTER
++      int i;
++#endif
+       /* Get RTAS dev node and fill up our "rtas" structure with infos
+        * about it.
+@@ -1077,6 +1224,12 @@ void __init rtas_initialize(void)
+ #ifdef CONFIG_RTAS_ERROR_LOGGING
+       rtas_last_error_token = rtas_token("rtas-last-error");
+ #endif
++
++#ifdef CONFIG_PPC_RTAS_FILTER
++      for (i = 0; i < ARRAY_SIZE(rtas_filters); i++) {
++              rtas_filters[i].token = rtas_token(rtas_filters[i].name);
++      }
++#endif
+ }
+ int __init early_init_dt_scan_rtas(unsigned long node,
diff --git a/queue-5.4/powerpc-warn-about-use-of-smt_snooze_delay.patch b/queue-5.4/powerpc-warn-about-use-of-smt_snooze_delay.patch
new file mode 100644 (file)
index 0000000..8412c5a
--- /dev/null
@@ -0,0 +1,104 @@
+From a02f6d42357acf6e5de6ffc728e6e77faf3ad217 Mon Sep 17 00:00:00 2001
+From: Joel Stanley <joel@jms.id.au>
+Date: Wed, 2 Sep 2020 09:30:11 +0930
+Subject: powerpc: Warn about use of smt_snooze_delay
+
+From: Joel Stanley <joel@jms.id.au>
+
+commit a02f6d42357acf6e5de6ffc728e6e77faf3ad217 upstream.
+
+It's not done anything for a long time. Save the percpu variable, and
+emit a warning to remind users to not expect it to do anything.
+
+This uses pr_warn_once instead of pr_warn_ratelimit as testing
+'ppc64_cpu --smt=off' on a 24 core / 4 SMT system showed the warning
+to be noisy, as the online/offline loop is slow.
+
+Fixes: 3fa8cad82b94 ("powerpc/pseries/cpuidle: smt-snooze-delay cleanup.")
+Cc: stable@vger.kernel.org # v3.14
+Signed-off-by: Joel Stanley <joel@jms.id.au>
+Acked-by: Gautham R. Shenoy <ego@linux.vnet.ibm.com>
+Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
+Link: https://lore.kernel.org/r/20200902000012.3440389-1-joel@jms.id.au
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/powerpc/kernel/sysfs.c |   42 +++++++++++++++++-------------------------
+ 1 file changed, 17 insertions(+), 25 deletions(-)
+
+--- a/arch/powerpc/kernel/sysfs.c
++++ b/arch/powerpc/kernel/sysfs.c
+@@ -31,29 +31,27 @@
+ static DEFINE_PER_CPU(struct cpu, cpu_devices);
+-/*
+- * SMT snooze delay stuff, 64-bit only for now
+- */
+-
+ #ifdef CONFIG_PPC64
+-/* Time in microseconds we delay before sleeping in the idle loop */
+-static DEFINE_PER_CPU(long, smt_snooze_delay) = { 100 };
++/*
++ * Snooze delay has not been hooked up since 3fa8cad82b94 ("powerpc/pseries/cpuidle:
++ * smt-snooze-delay cleanup.") and has been broken even longer. As was foretold in
++ * 2014:
++ *
++ *  "ppc64_util currently utilises it. Once we fix ppc64_util, propose to clean
++ *  up the kernel code."
++ *
++ * powerpc-utils stopped using it as of 1.3.8. At some point in the future this
++ * code should be removed.
++ */
+ static ssize_t store_smt_snooze_delay(struct device *dev,
+                                     struct device_attribute *attr,
+                                     const char *buf,
+                                     size_t count)
+ {
+-      struct cpu *cpu = container_of(dev, struct cpu, dev);
+-      ssize_t ret;
+-      long snooze;
+-
+-      ret = sscanf(buf, "%ld", &snooze);
+-      if (ret != 1)
+-              return -EINVAL;
+-
+-      per_cpu(smt_snooze_delay, cpu->dev.id) = snooze;
++      pr_warn_once("%s (%d) stored to unsupported smt_snooze_delay, which has no effect.\n",
++                   current->comm, current->pid);
+       return count;
+ }
+@@ -61,9 +59,9 @@ static ssize_t show_smt_snooze_delay(str
+                                    struct device_attribute *attr,
+                                    char *buf)
+ {
+-      struct cpu *cpu = container_of(dev, struct cpu, dev);
+-
+-      return sprintf(buf, "%ld\n", per_cpu(smt_snooze_delay, cpu->dev.id));
++      pr_warn_once("%s (%d) read from unsupported smt_snooze_delay\n",
++                   current->comm, current->pid);
++      return sprintf(buf, "100\n");
+ }
+ static DEVICE_ATTR(smt_snooze_delay, 0644, show_smt_snooze_delay,
+@@ -71,16 +69,10 @@ static DEVICE_ATTR(smt_snooze_delay, 064
+ static int __init setup_smt_snooze_delay(char *str)
+ {
+-      unsigned int cpu;
+-      long snooze;
+-
+       if (!cpu_has_feature(CPU_FTR_SMT))
+               return 1;
+-      snooze = simple_strtol(str, NULL, 10);
+-      for_each_possible_cpu(cpu)
+-              per_cpu(smt_snooze_delay, cpu) = snooze;
+-
++      pr_warn("smt-snooze-delay command line option has no effect\n");
+       return 1;
+ }
+ __setup("smt-snooze-delay=", setup_smt_snooze_delay);
diff --git a/queue-5.4/s390-stp-add-locking-to-sysfs-functions.patch b/queue-5.4/s390-stp-add-locking-to-sysfs-functions.patch
new file mode 100644 (file)
index 0000000..1b6c60a
--- /dev/null
@@ -0,0 +1,236 @@
+From b3bd02495cb339124f13135d51940cf48d83e5cb Mon Sep 17 00:00:00 2001
+From: Sven Schnelle <svens@linux.ibm.com>
+Date: Tue, 15 Sep 2020 08:53:50 +0200
+Subject: s390/stp: add locking to sysfs functions
+
+From: Sven Schnelle <svens@linux.ibm.com>
+
+commit b3bd02495cb339124f13135d51940cf48d83e5cb upstream.
+
+The sysfs function might race with stp_work_fn. To prevent that,
+add the required locking. Another issue is that the sysfs functions
+are checking the stp_online flag, but this flag just holds the user
+setting whether STP is enabled. Add a flag to clock_sync_flag whether
+stp_info holds valid data and use that instead.
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Sven Schnelle <svens@linux.ibm.com>
+Reviewed-by: Alexander Egorenkov <egorenar@linux.ibm.com>
+Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/s390/kernel/time.c |  118 ++++++++++++++++++++++++++++++++++--------------
+ 1 file changed, 85 insertions(+), 33 deletions(-)
+
+--- a/arch/s390/kernel/time.c
++++ b/arch/s390/kernel/time.c
+@@ -354,8 +354,9 @@ static DEFINE_PER_CPU(atomic_t, clock_sy
+ static DEFINE_MUTEX(clock_sync_mutex);
+ static unsigned long clock_sync_flags;
+-#define CLOCK_SYNC_HAS_STP    0
+-#define CLOCK_SYNC_STP                1
++#define CLOCK_SYNC_HAS_STP            0
++#define CLOCK_SYNC_STP                        1
++#define CLOCK_SYNC_STPINFO_VALID      2
+ /*
+  * The get_clock function for the physical clock. It will get the current
+@@ -592,6 +593,22 @@ void stp_queue_work(void)
+       queue_work(time_sync_wq, &stp_work);
+ }
++static int __store_stpinfo(void)
++{
++      int rc = chsc_sstpi(stp_page, &stp_info, sizeof(struct stp_sstpi));
++
++      if (rc)
++              clear_bit(CLOCK_SYNC_STPINFO_VALID, &clock_sync_flags);
++      else
++              set_bit(CLOCK_SYNC_STPINFO_VALID, &clock_sync_flags);
++      return rc;
++}
++
++static int stpinfo_valid(void)
++{
++      return stp_online && test_bit(CLOCK_SYNC_STPINFO_VALID, &clock_sync_flags);
++}
++
+ static int stp_sync_clock(void *data)
+ {
+       struct clock_sync_data *sync = data;
+@@ -613,8 +630,7 @@ static int stp_sync_clock(void *data)
+                       if (rc == 0) {
+                               sync->clock_delta = clock_delta;
+                               clock_sync_global(clock_delta);
+-                              rc = chsc_sstpi(stp_page, &stp_info,
+-                                              sizeof(struct stp_sstpi));
++                              rc = __store_stpinfo();
+                               if (rc == 0 && stp_info.tmd != 2)
+                                       rc = -EAGAIN;
+                       }
+@@ -659,7 +675,7 @@ static void stp_work_fn(struct work_stru
+       if (rc)
+               goto out_unlock;
+-      rc = chsc_sstpi(stp_page, &stp_info, sizeof(struct stp_sstpi));
++      rc = __store_stpinfo();
+       if (rc || stp_info.c == 0)
+               goto out_unlock;
+@@ -696,10 +712,14 @@ static ssize_t stp_ctn_id_show(struct de
+                               struct device_attribute *attr,
+                               char *buf)
+ {
+-      if (!stp_online)
+-              return -ENODATA;
+-      return sprintf(buf, "%016llx\n",
+-                     *(unsigned long long *) stp_info.ctnid);
++      ssize_t ret = -ENODATA;
++
++      mutex_lock(&stp_work_mutex);
++      if (stpinfo_valid())
++              ret = sprintf(buf, "%016llx\n",
++                            *(unsigned long long *) stp_info.ctnid);
++      mutex_unlock(&stp_work_mutex);
++      return ret;
+ }
+ static DEVICE_ATTR(ctn_id, 0400, stp_ctn_id_show, NULL);
+@@ -708,9 +728,13 @@ static ssize_t stp_ctn_type_show(struct
+                               struct device_attribute *attr,
+                               char *buf)
+ {
+-      if (!stp_online)
+-              return -ENODATA;
+-      return sprintf(buf, "%i\n", stp_info.ctn);
++      ssize_t ret = -ENODATA;
++
++      mutex_lock(&stp_work_mutex);
++      if (stpinfo_valid())
++              ret = sprintf(buf, "%i\n", stp_info.ctn);
++      mutex_unlock(&stp_work_mutex);
++      return ret;
+ }
+ static DEVICE_ATTR(ctn_type, 0400, stp_ctn_type_show, NULL);
+@@ -719,9 +743,13 @@ static ssize_t stp_dst_offset_show(struc
+                                  struct device_attribute *attr,
+                                  char *buf)
+ {
+-      if (!stp_online || !(stp_info.vbits & 0x2000))
+-              return -ENODATA;
+-      return sprintf(buf, "%i\n", (int)(s16) stp_info.dsto);
++      ssize_t ret = -ENODATA;
++
++      mutex_lock(&stp_work_mutex);
++      if (stpinfo_valid() && (stp_info.vbits & 0x2000))
++              ret = sprintf(buf, "%i\n", (int)(s16) stp_info.dsto);
++      mutex_unlock(&stp_work_mutex);
++      return ret;
+ }
+ static DEVICE_ATTR(dst_offset, 0400, stp_dst_offset_show, NULL);
+@@ -730,9 +758,13 @@ static ssize_t stp_leap_seconds_show(str
+                                       struct device_attribute *attr,
+                                       char *buf)
+ {
+-      if (!stp_online || !(stp_info.vbits & 0x8000))
+-              return -ENODATA;
+-      return sprintf(buf, "%i\n", (int)(s16) stp_info.leaps);
++      ssize_t ret = -ENODATA;
++
++      mutex_lock(&stp_work_mutex);
++      if (stpinfo_valid() && (stp_info.vbits & 0x8000))
++              ret = sprintf(buf, "%i\n", (int)(s16) stp_info.leaps);
++      mutex_unlock(&stp_work_mutex);
++      return ret;
+ }
+ static DEVICE_ATTR(leap_seconds, 0400, stp_leap_seconds_show, NULL);
+@@ -741,9 +773,13 @@ static ssize_t stp_stratum_show(struct d
+                               struct device_attribute *attr,
+                               char *buf)
+ {
+-      if (!stp_online)
+-              return -ENODATA;
+-      return sprintf(buf, "%i\n", (int)(s16) stp_info.stratum);
++      ssize_t ret = -ENODATA;
++
++      mutex_lock(&stp_work_mutex);
++      if (stpinfo_valid())
++              ret = sprintf(buf, "%i\n", (int)(s16) stp_info.stratum);
++      mutex_unlock(&stp_work_mutex);
++      return ret;
+ }
+ static DEVICE_ATTR(stratum, 0400, stp_stratum_show, NULL);
+@@ -752,9 +788,13 @@ static ssize_t stp_time_offset_show(stru
+                               struct device_attribute *attr,
+                               char *buf)
+ {
+-      if (!stp_online || !(stp_info.vbits & 0x0800))
+-              return -ENODATA;
+-      return sprintf(buf, "%i\n", (int) stp_info.tto);
++      ssize_t ret = -ENODATA;
++
++      mutex_lock(&stp_work_mutex);
++      if (stpinfo_valid() && (stp_info.vbits & 0x0800))
++              ret = sprintf(buf, "%i\n", (int) stp_info.tto);
++      mutex_unlock(&stp_work_mutex);
++      return ret;
+ }
+ static DEVICE_ATTR(time_offset, 0400, stp_time_offset_show, NULL);
+@@ -763,9 +803,13 @@ static ssize_t stp_time_zone_offset_show
+                               struct device_attribute *attr,
+                               char *buf)
+ {
+-      if (!stp_online || !(stp_info.vbits & 0x4000))
+-              return -ENODATA;
+-      return sprintf(buf, "%i\n", (int)(s16) stp_info.tzo);
++      ssize_t ret = -ENODATA;
++
++      mutex_lock(&stp_work_mutex);
++      if (stpinfo_valid() && (stp_info.vbits & 0x4000))
++              ret = sprintf(buf, "%i\n", (int)(s16) stp_info.tzo);
++      mutex_unlock(&stp_work_mutex);
++      return ret;
+ }
+ static DEVICE_ATTR(time_zone_offset, 0400,
+@@ -775,9 +819,13 @@ static ssize_t stp_timing_mode_show(stru
+                               struct device_attribute *attr,
+                               char *buf)
+ {
+-      if (!stp_online)
+-              return -ENODATA;
+-      return sprintf(buf, "%i\n", stp_info.tmd);
++      ssize_t ret = -ENODATA;
++
++      mutex_lock(&stp_work_mutex);
++      if (stpinfo_valid())
++              ret = sprintf(buf, "%i\n", stp_info.tmd);
++      mutex_unlock(&stp_work_mutex);
++      return ret;
+ }
+ static DEVICE_ATTR(timing_mode, 0400, stp_timing_mode_show, NULL);
+@@ -786,9 +834,13 @@ static ssize_t stp_timing_state_show(str
+                               struct device_attribute *attr,
+                               char *buf)
+ {
+-      if (!stp_online)
+-              return -ENODATA;
+-      return sprintf(buf, "%i\n", stp_info.tst);
++      ssize_t ret = -ENODATA;
++
++      mutex_lock(&stp_work_mutex);
++      if (stpinfo_valid())
++              ret = sprintf(buf, "%i\n", stp_info.tst);
++      mutex_unlock(&stp_work_mutex);
++      return ret;
+ }
+ static DEVICE_ATTR(timing_state, 0400, stp_timing_state_show, NULL);
diff --git a/queue-5.4/scsi-mptfusion-fix-null-pointer-dereferences-in-mptscsih_remove.patch b/queue-5.4/scsi-mptfusion-fix-null-pointer-dereferences-in-mptscsih_remove.patch
new file mode 100644 (file)
index 0000000..f0fdcdb
--- /dev/null
@@ -0,0 +1,77 @@
+From 2f4843b172c2c0360ee7792ad98025fae7baefde Mon Sep 17 00:00:00 2001
+From: Helge Deller <deller@gmx.de>
+Date: Thu, 22 Oct 2020 11:00:05 +0200
+Subject: scsi: mptfusion: Fix null pointer dereferences in mptscsih_remove()
+
+From: Helge Deller <deller@gmx.de>
+
+commit 2f4843b172c2c0360ee7792ad98025fae7baefde upstream.
+
+The mptscsih_remove() function triggers a kernel oops if the Scsi_Host
+pointer (ioc->sh) is NULL, as can be seen in this syslog:
+
+ ioc0: LSI53C1030 B2: Capabilities={Initiator,Target}
+ Begin: Waiting for root file system ...
+ scsi host2: error handler thread failed to spawn, error = -4
+ mptspi: ioc0: WARNING - Unable to register controller with SCSI subsystem
+ Backtrace:
+  [<000000001045b7cc>] mptspi_probe+0x248/0x3d0 [mptspi]
+  [<0000000040946470>] pci_device_probe+0x1ac/0x2d8
+  [<0000000040add668>] really_probe+0x1bc/0x988
+  [<0000000040ade704>] driver_probe_device+0x160/0x218
+  [<0000000040adee24>] device_driver_attach+0x160/0x188
+  [<0000000040adef90>] __driver_attach+0x144/0x320
+  [<0000000040ad7c78>] bus_for_each_dev+0xd4/0x158
+  [<0000000040adc138>] driver_attach+0x4c/0x80
+  [<0000000040adb3ec>] bus_add_driver+0x3e0/0x498
+  [<0000000040ae0130>] driver_register+0xf4/0x298
+  [<00000000409450c4>] __pci_register_driver+0x78/0xa8
+  [<000000000007d248>] mptspi_init+0x18c/0x1c4 [mptspi]
+
+This patch adds the necessary NULL-pointer checks.  Successfully tested on
+a HP C8000 parisc workstation with buggy SCSI drives.
+
+Link: https://lore.kernel.org/r/20201022090005.GA9000@ls3530.fritz.box
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Helge Deller <deller@gmx.de>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/message/fusion/mptscsih.c |   13 ++++++++-----
+ 1 file changed, 8 insertions(+), 5 deletions(-)
+
+--- a/drivers/message/fusion/mptscsih.c
++++ b/drivers/message/fusion/mptscsih.c
+@@ -1176,8 +1176,10 @@ mptscsih_remove(struct pci_dev *pdev)
+       MPT_SCSI_HOST           *hd;
+       int sz1;
+-      if((hd = shost_priv(host)) == NULL)
+-              return;
++      if (host == NULL)
++              hd = NULL;
++      else
++              hd = shost_priv(host);
+       mptscsih_shutdown(pdev);
+@@ -1193,14 +1195,15 @@ mptscsih_remove(struct pci_dev *pdev)
+           "Free'd ScsiLookup (%d) memory\n",
+           ioc->name, sz1));
+-      kfree(hd->info_kbuf);
++      if (hd)
++              kfree(hd->info_kbuf);
+       /* NULL the Scsi_Host pointer
+        */
+       ioc->sh = NULL;
+-      scsi_host_put(host);
+-
++      if (host)
++              scsi_host_put(host);
+       mpt_detach(pdev);
+ }
diff --git a/queue-5.4/scsi-qla2xxx-fix-crash-on-session-cleanup-with-unload.patch b/queue-5.4/scsi-qla2xxx-fix-crash-on-session-cleanup-with-unload.patch
new file mode 100644 (file)
index 0000000..de61bfb
--- /dev/null
@@ -0,0 +1,49 @@
+From 50457dab670f396557e60c07f086358460876353 Mon Sep 17 00:00:00 2001
+From: Quinn Tran <qutran@marvell.com>
+Date: Tue, 29 Sep 2020 03:21:50 -0700
+Subject: scsi: qla2xxx: Fix crash on session cleanup with unload
+
+From: Quinn Tran <qutran@marvell.com>
+
+commit 50457dab670f396557e60c07f086358460876353 upstream.
+
+On unload, session cleanup prematurely gave the signal for driver unload
+path to advance.
+
+Link: https://lore.kernel.org/r/20200929102152.32278-6-njavali@marvell.com
+Fixes: 726b85487067 ("qla2xxx: Add framework for async fabric discovery")
+Cc: stable@vger.kernel.org
+Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com>
+Signed-off-by: Quinn Tran <qutran@marvell.com>
+Signed-off-by: Nilesh Javali <njavali@marvell.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/scsi/qla2xxx/qla_target.c |   13 +++++++------
+ 1 file changed, 7 insertions(+), 6 deletions(-)
+
+--- a/drivers/scsi/qla2xxx/qla_target.c
++++ b/drivers/scsi/qla2xxx/qla_target.c
+@@ -1230,14 +1230,15 @@ void qlt_schedule_sess_for_deletion(stru
+       case DSC_DELETE_PEND:
+               return;
+       case DSC_DELETED:
+-              if (tgt && tgt->tgt_stop && (tgt->sess_count == 0))
+-                      wake_up_all(&tgt->waitQ);
+-              if (sess->vha->fcport_count == 0)
+-                      wake_up_all(&sess->vha->fcport_waitQ);
+-
+               if (!sess->plogi_link[QLT_PLOGI_LINK_SAME_WWN] &&
+-                      !sess->plogi_link[QLT_PLOGI_LINK_CONFLICT])
++                      !sess->plogi_link[QLT_PLOGI_LINK_CONFLICT]) {
++                      if (tgt && tgt->tgt_stop && tgt->sess_count == 0)
++                              wake_up_all(&tgt->waitQ);
++
++                      if (sess->vha->fcport_count == 0)
++                              wake_up_all(&sess->vha->fcport_waitQ);
+                       return;
++              }
+               break;
+       case DSC_UPD_FCPORT:
+               /*
index b691b8f40cf5e2a8d4c81456366f0fb5122c6ac7..a367994ae0b34f72627833d06ebd1731bddefdbb 100644 (file)
@@ -102,3 +102,71 @@ perf-x86-intel-fix-ice-lake-event-constraint-table.patch
 perf-x86-amd-ibs-don-t-include-randomized-bits-in-get_ibs_op_count.patch
 perf-x86-amd-ibs-fix-raw-sample-data-accumulation.patch
 spi-sprd-release-dma-channel-also-on-probe-deferral.patch
+extcon-ptn5150-fix-usage-of-atomic-gpio-with-sleeping-gpio-chips.patch
+leds-bcm6328-bcm6358-use-devres-led-registering-function.patch
+media-uvcvideo-fix-uvc_ctrl_fixup_xu_info-not-having-any-effect.patch
+fs-don-t-invalidate-page-buffers-in-block_write_full_page.patch
+nfs-fix-nfs_path-in-case-of-a-rename-retry.patch
+acpi-button-fix-handling-lid-state-changes-when-input-device-closed.patch
+acpi-extlog-check-for-rdmsr-failure.patch
+acpi-video-use-acpi-backlight-for-hp-635-notebook.patch
+acpi-debug-don-t-allow-debugging-when-acpi-is-disabled.patch
+pci-acpi-whitelist-hotplug-ports-for-d3-if-power-managed-by-acpi.patch
+acpi-ec-pm-flush-ec-work-unconditionally-after-wakeup.patch
+acpi-ec-pm-drop-ec_no_wakeup-check-from-acpi_ec_dispatch_gpe.patch
+acpi-cpufreq-honor-_psd-table-setting-on-new-amd-cpus.patch
+w1-mxc_w1-fix-timeout-resolution-problem-leading-to-bus-error.patch
+scsi-mptfusion-fix-null-pointer-dereferences-in-mptscsih_remove.patch
+scsi-qla2xxx-fix-crash-on-session-cleanup-with-unload.patch
+pm-runtime-remove-link-state-checks-in-rpm_get-put_supplier.patch
+btrfs-qgroup-fix-wrong-qgroup-metadata-reserve-for-delayed-inode.patch
+btrfs-improve-device-scanning-messages.patch
+btrfs-reschedule-if-necessary-when-logging-directory-items.patch
+btrfs-send-orphanize-first-all-conflicting-inodes-when-processing-references.patch
+btrfs-send-recompute-reference-path-after-orphanization-of-a-directory.patch
+btrfs-use-kvzalloc-to-allocate-clone_roots-in-btrfs_ioctl_send.patch
+btrfs-tree-checker-fix-false-alert-caused-by-legacy-btrfs-root-item.patch
+btrfs-cleanup-cow-block-on-error.patch
+btrfs-tree-checker-validate-number-of-chunk-stripes-and-parity.patch
+btrfs-fix-use-after-free-on-readahead-extent-after-failure-to-create-it.patch
+btrfs-fix-readahead-hang-and-use-after-free-after-removing-a-device.patch
+usb-xhci-workaround-for-s3-issue-on-amd-snps-3.0-xhc.patch
+usb-dwc3-pci-allow-elkhart-lake-to-utilize-dsm-method-for-pm-functionality.patch
+usb-dwc3-ep0-fix-zlp-for-out-ep0-requests.patch
+usb-dwc3-gadget-check-mps-of-the-request-length.patch
+usb-dwc3-core-add-phy-cleanup-for-probe-error-handling.patch
+usb-dwc3-core-don-t-trigger-runtime-pm-when-remove-driver.patch
+usb-dwc3-gadget-resume-pending-requests-after-clear_stall.patch
+usb-dwc3-gadget-end_transfer-before-clear_stall-command.patch
+usb-cdc-acm-fix-cooldown-mechanism.patch
+usb-typec-tcpm-reset-hard_reset_count-for-any-disconnect.patch
+usb-host-fsl-mph-dr-of-check-return-of-dma_set_mask.patch
+drm-i915-force-vt-d-workarounds-when-running-as-a-guest-os.patch
+vt-keyboard-simplify-vt_kdgkbsent.patch
+vt-keyboard-extend-func_buf_lock-to-readers.patch
+hid-wacom-avoid-entering-wacom_wac_pen_report-for-pad-battery.patch
+udf-fix-memory-leak-when-mounting.patch
+dmaengine-dma-jz4780-fix-race-in-jz4780_dma_tx_status.patch
+iio-light-si1145-fix-timestamp-alignment-and-prevent-data-leak.patch
+iio-adc-gyroadc-fix-leak-of-device-node-iterator.patch
+iio-adc-ti-adc0832-fix-alignment-issue-with-timestamp.patch
+iio-adc-ti-adc12138-fix-alignment-issue-with-timestamp.patch
+iio-gyro-itg3200-fix-timestamp-alignment-and-prevent-data-leak.patch
+powerpc-drmem-make-lmb_size-64-bit.patch
+mips-dec-restore-bootmem-reservation-for-firmware-working-memory-area.patch
+s390-stp-add-locking-to-sysfs-functions.patch
+powerpc-rtas-restrict-rtas-requests-from-userspace.patch
+powerpc-warn-about-use-of-smt_snooze_delay.patch
+powerpc-memhotplug-make-lmb-size-64bit.patch
+powerpc-powernv-elog-fix-race-while-processing-opal-error-log-event.patch
+powerpc-powermac-fix-low_sleep_handler-with-kuap-and-kuep.patch
+powerpc-fix-undetected-data-corruption-with-p9n-dd2.1-vsx-ci-load-emulation.patch
+nfsv4-wait-for-stateid-updates-after-close-open_downgrade.patch
+nfsv4.2-support-exchgid4_flag_supp_fence_ops-4.2-exchange_id-flag.patch
+nfsd-add-missing-nfsv2-.pc_func-methods.patch
+ubifs-dent-fix-some-potential-memory-leaks-while-iterating-entries.patch
+ubifs-xattr-fix-some-potential-memory-leaks-while-iterating-entries.patch
+ubifs-journal-make-sure-to-not-dirty-twice-for-auth-nodes.patch
+ubifs-fix-a-memleak-after-dumping-authentication-mount-options.patch
+ubifs-don-t-parse-authentication-mount-options-in-remount-process.patch
+ubifs-mount_ubifs-release-authentication-resource-in-error-handling-path.patch
diff --git a/queue-5.4/ubifs-dent-fix-some-potential-memory-leaks-while-iterating-entries.patch b/queue-5.4/ubifs-dent-fix-some-potential-memory-leaks-while-iterating-entries.patch
new file mode 100644 (file)
index 0000000..a9ba8ff
--- /dev/null
@@ -0,0 +1,33 @@
+From 58f6e78a65f1fcbf732f60a7478ccc99873ff3ba Mon Sep 17 00:00:00 2001
+From: Zhihao Cheng <chengzhihao1@huawei.com>
+Date: Mon, 1 Jun 2020 17:10:37 +0800
+Subject: ubifs: dent: Fix some potential memory leaks while iterating entries
+
+From: Zhihao Cheng <chengzhihao1@huawei.com>
+
+commit 58f6e78a65f1fcbf732f60a7478ccc99873ff3ba upstream.
+
+Fix some potential memory leaks in error handling branches while
+iterating dent entries. For example, function dbg_check_dir()
+forgets to free pdent if it exists.
+
+Signed-off-by: Zhihao Cheng <chengzhihao1@huawei.com>
+Cc: <stable@vger.kernel.org>
+Fixes: 1e51764a3c2ac05a2 ("UBIFS: add new flash file system")
+Signed-off-by: Richard Weinberger <richard@nod.at>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/ubifs/debug.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/fs/ubifs/debug.c
++++ b/fs/ubifs/debug.c
+@@ -1123,6 +1123,7 @@ int dbg_check_dir(struct ubifs_info *c,
+                       err = PTR_ERR(dent);
+                       if (err == -ENOENT)
+                               break;
++                      kfree(pdent);
+                       return err;
+               }
diff --git a/queue-5.4/ubifs-don-t-parse-authentication-mount-options-in-remount-process.patch b/queue-5.4/ubifs-don-t-parse-authentication-mount-options-in-remount-process.patch
new file mode 100644 (file)
index 0000000..2b2064c
--- /dev/null
@@ -0,0 +1,55 @@
+From bb674a4d4de1032837fcbf860a63939e66f0b7ad Mon Sep 17 00:00:00 2001
+From: Zhihao Cheng <chengzhihao1@huawei.com>
+Date: Tue, 29 Sep 2020 20:45:30 +0800
+Subject: ubifs: Don't parse authentication mount options in remount process
+
+From: Zhihao Cheng <chengzhihao1@huawei.com>
+
+commit bb674a4d4de1032837fcbf860a63939e66f0b7ad upstream.
+
+There is no need to dump authentication options while remounting,
+because authentication initialization can only be doing once in
+the first mount process. Dumping authentication mount options in
+remount process may cause memory leak if UBIFS has already been
+mounted with old authentication mount options.
+
+Signed-off-by: Zhihao Cheng <chengzhihao1@huawei.com>
+Cc: <stable@vger.kernel.org>  # 4.20+
+Fixes: d8a22773a12c6d7 ("ubifs: Enable authentication support")
+Reviewed-by: Sascha Hauer <s.hauer@pengutronix.de>
+Signed-off-by: Richard Weinberger <richard@nod.at>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/ubifs/super.c |   18 ++++++++++++------
+ 1 file changed, 12 insertions(+), 6 deletions(-)
+
+--- a/fs/ubifs/super.c
++++ b/fs/ubifs/super.c
+@@ -1092,14 +1092,20 @@ static int ubifs_parse_options(struct ub
+                       break;
+               }
+               case Opt_auth_key:
+-                      c->auth_key_name = kstrdup(args[0].from, GFP_KERNEL);
+-                      if (!c->auth_key_name)
+-                              return -ENOMEM;
++                      if (!is_remount) {
++                              c->auth_key_name = kstrdup(args[0].from,
++                                                              GFP_KERNEL);
++                              if (!c->auth_key_name)
++                                      return -ENOMEM;
++                      }
+                       break;
+               case Opt_auth_hash_name:
+-                      c->auth_hash_name = kstrdup(args[0].from, GFP_KERNEL);
+-                      if (!c->auth_hash_name)
+-                              return -ENOMEM;
++                      if (!is_remount) {
++                              c->auth_hash_name = kstrdup(args[0].from,
++                                                              GFP_KERNEL);
++                              if (!c->auth_hash_name)
++                                      return -ENOMEM;
++                      }
+                       break;
+               case Opt_ignore:
+                       break;
diff --git a/queue-5.4/ubifs-fix-a-memleak-after-dumping-authentication-mount-options.patch b/queue-5.4/ubifs-fix-a-memleak-after-dumping-authentication-mount-options.patch
new file mode 100644 (file)
index 0000000..9a20ab4
--- /dev/null
@@ -0,0 +1,62 @@
+From 47f6d9ce45b03a40c34b668a9884754c58122b39 Mon Sep 17 00:00:00 2001
+From: Zhihao Cheng <chengzhihao1@huawei.com>
+Date: Tue, 29 Sep 2020 20:45:29 +0800
+Subject: ubifs: Fix a memleak after dumping authentication mount options
+
+From: Zhihao Cheng <chengzhihao1@huawei.com>
+
+commit 47f6d9ce45b03a40c34b668a9884754c58122b39 upstream.
+
+Fix a memory leak after dumping authentication mount options in error
+handling branch.
+
+Signed-off-by: Zhihao Cheng <chengzhihao1@huawei.com>
+Cc: <stable@vger.kernel.org>  # 4.20+
+Fixes: d8a22773a12c6d7 ("ubifs: Enable authentication support")
+Reviewed-by: Sascha Hauer <s.hauer@pengutronix.de>
+Signed-off-by: Richard Weinberger <richard@nod.at>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/ubifs/super.c |   16 ++++++++++++++--
+ 1 file changed, 14 insertions(+), 2 deletions(-)
+
+--- a/fs/ubifs/super.c
++++ b/fs/ubifs/super.c
+@@ -1123,6 +1123,18 @@ static int ubifs_parse_options(struct ub
+       return 0;
+ }
++/*
++ * ubifs_release_options - release mount parameters which have been dumped.
++ * @c: UBIFS file-system description object
++ */
++static void ubifs_release_options(struct ubifs_info *c)
++{
++      kfree(c->auth_key_name);
++      c->auth_key_name = NULL;
++      kfree(c->auth_hash_name);
++      c->auth_hash_name = NULL;
++}
++
+ /**
+  * destroy_journal - destroy journal data structures.
+  * @c: UBIFS file-system description object
+@@ -1632,8 +1644,7 @@ static void ubifs_umount(struct ubifs_in
+       ubifs_lpt_free(c, 0);
+       ubifs_exit_authentication(c);
+-      kfree(c->auth_key_name);
+-      kfree(c->auth_hash_name);
++      ubifs_release_options(c);
+       kfree(c->cbuf);
+       kfree(c->rcvrd_mst_node);
+       kfree(c->mst_node);
+@@ -2201,6 +2212,7 @@ out_umount:
+ out_unlock:
+       mutex_unlock(&c->umount_mutex);
+ out_close:
++      ubifs_release_options(c);
+       ubi_close_volume(c->ubi);
+ out:
+       return err;
diff --git a/queue-5.4/ubifs-journal-make-sure-to-not-dirty-twice-for-auth-nodes.patch b/queue-5.4/ubifs-journal-make-sure-to-not-dirty-twice-for-auth-nodes.patch
new file mode 100644 (file)
index 0000000..bed5467
--- /dev/null
@@ -0,0 +1,46 @@
+From 78c7d49f55d8631b67c09f9bfbe8155211a9ea06 Mon Sep 17 00:00:00 2001
+From: Richard Weinberger <richard@nod.at>
+Date: Mon, 28 Sep 2020 20:58:59 +0200
+Subject: ubifs: journal: Make sure to not dirty twice for auth nodes
+
+From: Richard Weinberger <richard@nod.at>
+
+commit 78c7d49f55d8631b67c09f9bfbe8155211a9ea06 upstream.
+
+When removing the last reference of an inode the size of an auth node
+is already part of write_len. So we must not call ubifs_add_auth_dirt().
+Call it only when needed.
+
+Cc: <stable@vger.kernel.org>
+Cc: Sascha Hauer <s.hauer@pengutronix.de>
+Cc: Kristof Havasi <havasiefr@gmail.com>
+Fixes: 6a98bc4614de ("ubifs: Add authentication nodes to journal")
+Reported-and-tested-by: Kristof Havasi <havasiefr@gmail.com>
+Reviewed-by: Sascha Hauer <s.hauer@pengutronix.de>
+Signed-off-by: Richard Weinberger <richard@nod.at>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/ubifs/journal.c |    4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/fs/ubifs/journal.c
++++ b/fs/ubifs/journal.c
+@@ -938,8 +938,6 @@ int ubifs_jnl_write_inode(struct ubifs_i
+                                         inode->i_ino);
+       release_head(c, BASEHD);
+-      ubifs_add_auth_dirt(c, lnum);
+-
+       if (last_reference) {
+               err = ubifs_tnc_remove_ino(c, inode->i_ino);
+               if (err)
+@@ -949,6 +947,8 @@ int ubifs_jnl_write_inode(struct ubifs_i
+       } else {
+               union ubifs_key key;
++              ubifs_add_auth_dirt(c, lnum);
++
+               ino_key_init(c, &key, inode->i_ino);
+               err = ubifs_tnc_add(c, &key, lnum, offs, ilen, hash);
+       }
diff --git a/queue-5.4/ubifs-mount_ubifs-release-authentication-resource-in-error-handling-path.patch b/queue-5.4/ubifs-mount_ubifs-release-authentication-resource-in-error-handling-path.patch
new file mode 100644 (file)
index 0000000..8904515
--- /dev/null
@@ -0,0 +1,65 @@
+From e2a05cc7f8229e150243cdae40f2af9021d67a4a Mon Sep 17 00:00:00 2001
+From: Zhihao Cheng <chengzhihao1@huawei.com>
+Date: Tue, 29 Sep 2020 20:45:31 +0800
+Subject: ubifs: mount_ubifs: Release authentication resource in error handling path
+
+From: Zhihao Cheng <chengzhihao1@huawei.com>
+
+commit e2a05cc7f8229e150243cdae40f2af9021d67a4a upstream.
+
+Release the authentication related resource in some error handling
+branches in mount_ubifs().
+
+Signed-off-by: Zhihao Cheng <chengzhihao1@huawei.com>
+Cc: <stable@vger.kernel.org>  # 4.20+
+Fixes: d8a22773a12c6d7 ("ubifs: Enable authentication support")
+Reviewed-by: Sascha Hauer <s.hauer@pengutronix.de>
+Signed-off-by: Richard Weinberger <richard@nod.at>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/ubifs/super.c |   10 ++++++----
+ 1 file changed, 6 insertions(+), 4 deletions(-)
+
+--- a/fs/ubifs/super.c
++++ b/fs/ubifs/super.c
+@@ -1313,7 +1313,7 @@ static int mount_ubifs(struct ubifs_info
+       err = ubifs_read_superblock(c);
+       if (err)
+-              goto out_free;
++              goto out_auth;
+       c->probing = 0;
+@@ -1325,18 +1325,18 @@ static int mount_ubifs(struct ubifs_info
+               ubifs_err(c, "'compressor \"%s\" is not compiled in",
+                         ubifs_compr_name(c, c->default_compr));
+               err = -ENOTSUPP;
+-              goto out_free;
++              goto out_auth;
+       }
+       err = init_constants_sb(c);
+       if (err)
+-              goto out_free;
++              goto out_auth;
+       sz = ALIGN(c->max_idx_node_sz, c->min_io_size) * 2;
+       c->cbuf = kmalloc(sz, GFP_NOFS);
+       if (!c->cbuf) {
+               err = -ENOMEM;
+-              goto out_free;
++              goto out_auth;
+       }
+       err = alloc_wbufs(c);
+@@ -1611,6 +1611,8 @@ out_wbufs:
+       free_wbufs(c);
+ out_cbuf:
+       kfree(c->cbuf);
++out_auth:
++      ubifs_exit_authentication(c);
+ out_free:
+       kfree(c->write_reserve_buf);
+       kfree(c->bu.buf);
diff --git a/queue-5.4/ubifs-xattr-fix-some-potential-memory-leaks-while-iterating-entries.patch b/queue-5.4/ubifs-xattr-fix-some-potential-memory-leaks-while-iterating-entries.patch
new file mode 100644 (file)
index 0000000..6e35681
--- /dev/null
@@ -0,0 +1,107 @@
+From f2aae745b82c842221f4f233051f9ac641790959 Mon Sep 17 00:00:00 2001
+From: Zhihao Cheng <chengzhihao1@huawei.com>
+Date: Mon, 1 Jun 2020 17:10:36 +0800
+Subject: ubifs: xattr: Fix some potential memory leaks while iterating entries
+
+From: Zhihao Cheng <chengzhihao1@huawei.com>
+
+commit f2aae745b82c842221f4f233051f9ac641790959 upstream.
+
+Fix some potential memory leaks in error handling branches while
+iterating xattr entries. For example, function ubifs_tnc_remove_ino()
+forgets to free pxent if it exists. Similar problems also exist in
+ubifs_purge_xattrs(), ubifs_add_orphan() and ubifs_jnl_write_inode().
+
+Signed-off-by: Zhihao Cheng <chengzhihao1@huawei.com>
+Cc: <stable@vger.kernel.org>
+Fixes: 1e51764a3c2ac05a2 ("UBIFS: add new flash file system")
+Signed-off-by: Richard Weinberger <richard@nod.at>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/ubifs/journal.c |    2 ++
+ fs/ubifs/orphan.c  |    2 ++
+ fs/ubifs/tnc.c     |    3 +++
+ fs/ubifs/xattr.c   |    2 ++
+ 4 files changed, 9 insertions(+)
+
+--- a/fs/ubifs/journal.c
++++ b/fs/ubifs/journal.c
+@@ -894,6 +894,7 @@ int ubifs_jnl_write_inode(struct ubifs_i
+                               if (err == -ENOENT)
+                                       break;
++                              kfree(pxent);
+                               goto out_release;
+                       }
+@@ -906,6 +907,7 @@ int ubifs_jnl_write_inode(struct ubifs_i
+                               ubifs_err(c, "dead directory entry '%s', error %d",
+                                         xent->name, err);
+                               ubifs_ro_mode(c, err);
++                              kfree(pxent);
+                               kfree(xent);
+                               goto out_release;
+                       }
+--- a/fs/ubifs/orphan.c
++++ b/fs/ubifs/orphan.c
+@@ -173,6 +173,7 @@ int ubifs_add_orphan(struct ubifs_info *
+                       err = PTR_ERR(xent);
+                       if (err == -ENOENT)
+                               break;
++                      kfree(pxent);
+                       return err;
+               }
+@@ -182,6 +183,7 @@ int ubifs_add_orphan(struct ubifs_info *
+               xattr_orphan = orphan_add(c, xattr_inum, orphan);
+               if (IS_ERR(xattr_orphan)) {
++                      kfree(pxent);
+                       kfree(xent);
+                       return PTR_ERR(xattr_orphan);
+               }
+--- a/fs/ubifs/tnc.c
++++ b/fs/ubifs/tnc.c
+@@ -2885,6 +2885,7 @@ int ubifs_tnc_remove_ino(struct ubifs_in
+                       err = PTR_ERR(xent);
+                       if (err == -ENOENT)
+                               break;
++                      kfree(pxent);
+                       return err;
+               }
+@@ -2898,6 +2899,7 @@ int ubifs_tnc_remove_ino(struct ubifs_in
+               fname_len(&nm) = le16_to_cpu(xent->nlen);
+               err = ubifs_tnc_remove_nm(c, &key1, &nm);
+               if (err) {
++                      kfree(pxent);
+                       kfree(xent);
+                       return err;
+               }
+@@ -2906,6 +2908,7 @@ int ubifs_tnc_remove_ino(struct ubifs_in
+               highest_ino_key(c, &key2, xattr_inum);
+               err = ubifs_tnc_remove_range(c, &key1, &key2);
+               if (err) {
++                      kfree(pxent);
+                       kfree(xent);
+                       return err;
+               }
+--- a/fs/ubifs/xattr.c
++++ b/fs/ubifs/xattr.c
+@@ -522,6 +522,7 @@ int ubifs_purge_xattrs(struct inode *hos
+                                 xent->name, err);
+                       ubifs_ro_mode(c, err);
+                       kfree(pxent);
++                      kfree(xent);
+                       return err;
+               }
+@@ -531,6 +532,7 @@ int ubifs_purge_xattrs(struct inode *hos
+               err = remove_xattr(c, host, xino, &nm);
+               if (err) {
+                       kfree(pxent);
++                      kfree(xent);
+                       iput(xino);
+                       ubifs_err(c, "cannot remove xattr, error %d", err);
+                       return err;
diff --git a/queue-5.4/udf-fix-memory-leak-when-mounting.patch b/queue-5.4/udf-fix-memory-leak-when-mounting.patch
new file mode 100644 (file)
index 0000000..2ac9fc4
--- /dev/null
@@ -0,0 +1,83 @@
+From a7be300de800e755714c71103ae4a0d205e41e99 Mon Sep 17 00:00:00 2001
+From: Jan Kara <jack@suse.cz>
+Date: Tue, 22 Sep 2020 12:20:14 +0200
+Subject: udf: Fix memory leak when mounting
+
+From: Jan Kara <jack@suse.cz>
+
+commit a7be300de800e755714c71103ae4a0d205e41e99 upstream.
+
+udf_process_sequence() allocates temporary array for processing
+partition descriptors on volume which it fails to free. Free the array
+when it is not needed anymore.
+
+Fixes: 7b78fd02fb19 ("udf: Fix handling of Partition Descriptors")
+CC: stable@vger.kernel.org
+Reported-by: syzbot+128f4dd6e796c98b3760@syzkaller.appspotmail.com
+Signed-off-by: Jan Kara <jack@suse.cz>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/udf/super.c |   21 +++++++++++++--------
+ 1 file changed, 13 insertions(+), 8 deletions(-)
+
+--- a/fs/udf/super.c
++++ b/fs/udf/super.c
+@@ -1703,7 +1703,8 @@ static noinline int udf_process_sequence
+                                       "Pointers (max %u supported)\n",
+                                       UDF_MAX_TD_NESTING);
+                               brelse(bh);
+-                              return -EIO;
++                              ret = -EIO;
++                              goto out;
+                       }
+                       vdp = (struct volDescPtr *)bh->b_data;
+@@ -1723,7 +1724,8 @@ static noinline int udf_process_sequence
+                       curr = get_volume_descriptor_record(ident, bh, &data);
+                       if (IS_ERR(curr)) {
+                               brelse(bh);
+-                              return PTR_ERR(curr);
++                              ret = PTR_ERR(curr);
++                              goto out;
+                       }
+                       /* Descriptor we don't care about? */
+                       if (!curr)
+@@ -1745,28 +1747,31 @@ static noinline int udf_process_sequence
+        */
+       if (!data.vds[VDS_POS_PRIMARY_VOL_DESC].block) {
+               udf_err(sb, "Primary Volume Descriptor not found!\n");
+-              return -EAGAIN;
++              ret = -EAGAIN;
++              goto out;
+       }
+       ret = udf_load_pvoldesc(sb, data.vds[VDS_POS_PRIMARY_VOL_DESC].block);
+       if (ret < 0)
+-              return ret;
++              goto out;
+       if (data.vds[VDS_POS_LOGICAL_VOL_DESC].block) {
+               ret = udf_load_logicalvol(sb,
+                               data.vds[VDS_POS_LOGICAL_VOL_DESC].block,
+                               fileset);
+               if (ret < 0)
+-                      return ret;
++                      goto out;
+       }
+       /* Now handle prevailing Partition Descriptors */
+       for (i = 0; i < data.num_part_descs; i++) {
+               ret = udf_load_partdesc(sb, data.part_descs_loc[i].rec.block);
+               if (ret < 0)
+-                      return ret;
++                      goto out;
+       }
+-
+-      return 0;
++      ret = 0;
++out:
++      kfree(data.part_descs_loc);
++      return ret;
+ }
+ /*
diff --git a/queue-5.4/usb-cdc-acm-fix-cooldown-mechanism.patch b/queue-5.4/usb-cdc-acm-fix-cooldown-mechanism.patch
new file mode 100644 (file)
index 0000000..19be0b6
--- /dev/null
@@ -0,0 +1,126 @@
+From 38203b8385bf6283537162bde7d499f830964711 Mon Sep 17 00:00:00 2001
+From: Jerome Brunet <jbrunet@baylibre.com>
+Date: Mon, 19 Oct 2020 19:07:02 +0200
+Subject: usb: cdc-acm: fix cooldown mechanism
+
+From: Jerome Brunet <jbrunet@baylibre.com>
+
+commit 38203b8385bf6283537162bde7d499f830964711 upstream.
+
+Commit a4e7279cd1d1 ("cdc-acm: introduce a cool down") is causing
+regression if there is some USB error, such as -EPROTO.
+
+This has been reported on some samples of the Odroid-N2 using the Combee II
+Zibgee USB dongle.
+
+> struct acm *acm = container_of(work, struct acm, work)
+
+is incorrect in case of a delayed work and causes warnings, usually from
+the workqueue:
+
+> WARNING: CPU: 0 PID: 0 at kernel/workqueue.c:1474 __queue_work+0x480/0x528.
+
+When this happens, USB eventually stops working completely after a while.
+Also the ACM_ERROR_DELAY bit is never set, so the cooldown mechanism
+previously introduced cannot be triggered and acm_submit_read_urb() is
+never called.
+
+This changes makes the cdc-acm driver use a single delayed work, fixing the
+pointer arithmetic in acm_softint() and set the ACM_ERROR_DELAY when the
+cooldown mechanism appear to be needed.
+
+Fixes: a4e7279cd1d1 ("cdc-acm: introduce a cool down")
+Cc: Oliver Neukum <oneukum@suse.com>
+Reported-by: Pascal Vizeli <pascal.vizeli@nabucasa.com>
+Acked-by: Oliver Neukum <oneukum@suse.com>
+Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
+Link: https://lore.kernel.org/r/20201019170702.150534-1-jbrunet@baylibre.com
+Cc: stable <stable@vger.kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/class/cdc-acm.c |   12 +++++-------
+ drivers/usb/class/cdc-acm.h |    3 +--
+ 2 files changed, 6 insertions(+), 9 deletions(-)
+
+--- a/drivers/usb/class/cdc-acm.c
++++ b/drivers/usb/class/cdc-acm.c
+@@ -507,6 +507,7 @@ static void acm_read_bulk_callback(struc
+                       "%s - cooling babbling device\n", __func__);
+               usb_mark_last_busy(acm->dev);
+               set_bit(rb->index, &acm->urbs_in_error_delay);
++              set_bit(ACM_ERROR_DELAY, &acm->flags);
+               cooldown = true;
+               break;
+       default:
+@@ -532,7 +533,7 @@ static void acm_read_bulk_callback(struc
+       if (stopped || stalled || cooldown) {
+               if (stalled)
+-                      schedule_work(&acm->work);
++                      schedule_delayed_work(&acm->dwork, 0);
+               else if (cooldown)
+                       schedule_delayed_work(&acm->dwork, HZ / 2);
+               return;
+@@ -562,13 +563,13 @@ static void acm_write_bulk(struct urb *u
+       acm_write_done(acm, wb);
+       spin_unlock_irqrestore(&acm->write_lock, flags);
+       set_bit(EVENT_TTY_WAKEUP, &acm->flags);
+-      schedule_work(&acm->work);
++      schedule_delayed_work(&acm->dwork, 0);
+ }
+ static void acm_softint(struct work_struct *work)
+ {
+       int i;
+-      struct acm *acm = container_of(work, struct acm, work);
++      struct acm *acm = container_of(work, struct acm, dwork.work);
+       if (test_bit(EVENT_RX_STALL, &acm->flags)) {
+               smp_mb(); /* against acm_suspend() */
+@@ -584,7 +585,7 @@ static void acm_softint(struct work_stru
+       if (test_and_clear_bit(ACM_ERROR_DELAY, &acm->flags)) {
+               for (i = 0; i < acm->rx_buflimit; i++)
+                       if (test_and_clear_bit(i, &acm->urbs_in_error_delay))
+-                                      acm_submit_read_urb(acm, i, GFP_NOIO);
++                              acm_submit_read_urb(acm, i, GFP_KERNEL);
+       }
+       if (test_and_clear_bit(EVENT_TTY_WAKEUP, &acm->flags))
+@@ -1364,7 +1365,6 @@ made_compressed_probe:
+       acm->ctrlsize = ctrlsize;
+       acm->readsize = readsize;
+       acm->rx_buflimit = num_rx_buf;
+-      INIT_WORK(&acm->work, acm_softint);
+       INIT_DELAYED_WORK(&acm->dwork, acm_softint);
+       init_waitqueue_head(&acm->wioctl);
+       spin_lock_init(&acm->write_lock);
+@@ -1574,7 +1574,6 @@ static void acm_disconnect(struct usb_in
+       }
+       acm_kill_urbs(acm);
+-      cancel_work_sync(&acm->work);
+       cancel_delayed_work_sync(&acm->dwork);
+       tty_unregister_device(acm_tty_driver, acm->minor);
+@@ -1617,7 +1616,6 @@ static int acm_suspend(struct usb_interf
+               return 0;
+       acm_kill_urbs(acm);
+-      cancel_work_sync(&acm->work);
+       cancel_delayed_work_sync(&acm->dwork);
+       acm->urbs_in_error_delay = 0;
+--- a/drivers/usb/class/cdc-acm.h
++++ b/drivers/usb/class/cdc-acm.h
+@@ -112,8 +112,7 @@ struct acm {
+ #             define ACM_ERROR_DELAY  3
+       unsigned long urbs_in_error_delay;              /* these need to be restarted after a delay */
+       struct usb_cdc_line_coding line;                /* bits, stop, parity */
+-      struct work_struct work;                        /* work queue entry for various purposes*/
+-      struct delayed_work dwork;                      /* for cool downs needed in error recovery */
++      struct delayed_work dwork;                      /* work queue entry for various purposes */
+       unsigned int ctrlin;                            /* input control lines (DCD, DSR, RI, break, overruns) */
+       unsigned int ctrlout;                           /* output control lines (DTR, RTS) */
+       struct async_icount iocount;                    /* counters for control line changes */
diff --git a/queue-5.4/usb-dwc3-core-add-phy-cleanup-for-probe-error-handling.patch b/queue-5.4/usb-dwc3-core-add-phy-cleanup-for-probe-error-handling.patch
new file mode 100644 (file)
index 0000000..997b868
--- /dev/null
@@ -0,0 +1,42 @@
+From 03c1fd622f72c7624c81b64fdba4a567ae5ee9cb Mon Sep 17 00:00:00 2001
+From: Li Jun <jun.li@nxp.com>
+Date: Tue, 28 Jul 2020 20:42:41 +0800
+Subject: usb: dwc3: core: add phy cleanup for probe error handling
+
+From: Li Jun <jun.li@nxp.com>
+
+commit 03c1fd622f72c7624c81b64fdba4a567ae5ee9cb upstream.
+
+Add the phy cleanup if dwc3 mode init fail, which is the missing part of
+de-init for dwc3 core init.
+
+Fixes: c499ff71ff2a ("usb: dwc3: core: re-factor init and exit paths")
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Li Jun <jun.li@nxp.com>
+Signed-off-by: Felipe Balbi <balbi@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/dwc3/core.c |   11 +++++++++++
+ 1 file changed, 11 insertions(+)
+
+--- a/drivers/usb/dwc3/core.c
++++ b/drivers/usb/dwc3/core.c
+@@ -1535,6 +1535,17 @@ static int dwc3_probe(struct platform_de
+ err5:
+       dwc3_event_buffers_cleanup(dwc);
++
++      usb_phy_shutdown(dwc->usb2_phy);
++      usb_phy_shutdown(dwc->usb3_phy);
++      phy_exit(dwc->usb2_generic_phy);
++      phy_exit(dwc->usb3_generic_phy);
++
++      usb_phy_set_suspend(dwc->usb2_phy, 1);
++      usb_phy_set_suspend(dwc->usb3_phy, 1);
++      phy_power_off(dwc->usb2_generic_phy);
++      phy_power_off(dwc->usb3_generic_phy);
++
+       dwc3_ulpi_exit(dwc);
+ err4:
diff --git a/queue-5.4/usb-dwc3-core-don-t-trigger-runtime-pm-when-remove-driver.patch b/queue-5.4/usb-dwc3-core-don-t-trigger-runtime-pm-when-remove-driver.patch
new file mode 100644 (file)
index 0000000..142a9db
--- /dev/null
@@ -0,0 +1,106 @@
+From 266d0493900ac5d6a21cdbe6b1624ed2da94d47a Mon Sep 17 00:00:00 2001
+From: Li Jun <jun.li@nxp.com>
+Date: Tue, 28 Jul 2020 20:42:40 +0800
+Subject: usb: dwc3: core: don't trigger runtime pm when remove driver
+
+From: Li Jun <jun.li@nxp.com>
+
+commit 266d0493900ac5d6a21cdbe6b1624ed2da94d47a upstream.
+
+No need to trigger runtime pm in driver removal, otherwise if user
+disable auto suspend via sys file, runtime suspend may be entered,
+which will call dwc3_core_exit() again and there will be clock disable
+not balance warning:
+
+[ 2026.820154] xhci-hcd xhci-hcd.0.auto: remove, state 4
+[ 2026.825268] usb usb2: USB disconnect, device number 1
+[ 2026.831017] xhci-hcd xhci-hcd.0.auto: USB bus 2 deregistered
+[ 2026.836806] xhci-hcd xhci-hcd.0.auto: remove, state 4
+[ 2026.842029] usb usb1: USB disconnect, device number 1
+[ 2026.848029] xhci-hcd xhci-hcd.0.auto: USB bus 1 deregistered
+[ 2026.865889] ------------[ cut here ]------------
+[ 2026.870506] usb2_ctrl_root_clk already disabled
+[ 2026.875082] WARNING: CPU: 0 PID: 731 at drivers/clk/clk.c:958
+clk_core_disable+0xa0/0xa8
+[ 2026.883170] Modules linked in: dwc3(-) phy_fsl_imx8mq_usb [last
+unloaded: dwc3]
+[ 2026.890488] CPU: 0 PID: 731 Comm: rmmod Not tainted
+5.8.0-rc7-00280-g9d08cca-dirty #245
+[ 2026.898489] Hardware name: NXP i.MX8MQ EVK (DT)
+[ 2026.903020] pstate: 20000085 (nzCv daIf -PAN -UAO BTYPE=--)
+[ 2026.908594] pc : clk_core_disable+0xa0/0xa8
+[ 2026.912777] lr : clk_core_disable+0xa0/0xa8
+[ 2026.916958] sp : ffff8000121b39a0
+[ 2026.920271] x29: ffff8000121b39a0 x28: ffff0000b11f3700
+[ 2026.925583] x27: 0000000000000000 x26: ffff0000b539c700
+[ 2026.930895] x25: 000001d7e44e1232 x24: ffff0000b76fa800
+[ 2026.936208] x23: ffff0000b76fa6f8 x22: ffff800008d01040
+[ 2026.941520] x21: ffff0000b539ce00 x20: ffff0000b7105000
+[ 2026.946832] x19: ffff0000b7105000 x18: 0000000000000010
+[ 2026.952144] x17: 0000000000000001 x16: 0000000000000000
+[ 2026.957456] x15: ffff0000b11f3b70 x14: ffffffffffffffff
+[ 2026.962768] x13: ffff8000921b36f7 x12: ffff8000121b36ff
+[ 2026.968080] x11: ffff8000119e1000 x10: ffff800011bf26d0
+[ 2026.973392] x9 : 0000000000000000 x8 : ffff800011bf3000
+[ 2026.978704] x7 : ffff800010695d68 x6 : 0000000000000252
+[ 2026.984016] x5 : ffff0000bb9881f0 x4 : 0000000000000000
+[ 2026.989327] x3 : 0000000000000027 x2 : 0000000000000023
+[ 2026.994639] x1 : ac2fa471aa7cab00 x0 : 0000000000000000
+[ 2026.999951] Call trace:
+[ 2027.002401]  clk_core_disable+0xa0/0xa8
+[ 2027.006238]  clk_core_disable_lock+0x20/0x38
+[ 2027.010508]  clk_disable+0x1c/0x28
+[ 2027.013911]  clk_bulk_disable+0x34/0x50
+[ 2027.017758]  dwc3_core_exit+0xec/0x110 [dwc3]
+[ 2027.022122]  dwc3_suspend_common+0x84/0x188 [dwc3]
+[ 2027.026919]  dwc3_runtime_suspend+0x74/0x9c [dwc3]
+[ 2027.031712]  pm_generic_runtime_suspend+0x28/0x40
+[ 2027.036419]  genpd_runtime_suspend+0xa0/0x258
+[ 2027.040777]  __rpm_callback+0x88/0x140
+[ 2027.044526]  rpm_callback+0x20/0x80
+[ 2027.048015]  rpm_suspend+0xd0/0x418
+[ 2027.051503]  __pm_runtime_suspend+0x58/0xa0
+[ 2027.055693]  dwc3_runtime_idle+0x7c/0x90 [dwc3]
+[ 2027.060224]  __rpm_callback+0x88/0x140
+[ 2027.063973]  rpm_idle+0x78/0x150
+[ 2027.067201]  __pm_runtime_idle+0x58/0xa0
+[ 2027.071130]  dwc3_remove+0x64/0xc0 [dwc3]
+[ 2027.075140]  platform_drv_remove+0x28/0x48
+[ 2027.079239]  device_release_driver_internal+0xf4/0x1c0
+[ 2027.084377]  driver_detach+0x4c/0xd8
+[ 2027.087954]  bus_remove_driver+0x54/0xa8
+[ 2027.091877]  driver_unregister+0x2c/0x58
+[ 2027.095799]  platform_driver_unregister+0x10/0x18
+[ 2027.100509]  dwc3_driver_exit+0x14/0x1408 [dwc3]
+[ 2027.105129]  __arm64_sys_delete_module+0x178/0x218
+[ 2027.109922]  el0_svc_common.constprop.0+0x68/0x160
+[ 2027.114714]  do_el0_svc+0x20/0x80
+[ 2027.118031]  el0_sync_handler+0x88/0x190
+[ 2027.121953]  el0_sync+0x140/0x180
+[ 2027.125267] ---[ end trace 027f4f8189958f1f ]---
+[ 2027.129976] ------------[ cut here ]------------
+
+Fixes: fc8bb91bc83e ("usb: dwc3: implement runtime PM")
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Li Jun <jun.li@nxp.com>
+Signed-off-by: Felipe Balbi <balbi@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/dwc3/core.c |    4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/usb/dwc3/core.c
++++ b/drivers/usb/dwc3/core.c
+@@ -1581,9 +1581,9 @@ static int dwc3_remove(struct platform_d
+       dwc3_core_exit(dwc);
+       dwc3_ulpi_exit(dwc);
+-      pm_runtime_put_sync(&pdev->dev);
+-      pm_runtime_allow(&pdev->dev);
+       pm_runtime_disable(&pdev->dev);
++      pm_runtime_put_noidle(&pdev->dev);
++      pm_runtime_set_suspended(&pdev->dev);
+       dwc3_free_event_buffers(dwc);
+       dwc3_free_scratch_buffers(dwc);
diff --git a/queue-5.4/usb-dwc3-ep0-fix-zlp-for-out-ep0-requests.patch b/queue-5.4/usb-dwc3-ep0-fix-zlp-for-out-ep0-requests.patch
new file mode 100644 (file)
index 0000000..705aae7
--- /dev/null
@@ -0,0 +1,63 @@
+From 66706077dc89c66a4777a4c6298273816afb848c Mon Sep 17 00:00:00 2001
+From: Thinh Nguyen <Thinh.Nguyen@synopsys.com>
+Date: Thu, 24 Sep 2020 01:21:43 -0700
+Subject: usb: dwc3: ep0: Fix ZLP for OUT ep0 requests
+
+From: Thinh Nguyen <Thinh.Nguyen@synopsys.com>
+
+commit 66706077dc89c66a4777a4c6298273816afb848c upstream.
+
+The current ZLP handling for ep0 requests is only for control IN
+requests. For OUT direction, DWC3 needs to check and setup for MPS
+alignment.
+
+Usually, control OUT requests can indicate its transfer size via the
+wLength field of the control message. So usb_request->zero is usually
+not needed for OUT direction. To handle ZLP OUT for control endpoint,
+make sure the TRB is MPS size.
+
+Cc: stable@vger.kernel.org
+Fixes: c7fcdeb2627c ("usb: dwc3: ep0: simplify EP0 state machine")
+Fixes: d6e5a549cc4d ("usb: dwc3: simplify ZLP handling")
+Signed-off-by: Thinh Nguyen <Thinh.Nguyen@synopsys.com>
+Signed-off-by: Felipe Balbi <balbi@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/dwc3/ep0.c |   11 +++++++++--
+ 1 file changed, 9 insertions(+), 2 deletions(-)
+
+--- a/drivers/usb/dwc3/ep0.c
++++ b/drivers/usb/dwc3/ep0.c
+@@ -942,12 +942,16 @@ static void dwc3_ep0_xfer_complete(struc
+ static void __dwc3_ep0_do_control_data(struct dwc3 *dwc,
+               struct dwc3_ep *dep, struct dwc3_request *req)
+ {
++      unsigned int            trb_length = 0;
+       int                     ret;
+       req->direction = !!dep->number;
+       if (req->request.length == 0) {
+-              dwc3_ep0_prepare_one_trb(dep, dwc->ep0_trb_addr, 0,
++              if (!req->direction)
++                      trb_length = dep->endpoint.maxpacket;
++
++              dwc3_ep0_prepare_one_trb(dep, dwc->bounce_addr, trb_length,
+                               DWC3_TRBCTL_CONTROL_DATA, false);
+               ret = dwc3_ep0_start_trans(dep);
+       } else if (!IS_ALIGNED(req->request.length, dep->endpoint.maxpacket)
+@@ -994,9 +998,12 @@ static void __dwc3_ep0_do_control_data(s
+               req->trb = &dwc->ep0_trb[dep->trb_enqueue - 1];
++              if (!req->direction)
++                      trb_length = dep->endpoint.maxpacket;
++
+               /* Now prepare one extra TRB to align transfer size */
+               dwc3_ep0_prepare_one_trb(dep, dwc->bounce_addr,
+-                                       0, DWC3_TRBCTL_CONTROL_DATA,
++                                       trb_length, DWC3_TRBCTL_CONTROL_DATA,
+                                        false);
+               ret = dwc3_ep0_start_trans(dep);
+       } else {
diff --git a/queue-5.4/usb-dwc3-gadget-check-mps-of-the-request-length.patch b/queue-5.4/usb-dwc3-gadget-check-mps-of-the-request-length.patch
new file mode 100644 (file)
index 0000000..70a0594
--- /dev/null
@@ -0,0 +1,43 @@
+From ca3df3468eec87f6374662f7de425bc44c3810c1 Mon Sep 17 00:00:00 2001
+From: Thinh Nguyen <Thinh.Nguyen@synopsys.com>
+Date: Thu, 24 Sep 2020 01:21:18 -0700
+Subject: usb: dwc3: gadget: Check MPS of the request length
+
+From: Thinh Nguyen <Thinh.Nguyen@synopsys.com>
+
+commit ca3df3468eec87f6374662f7de425bc44c3810c1 upstream.
+
+When preparing for SG, not all the entries are prepared at once. When
+resume, don't use the remaining request length to calculate for MPS
+alignment. Use the entire request->length to do that.
+
+Cc: stable@vger.kernel.org
+Fixes: 5d187c0454ef ("usb: dwc3: gadget: Don't setup more than requested")
+Signed-off-by: Thinh Nguyen <Thinh.Nguyen@synopsys.com>
+Signed-off-by: Felipe Balbi <balbi@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/dwc3/gadget.c |    4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/usb/dwc3/gadget.c
++++ b/drivers/usb/dwc3/gadget.c
+@@ -1057,6 +1057,8 @@ static void dwc3_prepare_one_trb_sg(stru
+       struct scatterlist *s;
+       int             i;
+       unsigned int length = req->request.length;
++      unsigned int maxp = usb_endpoint_maxp(dep->endpoint.desc);
++      unsigned int rem = length % maxp;
+       unsigned int remaining = req->request.num_mapped_sgs
+               - req->num_queued_sgs;
+@@ -1068,8 +1070,6 @@ static void dwc3_prepare_one_trb_sg(stru
+               length -= sg_dma_len(s);
+       for_each_sg(sg, s, remaining, i) {
+-              unsigned int maxp = usb_endpoint_maxp(dep->endpoint.desc);
+-              unsigned int rem = length % maxp;
+               unsigned int trb_length;
+               unsigned chain = true;
diff --git a/queue-5.4/usb-dwc3-gadget-end_transfer-before-clear_stall-command.patch b/queue-5.4/usb-dwc3-gadget-end_transfer-before-clear_stall-command.patch
new file mode 100644 (file)
index 0000000..bcae220
--- /dev/null
@@ -0,0 +1,145 @@
+From d97c78a1908e59a1fdbcbece87cd0440b5d7a1f2 Mon Sep 17 00:00:00 2001
+From: Thinh Nguyen <Thinh.Nguyen@synopsys.com>
+Date: Wed, 2 Sep 2020 18:43:04 -0700
+Subject: usb: dwc3: gadget: END_TRANSFER before CLEAR_STALL command
+
+From: Thinh Nguyen <Thinh.Nguyen@synopsys.com>
+
+commit d97c78a1908e59a1fdbcbece87cd0440b5d7a1f2 upstream.
+
+According the programming guide (for all DWC3 IPs), when the driver
+handles ClearFeature(halt) request, it should issue CLEAR_STALL command
+_after_ the END_TRANSFER command completes. The END_TRANSFER command may
+take some time to complete. So, delay the ClearFeature(halt) request
+control status stage and wait for END_TRANSFER command completion
+interrupt. Only after END_TRANSFER command completes that the driver
+may issue CLEAR_STALL command.
+
+Cc: stable@vger.kernel.org
+Fixes: cb11ea56f37a ("usb: dwc3: gadget: Properly handle ClearFeature(halt)")
+Signed-off-by: Thinh Nguyen <thinhn@synopsys.com>
+Signed-off-by: Felipe Balbi <balbi@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/dwc3/core.h   |    1 +
+ drivers/usb/dwc3/ep0.c    |   16 ++++++++++++++++
+ drivers/usb/dwc3/gadget.c |   40 ++++++++++++++++++++++++++++++++--------
+ drivers/usb/dwc3/gadget.h |    1 +
+ 4 files changed, 50 insertions(+), 8 deletions(-)
+
+--- a/drivers/usb/dwc3/core.h
++++ b/drivers/usb/dwc3/core.h
+@@ -700,6 +700,7 @@ struct dwc3_ep {
+ #define DWC3_EP_END_TRANSFER_PENDING BIT(4)
+ #define DWC3_EP_PENDING_REQUEST       BIT(5)
+ #define DWC3_EP_DELAY_START   BIT(6)
++#define DWC3_EP_PENDING_CLEAR_STALL   BIT(11)
+       /* This last one is specific to EP0 */
+ #define DWC3_EP0_DIR_IN               BIT(31)
+--- a/drivers/usb/dwc3/ep0.c
++++ b/drivers/usb/dwc3/ep0.c
+@@ -524,6 +524,11 @@ static int dwc3_ep0_handle_endpoint(stru
+               ret = __dwc3_gadget_ep_set_halt(dep, set, true);
+               if (ret)
+                       return -EINVAL;
++
++              /* ClearFeature(Halt) may need delayed status */
++              if (!set && (dep->flags & DWC3_EP_END_TRANSFER_PENDING))
++                      return USB_GADGET_DELAYED_STATUS;
++
+               break;
+       default:
+               return -EINVAL;
+@@ -1049,6 +1054,17 @@ static void dwc3_ep0_do_control_status(s
+       __dwc3_ep0_do_control_status(dwc, dep);
+ }
++void dwc3_ep0_send_delayed_status(struct dwc3 *dwc)
++{
++      unsigned int direction = !dwc->ep0_expect_in;
++
++      if (dwc->ep0state != EP0_STATUS_PHASE)
++              return;
++
++      dwc->delayed_status = false;
++      __dwc3_ep0_do_control_status(dwc, dwc->eps[direction]);
++}
++
+ static void dwc3_ep0_end_control_data(struct dwc3 *dwc, struct dwc3_ep *dep)
+ {
+       struct dwc3_gadget_ep_cmd_params params;
+--- a/drivers/usb/dwc3/gadget.c
++++ b/drivers/usb/dwc3/gadget.c
+@@ -1719,6 +1719,18 @@ int __dwc3_gadget_ep_set_halt(struct dwc
+                       return 0;
+               }
++              dwc3_stop_active_transfer(dep, true, true);
++
++              list_for_each_entry_safe(req, tmp, &dep->started_list, list)
++                      dwc3_gadget_move_cancelled_request(req);
++
++              if (dep->flags & DWC3_EP_END_TRANSFER_PENDING) {
++                      dep->flags |= DWC3_EP_PENDING_CLEAR_STALL;
++                      return 0;
++              }
++
++              dwc3_gadget_ep_cleanup_cancelled_requests(dep);
++
+               ret = dwc3_send_clear_stall_ep_cmd(dep);
+               if (ret) {
+                       dev_err(dwc->dev, "failed to clear STALL on %s\n",
+@@ -1728,14 +1740,6 @@ int __dwc3_gadget_ep_set_halt(struct dwc
+               dep->flags &= ~(DWC3_EP_STALL | DWC3_EP_WEDGE);
+-              dwc3_stop_active_transfer(dep, true, true);
+-
+-              list_for_each_entry_safe(req, tmp, &dep->started_list, list)
+-                      dwc3_gadget_move_cancelled_request(req);
+-
+-              if (!(dep->flags & DWC3_EP_END_TRANSFER_PENDING))
+-                      dwc3_gadget_ep_cleanup_cancelled_requests(dep);
+-
+               if ((dep->flags & DWC3_EP_DELAY_START) &&
+                   !usb_endpoint_xfer_isoc(dep->endpoint.desc))
+                       __dwc3_gadget_kick_transfer(dep);
+@@ -2767,6 +2771,26 @@ static void dwc3_endpoint_interrupt(stru
+                       dep->flags &= ~DWC3_EP_END_TRANSFER_PENDING;
+                       dep->flags &= ~DWC3_EP_TRANSFER_STARTED;
+                       dwc3_gadget_ep_cleanup_cancelled_requests(dep);
++
++                      if (dep->flags & DWC3_EP_PENDING_CLEAR_STALL) {
++                              struct dwc3 *dwc = dep->dwc;
++
++                              dep->flags &= ~DWC3_EP_PENDING_CLEAR_STALL;
++                              if (dwc3_send_clear_stall_ep_cmd(dep)) {
++                                      struct usb_ep *ep0 = &dwc->eps[0]->endpoint;
++
++                                      dev_err(dwc->dev, "failed to clear STALL on %s\n",
++                                              dep->name);
++                                      if (dwc->delayed_status)
++                                              __dwc3_gadget_ep0_set_halt(ep0, 1);
++                                      return;
++                              }
++
++                              dep->flags &= ~(DWC3_EP_STALL | DWC3_EP_WEDGE);
++                              if (dwc->delayed_status)
++                                      dwc3_ep0_send_delayed_status(dwc);
++                      }
++
+                       if ((dep->flags & DWC3_EP_DELAY_START) &&
+                           !usb_endpoint_xfer_isoc(dep->endpoint.desc))
+                               __dwc3_gadget_kick_transfer(dep);
+--- a/drivers/usb/dwc3/gadget.h
++++ b/drivers/usb/dwc3/gadget.h
+@@ -111,6 +111,7 @@ int dwc3_gadget_ep0_set_halt(struct usb_
+ int dwc3_gadget_ep0_queue(struct usb_ep *ep, struct usb_request *request,
+               gfp_t gfp_flags);
+ int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value, int protocol);
++void dwc3_ep0_send_delayed_status(struct dwc3 *dwc);
+ /**
+  * dwc3_gadget_ep_get_transfer_index - Gets transfer index from HW
diff --git a/queue-5.4/usb-dwc3-gadget-resume-pending-requests-after-clear_stall.patch b/queue-5.4/usb-dwc3-gadget-resume-pending-requests-after-clear_stall.patch
new file mode 100644 (file)
index 0000000..e68b372
--- /dev/null
@@ -0,0 +1,66 @@
+From c503672abe1348f10f5a54a662336358c6e1a297 Mon Sep 17 00:00:00 2001
+From: Thinh Nguyen <Thinh.Nguyen@synopsys.com>
+Date: Wed, 2 Sep 2020 18:42:58 -0700
+Subject: usb: dwc3: gadget: Resume pending requests after CLEAR_STALL
+
+From: Thinh Nguyen <Thinh.Nguyen@synopsys.com>
+
+commit c503672abe1348f10f5a54a662336358c6e1a297 upstream.
+
+The function driver may queue new requests right after halting the
+endpoint (i.e. queue new requests while the endpoint is stalled).
+There's no restriction preventing it from doing so. However, dwc3
+currently drops those requests after CLEAR_STALL. The driver should only
+drop started requests. Keep the pending requests in the pending list to
+resume and process them after the host issues ClearFeature(Halt) to the
+endpoint.
+
+Cc: stable@vger.kernel.org
+Fixes: cb11ea56f37a ("usb: dwc3: gadget: Properly handle ClearFeature(halt)")
+Signed-off-by: Thinh Nguyen <thinhn@synopsys.com>
+Signed-off-by: Felipe Balbi <balbi@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/dwc3/gadget.c |   22 ++++++++++++++--------
+ 1 file changed, 14 insertions(+), 8 deletions(-)
+
+--- a/drivers/usb/dwc3/gadget.c
++++ b/drivers/usb/dwc3/gadget.c
+@@ -1521,8 +1521,13 @@ static int __dwc3_gadget_ep_queue(struct
+       list_add_tail(&req->list, &dep->pending_list);
+       req->status = DWC3_REQUEST_STATUS_QUEUED;
+-      /* Start the transfer only after the END_TRANSFER is completed */
+-      if (dep->flags & DWC3_EP_END_TRANSFER_PENDING) {
++      /*
++       * Start the transfer only after the END_TRANSFER is completed
++       * and endpoint STALL is cleared.
++       */
++      if ((dep->flags & DWC3_EP_END_TRANSFER_PENDING) ||
++          (dep->flags & DWC3_EP_WEDGE) ||
++          (dep->flags & DWC3_EP_STALL)) {
+               dep->flags |= DWC3_EP_DELAY_START;
+               return 0;
+       }
+@@ -1728,13 +1733,14 @@ int __dwc3_gadget_ep_set_halt(struct dwc
+               list_for_each_entry_safe(req, tmp, &dep->started_list, list)
+                       dwc3_gadget_move_cancelled_request(req);
+-              list_for_each_entry_safe(req, tmp, &dep->pending_list, list)
+-                      dwc3_gadget_move_cancelled_request(req);
+-
+-              if (!(dep->flags & DWC3_EP_END_TRANSFER_PENDING)) {
+-                      dep->flags &= ~DWC3_EP_DELAY_START;
++              if (!(dep->flags & DWC3_EP_END_TRANSFER_PENDING))
+                       dwc3_gadget_ep_cleanup_cancelled_requests(dep);
+-              }
++
++              if ((dep->flags & DWC3_EP_DELAY_START) &&
++                  !usb_endpoint_xfer_isoc(dep->endpoint.desc))
++                      __dwc3_gadget_kick_transfer(dep);
++
++              dep->flags &= ~DWC3_EP_DELAY_START;
+       }
+       return ret;
diff --git a/queue-5.4/usb-dwc3-pci-allow-elkhart-lake-to-utilize-dsm-method-for-pm-functionality.patch b/queue-5.4/usb-dwc3-pci-allow-elkhart-lake-to-utilize-dsm-method-for-pm-functionality.patch
new file mode 100644 (file)
index 0000000..b9b3dc2
--- /dev/null
@@ -0,0 +1,40 @@
+From a609ce2a13360d639b384b6ca783b38c1247f2db Mon Sep 17 00:00:00 2001
+From: Raymond Tan <raymond.tan@intel.com>
+Date: Fri, 21 Aug 2020 16:11:01 +0300
+Subject: usb: dwc3: pci: Allow Elkhart Lake to utilize DSM method for PM functionality
+
+From: Raymond Tan <raymond.tan@intel.com>
+
+commit a609ce2a13360d639b384b6ca783b38c1247f2db upstream.
+
+Similar to some other IA platforms, Elkhart Lake too depends on the
+PMU register write to request transition of Dx power state.
+
+Thus, we add the PCI_DEVICE_ID_INTEL_EHLLP to the list of devices that
+shall execute the ACPI _DSM method during D0/D3 sequence.
+
+[heikki.krogerus@linux.intel.com: included Fixes tag]
+
+Fixes: dbb0569de852 ("usb: dwc3: pci: Add Support for Intel Elkhart Lake Devices")
+Cc: stable@vger.kernel.org
+Signed-off-by: Raymond Tan <raymond.tan@intel.com>
+Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
+Signed-off-by: Felipe Balbi <balbi@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/dwc3/dwc3-pci.c |    3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/usb/dwc3/dwc3-pci.c
++++ b/drivers/usb/dwc3/dwc3-pci.c
+@@ -147,7 +147,8 @@ static int dwc3_pci_quirks(struct dwc3_p
+       if (pdev->vendor == PCI_VENDOR_ID_INTEL) {
+               if (pdev->device == PCI_DEVICE_ID_INTEL_BXT ||
+-                              pdev->device == PCI_DEVICE_ID_INTEL_BXT_M) {
++                  pdev->device == PCI_DEVICE_ID_INTEL_BXT_M ||
++                  pdev->device == PCI_DEVICE_ID_INTEL_EHLLP) {
+                       guid_parse(PCI_INTEL_BXT_DSM_GUID, &dwc->guid);
+                       dwc->has_dsm_for_pm = true;
+               }
diff --git a/queue-5.4/usb-host-fsl-mph-dr-of-check-return-of-dma_set_mask.patch b/queue-5.4/usb-host-fsl-mph-dr-of-check-return-of-dma_set_mask.patch
new file mode 100644 (file)
index 0000000..3aaecbf
--- /dev/null
@@ -0,0 +1,42 @@
+From 3cd54a618834430a26a648d880dd83d740f2ae30 Mon Sep 17 00:00:00 2001
+From: Ran Wang <ran.wang_1@nxp.com>
+Date: Sat, 10 Oct 2020 14:03:08 +0800
+Subject: usb: host: fsl-mph-dr-of: check return of dma_set_mask()
+
+From: Ran Wang <ran.wang_1@nxp.com>
+
+commit 3cd54a618834430a26a648d880dd83d740f2ae30 upstream.
+
+fsl_usb2_device_register() should stop init if dma_set_mask() return
+error.
+
+Fixes: cae058610465 ("drivers/usb/host: fsl: Set DMA_MASK of usb platform device")
+Reviewed-by: Peter Chen <peter.chen@nxp.com>
+Signed-off-by: Ran Wang <ran.wang_1@nxp.com>
+Link: https://lore.kernel.org/r/20201010060308.33693-1-ran.wang_1@nxp.com
+Cc: stable <stable@vger.kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/host/fsl-mph-dr-of.c |    9 ++++++---
+ 1 file changed, 6 insertions(+), 3 deletions(-)
+
+--- a/drivers/usb/host/fsl-mph-dr-of.c
++++ b/drivers/usb/host/fsl-mph-dr-of.c
+@@ -94,10 +94,13 @@ static struct platform_device *fsl_usb2_
+       pdev->dev.coherent_dma_mask = ofdev->dev.coherent_dma_mask;
+-      if (!pdev->dev.dma_mask)
++      if (!pdev->dev.dma_mask) {
+               pdev->dev.dma_mask = &ofdev->dev.coherent_dma_mask;
+-      else
+-              dma_set_mask(&pdev->dev, DMA_BIT_MASK(32));
++      } else {
++              retval = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32));
++              if (retval)
++                      goto error;
++      }
+       retval = platform_device_add_data(pdev, pdata, sizeof(*pdata));
+       if (retval)
diff --git a/queue-5.4/usb-typec-tcpm-reset-hard_reset_count-for-any-disconnect.patch b/queue-5.4/usb-typec-tcpm-reset-hard_reset_count-for-any-disconnect.patch
new file mode 100644 (file)
index 0000000..da8f21b
--- /dev/null
@@ -0,0 +1,99 @@
+From 2d9c6442a9c81f4f8dee678d0b3c183173ab1e2d Mon Sep 17 00:00:00 2001
+From: Li Jun <jun.li@nxp.com>
+Date: Mon, 12 Oct 2020 19:03:12 +0800
+Subject: usb: typec: tcpm: reset hard_reset_count for any disconnect
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Li Jun <jun.li@nxp.com>
+
+commit 2d9c6442a9c81f4f8dee678d0b3c183173ab1e2d upstream.
+
+Current tcpm_detach() only reset hard_reset_count if port->attached
+is true, this may cause this counter clear is missed if the CC
+disconnect event is generated after tcpm_port_reset() is done
+by other events, e.g. VBUS off comes first before CC disconect for
+a power sink, in that case the first tcpm_detach() will only clear
+port->attached flag but leave hard_reset_count there because
+tcpm_port_is_disconnected() is still false, then later tcpm_detach()
+by CC disconnect will directly return due to port->attached is cleared,
+finally this will result tcpm will not try hard reset or error recovery
+for later attach.
+
+ChiYuan reported this issue on his platform with below tcpm trace:
+After power sink session setup after hard reset 2 times, detach
+from the power source and then attach:
+[ 4848.046358] VBUS off
+[ 4848.046384] state change SNK_READY -> SNK_UNATTACHED
+[ 4848.050908] Setting voltage/current limit 0 mV 0 mA
+[ 4848.050936] polarity 0
+[ 4848.052593] Requesting mux state 0, usb-role 0, orientation 0
+[ 4848.053222] Start toggling
+[ 4848.086500] state change SNK_UNATTACHED -> TOGGLING
+[ 4848.089983] CC1: 0 -> 0, CC2: 3 -> 3 [state TOGGLING, polarity 0, connected]
+[ 4848.089993] state change TOGGLING -> SNK_ATTACH_WAIT
+[ 4848.090031] pending state change SNK_ATTACH_WAIT -> SNK_DEBOUNCED @200 ms
+[ 4848.141162] CC1: 0 -> 0, CC2: 3 -> 0 [state SNK_ATTACH_WAIT, polarity 0, disconnected]
+[ 4848.141170] state change SNK_ATTACH_WAIT -> SNK_ATTACH_WAIT
+[ 4848.141184] pending state change SNK_ATTACH_WAIT -> SNK_UNATTACHED @20 ms
+[ 4848.163156] state change SNK_ATTACH_WAIT -> SNK_UNATTACHED [delayed 20 ms]
+[ 4848.163162] Start toggling
+[ 4848.216918] CC1: 0 -> 0, CC2: 0 -> 3 [state TOGGLING, polarity 0, connected]
+[ 4848.216954] state change TOGGLING -> SNK_ATTACH_WAIT
+[ 4848.217080] pending state change SNK_ATTACH_WAIT -> SNK_DEBOUNCED @200 ms
+[ 4848.231771] CC1: 0 -> 0, CC2: 3 -> 0 [state SNK_ATTACH_WAIT, polarity 0, disconnected]
+[ 4848.231800] state change SNK_ATTACH_WAIT -> SNK_ATTACH_WAIT
+[ 4848.231857] pending state change SNK_ATTACH_WAIT -> SNK_UNATTACHED @20 ms
+[ 4848.256022] state change SNK_ATTACH_WAIT -> SNK_UNATTACHED [delayed20 ms]
+[ 4848.256049] Start toggling
+[ 4848.871148] VBUS on
+[ 4848.885324] CC1: 0 -> 0, CC2: 0 -> 3 [state TOGGLING, polarity 0, connected]
+[ 4848.885372] state change TOGGLING -> SNK_ATTACH_WAIT
+[ 4848.885548] pending state change SNK_ATTACH_WAIT -> SNK_DEBOUNCED @200 ms
+[ 4849.088240] state change SNK_ATTACH_WAIT -> SNK_DEBOUNCED [delayed200 ms]
+[ 4849.088284] state change SNK_DEBOUNCED -> SNK_ATTACHED
+[ 4849.088291] polarity 1
+[ 4849.088769] Requesting mux state 1, usb-role 2, orientation 2
+[ 4849.088895] state change SNK_ATTACHED -> SNK_STARTUP
+[ 4849.088907] state change SNK_STARTUP -> SNK_DISCOVERY
+[ 4849.088915] Setting voltage/current limit 5000 mV 0 mA
+[ 4849.088927] vbus=0 charge:=1
+[ 4849.090505] state change SNK_DISCOVERY -> SNK_WAIT_CAPABILITIES
+[ 4849.090828] pending state change SNK_WAIT_CAPABILITIES -> SNK_READY @240 ms
+[ 4849.335878] state change SNK_WAIT_CAPABILITIES -> SNK_READY [delayed240 ms]
+
+this patch fix this issue by clear hard_reset_count at any cases
+of cc disconnect, í.e. don't check port->attached flag.
+
+Fixes: 4b4e02c83167 ("typec: tcpm: Move out of staging")
+Cc: stable@vger.kernel.org
+Reported-and-tested-by: ChiYuan Huang <cy_huang@richtek.com>
+Reviewed-by: Guenter Roeck <linux@roeck-us.net>
+Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
+Signed-off-by: Li Jun <jun.li@nxp.com>
+Link: https://lore.kernel.org/r/1602500592-3817-1-git-send-email-jun.li@nxp.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/typec/tcpm/tcpm.c |    6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+--- a/drivers/usb/typec/tcpm/tcpm.c
++++ b/drivers/usb/typec/tcpm/tcpm.c
+@@ -2723,12 +2723,12 @@ static void tcpm_reset_port(struct tcpm_
+ static void tcpm_detach(struct tcpm_port *port)
+ {
+-      if (!port->attached)
+-              return;
+-
+       if (tcpm_port_is_disconnected(port))
+               port->hard_reset_count = 0;
++      if (!port->attached)
++              return;
++
+       tcpm_reset_port(port);
+ }
diff --git a/queue-5.4/usb-xhci-workaround-for-s3-issue-on-amd-snps-3.0-xhc.patch b/queue-5.4/usb-xhci-workaround-for-s3-issue-on-amd-snps-3.0-xhc.patch
new file mode 100644 (file)
index 0000000..85bf148
--- /dev/null
@@ -0,0 +1,81 @@
+From 2a632815683d2d34df52b701a36fe5ac6654e719 Mon Sep 17 00:00:00 2001
+From: Sandeep Singh <sandeep.singh@amd.com>
+Date: Wed, 28 Oct 2020 22:31:23 +0200
+Subject: usb: xhci: Workaround for S3 issue on AMD SNPS 3.0 xHC
+
+From: Sandeep Singh <sandeep.singh@amd.com>
+
+commit 2a632815683d2d34df52b701a36fe5ac6654e719 upstream.
+
+On some platform of AMD, S3 fails with HCE and SRE errors. To fix this,
+need to disable a bit which is enable in sparse controller.
+
+Cc: stable@vger.kernel.org #v4.19+
+Signed-off-by: Sanket Goswami <Sanket.Goswami@amd.com>
+Signed-off-by: Sandeep Singh <sandeep.singh@amd.com>
+Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
+Link: https://lore.kernel.org/r/20201028203124.375344-3-mathias.nyman@linux.intel.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/host/xhci-pci.c |   17 +++++++++++++++++
+ drivers/usb/host/xhci.h     |    1 +
+ 2 files changed, 18 insertions(+)
+
+--- a/drivers/usb/host/xhci-pci.c
++++ b/drivers/usb/host/xhci-pci.c
+@@ -21,6 +21,8 @@
+ #define SSIC_PORT_CFG2_OFFSET 0x30
+ #define PROG_DONE             (1 << 30)
+ #define SSIC_PORT_UNUSED      (1 << 31)
++#define SPARSE_DISABLE_BIT    17
++#define SPARSE_CNTL_ENABLE    0xC12C
+ /* Device for a quirk */
+ #define PCI_VENDOR_ID_FRESCO_LOGIC    0x1b73
+@@ -149,6 +151,9 @@ static void xhci_pci_quirks(struct devic
+           (pdev->device == 0x15e0 || pdev->device == 0x15e1))
+               xhci->quirks |= XHCI_SNPS_BROKEN_SUSPEND;
++      if (pdev->vendor == PCI_VENDOR_ID_AMD && pdev->device == 0x15e5)
++              xhci->quirks |= XHCI_DISABLE_SPARSE;
++
+       if (pdev->vendor == PCI_VENDOR_ID_AMD)
+               xhci->quirks |= XHCI_TRUST_TX_LENGTH;
+@@ -467,6 +472,15 @@ static void xhci_pme_quirk(struct usb_hc
+       readl(reg);
+ }
++static void xhci_sparse_control_quirk(struct usb_hcd *hcd)
++{
++      u32 reg;
++
++      reg = readl(hcd->regs + SPARSE_CNTL_ENABLE);
++      reg &= ~BIT(SPARSE_DISABLE_BIT);
++      writel(reg, hcd->regs + SPARSE_CNTL_ENABLE);
++}
++
+ static int xhci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup)
+ {
+       struct xhci_hcd *xhci = hcd_to_xhci(hcd);
+@@ -486,6 +500,9 @@ static int xhci_pci_suspend(struct usb_h
+       if (xhci->quirks & XHCI_SSIC_PORT_UNUSED)
+               xhci_ssic_port_unused_quirk(hcd, true);
++      if (xhci->quirks & XHCI_DISABLE_SPARSE)
++              xhci_sparse_control_quirk(hcd);
++
+       ret = xhci_suspend(xhci, do_wakeup);
+       if (ret && (xhci->quirks & XHCI_SSIC_PORT_UNUSED))
+               xhci_ssic_port_unused_quirk(hcd, false);
+--- a/drivers/usb/host/xhci.h
++++ b/drivers/usb/host/xhci.h
+@@ -1873,6 +1873,7 @@ struct xhci_hcd {
+ #define XHCI_DEFAULT_PM_RUNTIME_ALLOW BIT_ULL(33)
+ #define XHCI_RESET_PLL_ON_DISCONNECT  BIT_ULL(34)
+ #define XHCI_SNPS_BROKEN_SUSPEND    BIT_ULL(35)
++#define XHCI_DISABLE_SPARSE   BIT_ULL(38)
+       unsigned int            num_active_eps;
+       unsigned int            limit_active_eps;
diff --git a/queue-5.4/vt-keyboard-extend-func_buf_lock-to-readers.patch b/queue-5.4/vt-keyboard-extend-func_buf_lock-to-readers.patch
new file mode 100644 (file)
index 0000000..d542356
--- /dev/null
@@ -0,0 +1,94 @@
+From 82e61c3909db51d91b9d3e2071557b6435018b80 Mon Sep 17 00:00:00 2001
+From: Jiri Slaby <jirislaby@kernel.org>
+Date: Mon, 19 Oct 2020 10:55:17 +0200
+Subject: vt: keyboard, extend func_buf_lock to readers
+
+From: Jiri Slaby <jslaby@suse.cz>
+
+commit 82e61c3909db51d91b9d3e2071557b6435018b80 upstream.
+
+Both read-side users of func_table/func_buf need locking. Without that,
+one can easily confuse the code by repeatedly setting altering strings
+like:
+while (1)
+       for (a = 0; a < 2; a++) {
+               struct kbsentry kbs = {};
+               strcpy((char *)kbs.kb_string, a ? ".\n" : "88888\n");
+               ioctl(fd, KDSKBSENT, &kbs);
+       }
+
+When that program runs, one can get unexpected output by holding F1
+(note the unxpected period on the last line):
+.
+88888
+.8888
+
+So protect all accesses to 'func_table' (and func_buf) by preexisting
+'func_buf_lock'.
+
+It is easy in 'k_fn' handler as 'puts_queue' is expected not to sleep.
+On the other hand, KDGKBSENT needs a local (atomic) copy of the string
+because copy_to_user can sleep. Use already allocated, but unused
+'kbs->kb_string' for that purpose.
+
+Note that the program above needs at least CAP_SYS_TTY_CONFIG.
+
+This depends on the previous patch and on the func_buf_lock lock added
+in commit 46ca3f735f34 (tty/vt: fix write/write race in ioctl(KDSKBSENT)
+handler) in 5.2.
+
+Likely fixes CVE-2020-25656.
+
+Cc: <stable@vger.kernel.org>
+Reported-by: Minh Yuan <yuanmingbuaa@gmail.com>
+Signed-off-by: Jiri Slaby <jslaby@suse.cz>
+Link: https://lore.kernel.org/r/20201019085517.10176-2-jslaby@suse.cz
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/tty/vt/keyboard.c |   17 +++++++++++++----
+ 1 file changed, 13 insertions(+), 4 deletions(-)
+
+--- a/drivers/tty/vt/keyboard.c
++++ b/drivers/tty/vt/keyboard.c
+@@ -742,8 +742,13 @@ static void k_fn(struct vc_data *vc, uns
+               return;
+       if ((unsigned)value < ARRAY_SIZE(func_table)) {
++              unsigned long flags;
++
++              spin_lock_irqsave(&func_buf_lock, flags);
+               if (func_table[value])
+                       puts_queue(vc, func_table[value]);
++              spin_unlock_irqrestore(&func_buf_lock, flags);
++
+       } else
+               pr_err("k_fn called with value=%d\n", value);
+ }
+@@ -1990,7 +1995,7 @@ out:
+ #undef s
+ #undef v
+-/* FIXME: This one needs untangling and locking */
++/* FIXME: This one needs untangling */
+ int vt_do_kdgkb_ioctl(int cmd, struct kbsentry __user *user_kdgkb, int perm)
+ {
+       struct kbsentry *kbs;
+@@ -2022,10 +2027,14 @@ int vt_do_kdgkb_ioctl(int cmd, struct kb
+       switch (cmd) {
+       case KDGKBSENT: {
+               /* size should have been a struct member */
+-              unsigned char *from = func_table[i] ? : "";
++              ssize_t len = sizeof(user_kdgkb->kb_string);
++
++              spin_lock_irqsave(&func_buf_lock, flags);
++              len = strlcpy(kbs->kb_string, func_table[i] ? : "", len);
++              spin_unlock_irqrestore(&func_buf_lock, flags);
+-              ret = copy_to_user(user_kdgkb->kb_string, from,
+-                              strlen(from) + 1) ? -EFAULT : 0;
++              ret = copy_to_user(user_kdgkb->kb_string, kbs->kb_string,
++                              len + 1) ? -EFAULT : 0;
+               goto reterr;
+       }
diff --git a/queue-5.4/vt-keyboard-simplify-vt_kdgkbsent.patch b/queue-5.4/vt-keyboard-simplify-vt_kdgkbsent.patch
new file mode 100644 (file)
index 0000000..8e119c4
--- /dev/null
@@ -0,0 +1,73 @@
+From 6ca03f90527e499dd5e32d6522909e2ad390896b Mon Sep 17 00:00:00 2001
+From: Jiri Slaby <jirislaby@kernel.org>
+Date: Mon, 19 Oct 2020 10:55:16 +0200
+Subject: vt: keyboard, simplify vt_kdgkbsent
+
+From: Jiri Slaby <jslaby@suse.cz>
+
+commit 6ca03f90527e499dd5e32d6522909e2ad390896b upstream.
+
+Use 'strlen' of the string, add one for NUL terminator and simply do
+'copy_to_user' instead of the explicit 'for' loop. This makes the
+KDGKBSENT case more compact.
+
+The only thing we need to take care about is NULL 'func_table[i]'. Use
+an empty string in that case.
+
+The original check for overflow could never trigger as the func_buf
+strings are always shorter or equal to 'struct kbsentry's.
+
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Jiri Slaby <jslaby@suse.cz>
+Link: https://lore.kernel.org/r/20201019085517.10176-1-jslaby@suse.cz
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/tty/vt/keyboard.c |   28 +++++++++-------------------
+ 1 file changed, 9 insertions(+), 19 deletions(-)
+
+--- a/drivers/tty/vt/keyboard.c
++++ b/drivers/tty/vt/keyboard.c
+@@ -1994,9 +1994,7 @@ out:
+ int vt_do_kdgkb_ioctl(int cmd, struct kbsentry __user *user_kdgkb, int perm)
+ {
+       struct kbsentry *kbs;
+-      char *p;
+       u_char *q;
+-      u_char __user *up;
+       int sz, fnw_sz;
+       int delta;
+       char *first_free, *fj, *fnw;
+@@ -2022,23 +2020,15 @@ int vt_do_kdgkb_ioctl(int cmd, struct kb
+       i = kbs->kb_func;
+       switch (cmd) {
+-      case KDGKBSENT:
+-              sz = sizeof(kbs->kb_string) - 1; /* sz should have been
+-                                                a struct member */
+-              up = user_kdgkb->kb_string;
+-              p = func_table[i];
+-              if(p)
+-                      for ( ; *p && sz; p++, sz--)
+-                              if (put_user(*p, up++)) {
+-                                      ret = -EFAULT;
+-                                      goto reterr;
+-                              }
+-              if (put_user('\0', up)) {
+-                      ret = -EFAULT;
+-                      goto reterr;
+-              }
+-              kfree(kbs);
+-              return ((p && *p) ? -EOVERFLOW : 0);
++      case KDGKBSENT: {
++              /* size should have been a struct member */
++              unsigned char *from = func_table[i] ? : "";
++
++              ret = copy_to_user(user_kdgkb->kb_string, from,
++                              strlen(from) + 1) ? -EFAULT : 0;
++
++              goto reterr;
++      }
+       case KDSKBSENT:
+               if (!perm) {
+                       ret = -EPERM;
diff --git a/queue-5.4/w1-mxc_w1-fix-timeout-resolution-problem-leading-to-bus-error.patch b/queue-5.4/w1-mxc_w1-fix-timeout-resolution-problem-leading-to-bus-error.patch
new file mode 100644 (file)
index 0000000..2c1fffb
--- /dev/null
@@ -0,0 +1,90 @@
+From c9723750a699c3bd465493ac2be8992b72ccb105 Mon Sep 17 00:00:00 2001
+From: Martin Fuzzey <martin.fuzzey@flowbird.group>
+Date: Wed, 30 Sep 2020 10:36:46 +0200
+Subject: w1: mxc_w1: Fix timeout resolution problem leading to bus error
+
+From: Martin Fuzzey <martin.fuzzey@flowbird.group>
+
+commit c9723750a699c3bd465493ac2be8992b72ccb105 upstream.
+
+On my platform (i.MX53) bus access sometimes fails with
+       w1_search: max_slave_count 64 reached, will continue next search.
+
+The reason is the use of jiffies to implement a 200us timeout in
+mxc_w1_ds2_touch_bit().
+On some platforms the jiffies timer resolution is insufficient for this.
+
+Fix by replacing jiffies by ktime_get().
+
+For consistency apply the same change to the other use of jiffies in
+mxc_w1_ds2_reset_bus().
+
+Fixes: f80b2581a706 ("w1: mxc_w1: Optimize mxc_w1_ds2_touch_bit()")
+Cc: stable <stable@vger.kernel.org>
+Signed-off-by: Martin Fuzzey <martin.fuzzey@flowbird.group>
+Link: https://lore.kernel.org/r/1601455030-6607-1-git-send-email-martin.fuzzey@flowbird.group
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/w1/masters/mxc_w1.c |   14 +++++++-------
+ 1 file changed, 7 insertions(+), 7 deletions(-)
+
+--- a/drivers/w1/masters/mxc_w1.c
++++ b/drivers/w1/masters/mxc_w1.c
+@@ -7,7 +7,7 @@
+ #include <linux/clk.h>
+ #include <linux/delay.h>
+ #include <linux/io.h>
+-#include <linux/jiffies.h>
++#include <linux/ktime.h>
+ #include <linux/module.h>
+ #include <linux/mod_devicetable.h>
+ #include <linux/platform_device.h>
+@@ -40,12 +40,12 @@ struct mxc_w1_device {
+ static u8 mxc_w1_ds2_reset_bus(void *data)
+ {
+       struct mxc_w1_device *dev = data;
+-      unsigned long timeout;
++      ktime_t timeout;
+       writeb(MXC_W1_CONTROL_RPP, dev->regs + MXC_W1_CONTROL);
+       /* Wait for reset sequence 511+512us, use 1500us for sure */
+-      timeout = jiffies + usecs_to_jiffies(1500);
++      timeout = ktime_add_us(ktime_get(), 1500);
+       udelay(511 + 512);
+@@ -55,7 +55,7 @@ static u8 mxc_w1_ds2_reset_bus(void *dat
+               /* PST bit is valid after the RPP bit is self-cleared */
+               if (!(ctrl & MXC_W1_CONTROL_RPP))
+                       return !(ctrl & MXC_W1_CONTROL_PST);
+-      } while (time_is_after_jiffies(timeout));
++      } while (ktime_before(ktime_get(), timeout));
+       return 1;
+ }
+@@ -68,12 +68,12 @@ static u8 mxc_w1_ds2_reset_bus(void *dat
+ static u8 mxc_w1_ds2_touch_bit(void *data, u8 bit)
+ {
+       struct mxc_w1_device *dev = data;
+-      unsigned long timeout;
++      ktime_t timeout;
+       writeb(MXC_W1_CONTROL_WR(bit), dev->regs + MXC_W1_CONTROL);
+       /* Wait for read/write bit (60us, Max 120us), use 200us for sure */
+-      timeout = jiffies + usecs_to_jiffies(200);
++      timeout = ktime_add_us(ktime_get(), 200);
+       udelay(60);
+@@ -83,7 +83,7 @@ static u8 mxc_w1_ds2_touch_bit(void *dat
+               /* RDST bit is valid after the WR1/RD bit is self-cleared */
+               if (!(ctrl & MXC_W1_CONTROL_WR(bit)))
+                       return !!(ctrl & MXC_W1_CONTROL_RDST);
+-      } while (time_is_after_jiffies(timeout));
++      } while (ktime_before(ktime_get(), timeout));
+       return 0;
+ }