]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
6.10-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 10 Sep 2024 07:57:09 +0000 (09:57 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 10 Sep 2024 07:57:09 +0000 (09:57 +0200)
added patches:
btrfs-fix-race-between-direct-io-write-and-fsync-when-using-same-fd.patch
drm-i915-display-add-mechanism-to-use-sink-model-when-applying-quirk.patch
drm-i915-display-increase-fast-wake-sync-length-as-a-quirk.patch

queue-6.10/btrfs-fix-race-between-direct-io-write-and-fsync-when-using-same-fd.patch [new file with mode: 0644]
queue-6.10/drm-i915-display-add-mechanism-to-use-sink-model-when-applying-quirk.patch [new file with mode: 0644]
queue-6.10/drm-i915-display-increase-fast-wake-sync-length-as-a-quirk.patch [new file with mode: 0644]
queue-6.10/series

diff --git a/queue-6.10/btrfs-fix-race-between-direct-io-write-and-fsync-when-using-same-fd.patch b/queue-6.10/btrfs-fix-race-between-direct-io-write-and-fsync-when-using-same-fd.patch
new file mode 100644 (file)
index 0000000..ceb9f2c
--- /dev/null
@@ -0,0 +1,313 @@
+From cd9253c23aedd61eb5ff11f37a36247cd46faf86 Mon Sep 17 00:00:00 2001
+From: Filipe Manana <fdmanana@suse.com>
+Date: Thu, 29 Aug 2024 18:25:49 +0100
+Subject: btrfs: fix race between direct IO write and fsync when using same fd
+
+From: Filipe Manana <fdmanana@suse.com>
+
+commit cd9253c23aedd61eb5ff11f37a36247cd46faf86 upstream.
+
+If we have 2 threads that are using the same file descriptor and one of
+them is doing direct IO writes while the other is doing fsync, we have a
+race where we can end up either:
+
+1) Attempt a fsync without holding the inode's lock, triggering an
+   assertion failures when assertions are enabled;
+
+2) Do an invalid memory access from the fsync task because the file private
+   points to memory allocated on stack by the direct IO task and it may be
+   used by the fsync task after the stack was destroyed.
+
+The race happens like this:
+
+1) A user space program opens a file descriptor with O_DIRECT;
+
+2) The program spawns 2 threads using libpthread for example;
+
+3) One of the threads uses the file descriptor to do direct IO writes,
+   while the other calls fsync using the same file descriptor.
+
+4) Call task A the thread doing direct IO writes and task B the thread
+   doing fsyncs;
+
+5) Task A does a direct IO write, and at btrfs_direct_write() sets the
+   file's private to an on stack allocated private with the member
+   'fsync_skip_inode_lock' set to true;
+
+6) Task B enters btrfs_sync_file() and sees that there's a private
+   structure associated to the file which has 'fsync_skip_inode_lock' set
+   to true, so it skips locking the inode's VFS lock;
+
+7) Task A completes the direct IO write, and resets the file's private to
+   NULL since it had no prior private and our private was stack allocated.
+   Then it unlocks the inode's VFS lock;
+
+8) Task B enters btrfs_get_ordered_extents_for_logging(), then the
+   assertion that checks the inode's VFS lock is held fails, since task B
+   never locked it and task A has already unlocked it.
+
+The stack trace produced is the following:
+
+   assertion failed: inode_is_locked(&inode->vfs_inode), in fs/btrfs/ordered-data.c:983
+   ------------[ cut here ]------------
+   kernel BUG at fs/btrfs/ordered-data.c:983!
+   Oops: invalid opcode: 0000 [#1] PREEMPT SMP PTI
+   CPU: 9 PID: 5072 Comm: worker Tainted: G     U     OE      6.10.5-1-default #1 openSUSE Tumbleweed 69f48d427608e1c09e60ea24c6c55e2ca1b049e8
+   Hardware name: Acer Predator PH315-52/Covini_CFS, BIOS V1.12 07/28/2020
+   RIP: 0010:btrfs_get_ordered_extents_for_logging.cold+0x1f/0x42 [btrfs]
+   Code: 50 d6 86 c0 e8 (...)
+   RSP: 0018:ffff9e4a03dcfc78 EFLAGS: 00010246
+   RAX: 0000000000000054 RBX: ffff9078a9868e98 RCX: 0000000000000000
+   RDX: 0000000000000000 RSI: ffff907dce4a7800 RDI: ffff907dce4a7800
+   RBP: ffff907805518800 R08: 0000000000000000 R09: ffff9e4a03dcfb38
+   R10: ffff9e4a03dcfb30 R11: 0000000000000003 R12: ffff907684ae7800
+   R13: 0000000000000001 R14: ffff90774646b600 R15: 0000000000000000
+   FS:  00007f04b96006c0(0000) GS:ffff907dce480000(0000) knlGS:0000000000000000
+   CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+   CR2: 00007f32acbfc000 CR3: 00000001fd4fa005 CR4: 00000000003726f0
+   Call Trace:
+    <TASK>
+    ? __die_body.cold+0x14/0x24
+    ? die+0x2e/0x50
+    ? do_trap+0xca/0x110
+    ? do_error_trap+0x6a/0x90
+    ? btrfs_get_ordered_extents_for_logging.cold+0x1f/0x42 [btrfs bb26272d49b4cdc847cf3f7faadd459b62caee9a]
+    ? exc_invalid_op+0x50/0x70
+    ? btrfs_get_ordered_extents_for_logging.cold+0x1f/0x42 [btrfs bb26272d49b4cdc847cf3f7faadd459b62caee9a]
+    ? asm_exc_invalid_op+0x1a/0x20
+    ? btrfs_get_ordered_extents_for_logging.cold+0x1f/0x42 [btrfs bb26272d49b4cdc847cf3f7faadd459b62caee9a]
+    ? btrfs_get_ordered_extents_for_logging.cold+0x1f/0x42 [btrfs bb26272d49b4cdc847cf3f7faadd459b62caee9a]
+    btrfs_sync_file+0x21a/0x4d0 [btrfs bb26272d49b4cdc847cf3f7faadd459b62caee9a]
+    ? __seccomp_filter+0x31d/0x4f0
+    __x64_sys_fdatasync+0x4f/0x90
+    do_syscall_64+0x82/0x160
+    ? do_futex+0xcb/0x190
+    ? __x64_sys_futex+0x10e/0x1d0
+    ? switch_fpu_return+0x4f/0xd0
+    ? syscall_exit_to_user_mode+0x72/0x220
+    ? do_syscall_64+0x8e/0x160
+    ? syscall_exit_to_user_mode+0x72/0x220
+    ? do_syscall_64+0x8e/0x160
+    ? syscall_exit_to_user_mode+0x72/0x220
+    ? do_syscall_64+0x8e/0x160
+    ? syscall_exit_to_user_mode+0x72/0x220
+    ? do_syscall_64+0x8e/0x160
+    entry_SYSCALL_64_after_hwframe+0x76/0x7e
+
+Another problem here is if task B grabs the private pointer and then uses
+it after task A has finished, since the private was allocated in the stack
+of task A, it results in some invalid memory access with a hard to predict
+result.
+
+This issue, triggering the assertion, was observed with QEMU workloads by
+two users in the Link tags below.
+
+Fix this by not relying on a file's private to pass information to fsync
+that it should skip locking the inode and instead pass this information
+through a special value stored in current->journal_info. This is safe
+because in the relevant section of the direct IO write path we are not
+holding a transaction handle, so current->journal_info is NULL.
+
+The following C program triggers the issue:
+
+   $ cat repro.c
+   /* Get the O_DIRECT definition. */
+   #ifndef _GNU_SOURCE
+   #define _GNU_SOURCE
+   #endif
+
+   #include <stdio.h>
+   #include <stdlib.h>
+   #include <unistd.h>
+   #include <stdint.h>
+   #include <fcntl.h>
+   #include <errno.h>
+   #include <string.h>
+   #include <pthread.h>
+
+   static int fd;
+
+   static ssize_t do_write(int fd, const void *buf, size_t count, off_t offset)
+   {
+       while (count > 0) {
+           ssize_t ret;
+
+           ret = pwrite(fd, buf, count, offset);
+           if (ret < 0) {
+               if (errno == EINTR)
+                   continue;
+               return ret;
+           }
+           count -= ret;
+           buf += ret;
+       }
+       return 0;
+   }
+
+   static void *fsync_loop(void *arg)
+   {
+       while (1) {
+           int ret;
+
+           ret = fsync(fd);
+           if (ret != 0) {
+               perror("Fsync failed");
+               exit(6);
+           }
+       }
+   }
+
+   int main(int argc, char *argv[])
+   {
+       long pagesize;
+       void *write_buf;
+       pthread_t fsyncer;
+       int ret;
+
+       if (argc != 2) {
+           fprintf(stderr, "Use: %s <file path>\n", argv[0]);
+           return 1;
+       }
+
+       fd = open(argv[1], O_WRONLY | O_CREAT | O_TRUNC | O_DIRECT, 0666);
+       if (fd == -1) {
+           perror("Failed to open/create file");
+           return 1;
+       }
+
+       pagesize = sysconf(_SC_PAGE_SIZE);
+       if (pagesize == -1) {
+           perror("Failed to get page size");
+           return 2;
+       }
+
+       ret = posix_memalign(&write_buf, pagesize, pagesize);
+       if (ret) {
+           perror("Failed to allocate buffer");
+           return 3;
+       }
+
+       ret = pthread_create(&fsyncer, NULL, fsync_loop, NULL);
+       if (ret != 0) {
+           fprintf(stderr, "Failed to create writer thread: %d\n", ret);
+           return 4;
+       }
+
+       while (1) {
+           ret = do_write(fd, write_buf, pagesize, 0);
+           if (ret != 0) {
+               perror("Write failed");
+               exit(5);
+           }
+       }
+
+       return 0;
+   }
+
+   $ mkfs.btrfs -f /dev/sdi
+   $ mount /dev/sdi /mnt/sdi
+   $ timeout 10 ./repro /mnt/sdi/foo
+
+Usually the race is triggered within less than 1 second. A test case for
+fstests will follow soon.
+
+Reported-by: Paulo Dias <paulo.miguel.dias@gmail.com>
+Link: https://bugzilla.kernel.org/show_bug.cgi?id=219187
+Reported-by: Andreas Jahn <jahn-andi@web.de>
+Link: https://bugzilla.kernel.org/show_bug.cgi?id=219199
+Reported-by: syzbot+4704b3cc972bd76024f1@syzkaller.appspotmail.com
+Link: https://lore.kernel.org/linux-btrfs/00000000000044ff540620d7dee2@google.com/
+Fixes: 939b656bc8ab ("btrfs: fix corruption after buffer fault in during direct IO append write")
+CC: stable@vger.kernel.org # 5.15+
+Reviewed-by: Josef Bacik <josef@toxicpanda.com>
+Signed-off-by: Filipe Manana <fdmanana@suse.com>
+Reviewed-by: David Sterba <dsterba@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/btrfs/ctree.h       |    1 -
+ fs/btrfs/file.c        |   25 ++++++++++---------------
+ fs/btrfs/transaction.h |    6 ++++++
+ 3 files changed, 16 insertions(+), 16 deletions(-)
+
+--- a/fs/btrfs/ctree.h
++++ b/fs/btrfs/ctree.h
+@@ -457,7 +457,6 @@ struct btrfs_file_private {
+       void *filldir_buf;
+       u64 last_index;
+       struct extent_state *llseek_cached_state;
+-      bool fsync_skip_inode_lock;
+ };
+ static inline u32 BTRFS_LEAF_DATA_SIZE(const struct btrfs_fs_info *info)
+--- a/fs/btrfs/file.c
++++ b/fs/btrfs/file.c
+@@ -1558,13 +1558,6 @@ again:
+       if (IS_ERR_OR_NULL(dio)) {
+               ret = PTR_ERR_OR_ZERO(dio);
+       } else {
+-              struct btrfs_file_private stack_private = { 0 };
+-              struct btrfs_file_private *private;
+-              const bool have_private = (file->private_data != NULL);
+-
+-              if (!have_private)
+-                      file->private_data = &stack_private;
+-
+               /*
+                * If we have a synchoronous write, we must make sure the fsync
+                * triggered by the iomap_dio_complete() call below doesn't
+@@ -1573,13 +1566,10 @@ again:
+                * partial writes due to the input buffer (or parts of it) not
+                * being already faulted in.
+                */
+-              private = file->private_data;
+-              private->fsync_skip_inode_lock = true;
++              ASSERT(current->journal_info == NULL);
++              current->journal_info = BTRFS_TRANS_DIO_WRITE_STUB;
+               ret = iomap_dio_complete(dio);
+-              private->fsync_skip_inode_lock = false;
+-
+-              if (!have_private)
+-                      file->private_data = NULL;
++              current->journal_info = NULL;
+       }
+       /* No increment (+=) because iomap returns a cumulative value. */
+@@ -1811,7 +1801,6 @@ static inline bool skip_inode_logging(co
+  */
+ int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
+ {
+-      struct btrfs_file_private *private = file->private_data;
+       struct dentry *dentry = file_dentry(file);
+       struct inode *inode = d_inode(dentry);
+       struct btrfs_fs_info *fs_info = inode_to_fs_info(inode);
+@@ -1821,7 +1810,13 @@ int btrfs_sync_file(struct file *file, l
+       int ret = 0, err;
+       u64 len;
+       bool full_sync;
+-      const bool skip_ilock = (private ? private->fsync_skip_inode_lock : false);
++      bool skip_ilock = false;
++
++      if (current->journal_info == BTRFS_TRANS_DIO_WRITE_STUB) {
++              skip_ilock = true;
++              current->journal_info = NULL;
++              lockdep_assert_held(&inode->i_rwsem);
++      }
+       trace_btrfs_sync_file(file, datasync);
+--- a/fs/btrfs/transaction.h
++++ b/fs/btrfs/transaction.h
+@@ -27,6 +27,12 @@ struct btrfs_root_item;
+ struct btrfs_root;
+ struct btrfs_path;
++/*
++ * Signal that a direct IO write is in progress, to avoid deadlock for sync
++ * direct IO writes when fsync is called during the direct IO write path.
++ */
++#define BTRFS_TRANS_DIO_WRITE_STUB    ((void *) 1)
++
+ /* Radix-tree tag for roots that are part of the trasaction. */
+ #define BTRFS_ROOT_TRANS_TAG                  0
diff --git a/queue-6.10/drm-i915-display-add-mechanism-to-use-sink-model-when-applying-quirk.patch b/queue-6.10/drm-i915-display-add-mechanism-to-use-sink-model-when-applying-quirk.patch
new file mode 100644 (file)
index 0000000..c6aaa29
--- /dev/null
@@ -0,0 +1,181 @@
+From 43cf50eb1408ccb99cab01521263e8cb4cfdc023 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Jouni=20H=C3=B6gander?= <jouni.hogander@intel.com>
+Date: Mon, 2 Sep 2024 09:42:40 +0300
+Subject: drm/i915/display: Add mechanism to use sink model when applying quirk
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Jouni Högander <jouni.hogander@intel.com>
+
+commit 43cf50eb1408ccb99cab01521263e8cb4cfdc023 upstream.
+
+Currently there is no way to apply quirk on device only if certain panel
+model is installed. This patch implements such mechanism by adding new
+quirk type intel_dpcd_quirk which contains also sink_oui and sink_device_id
+fields and using also them to figure out if applying quirk is needed.
+
+New intel_init_dpcd_quirks is added and called after drm_dp_read_desc with
+proper sink device identity read from dpcdc.
+
+v3:
+  - !mem_is_zero fixed to mem_is_zero
+v2:
+  - instead of using struct intel_quirk add new struct intel_dpcd_quirk
+
+Signed-off-by: Jouni Högander <jouni.hogander@intel.com>
+Reviewed-by: Jani Nikula <jani.nikula@intel.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20240902064241.1020965-2-jouni.hogander@intel.com
+(cherry picked from commit b3b91369908ac63be6f64905448b8ba5cd151875)
+Signed-off-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/i915/display/intel_display_types.h |    4 +
+ drivers/gpu/drm/i915/display/intel_dp.c            |    4 +
+ drivers/gpu/drm/i915/display/intel_quirks.c        |   51 +++++++++++++++++++++
+ drivers/gpu/drm/i915/display/intel_quirks.h        |    5 ++
+ 4 files changed, 64 insertions(+)
+
+--- a/drivers/gpu/drm/i915/display/intel_display_types.h
++++ b/drivers/gpu/drm/i915/display/intel_display_types.h
+@@ -1840,6 +1840,10 @@ struct intel_dp {
+       unsigned long last_oui_write;
+       bool colorimetry_support;
++
++      struct {
++              unsigned long mask;
++      } quirks;
+ };
+ enum lspcon_vendor {
+--- a/drivers/gpu/drm/i915/display/intel_dp.c
++++ b/drivers/gpu/drm/i915/display/intel_dp.c
+@@ -79,6 +79,7 @@
+ #include "intel_pch_display.h"
+ #include "intel_pps.h"
+ #include "intel_psr.h"
++#include "intel_quirks.h"
+ #include "intel_tc.h"
+ #include "intel_vdsc.h"
+ #include "intel_vrr.h"
+@@ -3941,6 +3942,7 @@ intel_edp_init_dpcd(struct intel_dp *int
+       drm_dp_read_desc(&intel_dp->aux, &intel_dp->desc,
+                        drm_dp_is_branch(intel_dp->dpcd));
++      intel_init_dpcd_quirks(intel_dp, &intel_dp->desc.ident);
+       /*
+        * Read the eDP display control registers.
+@@ -4053,6 +4055,8 @@ intel_dp_get_dpcd(struct intel_dp *intel
+               drm_dp_read_desc(&intel_dp->aux, &intel_dp->desc,
+                                drm_dp_is_branch(intel_dp->dpcd));
++              intel_init_dpcd_quirks(intel_dp, &intel_dp->desc.ident);
++
+               intel_dp_update_sink_caps(intel_dp);
+       }
+--- a/drivers/gpu/drm/i915/display/intel_quirks.c
++++ b/drivers/gpu/drm/i915/display/intel_quirks.c
+@@ -14,6 +14,11 @@ static void intel_set_quirk(struct intel
+       display->quirks.mask |= BIT(quirk);
+ }
++static void intel_set_dpcd_quirk(struct intel_dp *intel_dp, enum intel_quirk_id quirk)
++{
++      intel_dp->quirks.mask |= BIT(quirk);
++}
++
+ /*
+  * Some machines (Lenovo U160) do not work with SSC on LVDS for some reason
+  */
+@@ -72,6 +77,21 @@ struct intel_quirk {
+       void (*hook)(struct intel_display *display);
+ };
++struct intel_dpcd_quirk {
++      int device;
++      int subsystem_vendor;
++      int subsystem_device;
++      u8 sink_oui[3];
++      u8 sink_device_id[6];
++      void (*hook)(struct intel_dp *intel_dp);
++};
++
++#define SINK_OUI(first, second, third) { (first), (second), (third) }
++#define SINK_DEVICE_ID(first, second, third, fourth, fifth, sixth) \
++      { (first), (second), (third), (fourth), (fifth), (sixth) }
++
++#define SINK_DEVICE_ID_ANY    SINK_DEVICE_ID(0, 0, 0, 0, 0, 0)
++
+ /* For systems that don't have a meaningful PCI subdevice/subvendor ID */
+ struct intel_dmi_quirk {
+       void (*hook)(struct intel_display *display);
+@@ -203,6 +223,9 @@ static struct intel_quirk intel_quirks[]
+       { 0x0f31, 0x103c, 0x220f, quirk_invert_brightness },
+ };
++static struct intel_dpcd_quirk intel_dpcd_quirks[] = {
++};
++
+ void intel_init_quirks(struct intel_display *display)
+ {
+       struct pci_dev *d = to_pci_dev(display->drm->dev);
+@@ -224,7 +247,35 @@ void intel_init_quirks(struct intel_disp
+       }
+ }
++void intel_init_dpcd_quirks(struct intel_dp *intel_dp,
++                          const struct drm_dp_dpcd_ident *ident)
++{
++      struct intel_display *display = to_intel_display(intel_dp);
++      struct pci_dev *d = to_pci_dev(display->drm->dev);
++      int i;
++
++      for (i = 0; i < ARRAY_SIZE(intel_dpcd_quirks); i++) {
++              struct intel_dpcd_quirk *q = &intel_dpcd_quirks[i];
++
++              if (d->device == q->device &&
++                  (d->subsystem_vendor == q->subsystem_vendor ||
++                   q->subsystem_vendor == PCI_ANY_ID) &&
++                  (d->subsystem_device == q->subsystem_device ||
++                   q->subsystem_device == PCI_ANY_ID) &&
++                  !memcmp(q->sink_oui, ident->oui, sizeof(ident->oui)) &&
++                  (!memcmp(q->sink_device_id, ident->device_id,
++                          sizeof(ident->device_id)) ||
++                   mem_is_zero(q->sink_device_id, sizeof(q->sink_device_id))))
++                      q->hook(intel_dp);
++      }
++}
++
+ bool intel_has_quirk(struct intel_display *display, enum intel_quirk_id quirk)
+ {
+       return display->quirks.mask & BIT(quirk);
+ }
++
++bool intel_has_dpcd_quirk(struct intel_dp *intel_dp, enum intel_quirk_id quirk)
++{
++      return intel_dp->quirks.mask & BIT(quirk);
++}
+--- a/drivers/gpu/drm/i915/display/intel_quirks.h
++++ b/drivers/gpu/drm/i915/display/intel_quirks.h
+@@ -9,6 +9,8 @@
+ #include <linux/types.h>
+ struct intel_display;
++struct intel_dp;
++struct drm_dp_dpcd_ident;
+ enum intel_quirk_id {
+       QUIRK_BACKLIGHT_PRESENT,
+@@ -20,6 +22,9 @@ enum intel_quirk_id {
+ };
+ void intel_init_quirks(struct intel_display *display);
++void intel_init_dpcd_quirks(struct intel_dp *intel_dp,
++                          const struct drm_dp_dpcd_ident *ident);
+ bool intel_has_quirk(struct intel_display *display, enum intel_quirk_id quirk);
++bool intel_has_dpcd_quirk(struct intel_dp *intel_dp, enum intel_quirk_id quirk);
+ #endif /* __INTEL_QUIRKS_H__ */
diff --git a/queue-6.10/drm-i915-display-increase-fast-wake-sync-length-as-a-quirk.patch b/queue-6.10/drm-i915-display-increase-fast-wake-sync-length-as-a-quirk.patch
new file mode 100644 (file)
index 0000000..5ac9483
--- /dev/null
@@ -0,0 +1,159 @@
+From a13494de53258d8cf82ed3bcd69176bbf7f2640e Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Jouni=20H=C3=B6gander?= <jouni.hogander@intel.com>
+Date: Mon, 2 Sep 2024 09:42:41 +0300
+Subject: drm/i915/display: Increase Fast Wake Sync length as a quirk
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Jouni Högander <jouni.hogander@intel.com>
+
+commit a13494de53258d8cf82ed3bcd69176bbf7f2640e upstream.
+
+In commit "drm/i915/display: Increase number of fast wake precharge pulses"
+we were increasing Fast Wake sync pulse length to fix problems observed on
+Dell Precision 5490 laptop with AUO panel. Later we have observed this is
+causing problems on other panels.
+
+Fix these problems by increasing Fast Wake sync pulse length as a quirk
+applied for Dell Precision 5490 with problematic panel.
+
+Fixes: f77772866385 ("drm/i915/display: Increase number of fast wake precharge pulses")
+Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
+Closes: http://gitlab.freedesktop.org/drm/i915/kernel/-/issues/9739
+Closes: https://gitlab.freedesktop.org/drm/xe/kernel/-/issues/2246
+Closes: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/11762
+Signed-off-by: Jouni Högander <jouni.hogander@intel.com>
+Reviewed-by: Jani Nikula <jani.nikula@intel.com>
+Cc: <stable@vger.kernel.org> # v6.10+
+Link: https://patchwork.freedesktop.org/patch/msgid/20240902064241.1020965-3-jouni.hogander@intel.com
+(cherry picked from commit fcba2ed66b39252210f4e739722ebcc5398c2197)
+Requires: 43cf50eb1408 ("drm/i915/display: Add mechanism to use sink model when applying quirk")
+Signed-off-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/i915/display/intel_dp_aux.c |   16 +++++++++++-----
+ drivers/gpu/drm/i915/display/intel_dp_aux.h |    2 +-
+ drivers/gpu/drm/i915/display/intel_psr.c    |    2 +-
+ drivers/gpu/drm/i915/display/intel_quirks.c |   19 ++++++++++++++++++-
+ drivers/gpu/drm/i915/display/intel_quirks.h |    1 +
+ 5 files changed, 32 insertions(+), 8 deletions(-)
+
+--- a/drivers/gpu/drm/i915/display/intel_dp_aux.c
++++ b/drivers/gpu/drm/i915/display/intel_dp_aux.c
+@@ -13,6 +13,7 @@
+ #include "intel_dp_aux.h"
+ #include "intel_dp_aux_regs.h"
+ #include "intel_pps.h"
++#include "intel_quirks.h"
+ #include "intel_tc.h"
+ #define AUX_CH_NAME_BUFSIZE   6
+@@ -142,16 +143,21 @@ static int intel_dp_aux_sync_len(void)
+       return precharge + preamble;
+ }
+-int intel_dp_aux_fw_sync_len(void)
++int intel_dp_aux_fw_sync_len(struct intel_dp *intel_dp)
+ {
++      int precharge = 10; /* 10-16 */
++      int preamble = 8;
++
+       /*
+        * We faced some glitches on Dell Precision 5490 MTL laptop with panel:
+        * "Manufacturer: AUO, Model: 63898" when using HW default 18. Using 20
+        * is fixing these problems with the panel. It is still within range
+-       * mentioned in eDP specification.
++       * mentioned in eDP specification. Increasing Fast Wake sync length is
++       * causing problems with other panels: increase length as a quirk for
++       * this specific laptop.
+        */
+-      int precharge = 12; /* 10-16 */
+-      int preamble = 8;
++      if (intel_has_dpcd_quirk(intel_dp, QUIRK_FW_SYNC_LEN))
++              precharge += 2;
+       return precharge + preamble;
+ }
+@@ -211,7 +217,7 @@ static u32 skl_get_aux_send_ctl(struct i
+               DP_AUX_CH_CTL_TIME_OUT_MAX |
+               DP_AUX_CH_CTL_RECEIVE_ERROR |
+               DP_AUX_CH_CTL_MESSAGE_SIZE(send_bytes) |
+-              DP_AUX_CH_CTL_FW_SYNC_PULSE_SKL(intel_dp_aux_fw_sync_len()) |
++              DP_AUX_CH_CTL_FW_SYNC_PULSE_SKL(intel_dp_aux_fw_sync_len(intel_dp)) |
+               DP_AUX_CH_CTL_SYNC_PULSE_SKL(intel_dp_aux_sync_len());
+       if (intel_tc_port_in_tbt_alt_mode(dig_port))
+--- a/drivers/gpu/drm/i915/display/intel_dp_aux.h
++++ b/drivers/gpu/drm/i915/display/intel_dp_aux.h
+@@ -20,6 +20,6 @@ enum aux_ch intel_dp_aux_ch(struct intel
+ void intel_dp_aux_irq_handler(struct drm_i915_private *i915);
+ u32 intel_dp_aux_pack(const u8 *src, int src_bytes);
+-int intel_dp_aux_fw_sync_len(void);
++int intel_dp_aux_fw_sync_len(struct intel_dp *intel_dp);
+ #endif /* __INTEL_DP_AUX_H__ */
+--- a/drivers/gpu/drm/i915/display/intel_psr.c
++++ b/drivers/gpu/drm/i915/display/intel_psr.c
+@@ -1356,7 +1356,7 @@ static bool _compute_alpm_params(struct
+       int tfw_exit_latency = 20; /* eDP spec */
+       int phy_wake = 4;          /* eDP spec */
+       int preamble = 8;          /* eDP spec */
+-      int precharge = intel_dp_aux_fw_sync_len() - preamble;
++      int precharge = intel_dp_aux_fw_sync_len(intel_dp) - preamble;
+       u8 max_wake_lines;
+       io_wake_time = max(precharge, io_buffer_wake_time(crtc_state)) +
+--- a/drivers/gpu/drm/i915/display/intel_quirks.c
++++ b/drivers/gpu/drm/i915/display/intel_quirks.c
+@@ -70,6 +70,14 @@ static void quirk_no_pps_backlight_power
+       drm_info(display->drm, "Applying no pps backlight power quirk\n");
+ }
++static void quirk_fw_sync_len(struct intel_dp *intel_dp)
++{
++      struct intel_display *display = to_intel_display(intel_dp);
++
++      intel_set_dpcd_quirk(intel_dp, QUIRK_FW_SYNC_LEN);
++      drm_info(display->drm, "Applying Fast Wake sync pulse count quirk\n");
++}
++
+ struct intel_quirk {
+       int device;
+       int subsystem_vendor;
+@@ -224,6 +232,15 @@ static struct intel_quirk intel_quirks[]
+ };
+ static struct intel_dpcd_quirk intel_dpcd_quirks[] = {
++      /* Dell Precision 5490 */
++      {
++              .device = 0x7d55,
++              .subsystem_vendor = 0x1028,
++              .subsystem_device = 0x0cc7,
++              .sink_oui = SINK_OUI(0x38, 0xec, 0x11),
++              .hook = quirk_fw_sync_len,
++      },
++
+ };
+ void intel_init_quirks(struct intel_display *display)
+@@ -265,7 +282,7 @@ void intel_init_dpcd_quirks(struct intel
+                   !memcmp(q->sink_oui, ident->oui, sizeof(ident->oui)) &&
+                   (!memcmp(q->sink_device_id, ident->device_id,
+                           sizeof(ident->device_id)) ||
+-                   mem_is_zero(q->sink_device_id, sizeof(q->sink_device_id))))
++                   !memchr_inv(q->sink_device_id, 0, sizeof(q->sink_device_id))))
+                       q->hook(intel_dp);
+       }
+ }
+--- a/drivers/gpu/drm/i915/display/intel_quirks.h
++++ b/drivers/gpu/drm/i915/display/intel_quirks.h
+@@ -19,6 +19,7 @@ enum intel_quirk_id {
+       QUIRK_INVERT_BRIGHTNESS,
+       QUIRK_LVDS_SSC_DISABLE,
+       QUIRK_NO_PPS_BACKLIGHT_POWER_HOOK,
++      QUIRK_FW_SYNC_LEN,
+ };
+ void intel_init_quirks(struct intel_display *display);
index 362c594721e18a5bc86771533f45c224317882d1..c6fa521fbffe7ca98e961329ec3dca227ca77ad1 100644 (file)
@@ -368,3 +368,6 @@ nvme-rename-cdr-more-dnr-to-nvme_status_.patch
 nvmet-identify-active-namespace-id-list-command-shou.patch
 ublk_drv-fix-null-pointer-dereference-in-ublk_ctrl_s.patch
 x86-mm-fix-pti-for-i386-some-more.patch
+drm-i915-display-add-mechanism-to-use-sink-model-when-applying-quirk.patch
+drm-i915-display-increase-fast-wake-sync-length-as-a-quirk.patch
+btrfs-fix-race-between-direct-io-write-and-fsync-when-using-same-fd.patch