From: Greg Kroah-Hartman Date: Wed, 26 Sep 2018 12:18:19 +0000 (+0200) Subject: 4.18-stable patches X-Git-Tag: v4.18.11~18 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=9d09275eeaeade9f771c45c72369a2e6620fa2bc;p=thirdparty%2Fkernel%2Fstable-queue.git 4.18-stable patches added patches: bpf-verifier-disallow-pointer-subtraction.patch drm-amdgpu-add-new-polaris-pci-id.patch drm-atomic-use-drm_drv_uses_atomic_modeset-for-debugfs-creation.patch drm-i915-bdw-increase-ips-disable-timeout-to-100ms.patch drm-nouveau-drm-nouveau-don-t-forget-to-cancel-hpd_work-on-suspend-unload.patch drm-nouveau-drm-nouveau-fix-bogus-drm_kms_helper_poll_enable-placement.patch drm-nouveau-drm-nouveau-fix-deadlock-with-fb_helper-with-async-rpm-requests.patch drm-nouveau-drm-nouveau-prevent-handling-acpi-hpd-events-too-early.patch drm-nouveau-drm-nouveau-use-pm_runtime_get_noresume-in-connector_detect.patch drm-nouveau-fix-deadlocks-in-nouveau_connector_detect.patch drm-nouveau-only-write-dp_mstm_ctrl-when-needed.patch drm-nouveau-remove-duplicate-poll_enable-in-pmops_runtime_suspend.patch drm-nouveau-reset-mst-branching-unit-before-enabling.patch drm-udl-destroy-framebuffer-only-if-it-was-initialized.patch drm-vc4-fix-the-no-scaling-case-on-multi-planar-yuv-formats.patch ext4-avoid-arithemetic-overflow-that-can-trigger-a-bug.patch ext4-avoid-divide-by-zero-fault-when-deleting-corrupted-inline-directories.patch ext4-check-to-make-sure-the-rename-2-s-destination-is-not-freed.patch ext4-dax-add-ext4_bmap-to-ext4_dax_aops.patch ext4-dax-set-ext4_dax_aops-for-dax-files.patch ext4-don-t-mark-mmp-buffer-head-dirty.patch ext4-fix-online-resize-s-handling-of-a-too-small-final-block-group.patch ext4-fix-online-resizing-for-bigalloc-file-systems-with-a-1k-block-size.patch ext4-recalucate-superblock-checksum-after-updating-free-blocks-inodes.patch ext4-show-test_dummy_encryption-mount-option-in-proc-mounts.patch libata-mask-swap-internal-and-hardware-tag.patch ocfs2-fix-ocfs2-read-block-panic.patch revert-rpmsg-core-add-support-to-power-domains-for.patch revert-uapi-linux-keyctl.h-don-t-use-c-reserved-keyword-as-a-struct-member-name.patch revert-ubifs-xattr-don-t-operate-on-deleted-inodes.patch scsi-target-iscsi-use-bin2hex-instead-of-a-re-implementation.patch scsi-target-iscsi-use-hex2bin-instead-of-a-re-implementation.patch tty-vt_ioctl-fix-potential-spectre-v1.patch --- diff --git a/queue-4.18/bpf-verifier-disallow-pointer-subtraction.patch b/queue-4.18/bpf-verifier-disallow-pointer-subtraction.patch new file mode 100644 index 00000000000..588ccb51fe7 --- /dev/null +++ b/queue-4.18/bpf-verifier-disallow-pointer-subtraction.patch @@ -0,0 +1,34 @@ +From dd066823db2ac4e22f721ec85190817b58059a54 Mon Sep 17 00:00:00 2001 +From: Alexei Starovoitov +Date: Wed, 12 Sep 2018 14:06:10 -0700 +Subject: bpf/verifier: disallow pointer subtraction + +From: Alexei Starovoitov + +commit dd066823db2ac4e22f721ec85190817b58059a54 upstream. + +Subtraction of pointers was accidentally allowed for unpriv programs +by commit 82abbf8d2fc4. Revert that part of commit. + +Fixes: 82abbf8d2fc4 ("bpf: do not allow root to mangle valid pointers") +Reported-by: Jann Horn +Acked-by: Daniel Borkmann +Signed-off-by: Alexei Starovoitov +Signed-off-by: Daniel Borkmann +Signed-off-by: Greg Kroah-Hartman + +--- + kernel/bpf/verifier.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/kernel/bpf/verifier.c ++++ b/kernel/bpf/verifier.c +@@ -3132,7 +3132,7 @@ static int adjust_reg_min_max_vals(struc + * an arbitrary scalar. Disallow all math except + * pointer subtraction + */ +- if (opcode == BPF_SUB){ ++ if (opcode == BPF_SUB && env->allow_ptr_leaks) { + mark_reg_unknown(env, regs, insn->dst_reg); + return 0; + } diff --git a/queue-4.18/drm-amdgpu-add-new-polaris-pci-id.patch b/queue-4.18/drm-amdgpu-add-new-polaris-pci-id.patch new file mode 100644 index 00000000000..a87dabca71e --- /dev/null +++ b/queue-4.18/drm-amdgpu-add-new-polaris-pci-id.patch @@ -0,0 +1,54 @@ +From 30f3984ede683b98a4e8096e200df78bf0609b4f Mon Sep 17 00:00:00 2001 +From: Alex Deucher +Date: Tue, 18 Sep 2018 15:28:24 -0500 +Subject: drm/amdgpu: add new polaris pci id + +From: Alex Deucher + +commit 30f3984ede683b98a4e8096e200df78bf0609b4f upstream. + +Add new pci id. + +Reviewed-by: Rex Zhu +Signed-off-by: Alex Deucher +Cc: stable@vger.kernel.org +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c | 14 ++++++++------ + drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 1 + + 2 files changed, 9 insertions(+), 6 deletions(-) + +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c +@@ -367,12 +367,14 @@ static int amdgpu_cgs_get_firmware_info( + break; + case CHIP_POLARIS10: + if (type == CGS_UCODE_ID_SMU) { +- if ((adev->pdev->device == 0x67df) && +- ((adev->pdev->revision == 0xe0) || +- (adev->pdev->revision == 0xe3) || +- (adev->pdev->revision == 0xe4) || +- (adev->pdev->revision == 0xe5) || +- (adev->pdev->revision == 0xe7) || ++ if (((adev->pdev->device == 0x67df) && ++ ((adev->pdev->revision == 0xe0) || ++ (adev->pdev->revision == 0xe3) || ++ (adev->pdev->revision == 0xe4) || ++ (adev->pdev->revision == 0xe5) || ++ (adev->pdev->revision == 0xe7) || ++ (adev->pdev->revision == 0xef))) || ++ ((adev->pdev->device == 0x6fdf) && + (adev->pdev->revision == 0xef))) { + info->is_kicker = true; + strcpy(fw_name, "amdgpu/polaris10_k_smc.bin"); +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +@@ -532,6 +532,7 @@ static const struct pci_device_id pciidl + {0x1002, 0x67CA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS10}, + {0x1002, 0x67CC, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS10}, + {0x1002, 0x67CF, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS10}, ++ {0x1002, 0x6FDF, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS10}, + /* Polaris12 */ + {0x1002, 0x6980, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS12}, + {0x1002, 0x6981, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS12}, diff --git a/queue-4.18/drm-atomic-use-drm_drv_uses_atomic_modeset-for-debugfs-creation.patch b/queue-4.18/drm-atomic-use-drm_drv_uses_atomic_modeset-for-debugfs-creation.patch new file mode 100644 index 00000000000..06b972cb53f --- /dev/null +++ b/queue-4.18/drm-atomic-use-drm_drv_uses_atomic_modeset-for-debugfs-creation.patch @@ -0,0 +1,50 @@ +From 3c499ea0c662e2f38aafbd4f516b08aab8cfa0e5 Mon Sep 17 00:00:00 2001 +From: Lyude Paul +Date: Mon, 17 Sep 2018 13:37:33 -0400 +Subject: drm/atomic: Use drm_drv_uses_atomic_modeset() for debugfs creation + +From: Lyude Paul + +commit 3c499ea0c662e2f38aafbd4f516b08aab8cfa0e5 upstream. + +As pointed out by Daniel Vetter, we should be usinng +drm_drv_uses_atomic_modeset() for determining whether or not we want to +make the debugfs nodes for atomic instead of checking DRIVER_ATOMIC, as +the former isn't an accurate representation of whether or not the driver +is actually using atomic modesetting internally (even though it might +not be exposing atomic capabilities). + +Signed-off-by: Lyude Paul +Cc: Daniel Vetter +Cc: stable@vger.kernel.org +Reviewed-by: Sean Paul +Link: https://patchwork.freedesktop.org/patch/msgid/20180917173733.21293-1-lyude@redhat.com +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/drm_atomic.c | 2 +- + drivers/gpu/drm/drm_debugfs.c | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/gpu/drm/drm_atomic.c ++++ b/drivers/gpu/drm/drm_atomic.c +@@ -1838,7 +1838,7 @@ static void __drm_state_dump(struct drm_ + struct drm_connector *connector; + struct drm_connector_list_iter conn_iter; + +- if (!drm_core_check_feature(dev, DRIVER_ATOMIC)) ++ if (!drm_drv_uses_atomic_modeset(dev)) + return; + + list_for_each_entry(plane, &config->plane_list, head) { +--- a/drivers/gpu/drm/drm_debugfs.c ++++ b/drivers/gpu/drm/drm_debugfs.c +@@ -150,7 +150,7 @@ int drm_debugfs_init(struct drm_minor *m + return ret; + } + +- if (drm_core_check_feature(dev, DRIVER_ATOMIC)) { ++ if (drm_drv_uses_atomic_modeset(dev)) { + ret = drm_atomic_debugfs_init(minor); + if (ret) { + DRM_ERROR("Failed to create atomic debugfs files\n"); diff --git a/queue-4.18/drm-i915-bdw-increase-ips-disable-timeout-to-100ms.patch b/queue-4.18/drm-i915-bdw-increase-ips-disable-timeout-to-100ms.patch new file mode 100644 index 00000000000..86f7be2d7d4 --- /dev/null +++ b/queue-4.18/drm-i915-bdw-increase-ips-disable-timeout-to-100ms.patch @@ -0,0 +1,51 @@ +From 92a6803149465e2339f8f7f8f6415d75be80073d Mon Sep 17 00:00:00 2001 +From: Imre Deak +Date: Wed, 5 Sep 2018 13:00:05 +0300 +Subject: drm/i915/bdw: Increase IPS disable timeout to 100ms +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Imre Deak + +commit 92a6803149465e2339f8f7f8f6415d75be80073d upstream. + +During IPS disabling the current 42ms timeout value leads to occasional +timeouts, increase it to 100ms which seems to get rid of the problem. + +References: https://bugs.freedesktop.org/show_bug.cgi?id=107494 +Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=107562 +Reported-by: Diego Viola +Tested-by: Diego Viola +Cc: Diego Viola +Cc: +Signed-off-by: Imre Deak +Reviewed-by: Ville Syrjälä +Link: https://patchwork.freedesktop.org/patch/msgid/20180905100005.7663-1-imre.deak@intel.com +(cherry picked from commit acb3ef0ee40ea657280a4a11d9f60eb2937c0dca) +Signed-off-by: Rodrigo Vivi +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/i915/intel_display.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +--- a/drivers/gpu/drm/i915/intel_display.c ++++ b/drivers/gpu/drm/i915/intel_display.c +@@ -5062,10 +5062,14 @@ void hsw_disable_ips(const struct intel_ + mutex_lock(&dev_priv->pcu_lock); + WARN_ON(sandybridge_pcode_write(dev_priv, DISPLAY_IPS_CONTROL, 0)); + mutex_unlock(&dev_priv->pcu_lock); +- /* wait for pcode to finish disabling IPS, which may take up to 42ms */ ++ /* ++ * Wait for PCODE to finish disabling IPS. The BSpec specified ++ * 42ms timeout value leads to occasional timeouts so use 100ms ++ * instead. ++ */ + if (intel_wait_for_register(dev_priv, + IPS_CTL, IPS_ENABLE, 0, +- 42)) ++ 100)) + DRM_ERROR("Timed out waiting for IPS disable\n"); + } else { + I915_WRITE(IPS_CTL, 0); diff --git a/queue-4.18/drm-nouveau-drm-nouveau-don-t-forget-to-cancel-hpd_work-on-suspend-unload.patch b/queue-4.18/drm-nouveau-drm-nouveau-don-t-forget-to-cancel-hpd_work-on-suspend-unload.patch new file mode 100644 index 00000000000..0cda3bf3666 --- /dev/null +++ b/queue-4.18/drm-nouveau-drm-nouveau-don-t-forget-to-cancel-hpd_work-on-suspend-unload.patch @@ -0,0 +1,82 @@ +From 2f7ca781fd382cf8dde73ed36dfdd93fd05b3332 Mon Sep 17 00:00:00 2001 +From: Lyude Paul +Date: Tue, 7 Aug 2018 17:32:48 -0400 +Subject: drm/nouveau/drm/nouveau: Don't forget to cancel hpd_work on suspend/unload + +From: Lyude Paul + +commit 2f7ca781fd382cf8dde73ed36dfdd93fd05b3332 upstream. + +Currently, there's nothing in nouveau that actually cancels this work +struct. So, cancel it on suspend/unload. Otherwise, if we're unlucky +enough hpd_work might try to keep running up until the system is +suspended. + +Signed-off-by: Lyude Paul +Cc: stable@vger.kernel.org +Signed-off-by: Ben Skeggs +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/nouveau/nouveau_display.c | 9 ++++++--- + drivers/gpu/drm/nouveau/nouveau_display.h | 2 +- + drivers/gpu/drm/nouveau/nouveau_drm.c | 2 +- + 3 files changed, 8 insertions(+), 5 deletions(-) + +--- a/drivers/gpu/drm/nouveau/nouveau_display.c ++++ b/drivers/gpu/drm/nouveau/nouveau_display.c +@@ -425,7 +425,7 @@ nouveau_display_init(struct drm_device * + } + + void +-nouveau_display_fini(struct drm_device *dev, bool suspend) ++nouveau_display_fini(struct drm_device *dev, bool suspend, bool runtime) + { + struct nouveau_display *disp = nouveau_display(dev); + struct nouveau_drm *drm = nouveau_drm(dev); +@@ -450,6 +450,9 @@ nouveau_display_fini(struct drm_device * + } + drm_connector_list_iter_end(&conn_iter); + ++ if (!runtime) ++ cancel_work_sync(&drm->hpd_work); ++ + drm_kms_helper_poll_disable(dev); + disp->fini(dev); + } +@@ -618,11 +621,11 @@ nouveau_display_suspend(struct drm_devic + } + } + +- nouveau_display_fini(dev, true); ++ nouveau_display_fini(dev, true, runtime); + return 0; + } + +- nouveau_display_fini(dev, true); ++ nouveau_display_fini(dev, true, runtime); + + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + struct nouveau_framebuffer *nouveau_fb; +--- a/drivers/gpu/drm/nouveau/nouveau_display.h ++++ b/drivers/gpu/drm/nouveau/nouveau_display.h +@@ -62,7 +62,7 @@ nouveau_display(struct drm_device *dev) + int nouveau_display_create(struct drm_device *dev); + void nouveau_display_destroy(struct drm_device *dev); + int nouveau_display_init(struct drm_device *dev); +-void nouveau_display_fini(struct drm_device *dev, bool suspend); ++void nouveau_display_fini(struct drm_device *dev, bool suspend, bool runtime); + int nouveau_display_suspend(struct drm_device *dev, bool runtime); + void nouveau_display_resume(struct drm_device *dev, bool runtime); + int nouveau_display_vblank_enable(struct drm_device *, unsigned int); +--- a/drivers/gpu/drm/nouveau/nouveau_drm.c ++++ b/drivers/gpu/drm/nouveau/nouveau_drm.c +@@ -629,7 +629,7 @@ nouveau_drm_unload(struct drm_device *de + nouveau_debugfs_fini(drm); + + if (dev->mode_config.num_crtc) +- nouveau_display_fini(dev, false); ++ nouveau_display_fini(dev, false, false); + nouveau_display_destroy(dev); + + nouveau_bios_takedown(dev); diff --git a/queue-4.18/drm-nouveau-drm-nouveau-fix-bogus-drm_kms_helper_poll_enable-placement.patch b/queue-4.18/drm-nouveau-drm-nouveau-fix-bogus-drm_kms_helper_poll_enable-placement.patch new file mode 100644 index 00000000000..b4ec4ff746c --- /dev/null +++ b/queue-4.18/drm-nouveau-drm-nouveau-fix-bogus-drm_kms_helper_poll_enable-placement.patch @@ -0,0 +1,73 @@ +From d77ef138ff572409ab93d492e5e6c826ee6fb21d Mon Sep 17 00:00:00 2001 +From: Lyude Paul +Date: Wed, 15 Aug 2018 15:00:11 -0400 +Subject: drm/nouveau/drm/nouveau: Fix bogus drm_kms_helper_poll_enable() placement + +From: Lyude Paul + +commit d77ef138ff572409ab93d492e5e6c826ee6fb21d upstream. + +Turns out this part is my fault for not noticing when reviewing +9a2eba337cace ("drm/nouveau: Fix drm poll_helper handling"). Currently +we call drm_kms_helper_poll_enable() from nouveau_display_hpd_work(). +This makes basically no sense however, because that means we're calling +drm_kms_helper_poll_enable() every time we schedule the hotplug +detection work. This is also against the advice mentioned in +drm_kms_helper_poll_enable()'s documentation: + + Note that calls to enable and disable polling must be strictly ordered, + which is automatically the case when they're only call from + suspend/resume callbacks. + +Of course, hotplugs can't really be ordered. They could even happen +immediately after we called drm_kms_helper_poll_disable() in +nouveau_display_fini(), which can lead to all sorts of issues. + +Additionally; enabling polling /after/ we call +drm_helper_hpd_irq_event() could also mean that we'd miss a hotplug +event anyway, since drm_helper_hpd_irq_event() wouldn't bother trying to +probe connectors so long as polling is disabled. + +So; simply move this back into nouveau_display_init() again. The race +condition that both of these patches attempted to work around has +already been fixed properly in + + d61a5c106351 ("drm/nouveau: Fix deadlock on runtime suspend") + +Fixes: 9a2eba337cace ("drm/nouveau: Fix drm poll_helper handling") +Signed-off-by: Lyude Paul +Acked-by: Karol Herbst +Acked-by: Daniel Vetter +Cc: Lukas Wunner +Cc: Peter Ujfalusi +Cc: stable@vger.kernel.org +Signed-off-by: Ben Skeggs +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/nouveau/nouveau_display.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +--- a/drivers/gpu/drm/nouveau/nouveau_display.c ++++ b/drivers/gpu/drm/nouveau/nouveau_display.c +@@ -355,8 +355,6 @@ nouveau_display_hpd_work(struct work_str + pm_runtime_get_sync(drm->dev->dev); + + drm_helper_hpd_irq_event(drm->dev); +- /* enable polling for external displays */ +- drm_kms_helper_poll_enable(drm->dev); + + pm_runtime_mark_last_busy(drm->dev->dev); + pm_runtime_put_sync(drm->dev->dev); +@@ -411,6 +409,11 @@ nouveau_display_init(struct drm_device * + if (ret) + return ret; + ++ /* enable connector detection and polling for connectors without HPD ++ * support ++ */ ++ drm_kms_helper_poll_enable(dev); ++ + /* enable hotplug interrupts */ + drm_connector_list_iter_begin(dev, &conn_iter); + nouveau_for_each_non_mst_connector_iter(connector, &conn_iter) { diff --git a/queue-4.18/drm-nouveau-drm-nouveau-fix-deadlock-with-fb_helper-with-async-rpm-requests.patch b/queue-4.18/drm-nouveau-drm-nouveau-fix-deadlock-with-fb_helper-with-async-rpm-requests.patch new file mode 100644 index 00000000000..3c14373424d --- /dev/null +++ b/queue-4.18/drm-nouveau-drm-nouveau-fix-deadlock-with-fb_helper-with-async-rpm-requests.patch @@ -0,0 +1,320 @@ +From 7fec8f5379fb6eddabc0aaef6d2304c366808f97 Mon Sep 17 00:00:00 2001 +From: Lyude Paul +Date: Wed, 15 Aug 2018 15:00:13 -0400 +Subject: drm/nouveau/drm/nouveau: Fix deadlock with fb_helper with async RPM requests + +From: Lyude Paul + +commit 7fec8f5379fb6eddabc0aaef6d2304c366808f97 upstream. + +Currently, nouveau uses the generic drm_fb_helper_output_poll_changed() +function provided by DRM as it's output_poll_changed callback. +Unfortunately however, this function doesn't grab runtime PM references +early enough and even if it did-we can't block waiting for the device to +resume in output_poll_changed() since it's very likely that we'll need +to grab the fb_helper lock at some point during the runtime resume +process. This currently results in deadlocking like so: + +[ 246.669625] INFO: task kworker/4:0:37 blocked for more than 120 seconds. +[ 246.673398] Not tainted 4.18.0-rc5Lyude-Test+ #2 +[ 246.675271] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message. +[ 246.676527] kworker/4:0 D 0 37 2 0x80000000 +[ 246.677580] Workqueue: events output_poll_execute [drm_kms_helper] +[ 246.678704] Call Trace: +[ 246.679753] __schedule+0x322/0xaf0 +[ 246.680916] schedule+0x33/0x90 +[ 246.681924] schedule_preempt_disabled+0x15/0x20 +[ 246.683023] __mutex_lock+0x569/0x9a0 +[ 246.684035] ? kobject_uevent_env+0x117/0x7b0 +[ 246.685132] ? drm_fb_helper_hotplug_event.part.28+0x20/0xb0 [drm_kms_helper] +[ 246.686179] mutex_lock_nested+0x1b/0x20 +[ 246.687278] ? mutex_lock_nested+0x1b/0x20 +[ 246.688307] drm_fb_helper_hotplug_event.part.28+0x20/0xb0 [drm_kms_helper] +[ 246.689420] drm_fb_helper_output_poll_changed+0x23/0x30 [drm_kms_helper] +[ 246.690462] drm_kms_helper_hotplug_event+0x2a/0x30 [drm_kms_helper] +[ 246.691570] output_poll_execute+0x198/0x1c0 [drm_kms_helper] +[ 246.692611] process_one_work+0x231/0x620 +[ 246.693725] worker_thread+0x214/0x3a0 +[ 246.694756] kthread+0x12b/0x150 +[ 246.695856] ? wq_pool_ids_show+0x140/0x140 +[ 246.696888] ? kthread_create_worker_on_cpu+0x70/0x70 +[ 246.697998] ret_from_fork+0x3a/0x50 +[ 246.699034] INFO: task kworker/0:1:60 blocked for more than 120 seconds. +[ 246.700153] Not tainted 4.18.0-rc5Lyude-Test+ #2 +[ 246.701182] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message. +[ 246.702278] kworker/0:1 D 0 60 2 0x80000000 +[ 246.703293] Workqueue: pm pm_runtime_work +[ 246.704393] Call Trace: +[ 246.705403] __schedule+0x322/0xaf0 +[ 246.706439] ? wait_for_completion+0x104/0x190 +[ 246.707393] schedule+0x33/0x90 +[ 246.708375] schedule_timeout+0x3a5/0x590 +[ 246.709289] ? mark_held_locks+0x58/0x80 +[ 246.710208] ? _raw_spin_unlock_irq+0x2c/0x40 +[ 246.711222] ? wait_for_completion+0x104/0x190 +[ 246.712134] ? trace_hardirqs_on_caller+0xf4/0x190 +[ 246.713094] ? wait_for_completion+0x104/0x190 +[ 246.713964] wait_for_completion+0x12c/0x190 +[ 246.714895] ? wake_up_q+0x80/0x80 +[ 246.715727] ? get_work_pool+0x90/0x90 +[ 246.716649] flush_work+0x1c9/0x280 +[ 246.717483] ? flush_workqueue_prep_pwqs+0x1b0/0x1b0 +[ 246.718442] __cancel_work_timer+0x146/0x1d0 +[ 246.719247] cancel_delayed_work_sync+0x13/0x20 +[ 246.720043] drm_kms_helper_poll_disable+0x1f/0x30 [drm_kms_helper] +[ 246.721123] nouveau_pmops_runtime_suspend+0x3d/0xb0 [nouveau] +[ 246.721897] pci_pm_runtime_suspend+0x6b/0x190 +[ 246.722825] ? pci_has_legacy_pm_support+0x70/0x70 +[ 246.723737] __rpm_callback+0x7a/0x1d0 +[ 246.724721] ? pci_has_legacy_pm_support+0x70/0x70 +[ 246.725607] rpm_callback+0x24/0x80 +[ 246.726553] ? pci_has_legacy_pm_support+0x70/0x70 +[ 246.727376] rpm_suspend+0x142/0x6b0 +[ 246.728185] pm_runtime_work+0x97/0xc0 +[ 246.728938] process_one_work+0x231/0x620 +[ 246.729796] worker_thread+0x44/0x3a0 +[ 246.730614] kthread+0x12b/0x150 +[ 246.731395] ? wq_pool_ids_show+0x140/0x140 +[ 246.732202] ? kthread_create_worker_on_cpu+0x70/0x70 +[ 246.732878] ret_from_fork+0x3a/0x50 +[ 246.733768] INFO: task kworker/4:2:422 blocked for more than 120 seconds. +[ 246.734587] Not tainted 4.18.0-rc5Lyude-Test+ #2 +[ 246.735393] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message. +[ 246.736113] kworker/4:2 D 0 422 2 0x80000080 +[ 246.736789] Workqueue: events_long drm_dp_mst_link_probe_work [drm_kms_helper] +[ 246.737665] Call Trace: +[ 246.738490] __schedule+0x322/0xaf0 +[ 246.739250] schedule+0x33/0x90 +[ 246.739908] rpm_resume+0x19c/0x850 +[ 246.740750] ? finish_wait+0x90/0x90 +[ 246.741541] __pm_runtime_resume+0x4e/0x90 +[ 246.742370] nv50_disp_atomic_commit+0x31/0x210 [nouveau] +[ 246.743124] drm_atomic_commit+0x4a/0x50 [drm] +[ 246.743775] restore_fbdev_mode_atomic+0x1c8/0x240 [drm_kms_helper] +[ 246.744603] restore_fbdev_mode+0x31/0x140 [drm_kms_helper] +[ 246.745373] drm_fb_helper_restore_fbdev_mode_unlocked+0x54/0xb0 [drm_kms_helper] +[ 246.746220] drm_fb_helper_set_par+0x2d/0x50 [drm_kms_helper] +[ 246.746884] drm_fb_helper_hotplug_event.part.28+0x96/0xb0 [drm_kms_helper] +[ 246.747675] drm_fb_helper_output_poll_changed+0x23/0x30 [drm_kms_helper] +[ 246.748544] drm_kms_helper_hotplug_event+0x2a/0x30 [drm_kms_helper] +[ 246.749439] nv50_mstm_hotplug+0x15/0x20 [nouveau] +[ 246.750111] drm_dp_send_link_address+0x177/0x1c0 [drm_kms_helper] +[ 246.750764] drm_dp_check_and_send_link_address+0xa8/0xd0 [drm_kms_helper] +[ 246.751602] drm_dp_mst_link_probe_work+0x51/0x90 [drm_kms_helper] +[ 246.752314] process_one_work+0x231/0x620 +[ 246.752979] worker_thread+0x44/0x3a0 +[ 246.753838] kthread+0x12b/0x150 +[ 246.754619] ? wq_pool_ids_show+0x140/0x140 +[ 246.755386] ? kthread_create_worker_on_cpu+0x70/0x70 +[ 246.756162] ret_from_fork+0x3a/0x50 +[ 246.756847] + Showing all locks held in the system: +[ 246.758261] 3 locks held by kworker/4:0/37: +[ 246.759016] #0: 00000000f8df4d2d ((wq_completion)"events"){+.+.}, at: process_one_work+0x1b3/0x620 +[ 246.759856] #1: 00000000e6065461 ((work_completion)(&(&dev->mode_config.output_poll_work)->work)){+.+.}, at: process_one_work+0x1b3/0x620 +[ 246.760670] #2: 00000000cb66735f (&helper->lock){+.+.}, at: drm_fb_helper_hotplug_event.part.28+0x20/0xb0 [drm_kms_helper] +[ 246.761516] 2 locks held by kworker/0:1/60: +[ 246.762274] #0: 00000000fff6be0f ((wq_completion)"pm"){+.+.}, at: process_one_work+0x1b3/0x620 +[ 246.762982] #1: 000000005ab44fb4 ((work_completion)(&dev->power.work)){+.+.}, at: process_one_work+0x1b3/0x620 +[ 246.763890] 1 lock held by khungtaskd/64: +[ 246.764664] #0: 000000008cb8b5c3 (rcu_read_lock){....}, at: debug_show_all_locks+0x23/0x185 +[ 246.765588] 5 locks held by kworker/4:2/422: +[ 246.766440] #0: 00000000232f0959 ((wq_completion)"events_long"){+.+.}, at: process_one_work+0x1b3/0x620 +[ 246.767390] #1: 00000000bb59b134 ((work_completion)(&mgr->work)){+.+.}, at: process_one_work+0x1b3/0x620 +[ 246.768154] #2: 00000000cb66735f (&helper->lock){+.+.}, at: drm_fb_helper_restore_fbdev_mode_unlocked+0x4c/0xb0 [drm_kms_helper] +[ 246.768966] #3: 000000004c8f0b6b (crtc_ww_class_acquire){+.+.}, at: restore_fbdev_mode_atomic+0x4b/0x240 [drm_kms_helper] +[ 246.769921] #4: 000000004c34a296 (crtc_ww_class_mutex){+.+.}, at: drm_modeset_backoff+0x8a/0x1b0 [drm] +[ 246.770839] 1 lock held by dmesg/1038: +[ 246.771739] 2 locks held by zsh/1172: +[ 246.772650] #0: 00000000836d0438 (&tty->ldisc_sem){++++}, at: ldsem_down_read+0x37/0x40 +[ 246.773680] #1: 000000001f4f4d48 (&ldata->atomic_read_lock){+.+.}, at: n_tty_read+0xc1/0x870 + +[ 246.775522] ============================================= + +After trying dozens of different solutions, I found one very simple one +that should also have the benefit of preventing us from having to fight +locking for the rest of our lives. So, we work around these deadlocks by +deferring all fbcon hotplug events that happen after the runtime suspend +process starts until after the device is resumed again. + +Changes since v7: + - Fixup commit message - Daniel Vetter + +Changes since v6: + - Remove unused nouveau_fbcon_hotplugged_in_suspend() - Ilia + +Changes since v5: + - Come up with the (hopefully final) solution for solving this dumb + problem, one that is a lot less likely to cause issues with locking in + the future. This should work around all deadlock conditions with fbcon + brought up thus far. + +Changes since v4: + - Add nouveau_fbcon_hotplugged_in_suspend() to workaround deadlock + condition that Lukas described + - Just move all of this out of drm_fb_helper. It seems that other DRM + drivers have already figured out other workarounds for this. If other + drivers do end up needing this in the future, we can just move this + back into drm_fb_helper again. + +Changes since v3: +- Actually check if fb_helper is NULL in both new helpers +- Actually check drm_fbdev_emulation in both new helpers +- Don't fire off a fb_helper hotplug unconditionally; only do it if + the following conditions are true (as otherwise, calling this in the + wrong spot will cause Bad Things to happen): + - fb_helper hotplug handling was actually inhibited previously + - fb_helper actually has a delayed hotplug pending + - fb_helper is actually bound + - fb_helper is actually initialized +- Add __must_check to drm_fb_helper_suspend_hotplug(). There's no + situation where a driver would actually want to use this without + checking the return value, so enforce that +- Rewrite and clarify the documentation for both helpers. +- Make sure to return true in the drm_fb_helper_suspend_hotplug() stub + that's provided in drm_fb_helper.h when CONFIG_DRM_FBDEV_EMULATION + isn't enabled +- Actually grab the toplevel fb_helper lock in + drm_fb_helper_resume_hotplug(), since it's possible other activity + (such as a hotplug) could be going on at the same time the driver + calls drm_fb_helper_resume_hotplug(). We need this to check whether or + not drm_fb_helper_hotplug_event() needs to be called anyway + +Signed-off-by: Lyude Paul +Reviewed-by: Karol Herbst +Acked-by: Daniel Vetter +Cc: stable@vger.kernel.org +Cc: Lukas Wunner +Signed-off-by: Ben Skeggs +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/nouveau/dispnv50/disp.c | 2 - + drivers/gpu/drm/nouveau/nouveau_display.c | 2 - + drivers/gpu/drm/nouveau/nouveau_fbcon.c | 57 ++++++++++++++++++++++++++++++ + drivers/gpu/drm/nouveau/nouveau_fbcon.h | 5 ++ + 4 files changed, 64 insertions(+), 2 deletions(-) + +--- a/drivers/gpu/drm/nouveau/dispnv50/disp.c ++++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c +@@ -2080,7 +2080,7 @@ nv50_disp_atomic_state_alloc(struct drm_ + static const struct drm_mode_config_funcs + nv50_disp_func = { + .fb_create = nouveau_user_framebuffer_create, +- .output_poll_changed = drm_fb_helper_output_poll_changed, ++ .output_poll_changed = nouveau_fbcon_output_poll_changed, + .atomic_check = nv50_disp_atomic_check, + .atomic_commit = nv50_disp_atomic_commit, + .atomic_state_alloc = nv50_disp_atomic_state_alloc, +--- a/drivers/gpu/drm/nouveau/nouveau_display.c ++++ b/drivers/gpu/drm/nouveau/nouveau_display.c +@@ -293,7 +293,7 @@ nouveau_user_framebuffer_create(struct d + + static const struct drm_mode_config_funcs nouveau_mode_config_funcs = { + .fb_create = nouveau_user_framebuffer_create, +- .output_poll_changed = drm_fb_helper_output_poll_changed, ++ .output_poll_changed = nouveau_fbcon_output_poll_changed, + }; + + +--- a/drivers/gpu/drm/nouveau/nouveau_fbcon.c ++++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.c +@@ -466,6 +466,7 @@ nouveau_fbcon_set_suspend_work(struct wo + console_unlock(); + + if (state == FBINFO_STATE_RUNNING) { ++ nouveau_fbcon_hotplug_resume(drm->fbcon); + pm_runtime_mark_last_busy(drm->dev->dev); + pm_runtime_put_sync(drm->dev->dev); + } +@@ -487,6 +488,61 @@ nouveau_fbcon_set_suspend(struct drm_dev + schedule_work(&drm->fbcon_work); + } + ++void ++nouveau_fbcon_output_poll_changed(struct drm_device *dev) ++{ ++ struct nouveau_drm *drm = nouveau_drm(dev); ++ struct nouveau_fbdev *fbcon = drm->fbcon; ++ int ret; ++ ++ if (!fbcon) ++ return; ++ ++ mutex_lock(&fbcon->hotplug_lock); ++ ++ ret = pm_runtime_get(dev->dev); ++ if (ret == 1 || ret == -EACCES) { ++ drm_fb_helper_hotplug_event(&fbcon->helper); ++ ++ pm_runtime_mark_last_busy(dev->dev); ++ pm_runtime_put_autosuspend(dev->dev); ++ } else if (ret == 0) { ++ /* If the GPU was already in the process of suspending before ++ * this event happened, then we can't block here as we'll ++ * deadlock the runtime pmops since they wait for us to ++ * finish. So, just defer this event for when we runtime ++ * resume again. It will be handled by fbcon_work. ++ */ ++ NV_DEBUG(drm, "fbcon HPD event deferred until runtime resume\n"); ++ fbcon->hotplug_waiting = true; ++ pm_runtime_put_noidle(drm->dev->dev); ++ } else { ++ DRM_WARN("fbcon HPD event lost due to RPM failure: %d\n", ++ ret); ++ } ++ ++ mutex_unlock(&fbcon->hotplug_lock); ++} ++ ++void ++nouveau_fbcon_hotplug_resume(struct nouveau_fbdev *fbcon) ++{ ++ struct nouveau_drm *drm; ++ ++ if (!fbcon) ++ return; ++ drm = nouveau_drm(fbcon->helper.dev); ++ ++ mutex_lock(&fbcon->hotplug_lock); ++ if (fbcon->hotplug_waiting) { ++ fbcon->hotplug_waiting = false; ++ ++ NV_DEBUG(drm, "Handling deferred fbcon HPD events\n"); ++ drm_fb_helper_hotplug_event(&fbcon->helper); ++ } ++ mutex_unlock(&fbcon->hotplug_lock); ++} ++ + int + nouveau_fbcon_init(struct drm_device *dev) + { +@@ -505,6 +561,7 @@ nouveau_fbcon_init(struct drm_device *de + + drm->fbcon = fbcon; + INIT_WORK(&drm->fbcon_work, nouveau_fbcon_set_suspend_work); ++ mutex_init(&fbcon->hotplug_lock); + + drm_fb_helper_prepare(dev, &fbcon->helper, &nouveau_fbcon_helper_funcs); + +--- a/drivers/gpu/drm/nouveau/nouveau_fbcon.h ++++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.h +@@ -41,6 +41,9 @@ struct nouveau_fbdev { + struct nvif_object gdi; + struct nvif_object blit; + struct nvif_object twod; ++ ++ struct mutex hotplug_lock; ++ bool hotplug_waiting; + }; + + void nouveau_fbcon_restore(void); +@@ -68,6 +71,8 @@ void nouveau_fbcon_set_suspend(struct dr + void nouveau_fbcon_accel_save_disable(struct drm_device *dev); + void nouveau_fbcon_accel_restore(struct drm_device *dev); + ++void nouveau_fbcon_output_poll_changed(struct drm_device *dev); ++void nouveau_fbcon_hotplug_resume(struct nouveau_fbdev *fbcon); + extern int nouveau_nofbaccel; + + #endif /* __NV50_FBCON_H__ */ diff --git a/queue-4.18/drm-nouveau-drm-nouveau-prevent-handling-acpi-hpd-events-too-early.patch b/queue-4.18/drm-nouveau-drm-nouveau-prevent-handling-acpi-hpd-events-too-early.patch new file mode 100644 index 00000000000..7d49c4b955c --- /dev/null +++ b/queue-4.18/drm-nouveau-drm-nouveau-prevent-handling-acpi-hpd-events-too-early.patch @@ -0,0 +1,122 @@ +From 79e765ad665da4b8aa7e9c878bd2fef837f6fea5 Mon Sep 17 00:00:00 2001 +From: Lyude Paul +Date: Thu, 16 Aug 2018 16:13:13 -0400 +Subject: drm/nouveau/drm/nouveau: Prevent handling ACPI HPD events too early + +From: Lyude Paul + +commit 79e765ad665da4b8aa7e9c878bd2fef837f6fea5 upstream. + +On most systems with ACPI hotplugging support, it seems that we always +receive a hotplug event once we re-enable EC interrupts even if the GPU +hasn't even been resumed yet. + +This can cause problems since even though we schedule hpd_work to handle +connector reprobing for us, hpd_work synchronizes on +pm_runtime_get_sync() to wait until the device is ready to perform +reprobing. Since runtime suspend/resume callbacks are disabled before +the PM core calls ->suspend(), any calls to pm_runtime_get_sync() during +this period will grab a runtime PM ref and return immediately with +-EACCES. Because we schedule hpd_work from our ACPI HPD handler, and +hpd_work synchronizes on pm_runtime_get_sync(), this causes us to launch +a connector reprobe immediately even if the GPU isn't actually resumed +just yet. This causes various warnings in dmesg and occasionally, also +prevents some displays connected to the dedicated GPU from coming back +up after suspend. Example: + +usb 1-4: USB disconnect, device number 14 +usb 1-4.1: USB disconnect, device number 15 +WARNING: CPU: 0 PID: 838 at drivers/gpu/drm/nouveau/include/nvkm/subdev/i2c.h:170 nouveau_dp_detect+0x17e/0x370 [nouveau] +CPU: 0 PID: 838 Comm: kworker/0:6 Not tainted 4.17.14-201.Lyude.bz1477182.V3.fc28.x86_64 #1 +Hardware name: LENOVO 20EQS64N00/20EQS64N00, BIOS N1EET77W (1.50 ) 03/28/2018 +Workqueue: events nouveau_display_hpd_work [nouveau] +RIP: 0010:nouveau_dp_detect+0x17e/0x370 [nouveau] +RSP: 0018:ffffa15143933cf0 EFLAGS: 00010293 +RAX: 0000000000000000 RBX: ffff8cb4f656c400 RCX: 0000000000000000 +RDX: ffffa1514500e4e4 RSI: ffffa1514500e4e4 RDI: 0000000001009002 +RBP: ffff8cb4f4a8a800 R08: ffffa15143933cfd R09: ffffa15143933cfc +R10: 0000000000000000 R11: 0000000000000000 R12: ffff8cb4fb57a000 +R13: ffff8cb4fb57a000 R14: ffff8cb4f4a8f800 R15: ffff8cb4f656c418 +FS: 0000000000000000(0000) GS:ffff8cb51f400000(0000) knlGS:0000000000000000 +CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +CR2: 00007f78ec938000 CR3: 000000073720a003 CR4: 00000000003606f0 +DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 +DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 +Call Trace: + ? _cond_resched+0x15/0x30 + nouveau_connector_detect+0x2ce/0x520 [nouveau] + ? _cond_resched+0x15/0x30 + ? ww_mutex_lock+0x12/0x40 + drm_helper_probe_detect_ctx+0x8b/0xe0 [drm_kms_helper] + drm_helper_hpd_irq_event+0xa8/0x120 [drm_kms_helper] + nouveau_display_hpd_work+0x2a/0x60 [nouveau] + process_one_work+0x187/0x340 + worker_thread+0x2e/0x380 + ? pwq_unbound_release_workfn+0xd0/0xd0 + kthread+0x112/0x130 + ? kthread_create_worker_on_cpu+0x70/0x70 + ret_from_fork+0x35/0x40 +Code: 4c 8d 44 24 0d b9 00 05 00 00 48 89 ef ba 09 00 00 00 be 01 00 00 00 e8 e1 09 f8 ff 85 c0 0f 85 b2 01 00 00 80 7c 24 0c 03 74 02 <0f> 0b 48 89 ef e8 b8 07 f8 ff f6 05 51 1b c8 ff 02 0f 84 72 ff +---[ end trace 55d811b38fc8e71a ]--- + +So, to fix this we attempt to grab a runtime PM reference in the ACPI +handler itself asynchronously. If the GPU is already awake (it will have +normal hotplugging at this point) or runtime PM callbacks are currently +disabled on the device, we drop our reference without updating the +autosuspend delay. We only schedule connector reprobes when we +successfully managed to queue up a resume request with our asynchronous +PM ref. + +This also has the added benefit of preventing redundant connector +reprobes from ACPI while the GPU is runtime resumed! + +Signed-off-by: Lyude Paul +Cc: stable@vger.kernel.org +Cc: Karol Herbst +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1477182#c41 +Signed-off-by: Lyude Paul +Signed-off-by: Ben Skeggs +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/nouveau/nouveau_display.c | 26 ++++++++++++++++++++------ + 1 file changed, 20 insertions(+), 6 deletions(-) + +--- a/drivers/gpu/drm/nouveau/nouveau_display.c ++++ b/drivers/gpu/drm/nouveau/nouveau_display.c +@@ -377,15 +377,29 @@ nouveau_display_acpi_ntfy(struct notifie + { + struct nouveau_drm *drm = container_of(nb, typeof(*drm), acpi_nb); + struct acpi_bus_event *info = data; ++ int ret; + + if (!strcmp(info->device_class, ACPI_VIDEO_CLASS)) { + if (info->type == ACPI_VIDEO_NOTIFY_PROBE) { +- /* +- * This may be the only indication we receive of a +- * connector hotplug on a runtime suspended GPU, +- * schedule hpd_work to check. +- */ +- schedule_work(&drm->hpd_work); ++ ret = pm_runtime_get(drm->dev->dev); ++ if (ret == 1 || ret == -EACCES) { ++ /* If the GPU is already awake, or in a state ++ * where we can't wake it up, it can handle ++ * it's own hotplug events. ++ */ ++ pm_runtime_put_autosuspend(drm->dev->dev); ++ } else if (ret == 0) { ++ /* This may be the only indication we receive ++ * of a connector hotplug on a runtime ++ * suspended GPU, schedule hpd_work to check. ++ */ ++ NV_DEBUG(drm, "ACPI requested connector reprobe\n"); ++ schedule_work(&drm->hpd_work); ++ pm_runtime_put_noidle(drm->dev->dev); ++ } else { ++ NV_WARN(drm, "Dropped ACPI reprobe event due to RPM error: %d\n", ++ ret); ++ } + + /* acpi-video should not generate keypresses for this */ + return NOTIFY_BAD; diff --git a/queue-4.18/drm-nouveau-drm-nouveau-use-pm_runtime_get_noresume-in-connector_detect.patch b/queue-4.18/drm-nouveau-drm-nouveau-use-pm_runtime_get_noresume-in-connector_detect.patch new file mode 100644 index 00000000000..4a0324e5754 --- /dev/null +++ b/queue-4.18/drm-nouveau-drm-nouveau-use-pm_runtime_get_noresume-in-connector_detect.patch @@ -0,0 +1,64 @@ +From 6833fb1ec120bf078e1a527c573a09d4de286224 Mon Sep 17 00:00:00 2001 +From: Lyude Paul +Date: Wed, 15 Aug 2018 15:00:14 -0400 +Subject: drm/nouveau/drm/nouveau: Use pm_runtime_get_noresume() in connector_detect() + +From: Lyude Paul + +commit 6833fb1ec120bf078e1a527c573a09d4de286224 upstream. + +It's true we can't resume the device from poll workers in +nouveau_connector_detect(). We can however, prevent the autosuspend +timer from elapsing immediately if it hasn't already without risking any +sort of deadlock with the runtime suspend/resume operations. So do that +instead of entirely avoiding grabbing a power reference. + +Signed-off-by: Lyude Paul +Reviewed-by: Karol Herbst +Acked-by: Daniel Vetter +Cc: stable@vger.kernel.org +Cc: Lukas Wunner +Signed-off-by: Ben Skeggs +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/nouveau/nouveau_connector.c | 20 +++++++++++--------- + 1 file changed, 11 insertions(+), 9 deletions(-) + +--- a/drivers/gpu/drm/nouveau/nouveau_connector.c ++++ b/drivers/gpu/drm/nouveau/nouveau_connector.c +@@ -570,12 +570,16 @@ nouveau_connector_detect(struct drm_conn + nv_connector->edid = NULL; + } + +- /* Outputs are only polled while runtime active, so acquiring a +- * runtime PM ref here is unnecessary (and would deadlock upon +- * runtime suspend because it waits for polling to finish). ++ /* Outputs are only polled while runtime active, so resuming the ++ * device here is unnecessary (and would deadlock upon runtime suspend ++ * because it waits for polling to finish). We do however, want to ++ * prevent the autosuspend timer from elapsing during this operation ++ * if possible. + */ +- if (!drm_kms_helper_is_poll_worker()) { +- ret = pm_runtime_get_sync(connector->dev->dev); ++ if (drm_kms_helper_is_poll_worker()) { ++ pm_runtime_get_noresume(dev->dev); ++ } else { ++ ret = pm_runtime_get_sync(dev->dev); + if (ret < 0 && ret != -EACCES) + return conn_status; + } +@@ -653,10 +657,8 @@ detect_analog: + + out: + +- if (!drm_kms_helper_is_poll_worker()) { +- pm_runtime_mark_last_busy(connector->dev->dev); +- pm_runtime_put_autosuspend(connector->dev->dev); +- } ++ pm_runtime_mark_last_busy(dev->dev); ++ pm_runtime_put_autosuspend(dev->dev); + + return conn_status; + } diff --git a/queue-4.18/drm-nouveau-fix-deadlocks-in-nouveau_connector_detect.patch b/queue-4.18/drm-nouveau-fix-deadlocks-in-nouveau_connector_detect.patch new file mode 100644 index 00000000000..fc2f07693d7 --- /dev/null +++ b/queue-4.18/drm-nouveau-fix-deadlocks-in-nouveau_connector_detect.patch @@ -0,0 +1,206 @@ +From 3e1a12754d4df5804bfca5dedf09d2ba291bdc2a Mon Sep 17 00:00:00 2001 +From: Lyude Paul +Date: Wed, 15 Aug 2018 15:00:15 -0400 +Subject: drm/nouveau: Fix deadlocks in nouveau_connector_detect() + +From: Lyude Paul + +commit 3e1a12754d4df5804bfca5dedf09d2ba291bdc2a upstream. + +When we disable hotplugging on the GPU, we need to be able to +synchronize with each connector's hotplug interrupt handler before the +interrupt is finally disabled. This can be a problem however, since +nouveau_connector_detect() currently grabs a runtime power reference +when handling connector probing. This will deadlock the runtime suspend +handler like so: + +[ 861.480896] INFO: task kworker/0:2:61 blocked for more than 120 seconds. +[ 861.483290] Tainted: G O 4.18.0-rc6Lyude-Test+ #1 +[ 861.485158] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message. +[ 861.486332] kworker/0:2 D 0 61 2 0x80000000 +[ 861.487044] Workqueue: events nouveau_display_hpd_work [nouveau] +[ 861.487737] Call Trace: +[ 861.488394] __schedule+0x322/0xaf0 +[ 861.489070] schedule+0x33/0x90 +[ 861.489744] rpm_resume+0x19c/0x850 +[ 861.490392] ? finish_wait+0x90/0x90 +[ 861.491068] __pm_runtime_resume+0x4e/0x90 +[ 861.491753] nouveau_display_hpd_work+0x22/0x60 [nouveau] +[ 861.492416] process_one_work+0x231/0x620 +[ 861.493068] worker_thread+0x44/0x3a0 +[ 861.493722] kthread+0x12b/0x150 +[ 861.494342] ? wq_pool_ids_show+0x140/0x140 +[ 861.494991] ? kthread_create_worker_on_cpu+0x70/0x70 +[ 861.495648] ret_from_fork+0x3a/0x50 +[ 861.496304] INFO: task kworker/6:2:320 blocked for more than 120 seconds. +[ 861.496968] Tainted: G O 4.18.0-rc6Lyude-Test+ #1 +[ 861.497654] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message. +[ 861.498341] kworker/6:2 D 0 320 2 0x80000080 +[ 861.499045] Workqueue: pm pm_runtime_work +[ 861.499739] Call Trace: +[ 861.500428] __schedule+0x322/0xaf0 +[ 861.501134] ? wait_for_completion+0x104/0x190 +[ 861.501851] schedule+0x33/0x90 +[ 861.502564] schedule_timeout+0x3a5/0x590 +[ 861.503284] ? mark_held_locks+0x58/0x80 +[ 861.503988] ? _raw_spin_unlock_irq+0x2c/0x40 +[ 861.504710] ? wait_for_completion+0x104/0x190 +[ 861.505417] ? trace_hardirqs_on_caller+0xf4/0x190 +[ 861.506136] ? wait_for_completion+0x104/0x190 +[ 861.506845] wait_for_completion+0x12c/0x190 +[ 861.507555] ? wake_up_q+0x80/0x80 +[ 861.508268] flush_work+0x1c9/0x280 +[ 861.508990] ? flush_workqueue_prep_pwqs+0x1b0/0x1b0 +[ 861.509735] nvif_notify_put+0xb1/0xc0 [nouveau] +[ 861.510482] nouveau_display_fini+0xbd/0x170 [nouveau] +[ 861.511241] nouveau_display_suspend+0x67/0x120 [nouveau] +[ 861.511969] nouveau_do_suspend+0x5e/0x2d0 [nouveau] +[ 861.512715] nouveau_pmops_runtime_suspend+0x47/0xb0 [nouveau] +[ 861.513435] pci_pm_runtime_suspend+0x6b/0x180 +[ 861.514165] ? pci_has_legacy_pm_support+0x70/0x70 +[ 861.514897] __rpm_callback+0x7a/0x1d0 +[ 861.515618] ? pci_has_legacy_pm_support+0x70/0x70 +[ 861.516313] rpm_callback+0x24/0x80 +[ 861.517027] ? pci_has_legacy_pm_support+0x70/0x70 +[ 861.517741] rpm_suspend+0x142/0x6b0 +[ 861.518449] pm_runtime_work+0x97/0xc0 +[ 861.519144] process_one_work+0x231/0x620 +[ 861.519831] worker_thread+0x44/0x3a0 +[ 861.520522] kthread+0x12b/0x150 +[ 861.521220] ? wq_pool_ids_show+0x140/0x140 +[ 861.521925] ? kthread_create_worker_on_cpu+0x70/0x70 +[ 861.522622] ret_from_fork+0x3a/0x50 +[ 861.523299] INFO: task kworker/6:0:1329 blocked for more than 120 seconds. +[ 861.523977] Tainted: G O 4.18.0-rc6Lyude-Test+ #1 +[ 861.524644] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message. +[ 861.525349] kworker/6:0 D 0 1329 2 0x80000000 +[ 861.526073] Workqueue: events nvif_notify_work [nouveau] +[ 861.526751] Call Trace: +[ 861.527411] __schedule+0x322/0xaf0 +[ 861.528089] schedule+0x33/0x90 +[ 861.528758] rpm_resume+0x19c/0x850 +[ 861.529399] ? finish_wait+0x90/0x90 +[ 861.530073] __pm_runtime_resume+0x4e/0x90 +[ 861.530798] nouveau_connector_detect+0x7e/0x510 [nouveau] +[ 861.531459] ? ww_mutex_lock+0x47/0x80 +[ 861.532097] ? ww_mutex_lock+0x47/0x80 +[ 861.532819] ? drm_modeset_lock+0x88/0x130 [drm] +[ 861.533481] drm_helper_probe_detect_ctx+0xa0/0x100 [drm_kms_helper] +[ 861.534127] drm_helper_hpd_irq_event+0xa4/0x120 [drm_kms_helper] +[ 861.534940] nouveau_connector_hotplug+0x98/0x120 [nouveau] +[ 861.535556] nvif_notify_work+0x2d/0xb0 [nouveau] +[ 861.536221] process_one_work+0x231/0x620 +[ 861.536994] worker_thread+0x44/0x3a0 +[ 861.537757] kthread+0x12b/0x150 +[ 861.538463] ? wq_pool_ids_show+0x140/0x140 +[ 861.539102] ? kthread_create_worker_on_cpu+0x70/0x70 +[ 861.539815] ret_from_fork+0x3a/0x50 +[ 861.540521] + Showing all locks held in the system: +[ 861.541696] 2 locks held by kworker/0:2/61: +[ 861.542406] #0: 000000002dbf8af5 ((wq_completion)"events"){+.+.}, at: process_one_work+0x1b3/0x620 +[ 861.543071] #1: 0000000076868126 ((work_completion)(&drm->hpd_work)){+.+.}, at: process_one_work+0x1b3/0x620 +[ 861.543814] 1 lock held by khungtaskd/64: +[ 861.544535] #0: 0000000059db4b53 (rcu_read_lock){....}, at: debug_show_all_locks+0x23/0x185 +[ 861.545160] 3 locks held by kworker/6:2/320: +[ 861.545896] #0: 00000000d9e1bc59 ((wq_completion)"pm"){+.+.}, at: process_one_work+0x1b3/0x620 +[ 861.546702] #1: 00000000c9f92d84 ((work_completion)(&dev->power.work)){+.+.}, at: process_one_work+0x1b3/0x620 +[ 861.547443] #2: 000000004afc5de1 (drm_connector_list_iter){.+.+}, at: nouveau_display_fini+0x96/0x170 [nouveau] +[ 861.548146] 1 lock held by dmesg/983: +[ 861.548889] 2 locks held by zsh/1250: +[ 861.549605] #0: 00000000348e3cf6 (&tty->ldisc_sem){++++}, at: ldsem_down_read+0x37/0x40 +[ 861.550393] #1: 000000007009a7a8 (&ldata->atomic_read_lock){+.+.}, at: n_tty_read+0xc1/0x870 +[ 861.551122] 6 locks held by kworker/6:0/1329: +[ 861.551957] #0: 000000002dbf8af5 ((wq_completion)"events"){+.+.}, at: process_one_work+0x1b3/0x620 +[ 861.552765] #1: 00000000ddb499ad ((work_completion)(¬ify->work)#2){+.+.}, at: process_one_work+0x1b3/0x620 +[ 861.553582] #2: 000000006e013cbe (&dev->mode_config.mutex){+.+.}, at: drm_helper_hpd_irq_event+0x6c/0x120 [drm_kms_helper] +[ 861.554357] #3: 000000004afc5de1 (drm_connector_list_iter){.+.+}, at: drm_helper_hpd_irq_event+0x78/0x120 [drm_kms_helper] +[ 861.555227] #4: 0000000044f294d9 (crtc_ww_class_acquire){+.+.}, at: drm_helper_probe_detect_ctx+0x3d/0x100 [drm_kms_helper] +[ 861.556133] #5: 00000000db193642 (crtc_ww_class_mutex){+.+.}, at: drm_modeset_lock+0x4b/0x130 [drm] + +[ 861.557864] ============================================= + +[ 861.559507] NMI backtrace for cpu 2 +[ 861.560363] CPU: 2 PID: 64 Comm: khungtaskd Tainted: G O 4.18.0-rc6Lyude-Test+ #1 +[ 861.561197] Hardware name: LENOVO 20EQS64N0B/20EQS64N0B, BIOS N1EET78W (1.51 ) 05/18/2018 +[ 861.561948] Call Trace: +[ 861.562757] dump_stack+0x8e/0xd3 +[ 861.563516] nmi_cpu_backtrace.cold.3+0x14/0x5a +[ 861.564269] ? lapic_can_unplug_cpu.cold.27+0x42/0x42 +[ 861.565029] nmi_trigger_cpumask_backtrace+0xa1/0xae +[ 861.565789] arch_trigger_cpumask_backtrace+0x19/0x20 +[ 861.566558] watchdog+0x316/0x580 +[ 861.567355] kthread+0x12b/0x150 +[ 861.568114] ? reset_hung_task_detector+0x20/0x20 +[ 861.568863] ? kthread_create_worker_on_cpu+0x70/0x70 +[ 861.569598] ret_from_fork+0x3a/0x50 +[ 861.570370] Sending NMI from CPU 2 to CPUs 0-1,3-7: +[ 861.571426] NMI backtrace for cpu 6 skipped: idling at intel_idle+0x7f/0x120 +[ 861.571429] NMI backtrace for cpu 7 skipped: idling at intel_idle+0x7f/0x120 +[ 861.571432] NMI backtrace for cpu 3 skipped: idling at intel_idle+0x7f/0x120 +[ 861.571464] NMI backtrace for cpu 5 skipped: idling at intel_idle+0x7f/0x120 +[ 861.571467] NMI backtrace for cpu 0 skipped: idling at intel_idle+0x7f/0x120 +[ 861.571469] NMI backtrace for cpu 4 skipped: idling at intel_idle+0x7f/0x120 +[ 861.571472] NMI backtrace for cpu 1 skipped: idling at intel_idle+0x7f/0x120 +[ 861.572428] Kernel panic - not syncing: hung_task: blocked tasks + +So: fix this by making it so that normal hotplug handling /only/ happens +so long as the GPU is currently awake without any pending runtime PM +requests. In the event that a hotplug occurs while the device is +suspending or resuming, we can simply defer our response until the GPU +is fully runtime resumed again. + +Changes since v4: +- Use a new trick I came up with using pm_runtime_get() instead of the + hackish junk we had before + +Signed-off-by: Lyude Paul +Reviewed-by: Karol Herbst +Acked-by: Daniel Vetter +Cc: stable@vger.kernel.org +Cc: Lukas Wunner +Signed-off-by: Ben Skeggs +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/nouveau/nouveau_connector.c | 22 ++++++++++++++++++++++ + 1 file changed, 22 insertions(+) + +--- a/drivers/gpu/drm/nouveau/nouveau_connector.c ++++ b/drivers/gpu/drm/nouveau/nouveau_connector.c +@@ -1120,6 +1120,26 @@ nouveau_connector_hotplug(struct nvif_no + const struct nvif_notify_conn_rep_v0 *rep = notify->data; + const char *name = connector->name; + struct nouveau_encoder *nv_encoder; ++ int ret; ++ ++ ret = pm_runtime_get(drm->dev->dev); ++ if (ret == 0) { ++ /* We can't block here if there's a pending PM request ++ * running, as we'll deadlock nouveau_display_fini() when it ++ * calls nvif_put() on our nvif_notify struct. So, simply ++ * defer the hotplug event until the device finishes resuming ++ */ ++ NV_DEBUG(drm, "Deferring HPD on %s until runtime resume\n", ++ name); ++ schedule_work(&drm->hpd_work); ++ ++ pm_runtime_put_noidle(drm->dev->dev); ++ return NVIF_NOTIFY_KEEP; ++ } else if (ret != 1 && ret != -EACCES) { ++ NV_WARN(drm, "HPD on %s dropped due to RPM failure: %d\n", ++ name, ret); ++ return NVIF_NOTIFY_DROP; ++ } + + if (rep->mask & NVIF_NOTIFY_CONN_V0_IRQ) { + NV_DEBUG(drm, "service %s\n", name); +@@ -1137,6 +1157,8 @@ nouveau_connector_hotplug(struct nvif_no + drm_helper_hpd_irq_event(connector->dev); + } + ++ pm_runtime_mark_last_busy(drm->dev->dev); ++ pm_runtime_put_autosuspend(drm->dev->dev); + return NVIF_NOTIFY_KEEP; + } + diff --git a/queue-4.18/drm-nouveau-only-write-dp_mstm_ctrl-when-needed.patch b/queue-4.18/drm-nouveau-only-write-dp_mstm_ctrl-when-needed.patch new file mode 100644 index 00000000000..c5f4cab67e3 --- /dev/null +++ b/queue-4.18/drm-nouveau-only-write-dp_mstm_ctrl-when-needed.patch @@ -0,0 +1,120 @@ +From b26b4590dd53e012526342e749c423e6c0e73437 Mon Sep 17 00:00:00 2001 +From: Lyude Paul +Date: Thu, 9 Aug 2018 18:22:05 -0400 +Subject: drm/nouveau: Only write DP_MSTM_CTRL when needed + +From: Lyude Paul + +commit b26b4590dd53e012526342e749c423e6c0e73437 upstream. + +Currently, nouveau will re-write the DP_MSTM_CTRL register for an MST +hub every time it receives a long HPD pulse on DP. This isn't actually +necessary and additionally, has some unintended side effects. + +With the P50 I've got here, rewriting DP_MSTM_CTRL constantly seems to +make it rather likely (1 out of 5 times usually) that bringing up MST +with it's ThinkPad dock will fail and result in sideband messages timing +out in the middle. Afterwards, successive probes don't manage to get the +dock to communicate properly over MST sideband properly. + +Many times sideband message timeouts from MST hubs are indicative of +either the source or the sink dropping an ESI event, which can cause +DRM's perspective of the topology's current state to go out of sync with +reality. While it's tough to really know for sure what's happening to +the dock, using userspace tools to write to DP_MSTM_CTRL in the middle +of the MST link probing process does appear to make things flaky. It's +possible that when we write to DP_MSTM_CTRL, the function that gets +triggered to respond in the dock's firmware temporarily puts it in a +state where it might end up not reporting an ESI to the source, or ends +up dropping a sideband message we sent it. + +So, to fix this we make it so that when probing an MST topology, we +respect it's current state. If the dock's already enabled, we simply +read DP_MSTM_CTRL and disable the topology if it's value is not what we +expected. Otherwise, we perform the normal MST probing dance. We avoid +taking any action except if the state of the MST topology actually +changes. + +This fixes MST sideband message timeouts and detection failures on my +P50 with its ThinkPad dock. + +Signed-off-by: Lyude Paul +Cc: stable@vger.kernel.org +Cc: Karol Herbst +Signed-off-by: Ben Skeggs +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/nouveau/dispnv50/disp.c | 45 +++++++++++++++++++++++++------- + 1 file changed, 36 insertions(+), 9 deletions(-) + +--- a/drivers/gpu/drm/nouveau/dispnv50/disp.c ++++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c +@@ -1121,31 +1121,58 @@ nv50_mstm_enable(struct nv50_mstm *mstm, + int + nv50_mstm_detect(struct nv50_mstm *mstm, u8 dpcd[8], int allow) + { +- int ret, state = 0; ++ struct drm_dp_aux *aux; ++ int ret; ++ bool old_state, new_state; ++ u8 mstm_ctrl; + + if (!mstm) + return 0; + +- if (dpcd[0] >= 0x12) { +- ret = drm_dp_dpcd_readb(mstm->mgr.aux, DP_MSTM_CAP, &dpcd[1]); ++ mutex_lock(&mstm->mgr.lock); ++ ++ old_state = mstm->mgr.mst_state; ++ new_state = old_state; ++ aux = mstm->mgr.aux; ++ ++ if (old_state) { ++ /* Just check that the MST hub is still as we expect it */ ++ ret = drm_dp_dpcd_readb(aux, DP_MSTM_CTRL, &mstm_ctrl); ++ if (ret < 0 || !(mstm_ctrl & DP_MST_EN)) { ++ DRM_DEBUG_KMS("Hub gone, disabling MST topology\n"); ++ new_state = false; ++ } ++ } else if (dpcd[0] >= 0x12) { ++ ret = drm_dp_dpcd_readb(aux, DP_MSTM_CAP, &dpcd[1]); + if (ret < 0) +- return ret; ++ goto probe_error; + + if (!(dpcd[1] & DP_MST_CAP)) + dpcd[0] = 0x11; + else +- state = allow; ++ new_state = allow; ++ } ++ ++ if (new_state == old_state) { ++ mutex_unlock(&mstm->mgr.lock); ++ return new_state; + } + +- ret = nv50_mstm_enable(mstm, dpcd[0], state); ++ ret = nv50_mstm_enable(mstm, dpcd[0], new_state); + if (ret) +- return ret; ++ goto probe_error; + +- ret = drm_dp_mst_topology_mgr_set_mst(&mstm->mgr, state); ++ mutex_unlock(&mstm->mgr.lock); ++ ++ ret = drm_dp_mst_topology_mgr_set_mst(&mstm->mgr, new_state); + if (ret) + return nv50_mstm_enable(mstm, dpcd[0], 0); + +- return mstm->mgr.mst_state; ++ return new_state; ++ ++probe_error: ++ mutex_unlock(&mstm->mgr.lock); ++ return ret; + } + + static void diff --git a/queue-4.18/drm-nouveau-remove-duplicate-poll_enable-in-pmops_runtime_suspend.patch b/queue-4.18/drm-nouveau-remove-duplicate-poll_enable-in-pmops_runtime_suspend.patch new file mode 100644 index 00000000000..13bf29d0112 --- /dev/null +++ b/queue-4.18/drm-nouveau-remove-duplicate-poll_enable-in-pmops_runtime_suspend.patch @@ -0,0 +1,37 @@ +From 611ce855420a6e8b9ff47af5f47431d52c7709f8 Mon Sep 17 00:00:00 2001 +From: Lyude Paul +Date: Wed, 15 Aug 2018 15:00:12 -0400 +Subject: drm/nouveau: Remove duplicate poll_enable() in pmops_runtime_suspend() + +From: Lyude Paul + +commit 611ce855420a6e8b9ff47af5f47431d52c7709f8 upstream. + +Since actual hotplug notifications don't get disabled until +nouveau_display_fini() is called, all this will do is cause any hotplugs +that happen between this drm_kms_helper_poll_disable() call and the +actual hotplug disablement to potentially be dropped if ACPI isn't +around to help us. + +Signed-off-by: Lyude Paul +Acked-by: Karol Herbst +Acked-by: Daniel Vetter +Cc: stable@vger.kernel.org +Cc: Lukas Wunner +Signed-off-by: Ben Skeggs +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/nouveau/nouveau_drm.c | 1 - + 1 file changed, 1 deletion(-) + +--- a/drivers/gpu/drm/nouveau/nouveau_drm.c ++++ b/drivers/gpu/drm/nouveau/nouveau_drm.c +@@ -835,7 +835,6 @@ nouveau_pmops_runtime_suspend(struct dev + return -EBUSY; + } + +- drm_kms_helper_poll_disable(drm_dev); + nouveau_switcheroo_optimus_dsm(); + ret = nouveau_do_suspend(drm_dev, true); + pci_save_state(pdev); diff --git a/queue-4.18/drm-nouveau-reset-mst-branching-unit-before-enabling.patch b/queue-4.18/drm-nouveau-reset-mst-branching-unit-before-enabling.patch new file mode 100644 index 00000000000..61fa34c4149 --- /dev/null +++ b/queue-4.18/drm-nouveau-reset-mst-branching-unit-before-enabling.patch @@ -0,0 +1,69 @@ +From fa3cdf8d0b092c4561f9f017dfac409eb7644737 Mon Sep 17 00:00:00 2001 +From: Lyude Paul +Date: Thu, 9 Aug 2018 18:22:06 -0400 +Subject: drm/nouveau: Reset MST branching unit before enabling + +From: Lyude Paul + +commit fa3cdf8d0b092c4561f9f017dfac409eb7644737 upstream. + +When probing a new MST device, it's not safe to make any assumptions +about it's current state. While most well mannered MST hubs will just +disable the branching unit on hotplug disconnects, this isn't enough to +save us from various other scenarios that might have resulted in +something writing to the MST branching unit before we got control of it. +This could happen if a previous probe we tried failed, if we're booting +in kexec context and the hub is still in the state the last kernel put +it in, etc. + +Luckily; there is no reason we can't just reset the branching unit +every time we enable a new topology. So, fix this by resetting it on +enabling new topologies to ensure that we always start off with a clean, +unmodified topology state on MST sinks. + +This fixes occasional hard-lockups on my P50's laptop dock (e.g. AUX +times out all DPCD trasactions) observed after multiple docks, undocks, +and module reloads. + +Signed-off-by: Lyude Paul +Cc: stable@vger.kernel.org +Cc: Karol Herbst +Signed-off-by: Ben Skeggs +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/nouveau/dispnv50/disp.c | 20 ++++++++++++-------- + 1 file changed, 12 insertions(+), 8 deletions(-) + +--- a/drivers/gpu/drm/nouveau/dispnv50/disp.c ++++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c +@@ -1098,17 +1098,21 @@ nv50_mstm_enable(struct nv50_mstm *mstm, + int ret; + + if (dpcd >= 0x12) { +- ret = drm_dp_dpcd_readb(mstm->mgr.aux, DP_MSTM_CTRL, &dpcd); ++ /* Even if we're enabling MST, start with disabling the ++ * branching unit to clear any sink-side MST topology state ++ * that wasn't set by us ++ */ ++ ret = drm_dp_dpcd_writeb(mstm->mgr.aux, DP_MSTM_CTRL, 0); + if (ret < 0) + return ret; + +- dpcd &= ~DP_MST_EN; +- if (state) +- dpcd |= DP_MST_EN; +- +- ret = drm_dp_dpcd_writeb(mstm->mgr.aux, DP_MSTM_CTRL, dpcd); +- if (ret < 0) +- return ret; ++ if (state) { ++ /* Now, start initializing */ ++ ret = drm_dp_dpcd_writeb(mstm->mgr.aux, DP_MSTM_CTRL, ++ DP_MST_EN); ++ if (ret < 0) ++ return ret; ++ } + } + + return nvif_mthd(disp, 0, &args, sizeof(args)); diff --git a/queue-4.18/drm-udl-destroy-framebuffer-only-if-it-was-initialized.patch b/queue-4.18/drm-udl-destroy-framebuffer-only-if-it-was-initialized.patch new file mode 100644 index 00000000000..24659a85f1e --- /dev/null +++ b/queue-4.18/drm-udl-destroy-framebuffer-only-if-it-was-initialized.patch @@ -0,0 +1,60 @@ +From fcb74da1eb8edd3a4ef9b9724f88ed709d684227 Mon Sep 17 00:00:00 2001 +From: Emil Lundmark +Date: Mon, 28 May 2018 16:27:11 +0200 +Subject: drm: udl: Destroy framebuffer only if it was initialized +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Emil Lundmark + +commit fcb74da1eb8edd3a4ef9b9724f88ed709d684227 upstream. + +This fixes a NULL pointer dereference that can happen if the UDL +driver is unloaded before the framebuffer is initialized. This can +happen e.g. if the USB device is unplugged right after it was plugged +in. + +As explained by Stéphane Marchesin: + +It happens when fbdev is disabled (which is the case for Chrome OS). +Even though intialization of the fbdev part is optional (it's done in +udlfb_create which is the callback for fb_probe()), the teardown isn't +optional (udl_driver_unload -> udl_fbdev_cleanup -> +udl_fbdev_destroy). + +Note that udl_fbdev_cleanup *tries* to be conditional (you can see it +does if (!udl->fbdev)) but that doesn't work, because udl->fbdev is +always set during udl_fbdev_init. + +Cc: stable@vger.kernel.org +Suggested-by: Sean Paul +Reviewed-by: Sean Paul +Acked-by: Daniel Vetter +Signed-off-by: Emil Lundmark +Signed-off-by: Sean Paul +Link: https://patchwork.freedesktop.org/patch/msgid/20180528142711.142466-1-lndmrk@chromium.org +Signed-off-by: Sean Paul +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/udl/udl_fb.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +--- a/drivers/gpu/drm/udl/udl_fb.c ++++ b/drivers/gpu/drm/udl/udl_fb.c +@@ -432,9 +432,11 @@ static void udl_fbdev_destroy(struct drm + { + drm_fb_helper_unregister_fbi(&ufbdev->helper); + drm_fb_helper_fini(&ufbdev->helper); +- drm_framebuffer_unregister_private(&ufbdev->ufb.base); +- drm_framebuffer_cleanup(&ufbdev->ufb.base); +- drm_gem_object_put_unlocked(&ufbdev->ufb.obj->base); ++ if (ufbdev->ufb.obj) { ++ drm_framebuffer_unregister_private(&ufbdev->ufb.base); ++ drm_framebuffer_cleanup(&ufbdev->ufb.base); ++ drm_gem_object_put_unlocked(&ufbdev->ufb.obj->base); ++ } + } + + int udl_fbdev_init(struct drm_device *dev) diff --git a/queue-4.18/drm-vc4-fix-the-no-scaling-case-on-multi-planar-yuv-formats.patch b/queue-4.18/drm-vc4-fix-the-no-scaling-case-on-multi-planar-yuv-formats.patch new file mode 100644 index 00000000000..7af9368d6d5 --- /dev/null +++ b/queue-4.18/drm-vc4-fix-the-no-scaling-case-on-multi-planar-yuv-formats.patch @@ -0,0 +1,85 @@ +From 658d8cbd07dae22ccecf49399e18c609c4e85c53 Mon Sep 17 00:00:00 2001 +From: Boris Brezillon +Date: Wed, 25 Jul 2018 14:29:07 +0200 +Subject: drm/vc4: Fix the "no scaling" case on multi-planar YUV formats + +From: Boris Brezillon + +commit 658d8cbd07dae22ccecf49399e18c609c4e85c53 upstream. + +When there's no scaling requested ->is_unity should be true no matter +the format. + +Also, when no scaling is requested and we have a multi-planar YUV +format, we should leave ->y_scaling[0] to VC4_SCALING_NONE and only +set ->x_scaling[0] to VC4_SCALING_PPF. + +Doing this fixes an hardly visible artifact (seen when using modetest +and a rather big overlay plane in YUV420). + +Fixes: fc04023fafec ("drm/vc4: Add support for YUV planes.") +Cc: +Signed-off-by: Boris Brezillon +Reviewed-by: Eric Anholt +Link: https://patchwork.freedesktop.org/patch/msgid/20180725122907.13702-1-boris.brezillon@bootlin.com +Signed-off-by: Sean Paul +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/vc4/vc4_plane.c | 25 ++++++++++++------------- + 1 file changed, 12 insertions(+), 13 deletions(-) + +--- a/drivers/gpu/drm/vc4/vc4_plane.c ++++ b/drivers/gpu/drm/vc4/vc4_plane.c +@@ -297,6 +297,9 @@ static int vc4_plane_setup_clipping_and_ + vc4_state->y_scaling[0] = vc4_get_scaling_mode(vc4_state->src_h[0], + vc4_state->crtc_h); + ++ vc4_state->is_unity = (vc4_state->x_scaling[0] == VC4_SCALING_NONE && ++ vc4_state->y_scaling[0] == VC4_SCALING_NONE); ++ + if (num_planes > 1) { + vc4_state->is_yuv = true; + +@@ -312,24 +315,17 @@ static int vc4_plane_setup_clipping_and_ + vc4_get_scaling_mode(vc4_state->src_h[1], + vc4_state->crtc_h); + +- /* YUV conversion requires that scaling be enabled, +- * even on a plane that's otherwise 1:1. Choose TPZ +- * for simplicity. ++ /* YUV conversion requires that horizontal scaling be enabled, ++ * even on a plane that's otherwise 1:1. Looks like only PPF ++ * works in that case, so let's pick that one. + */ +- if (vc4_state->x_scaling[0] == VC4_SCALING_NONE) +- vc4_state->x_scaling[0] = VC4_SCALING_TPZ; +- if (vc4_state->y_scaling[0] == VC4_SCALING_NONE) +- vc4_state->y_scaling[0] = VC4_SCALING_TPZ; ++ if (vc4_state->is_unity) ++ vc4_state->x_scaling[0] = VC4_SCALING_PPF; + } else { + vc4_state->x_scaling[1] = VC4_SCALING_NONE; + vc4_state->y_scaling[1] = VC4_SCALING_NONE; + } + +- vc4_state->is_unity = (vc4_state->x_scaling[0] == VC4_SCALING_NONE && +- vc4_state->y_scaling[0] == VC4_SCALING_NONE && +- vc4_state->x_scaling[1] == VC4_SCALING_NONE && +- vc4_state->y_scaling[1] == VC4_SCALING_NONE); +- + /* No configuring scaling on the cursor plane, since it gets + non-vblank-synced updates, and scaling requires requires + LBM changes which have to be vblank-synced. +@@ -621,7 +617,10 @@ static int vc4_plane_mode_set(struct drm + vc4_dlist_write(vc4_state, SCALER_CSC2_ITR_R_601_5); + } + +- if (!vc4_state->is_unity) { ++ if (vc4_state->x_scaling[0] != VC4_SCALING_NONE || ++ vc4_state->x_scaling[1] != VC4_SCALING_NONE || ++ vc4_state->y_scaling[0] != VC4_SCALING_NONE || ++ vc4_state->y_scaling[1] != VC4_SCALING_NONE) { + /* LBM Base Address. */ + if (vc4_state->y_scaling[0] != VC4_SCALING_NONE || + vc4_state->y_scaling[1] != VC4_SCALING_NONE) { diff --git a/queue-4.18/ext4-avoid-arithemetic-overflow-that-can-trigger-a-bug.patch b/queue-4.18/ext4-avoid-arithemetic-overflow-that-can-trigger-a-bug.patch new file mode 100644 index 00000000000..9051d1bb398 --- /dev/null +++ b/queue-4.18/ext4-avoid-arithemetic-overflow-that-can-trigger-a-bug.patch @@ -0,0 +1,58 @@ +From bcd8e91f98c156f4b1ebcfacae675f9cfd962441 Mon Sep 17 00:00:00 2001 +From: Theodore Ts'o +Date: Sat, 1 Sep 2018 12:45:04 -0400 +Subject: ext4: avoid arithemetic overflow that can trigger a BUG + +From: Theodore Ts'o + +commit bcd8e91f98c156f4b1ebcfacae675f9cfd962441 upstream. + +A maliciously crafted file system can cause an overflow when the +results of a 64-bit calculation is stored into a 32-bit length +parameter. + +https://bugzilla.kernel.org/show_bug.cgi?id=200623 + +Signed-off-by: Theodore Ts'o +Reported-by: Wen Xu +Cc: stable@vger.kernel.org +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ext4/ext4.h | 3 +++ + fs/ext4/inode.c | 8 ++++++-- + 2 files changed, 9 insertions(+), 2 deletions(-) + +--- a/fs/ext4/ext4.h ++++ b/fs/ext4/ext4.h +@@ -675,6 +675,9 @@ enum { + /* Max physical block we can address w/o extents */ + #define EXT4_MAX_BLOCK_FILE_PHYS 0xFFFFFFFF + ++/* Max logical block we can support */ ++#define EXT4_MAX_LOGICAL_BLOCK 0xFFFFFFFF ++ + /* + * Structure of an inode on the disk + */ +--- a/fs/ext4/inode.c ++++ b/fs/ext4/inode.c +@@ -3412,12 +3412,16 @@ static int ext4_iomap_begin(struct inode + { + struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); + unsigned int blkbits = inode->i_blkbits; +- unsigned long first_block = offset >> blkbits; +- unsigned long last_block = (offset + length - 1) >> blkbits; ++ unsigned long first_block, last_block; + struct ext4_map_blocks map; + bool delalloc = false; + int ret; + ++ if ((offset >> blkbits) > EXT4_MAX_LOGICAL_BLOCK) ++ return -EINVAL; ++ first_block = offset >> blkbits; ++ last_block = min_t(loff_t, (offset + length - 1) >> blkbits, ++ EXT4_MAX_LOGICAL_BLOCK); + + if (flags & IOMAP_REPORT) { + if (ext4_has_inline_data(inode)) { diff --git a/queue-4.18/ext4-avoid-divide-by-zero-fault-when-deleting-corrupted-inline-directories.patch b/queue-4.18/ext4-avoid-divide-by-zero-fault-when-deleting-corrupted-inline-directories.patch new file mode 100644 index 00000000000..8ca0813c8bc --- /dev/null +++ b/queue-4.18/ext4-avoid-divide-by-zero-fault-when-deleting-corrupted-inline-directories.patch @@ -0,0 +1,92 @@ +From 4d982e25d0bdc83d8c64e66fdeca0b89240b3b85 Mon Sep 17 00:00:00 2001 +From: Theodore Ts'o +Date: Mon, 27 Aug 2018 09:22:45 -0400 +Subject: ext4: avoid divide by zero fault when deleting corrupted inline directories + +From: Theodore Ts'o + +commit 4d982e25d0bdc83d8c64e66fdeca0b89240b3b85 upstream. + +A specially crafted file system can trick empty_inline_dir() into +reading past the last valid entry in a inline directory, and then run +into the end of xattr marker. This will trigger a divide by zero +fault. Fix this by using the size of the inline directory instead of +dir->i_size. + +Also clean up error reporting in __ext4_check_dir_entry so that the +message is clearer and more understandable --- and avoids the division +by zero trap if the size passed in is zero. (I'm not sure why we +coded it that way in the first place; printing offset % size is +actually more confusing and less useful.) + +https://bugzilla.kernel.org/show_bug.cgi?id=200933 + +Signed-off-by: Theodore Ts'o +Reported-by: Wen Xu +Cc: stable@vger.kernel.org +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ext4/dir.c | 20 +++++++++----------- + fs/ext4/inline.c | 4 +++- + 2 files changed, 12 insertions(+), 12 deletions(-) + +--- a/fs/ext4/dir.c ++++ b/fs/ext4/dir.c +@@ -76,7 +76,7 @@ int __ext4_check_dir_entry(const char *f + else if (unlikely(rlen < EXT4_DIR_REC_LEN(de->name_len))) + error_msg = "rec_len is too small for name_len"; + else if (unlikely(((char *) de - buf) + rlen > size)) +- error_msg = "directory entry across range"; ++ error_msg = "directory entry overrun"; + else if (unlikely(le32_to_cpu(de->inode) > + le32_to_cpu(EXT4_SB(dir->i_sb)->s_es->s_inodes_count))) + error_msg = "inode out of bounds"; +@@ -85,18 +85,16 @@ int __ext4_check_dir_entry(const char *f + + if (filp) + ext4_error_file(filp, function, line, bh->b_blocknr, +- "bad entry in directory: %s - offset=%u(%u), " +- "inode=%u, rec_len=%d, name_len=%d", +- error_msg, (unsigned) (offset % size), +- offset, le32_to_cpu(de->inode), +- rlen, de->name_len); ++ "bad entry in directory: %s - offset=%u, " ++ "inode=%u, rec_len=%d, name_len=%d, size=%d", ++ error_msg, offset, le32_to_cpu(de->inode), ++ rlen, de->name_len, size); + else + ext4_error_inode(dir, function, line, bh->b_blocknr, +- "bad entry in directory: %s - offset=%u(%u), " +- "inode=%u, rec_len=%d, name_len=%d", +- error_msg, (unsigned) (offset % size), +- offset, le32_to_cpu(de->inode), +- rlen, de->name_len); ++ "bad entry in directory: %s - offset=%u, " ++ "inode=%u, rec_len=%d, name_len=%d, size=%d", ++ error_msg, offset, le32_to_cpu(de->inode), ++ rlen, de->name_len, size); + + return 1; + } +--- a/fs/ext4/inline.c ++++ b/fs/ext4/inline.c +@@ -1753,6 +1753,7 @@ bool empty_inline_dir(struct inode *dir, + { + int err, inline_size; + struct ext4_iloc iloc; ++ size_t inline_len; + void *inline_pos; + unsigned int offset; + struct ext4_dir_entry_2 *de; +@@ -1780,8 +1781,9 @@ bool empty_inline_dir(struct inode *dir, + goto out; + } + ++ inline_len = ext4_get_inline_size(dir); + offset = EXT4_INLINE_DOTDOT_SIZE; +- while (offset < dir->i_size) { ++ while (offset < inline_len) { + de = ext4_get_inline_entry(dir, &iloc, offset, + &inline_pos, &inline_size); + if (ext4_check_dir_entry(dir, NULL, de, diff --git a/queue-4.18/ext4-check-to-make-sure-the-rename-2-s-destination-is-not-freed.patch b/queue-4.18/ext4-check-to-make-sure-the-rename-2-s-destination-is-not-freed.patch new file mode 100644 index 00000000000..bec7223eec4 --- /dev/null +++ b/queue-4.18/ext4-check-to-make-sure-the-rename-2-s-destination-is-not-freed.patch @@ -0,0 +1,40 @@ +From b50282f3241acee880514212d88b6049fb5039c8 Mon Sep 17 00:00:00 2001 +From: Theodore Ts'o +Date: Mon, 27 Aug 2018 01:47:09 -0400 +Subject: ext4: check to make sure the rename(2)'s destination is not freed + +From: Theodore Ts'o + +commit b50282f3241acee880514212d88b6049fb5039c8 upstream. + +If the destination of the rename(2) system call exists, the inode's +link count (i_nlinks) must be non-zero. If it is, the inode can end +up on the orphan list prematurely, leading to all sorts of hilarity, +including a use-after-free. + +https://bugzilla.kernel.org/show_bug.cgi?id=200931 + +Signed-off-by: Theodore Ts'o +Reported-by: Wen Xu +Cc: stable@vger.kernel.org +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ext4/namei.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +--- a/fs/ext4/namei.c ++++ b/fs/ext4/namei.c +@@ -3478,6 +3478,12 @@ static int ext4_rename(struct inode *old + int credits; + u8 old_file_type; + ++ if (new.inode && new.inode->i_nlink == 0) { ++ EXT4_ERROR_INODE(new.inode, ++ "target of rename is already freed"); ++ return -EFSCORRUPTED; ++ } ++ + if ((ext4_test_inode_flag(new_dir, EXT4_INODE_PROJINHERIT)) && + (!projid_eq(EXT4_I(new_dir)->i_projid, + EXT4_I(old_dentry->d_inode)->i_projid))) diff --git a/queue-4.18/ext4-dax-add-ext4_bmap-to-ext4_dax_aops.patch b/queue-4.18/ext4-dax-add-ext4_bmap-to-ext4_dax_aops.patch new file mode 100644 index 00000000000..1f7432aad23 --- /dev/null +++ b/queue-4.18/ext4-dax-add-ext4_bmap-to-ext4_dax_aops.patch @@ -0,0 +1,38 @@ +From 94dbb63117e82253c9592816aa4465f0a9c94850 Mon Sep 17 00:00:00 2001 +From: Toshi Kani +Date: Sat, 15 Sep 2018 21:23:41 -0400 +Subject: ext4, dax: add ext4_bmap to ext4_dax_aops + +From: Toshi Kani + +commit 94dbb63117e82253c9592816aa4465f0a9c94850 upstream. + +Ext4 mount path calls .bmap to the journal inode. This currently +works for the DAX mount case because ext4_iget() always set +'ext4_da_aops' to any regular files. + +In preparation to fix ext4_iget() to set 'ext4_dax_aops' for ext4 +DAX files, add ext4_bmap() to 'ext4_dax_aops', since bmap works for +DAX inodes. + +Fixes: 5f0663bb4a64 ("ext4, dax: introduce ext4_dax_aops") +Signed-off-by: Toshi Kani +Signed-off-by: Theodore Ts'o +Suggested-by: Jan Kara +Cc: stable@vger.kernel.org +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ext4/inode.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/fs/ext4/inode.c ++++ b/fs/ext4/inode.c +@@ -3951,6 +3951,7 @@ static const struct address_space_operat + .writepages = ext4_dax_writepages, + .direct_IO = noop_direct_IO, + .set_page_dirty = noop_set_page_dirty, ++ .bmap = ext4_bmap, + .invalidatepage = noop_invalidatepage, + }; + diff --git a/queue-4.18/ext4-dax-set-ext4_dax_aops-for-dax-files.patch b/queue-4.18/ext4-dax-set-ext4_dax_aops-for-dax-files.patch new file mode 100644 index 00000000000..68c5ddce7ee --- /dev/null +++ b/queue-4.18/ext4-dax-set-ext4_dax_aops-for-dax-files.patch @@ -0,0 +1,62 @@ +From cce6c9f7e6029caee45c459db5b3e78fec6973cb Mon Sep 17 00:00:00 2001 +From: Toshi Kani +Date: Sat, 15 Sep 2018 21:37:59 -0400 +Subject: ext4, dax: set ext4_dax_aops for dax files + +From: Toshi Kani + +commit cce6c9f7e6029caee45c459db5b3e78fec6973cb upstream. + +Sync syscall to DAX file needs to flush processor cache, but it +currently does not flush to existing DAX files. This is because +'ext4_da_aops' is set to address_space_operations of existing DAX +files, instead of 'ext4_dax_aops', since S_DAX flag is set after +ext4_set_aops() in the open path. + + New file + -------- + lookup_open + ext4_create + __ext4_new_inode + ext4_set_inode_flags // Set S_DAX flag + ext4_set_aops // Set aops to ext4_dax_aops + + Existing file + ------------- + lookup_open + ext4_lookup + ext4_iget + ext4_set_aops // Set aops to ext4_da_aops + ext4_set_inode_flags // Set S_DAX flag + +Change ext4_iget() to initialize i_flags before ext4_set_aops(). + +Fixes: 5f0663bb4a64 ("ext4, dax: introduce ext4_dax_aops") +Signed-off-by: Toshi Kani +Signed-off-by: Theodore Ts'o +Suggested-by: Jan Kara +Cc: stable@vger.kernel.org +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ext4/inode.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/fs/ext4/inode.c ++++ b/fs/ext4/inode.c +@@ -4861,6 +4861,7 @@ struct inode *ext4_iget(struct super_blo + * not initialized on a new filesystem. */ + } + ei->i_flags = le32_to_cpu(raw_inode->i_flags); ++ ext4_set_inode_flags(inode); + inode->i_blocks = ext4_inode_blocks(raw_inode, ei); + ei->i_file_acl = le32_to_cpu(raw_inode->i_file_acl_lo); + if (ext4_has_feature_64bit(sb)) +@@ -5010,7 +5011,6 @@ struct inode *ext4_iget(struct super_blo + goto bad_inode; + } + brelse(iloc.bh); +- ext4_set_inode_flags(inode); + + unlock_new_inode(inode); + return inode; diff --git a/queue-4.18/ext4-don-t-mark-mmp-buffer-head-dirty.patch b/queue-4.18/ext4-don-t-mark-mmp-buffer-head-dirty.patch new file mode 100644 index 00000000000..4e671c5f642 --- /dev/null +++ b/queue-4.18/ext4-don-t-mark-mmp-buffer-head-dirty.patch @@ -0,0 +1,39 @@ +From fe18d649891d813964d3aaeebad873f281627fbc Mon Sep 17 00:00:00 2001 +From: Li Dongyang +Date: Sat, 15 Sep 2018 17:11:25 -0400 +Subject: ext4: don't mark mmp buffer head dirty + +From: Li Dongyang + +commit fe18d649891d813964d3aaeebad873f281627fbc upstream. + +Marking mmp bh dirty before writing it will make writeback +pick up mmp block later and submit a write, we don't want the +duplicate write as kmmpd thread should have full control of +reading and writing the mmp block. +Another reason is we will also have random I/O error on +the writeback request when blk integrity is enabled, because +kmmpd could modify the content of the mmp block(e.g. setting +new seq and time) while the mmp block is under I/O requested +by writeback. + +Signed-off-by: Li Dongyang +Signed-off-by: Theodore Ts'o +Reviewed-by: Andreas Dilger +Cc: stable@vger.kernel.org +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ext4/mmp.c | 1 - + 1 file changed, 1 deletion(-) + +--- a/fs/ext4/mmp.c ++++ b/fs/ext4/mmp.c +@@ -49,7 +49,6 @@ static int write_mmp_block(struct super_ + */ + sb_start_write(sb); + ext4_mmp_csum_set(sb, mmp); +- mark_buffer_dirty(bh); + lock_buffer(bh); + bh->b_end_io = end_buffer_write_sync; + get_bh(bh); diff --git a/queue-4.18/ext4-fix-online-resize-s-handling-of-a-too-small-final-block-group.patch b/queue-4.18/ext4-fix-online-resize-s-handling-of-a-too-small-final-block-group.patch new file mode 100644 index 00000000000..f47f3140191 --- /dev/null +++ b/queue-4.18/ext4-fix-online-resize-s-handling-of-a-too-small-final-block-group.patch @@ -0,0 +1,62 @@ +From f0a459dec5495a3580f8d784555e6f8f3bf7f263 Mon Sep 17 00:00:00 2001 +From: Theodore Ts'o +Date: Mon, 3 Sep 2018 22:19:43 -0400 +Subject: ext4: fix online resize's handling of a too-small final block group + +From: Theodore Ts'o + +commit f0a459dec5495a3580f8d784555e6f8f3bf7f263 upstream. + +Avoid growing the file system to an extent so that the last block +group is too small to hold all of the metadata that must be stored in +the block group. + +This problem can be triggered with the following reproducer: + +umount /mnt +mke2fs -F -m0 -b 4096 -t ext4 -O resize_inode,^has_journal \ + -E resize=1073741824 /tmp/foo.img 128M +mount /tmp/foo.img /mnt +truncate --size 1708M /tmp/foo.img +resize2fs /dev/loop0 295400 +umount /mnt +e2fsck -fy /tmp/foo.img + +Reported-by: Torsten Hilbrich +Signed-off-by: Theodore Ts'o +Cc: stable@vger.kernel.org +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ext4/resize.c | 20 ++++++++++++++++++++ + 1 file changed, 20 insertions(+) + +--- a/fs/ext4/resize.c ++++ b/fs/ext4/resize.c +@@ -1986,6 +1986,26 @@ retry: + } + } + ++ /* ++ * Make sure the last group has enough space so that it's ++ * guaranteed to have enough space for all metadata blocks ++ * that it might need to hold. (We might not need to store ++ * the inode table blocks in the last block group, but there ++ * will be cases where this might be needed.) ++ */ ++ if ((ext4_group_first_block_no(sb, n_group) + ++ ext4_group_overhead_blocks(sb, n_group) + 2 + ++ sbi->s_itb_per_group + sbi->s_cluster_ratio) >= n_blocks_count) { ++ n_blocks_count = ext4_group_first_block_no(sb, n_group); ++ n_group--; ++ n_blocks_count_retry = 0; ++ if (resize_inode) { ++ iput(resize_inode); ++ resize_inode = NULL; ++ } ++ goto retry; ++ } ++ + /* extend the last group */ + if (n_group == o_group) + add = n_blocks_count - o_blocks_count; diff --git a/queue-4.18/ext4-fix-online-resizing-for-bigalloc-file-systems-with-a-1k-block-size.patch b/queue-4.18/ext4-fix-online-resizing-for-bigalloc-file-systems-with-a-1k-block-size.patch new file mode 100644 index 00000000000..936be51f4a4 --- /dev/null +++ b/queue-4.18/ext4-fix-online-resizing-for-bigalloc-file-systems-with-a-1k-block-size.patch @@ -0,0 +1,41 @@ +From 5f8c10936fab2b69a487400f2872902e597dd320 Mon Sep 17 00:00:00 2001 +From: Theodore Ts'o +Date: Mon, 3 Sep 2018 22:25:01 -0400 +Subject: ext4: fix online resizing for bigalloc file systems with a 1k block size + +From: Theodore Ts'o + +commit 5f8c10936fab2b69a487400f2872902e597dd320 upstream. + +An online resize of a file system with the bigalloc feature enabled +and a 1k block size would be refused since ext4_resize_begin() did not +understand s_first_data_block is 0 for all bigalloc file systems, even +when the block size is 1k. + +Signed-off-by: Theodore Ts'o +Cc: stable@vger.kernel.org +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ext4/resize.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/fs/ext4/resize.c ++++ b/fs/ext4/resize.c +@@ -19,6 +19,7 @@ + + int ext4_resize_begin(struct super_block *sb) + { ++ struct ext4_sb_info *sbi = EXT4_SB(sb); + int ret = 0; + + if (!capable(CAP_SYS_RESOURCE)) +@@ -29,7 +30,7 @@ int ext4_resize_begin(struct super_block + * because the user tools have no way of handling this. Probably a + * bad time to do it anyways. + */ +- if (EXT4_SB(sb)->s_sbh->b_blocknr != ++ if (EXT4_B2C(sbi, sbi->s_sbh->b_blocknr) != + le32_to_cpu(EXT4_SB(sb)->s_es->s_first_data_block)) { + ext4_warning(sb, "won't resize using backup superblock at %llu", + (unsigned long long)EXT4_SB(sb)->s_sbh->b_blocknr); diff --git a/queue-4.18/ext4-recalucate-superblock-checksum-after-updating-free-blocks-inodes.patch b/queue-4.18/ext4-recalucate-superblock-checksum-after-updating-free-blocks-inodes.patch new file mode 100644 index 00000000000..582a3ffa20b --- /dev/null +++ b/queue-4.18/ext4-recalucate-superblock-checksum-after-updating-free-blocks-inodes.patch @@ -0,0 +1,61 @@ +From 4274f516d4bc50648a4d97e4f67ecbd7b65cde4a Mon Sep 17 00:00:00 2001 +From: Theodore Ts'o +Date: Sat, 1 Sep 2018 14:42:14 -0400 +Subject: ext4: recalucate superblock checksum after updating free blocks/inodes + +From: Theodore Ts'o + +commit 4274f516d4bc50648a4d97e4f67ecbd7b65cde4a upstream. + +When mounting the superblock, ext4_fill_super() calculates the free +blocks and free inodes and stores them in the superblock. It's not +strictly necessary, since we don't use them any more, but it's nice to +keep them roughly aligned to reality. + +Since it's not critical for file system correctness, the code doesn't +call ext4_commit_super(). The problem is that it's in +ext4_commit_super() that we recalculate the superblock checksum. So +if we're not going to call ext4_commit_super(), we need to call +ext4_superblock_csum_set() to make sure the superblock checksum is +consistent. + +Most of the time, this doesn't matter, since we end up calling +ext4_commit_super() very soon thereafter, and definitely by the time +the file system is unmounted. However, it doesn't work in this +sequence: + +mke2fs -Fq -t ext4 /dev/vdc 128M +mount /dev/vdc /vdc +cp xfstests/git-versions /vdc +godown /vdc +umount /vdc +mount /dev/vdc +tune2fs -l /dev/vdc + +With this commit, the "tune2fs -l" no longer fails. + +Reported-by: Chengguang Xu +Signed-off-by: Theodore Ts'o +Cc: stable@vger.kernel.org +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ext4/super.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/fs/ext4/super.c ++++ b/fs/ext4/super.c +@@ -4357,11 +4357,13 @@ no_journal: + block = ext4_count_free_clusters(sb); + ext4_free_blocks_count_set(sbi->s_es, + EXT4_C2B(sbi, block)); ++ ext4_superblock_csum_set(sb); + err = percpu_counter_init(&sbi->s_freeclusters_counter, block, + GFP_KERNEL); + if (!err) { + unsigned long freei = ext4_count_free_inodes(sb); + sbi->s_es->s_free_inodes_count = cpu_to_le32(freei); ++ ext4_superblock_csum_set(sb); + err = percpu_counter_init(&sbi->s_freeinodes_counter, freei, + GFP_KERNEL); + } diff --git a/queue-4.18/ext4-show-test_dummy_encryption-mount-option-in-proc-mounts.patch b/queue-4.18/ext4-show-test_dummy_encryption-mount-option-in-proc-mounts.patch new file mode 100644 index 00000000000..8ac726310c9 --- /dev/null +++ b/queue-4.18/ext4-show-test_dummy_encryption-mount-option-in-proc-mounts.patch @@ -0,0 +1,32 @@ +From 338affb548c243d2af25b1ca628e67819350de6b Mon Sep 17 00:00:00 2001 +From: Eric Biggers +Date: Sat, 15 Sep 2018 14:28:26 -0400 +Subject: ext4: show test_dummy_encryption mount option in /proc/mounts + +From: Eric Biggers + +commit 338affb548c243d2af25b1ca628e67819350de6b upstream. + +When in effect, add "test_dummy_encryption" to _ext4_show_options() so +that it is shown in /proc/mounts and other relevant procfs files. + +Signed-off-by: Eric Biggers +Signed-off-by: Theodore Ts'o +Cc: stable@vger.kernel.org +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ext4/super.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/fs/ext4/super.c ++++ b/fs/ext4/super.c +@@ -2126,6 +2126,8 @@ static int _ext4_show_options(struct seq + SEQ_OPTS_PRINT("max_dir_size_kb=%u", sbi->s_max_dir_size_kb); + if (test_opt(sb, DATA_ERR_ABORT)) + SEQ_OPTS_PUTS("data_err=abort"); ++ if (DUMMY_ENCRYPTION_ENABLED(sbi)) ++ SEQ_OPTS_PUTS("test_dummy_encryption"); + + ext4_show_quota_options(seq, sb); + return 0; diff --git a/queue-4.18/libata-mask-swap-internal-and-hardware-tag.patch b/queue-4.18/libata-mask-swap-internal-and-hardware-tag.patch new file mode 100644 index 00000000000..f08007df5e3 --- /dev/null +++ b/queue-4.18/libata-mask-swap-internal-and-hardware-tag.patch @@ -0,0 +1,57 @@ +From 7ce5c8cd753f9afa8e79e9ec40351998e354f239 Mon Sep 17 00:00:00 2001 +From: Jens Axboe +Date: Thu, 20 Sep 2018 08:30:55 -0600 +Subject: libata: mask swap internal and hardware tag + +From: Jens Axboe + +commit 7ce5c8cd753f9afa8e79e9ec40351998e354f239 upstream. + +hen we're comparing the hardware completion mask passed in from the +driver with the internal tag pending mask, we need to account for the +fact that the internal tag is different from the hardware tag. If not, +then we can end up either prematurely completing the internal tag (since +it's not set in the hw mask), or simply flag an error: + +ata2: illegal qc_active transition (100000000->00000001) + +If the internal tag is set, then swap that with the hardware tag in this +case before comparing with what the hardware reports. + +Fixes: 28361c403683 ("libata: add extra internal command") +Buglink: https://bugzilla.kernel.org/show_bug.cgi?id=201151 +Cc: stable@vger.kernel.org +Reported-by: Paul Sbarra +Tested-by: Paul Sbarra +Signed-off-by: Jens Axboe +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/ata/libata-core.c | 14 ++++++++++++-- + 1 file changed, 12 insertions(+), 2 deletions(-) + +--- a/drivers/ata/libata-core.c ++++ b/drivers/ata/libata-core.c +@@ -5358,10 +5358,20 @@ void ata_qc_complete(struct ata_queued_c + */ + int ata_qc_complete_multiple(struct ata_port *ap, u64 qc_active) + { ++ u64 done_mask, ap_qc_active = ap->qc_active; + int nr_done = 0; +- u64 done_mask; + +- done_mask = ap->qc_active ^ qc_active; ++ /* ++ * If the internal tag is set on ap->qc_active, then we care about ++ * bit0 on the passed in qc_active mask. Move that bit up to match ++ * the internal tag. ++ */ ++ if (ap_qc_active & (1ULL << ATA_TAG_INTERNAL)) { ++ qc_active |= (qc_active & 0x01) << ATA_TAG_INTERNAL; ++ qc_active ^= qc_active & 0x01; ++ } ++ ++ done_mask = ap_qc_active ^ qc_active; + + if (unlikely(done_mask & qc_active)) { + ata_port_err(ap, "illegal qc_active transition (%08llx->%08llx)\n", diff --git a/queue-4.18/ocfs2-fix-ocfs2-read-block-panic.patch b/queue-4.18/ocfs2-fix-ocfs2-read-block-panic.patch new file mode 100644 index 00000000000..7b41576f687 --- /dev/null +++ b/queue-4.18/ocfs2-fix-ocfs2-read-block-panic.patch @@ -0,0 +1,87 @@ +From 234b69e3e089d850a98e7b3145bd00e9b52b1111 Mon Sep 17 00:00:00 2001 +From: Junxiao Bi +Date: Thu, 20 Sep 2018 12:22:51 -0700 +Subject: ocfs2: fix ocfs2 read block panic + +From: Junxiao Bi + +commit 234b69e3e089d850a98e7b3145bd00e9b52b1111 upstream. + +While reading block, it is possible that io error return due to underlying +storage issue, in this case, BH_NeedsValidate was left in the buffer head. +Then when reading the very block next time, if it was already linked into +journal, that will trigger the following panic. + +[203748.702517] kernel BUG at fs/ocfs2/buffer_head_io.c:342! +[203748.702533] invalid opcode: 0000 [#1] SMP +[203748.702561] Modules linked in: ocfs2 ocfs2_dlmfs ocfs2_stack_o2cb ocfs2_dlm ocfs2_nodemanager ocfs2_stackglue configfs sunrpc dm_switch dm_queue_length dm_multipath bonding be2iscsi iscsi_boot_sysfs bnx2i cnic uio cxgb4i iw_cxgb4 cxgb4 cxgb3i libcxgbi iw_cxgb3 cxgb3 mdio ib_iser rdma_cm ib_cm iw_cm ib_sa ib_mad ib_core ib_addr ipv6 iscsi_tcp libiscsi_tcp libiscsi scsi_transport_iscsi ipmi_devintf iTCO_wdt iTCO_vendor_support dcdbas ipmi_ssif i2c_core ipmi_si ipmi_msghandler acpi_pad pcspkr sb_edac edac_core lpc_ich mfd_core shpchp sg tg3 ptp pps_core ext4 jbd2 mbcache2 sr_mod cdrom sd_mod ahci libahci megaraid_sas wmi dm_mirror dm_region_hash dm_log dm_mod +[203748.703024] CPU: 7 PID: 38369 Comm: touch Not tainted 4.1.12-124.18.6.el6uek.x86_64 #2 +[203748.703045] Hardware name: Dell Inc. PowerEdge R620/0PXXHP, BIOS 2.5.2 01/28/2015 +[203748.703067] task: ffff880768139c00 ti: ffff88006ff48000 task.ti: ffff88006ff48000 +[203748.703088] RIP: 0010:[] [] ocfs2_read_blocks+0x669/0x7f0 [ocfs2] +[203748.703130] RSP: 0018:ffff88006ff4b818 EFLAGS: 00010206 +[203748.703389] RAX: 0000000008620029 RBX: ffff88006ff4b910 RCX: 0000000000000000 +[203748.703885] RDX: 0000000000000001 RSI: 0000000000000000 RDI: 00000000023079fe +[203748.704382] RBP: ffff88006ff4b8d8 R08: 0000000000000000 R09: ffff8807578c25b0 +[203748.704877] R10: 000000000f637376 R11: 000000003030322e R12: 0000000000000000 +[203748.705373] R13: ffff88006ff4b910 R14: ffff880732fe38f0 R15: 0000000000000000 +[203748.705871] FS: 00007f401992c700(0000) GS:ffff880bfebc0000(0000) knlGS:0000000000000000 +[203748.706370] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +[203748.706627] CR2: 00007f4019252440 CR3: 00000000a621e000 CR4: 0000000000060670 +[203748.707124] Stack: +[203748.707371] ffff88006ff4b828 ffffffffa0609f52 ffff88006ff4b838 0000000000000001 +[203748.707885] 0000000000000000 0000000000000000 ffff880bf67c3800 ffffffffa05eca00 +[203748.708399] 00000000023079ff ffffffff81c58b80 0000000000000000 0000000000000000 +[203748.708915] Call Trace: +[203748.709175] [] ? ocfs2_inode_cache_io_unlock+0x12/0x20 [ocfs2] +[203748.709680] [] ? ocfs2_empty_dir_filldir+0x80/0x80 [ocfs2] +[203748.710185] [] ocfs2_read_dir_block_direct+0x3b/0x200 [ocfs2] +[203748.710691] [] ocfs2_prepare_dx_dir_for_insert.isra.57+0x19f/0xf60 [ocfs2] +[203748.711204] [] ? ocfs2_metadata_cache_io_unlock+0x1f/0x30 [ocfs2] +[203748.711716] [] ocfs2_prepare_dir_for_insert+0x13a/0x890 [ocfs2] +[203748.712227] [] ? ocfs2_check_dir_for_entry+0x8e/0x140 [ocfs2] +[203748.712737] [] ocfs2_mknod+0x4b2/0x1370 [ocfs2] +[203748.713003] [] ocfs2_create+0x65/0x170 [ocfs2] +[203748.713263] [] vfs_create+0xdb/0x150 +[203748.713518] [] do_last+0x815/0x1210 +[203748.713772] [] ? path_init+0xb9/0x450 +[203748.714123] [] path_openat+0x80/0x600 +[203748.714378] [] ? handle_pte_fault+0xd15/0x1620 +[203748.714634] [] do_filp_open+0x3a/0xb0 +[203748.714888] [] ? __alloc_fd+0xa7/0x130 +[203748.715143] [] do_sys_open+0x12c/0x220 +[203748.715403] [] ? syscall_trace_enter_phase1+0x11b/0x180 +[203748.715668] [] ? system_call_after_swapgs+0xe9/0x190 +[203748.715928] [] SyS_open+0x1e/0x20 +[203748.716184] [] system_call_fastpath+0x18/0xd7 +[203748.716440] Code: 00 00 48 8b 7b 08 48 83 c3 10 45 89 f8 44 89 e1 44 89 f2 4c 89 ee e8 07 06 11 e1 48 8b 03 48 85 c0 75 df 8b 5d c8 e9 4d fa ff ff <0f> 0b 48 8b 7d a0 e8 dc c6 06 00 48 b8 00 00 00 00 00 00 00 10 +[203748.717505] RIP [] ocfs2_read_blocks+0x669/0x7f0 [ocfs2] +[203748.717775] RSP + +Joesph ever reported a similar panic. +Link: https://oss.oracle.com/pipermail/ocfs2-devel/2013-May/008931.html + +Link: http://lkml.kernel.org/r/20180912063207.29484-1-junxiao.bi@oracle.com +Signed-off-by: Junxiao Bi +Cc: Joseph Qi +Cc: Mark Fasheh +Cc: Joel Becker +Cc: Changwei Ge +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ocfs2/buffer_head_io.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/fs/ocfs2/buffer_head_io.c ++++ b/fs/ocfs2/buffer_head_io.c +@@ -342,6 +342,7 @@ int ocfs2_read_blocks(struct ocfs2_cachi + * for this bh as it's not marked locally + * uptodate. */ + status = -EIO; ++ clear_buffer_needs_validate(bh); + put_bh(bh); + bhs[i] = NULL; + continue; diff --git a/queue-4.18/revert-rpmsg-core-add-support-to-power-domains-for.patch b/queue-4.18/revert-rpmsg-core-add-support-to-power-domains-for.patch new file mode 100644 index 00000000000..5cd1f215025 --- /dev/null +++ b/queue-4.18/revert-rpmsg-core-add-support-to-power-domains-for.patch @@ -0,0 +1,67 @@ +From 2e7ee255a2780a5e5e8e35588cd08c3afab4eef3 Mon Sep 17 00:00:00 2001 +From: Greg Kroah-Hartman +Date: Wed, 26 Sep 2018 13:53:39 +0200 +Subject: Revert "rpmsg: core: add support to power domains for devices" + +From: Greg Kroah-Hartman + +This reverts commit e5d9ae0077a5cf336d298002959dc0c8dcfe7b89 which is +commit fe782affd0f440a4e60e2cc81b8f2eccb2923113 upstream + +Rafael reports that this patch causes problems: + > -rc2 looks good. There is a problem on dragonboard during boot that was + > introduced in v4.14.71 that I didn't notice last week. We'll bisect it + > and report back later this week. dragonboard on the other branches (4.9, + > 4.18, mainline) looks fine. + + As Dan pointed out, during validation, we have bisected this issue on + a dragonboard 410c (can't find root device) to the following commit + for v4.14: + + [1ed3a9307230] rpmsg: core: add support to power domains for devices + + There is an on-going discussion on "[PATCH] rpmsg: core: add support + to power domains for devices" about this patch having other + dependencies and breaking something else on v4.14 as well. + +so drop it. + +Reported-by: Rafael Tinoco +Cc: Srinivas Kandagatla +Cc: Bjorn Andersson +Cc: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/rpmsg/rpmsg_core.c | 7 ------- + 1 file changed, 7 deletions(-) + +--- a/drivers/rpmsg/rpmsg_core.c ++++ b/drivers/rpmsg/rpmsg_core.c +@@ -15,7 +15,6 @@ + #include + #include + #include +-#include + #include + + #include "rpmsg_internal.h" +@@ -450,10 +449,6 @@ static int rpmsg_dev_probe(struct device + struct rpmsg_endpoint *ept = NULL; + int err; + +- err = dev_pm_domain_attach(dev, true); +- if (err) +- goto out; +- + if (rpdrv->callback) { + strncpy(chinfo.name, rpdev->id.name, RPMSG_NAME_SIZE); + chinfo.src = rpdev->src; +@@ -495,8 +490,6 @@ static int rpmsg_dev_remove(struct devic + + rpdrv->remove(rpdev); + +- dev_pm_domain_detach(dev, true); +- + if (rpdev->ept) + rpmsg_destroy_ept(rpdev->ept); + diff --git a/queue-4.18/revert-uapi-linux-keyctl.h-don-t-use-c-reserved-keyword-as-a-struct-member-name.patch b/queue-4.18/revert-uapi-linux-keyctl.h-don-t-use-c-reserved-keyword-as-a-struct-member-name.patch new file mode 100644 index 00000000000..c1d5947927d --- /dev/null +++ b/queue-4.18/revert-uapi-linux-keyctl.h-don-t-use-c-reserved-keyword-as-a-struct-member-name.patch @@ -0,0 +1,61 @@ +From 8c0f9f5b309d627182d5da72a69246f58bde1026 Mon Sep 17 00:00:00 2001 +From: Lubomir Rintel +Date: Mon, 24 Sep 2018 13:18:34 +0100 +Subject: Revert "uapi/linux/keyctl.h: don't use C++ reserved keyword as a struct member name" + +From: Lubomir Rintel + +commit 8c0f9f5b309d627182d5da72a69246f58bde1026 upstream. + +This changes UAPI, breaking iwd and libell: + + ell/key.c: In function 'kernel_dh_compute': + ell/key.c:205:38: error: 'struct keyctl_dh_params' has no member named 'private'; did you mean 'dh_private'? + struct keyctl_dh_params params = { .private = private, + ^~~~~~~ + dh_private + +This reverts commit 8a2336e549d385bb0b46880435b411df8d8200e8. + +Fixes: 8a2336e549d3 ("uapi/linux/keyctl.h: don't use C++ reserved keyword as a struct member name") +Signed-off-by: Lubomir Rintel +Signed-off-by: David Howells +cc: Randy Dunlap +cc: Mat Martineau +cc: Stephan Mueller +cc: James Morris +cc: "Serge E. Hallyn" +cc: Mat Martineau +cc: Andrew Morton +cc: Linus Torvalds +cc: +Signed-off-by: James Morris +Signed-off-by: Greg Kroah-Hartman + +--- + include/uapi/linux/keyctl.h | 2 +- + security/keys/dh.c | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +--- a/include/uapi/linux/keyctl.h ++++ b/include/uapi/linux/keyctl.h +@@ -65,7 +65,7 @@ + + /* keyctl structures */ + struct keyctl_dh_params { +- __s32 dh_private; ++ __s32 private; + __s32 prime; + __s32 base; + }; +--- a/security/keys/dh.c ++++ b/security/keys/dh.c +@@ -300,7 +300,7 @@ long __keyctl_dh_compute(struct keyctl_d + } + dh_inputs.g_size = dlen; + +- dlen = dh_data_from_key(pcopy.dh_private, &dh_inputs.key); ++ dlen = dh_data_from_key(pcopy.private, &dh_inputs.key); + if (dlen < 0) { + ret = dlen; + goto out2; diff --git a/queue-4.18/revert-ubifs-xattr-don-t-operate-on-deleted-inodes.patch b/queue-4.18/revert-ubifs-xattr-don-t-operate-on-deleted-inodes.patch new file mode 100644 index 00000000000..bb6f9da7324 --- /dev/null +++ b/queue-4.18/revert-ubifs-xattr-don-t-operate-on-deleted-inodes.patch @@ -0,0 +1,103 @@ +From f061c1cc404a618858a77aea233fde0aeaad2f2d Mon Sep 17 00:00:00 2001 +From: Richard Weinberger +Date: Sun, 16 Sep 2018 23:57:35 +0200 +Subject: Revert "ubifs: xattr: Don't operate on deleted inodes" + +From: Richard Weinberger + +commit f061c1cc404a618858a77aea233fde0aeaad2f2d upstream. + +This reverts commit 11a6fc3dc743e22fb50f2196ec55bee5140d3c52. +UBIFS wants to assert that xattr operations are only issued on files +with positive link count. The said patch made this operations return +-ENOENT for unlinked files such that the asserts will no longer trigger. +This was wrong since xattr operations are perfectly fine on unlinked +files. +Instead the assertions need to be fixed/removed. + +Cc: +Fixes: 11a6fc3dc743 ("ubifs: xattr: Don't operate on deleted inodes") +Reported-by: Koen Vandeputte +Tested-by: Joel Stanley +Signed-off-by: Richard Weinberger +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ubifs/xattr.c | 24 ------------------------ + 1 file changed, 24 deletions(-) + +--- a/fs/ubifs/xattr.c ++++ b/fs/ubifs/xattr.c +@@ -152,12 +152,6 @@ static int create_xattr(struct ubifs_inf + ui->data_len = size; + + mutex_lock(&host_ui->ui_mutex); +- +- if (!host->i_nlink) { +- err = -ENOENT; +- goto out_noent; +- } +- + host->i_ctime = current_time(host); + host_ui->xattr_cnt += 1; + host_ui->xattr_size += CALC_DENT_SIZE(fname_len(nm)); +@@ -190,7 +184,6 @@ out_cancel: + host_ui->xattr_size -= CALC_XATTR_BYTES(size); + host_ui->xattr_names -= fname_len(nm); + host_ui->flags &= ~UBIFS_CRYPT_FL; +-out_noent: + mutex_unlock(&host_ui->ui_mutex); + out_free: + make_bad_inode(inode); +@@ -242,12 +235,6 @@ static int change_xattr(struct ubifs_inf + mutex_unlock(&ui->ui_mutex); + + mutex_lock(&host_ui->ui_mutex); +- +- if (!host->i_nlink) { +- err = -ENOENT; +- goto out_noent; +- } +- + host->i_ctime = current_time(host); + host_ui->xattr_size -= CALC_XATTR_BYTES(old_size); + host_ui->xattr_size += CALC_XATTR_BYTES(size); +@@ -269,7 +256,6 @@ static int change_xattr(struct ubifs_inf + out_cancel: + host_ui->xattr_size -= CALC_XATTR_BYTES(size); + host_ui->xattr_size += CALC_XATTR_BYTES(old_size); +-out_noent: + mutex_unlock(&host_ui->ui_mutex); + make_bad_inode(inode); + out_free: +@@ -496,12 +482,6 @@ static int remove_xattr(struct ubifs_inf + return err; + + mutex_lock(&host_ui->ui_mutex); +- +- if (!host->i_nlink) { +- err = -ENOENT; +- goto out_noent; +- } +- + host->i_ctime = current_time(host); + host_ui->xattr_cnt -= 1; + host_ui->xattr_size -= CALC_DENT_SIZE(fname_len(nm)); +@@ -521,7 +501,6 @@ out_cancel: + host_ui->xattr_size += CALC_DENT_SIZE(fname_len(nm)); + host_ui->xattr_size += CALC_XATTR_BYTES(ui->data_len); + host_ui->xattr_names += fname_len(nm); +-out_noent: + mutex_unlock(&host_ui->ui_mutex); + ubifs_release_budget(c, &req); + make_bad_inode(inode); +@@ -561,9 +540,6 @@ static int ubifs_xattr_remove(struct ino + + ubifs_assert(inode_is_locked(host)); + +- if (!host->i_nlink) +- return -ENOENT; +- + if (fname_len(&nm) > UBIFS_MAX_NLEN) + return -ENAMETOOLONG; + diff --git a/queue-4.18/scsi-target-iscsi-use-bin2hex-instead-of-a-re-implementation.patch b/queue-4.18/scsi-target-iscsi-use-bin2hex-instead-of-a-re-implementation.patch new file mode 100644 index 00000000000..485fad2f9be --- /dev/null +++ b/queue-4.18/scsi-target-iscsi-use-bin2hex-instead-of-a-re-implementation.patch @@ -0,0 +1,63 @@ +From 8c39e2699f8acb2e29782a834e56306da24937fe Mon Sep 17 00:00:00 2001 +From: Vincent Pelletier +Date: Sun, 9 Sep 2018 04:09:27 +0000 +Subject: scsi: target: iscsi: Use bin2hex instead of a re-implementation + +From: Vincent Pelletier + +commit 8c39e2699f8acb2e29782a834e56306da24937fe upstream. + +Signed-off-by: Vincent Pelletier +Reviewed-by: Mike Christie +Signed-off-by: Martin K. Petersen +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/target/iscsi/iscsi_target_auth.c | 15 +++------------ + 1 file changed, 3 insertions(+), 12 deletions(-) + +--- a/drivers/target/iscsi/iscsi_target_auth.c ++++ b/drivers/target/iscsi/iscsi_target_auth.c +@@ -26,15 +26,6 @@ + #include "iscsi_target_nego.h" + #include "iscsi_target_auth.h" + +-static void chap_binaryhex_to_asciihex(char *dst, char *src, int src_len) +-{ +- int i; +- +- for (i = 0; i < src_len; i++) { +- sprintf(&dst[i*2], "%02x", (int) src[i] & 0xff); +- } +-} +- + static int chap_gen_challenge( + struct iscsi_conn *conn, + int caller, +@@ -50,7 +41,7 @@ static int chap_gen_challenge( + ret = get_random_bytes_wait(chap->challenge, CHAP_CHALLENGE_LENGTH); + if (unlikely(ret)) + return ret; +- chap_binaryhex_to_asciihex(challenge_asciihex, chap->challenge, ++ bin2hex(challenge_asciihex, chap->challenge, + CHAP_CHALLENGE_LENGTH); + /* + * Set CHAP_C, and copy the generated challenge into c_str. +@@ -289,7 +280,7 @@ static int chap_server_compute_md5( + goto out; + } + +- chap_binaryhex_to_asciihex(response, server_digest, MD5_SIGNATURE_SIZE); ++ bin2hex(response, server_digest, MD5_SIGNATURE_SIZE); + pr_debug("[server] MD5 Server Digest: %s\n", response); + + if (memcmp(server_digest, client_digest, MD5_SIGNATURE_SIZE) != 0) { +@@ -411,7 +402,7 @@ static int chap_server_compute_md5( + /* + * Convert response from binary hex to ascii hext. + */ +- chap_binaryhex_to_asciihex(response, digest, MD5_SIGNATURE_SIZE); ++ bin2hex(response, digest, MD5_SIGNATURE_SIZE); + *nr_out_len += sprintf(nr_out_ptr + *nr_out_len, "CHAP_R=0x%s", + response); + *nr_out_len += 1; diff --git a/queue-4.18/scsi-target-iscsi-use-hex2bin-instead-of-a-re-implementation.patch b/queue-4.18/scsi-target-iscsi-use-hex2bin-instead-of-a-re-implementation.patch new file mode 100644 index 00000000000..40cd9dd5a44 --- /dev/null +++ b/queue-4.18/scsi-target-iscsi-use-hex2bin-instead-of-a-re-implementation.patch @@ -0,0 +1,181 @@ +From 1816494330a83f2a064499d8ed2797045641f92c Mon Sep 17 00:00:00 2001 +From: Vincent Pelletier +Date: Sun, 9 Sep 2018 04:09:26 +0000 +Subject: scsi: target: iscsi: Use hex2bin instead of a re-implementation + +From: Vincent Pelletier + +commit 1816494330a83f2a064499d8ed2797045641f92c upstream. + +This change has the following effects, in order of descreasing importance: + +1) Prevent a stack buffer overflow + +2) Do not append an unnecessary NULL to an anyway binary buffer, which + is writing one byte past client_digest when caller is: + chap_string_to_hex(client_digest, chap_r, strlen(chap_r)); + +The latter was found by KASAN (see below) when input value hes expected size +(32 hex chars), and further analysis revealed a stack buffer overflow can +happen when network-received value is longer, allowing an unauthenticated +remote attacker to smash up to 17 bytes after destination buffer (16 bytes +attacker-controlled and one null). As switching to hex2bin requires +specifying destination buffer length, and does not internally append any null, +it solves both issues. + +This addresses CVE-2018-14633. + +Beyond this: + +- Validate received value length and check hex2bin accepted the input, to log + this rejection reason instead of just failing authentication. + +- Only log received CHAP_R and CHAP_C values once they passed sanity checks. + +================================================================== +BUG: KASAN: stack-out-of-bounds in chap_string_to_hex+0x32/0x60 [iscsi_target_mod] +Write of size 1 at addr ffff8801090ef7c8 by task kworker/0:0/1021 + +CPU: 0 PID: 1021 Comm: kworker/0:0 Tainted: G O 4.17.8kasan.sess.connops+ #2 +Hardware name: To be filled by O.E.M. To be filled by O.E.M./Aptio CRB, BIOS 5.6.5 05/19/2014 +Workqueue: events iscsi_target_do_login_rx [iscsi_target_mod] +Call Trace: + dump_stack+0x71/0xac + print_address_description+0x65/0x22e + ? chap_string_to_hex+0x32/0x60 [iscsi_target_mod] + kasan_report.cold.6+0x241/0x2fd + chap_string_to_hex+0x32/0x60 [iscsi_target_mod] + chap_server_compute_md5.isra.2+0x2cb/0x860 [iscsi_target_mod] + ? chap_binaryhex_to_asciihex.constprop.5+0x50/0x50 [iscsi_target_mod] + ? ftrace_caller_op_ptr+0xe/0xe + ? __orc_find+0x6f/0xc0 + ? unwind_next_frame+0x231/0x850 + ? kthread+0x1a0/0x1c0 + ? ret_from_fork+0x35/0x40 + ? ret_from_fork+0x35/0x40 + ? iscsi_target_do_login_rx+0x3bc/0x4c0 [iscsi_target_mod] + ? deref_stack_reg+0xd0/0xd0 + ? iscsi_target_do_login_rx+0x3bc/0x4c0 [iscsi_target_mod] + ? is_module_text_address+0xa/0x11 + ? kernel_text_address+0x4c/0x110 + ? __save_stack_trace+0x82/0x100 + ? ret_from_fork+0x35/0x40 + ? save_stack+0x8c/0xb0 + ? 0xffffffffc1660000 + ? iscsi_target_do_login+0x155/0x8d0 [iscsi_target_mod] + ? iscsi_target_do_login_rx+0x3bc/0x4c0 [iscsi_target_mod] + ? process_one_work+0x35c/0x640 + ? worker_thread+0x66/0x5d0 + ? kthread+0x1a0/0x1c0 + ? ret_from_fork+0x35/0x40 + ? iscsi_update_param_value+0x80/0x80 [iscsi_target_mod] + ? iscsit_release_cmd+0x170/0x170 [iscsi_target_mod] + chap_main_loop+0x172/0x570 [iscsi_target_mod] + ? chap_server_compute_md5.isra.2+0x860/0x860 [iscsi_target_mod] + ? rx_data+0xd6/0x120 [iscsi_target_mod] + ? iscsit_print_session_params+0xd0/0xd0 [iscsi_target_mod] + ? cyc2ns_read_begin.part.2+0x90/0x90 + ? _raw_spin_lock_irqsave+0x25/0x50 + ? memcmp+0x45/0x70 + iscsi_target_do_login+0x875/0x8d0 [iscsi_target_mod] + ? iscsi_target_check_first_request.isra.5+0x1a0/0x1a0 [iscsi_target_mod] + ? del_timer+0xe0/0xe0 + ? memset+0x1f/0x40 + ? flush_sigqueue+0x29/0xd0 + iscsi_target_do_login_rx+0x3bc/0x4c0 [iscsi_target_mod] + ? iscsi_target_nego_release+0x80/0x80 [iscsi_target_mod] + ? iscsi_target_restore_sock_callbacks+0x130/0x130 [iscsi_target_mod] + process_one_work+0x35c/0x640 + worker_thread+0x66/0x5d0 + ? flush_rcu_work+0x40/0x40 + kthread+0x1a0/0x1c0 + ? kthread_bind+0x30/0x30 + ret_from_fork+0x35/0x40 + +The buggy address belongs to the page: +page:ffffea0004243bc0 count:0 mapcount:0 mapping:0000000000000000 index:0x0 +flags: 0x17fffc000000000() +raw: 017fffc000000000 0000000000000000 0000000000000000 00000000ffffffff +raw: ffffea0004243c20 ffffea0004243ba0 0000000000000000 0000000000000000 +page dumped because: kasan: bad access detected + +Memory state around the buggy address: + ffff8801090ef680: f2 f2 f2 f2 f2 f2 f2 01 f2 f2 f2 f2 f2 f2 f2 00 + ffff8801090ef700: f2 f2 f2 f2 f2 f2 f2 00 02 f2 f2 f2 f2 f2 f2 00 +>ffff8801090ef780: 00 f2 f2 f2 f2 f2 f2 00 00 f2 f2 f2 f2 f2 f2 00 + ^ + ffff8801090ef800: 00 f2 f2 f2 f2 f2 f2 00 00 00 00 02 f2 f2 f2 f2 + ffff8801090ef880: f2 f2 f2 00 00 00 00 00 00 00 00 f2 f2 f2 f2 00 +================================================================== + +Signed-off-by: Vincent Pelletier +Reviewed-by: Mike Christie +Signed-off-by: Martin K. Petersen +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/target/iscsi/iscsi_target_auth.c | 30 ++++++++++++++---------------- + 1 file changed, 14 insertions(+), 16 deletions(-) + +--- a/drivers/target/iscsi/iscsi_target_auth.c ++++ b/drivers/target/iscsi/iscsi_target_auth.c +@@ -26,18 +26,6 @@ + #include "iscsi_target_nego.h" + #include "iscsi_target_auth.h" + +-static int chap_string_to_hex(unsigned char *dst, unsigned char *src, int len) +-{ +- int j = DIV_ROUND_UP(len, 2), rc; +- +- rc = hex2bin(dst, src, j); +- if (rc < 0) +- pr_debug("CHAP string contains non hex digit symbols\n"); +- +- dst[j] = '\0'; +- return j; +-} +- + static void chap_binaryhex_to_asciihex(char *dst, char *src, int src_len) + { + int i; +@@ -248,9 +236,16 @@ static int chap_server_compute_md5( + pr_err("Could not find CHAP_R.\n"); + goto out; + } ++ if (strlen(chap_r) != MD5_SIGNATURE_SIZE * 2) { ++ pr_err("Malformed CHAP_R\n"); ++ goto out; ++ } ++ if (hex2bin(client_digest, chap_r, MD5_SIGNATURE_SIZE) < 0) { ++ pr_err("Malformed CHAP_R\n"); ++ goto out; ++ } + + pr_debug("[server] Got CHAP_R=%s\n", chap_r); +- chap_string_to_hex(client_digest, chap_r, strlen(chap_r)); + + tfm = crypto_alloc_shash("md5", 0, 0); + if (IS_ERR(tfm)) { +@@ -349,9 +344,7 @@ static int chap_server_compute_md5( + pr_err("Could not find CHAP_C.\n"); + goto out; + } +- pr_debug("[server] Got CHAP_C=%s\n", challenge); +- challenge_len = chap_string_to_hex(challenge_binhex, challenge, +- strlen(challenge)); ++ challenge_len = DIV_ROUND_UP(strlen(challenge), 2); + if (!challenge_len) { + pr_err("Unable to convert incoming challenge\n"); + goto out; +@@ -360,6 +353,11 @@ static int chap_server_compute_md5( + pr_err("CHAP_C exceeds maximum binary size of 1024 bytes\n"); + goto out; + } ++ if (hex2bin(challenge_binhex, challenge, challenge_len) < 0) { ++ pr_err("Malformed CHAP_C\n"); ++ goto out; ++ } ++ pr_debug("[server] Got CHAP_C=%s\n", challenge); + /* + * During mutual authentication, the CHAP_C generated by the + * initiator must not match the original CHAP_C generated by diff --git a/queue-4.18/series b/queue-4.18/series index 0f568f81a63..182185629bb 100644 --- a/queue-4.18/series +++ b/queue-4.18/series @@ -50,3 +50,36 @@ crypto-x86-aegis-morus-do-not-require-osxsave-for-sse2.patch fork-report-pid-exhaustion-correctly.patch mm-disable-deferred-struct-page-for-32-bit-arches.patch mm-shmem.c-correctly-annotate-new-inodes-for-lockdep.patch +revert-rpmsg-core-add-support-to-power-domains-for.patch +bpf-verifier-disallow-pointer-subtraction.patch +revert-uapi-linux-keyctl.h-don-t-use-c-reserved-keyword-as-a-struct-member-name.patch +scsi-target-iscsi-use-hex2bin-instead-of-a-re-implementation.patch +scsi-target-iscsi-use-bin2hex-instead-of-a-re-implementation.patch +revert-ubifs-xattr-don-t-operate-on-deleted-inodes.patch +libata-mask-swap-internal-and-hardware-tag.patch +ocfs2-fix-ocfs2-read-block-panic.patch +drm-i915-bdw-increase-ips-disable-timeout-to-100ms.patch +drm-nouveau-reset-mst-branching-unit-before-enabling.patch +drm-nouveau-only-write-dp_mstm_ctrl-when-needed.patch +drm-nouveau-remove-duplicate-poll_enable-in-pmops_runtime_suspend.patch +drm-nouveau-fix-deadlocks-in-nouveau_connector_detect.patch +drm-nouveau-drm-nouveau-don-t-forget-to-cancel-hpd_work-on-suspend-unload.patch +drm-nouveau-drm-nouveau-fix-bogus-drm_kms_helper_poll_enable-placement.patch +drm-nouveau-drm-nouveau-fix-deadlock-with-fb_helper-with-async-rpm-requests.patch +drm-nouveau-drm-nouveau-use-pm_runtime_get_noresume-in-connector_detect.patch +drm-nouveau-drm-nouveau-prevent-handling-acpi-hpd-events-too-early.patch +drm-vc4-fix-the-no-scaling-case-on-multi-planar-yuv-formats.patch +drm-udl-destroy-framebuffer-only-if-it-was-initialized.patch +drm-amdgpu-add-new-polaris-pci-id.patch +drm-atomic-use-drm_drv_uses_atomic_modeset-for-debugfs-creation.patch +tty-vt_ioctl-fix-potential-spectre-v1.patch +ext4-check-to-make-sure-the-rename-2-s-destination-is-not-freed.patch +ext4-avoid-divide-by-zero-fault-when-deleting-corrupted-inline-directories.patch +ext4-avoid-arithemetic-overflow-that-can-trigger-a-bug.patch +ext4-recalucate-superblock-checksum-after-updating-free-blocks-inodes.patch +ext4-fix-online-resize-s-handling-of-a-too-small-final-block-group.patch +ext4-fix-online-resizing-for-bigalloc-file-systems-with-a-1k-block-size.patch +ext4-don-t-mark-mmp-buffer-head-dirty.patch +ext4-show-test_dummy_encryption-mount-option-in-proc-mounts.patch +ext4-dax-add-ext4_bmap-to-ext4_dax_aops.patch +ext4-dax-set-ext4_dax_aops-for-dax-files.patch diff --git a/queue-4.18/tty-vt_ioctl-fix-potential-spectre-v1.patch b/queue-4.18/tty-vt_ioctl-fix-potential-spectre-v1.patch new file mode 100644 index 00000000000..13e041a57d0 --- /dev/null +++ b/queue-4.18/tty-vt_ioctl-fix-potential-spectre-v1.patch @@ -0,0 +1,54 @@ +From e97267cb4d1ee01ca0929638ec0fcbb0904f903d Mon Sep 17 00:00:00 2001 +From: "Gustavo A. R. Silva" +Date: Thu, 16 Aug 2018 15:30:38 -0500 +Subject: tty: vt_ioctl: fix potential Spectre v1 + +From: Gustavo A. R. Silva + +commit e97267cb4d1ee01ca0929638ec0fcbb0904f903d upstream. + +vsa.console is indirectly controlled by user-space, hence leading to +a potential exploitation of the Spectre variant 1 vulnerability. + +This issue was detected with the help of Smatch: + +drivers/tty/vt/vt_ioctl.c:711 vt_ioctl() warn: potential spectre issue +'vc_cons' [r] + +Fix this by sanitizing vsa.console before using it to index vc_cons + +Notice that given that speculation windows are large, the policy is +to kill the speculation on the first load and not worry if it can be +completed with a dependent load/store [1]. + +[1] https://marc.info/?l=linux-kernel&m=152449131114778&w=2 + +Cc: stable@vger.kernel.org +Signed-off-by: Gustavo A. R. Silva +Reviewed-by: Alan Cox +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/tty/vt/vt_ioctl.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/drivers/tty/vt/vt_ioctl.c ++++ b/drivers/tty/vt/vt_ioctl.c +@@ -32,6 +32,8 @@ + #include + #include + ++#include ++ + #include + #include + #include +@@ -700,6 +702,8 @@ int vt_ioctl(struct tty_struct *tty, + if (vsa.console == 0 || vsa.console > MAX_NR_CONSOLES) + ret = -ENXIO; + else { ++ vsa.console = array_index_nospec(vsa.console, ++ MAX_NR_CONSOLES + 1); + vsa.console--; + console_lock(); + ret = vc_allocate(vsa.console);