]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
Fixes for 4.19
authorSasha Levin <sashal@kernel.org>
Thu, 28 Sep 2023 20:55:27 +0000 (16:55 -0400)
committerSasha Levin <sashal@kernel.org>
Thu, 28 Sep 2023 20:55:27 +0000 (16:55 -0400)
Signed-off-by: Sasha Levin <sashal@kernel.org>
18 files changed:
queue-4.19/ext4-add-new-helper-interface-ext4_try_to_trim_range.patch [new file with mode: 0644]
queue-4.19/ext4-change-s_last_trim_minblks-type-to-unsigned-lon.patch [new file with mode: 0644]
queue-4.19/ext4-do-not-let-fstrim-block-system-suspend.patch [new file with mode: 0644]
queue-4.19/ext4-mark-group-as-trimmed-only-if-it-was-fully-scan.patch [new file with mode: 0644]
queue-4.19/ext4-move-setting-of-trimmed-bit-into-ext4_try_to_tr.patch [new file with mode: 0644]
queue-4.19/ext4-remove-the-group-parameter-of-ext4_trim_extent.patch [new file with mode: 0644]
queue-4.19/ext4-replace-the-traditional-ternary-conditional-ope.patch [new file with mode: 0644]
queue-4.19/ext4-scope-ret-locally-in-ext4_try_to_trim_range.patch [new file with mode: 0644]
queue-4.19/input-i8042-add-quirk-for-tuxedo-gemini-17-gen1-clev.patch [new file with mode: 0644]
queue-4.19/scsi-megaraid_sas-fix-deadlock-on-firmware-crashdump.patch [new file with mode: 0644]
queue-4.19/scsi-megaraid_sas-load-balance-completions-across-al.patch [new file with mode: 0644]
queue-4.19/scsi-qla2xxx-add-protection-mask-module-parameters.patch [new file with mode: 0644]
queue-4.19/scsi-qla2xxx-remove-unsupported-ql2xenabledif-option.patch [new file with mode: 0644]
queue-4.19/series
queue-4.19/usb-typec-bus-verify-partner-exists-in-typec_altmode.patch [new file with mode: 0644]
queue-4.19/usb-typec-group-all-tcpci-tcpm-code-together.patch [new file with mode: 0644]
queue-4.19/usb-typec-tcpm-refactor-tcpm_handle_vdm_request-payl.patch [new file with mode: 0644]
queue-4.19/usb-typec-tcpm-refactor-tcpm_handle_vdm_request.patch [new file with mode: 0644]

diff --git a/queue-4.19/ext4-add-new-helper-interface-ext4_try_to_trim_range.patch b/queue-4.19/ext4-add-new-helper-interface-ext4_try_to_trim_range.patch
new file mode 100644 (file)
index 0000000..1facde4
--- /dev/null
@@ -0,0 +1,165 @@
+From d52bf582fb8877d648d6ba5f6f11aac09eea4639 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 24 Jul 2021 15:41:21 +0800
+Subject: ext4: add new helper interface ext4_try_to_trim_range()
+
+From: Wang Jianchao <wangjianchao@kuaishou.com>
+
+[ Upstream commit 6920b3913235f517728bb69abe9b39047a987113 ]
+
+There is no functional change in this patch but just split the
+codes, which serachs free block and does trim, into a new function
+ext4_try_to_trim_range. This is preparing for the following async
+backgroup discard.
+
+Reviewed-by: Andreas Dilger <adilger@dilger.ca>
+Signed-off-by: Wang Jianchao <wangjianchao@kuaishou.com>
+Reviewed-by: Jan Kara <jack@suse.cz>
+Link: https://lore.kernel.org/r/20210724074124.25731-3-jianchao.wan9@gmail.com
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Stable-dep-of: 45e4ab320c9b ("ext4: move setting of trimmed bit into ext4_try_to_trim_range()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/ext4/mballoc.c | 102 ++++++++++++++++++++++++++--------------------
+ 1 file changed, 57 insertions(+), 45 deletions(-)
+
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index 7b81094831754..51def652098b3 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -5184,6 +5184,54 @@ __acquires(bitlock)
+       return ret;
+ }
++static int ext4_try_to_trim_range(struct super_block *sb,
++              struct ext4_buddy *e4b, ext4_grpblk_t start,
++              ext4_grpblk_t max, ext4_grpblk_t minblocks)
++{
++      ext4_grpblk_t next, count, free_count;
++      void *bitmap;
++      int ret = 0;
++
++      bitmap = e4b->bd_bitmap;
++      start = (e4b->bd_info->bb_first_free > start) ?
++              e4b->bd_info->bb_first_free : start;
++      count = 0;
++      free_count = 0;
++
++      while (start <= max) {
++              start = mb_find_next_zero_bit(bitmap, max + 1, start);
++              if (start > max)
++                      break;
++              next = mb_find_next_bit(bitmap, max + 1, start);
++
++              if ((next - start) >= minblocks) {
++                      ret = ext4_trim_extent(sb, start, next - start, e4b);
++                      if (ret && ret != -EOPNOTSUPP)
++                              break;
++                      ret = 0;
++                      count += next - start;
++              }
++              free_count += next - start;
++              start = next + 1;
++
++              if (fatal_signal_pending(current)) {
++                      count = -ERESTARTSYS;
++                      break;
++              }
++
++              if (need_resched()) {
++                      ext4_unlock_group(sb, e4b->bd_group);
++                      cond_resched();
++                      ext4_lock_group(sb, e4b->bd_group);
++              }
++
++              if ((e4b->bd_info->bb_free - free_count) < minblocks)
++                      break;
++      }
++
++      return count;
++}
++
+ /**
+  * ext4_trim_all_free -- function to trim all free space in alloc. group
+  * @sb:                       super block for file system
+@@ -5207,10 +5255,8 @@ ext4_trim_all_free(struct super_block *sb, ext4_group_t group,
+                  ext4_grpblk_t start, ext4_grpblk_t max,
+                  ext4_grpblk_t minblocks)
+ {
+-      void *bitmap;
+-      ext4_grpblk_t next, count = 0, free_count = 0;
+       struct ext4_buddy e4b;
+-      int ret = 0;
++      int ret;
+       trace_ext4_trim_all_free(sb, group, start, max);
+@@ -5220,57 +5266,23 @@ ext4_trim_all_free(struct super_block *sb, ext4_group_t group,
+                            ret, group);
+               return ret;
+       }
+-      bitmap = e4b.bd_bitmap;
+       ext4_lock_group(sb, group);
+-      if (EXT4_MB_GRP_WAS_TRIMMED(e4b.bd_info) &&
+-          minblocks >= atomic_read(&EXT4_SB(sb)->s_last_trim_minblks))
+-              goto out;
+-
+-      start = (e4b.bd_info->bb_first_free > start) ?
+-              e4b.bd_info->bb_first_free : start;
+-
+-      while (start <= max) {
+-              start = mb_find_next_zero_bit(bitmap, max + 1, start);
+-              if (start > max)
+-                      break;
+-              next = mb_find_next_bit(bitmap, max + 1, start);
+-
+-              if ((next - start) >= minblocks) {
+-                      ret = ext4_trim_extent(sb, start, next - start, &e4b);
+-                      if (ret && ret != -EOPNOTSUPP)
+-                              break;
+-                      ret = 0;
+-                      count += next - start;
+-              }
+-              free_count += next - start;
+-              start = next + 1;
+-
+-              if (fatal_signal_pending(current)) {
+-                      count = -ERESTARTSYS;
+-                      break;
+-              }
+-
+-              if (need_resched()) {
+-                      ext4_unlock_group(sb, group);
+-                      cond_resched();
+-                      ext4_lock_group(sb, group);
+-              }
+-              if ((e4b.bd_info->bb_free - free_count) < minblocks)
+-                      break;
++      if (!EXT4_MB_GRP_WAS_TRIMMED(e4b.bd_info) ||
++          minblocks < atomic_read(&EXT4_SB(sb)->s_last_trim_minblks)) {
++              ret = ext4_try_to_trim_range(sb, &e4b, start, max, minblocks);
++              if (ret >= 0)
++                      EXT4_MB_GRP_SET_TRIMMED(e4b.bd_info);
++      } else {
++              ret = 0;
+       }
+-      if (!ret) {
+-              ret = count;
+-              EXT4_MB_GRP_SET_TRIMMED(e4b.bd_info);
+-      }
+-out:
+       ext4_unlock_group(sb, group);
+       ext4_mb_unload_buddy(&e4b);
+       ext4_debug("trimmed %d blocks in the group %d\n",
+-              count, group);
++              ret, group);
+       return ret;
+ }
+-- 
+2.40.1
+
diff --git a/queue-4.19/ext4-change-s_last_trim_minblks-type-to-unsigned-lon.patch b/queue-4.19/ext4-change-s_last_trim_minblks-type-to-unsigned-lon.patch
new file mode 100644 (file)
index 0000000..7d86a5d
--- /dev/null
@@ -0,0 +1,64 @@
+From 2d6c87ae043945d0e573fec55db8b466e4c79251 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 3 Nov 2021 15:51:21 +0100
+Subject: ext4: change s_last_trim_minblks type to unsigned long
+
+From: Lukas Czerner <lczerner@redhat.com>
+
+[ Upstream commit 2327fb2e23416cfb2795ccca2f77d4d65925be99 ]
+
+There is no good reason for the s_last_trim_minblks to be atomic. There is
+no data integrity needed and there is no real danger in setting and
+reading it in a racy manner. Change it to be unsigned long, the same type
+as s_clusters_per_group which is the maximum that's allowed.
+
+Signed-off-by: Lukas Czerner <lczerner@redhat.com>
+Suggested-by: Andreas Dilger <adilger@dilger.ca>
+Reviewed-by: Andreas Dilger <adilger@dilger.ca>
+Link: https://lore.kernel.org/r/20211103145122.17338-1-lczerner@redhat.com
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Stable-dep-of: 45e4ab320c9b ("ext4: move setting of trimmed bit into ext4_try_to_trim_range()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/ext4/ext4.h    | 2 +-
+ fs/ext4/mballoc.c | 4 ++--
+ 2 files changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 909f231a387d7..fa2579abea7df 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -1500,7 +1500,7 @@ struct ext4_sb_info {
+       struct task_struct *s_mmp_tsk;
+       /* record the last minlen when FITRIM is called. */
+-      atomic_t s_last_trim_minblks;
++      unsigned long s_last_trim_minblks;
+       /* Reference to checksum algorithm driver via cryptoapi */
+       struct crypto_shash *s_chksum_driver;
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index 58a0d2ea314b7..b76e8b8f01a10 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -5269,7 +5269,7 @@ ext4_trim_all_free(struct super_block *sb, ext4_group_t group,
+       ext4_lock_group(sb, group);
+       if (!EXT4_MB_GRP_WAS_TRIMMED(e4b.bd_info) ||
+-          minblocks < atomic_read(&EXT4_SB(sb)->s_last_trim_minblks)) {
++          minblocks < EXT4_SB(sb)->s_last_trim_minblks) {
+               ret = ext4_try_to_trim_range(sb, &e4b, start, max, minblocks);
+               if (ret >= 0)
+                       EXT4_MB_GRP_SET_TRIMMED(e4b.bd_info);
+@@ -5378,7 +5378,7 @@ int ext4_trim_fs(struct super_block *sb, struct fstrim_range *range)
+       }
+       if (!ret)
+-              atomic_set(&EXT4_SB(sb)->s_last_trim_minblks, minlen);
++              EXT4_SB(sb)->s_last_trim_minblks = minlen;
+ out:
+       range->len = EXT4_C2B(EXT4_SB(sb), trimmed) << sb->s_blocksize_bits;
+-- 
+2.40.1
+
diff --git a/queue-4.19/ext4-do-not-let-fstrim-block-system-suspend.patch b/queue-4.19/ext4-do-not-let-fstrim-block-system-suspend.patch
new file mode 100644 (file)
index 0000000..06509a7
--- /dev/null
@@ -0,0 +1,76 @@
+From 63fc38e35ab0e5b042f060431aae33af99041217 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 13 Sep 2023 17:04:55 +0200
+Subject: ext4: do not let fstrim block system suspend
+
+From: Jan Kara <jack@suse.cz>
+
+[ Upstream commit 5229a658f6453362fbb9da6bf96872ef25a7097e ]
+
+Len Brown has reported that system suspend sometimes fail due to
+inability to freeze a task working in ext4_trim_fs() for one minute.
+Trimming a large filesystem on a disk that slowly processes discard
+requests can indeed take a long time. Since discard is just an advisory
+call, it is perfectly fine to interrupt it at any time and the return
+number of discarded blocks until that moment. Do that when we detect the
+task is being frozen.
+
+Cc: stable@kernel.org
+Reported-by: Len Brown <lenb@kernel.org>
+Suggested-by: Dave Chinner <david@fromorbit.com>
+References: https://bugzilla.kernel.org/show_bug.cgi?id=216322
+Signed-off-by: Jan Kara <jack@suse.cz>
+Link: https://lore.kernel.org/r/20230913150504.9054-2-jack@suse.cz
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/ext4/mballoc.c | 12 ++++++++++--
+ 1 file changed, 10 insertions(+), 2 deletions(-)
+
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index 94b3bf8173e20..fb2f255c48e81 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -16,6 +16,7 @@
+ #include <linux/slab.h>
+ #include <linux/nospec.h>
+ #include <linux/backing-dev.h>
++#include <linux/freezer.h>
+ #include <trace/events/ext4.h>
+ #ifdef CONFIG_EXT4_DEBUG
+@@ -5194,6 +5195,11 @@ static ext4_grpblk_t ext4_last_grp_cluster(struct super_block *sb,
+                                       EXT4_CLUSTER_BITS(sb);
+ }
++static bool ext4_trim_interrupted(void)
++{
++      return fatal_signal_pending(current) || freezing(current);
++}
++
+ static int ext4_try_to_trim_range(struct super_block *sb,
+               struct ext4_buddy *e4b, ext4_grpblk_t start,
+               ext4_grpblk_t max, ext4_grpblk_t minblocks)
+@@ -5225,8 +5231,8 @@ static int ext4_try_to_trim_range(struct super_block *sb,
+               free_count += next - start;
+               start = next + 1;
+-              if (fatal_signal_pending(current))
+-                      return -ERESTARTSYS;
++              if (ext4_trim_interrupted())
++                      return count;
+               if (need_resched()) {
+                       ext4_unlock_group(sb, e4b->bd_group);
+@@ -5353,6 +5359,8 @@ int ext4_trim_fs(struct super_block *sb, struct fstrim_range *range)
+       end = EXT4_CLUSTERS_PER_GROUP(sb) - 1;
+       for (group = first_group; group <= last_group; group++) {
++              if (ext4_trim_interrupted())
++                      break;
+               grp = ext4_get_group_info(sb, group);
+               /* We only do this if the grp has never been initialized */
+               if (unlikely(EXT4_MB_GRP_NEED_INIT(grp))) {
+-- 
+2.40.1
+
diff --git a/queue-4.19/ext4-mark-group-as-trimmed-only-if-it-was-fully-scan.patch b/queue-4.19/ext4-mark-group-as-trimmed-only-if-it-was-fully-scan.patch
new file mode 100644 (file)
index 0000000..ea98ff4
--- /dev/null
@@ -0,0 +1,107 @@
+From e4ed3fc2904824cbb013485288c7dc6264b33f95 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 17 Apr 2022 20:03:15 +0300
+Subject: ext4: mark group as trimmed only if it was fully scanned
+
+From: Dmitry Monakhov <dmtrmonakhov@yandex-team.ru>
+
+[ Upstream commit d63c00ea435a5352f486c259665a4ced60399421 ]
+
+Otherwise nonaligned fstrim calls will works inconveniently for iterative
+scanners, for example:
+
+// trim [0,16MB] for group-1, but mark full group as trimmed
+fstrim  -o $((1024*1024*128)) -l $((1024*1024*16)) ./m
+// handle [16MB,16MB] for group-1, do nothing because group already has the flag.
+fstrim  -o $((1024*1024*144)) -l $((1024*1024*16)) ./m
+
+[ Update function documentation for ext4_trim_all_free -- TYT ]
+
+Signed-off-by: Dmitry Monakhov <dmtrmonakhov@yandex-team.ru>
+Link: https://lore.kernel.org/r/1650214995-860245-1-git-send-email-dmtrmonakhov@yandex-team.ru
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Cc: stable@kernel.org
+Stable-dep-of: 45e4ab320c9b ("ext4: move setting of trimmed bit into ext4_try_to_trim_range()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/ext4/mballoc.c | 18 ++++++++++++------
+ 1 file changed, 12 insertions(+), 6 deletions(-)
+
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index b76e8b8f01a10..e926b8c3ea893 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -5238,6 +5238,7 @@ static int ext4_try_to_trim_range(struct super_block *sb,
+  * @start:            first group block to examine
+  * @max:              last group block to examine
+  * @minblocks:                minimum extent block count
++ * @set_trimmed:      set the trimmed flag if at least one block is trimmed
+  *
+  * ext4_trim_all_free walks through group's buddy bitmap searching for free
+  * extents. When the free block is found, ext4_trim_extent is called to TRIM
+@@ -5252,7 +5253,7 @@ static int ext4_try_to_trim_range(struct super_block *sb,
+ static ext4_grpblk_t
+ ext4_trim_all_free(struct super_block *sb, ext4_group_t group,
+                  ext4_grpblk_t start, ext4_grpblk_t max,
+-                 ext4_grpblk_t minblocks)
++                 ext4_grpblk_t minblocks, bool set_trimmed)
+ {
+       struct ext4_buddy e4b;
+       int ret;
+@@ -5271,7 +5272,7 @@ ext4_trim_all_free(struct super_block *sb, ext4_group_t group,
+       if (!EXT4_MB_GRP_WAS_TRIMMED(e4b.bd_info) ||
+           minblocks < EXT4_SB(sb)->s_last_trim_minblks) {
+               ret = ext4_try_to_trim_range(sb, &e4b, start, max, minblocks);
+-              if (ret >= 0)
++              if (ret >= 0 && set_trimmed)
+                       EXT4_MB_GRP_SET_TRIMMED(e4b.bd_info);
+       } else {
+               ret = 0;
+@@ -5308,6 +5309,7 @@ int ext4_trim_fs(struct super_block *sb, struct fstrim_range *range)
+       ext4_fsblk_t first_data_blk =
+                       le32_to_cpu(EXT4_SB(sb)->s_es->s_first_data_block);
+       ext4_fsblk_t max_blks = ext4_blocks_count(EXT4_SB(sb)->s_es);
++      bool whole_group, eof = false;
+       int ret = 0;
+       start = range->start >> sb->s_blocksize_bits;
+@@ -5326,8 +5328,10 @@ int ext4_trim_fs(struct super_block *sb, struct fstrim_range *range)
+               if (minlen > EXT4_CLUSTERS_PER_GROUP(sb))
+                       goto out;
+       }
+-      if (end >= max_blks)
++      if (end >= max_blks - 1) {
+               end = max_blks - 1;
++              eof = true;
++      }
+       if (end <= first_data_blk)
+               goto out;
+       if (start < first_data_blk)
+@@ -5341,6 +5345,7 @@ int ext4_trim_fs(struct super_block *sb, struct fstrim_range *range)
+       /* end now represents the last cluster to discard in this group */
+       end = EXT4_CLUSTERS_PER_GROUP(sb) - 1;
++      whole_group = true;
+       for (group = first_group; group <= last_group; group++) {
+               grp = ext4_get_group_info(sb, group);
+@@ -5357,12 +5362,13 @@ int ext4_trim_fs(struct super_block *sb, struct fstrim_range *range)
+                * change it for the last group, note that last_cluster is
+                * already computed earlier by ext4_get_group_no_and_offset()
+                */
+-              if (group == last_group)
++              if (group == last_group) {
+                       end = last_cluster;
+-
++                      whole_group = eof ? true : end == EXT4_CLUSTERS_PER_GROUP(sb) - 1;
++              }
+               if (grp->bb_free >= minlen) {
+                       cnt = ext4_trim_all_free(sb, group, first_cluster,
+-                                              end, minlen);
++                                               end, minlen, whole_group);
+                       if (cnt < 0) {
+                               ret = cnt;
+                               break;
+-- 
+2.40.1
+
diff --git a/queue-4.19/ext4-move-setting-of-trimmed-bit-into-ext4_try_to_tr.patch b/queue-4.19/ext4-move-setting-of-trimmed-bit-into-ext4_try_to_tr.patch
new file mode 100644 (file)
index 0000000..ae33d0d
--- /dev/null
@@ -0,0 +1,168 @@
+From 7615b899fabc012b520ccf99eb10a9507834b98b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 13 Sep 2023 17:04:54 +0200
+Subject: ext4: move setting of trimmed bit into ext4_try_to_trim_range()
+
+From: Jan Kara <jack@suse.cz>
+
+[ Upstream commit 45e4ab320c9b5fa67b1fc3b6a9b381cfcc0c8488 ]
+
+Currently we set the group's trimmed bit in ext4_trim_all_free() based
+on return value of ext4_try_to_trim_range(). However when we will want
+to abort trimming because of suspend attempt, we want to return success
+from ext4_try_to_trim_range() but not set the trimmed bit. Instead
+implementing awkward propagation of this information, just move setting
+of trimmed bit into ext4_try_to_trim_range() when the whole group is
+trimmed.
+
+Cc: stable@kernel.org
+Signed-off-by: Jan Kara <jack@suse.cz>
+Link: https://lore.kernel.org/r/20230913150504.9054-1-jack@suse.cz
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/ext4/mballoc.c | 46 +++++++++++++++++++++++++---------------------
+ 1 file changed, 25 insertions(+), 21 deletions(-)
+
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index 22da6b1143e5d..94b3bf8173e20 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -5184,14 +5184,27 @@ __acquires(bitlock)
+       return ret;
+ }
++static ext4_grpblk_t ext4_last_grp_cluster(struct super_block *sb,
++                                         ext4_group_t grp)
++{
++      if (grp < ext4_get_groups_count(sb))
++              return EXT4_CLUSTERS_PER_GROUP(sb) - 1;
++      return (ext4_blocks_count(EXT4_SB(sb)->s_es) -
++              ext4_group_first_block_no(sb, grp) - 1) >>
++                                      EXT4_CLUSTER_BITS(sb);
++}
++
+ static int ext4_try_to_trim_range(struct super_block *sb,
+               struct ext4_buddy *e4b, ext4_grpblk_t start,
+               ext4_grpblk_t max, ext4_grpblk_t minblocks)
+ {
+       ext4_grpblk_t next, count, free_count;
++      bool set_trimmed = false;
+       void *bitmap;
+       bitmap = e4b->bd_bitmap;
++      if (start == 0 && max >= ext4_last_grp_cluster(sb, e4b->bd_group))
++              set_trimmed = true;
+       start = max(e4b->bd_info->bb_first_free, start);
+       count = 0;
+       free_count = 0;
+@@ -5206,16 +5219,14 @@ static int ext4_try_to_trim_range(struct super_block *sb,
+                       int ret = ext4_trim_extent(sb, start, next - start, e4b);
+                       if (ret && ret != -EOPNOTSUPP)
+-                              break;
++                              return count;
+                       count += next - start;
+               }
+               free_count += next - start;
+               start = next + 1;
+-              if (fatal_signal_pending(current)) {
+-                      count = -ERESTARTSYS;
+-                      break;
+-              }
++              if (fatal_signal_pending(current))
++                      return -ERESTARTSYS;
+               if (need_resched()) {
+                       ext4_unlock_group(sb, e4b->bd_group);
+@@ -5227,6 +5238,9 @@ static int ext4_try_to_trim_range(struct super_block *sb,
+                       break;
+       }
++      if (set_trimmed)
++              EXT4_MB_GRP_SET_TRIMMED(e4b->bd_info);
++
+       return count;
+ }
+@@ -5237,7 +5251,6 @@ static int ext4_try_to_trim_range(struct super_block *sb,
+  * @start:            first group block to examine
+  * @max:              last group block to examine
+  * @minblocks:                minimum extent block count
+- * @set_trimmed:      set the trimmed flag if at least one block is trimmed
+  *
+  * ext4_trim_all_free walks through group's buddy bitmap searching for free
+  * extents. When the free block is found, ext4_trim_extent is called to TRIM
+@@ -5252,7 +5265,7 @@ static int ext4_try_to_trim_range(struct super_block *sb,
+ static ext4_grpblk_t
+ ext4_trim_all_free(struct super_block *sb, ext4_group_t group,
+                  ext4_grpblk_t start, ext4_grpblk_t max,
+-                 ext4_grpblk_t minblocks, bool set_trimmed)
++                 ext4_grpblk_t minblocks)
+ {
+       struct ext4_buddy e4b;
+       int ret;
+@@ -5269,13 +5282,10 @@ ext4_trim_all_free(struct super_block *sb, ext4_group_t group,
+       ext4_lock_group(sb, group);
+       if (!EXT4_MB_GRP_WAS_TRIMMED(e4b.bd_info) ||
+-          minblocks < EXT4_SB(sb)->s_last_trim_minblks) {
++          minblocks < EXT4_SB(sb)->s_last_trim_minblks)
+               ret = ext4_try_to_trim_range(sb, &e4b, start, max, minblocks);
+-              if (ret >= 0 && set_trimmed)
+-                      EXT4_MB_GRP_SET_TRIMMED(e4b.bd_info);
+-      } else {
++      else
+               ret = 0;
+-      }
+       ext4_unlock_group(sb, group);
+       ext4_mb_unload_buddy(&e4b);
+@@ -5308,7 +5318,6 @@ int ext4_trim_fs(struct super_block *sb, struct fstrim_range *range)
+       ext4_fsblk_t first_data_blk =
+                       le32_to_cpu(EXT4_SB(sb)->s_es->s_first_data_block);
+       ext4_fsblk_t max_blks = ext4_blocks_count(EXT4_SB(sb)->s_es);
+-      bool whole_group, eof = false;
+       int ret = 0;
+       start = range->start >> sb->s_blocksize_bits;
+@@ -5327,10 +5336,8 @@ int ext4_trim_fs(struct super_block *sb, struct fstrim_range *range)
+               if (minlen > EXT4_CLUSTERS_PER_GROUP(sb))
+                       goto out;
+       }
+-      if (end >= max_blks - 1) {
++      if (end >= max_blks - 1)
+               end = max_blks - 1;
+-              eof = true;
+-      }
+       if (end <= first_data_blk)
+               goto out;
+       if (start < first_data_blk)
+@@ -5344,7 +5351,6 @@ int ext4_trim_fs(struct super_block *sb, struct fstrim_range *range)
+       /* end now represents the last cluster to discard in this group */
+       end = EXT4_CLUSTERS_PER_GROUP(sb) - 1;
+-      whole_group = true;
+       for (group = first_group; group <= last_group; group++) {
+               grp = ext4_get_group_info(sb, group);
+@@ -5361,13 +5367,11 @@ int ext4_trim_fs(struct super_block *sb, struct fstrim_range *range)
+                * change it for the last group, note that last_cluster is
+                * already computed earlier by ext4_get_group_no_and_offset()
+                */
+-              if (group == last_group) {
++              if (group == last_group)
+                       end = last_cluster;
+-                      whole_group = eof ? true : end == EXT4_CLUSTERS_PER_GROUP(sb) - 1;
+-              }
+               if (grp->bb_free >= minlen) {
+                       cnt = ext4_trim_all_free(sb, group, first_cluster,
+-                                               end, minlen, whole_group);
++                                               end, minlen);
+                       if (cnt < 0) {
+                               ret = cnt;
+                               break;
+-- 
+2.40.1
+
diff --git a/queue-4.19/ext4-remove-the-group-parameter-of-ext4_trim_extent.patch b/queue-4.19/ext4-remove-the-group-parameter-of-ext4_trim_extent.patch
new file mode 100644 (file)
index 0000000..c4bae6d
--- /dev/null
@@ -0,0 +1,63 @@
+From 5b2e280bd439a66416f6278a45bfc619118ee65c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 24 Jul 2021 15:41:20 +0800
+Subject: ext4: remove the 'group' parameter of ext4_trim_extent
+
+From: Wang Jianchao <wangjianchao@kuaishou.com>
+
+[ Upstream commit bd2eea8d0a6b6a9aca22f20bf74f73b71d8808af ]
+
+Get rid of the 'group' parameter of ext4_trim_extent as we can get
+it from the 'e4b'.
+
+Reviewed-by: Andreas Dilger <adilger@dilger.ca>
+Signed-off-by: Wang Jianchao <wangjianchao@kuaishou.com>
+Reviewed-by: Jan Kara <jack@suse.cz>
+Link: https://lore.kernel.org/r/20210724074124.25731-2-jianchao.wan9@gmail.com
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Stable-dep-of: 45e4ab320c9b ("ext4: move setting of trimmed bit into ext4_try_to_trim_range()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/ext4/mballoc.c | 9 ++++-----
+ 1 file changed, 4 insertions(+), 5 deletions(-)
+
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index 7692c12b85285..7b81094831754 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -5149,19 +5149,19 @@ int ext4_group_add_blocks(handle_t *handle, struct super_block *sb,
+  * @sb:               super block for the file system
+  * @start:    starting block of the free extent in the alloc. group
+  * @count:    number of blocks to TRIM
+- * @group:    alloc. group we are working with
+  * @e4b:      ext4 buddy for the group
+  *
+  * Trim "count" blocks starting at "start" in the "group". To assure that no
+  * one will allocate those blocks, mark it as used in buddy bitmap. This must
+  * be called with under the group lock.
+  */
+-static int ext4_trim_extent(struct super_block *sb, int start, int count,
+-                           ext4_group_t group, struct ext4_buddy *e4b)
++static int ext4_trim_extent(struct super_block *sb,
++              int start, int count, struct ext4_buddy *e4b)
+ __releases(bitlock)
+ __acquires(bitlock)
+ {
+       struct ext4_free_extent ex;
++      ext4_group_t group = e4b->bd_group;
+       int ret = 0;
+       trace_ext4_trim_extent(sb, group, start, count);
+@@ -5237,8 +5237,7 @@ ext4_trim_all_free(struct super_block *sb, ext4_group_t group,
+               next = mb_find_next_bit(bitmap, max + 1, start);
+               if ((next - start) >= minblocks) {
+-                      ret = ext4_trim_extent(sb, start,
+-                                             next - start, group, &e4b);
++                      ret = ext4_trim_extent(sb, start, next - start, &e4b);
+                       if (ret && ret != -EOPNOTSUPP)
+                               break;
+                       ret = 0;
+-- 
+2.40.1
+
diff --git a/queue-4.19/ext4-replace-the-traditional-ternary-conditional-ope.patch b/queue-4.19/ext4-replace-the-traditional-ternary-conditional-ope.patch
new file mode 100644 (file)
index 0000000..b88097d
--- /dev/null
@@ -0,0 +1,49 @@
+From 4dbbba480ea84526dfbf9badd67d2c0ee5bf9434 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 1 Aug 2023 22:32:00 +0800
+Subject: ext4: replace the traditional ternary conditional operator with with
+ max()/min()
+
+From: Kemeng Shi <shikemeng@huaweicloud.com>
+
+[ Upstream commit de8bf0e5ee7482585450357c6d4eddec8efc5cb7 ]
+
+Replace the traditional ternary conditional operator with with max()/min()
+
+Signed-off-by: Kemeng Shi <shikemeng@huaweicloud.com>
+Reviewed-by: Ritesh Harjani (IBM) <ritesh.list@gmail.com>
+Link: https://lore.kernel.org/r/20230801143204.2284343-7-shikemeng@huaweicloud.com
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Stable-dep-of: 45e4ab320c9b ("ext4: move setting of trimmed bit into ext4_try_to_trim_range()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/ext4/mballoc.c | 6 ++----
+ 1 file changed, 2 insertions(+), 4 deletions(-)
+
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index e926b8c3ea893..22da6b1143e5d 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -5192,8 +5192,7 @@ static int ext4_try_to_trim_range(struct super_block *sb,
+       void *bitmap;
+       bitmap = e4b->bd_bitmap;
+-      start = (e4b->bd_info->bb_first_free > start) ?
+-              e4b->bd_info->bb_first_free : start;
++      start = max(e4b->bd_info->bb_first_free, start);
+       count = 0;
+       free_count = 0;
+@@ -5413,8 +5412,7 @@ ext4_mballoc_query_range(
+       ext4_lock_group(sb, group);
+-      start = (e4b.bd_info->bb_first_free > start) ?
+-              e4b.bd_info->bb_first_free : start;
++      start = max(e4b.bd_info->bb_first_free, start);
+       if (end >= EXT4_CLUSTERS_PER_GROUP(sb))
+               end = EXT4_CLUSTERS_PER_GROUP(sb) - 1;
+-- 
+2.40.1
+
diff --git a/queue-4.19/ext4-scope-ret-locally-in-ext4_try_to_trim_range.patch b/queue-4.19/ext4-scope-ret-locally-in-ext4_try_to_trim_range.patch
new file mode 100644 (file)
index 0000000..8229c74
--- /dev/null
@@ -0,0 +1,55 @@
+From 21abc74977d5eb29ce86d5eb9d66b9bad594bf87 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 20 Aug 2021 14:08:53 +0200
+Subject: ext4: scope ret locally in ext4_try_to_trim_range()
+
+From: Lukas Bulwahn <lukas.bulwahn@gmail.com>
+
+[ Upstream commit afcc4e32f606dbfb47aa7309172c89174b86e74c ]
+
+As commit 6920b3913235 ("ext4: add new helper interface
+ext4_try_to_trim_range()") moves some code into the separate function
+ext4_try_to_trim_range(), the use of the variable ret within that
+function is more limited and can be adjusted as well.
+
+Scope the use of the variable ret locally and drop dead assignments.
+
+No functional change.
+
+Signed-off-by: Lukas Bulwahn <lukas.bulwahn@gmail.com>
+Link: https://lore.kernel.org/r/20210820120853.23134-1-lukas.bulwahn@gmail.com
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Stable-dep-of: 45e4ab320c9b ("ext4: move setting of trimmed bit into ext4_try_to_trim_range()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/ext4/mballoc.c | 5 ++---
+ 1 file changed, 2 insertions(+), 3 deletions(-)
+
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index 51def652098b3..58a0d2ea314b7 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -5190,7 +5190,6 @@ static int ext4_try_to_trim_range(struct super_block *sb,
+ {
+       ext4_grpblk_t next, count, free_count;
+       void *bitmap;
+-      int ret = 0;
+       bitmap = e4b->bd_bitmap;
+       start = (e4b->bd_info->bb_first_free > start) ?
+@@ -5205,10 +5204,10 @@ static int ext4_try_to_trim_range(struct super_block *sb,
+               next = mb_find_next_bit(bitmap, max + 1, start);
+               if ((next - start) >= minblocks) {
+-                      ret = ext4_trim_extent(sb, start, next - start, e4b);
++                      int ret = ext4_trim_extent(sb, start, next - start, e4b);
++
+                       if (ret && ret != -EOPNOTSUPP)
+                               break;
+-                      ret = 0;
+                       count += next - start;
+               }
+               free_count += next - start;
+-- 
+2.40.1
+
diff --git a/queue-4.19/input-i8042-add-quirk-for-tuxedo-gemini-17-gen1-clev.patch b/queue-4.19/input-i8042-add-quirk-for-tuxedo-gemini-17-gen1-clev.patch
new file mode 100644 (file)
index 0000000..9634292
--- /dev/null
@@ -0,0 +1,50 @@
+From 85b2d545e7b9ab18722f944b01307672b1737ad4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 12 Jul 2023 11:56:51 -0700
+Subject: Input: i8042 - add quirk for TUXEDO Gemini 17 Gen1/Clevo PD70PN
+
+From: Werner Sembach <wse@tuxedocomputers.com>
+
+[ Upstream commit eb09074bdb05ffd6bfe77f8b4a41b76ef78c997b ]
+
+The touchpad of this device is both connected via PS/2 and i2c. This causes
+strange behavior when both driver fight for control. The easy fix is to
+prevent the PS/2 driver from accessing the mouse port as the full feature
+set of the touchpad is only supported in the i2c interface anyway.
+
+The strange behavior in this case is, that when an external screen is
+connected and the notebook is closed, the pointer on the external screen is
+moving to the lower right corner. When the notebook is opened again, this
+movement stops, but the touchpad clicks are unresponsive afterwards until
+reboot.
+
+Signed-off-by: Werner Sembach <wse@tuxedocomputers.com>
+Cc: stable@vger.kernel.org
+Link: https://lore.kernel.org/r/20230607173331.851192-1-wse@tuxedocomputers.com
+Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/input/serio/i8042-x86ia64io.h | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h
+index da2bf8259330e..0cf9a37873261 100644
+--- a/drivers/input/serio/i8042-x86ia64io.h
++++ b/drivers/input/serio/i8042-x86ia64io.h
+@@ -1188,6 +1188,13 @@ static const struct dmi_system_id i8042_dmi_quirk_table[] __initconst = {
+               .driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS |
+                                       SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP)
+       },
++      /* See comment on TUXEDO InfinityBook S17 Gen6 / Clevo NS70MU above */
++      {
++              .matches = {
++                      DMI_MATCH(DMI_BOARD_NAME, "PD5x_7xPNP_PNR_PNN_PNT"),
++              },
++              .driver_data = (void *)(SERIO_QUIRK_NOAUX)
++      },
+       {
+               .matches = {
+                       DMI_MATCH(DMI_BOARD_NAME, "X170SM"),
+-- 
+2.40.1
+
diff --git a/queue-4.19/scsi-megaraid_sas-fix-deadlock-on-firmware-crashdump.patch b/queue-4.19/scsi-megaraid_sas-fix-deadlock-on-firmware-crashdump.patch
new file mode 100644 (file)
index 0000000..2e555eb
--- /dev/null
@@ -0,0 +1,183 @@
+From 91a3f294febcd7987d48cf7e248db51be5a93290 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 28 Aug 2023 15:10:18 -0700
+Subject: scsi: megaraid_sas: Fix deadlock on firmware crashdump
+
+From: Junxiao Bi <junxiao.bi@oracle.com>
+
+[ Upstream commit 0b0747d507bffb827e40fc0f9fb5883fffc23477 ]
+
+The following processes run into a deadlock. CPU 41 was waiting for CPU 29
+to handle a CSD request while holding spinlock "crashdump_lock", but CPU 29
+was hung by that spinlock with IRQs disabled.
+
+  PID: 17360    TASK: ffff95c1090c5c40  CPU: 41  COMMAND: "mrdiagd"
+  !# 0 [ffffb80edbf37b58] __read_once_size at ffffffff9b871a40 include/linux/compiler.h:185:0
+  !# 1 [ffffb80edbf37b58] atomic_read at ffffffff9b871a40 arch/x86/include/asm/atomic.h:27:0
+  !# 2 [ffffb80edbf37b58] dump_stack at ffffffff9b871a40 lib/dump_stack.c:54:0
+   # 3 [ffffb80edbf37b78] csd_lock_wait_toolong at ffffffff9b131ad5 kernel/smp.c:364:0
+   # 4 [ffffb80edbf37b78] __csd_lock_wait at ffffffff9b131ad5 kernel/smp.c:384:0
+   # 5 [ffffb80edbf37bf8] csd_lock_wait at ffffffff9b13267a kernel/smp.c:394:0
+   # 6 [ffffb80edbf37bf8] smp_call_function_many at ffffffff9b13267a kernel/smp.c:843:0
+   # 7 [ffffb80edbf37c50] smp_call_function at ffffffff9b13279d kernel/smp.c:867:0
+   # 8 [ffffb80edbf37c50] on_each_cpu at ffffffff9b13279d kernel/smp.c:976:0
+   # 9 [ffffb80edbf37c78] flush_tlb_kernel_range at ffffffff9b085c4b arch/x86/mm/tlb.c:742:0
+   #10 [ffffb80edbf37cb8] __purge_vmap_area_lazy at ffffffff9b23a1e0 mm/vmalloc.c:701:0
+   #11 [ffffb80edbf37ce0] try_purge_vmap_area_lazy at ffffffff9b23a2cc mm/vmalloc.c:722:0
+   #12 [ffffb80edbf37ce0] free_vmap_area_noflush at ffffffff9b23a2cc mm/vmalloc.c:754:0
+   #13 [ffffb80edbf37cf8] free_unmap_vmap_area at ffffffff9b23bb3b mm/vmalloc.c:764:0
+   #14 [ffffb80edbf37cf8] remove_vm_area at ffffffff9b23bb3b mm/vmalloc.c:1509:0
+   #15 [ffffb80edbf37d18] __vunmap at ffffffff9b23bb8a mm/vmalloc.c:1537:0
+   #16 [ffffb80edbf37d40] vfree at ffffffff9b23bc85 mm/vmalloc.c:1612:0
+   #17 [ffffb80edbf37d58] megasas_free_host_crash_buffer [megaraid_sas] at ffffffffc020b7f2 drivers/scsi/megaraid/megaraid_sas_fusion.c:3932:0
+   #18 [ffffb80edbf37d80] fw_crash_state_store [megaraid_sas] at ffffffffc01f804d drivers/scsi/megaraid/megaraid_sas_base.c:3291:0
+   #19 [ffffb80edbf37dc0] dev_attr_store at ffffffff9b56dd7b drivers/base/core.c:758:0
+   #20 [ffffb80edbf37dd0] sysfs_kf_write at ffffffff9b326acf fs/sysfs/file.c:144:0
+   #21 [ffffb80edbf37de0] kernfs_fop_write at ffffffff9b325fd4 fs/kernfs/file.c:316:0
+   #22 [ffffb80edbf37e20] __vfs_write at ffffffff9b29418a fs/read_write.c:480:0
+   #23 [ffffb80edbf37ea8] vfs_write at ffffffff9b294462 fs/read_write.c:544:0
+   #24 [ffffb80edbf37ee8] SYSC_write at ffffffff9b2946ec fs/read_write.c:590:0
+   #25 [ffffb80edbf37ee8] SyS_write at ffffffff9b2946ec fs/read_write.c:582:0
+   #26 [ffffb80edbf37f30] do_syscall_64 at ffffffff9b003ca9 arch/x86/entry/common.c:298:0
+   #27 [ffffb80edbf37f58] entry_SYSCALL_64 at ffffffff9ba001b1 arch/x86/entry/entry_64.S:238:0
+
+  PID: 17355    TASK: ffff95c1090c3d80  CPU: 29  COMMAND: "mrdiagd"
+  !# 0 [ffffb80f2d3c7d30] __read_once_size at ffffffff9b0f2ab0 include/linux/compiler.h:185:0
+  !# 1 [ffffb80f2d3c7d30] native_queued_spin_lock_slowpath at ffffffff9b0f2ab0 kernel/locking/qspinlock.c:368:0
+   # 2 [ffffb80f2d3c7d58] pv_queued_spin_lock_slowpath at ffffffff9b0f244b arch/x86/include/asm/paravirt.h:674:0
+   # 3 [ffffb80f2d3c7d58] queued_spin_lock_slowpath at ffffffff9b0f244b arch/x86/include/asm/qspinlock.h:53:0
+   # 4 [ffffb80f2d3c7d68] queued_spin_lock at ffffffff9b8961a6 include/asm-generic/qspinlock.h:90:0
+   # 5 [ffffb80f2d3c7d68] do_raw_spin_lock_flags at ffffffff9b8961a6 include/linux/spinlock.h:173:0
+   # 6 [ffffb80f2d3c7d68] __raw_spin_lock_irqsave at ffffffff9b8961a6 include/linux/spinlock_api_smp.h:122:0
+   # 7 [ffffb80f2d3c7d68] _raw_spin_lock_irqsave at ffffffff9b8961a6 kernel/locking/spinlock.c:160:0
+   # 8 [ffffb80f2d3c7d88] fw_crash_buffer_store [megaraid_sas] at ffffffffc01f8129 drivers/scsi/megaraid/megaraid_sas_base.c:3205:0
+   # 9 [ffffb80f2d3c7dc0] dev_attr_store at ffffffff9b56dd7b drivers/base/core.c:758:0
+   #10 [ffffb80f2d3c7dd0] sysfs_kf_write at ffffffff9b326acf fs/sysfs/file.c:144:0
+   #11 [ffffb80f2d3c7de0] kernfs_fop_write at ffffffff9b325fd4 fs/kernfs/file.c:316:0
+   #12 [ffffb80f2d3c7e20] __vfs_write at ffffffff9b29418a fs/read_write.c:480:0
+   #13 [ffffb80f2d3c7ea8] vfs_write at ffffffff9b294462 fs/read_write.c:544:0
+   #14 [ffffb80f2d3c7ee8] SYSC_write at ffffffff9b2946ec fs/read_write.c:590:0
+   #15 [ffffb80f2d3c7ee8] SyS_write at ffffffff9b2946ec fs/read_write.c:582:0
+   #16 [ffffb80f2d3c7f30] do_syscall_64 at ffffffff9b003ca9 arch/x86/entry/common.c:298:0
+   #17 [ffffb80f2d3c7f58] entry_SYSCALL_64 at ffffffff9ba001b1 arch/x86/entry/entry_64.S:238:0
+
+The lock is used to synchronize different sysfs operations, it doesn't
+protect any resource that will be touched by an interrupt. Consequently
+it's not required to disable IRQs. Replace the spinlock with a mutex to fix
+the deadlock.
+
+Signed-off-by: Junxiao Bi <junxiao.bi@oracle.com>
+Link: https://lore.kernel.org/r/20230828221018.19471-1-junxiao.bi@oracle.com
+Reviewed-by: Mike Christie <michael.christie@oracle.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/scsi/megaraid/megaraid_sas.h      |  2 +-
+ drivers/scsi/megaraid/megaraid_sas_base.c | 21 +++++++++------------
+ 2 files changed, 10 insertions(+), 13 deletions(-)
+
+diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h
+index 80ae48b65b608..0d7cca9365aac 100644
+--- a/drivers/scsi/megaraid/megaraid_sas.h
++++ b/drivers/scsi/megaraid/megaraid_sas.h
+@@ -2194,7 +2194,7 @@ struct megasas_instance {
+       u32 support_morethan256jbod; /* FW support for more than 256 PD/JBOD */
+       bool use_seqnum_jbod_fp;   /* Added for PD sequence */
+       bool smp_affinity_enable;
+-      spinlock_t crashdump_lock;
++      struct mutex crashdump_lock;
+       struct megasas_register_set __iomem *reg_set;
+       u32 __iomem *reply_post_host_index_addr[MR_MAX_MSIX_REG_ARRAY];
+diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c
+index 2b6b6d3deba86..bdfa36712fcc4 100644
+--- a/drivers/scsi/megaraid/megaraid_sas_base.c
++++ b/drivers/scsi/megaraid/megaraid_sas_base.c
+@@ -3004,14 +3004,13 @@ megasas_fw_crash_buffer_store(struct device *cdev,
+       struct megasas_instance *instance =
+               (struct megasas_instance *) shost->hostdata;
+       int val = 0;
+-      unsigned long flags;
+       if (kstrtoint(buf, 0, &val) != 0)
+               return -EINVAL;
+-      spin_lock_irqsave(&instance->crashdump_lock, flags);
++      mutex_lock(&instance->crashdump_lock);
+       instance->fw_crash_buffer_offset = val;
+-      spin_unlock_irqrestore(&instance->crashdump_lock, flags);
++      mutex_unlock(&instance->crashdump_lock);
+       return strlen(buf);
+ }
+@@ -3027,17 +3026,16 @@ megasas_fw_crash_buffer_show(struct device *cdev,
+       unsigned long dmachunk = CRASH_DMA_BUF_SIZE;
+       unsigned long chunk_left_bytes;
+       unsigned long src_addr;
+-      unsigned long flags;
+       u32 buff_offset;
+-      spin_lock_irqsave(&instance->crashdump_lock, flags);
++      mutex_lock(&instance->crashdump_lock);
+       buff_offset = instance->fw_crash_buffer_offset;
+       if (!instance->crash_dump_buf ||
+               !((instance->fw_crash_state == AVAILABLE) ||
+               (instance->fw_crash_state == COPYING))) {
+               dev_err(&instance->pdev->dev,
+                       "Firmware crash dump is not available\n");
+-              spin_unlock_irqrestore(&instance->crashdump_lock, flags);
++              mutex_unlock(&instance->crashdump_lock);
+               return -EINVAL;
+       }
+@@ -3046,7 +3044,7 @@ megasas_fw_crash_buffer_show(struct device *cdev,
+       if (buff_offset > (instance->fw_crash_buffer_size * dmachunk)) {
+               dev_err(&instance->pdev->dev,
+                       "Firmware crash dump offset is out of range\n");
+-              spin_unlock_irqrestore(&instance->crashdump_lock, flags);
++              mutex_unlock(&instance->crashdump_lock);
+               return 0;
+       }
+@@ -3058,7 +3056,7 @@ megasas_fw_crash_buffer_show(struct device *cdev,
+       src_addr = (unsigned long)instance->crash_buf[buff_offset / dmachunk] +
+               (buff_offset % dmachunk);
+       memcpy(buf, (void *)src_addr, size);
+-      spin_unlock_irqrestore(&instance->crashdump_lock, flags);
++      mutex_unlock(&instance->crashdump_lock);
+       return size;
+ }
+@@ -3083,7 +3081,6 @@ megasas_fw_crash_state_store(struct device *cdev,
+       struct megasas_instance *instance =
+               (struct megasas_instance *) shost->hostdata;
+       int val = 0;
+-      unsigned long flags;
+       if (kstrtoint(buf, 0, &val) != 0)
+               return -EINVAL;
+@@ -3097,9 +3094,9 @@ megasas_fw_crash_state_store(struct device *cdev,
+       instance->fw_crash_state = val;
+       if ((val == COPIED) || (val == COPY_ERROR)) {
+-              spin_lock_irqsave(&instance->crashdump_lock, flags);
++              mutex_lock(&instance->crashdump_lock);
+               megasas_free_host_crash_buffer(instance);
+-              spin_unlock_irqrestore(&instance->crashdump_lock, flags);
++              mutex_unlock(&instance->crashdump_lock);
+               if (val == COPY_ERROR)
+                       dev_info(&instance->pdev->dev, "application failed to "
+                               "copy Firmware crash dump\n");
+@@ -6463,7 +6460,7 @@ static inline void megasas_init_ctrl_params(struct megasas_instance *instance)
+       init_waitqueue_head(&instance->int_cmd_wait_q);
+       init_waitqueue_head(&instance->abort_cmd_wait_q);
+-      spin_lock_init(&instance->crashdump_lock);
++      mutex_init(&instance->crashdump_lock);
+       spin_lock_init(&instance->mfi_pool_lock);
+       spin_lock_init(&instance->hba_lock);
+       spin_lock_init(&instance->stream_lock);
+-- 
+2.40.1
+
diff --git a/queue-4.19/scsi-megaraid_sas-load-balance-completions-across-al.patch b/queue-4.19/scsi-megaraid_sas-load-balance-completions-across-al.patch
new file mode 100644 (file)
index 0000000..f071059
--- /dev/null
@@ -0,0 +1,181 @@
+From 55ce88cf3cd84bb969f14dda7cd9030faffd71b6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 7 May 2019 10:05:36 -0700
+Subject: scsi: megaraid_sas: Load balance completions across all MSI-X
+
+From: Shivasharan S <shivasharan.srikanteshwara@broadcom.com>
+
+[ Upstream commit 1d15d9098ad12b0021ac5a6b851f26d1ab021e5a ]
+
+Driver will use "reply descriptor post queues" in round robin fashion when
+the combined MSI-X mode is not enabled. With this IO completions are
+distributed and load balanced across all the available reply descriptor
+post queues equally.
+
+This is enabled only if combined MSI-X mode is not enabled in firmware.
+This improves performance and also fixes soft lockups.
+
+When load balancing is enabled, IRQ affinity from driver needs to be
+disabled.
+
+Signed-off-by: Kashyap Desai <kashyap.desai@broadcom.com>
+Signed-off-by: Shivasharan S <shivasharan.srikanteshwara@broadcom.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Stable-dep-of: 0b0747d507bf ("scsi: megaraid_sas: Fix deadlock on firmware crashdump")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/scsi/megaraid/megaraid_sas.h        |  3 +++
+ drivers/scsi/megaraid/megaraid_sas_base.c   | 22 +++++++++++++++++----
+ drivers/scsi/megaraid/megaraid_sas_fusion.c | 18 +++++++++++++----
+ 3 files changed, 35 insertions(+), 8 deletions(-)
+
+diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h
+index 67d356d847176..80ae48b65b608 100644
+--- a/drivers/scsi/megaraid/megaraid_sas.h
++++ b/drivers/scsi/megaraid/megaraid_sas.h
+@@ -2193,6 +2193,7 @@ struct megasas_instance {
+       u32 secure_jbod_support;
+       u32 support_morethan256jbod; /* FW support for more than 256 PD/JBOD */
+       bool use_seqnum_jbod_fp;   /* Added for PD sequence */
++      bool smp_affinity_enable;
+       spinlock_t crashdump_lock;
+       struct megasas_register_set __iomem *reg_set;
+@@ -2210,6 +2211,7 @@ struct megasas_instance {
+       u16 ldio_threshold;
+       u16 cur_can_queue;
+       u32 max_sectors_per_req;
++      bool msix_load_balance;
+       struct megasas_aen_event *ev;
+       struct megasas_cmd **cmd_list;
+@@ -2246,6 +2248,7 @@ struct megasas_instance {
+       atomic_t sge_holes_type1;
+       atomic_t sge_holes_type2;
+       atomic_t sge_holes_type3;
++      atomic64_t total_io_count;
+       struct megasas_instance_template *instancet;
+       struct tasklet_struct isr_tasklet;
+diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c
+index 8d1df03386b4f..2b6b6d3deba86 100644
+--- a/drivers/scsi/megaraid/megaraid_sas_base.c
++++ b/drivers/scsi/megaraid/megaraid_sas_base.c
+@@ -5101,6 +5101,7 @@ megasas_setup_irqs_msix(struct megasas_instance *instance, u8 is_probe)
+                                        &instance->irq_context[j]);
+                       /* Retry irq register for IO_APIC*/
+                       instance->msix_vectors = 0;
++                      instance->msix_load_balance = false;
+                       if (is_probe) {
+                               pci_free_irq_vectors(instance->pdev);
+                               return megasas_setup_irqs_ioapic(instance);
+@@ -5109,6 +5110,7 @@ megasas_setup_irqs_msix(struct megasas_instance *instance, u8 is_probe)
+                       }
+               }
+       }
++
+       return 0;
+ }
+@@ -5364,6 +5366,12 @@ static int megasas_init_fw(struct megasas_instance *instance)
+                               if (rdpq_enable)
+                                       instance->is_rdpq = (scratch_pad_2 & MR_RDPQ_MODE_OFFSET) ?
+                                                               1 : 0;
++
++                              if (!instance->msix_combined) {
++                                      instance->msix_load_balance = true;
++                                      instance->smp_affinity_enable = false;
++                              }
++
+                               fw_msix_count = instance->msix_vectors;
+                               /* Save 1-15 reply post index address to local memory
+                                * Index 0 is already saved from reg offset
+@@ -5382,17 +5390,20 @@ static int megasas_init_fw(struct megasas_instance *instance)
+                                       instance->msix_vectors);
+               } else /* MFI adapters */
+                       instance->msix_vectors = 1;
++
+               /* Don't bother allocating more MSI-X vectors than cpus */
+               instance->msix_vectors = min(instance->msix_vectors,
+                                            (unsigned int)num_online_cpus());
+-              if (smp_affinity_enable)
++              if (instance->smp_affinity_enable)
+                       irq_flags |= PCI_IRQ_AFFINITY;
+               i = pci_alloc_irq_vectors(instance->pdev, 1,
+                                         instance->msix_vectors, irq_flags);
+-              if (i > 0)
++              if (i > 0) {
+                       instance->msix_vectors = i;
+-              else
++              } else {
+                       instance->msix_vectors = 0;
++                      instance->msix_load_balance = false;
++              }
+       }
+       /*
+        * MSI-X host index 0 is common for all adapter.
+@@ -6447,6 +6458,7 @@ static inline void megasas_init_ctrl_params(struct megasas_instance *instance)
+       INIT_LIST_HEAD(&instance->internal_reset_pending_q);
+       atomic_set(&instance->fw_outstanding, 0);
++      atomic64_set(&instance->total_io_count, 0);
+       init_waitqueue_head(&instance->int_cmd_wait_q);
+       init_waitqueue_head(&instance->abort_cmd_wait_q);
+@@ -6469,6 +6481,8 @@ static inline void megasas_init_ctrl_params(struct megasas_instance *instance)
+       instance->last_time = 0;
+       instance->disableOnlineCtrlReset = 1;
+       instance->UnevenSpanSupport = 0;
++      instance->smp_affinity_enable = smp_affinity_enable ? true : false;
++      instance->msix_load_balance = false;
+       if (instance->adapter_type != MFI_SERIES) {
+               INIT_WORK(&instance->work_init, megasas_fusion_ocr_wq);
+@@ -6818,7 +6832,7 @@ megasas_resume(struct pci_dev *pdev)
+       /* Now re-enable MSI-X */
+       if (instance->msix_vectors) {
+               irq_flags = PCI_IRQ_MSIX;
+-              if (smp_affinity_enable)
++              if (instance->smp_affinity_enable)
+                       irq_flags |= PCI_IRQ_AFFINITY;
+       }
+       rval = pci_alloc_irq_vectors(instance->pdev, 1,
+diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.c b/drivers/scsi/megaraid/megaraid_sas_fusion.c
+index b400167f9ad42..294e1a3a6adfa 100644
+--- a/drivers/scsi/megaraid/megaraid_sas_fusion.c
++++ b/drivers/scsi/megaraid/megaraid_sas_fusion.c
+@@ -2641,8 +2641,13 @@ megasas_build_ldio_fusion(struct megasas_instance *instance,
+                       fp_possible = (io_info.fpOkForIo > 0) ? true : false;
+       }
+-      cmd->request_desc->SCSIIO.MSIxIndex =
+-              instance->reply_map[raw_smp_processor_id()];
++      if (instance->msix_load_balance)
++              cmd->request_desc->SCSIIO.MSIxIndex =
++                      (mega_mod64(atomic64_add_return(1, &instance->total_io_count),
++                                  instance->msix_vectors));
++      else
++              cmd->request_desc->SCSIIO.MSIxIndex =
++                      instance->reply_map[raw_smp_processor_id()];
+       praid_context = &io_request->RaidContext;
+@@ -2969,8 +2974,13 @@ megasas_build_syspd_fusion(struct megasas_instance *instance,
+       cmd->request_desc->SCSIIO.DevHandle = io_request->DevHandle;
+-      cmd->request_desc->SCSIIO.MSIxIndex =
+-              instance->reply_map[raw_smp_processor_id()];
++      if (instance->msix_load_balance)
++              cmd->request_desc->SCSIIO.MSIxIndex =
++                      (mega_mod64(atomic64_add_return(1, &instance->total_io_count),
++                                  instance->msix_vectors));
++      else
++              cmd->request_desc->SCSIIO.MSIxIndex =
++                      instance->reply_map[raw_smp_processor_id()];
+       if (!fp_possible) {
+               /* system pd firmware path */
+-- 
+2.40.1
+
diff --git a/queue-4.19/scsi-qla2xxx-add-protection-mask-module-parameters.patch b/queue-4.19/scsi-qla2xxx-add-protection-mask-module-parameters.patch
new file mode 100644 (file)
index 0000000..859db7b
--- /dev/null
@@ -0,0 +1,85 @@
+From e3c515b3a49c366558f2825541335093c9aeb991 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 21 Dec 2018 09:33:44 -0800
+Subject: scsi: qla2xxx: Add protection mask module parameters
+
+From: Martin K. Petersen <martin.petersen@oracle.com>
+
+[ Upstream commit 7855d2ba1172d716d96a628af7c5bafa5725ac57 ]
+
+Allow user to selectively enable/disable DIF/DIX protection
+capabilities mask.
+
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Himanshu Madhani <hmadhani@marvell.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Stable-dep-of: e9105c4b7a92 ("scsi: qla2xxx: Remove unsupported ql2xenabledif option")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/scsi/qla2xxx/qla_os.c | 36 +++++++++++++++++++++++++++--------
+ 1 file changed, 28 insertions(+), 8 deletions(-)
+
+diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
+index 4580774b2c3e7..27514d0abe845 100644
+--- a/drivers/scsi/qla2xxx/qla_os.c
++++ b/drivers/scsi/qla2xxx/qla_os.c
+@@ -277,6 +277,20 @@ MODULE_PARM_DESC(qla2xuseresexchforels,
+                "Reserve 1/2 of emergency exchanges for ELS.\n"
+                " 0 (default): disabled");
++int ql2xprotmask;
++module_param(ql2xprotmask, int, 0644);
++MODULE_PARM_DESC(ql2xprotmask,
++               "Override DIF/DIX protection capabilities mask\n"
++               "Default is 0 which sets protection mask based on "
++               "capabilities reported by HBA firmware.\n");
++
++int ql2xprotguard;
++module_param(ql2xprotguard, int, 0644);
++MODULE_PARM_DESC(ql2xprotguard, "Override choice of DIX checksum\n"
++               "  0 -- Let HBA firmware decide\n"
++               "  1 -- Force T10 CRC\n"
++               "  2 -- Force IP checksum\n");
++
+ /*
+  * SCSI host template entry points
+  */
+@@ -3293,13 +3307,16 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
+                           "Registering for DIF/DIX type 1 and 3 protection.\n");
+                       if (ql2xenabledif == 1)
+                               prot = SHOST_DIX_TYPE0_PROTECTION;
+-                      scsi_host_set_prot(host,
+-                          prot | SHOST_DIF_TYPE1_PROTECTION
+-                          | SHOST_DIF_TYPE2_PROTECTION
+-                          | SHOST_DIF_TYPE3_PROTECTION
+-                          | SHOST_DIX_TYPE1_PROTECTION
+-                          | SHOST_DIX_TYPE2_PROTECTION
+-                          | SHOST_DIX_TYPE3_PROTECTION);
++                      if (ql2xprotmask)
++                              scsi_host_set_prot(host, ql2xprotmask);
++                      else
++                              scsi_host_set_prot(host,
++                                  prot | SHOST_DIF_TYPE1_PROTECTION
++                                  | SHOST_DIF_TYPE2_PROTECTION
++                                  | SHOST_DIF_TYPE3_PROTECTION
++                                  | SHOST_DIX_TYPE1_PROTECTION
++                                  | SHOST_DIX_TYPE2_PROTECTION
++                                  | SHOST_DIX_TYPE3_PROTECTION);
+                       guard = SHOST_DIX_GUARD_CRC;
+@@ -3307,7 +3324,10 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
+                           (ql2xenabledif > 1 || IS_PI_DIFB_DIX0_CAPABLE(ha)))
+                               guard |= SHOST_DIX_GUARD_IP;
+-                      scsi_host_set_guard(host, guard);
++                      if (ql2xprotguard)
++                              scsi_host_set_guard(host, ql2xprotguard);
++                      else
++                              scsi_host_set_guard(host, guard);
+               } else
+                       base_vha->flags.difdix_supported = 0;
+       }
+-- 
+2.40.1
+
diff --git a/queue-4.19/scsi-qla2xxx-remove-unsupported-ql2xenabledif-option.patch b/queue-4.19/scsi-qla2xxx-remove-unsupported-ql2xenabledif-option.patch
new file mode 100644 (file)
index 0000000..c000990
--- /dev/null
@@ -0,0 +1,84 @@
+From a845e49035f5cbcc27f60c2c9d081049a0a90bfd Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 21 Aug 2023 18:30:42 +0530
+Subject: scsi: qla2xxx: Remove unsupported ql2xenabledif option
+
+From: Manish Rangankar <mrangankar@marvell.com>
+
+[ Upstream commit e9105c4b7a9208a21a9bda133707624f12ddabc2 ]
+
+User accidently passed module parameter ql2xenabledif=1 which is
+unsupported. However, driver still initialized which lead to guard tag
+errors during device discovery.
+
+Remove unsupported ql2xenabledif=1 option and validate the user input.
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Manish Rangankar <mrangankar@marvell.com>
+Signed-off-by: Nilesh Javali <njavali@marvell.com>
+Link: https://lore.kernel.org/r/20230821130045.34850-7-njavali@marvell.com
+Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/scsi/qla2xxx/qla_attr.c | 2 --
+ drivers/scsi/qla2xxx/qla_dbg.c  | 2 +-
+ drivers/scsi/qla2xxx/qla_os.c   | 9 +++++++--
+ 3 files changed, 8 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c
+index 6c9095d0aa0f4..9a25e92ef1abe 100644
+--- a/drivers/scsi/qla2xxx/qla_attr.c
++++ b/drivers/scsi/qla2xxx/qla_attr.c
+@@ -2088,8 +2088,6 @@ qla24xx_vport_create(struct fc_vport *fc_vport, bool disable)
+                       vha->flags.difdix_supported = 1;
+                       ql_dbg(ql_dbg_user, vha, 0x7082,
+                           "Registered for DIF/DIX type 1 and 3 protection.\n");
+-                      if (ql2xenabledif == 1)
+-                              prot = SHOST_DIX_TYPE0_PROTECTION;
+                       scsi_host_set_prot(vha->host,
+                           prot | SHOST_DIF_TYPE1_PROTECTION
+                           | SHOST_DIF_TYPE2_PROTECTION
+diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c
+index 36871760a5d37..fcbadd41856c2 100644
+--- a/drivers/scsi/qla2xxx/qla_dbg.c
++++ b/drivers/scsi/qla2xxx/qla_dbg.c
+@@ -22,7 +22,7 @@
+  * | Queue Command and IO tracing |       0x3074       | 0x300b         |
+  * |                              |                    | 0x3027-0x3028  |
+  * |                              |                    | 0x303d-0x3041  |
+- * |                              |                    | 0x302d,0x3033  |
++ * |                              |                    | 0x302e,0x3033  |
+  * |                              |                    | 0x3036,0x3038  |
+  * |                              |                    | 0x303a               |
+  * | DPC Thread                   |       0x4023       | 0x4002,0x4013  |
+diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
+index 27514d0abe845..36dca08166f29 100644
+--- a/drivers/scsi/qla2xxx/qla_os.c
++++ b/drivers/scsi/qla2xxx/qla_os.c
+@@ -3069,6 +3069,13 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
+       host->max_id = ha->max_fibre_devices;
+       host->cmd_per_lun = 3;
+       host->unique_id = host->host_no;
++
++      if (ql2xenabledif && ql2xenabledif != 2) {
++              ql_log(ql_log_warn, base_vha, 0x302d,
++                     "Invalid value for ql2xenabledif, resetting it to default (2)\n");
++              ql2xenabledif = 2;
++      }
++
+       if (IS_T10_PI_CAPABLE(ha) && ql2xenabledif)
+               host->max_cmd_len = 32;
+       else
+@@ -3305,8 +3312,6 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
+                       base_vha->flags.difdix_supported = 1;
+                       ql_dbg(ql_dbg_init, base_vha, 0x00f1,
+                           "Registering for DIF/DIX type 1 and 3 protection.\n");
+-                      if (ql2xenabledif == 1)
+-                              prot = SHOST_DIX_TYPE0_PROTECTION;
+                       if (ql2xprotmask)
+                               scsi_host_set_prot(host, ql2xprotmask);
+                       else
+-- 
+2.40.1
+
index f87bd80c5f7e0b6044fe30de78e1a34979c57364..3dd27adc8fa0e6c4e0014cbd59c554eca7f6bf76 100644 (file)
@@ -12,3 +12,20 @@ net-bridge-use-dev_stats_inc.patch
 team-fix-null-ptr-deref-when-team-device-type-is-cha.patch
 gpio-tb10x-fix-an-error-handling-path-in-tb10x_gpio_.patch
 i2c-mux-demux-pinctrl-check-the-return-value-of-devm.patch
+input-i8042-add-quirk-for-tuxedo-gemini-17-gen1-clev.patch
+scsi-qla2xxx-add-protection-mask-module-parameters.patch
+scsi-qla2xxx-remove-unsupported-ql2xenabledif-option.patch
+usb-typec-group-all-tcpci-tcpm-code-together.patch
+usb-typec-tcpm-refactor-tcpm_handle_vdm_request-payl.patch
+usb-typec-tcpm-refactor-tcpm_handle_vdm_request.patch
+usb-typec-bus-verify-partner-exists-in-typec_altmode.patch
+scsi-megaraid_sas-load-balance-completions-across-al.patch
+scsi-megaraid_sas-fix-deadlock-on-firmware-crashdump.patch
+ext4-remove-the-group-parameter-of-ext4_trim_extent.patch
+ext4-add-new-helper-interface-ext4_try_to_trim_range.patch
+ext4-scope-ret-locally-in-ext4_try_to_trim_range.patch
+ext4-change-s_last_trim_minblks-type-to-unsigned-lon.patch
+ext4-mark-group-as-trimmed-only-if-it-was-fully-scan.patch
+ext4-replace-the-traditional-ternary-conditional-ope.patch
+ext4-move-setting-of-trimmed-bit-into-ext4_try_to_tr.patch
+ext4-do-not-let-fstrim-block-system-suspend.patch
diff --git a/queue-4.19/usb-typec-bus-verify-partner-exists-in-typec_altmode.patch b/queue-4.19/usb-typec-bus-verify-partner-exists-in-typec_altmode.patch
new file mode 100644 (file)
index 0000000..37b2195
--- /dev/null
@@ -0,0 +1,93 @@
+From a73fdd2d1d0ccdd40a7832fc85a8a7d6239b688e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 14 Aug 2023 18:05:59 +0000
+Subject: usb: typec: bus: verify partner exists in typec_altmode_attention
+
+From: RD Babiera <rdbabiera@google.com>
+
+[ Upstream commit f23643306430f86e2f413ee2b986e0773e79da31 ]
+
+Some usb hubs will negotiate DisplayPort Alt mode with the device
+but will then negotiate a data role swap after entering the alt
+mode. The data role swap causes the device to unregister all alt
+modes, however the usb hub will still send Attention messages
+even after failing to reregister the Alt Mode. type_altmode_attention
+currently does not verify whether or not a device's altmode partner
+exists, which results in a NULL pointer error when dereferencing
+the typec_altmode and typec_altmode_ops belonging to the altmode
+partner.
+
+Verify the presence of a device's altmode partner before sending
+the Attention message to the Alt Mode driver.
+
+Fixes: 8a37d87d72f0 ("usb: typec: Bus type for alternate modes")
+Cc: stable@vger.kernel.org
+Signed-off-by: RD Babiera <rdbabiera@google.com>
+Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
+Reviewed-by: Guenter Roeck <linux@roeck-us.net>
+Link: https://lore.kernel.org/r/20230814180559.923475-1-rdbabiera@google.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/usb/typec/bus.c           | 12 ++++++++++--
+ drivers/usb/typec/tcpm/tcpm.c     |  3 ++-
+ include/linux/usb/typec_altmode.h |  2 +-
+ 3 files changed, 13 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/usb/typec/bus.c b/drivers/usb/typec/bus.c
+index 7605963f71ede..31188354bca04 100644
+--- a/drivers/usb/typec/bus.c
++++ b/drivers/usb/typec/bus.c
+@@ -146,12 +146,20 @@ EXPORT_SYMBOL_GPL(typec_altmode_exit);
+  *
+  * Notifies the partner of @adev about Attention command.
+  */
+-void typec_altmode_attention(struct typec_altmode *adev, u32 vdo)
++int typec_altmode_attention(struct typec_altmode *adev, u32 vdo)
+ {
+-      struct typec_altmode *pdev = &to_altmode(adev)->partner->adev;
++      struct altmode *partner = to_altmode(adev)->partner;
++      struct typec_altmode *pdev;
++
++      if (!partner)
++              return -ENODEV;
++
++      pdev = &partner->adev;
+       if (pdev->ops && pdev->ops->attention)
+               pdev->ops->attention(pdev, vdo);
++
++      return 0;
+ }
+ EXPORT_SYMBOL_GPL(typec_altmode_attention);
+diff --git a/drivers/usb/typec/tcpm/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c
+index 9cb781e6a0b53..c5132f2942f71 100644
+--- a/drivers/usb/typec/tcpm/tcpm.c
++++ b/drivers/usb/typec/tcpm/tcpm.c
+@@ -1258,7 +1258,8 @@ static void tcpm_handle_vdm_request(struct tcpm_port *port,
+                       }
+                       break;
+               case ADEV_ATTENTION:
+-                      typec_altmode_attention(adev, p[1]);
++                      if (typec_altmode_attention(adev, p[1]))
++                              tcpm_log(port, "typec_altmode_attention no port partner altmode");
+                       break;
+               }
+       }
+diff --git a/include/linux/usb/typec_altmode.h b/include/linux/usb/typec_altmode.h
+index 9a88c74a1d0d0..969b7c5040875 100644
+--- a/include/linux/usb/typec_altmode.h
++++ b/include/linux/usb/typec_altmode.h
+@@ -67,7 +67,7 @@ struct typec_altmode_ops {
+ int typec_altmode_enter(struct typec_altmode *altmode);
+ int typec_altmode_exit(struct typec_altmode *altmode);
+-void typec_altmode_attention(struct typec_altmode *altmode, u32 vdo);
++int typec_altmode_attention(struct typec_altmode *altmode, u32 vdo);
+ int typec_altmode_vdm(struct typec_altmode *altmode,
+                     const u32 header, const u32 *vdo, int count);
+ int typec_altmode_notify(struct typec_altmode *altmode, unsigned long conf,
+-- 
+2.40.1
+
diff --git a/queue-4.19/usb-typec-group-all-tcpci-tcpm-code-together.patch b/queue-4.19/usb-typec-group-all-tcpci-tcpm-code-together.patch
new file mode 100644 (file)
index 0000000..a027fd0
--- /dev/null
@@ -0,0 +1,259 @@
+From f2618e9c223c548dead24007d7ee7ab21531cab4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 20 Sep 2018 14:23:47 +0300
+Subject: usb: typec: Group all TCPCI/TCPM code together
+
+From: Heikki Krogerus <heikki.krogerus@linux.intel.com>
+
+[ Upstream commit ae8a2ca8a2215c7e31e6d874f7303801bb15fbbc ]
+
+Moving all the drivers that depend on the Port Controller
+Manager under a new directory drivers/usb/typec/tcpm/ and
+making Guenter Roeck the designated reviewer of that code.
+
+Acked-by: Guenter Roeck <linux@roeck-us.net>
+Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Stable-dep-of: f23643306430 ("usb: typec: bus: verify partner exists in typec_altmode_attention")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ MAINTAINERS                                   |  6 +++
+ drivers/usb/typec/Kconfig                     | 45 +---------------
+ drivers/usb/typec/Makefile                    |  6 +--
+ drivers/usb/typec/fusb302/Kconfig             |  7 ---
+ drivers/usb/typec/fusb302/Makefile            |  2 -
+ drivers/usb/typec/tcpm/Kconfig                | 52 +++++++++++++++++++
+ drivers/usb/typec/tcpm/Makefile               |  7 +++
+ drivers/usb/typec/{fusb302 => tcpm}/fusb302.c |  0
+ .../usb/typec/{fusb302 => tcpm}/fusb302_reg.h |  0
+ drivers/usb/typec/{ => tcpm}/tcpci.c          |  0
+ drivers/usb/typec/{ => tcpm}/tcpci.h          |  0
+ drivers/usb/typec/{ => tcpm}/tcpci_rt1711h.c  |  0
+ drivers/usb/typec/{ => tcpm}/tcpm.c           |  0
+ .../usb/typec/{typec_wcove.c => tcpm/wcove.c} |  0
+ 14 files changed, 67 insertions(+), 58 deletions(-)
+ delete mode 100644 drivers/usb/typec/fusb302/Kconfig
+ delete mode 100644 drivers/usb/typec/fusb302/Makefile
+ create mode 100644 drivers/usb/typec/tcpm/Kconfig
+ create mode 100644 drivers/usb/typec/tcpm/Makefile
+ rename drivers/usb/typec/{fusb302 => tcpm}/fusb302.c (100%)
+ rename drivers/usb/typec/{fusb302 => tcpm}/fusb302_reg.h (100%)
+ rename drivers/usb/typec/{ => tcpm}/tcpci.c (100%)
+ rename drivers/usb/typec/{ => tcpm}/tcpci.h (100%)
+ rename drivers/usb/typec/{ => tcpm}/tcpci_rt1711h.c (100%)
+ rename drivers/usb/typec/{ => tcpm}/tcpm.c (100%)
+ rename drivers/usb/typec/{typec_wcove.c => tcpm/wcove.c} (100%)
+
+diff --git a/MAINTAINERS b/MAINTAINERS
+index 59003315a9597..bf33725ca5157 100644
+--- a/MAINTAINERS
++++ b/MAINTAINERS
+@@ -15307,6 +15307,12 @@ F:    Documentation/driver-api/usb/typec_bus.rst
+ F:    drivers/usb/typec/altmodes/
+ F:    include/linux/usb/typec_altmode.h
++USB TYPEC PORT CONTROLLER DRIVERS
++M:    Guenter Roeck <linux@roeck-us.net>
++L:    linux-usb@vger.kernel.org
++S:    Maintained
++F:    drivers/usb/typec/tcpm/
++
+ USB UHCI DRIVER
+ M:    Alan Stern <stern@rowland.harvard.edu>
+ L:    linux-usb@vger.kernel.org
+diff --git a/drivers/usb/typec/Kconfig b/drivers/usb/typec/Kconfig
+index 8445890accdfe..e078f23e3f8d5 100644
+--- a/drivers/usb/typec/Kconfig
++++ b/drivers/usb/typec/Kconfig
+@@ -45,50 +45,7 @@ menuconfig TYPEC
+ if TYPEC
+-config TYPEC_TCPM
+-      tristate "USB Type-C Port Controller Manager"
+-      depends on USB
+-      select USB_ROLE_SWITCH
+-      select POWER_SUPPLY
+-      help
+-        The Type-C Port Controller Manager provides a USB PD and USB Type-C
+-        state machine for use with Type-C Port Controllers.
+-
+-if TYPEC_TCPM
+-
+-config TYPEC_TCPCI
+-      tristate "Type-C Port Controller Interface driver"
+-      depends on I2C
+-      select REGMAP_I2C
+-      help
+-        Type-C Port Controller driver for TCPCI-compliant controller.
+-
+-config TYPEC_RT1711H
+-      tristate "Richtek RT1711H Type-C chip driver"
+-      depends on I2C
+-      select TYPEC_TCPCI
+-      help
+-        Richtek RT1711H Type-C chip driver that works with
+-        Type-C Port Controller Manager to provide USB PD and USB
+-        Type-C functionalities.
+-
+-source "drivers/usb/typec/fusb302/Kconfig"
+-
+-config TYPEC_WCOVE
+-      tristate "Intel WhiskeyCove PMIC USB Type-C PHY driver"
+-      depends on ACPI
+-      depends on INTEL_SOC_PMIC
+-      depends on INTEL_PMC_IPC
+-      depends on BXT_WC_PMIC_OPREGION
+-      help
+-        This driver adds support for USB Type-C detection on Intel Broxton
+-        platforms that have Intel Whiskey Cove PMIC. The driver can detect the
+-        role and cable orientation.
+-
+-        To compile this driver as module, choose M here: the module will be
+-        called typec_wcove
+-
+-endif # TYPEC_TCPM
++source "drivers/usb/typec/tcpm/Kconfig"
+ source "drivers/usb/typec/ucsi/Kconfig"
+diff --git a/drivers/usb/typec/Makefile b/drivers/usb/typec/Makefile
+index 45b0aef428a82..6696b7263d61a 100644
+--- a/drivers/usb/typec/Makefile
++++ b/drivers/usb/typec/Makefile
+@@ -2,11 +2,7 @@
+ obj-$(CONFIG_TYPEC)           += typec.o
+ typec-y                               := class.o mux.o bus.o
+ obj-$(CONFIG_TYPEC)           += altmodes/
+-obj-$(CONFIG_TYPEC_TCPM)      += tcpm.o
+-obj-y                         += fusb302/
+-obj-$(CONFIG_TYPEC_WCOVE)     += typec_wcove.o
++obj-$(CONFIG_TYPEC_TCPM)      += tcpm/
+ obj-$(CONFIG_TYPEC_UCSI)      += ucsi/
+ obj-$(CONFIG_TYPEC_TPS6598X)  += tps6598x.o
+ obj-$(CONFIG_TYPEC)           += mux/
+-obj-$(CONFIG_TYPEC_TCPCI)     += tcpci.o
+-obj-$(CONFIG_TYPEC_RT1711H)   += tcpci_rt1711h.o
+diff --git a/drivers/usb/typec/fusb302/Kconfig b/drivers/usb/typec/fusb302/Kconfig
+deleted file mode 100644
+index fce099ff39fea..0000000000000
+--- a/drivers/usb/typec/fusb302/Kconfig
++++ /dev/null
+@@ -1,7 +0,0 @@
+-config TYPEC_FUSB302
+-      tristate "Fairchild FUSB302 Type-C chip driver"
+-      depends on I2C
+-      help
+-        The Fairchild FUSB302 Type-C chip driver that works with
+-        Type-C Port Controller Manager to provide USB PD and USB
+-        Type-C functionalities.
+diff --git a/drivers/usb/typec/fusb302/Makefile b/drivers/usb/typec/fusb302/Makefile
+deleted file mode 100644
+index 3b51b33631a08..0000000000000
+--- a/drivers/usb/typec/fusb302/Makefile
++++ /dev/null
+@@ -1,2 +0,0 @@
+-# SPDX-License-Identifier: GPL-2.0
+-obj-$(CONFIG_TYPEC_FUSB302)   += fusb302.o
+diff --git a/drivers/usb/typec/tcpm/Kconfig b/drivers/usb/typec/tcpm/Kconfig
+new file mode 100644
+index 0000000000000..f03ea8a617686
+--- /dev/null
++++ b/drivers/usb/typec/tcpm/Kconfig
+@@ -0,0 +1,52 @@
++config TYPEC_TCPM
++      tristate "USB Type-C Port Controller Manager"
++      depends on USB
++      select USB_ROLE_SWITCH
++      select POWER_SUPPLY
++      help
++        The Type-C Port Controller Manager provides a USB PD and USB Type-C
++        state machine for use with Type-C Port Controllers.
++
++if TYPEC_TCPM
++
++config TYPEC_TCPCI
++      tristate "Type-C Port Controller Interface driver"
++      depends on I2C
++      select REGMAP_I2C
++      help
++        Type-C Port Controller driver for TCPCI-compliant controller.
++
++if TYPEC_TCPCI
++
++config TYPEC_RT1711H
++      tristate "Richtek RT1711H Type-C chip driver"
++      help
++        Richtek RT1711H Type-C chip driver that works with
++        Type-C Port Controller Manager to provide USB PD and USB
++        Type-C functionalities.
++
++endif # TYPEC_TCPCI
++
++config TYPEC_FUSB302
++      tristate "Fairchild FUSB302 Type-C chip driver"
++      depends on I2C
++      help
++        The Fairchild FUSB302 Type-C chip driver that works with
++        Type-C Port Controller Manager to provide USB PD and USB
++        Type-C functionalities.
++
++config TYPEC_WCOVE
++      tristate "Intel WhiskeyCove PMIC USB Type-C PHY driver"
++      depends on ACPI
++      depends on INTEL_SOC_PMIC
++      depends on INTEL_PMC_IPC
++      depends on BXT_WC_PMIC_OPREGION
++      help
++        This driver adds support for USB Type-C on Intel Broxton platforms
++        that have Intel Whiskey Cove PMIC. The driver works with USB Type-C
++        Port Controller Manager to provide USB PD and Type-C functionalities.
++
++        To compile this driver as module, choose M here: the module will be
++        called typec_wcove.ko
++
++endif # TYPEC_TCPM
+diff --git a/drivers/usb/typec/tcpm/Makefile b/drivers/usb/typec/tcpm/Makefile
+new file mode 100644
+index 0000000000000..a5ff6c8eb8922
+--- /dev/null
++++ b/drivers/usb/typec/tcpm/Makefile
+@@ -0,0 +1,7 @@
++# SPDX-License-Identifier: GPL-2.0
++obj-$(CONFIG_TYPEC_TCPM)      += tcpm.o
++obj-$(CONFIG_TYPEC_FUSB302)   += fusb302.o
++obj-$(CONFIG_TYPEC_WCOVE)     += typec_wcove.o
++typec_wcove-y                 := wcove.o
++obj-$(CONFIG_TYPEC_TCPCI)     += tcpci.o
++obj-$(CONFIG_TYPEC_RT1711H)   += tcpci_rt1711h.o
+diff --git a/drivers/usb/typec/fusb302/fusb302.c b/drivers/usb/typec/tcpm/fusb302.c
+similarity index 100%
+rename from drivers/usb/typec/fusb302/fusb302.c
+rename to drivers/usb/typec/tcpm/fusb302.c
+diff --git a/drivers/usb/typec/fusb302/fusb302_reg.h b/drivers/usb/typec/tcpm/fusb302_reg.h
+similarity index 100%
+rename from drivers/usb/typec/fusb302/fusb302_reg.h
+rename to drivers/usb/typec/tcpm/fusb302_reg.h
+diff --git a/drivers/usb/typec/tcpci.c b/drivers/usb/typec/tcpm/tcpci.c
+similarity index 100%
+rename from drivers/usb/typec/tcpci.c
+rename to drivers/usb/typec/tcpm/tcpci.c
+diff --git a/drivers/usb/typec/tcpci.h b/drivers/usb/typec/tcpm/tcpci.h
+similarity index 100%
+rename from drivers/usb/typec/tcpci.h
+rename to drivers/usb/typec/tcpm/tcpci.h
+diff --git a/drivers/usb/typec/tcpci_rt1711h.c b/drivers/usb/typec/tcpm/tcpci_rt1711h.c
+similarity index 100%
+rename from drivers/usb/typec/tcpci_rt1711h.c
+rename to drivers/usb/typec/tcpm/tcpci_rt1711h.c
+diff --git a/drivers/usb/typec/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c
+similarity index 100%
+rename from drivers/usb/typec/tcpm.c
+rename to drivers/usb/typec/tcpm/tcpm.c
+diff --git a/drivers/usb/typec/typec_wcove.c b/drivers/usb/typec/tcpm/wcove.c
+similarity index 100%
+rename from drivers/usb/typec/typec_wcove.c
+rename to drivers/usb/typec/tcpm/wcove.c
+-- 
+2.40.1
+
diff --git a/queue-4.19/usb-typec-tcpm-refactor-tcpm_handle_vdm_request-payl.patch b/queue-4.19/usb-typec-tcpm-refactor-tcpm_handle_vdm_request-payl.patch
new file mode 100644 (file)
index 0000000..f2ad1a2
--- /dev/null
@@ -0,0 +1,186 @@
+From 85a3921f0d91a275cdd0ede4cf05bf66ce215388 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 24 Jul 2020 19:46:59 +0200
+Subject: usb: typec: tcpm: Refactor tcpm_handle_vdm_request payload handling
+
+From: Hans de Goede <hdegoede@redhat.com>
+
+[ Upstream commit 8afe9a3548f9d1805dcea6d97978f2179c8403a3 ]
+
+Refactor the tcpm_handle_vdm_request payload handling by doing the
+endianness conversion only once directly inside tcpm_handle_vdm_request
+itself instead of doing it multiple times inside various helper functions
+called by tcpm_handle_vdm_request.
+
+This is a preparation patch for some further refactoring to fix an AB BA
+lock inversion between the tcpm code and some altmode drivers.
+
+Reviewed-by: Guenter Roeck <linux@roeck-us.net>
+Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Link: https://lore.kernel.org/r/20200724174702.61754-3-hdegoede@redhat.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Stable-dep-of: f23643306430 ("usb: typec: bus: verify partner exists in typec_altmode_attention")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/usb/typec/tcpm/tcpm.c | 49 ++++++++++++++++-------------------
+ 1 file changed, 22 insertions(+), 27 deletions(-)
+
+diff --git a/drivers/usb/typec/tcpm/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c
+index 0fdae44c9b8cf..7487efbd8c2d3 100644
+--- a/drivers/usb/typec/tcpm/tcpm.c
++++ b/drivers/usb/typec/tcpm/tcpm.c
+@@ -957,16 +957,15 @@ static void tcpm_queue_vdm(struct tcpm_port *port, const u32 header,
+       port->vdm_state = VDM_STATE_READY;
+ }
+-static void svdm_consume_identity(struct tcpm_port *port, const __le32 *payload,
+-                                int cnt)
++static void svdm_consume_identity(struct tcpm_port *port, const u32 *p, int cnt)
+ {
+-      u32 vdo = le32_to_cpu(payload[VDO_INDEX_IDH]);
+-      u32 product = le32_to_cpu(payload[VDO_INDEX_PRODUCT]);
++      u32 vdo = p[VDO_INDEX_IDH];
++      u32 product = p[VDO_INDEX_PRODUCT];
+       memset(&port->mode_data, 0, sizeof(port->mode_data));
+       port->partner_ident.id_header = vdo;
+-      port->partner_ident.cert_stat = le32_to_cpu(payload[VDO_INDEX_CSTAT]);
++      port->partner_ident.cert_stat = p[VDO_INDEX_CSTAT];
+       port->partner_ident.product = product;
+       typec_partner_set_identity(port->partner);
+@@ -976,17 +975,15 @@ static void svdm_consume_identity(struct tcpm_port *port, const __le32 *payload,
+                PD_PRODUCT_PID(product), product & 0xffff);
+ }
+-static bool svdm_consume_svids(struct tcpm_port *port, const __le32 *payload,
+-                             int cnt)
++static bool svdm_consume_svids(struct tcpm_port *port, const u32 *p, int cnt)
+ {
+       struct pd_mode_data *pmdata = &port->mode_data;
+       int i;
+       for (i = 1; i < cnt; i++) {
+-              u32 p = le32_to_cpu(payload[i]);
+               u16 svid;
+-              svid = (p >> 16) & 0xffff;
++              svid = (p[i] >> 16) & 0xffff;
+               if (!svid)
+                       return false;
+@@ -996,7 +993,7 @@ static bool svdm_consume_svids(struct tcpm_port *port, const __le32 *payload,
+               pmdata->svids[pmdata->nsvids++] = svid;
+               tcpm_log(port, "SVID %d: 0x%x", pmdata->nsvids, svid);
+-              svid = p & 0xffff;
++              svid = p[i] & 0xffff;
+               if (!svid)
+                       return false;
+@@ -1026,8 +1023,7 @@ static bool svdm_consume_svids(struct tcpm_port *port, const __le32 *payload,
+       return false;
+ }
+-static void svdm_consume_modes(struct tcpm_port *port, const __le32 *payload,
+-                             int cnt)
++static void svdm_consume_modes(struct tcpm_port *port, const u32 *p, int cnt)
+ {
+       struct pd_mode_data *pmdata = &port->mode_data;
+       struct typec_altmode_desc *paltmode;
+@@ -1044,7 +1040,7 @@ static void svdm_consume_modes(struct tcpm_port *port, const __le32 *payload,
+               paltmode->svid = pmdata->svids[pmdata->svid_index];
+               paltmode->mode = i;
+-              paltmode->vdo = le32_to_cpu(payload[i]);
++              paltmode->vdo = p[i];
+               tcpm_log(port, " Alternate mode %d: SVID 0x%04x, VDO %d: 0x%08x",
+                        pmdata->altmodes, paltmode->svid,
+@@ -1072,21 +1068,17 @@ static void tcpm_register_partner_altmodes(struct tcpm_port *port)
+ #define supports_modal(port)  PD_IDH_MODAL_SUPP((port)->partner_ident.id_header)
+-static int tcpm_pd_svdm(struct tcpm_port *port, const __le32 *payload, int cnt,
++static int tcpm_pd_svdm(struct tcpm_port *port, const u32 *p, int cnt,
+                       u32 *response)
+ {
+       struct typec_altmode *adev;
+       struct typec_altmode *pdev;
+       struct pd_mode_data *modep;
+-      u32 p[PD_MAX_PAYLOAD];
+       int rlen = 0;
+       int cmd_type;
+       int cmd;
+       int i;
+-      for (i = 0; i < cnt; i++)
+-              p[i] = le32_to_cpu(payload[i]);
+-
+       cmd_type = PD_VDO_CMDT(p[0]);
+       cmd = PD_VDO_CMD(p[0]);
+@@ -1147,13 +1139,13 @@ static int tcpm_pd_svdm(struct tcpm_port *port, const __le32 *payload, int cnt,
+               switch (cmd) {
+               case CMD_DISCOVER_IDENT:
+                       /* 6.4.4.3.1 */
+-                      svdm_consume_identity(port, payload, cnt);
++                      svdm_consume_identity(port, p, cnt);
+                       response[0] = VDO(USB_SID_PD, 1, CMD_DISCOVER_SVID);
+                       rlen = 1;
+                       break;
+               case CMD_DISCOVER_SVID:
+                       /* 6.4.4.3.2 */
+-                      if (svdm_consume_svids(port, payload, cnt)) {
++                      if (svdm_consume_svids(port, p, cnt)) {
+                               response[0] = VDO(USB_SID_PD, 1,
+                                                 CMD_DISCOVER_SVID);
+                               rlen = 1;
+@@ -1165,7 +1157,7 @@ static int tcpm_pd_svdm(struct tcpm_port *port, const __le32 *payload, int cnt,
+                       break;
+               case CMD_DISCOVER_MODES:
+                       /* 6.4.4.3.3 */
+-                      svdm_consume_modes(port, payload, cnt);
++                      svdm_consume_modes(port, p, cnt);
+                       modep->svid_index++;
+                       if (modep->svid_index < modep->nsvids) {
+                               u16 svid = modep->svids[modep->svid_index];
+@@ -1228,15 +1220,18 @@ static int tcpm_pd_svdm(struct tcpm_port *port, const __le32 *payload, int cnt,
+ static void tcpm_handle_vdm_request(struct tcpm_port *port,
+                                   const __le32 *payload, int cnt)
+ {
+-      int rlen = 0;
++      u32 p[PD_MAX_PAYLOAD];
+       u32 response[8] = { };
+-      u32 p0 = le32_to_cpu(payload[0]);
++      int i, rlen = 0;
++
++      for (i = 0; i < cnt; i++)
++              p[i] = le32_to_cpu(payload[i]);
+       if (port->vdm_state == VDM_STATE_BUSY) {
+               /* If UFP responded busy retry after timeout */
+-              if (PD_VDO_CMDT(p0) == CMDT_RSP_BUSY) {
++              if (PD_VDO_CMDT(p[0]) == CMDT_RSP_BUSY) {
+                       port->vdm_state = VDM_STATE_WAIT_RSP_BUSY;
+-                      port->vdo_retry = (p0 & ~VDO_CMDT_MASK) |
++                      port->vdo_retry = (p[0] & ~VDO_CMDT_MASK) |
+                               CMDT_INIT;
+                       mod_delayed_work(port->wq, &port->vdm_state_machine,
+                                        msecs_to_jiffies(PD_T_VDM_BUSY));
+@@ -1245,8 +1240,8 @@ static void tcpm_handle_vdm_request(struct tcpm_port *port,
+               port->vdm_state = VDM_STATE_DONE;
+       }
+-      if (PD_VDO_SVDM(p0))
+-              rlen = tcpm_pd_svdm(port, payload, cnt, response);
++      if (PD_VDO_SVDM(p[0]))
++              rlen = tcpm_pd_svdm(port, p, cnt, response);
+       if (rlen > 0) {
+               tcpm_queue_vdm(port, response[0], &response[1], rlen - 1);
+-- 
+2.40.1
+
diff --git a/queue-4.19/usb-typec-tcpm-refactor-tcpm_handle_vdm_request.patch b/queue-4.19/usb-typec-tcpm-refactor-tcpm_handle_vdm_request.patch
new file mode 100644 (file)
index 0000000..9486df7
--- /dev/null
@@ -0,0 +1,187 @@
+From f466ff43d249d583e28dbece37f4110f9c1f8239 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 24 Jul 2020 19:47:00 +0200
+Subject: usb: typec: tcpm: Refactor tcpm_handle_vdm_request
+
+From: Hans de Goede <hdegoede@redhat.com>
+
+[ Upstream commit 95b4d51c96a87cd760c2a4f27fb28a59a27b6368 ]
+
+Refactor tcpm_handle_vdm_request and its tcpm_pd_svdm helper function so
+that reporting the results of the vdm to the altmode-driver is separated
+out into a clear separate step inside tcpm_handle_vdm_request, instead
+of being scattered over various places inside the tcpm_pd_svdm helper.
+
+This is a preparation patch for fixing an AB BA lock inversion between the
+tcpm code and some altmode drivers.
+
+Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
+Reviewed-by: Guenter Roeck <linux@roeck-us.net>
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Link: https://lore.kernel.org/r/20200724174702.61754-4-hdegoede@redhat.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Stable-dep-of: f23643306430 ("usb: typec: bus: verify partner exists in typec_altmode_attention")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/usb/typec/tcpm/tcpm.c | 76 ++++++++++++++++++++++-------------
+ 1 file changed, 48 insertions(+), 28 deletions(-)
+
+diff --git a/drivers/usb/typec/tcpm/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c
+index 7487efbd8c2d3..9cb781e6a0b53 100644
+--- a/drivers/usb/typec/tcpm/tcpm.c
++++ b/drivers/usb/typec/tcpm/tcpm.c
+@@ -158,6 +158,14 @@ enum pd_msg_request {
+       PD_MSG_DATA_SOURCE_CAP,
+ };
++enum adev_actions {
++      ADEV_NONE = 0,
++      ADEV_NOTIFY_USB_AND_QUEUE_VDM,
++      ADEV_QUEUE_VDM,
++      ADEV_QUEUE_VDM_SEND_EXIT_MODE_ON_FAIL,
++      ADEV_ATTENTION,
++};
++
+ /* Events from low level driver */
+ #define TCPM_CC_EVENT         BIT(0)
+@@ -1068,10 +1076,10 @@ static void tcpm_register_partner_altmodes(struct tcpm_port *port)
+ #define supports_modal(port)  PD_IDH_MODAL_SUPP((port)->partner_ident.id_header)
+-static int tcpm_pd_svdm(struct tcpm_port *port, const u32 *p, int cnt,
+-                      u32 *response)
++static int tcpm_pd_svdm(struct tcpm_port *port, struct typec_altmode *adev,
++                      const u32 *p, int cnt, u32 *response,
++                      enum adev_actions *adev_action)
+ {
+-      struct typec_altmode *adev;
+       struct typec_altmode *pdev;
+       struct pd_mode_data *modep;
+       int rlen = 0;
+@@ -1087,9 +1095,6 @@ static int tcpm_pd_svdm(struct tcpm_port *port, const u32 *p, int cnt,
+       modep = &port->mode_data;
+-      adev = typec_match_altmode(port->port_altmode, ALTMODE_DISCOVERY_MAX,
+-                                 PD_VDO_VID(p[0]), PD_VDO_OPOS(p[0]));
+-
+       pdev = typec_match_altmode(port->partner_altmode, ALTMODE_DISCOVERY_MAX,
+                                  PD_VDO_VID(p[0]), PD_VDO_OPOS(p[0]));
+@@ -1115,8 +1120,7 @@ static int tcpm_pd_svdm(struct tcpm_port *port, const u32 *p, int cnt,
+                       break;
+               case CMD_ATTENTION:
+                       /* Attention command does not have response */
+-                      if (adev)
+-                              typec_altmode_attention(adev, p[1]);
++                      *adev_action = ADEV_ATTENTION;
+                       return 0;
+               default:
+                       break;
+@@ -1170,23 +1174,15 @@ static int tcpm_pd_svdm(struct tcpm_port *port, const u32 *p, int cnt,
+               case CMD_ENTER_MODE:
+                       if (adev && pdev) {
+                               typec_altmode_update_active(pdev, true);
+-
+-                              if (typec_altmode_vdm(adev, p[0], &p[1], cnt)) {
+-                                      response[0] = VDO(adev->svid, 1,
+-                                                        CMD_EXIT_MODE);
+-                                      response[0] |= VDO_OPOS(adev->mode);
+-                                      return 1;
+-                              }
++                              *adev_action = ADEV_QUEUE_VDM_SEND_EXIT_MODE_ON_FAIL;
+                       }
+                       return 0;
+               case CMD_EXIT_MODE:
+                       if (adev && pdev) {
+                               typec_altmode_update_active(pdev, false);
+-
+                               /* Back to USB Operation */
+-                              WARN_ON(typec_altmode_notify(adev,
+-                                                           TYPEC_STATE_USB,
+-                                                           NULL));
++                              *adev_action = ADEV_NOTIFY_USB_AND_QUEUE_VDM;
++                              return 0;
+                       }
+                       break;
+               default:
+@@ -1197,11 +1193,8 @@ static int tcpm_pd_svdm(struct tcpm_port *port, const u32 *p, int cnt,
+               switch (cmd) {
+               case CMD_ENTER_MODE:
+                       /* Back to USB Operation */
+-                      if (adev)
+-                              WARN_ON(typec_altmode_notify(adev,
+-                                                           TYPEC_STATE_USB,
+-                                                           NULL));
+-                      break;
++                      *adev_action = ADEV_NOTIFY_USB_AND_QUEUE_VDM;
++                      return 0;
+               default:
+                       break;
+               }
+@@ -1211,15 +1204,15 @@ static int tcpm_pd_svdm(struct tcpm_port *port, const u32 *p, int cnt,
+       }
+       /* Informing the alternate mode drivers about everything */
+-      if (adev)
+-              typec_altmode_vdm(adev, p[0], &p[1], cnt);
+-
++      *adev_action = ADEV_QUEUE_VDM;
+       return rlen;
+ }
+ static void tcpm_handle_vdm_request(struct tcpm_port *port,
+                                   const __le32 *payload, int cnt)
+ {
++      enum adev_actions adev_action = ADEV_NONE;
++      struct typec_altmode *adev;
+       u32 p[PD_MAX_PAYLOAD];
+       u32 response[8] = { };
+       int i, rlen = 0;
+@@ -1227,6 +1220,9 @@ static void tcpm_handle_vdm_request(struct tcpm_port *port,
+       for (i = 0; i < cnt; i++)
+               p[i] = le32_to_cpu(payload[i]);
++      adev = typec_match_altmode(port->port_altmode, ALTMODE_DISCOVERY_MAX,
++                                 PD_VDO_VID(p[0]), PD_VDO_OPOS(p[0]));
++
+       if (port->vdm_state == VDM_STATE_BUSY) {
+               /* If UFP responded busy retry after timeout */
+               if (PD_VDO_CMDT(p[0]) == CMDT_RSP_BUSY) {
+@@ -1241,7 +1237,31 @@ static void tcpm_handle_vdm_request(struct tcpm_port *port,
+       }
+       if (PD_VDO_SVDM(p[0]))
+-              rlen = tcpm_pd_svdm(port, p, cnt, response);
++              rlen = tcpm_pd_svdm(port, adev, p, cnt, response, &adev_action);
++
++      if (adev) {
++              switch (adev_action) {
++              case ADEV_NONE:
++                      break;
++              case ADEV_NOTIFY_USB_AND_QUEUE_VDM:
++                      WARN_ON(typec_altmode_notify(adev, TYPEC_STATE_USB, NULL));
++                      typec_altmode_vdm(adev, p[0], &p[1], cnt);
++                      break;
++              case ADEV_QUEUE_VDM:
++                      typec_altmode_vdm(adev, p[0], &p[1], cnt);
++                      break;
++              case ADEV_QUEUE_VDM_SEND_EXIT_MODE_ON_FAIL:
++                      if (typec_altmode_vdm(adev, p[0], &p[1], cnt)) {
++                              response[0] = VDO(adev->svid, 1, CMD_EXIT_MODE);
++                              response[0] |= VDO_OPOS(adev->mode);
++                              rlen = 1;
++                      }
++                      break;
++              case ADEV_ATTENTION:
++                      typec_altmode_attention(adev, p[1]);
++                      break;
++              }
++      }
+       if (rlen > 0) {
+               tcpm_queue_vdm(port, response[0], &response[1], rlen - 1);
+-- 
+2.40.1
+