From 3d795cf3f7b2232c601dc5e864190d2a1a382829 Mon Sep 17 00:00:00 2001 From: Sasha Levin Date: Fri, 28 Jul 2023 10:38:02 -0400 Subject: [PATCH] Fixes for 5.15 Signed-off-by: Sasha Levin --- ...between-quota-disable-and-relocation.patch | 97 +++++ ...-close-is-disabled-then-close-files-.patch | 41 +++ ...issing-directory-in-maintainers-file.patch | 36 ++ .../cifs-use-fs_context-for-automounts.patch | 168 +++++++++ .../dlm-cleanup-plock_op-vs-plock_xop.patch | 233 ++++++++++++ ...dlm-rearrange-async-condition-return.patch | 67 ++++ .../drm-amdgpu-fix-vkms-crtc-settings.patch | 168 +++++++++ ...relax-timer-deactivation-by-hrtimer_.patch | 106 ++++++ ...-t-leak-a-resource-on-eviction-error.patch | 72 ++++ ...int-error-message-if-eviction-was-in.patch | 42 +++ ...onsider-pinned-bos-for-eviction-swap.patch | 46 +++ ...-posix-locks-only-when-process-is-ki.patch | 44 +++ .../gpio-mvebu-fix-irq-domain-leak.patch | 77 ++++ ...o-mvebu-make-use-of-devm_pwmchip_add.patch | 61 ++++ ...ke-tps68470_gpio_output-always-set-t.patch | 50 +++ ...-messages-for-failed-memory-allocati.patch | 81 +++++ .../i2c-improve-size-determinations.patch | 54 +++ ...ve-a-useless-call-in-the-remove-func.patch | 49 +++ ...omadik-remove-unnecessary-goto-label.patch | 85 +++++ ...i2c-nomadik-use-devm_clk_get_enabled.patch | 76 ++++ ...udit-the-capability-check-in-io_urin.patch | 47 +++ ...when-checking-checkpoint-buffer-busy.patch | 150 ++++++++ ...-judgement-for-buffer-head-removing-.patch | 106 ++++++ ...bd2-remove-journal_clean_one_cp_list.patch | 235 ++++++++++++ .../jbd2-remove-t_checkpoint_io_list.patch | 146 ++++++++ .../ksmbd-remove-internal.h-include.patch | 66 ++++ ...-pv-fix-index-value-of-replaced-asce.patch | 46 +++ ...ename-tail-to-old_tail-in-n_tty_read.patch | 60 ++++ .../pci-aspm-avoid-link-retraining-race.patch | 64 ++++ ...spm-factor-out-pcie_wait_for_retrain.patch | 79 ++++ ...0-or-etimedout-from-pcie_retrain_lin.patch | 72 ++++ ...-t-advertise-msi-x-in-pcie-capabilit.patch | 103 ++++++ ...-window-mapping-and-address-translat.patch | 340 ++++++++++++++++++ ...ip-remove-writes-to-unused-registers.patch | 55 +++ ...ndling-of-period-duty-if-greater-tha.patch | 85 +++++ ...lify-duplicated-per-channel-tracking.patch | 77 ++++ ...dd-fault-name-injection-to-kernel-pr.patch | 135 +++++++ ...-debug-prints-in-the-device-remove-p.patch | 54 +++ ...-qla2xxx-fix-hang-in-task-management.patch | 195 ++++++++++ ...-task-management-cmd-fail-due-to-una.patch | 155 ++++++++ ...2xxx-fix-task-management-cmd-failure.patch | 325 +++++++++++++++++ ...si-qla2xxx-multi-que-support-for-tmf.patch | 200 +++++++++++ ...move-unused-declarations-for-qla2xxx.patch | 109 ++++++ queue-5.15/series | 48 +++ ...nthetic-events-to-pass-around-stackt.patch | 282 +++++++++++++++ ...s-add-symstr-type-for-dynamic-events.patch | 313 ++++++++++++++++ ...ix-to-avoid-double-count-of-the-stri.patch | 49 +++ ...ix-to-record-0-length-data_loc-in-fe.patch | 109 ++++++ ...-hang-on-tty-device-with-no_room-set.patch | 116 ++++++ 49 files changed, 5474 insertions(+) create mode 100644 queue-5.15/btrfs-fix-race-between-quota-disable-and-relocation.patch create mode 100644 queue-5.15/cifs-if-deferred-close-is-disabled-then-close-files-.patch create mode 100644 queue-5.15/cifs-missing-directory-in-maintainers-file.patch create mode 100644 queue-5.15/cifs-use-fs_context-for-automounts.patch create mode 100644 queue-5.15/dlm-cleanup-plock_op-vs-plock_xop.patch create mode 100644 queue-5.15/dlm-rearrange-async-condition-return.patch create mode 100644 queue-5.15/drm-amdgpu-fix-vkms-crtc-settings.patch create mode 100644 queue-5.15/drm-amdgpu-vkms-relax-timer-deactivation-by-hrtimer_.patch create mode 100644 queue-5.15/drm-ttm-don-t-leak-a-resource-on-eviction-error.patch create mode 100644 queue-5.15/drm-ttm-don-t-print-error-message-if-eviction-was-in.patch create mode 100644 queue-5.15/drm-ttm-never-consider-pinned-bos-for-eviction-swap.patch create mode 100644 queue-5.15/fs-dlm-interrupt-posix-locks-only-when-process-is-ki.patch create mode 100644 queue-5.15/gpio-mvebu-fix-irq-domain-leak.patch create mode 100644 queue-5.15/gpio-mvebu-make-use-of-devm_pwmchip_add.patch create mode 100644 queue-5.15/gpio-tps68470-make-tps68470_gpio_output-always-set-t.patch create mode 100644 queue-5.15/i2c-delete-error-messages-for-failed-memory-allocati.patch create mode 100644 queue-5.15/i2c-improve-size-determinations.patch create mode 100644 queue-5.15/i2c-nomadik-remove-a-useless-call-in-the-remove-func.patch create mode 100644 queue-5.15/i2c-nomadik-remove-unnecessary-goto-label.patch create mode 100644 queue-5.15/i2c-nomadik-use-devm_clk_get_enabled.patch create mode 100644 queue-5.15/io_uring-don-t-audit-the-capability-check-in-io_urin.patch create mode 100644 queue-5.15/jbd2-fix-a-race-when-checking-checkpoint-buffer-busy.patch create mode 100644 queue-5.15/jbd2-fix-wrongly-judgement-for-buffer-head-removing-.patch create mode 100644 queue-5.15/jbd2-remove-journal_clean_one_cp_list.patch create mode 100644 queue-5.15/jbd2-remove-t_checkpoint_io_list.patch create mode 100644 queue-5.15/ksmbd-remove-internal.h-include.patch create mode 100644 queue-5.15/kvm-s390-pv-fix-index-value-of-replaced-asce.patch create mode 100644 queue-5.15/n_tty-rename-tail-to-old_tail-in-n_tty_read.patch create mode 100644 queue-5.15/pci-aspm-avoid-link-retraining-race.patch create mode 100644 queue-5.15/pci-aspm-factor-out-pcie_wait_for_retrain.patch create mode 100644 queue-5.15/pci-aspm-return-0-or-etimedout-from-pcie_retrain_lin.patch create mode 100644 queue-5.15/pci-rockchip-don-t-advertise-msi-x-in-pcie-capabilit.patch create mode 100644 queue-5.15/pci-rockchip-fix-window-mapping-and-address-translat.patch create mode 100644 queue-5.15/pci-rockchip-remove-writes-to-unused-registers.patch create mode 100644 queue-5.15/pwm-meson-fix-handling-of-period-duty-if-greater-tha.patch create mode 100644 queue-5.15/pwm-meson-simplify-duplicated-per-channel-tracking.patch create mode 100644 queue-5.15/revert-tracing-add-fault-name-injection-to-kernel-pr.patch create mode 100644 queue-5.15/scsi-qla2xxx-add-debug-prints-in-the-device-remove-p.patch create mode 100644 queue-5.15/scsi-qla2xxx-fix-hang-in-task-management.patch create mode 100644 queue-5.15/scsi-qla2xxx-fix-task-management-cmd-fail-due-to-una.patch create mode 100644 queue-5.15/scsi-qla2xxx-fix-task-management-cmd-failure.patch create mode 100644 queue-5.15/scsi-qla2xxx-multi-que-support-for-tmf.patch create mode 100644 queue-5.15/scsi-qla2xxx-remove-unused-declarations-for-qla2xxx.patch create mode 100644 queue-5.15/tracing-allow-synthetic-events-to-pass-around-stackt.patch create mode 100644 queue-5.15/tracing-probes-add-symstr-type-for-dynamic-events.patch create mode 100644 queue-5.15/tracing-probes-fix-to-avoid-double-count-of-the-stri.patch create mode 100644 queue-5.15/tracing-probes-fix-to-record-0-length-data_loc-in-fe.patch create mode 100644 queue-5.15/tty-fix-hang-on-tty-device-with-no_room-set.patch diff --git a/queue-5.15/btrfs-fix-race-between-quota-disable-and-relocation.patch b/queue-5.15/btrfs-fix-race-between-quota-disable-and-relocation.patch new file mode 100644 index 00000000000..2ab859eb027 --- /dev/null +++ b/queue-5.15/btrfs-fix-race-between-quota-disable-and-relocation.patch @@ -0,0 +1,97 @@ +From ee59420526d47ee7ea747caa98d04afdebeb2fc7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 19 Jun 2023 17:21:50 +0100 +Subject: btrfs: fix race between quota disable and relocation + +From: Filipe Manana + +[ Upstream commit 8a4a0b2a3eaf75ca8854f856ef29690c12b2f531 ] + +If we disable quotas while we have a relocation of a metadata block group +that has extents belonging to the quota root, we can cause the relocation +to fail with -ENOENT. This is because relocation builds backref nodes for +extents of the quota root and later needs to walk the backrefs and access +the quota root - however if in between a task disables quotas, it results +in deleting the quota root from the root tree (with btrfs_del_root(), +called from btrfs_quota_disable(). + +This can be sporadically triggered by test case btrfs/255 from fstests: + + $ ./check btrfs/255 + FSTYP -- btrfs + PLATFORM -- Linux/x86_64 debian0 6.4.0-rc6-btrfs-next-134+ #1 SMP PREEMPT_DYNAMIC Thu Jun 15 11:59:28 WEST 2023 + MKFS_OPTIONS -- /dev/sdc + MOUNT_OPTIONS -- /dev/sdc /home/fdmanana/btrfs-tests/scratch_1 + + btrfs/255 6s ... _check_dmesg: something found in dmesg (see /home/fdmanana/git/hub/xfstests/results//btrfs/255.dmesg) + - output mismatch (see /home/fdmanana/git/hub/xfstests/results//btrfs/255.out.bad) + --- tests/btrfs/255.out 2023-03-02 21:47:53.876609426 +0000 + +++ /home/fdmanana/git/hub/xfstests/results//btrfs/255.out.bad 2023-06-16 10:20:39.267563212 +0100 + @@ -1,2 +1,4 @@ + QA output created by 255 + +ERROR: error during balancing '/home/fdmanana/btrfs-tests/scratch_1': No such file or directory + +There may be more info in syslog - try dmesg | tail + Silence is golden + ... + (Run 'diff -u /home/fdmanana/git/hub/xfstests/tests/btrfs/255.out /home/fdmanana/git/hub/xfstests/results//btrfs/255.out.bad' to see the entire diff) + Ran: btrfs/255 + Failures: btrfs/255 + Failed 1 of 1 tests + +To fix this make the quota disable operation take the cleaner mutex, as +relocation of a block group also takes this mutex. This is also what we +do when deleting a subvolume/snapshot, we take the cleaner mutex in the +cleaner kthread (at cleaner_kthread()) and then we call btrfs_del_root() +at btrfs_drop_snapshot() while under the protection of the cleaner mutex. + +Fixes: bed92eae26cc ("Btrfs: qgroup implementation and prototypes") +CC: stable@vger.kernel.org # 5.4+ +Signed-off-by: Filipe Manana +Signed-off-by: David Sterba +Signed-off-by: Sasha Levin +--- + fs/btrfs/qgroup.c | 18 +++++++++++++++--- + 1 file changed, 15 insertions(+), 3 deletions(-) + +diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c +index d408d1dfde7c8..d46a070275ff5 100644 +--- a/fs/btrfs/qgroup.c ++++ b/fs/btrfs/qgroup.c +@@ -1201,12 +1201,23 @@ int btrfs_quota_disable(struct btrfs_fs_info *fs_info) + int ret = 0; + + /* +- * We need to have subvol_sem write locked, to prevent races between +- * concurrent tasks trying to disable quotas, because we will unlock +- * and relock qgroup_ioctl_lock across BTRFS_FS_QUOTA_ENABLED changes. ++ * We need to have subvol_sem write locked to prevent races with ++ * snapshot creation. + */ + lockdep_assert_held_write(&fs_info->subvol_sem); + ++ /* ++ * Lock the cleaner mutex to prevent races with concurrent relocation, ++ * because relocation may be building backrefs for blocks of the quota ++ * root while we are deleting the root. This is like dropping fs roots ++ * of deleted snapshots/subvolumes, we need the same protection. ++ * ++ * This also prevents races between concurrent tasks trying to disable ++ * quotas, because we will unlock and relock qgroup_ioctl_lock across ++ * BTRFS_FS_QUOTA_ENABLED changes. ++ */ ++ mutex_lock(&fs_info->cleaner_mutex); ++ + mutex_lock(&fs_info->qgroup_ioctl_lock); + if (!fs_info->quota_root) + goto out; +@@ -1287,6 +1298,7 @@ int btrfs_quota_disable(struct btrfs_fs_info *fs_info) + btrfs_end_transaction(trans); + else if (trans) + ret = btrfs_end_transaction(trans); ++ mutex_unlock(&fs_info->cleaner_mutex); + + return ret; + } +-- +2.39.2 + diff --git a/queue-5.15/cifs-if-deferred-close-is-disabled-then-close-files-.patch b/queue-5.15/cifs-if-deferred-close-is-disabled-then-close-files-.patch new file mode 100644 index 00000000000..7c8ba365e26 --- /dev/null +++ b/queue-5.15/cifs-if-deferred-close-is-disabled-then-close-files-.patch @@ -0,0 +1,41 @@ +From 4f410636bcafe6febb64257cd99651160e10504a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 7 Jul 2023 15:29:01 +0000 +Subject: cifs: if deferred close is disabled then close files immediately + +From: Bharath SM + +[ Upstream commit df9d70c18616760c6504b97fec66b6379c172dbb ] + +If defer close timeout value is set to 0, then there is no +need to include files in the deferred close list and utilize +the delayed worker for closing. Instead, we can close them +immediately. + +Signed-off-by: Bharath SM +Reviewed-by: Shyam Prasad N +Cc: stable@vger.kernel.org +Signed-off-by: Steve French +Signed-off-by: Sasha Levin +--- + fs/cifs/file.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/fs/cifs/file.c b/fs/cifs/file.c +index 4e4f73a90574b..e65fbae9e804b 100644 +--- a/fs/cifs/file.c ++++ b/fs/cifs/file.c +@@ -880,8 +880,8 @@ int cifs_close(struct inode *inode, struct file *file) + cfile = file->private_data; + file->private_data = NULL; + dclose = kmalloc(sizeof(struct cifs_deferred_close), GFP_KERNEL); +- if ((cinode->oplock == CIFS_CACHE_RHW_FLG) && +- cinode->lease_granted && ++ if ((cifs_sb->ctx->closetimeo && cinode->oplock == CIFS_CACHE_RHW_FLG) ++ && cinode->lease_granted && + !test_bit(CIFS_INO_CLOSE_ON_LOCK, &cinode->flags) && + dclose) { + if (test_and_clear_bit(CIFS_INO_MODIFIED_ATTR, &cinode->flags)) { +-- +2.39.2 + diff --git a/queue-5.15/cifs-missing-directory-in-maintainers-file.patch b/queue-5.15/cifs-missing-directory-in-maintainers-file.patch new file mode 100644 index 00000000000..19b59935691 --- /dev/null +++ b/queue-5.15/cifs-missing-directory-in-maintainers-file.patch @@ -0,0 +1,36 @@ +From 3113e3cbb7f24f98ee9c32672187cddbc3f24d1b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 13 Aug 2022 17:22:11 -0500 +Subject: cifs: missing directory in MAINTAINERS file + +From: Steve French + +[ Upstream commit 5dd8ce24667a70bb9f7808f5eec0354bd37290c6 ] + +The include/uapi/linux/cifs directory (not just fs/cifs and +fs/smbfs_common) should be included in cifs entry in the +MAINTAINERS file. + +Reviewed-by: Paulo Alcantara (SUSE) +Signed-off-by: Steve French +Stable-dep-of: df9d70c18616 ("cifs: if deferred close is disabled then close files immediately") +Signed-off-by: Sasha Levin +--- + MAINTAINERS | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/MAINTAINERS b/MAINTAINERS +index 2bf1ad0fb2a6f..e6b53e76651be 100644 +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -4666,6 +4666,7 @@ T: git git://git.samba.org/sfrench/cifs-2.6.git + F: Documentation/admin-guide/cifs/ + F: fs/cifs/ + F: fs/smbfs_common/ ++F: include/uapi/linux/cifs + + COMPACTPCI HOTPLUG CORE + M: Scott Murray +-- +2.39.2 + diff --git a/queue-5.15/cifs-use-fs_context-for-automounts.patch b/queue-5.15/cifs-use-fs_context-for-automounts.patch new file mode 100644 index 00000000000..34e060c1125 --- /dev/null +++ b/queue-5.15/cifs-use-fs_context-for-automounts.patch @@ -0,0 +1,168 @@ +From 6e997dc19578b44af9b5e3aea9152e7f5812e359 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 4 Oct 2022 18:41:20 -0300 +Subject: cifs: use fs_context for automounts + +From: Paulo Alcantara + +[ Upstream commit 9fd29a5bae6e8f94b410374099a6fddb253d2d5f ] + +Use filesystem context support to handle dfs links. + +Signed-off-by: Paulo Alcantara (SUSE) +Signed-off-by: Steve French +Stable-dep-of: df9d70c18616 ("cifs: if deferred close is disabled then close files immediately") +Signed-off-by: Sasha Levin +--- + fs/cifs/cifs_dfs_ref.c | 100 +++++++++++++++++------------------------ + 1 file changed, 40 insertions(+), 60 deletions(-) + +diff --git a/fs/cifs/cifs_dfs_ref.c b/fs/cifs/cifs_dfs_ref.c +index b0864da9ef434..020e71fe1454e 100644 +--- a/fs/cifs/cifs_dfs_ref.c ++++ b/fs/cifs/cifs_dfs_ref.c +@@ -258,61 +258,23 @@ char *cifs_compose_mount_options(const char *sb_mountdata, + goto compose_mount_options_out; + } + +-/** +- * cifs_dfs_do_mount - mounts specified path using DFS full path +- * +- * Always pass down @fullpath to smb3_do_mount() so we can use the root server +- * to perform failover in case we failed to connect to the first target in the +- * referral. +- * +- * @mntpt: directory entry for the path we are trying to automount +- * @cifs_sb: parent/root superblock +- * @fullpath: full path in UNC format +- */ +-static struct vfsmount *cifs_dfs_do_mount(struct dentry *mntpt, +- struct cifs_sb_info *cifs_sb, +- const char *fullpath) +-{ +- struct vfsmount *mnt; +- char *mountdata; +- char *devname; +- +- devname = kstrdup(fullpath, GFP_KERNEL); +- if (!devname) +- return ERR_PTR(-ENOMEM); +- +- convert_delimiter(devname, '/'); +- +- /* TODO: change to call fs_context_for_mount(), fill in context directly, call fc_mount */ +- +- /* See afs_mntpt_do_automount in fs/afs/mntpt.c for an example */ +- +- /* strip first '\' from fullpath */ +- mountdata = cifs_compose_mount_options(cifs_sb->ctx->mount_options, +- fullpath + 1, NULL, NULL); +- if (IS_ERR(mountdata)) { +- kfree(devname); +- return (struct vfsmount *)mountdata; +- } +- +- mnt = vfs_submount(mntpt, &cifs_fs_type, devname, mountdata); +- kfree(mountdata); +- kfree(devname); +- return mnt; +-} +- + /* + * Create a vfsmount that we can automount + */ +-static struct vfsmount *cifs_dfs_do_automount(struct dentry *mntpt) ++static struct vfsmount *cifs_dfs_do_automount(struct path *path) + { ++ int rc; ++ struct dentry *mntpt = path->dentry; ++ struct fs_context *fc; + struct cifs_sb_info *cifs_sb; +- void *page; ++ void *page = NULL; ++ struct smb3_fs_context *ctx, *cur_ctx; ++ struct smb3_fs_context tmp; + char *full_path; + struct vfsmount *mnt; + +- cifs_dbg(FYI, "in %s\n", __func__); +- BUG_ON(IS_ROOT(mntpt)); ++ if (IS_ROOT(mntpt)) ++ return ERR_PTR(-ESTALE); + + /* + * The MSDFS spec states that paths in DFS referral requests and +@@ -321,29 +283,47 @@ static struct vfsmount *cifs_dfs_do_automount(struct dentry *mntpt) + * gives us the latter, so we must adjust the result. + */ + cifs_sb = CIFS_SB(mntpt->d_sb); +- if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_DFS) { +- mnt = ERR_PTR(-EREMOTE); +- goto cdda_exit; +- } ++ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_DFS) ++ return ERR_PTR(-EREMOTE); ++ ++ cur_ctx = cifs_sb->ctx; ++ ++ fc = fs_context_for_submount(path->mnt->mnt_sb->s_type, mntpt); ++ if (IS_ERR(fc)) ++ return ERR_CAST(fc); ++ ++ ctx = smb3_fc2context(fc); + + page = alloc_dentry_path(); + /* always use tree name prefix */ + full_path = build_path_from_dentry_optional_prefix(mntpt, page, true); + if (IS_ERR(full_path)) { + mnt = ERR_CAST(full_path); +- goto free_full_path; ++ goto out; + } + +- convert_delimiter(full_path, '\\'); ++ convert_delimiter(full_path, '/'); + cifs_dbg(FYI, "%s: full_path: %s\n", __func__, full_path); + +- mnt = cifs_dfs_do_mount(mntpt, cifs_sb, full_path); +- cifs_dbg(FYI, "%s: cifs_dfs_do_mount:%s , mnt:%p\n", __func__, full_path + 1, mnt); ++ tmp = *cur_ctx; ++ tmp.source = full_path; ++ tmp.UNC = tmp.prepath = NULL; ++ ++ rc = smb3_fs_context_dup(ctx, &tmp); ++ if (rc) { ++ mnt = ERR_PTR(rc); ++ goto out; ++ } ++ ++ rc = smb3_parse_devname(full_path, ctx); ++ if (!rc) ++ mnt = fc_mount(fc); ++ else ++ mnt = ERR_PTR(rc); + +-free_full_path: ++out: ++ put_fs_context(fc); + free_dentry_path(page); +-cdda_exit: +- cifs_dbg(FYI, "leaving %s\n" , __func__); + return mnt; + } + +@@ -354,9 +334,9 @@ struct vfsmount *cifs_dfs_d_automount(struct path *path) + { + struct vfsmount *newmnt; + +- cifs_dbg(FYI, "in %s\n", __func__); ++ cifs_dbg(FYI, "%s: %pd\n", __func__, path->dentry); + +- newmnt = cifs_dfs_do_automount(path->dentry); ++ newmnt = cifs_dfs_do_automount(path); + if (IS_ERR(newmnt)) { + cifs_dbg(FYI, "leaving %s [automount failed]\n" , __func__); + return newmnt; +-- +2.39.2 + diff --git a/queue-5.15/dlm-cleanup-plock_op-vs-plock_xop.patch b/queue-5.15/dlm-cleanup-plock_op-vs-plock_xop.patch new file mode 100644 index 00000000000..e8bc5a84cb6 --- /dev/null +++ b/queue-5.15/dlm-cleanup-plock_op-vs-plock_xop.patch @@ -0,0 +1,233 @@ +From cd247b5ace431ae27ed84f2a1571d879c2ba1164 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 4 Apr 2022 16:06:32 -0400 +Subject: dlm: cleanup plock_op vs plock_xop + +From: Alexander Aring + +[ Upstream commit bcbb4ba6c9ba81e6975b642a2cade68044cd8a66 ] + +Lately the different casting between plock_op and plock_xop and list +holders which was involved showed some issues which were hard to see. +This patch removes the "plock_xop" structure and introduces a +"struct plock_async_data". This structure will be set in "struct plock_op" +in case of asynchronous lock handling as the original "plock_xop" was +made for. There is no need anymore to cast pointers around for +additional fields in case of asynchronous lock handling. As disadvantage +another allocation was introduces but only needed in the asynchronous +case which is currently only used in combination with nfs lockd. + +Signed-off-by: Alexander Aring +Signed-off-by: David Teigland +Stable-dep-of: 59e45c758ca1 ("fs: dlm: interrupt posix locks only when process is killed") +Signed-off-by: Sasha Levin +--- + fs/dlm/plock.c | 77 ++++++++++++++++++++++++++++++-------------------- + 1 file changed, 46 insertions(+), 31 deletions(-) + +diff --git a/fs/dlm/plock.c b/fs/dlm/plock.c +index edce0b25cd90e..e70e23eca03ec 100644 +--- a/fs/dlm/plock.c ++++ b/fs/dlm/plock.c +@@ -19,20 +19,20 @@ static struct list_head recv_list; + static wait_queue_head_t send_wq; + static wait_queue_head_t recv_wq; + +-struct plock_op { +- struct list_head list; +- int done; +- struct dlm_plock_info info; +- int (*callback)(struct file_lock *fl, int result); +-}; +- +-struct plock_xop { +- struct plock_op xop; ++struct plock_async_data { + void *fl; + void *file; + struct file_lock flc; ++ int (*callback)(struct file_lock *fl, int result); + }; + ++struct plock_op { ++ struct list_head list; ++ int done; ++ struct dlm_plock_info info; ++ /* if set indicates async handling */ ++ struct plock_async_data *data; ++}; + + static inline void set_version(struct dlm_plock_info *info) + { +@@ -58,6 +58,12 @@ static int check_version(struct dlm_plock_info *info) + return 0; + } + ++static void dlm_release_plock_op(struct plock_op *op) ++{ ++ kfree(op->data); ++ kfree(op); ++} ++ + static void send_op(struct plock_op *op) + { + set_version(&op->info); +@@ -101,22 +107,21 @@ static void do_unlock_close(struct dlm_ls *ls, u64 number, + int dlm_posix_lock(dlm_lockspace_t *lockspace, u64 number, struct file *file, + int cmd, struct file_lock *fl) + { ++ struct plock_async_data *op_data; + struct dlm_ls *ls; + struct plock_op *op; +- struct plock_xop *xop; + int rv; + + ls = dlm_find_lockspace_local(lockspace); + if (!ls) + return -EINVAL; + +- xop = kzalloc(sizeof(*xop), GFP_NOFS); +- if (!xop) { ++ op = kzalloc(sizeof(*op), GFP_NOFS); ++ if (!op) { + rv = -ENOMEM; + goto out; + } + +- op = &xop->xop; + op->info.optype = DLM_PLOCK_OP_LOCK; + op->info.pid = fl->fl_pid; + op->info.ex = (fl->fl_type == F_WRLCK); +@@ -125,22 +130,32 @@ int dlm_posix_lock(dlm_lockspace_t *lockspace, u64 number, struct file *file, + op->info.number = number; + op->info.start = fl->fl_start; + op->info.end = fl->fl_end; ++ /* async handling */ + if (fl->fl_lmops && fl->fl_lmops->lm_grant) { ++ op_data = kzalloc(sizeof(*op_data), GFP_NOFS); ++ if (!op_data) { ++ dlm_release_plock_op(op); ++ rv = -ENOMEM; ++ goto out; ++ } ++ + /* fl_owner is lockd which doesn't distinguish + processes on the nfs client */ + op->info.owner = (__u64) fl->fl_pid; +- op->callback = fl->fl_lmops->lm_grant; +- locks_init_lock(&xop->flc); +- locks_copy_lock(&xop->flc, fl); +- xop->fl = fl; +- xop->file = file; ++ op_data->callback = fl->fl_lmops->lm_grant; ++ locks_init_lock(&op_data->flc); ++ locks_copy_lock(&op_data->flc, fl); ++ op_data->fl = fl; ++ op_data->file = file; ++ ++ op->data = op_data; + } else { + op->info.owner = (__u64)(long) fl->fl_owner; + } + + send_op(op); + +- if (!op->callback) { ++ if (!op->data) { + rv = wait_event_interruptible(recv_wq, (op->done != 0)); + if (rv == -ERESTARTSYS) { + log_debug(ls, "dlm_posix_lock: wait killed %llx", +@@ -148,7 +163,7 @@ int dlm_posix_lock(dlm_lockspace_t *lockspace, u64 number, struct file *file, + spin_lock(&ops_lock); + list_del(&op->list); + spin_unlock(&ops_lock); +- kfree(xop); ++ dlm_release_plock_op(op); + do_unlock_close(ls, number, file, fl); + goto out; + } +@@ -173,7 +188,7 @@ int dlm_posix_lock(dlm_lockspace_t *lockspace, u64 number, struct file *file, + (unsigned long long)number); + } + +- kfree(xop); ++ dlm_release_plock_op(op); + out: + dlm_put_lockspace(ls); + return rv; +@@ -183,11 +198,11 @@ EXPORT_SYMBOL_GPL(dlm_posix_lock); + /* Returns failure iff a successful lock operation should be canceled */ + static int dlm_plock_callback(struct plock_op *op) + { ++ struct plock_async_data *op_data = op->data; + struct file *file; + struct file_lock *fl; + struct file_lock *flc; + int (*notify)(struct file_lock *fl, int result) = NULL; +- struct plock_xop *xop = (struct plock_xop *)op; + int rv = 0; + + spin_lock(&ops_lock); +@@ -199,10 +214,10 @@ static int dlm_plock_callback(struct plock_op *op) + spin_unlock(&ops_lock); + + /* check if the following 2 are still valid or make a copy */ +- file = xop->file; +- flc = &xop->flc; +- fl = xop->fl; +- notify = op->callback; ++ file = op_data->file; ++ flc = &op_data->flc; ++ fl = op_data->fl; ++ notify = op_data->callback; + + if (op->info.rv) { + notify(fl, op->info.rv); +@@ -233,7 +248,7 @@ static int dlm_plock_callback(struct plock_op *op) + } + + out: +- kfree(xop); ++ dlm_release_plock_op(op); + return rv; + } + +@@ -303,7 +318,7 @@ int dlm_posix_unlock(dlm_lockspace_t *lockspace, u64 number, struct file *file, + rv = 0; + + out_free: +- kfree(op); ++ dlm_release_plock_op(op); + out: + dlm_put_lockspace(ls); + fl->fl_flags = fl_flags; +@@ -371,7 +386,7 @@ int dlm_posix_get(dlm_lockspace_t *lockspace, u64 number, struct file *file, + rv = 0; + } + +- kfree(op); ++ dlm_release_plock_op(op); + out: + dlm_put_lockspace(ls); + return rv; +@@ -407,7 +422,7 @@ static ssize_t dev_read(struct file *file, char __user *u, size_t count, + (the process did not make an unlock call). */ + + if (op->info.flags & DLM_PLOCK_FL_CLOSE) +- kfree(op); ++ dlm_release_plock_op(op); + + if (copy_to_user(u, &info, sizeof(info))) + return -EFAULT; +@@ -439,7 +454,7 @@ static ssize_t dev_write(struct file *file, const char __user *u, size_t count, + op->info.owner == info.owner) { + list_del_init(&op->list); + memcpy(&op->info, &info, sizeof(info)); +- if (op->callback) ++ if (op->data) + do_callback = 1; + else + op->done = 1; +-- +2.39.2 + diff --git a/queue-5.15/dlm-rearrange-async-condition-return.patch b/queue-5.15/dlm-rearrange-async-condition-return.patch new file mode 100644 index 00000000000..e2a60292eb2 --- /dev/null +++ b/queue-5.15/dlm-rearrange-async-condition-return.patch @@ -0,0 +1,67 @@ +From 9171eb97c29452e232caa4b44526dffa6e515757 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 4 Apr 2022 16:06:33 -0400 +Subject: dlm: rearrange async condition return + +From: Alexander Aring + +[ Upstream commit a800ba77fd285c6391a82819867ac64e9ab3af46 ] + +This patch moves the return of FILE_LOCK_DEFERRED a little bit earlier +than checking afterwards again if the request was an asynchronous request. + +Signed-off-by: Alexander Aring +Signed-off-by: David Teigland +Stable-dep-of: 59e45c758ca1 ("fs: dlm: interrupt posix locks only when process is killed") +Signed-off-by: Sasha Levin +--- + fs/dlm/plock.c | 27 +++++++++++++-------------- + 1 file changed, 13 insertions(+), 14 deletions(-) + +diff --git a/fs/dlm/plock.c b/fs/dlm/plock.c +index e70e23eca03ec..01fb7d8c0bca5 100644 +--- a/fs/dlm/plock.c ++++ b/fs/dlm/plock.c +@@ -149,26 +149,25 @@ int dlm_posix_lock(dlm_lockspace_t *lockspace, u64 number, struct file *file, + op_data->file = file; + + op->data = op_data; ++ ++ send_op(op); ++ rv = FILE_LOCK_DEFERRED; ++ goto out; + } else { + op->info.owner = (__u64)(long) fl->fl_owner; + } + + send_op(op); + +- if (!op->data) { +- rv = wait_event_interruptible(recv_wq, (op->done != 0)); +- if (rv == -ERESTARTSYS) { +- log_debug(ls, "dlm_posix_lock: wait killed %llx", +- (unsigned long long)number); +- spin_lock(&ops_lock); +- list_del(&op->list); +- spin_unlock(&ops_lock); +- dlm_release_plock_op(op); +- do_unlock_close(ls, number, file, fl); +- goto out; +- } +- } else { +- rv = FILE_LOCK_DEFERRED; ++ rv = wait_event_interruptible(recv_wq, (op->done != 0)); ++ if (rv == -ERESTARTSYS) { ++ log_debug(ls, "%s: wait killed %llx", __func__, ++ (unsigned long long)number); ++ spin_lock(&ops_lock); ++ list_del(&op->list); ++ spin_unlock(&ops_lock); ++ dlm_release_plock_op(op); ++ do_unlock_close(ls, number, file, fl); + goto out; + } + +-- +2.39.2 + diff --git a/queue-5.15/drm-amdgpu-fix-vkms-crtc-settings.patch b/queue-5.15/drm-amdgpu-fix-vkms-crtc-settings.patch new file mode 100644 index 00000000000..84a1fdf4dca --- /dev/null +++ b/queue-5.15/drm-amdgpu-fix-vkms-crtc-settings.patch @@ -0,0 +1,168 @@ +From cb0e3d168f003d982d765720240b875c61a43964 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 24 Nov 2021 10:34:57 +0800 +Subject: drm/amdgpu: fix vkms crtc settings + +From: Flora Cui + +[ Upstream commit deefd07eedb7baa25956c8365373e6a58c81565a ] + +otherwise adev->mode_info.crtcs[] is NULL + +Signed-off-by: Flora Cui +Reviewed-by: Alex Deucher +Signed-off-by: Alex Deucher +Stable-dep-of: b42ae87a7b38 ("drm/amdgpu/vkms: relax timer deactivation by hrtimer_try_to_cancel") +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c | 42 ++++++++++++++++-------- + drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h | 5 ++- + 2 files changed, 30 insertions(+), 17 deletions(-) + +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c +index 7d58bf410be05..24251cdf95073 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c +@@ -16,6 +16,8 @@ + #include "ivsrcid/ivsrcid_vislands30.h" + #include "amdgpu_vkms.h" + #include "amdgpu_display.h" ++#include "atom.h" ++#include "amdgpu_irq.h" + + /** + * DOC: amdgpu_vkms +@@ -41,14 +43,13 @@ static const u32 amdgpu_vkms_formats[] = { + + static enum hrtimer_restart amdgpu_vkms_vblank_simulate(struct hrtimer *timer) + { +- struct amdgpu_vkms_output *output = container_of(timer, +- struct amdgpu_vkms_output, +- vblank_hrtimer); +- struct drm_crtc *crtc = &output->crtc; ++ struct amdgpu_crtc *amdgpu_crtc = container_of(timer, struct amdgpu_crtc, vblank_timer); ++ struct drm_crtc *crtc = &amdgpu_crtc->base; ++ struct amdgpu_vkms_output *output = drm_crtc_to_amdgpu_vkms_output(crtc); + u64 ret_overrun; + bool ret; + +- ret_overrun = hrtimer_forward_now(&output->vblank_hrtimer, ++ ret_overrun = hrtimer_forward_now(&amdgpu_crtc->vblank_timer, + output->period_ns); + WARN_ON(ret_overrun != 1); + +@@ -65,22 +66,21 @@ static int amdgpu_vkms_enable_vblank(struct drm_crtc *crtc) + unsigned int pipe = drm_crtc_index(crtc); + struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; + struct amdgpu_vkms_output *out = drm_crtc_to_amdgpu_vkms_output(crtc); ++ struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); + + drm_calc_timestamping_constants(crtc, &crtc->mode); + +- hrtimer_init(&out->vblank_hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); +- out->vblank_hrtimer.function = &amdgpu_vkms_vblank_simulate; + out->period_ns = ktime_set(0, vblank->framedur_ns); +- hrtimer_start(&out->vblank_hrtimer, out->period_ns, HRTIMER_MODE_REL); ++ hrtimer_start(&amdgpu_crtc->vblank_timer, out->period_ns, HRTIMER_MODE_REL); + + return 0; + } + + static void amdgpu_vkms_disable_vblank(struct drm_crtc *crtc) + { +- struct amdgpu_vkms_output *out = drm_crtc_to_amdgpu_vkms_output(crtc); ++ struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); + +- hrtimer_cancel(&out->vblank_hrtimer); ++ hrtimer_cancel(&amdgpu_crtc->vblank_timer); + } + + static bool amdgpu_vkms_get_vblank_timestamp(struct drm_crtc *crtc, +@@ -92,13 +92,14 @@ static bool amdgpu_vkms_get_vblank_timestamp(struct drm_crtc *crtc, + unsigned int pipe = crtc->index; + struct amdgpu_vkms_output *output = drm_crtc_to_amdgpu_vkms_output(crtc); + struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; ++ struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); + + if (!READ_ONCE(vblank->enabled)) { + *vblank_time = ktime_get(); + return true; + } + +- *vblank_time = READ_ONCE(output->vblank_hrtimer.node.expires); ++ *vblank_time = READ_ONCE(amdgpu_crtc->vblank_timer.node.expires); + + if (WARN_ON(*vblank_time == vblank->time)) + return true; +@@ -166,6 +167,8 @@ static const struct drm_crtc_helper_funcs amdgpu_vkms_crtc_helper_funcs = { + static int amdgpu_vkms_crtc_init(struct drm_device *dev, struct drm_crtc *crtc, + struct drm_plane *primary, struct drm_plane *cursor) + { ++ struct amdgpu_device *adev = drm_to_adev(dev); ++ struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); + int ret; + + ret = drm_crtc_init_with_planes(dev, crtc, primary, cursor, +@@ -177,6 +180,17 @@ static int amdgpu_vkms_crtc_init(struct drm_device *dev, struct drm_crtc *crtc, + + drm_crtc_helper_add(crtc, &amdgpu_vkms_crtc_helper_funcs); + ++ amdgpu_crtc->crtc_id = drm_crtc_index(crtc); ++ adev->mode_info.crtcs[drm_crtc_index(crtc)] = amdgpu_crtc; ++ ++ amdgpu_crtc->pll_id = ATOM_PPLL_INVALID; ++ amdgpu_crtc->encoder = NULL; ++ amdgpu_crtc->connector = NULL; ++ amdgpu_crtc->vsync_timer_enabled = AMDGPU_IRQ_STATE_DISABLE; ++ ++ hrtimer_init(&amdgpu_crtc->vblank_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); ++ amdgpu_crtc->vblank_timer.function = &amdgpu_vkms_vblank_simulate; ++ + return ret; + } + +@@ -402,7 +416,7 @@ int amdgpu_vkms_output_init(struct drm_device *dev, + { + struct drm_connector *connector = &output->connector; + struct drm_encoder *encoder = &output->encoder; +- struct drm_crtc *crtc = &output->crtc; ++ struct drm_crtc *crtc = &output->crtc.base; + struct drm_plane *primary, *cursor = NULL; + int ret; + +@@ -505,8 +519,8 @@ static int amdgpu_vkms_sw_fini(void *handle) + int i = 0; + + for (i = 0; i < adev->mode_info.num_crtc; i++) +- if (adev->amdgpu_vkms_output[i].vblank_hrtimer.function) +- hrtimer_cancel(&adev->amdgpu_vkms_output[i].vblank_hrtimer); ++ if (adev->mode_info.crtcs[i]) ++ hrtimer_cancel(&adev->mode_info.crtcs[i]->vblank_timer); + + kfree(adev->mode_info.bios_hardcoded_edid); + kfree(adev->amdgpu_vkms_output); +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h +index 97f1b79c0724e..4f8722ff37c25 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h +@@ -10,15 +10,14 @@ + #define YRES_MAX 16384 + + #define drm_crtc_to_amdgpu_vkms_output(target) \ +- container_of(target, struct amdgpu_vkms_output, crtc) ++ container_of(target, struct amdgpu_vkms_output, crtc.base) + + extern const struct amdgpu_ip_block_version amdgpu_vkms_ip_block; + + struct amdgpu_vkms_output { +- struct drm_crtc crtc; ++ struct amdgpu_crtc crtc; + struct drm_encoder encoder; + struct drm_connector connector; +- struct hrtimer vblank_hrtimer; + ktime_t period_ns; + struct drm_pending_vblank_event *event; + }; +-- +2.39.2 + diff --git a/queue-5.15/drm-amdgpu-vkms-relax-timer-deactivation-by-hrtimer_.patch b/queue-5.15/drm-amdgpu-vkms-relax-timer-deactivation-by-hrtimer_.patch new file mode 100644 index 00000000000..8cc1ae92d5a --- /dev/null +++ b/queue-5.15/drm-amdgpu-vkms-relax-timer-deactivation-by-hrtimer_.patch @@ -0,0 +1,106 @@ +From 2291d9f1bcb49b557c2877157eaa2d6bc91da1d3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Jul 2023 15:57:21 +0800 +Subject: drm/amdgpu/vkms: relax timer deactivation by hrtimer_try_to_cancel +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Guchun Chen + +[ Upstream commit b42ae87a7b3878afaf4c3852ca66c025a5b996e0 ] + +In below thousands of screen rotation loop tests with virtual display +enabled, a CPU hard lockup issue may happen, leading system to unresponsive +and crash. + +do { + xrandr --output Virtual --rotate inverted + xrandr --output Virtual --rotate right + xrandr --output Virtual --rotate left + xrandr --output Virtual --rotate normal +} while (1); + +NMI watchdog: Watchdog detected hard LOCKUP on cpu 1 + +? hrtimer_run_softirq+0x140/0x140 +? store_vblank+0xe0/0xe0 [drm] +hrtimer_cancel+0x15/0x30 +amdgpu_vkms_disable_vblank+0x15/0x30 [amdgpu] +drm_vblank_disable_and_save+0x185/0x1f0 [drm] +drm_crtc_vblank_off+0x159/0x4c0 [drm] +? record_print_text.cold+0x11/0x11 +? wait_for_completion_timeout+0x232/0x280 +? drm_crtc_wait_one_vblank+0x40/0x40 [drm] +? bit_wait_io_timeout+0xe0/0xe0 +? wait_for_completion_interruptible+0x1d7/0x320 +? mutex_unlock+0x81/0xd0 +amdgpu_vkms_crtc_atomic_disable + +It's caused by a stuck in lock dependency in such scenario on different +CPUs. + +CPU1 CPU2 +drm_crtc_vblank_off hrtimer_interrupt + grab event_lock (irq disabled) __hrtimer_run_queues + grab vbl_lock/vblank_time_block amdgpu_vkms_vblank_simulate + amdgpu_vkms_disable_vblank drm_handle_vblank + hrtimer_cancel grab dev->event_lock + +So CPU1 stucks in hrtimer_cancel as timer callback is running endless on +current clock base, as that timer queue on CPU2 has no chance to finish it +because of failing to hold the lock. So NMI watchdog will throw the errors +after its threshold, and all later CPUs are impacted/blocked. + +So use hrtimer_try_to_cancel to fix this, as disable_vblank callback +does not need to wait the handler to finish. And also it's not necessary +to check the return value of hrtimer_try_to_cancel, because even if it's +-1 which means current timer callback is running, it will be reprogrammed +in hrtimer_start with calling enable_vblank to make it works. + +v2: only re-arm timer when vblank is enabled (Christian) and add a Fixes +tag as well + +v3: drop warn printing (Christian) + +v4: drop superfluous check of blank->enabled in timer function, as it's +guaranteed in drm_handle_vblank (Christian) + +Fixes: 84ec374bd580 ("drm/amdgpu: create amdgpu_vkms (v4)") +Cc: stable@vger.kernel.org +Suggested-by: Christian König +Signed-off-by: Guchun Chen +Reviewed-by: Christian König +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c +index 24251cdf95073..4e8274de8fc0c 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c +@@ -54,8 +54,9 @@ static enum hrtimer_restart amdgpu_vkms_vblank_simulate(struct hrtimer *timer) + WARN_ON(ret_overrun != 1); + + ret = drm_crtc_handle_vblank(crtc); ++ /* Don't queue timer again when vblank is disabled. */ + if (!ret) +- DRM_ERROR("amdgpu_vkms failure on handling vblank"); ++ return HRTIMER_NORESTART; + + return HRTIMER_RESTART; + } +@@ -80,7 +81,7 @@ static void amdgpu_vkms_disable_vblank(struct drm_crtc *crtc) + { + struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); + +- hrtimer_cancel(&amdgpu_crtc->vblank_timer); ++ hrtimer_try_to_cancel(&amdgpu_crtc->vblank_timer); + } + + static bool amdgpu_vkms_get_vblank_timestamp(struct drm_crtc *crtc, +-- +2.39.2 + diff --git a/queue-5.15/drm-ttm-don-t-leak-a-resource-on-eviction-error.patch b/queue-5.15/drm-ttm-don-t-leak-a-resource-on-eviction-error.patch new file mode 100644 index 00000000000..6fef51c8317 --- /dev/null +++ b/queue-5.15/drm-ttm-don-t-leak-a-resource-on-eviction-error.patch @@ -0,0 +1,72 @@ +From cb49f8d791c2603eb5da6e5bbdbf36dcc53d37d3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 26 Jun 2023 11:14:49 +0200 +Subject: drm/ttm: Don't leak a resource on eviction error +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Thomas Hellström + +[ Upstream commit e8188c461ee015ba0b9ab2fc82dbd5ebca5a5532 ] + +On eviction errors other than -EMULTIHOP we were leaking a resource. +Fix. + +v2: +- Avoid yet another goto (Andi Shyti) + +Fixes: 403797925768 ("drm/ttm: Fix multihop assert on eviction.") +Cc: Andrey Grodzovsky +Cc: Christian König +Cc: Christian Koenig +Cc: Huang Rui +Cc: dri-devel@lists.freedesktop.org +Cc: # v5.15+ +Signed-off-by: Thomas Hellström +Reviewed-by: Nirmoy Das #v1 +Reviewed-by: Andi Shyti +Reviewed-by: Christian König +Link: https://patchwork.freedesktop.org/patch/msgid/20230626091450.14757-4-thomas.hellstrom@linux.intel.com +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/ttm/ttm_bo.c | 22 +++++++++++----------- + 1 file changed, 11 insertions(+), 11 deletions(-) + +diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c +index cf390ab636978..6080f4b5c450c 100644 +--- a/drivers/gpu/drm/ttm/ttm_bo.c ++++ b/drivers/gpu/drm/ttm/ttm_bo.c +@@ -552,18 +552,18 @@ static int ttm_bo_evict(struct ttm_buffer_object *bo, + goto out; + } + +-bounce: +- ret = ttm_bo_handle_move_mem(bo, evict_mem, true, ctx, &hop); +- if (ret == -EMULTIHOP) { ++ do { ++ ret = ttm_bo_handle_move_mem(bo, evict_mem, true, ctx, &hop); ++ if (ret != -EMULTIHOP) ++ break; ++ + ret = ttm_bo_bounce_temp_buffer(bo, &evict_mem, ctx, &hop); +- if (ret) { +- if (ret != -ERESTARTSYS && ret != -EINTR) +- pr_err("Buffer eviction failed\n"); +- ttm_resource_free(bo, &evict_mem); +- goto out; +- } +- /* try and move to final place now. */ +- goto bounce; ++ } while (!ret); ++ ++ if (ret) { ++ ttm_resource_free(bo, &evict_mem); ++ if (ret != -ERESTARTSYS && ret != -EINTR) ++ pr_err("Buffer eviction failed\n"); + } + out: + return ret; +-- +2.39.2 + diff --git a/queue-5.15/drm-ttm-don-t-print-error-message-if-eviction-was-in.patch b/queue-5.15/drm-ttm-don-t-print-error-message-if-eviction-was-in.patch new file mode 100644 index 00000000000..d7e286769c5 --- /dev/null +++ b/queue-5.15/drm-ttm-don-t-print-error-message-if-eviction-was-in.patch @@ -0,0 +1,42 @@ +From cfdc82035adbf6df02439a902bf16a5f19898007 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 Mar 2023 15:46:19 +0100 +Subject: drm/ttm: Don't print error message if eviction was interrupted +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Thomas Hellström + +[ Upstream commit 8ab3b0663e279ab550bc2c0b5d602960e8b94e02 ] + +Avoid printing an error message if eviction was interrupted by, +for example, the user pressing CTRL-C. That may happen if eviction +is waiting for something, like for example a free batch-buffer. + +Signed-off-by: Thomas Hellström +Reviewed-by: Christian König +Link: https://patchwork.freedesktop.org/patch/msgid/20230307144621.10748-6-thomas.hellstrom@linux.intel.com +Stable-dep-of: e8188c461ee0 ("drm/ttm: Don't leak a resource on eviction error") +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/ttm/ttm_bo.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c +index d5a2b69489e7f..cf390ab636978 100644 +--- a/drivers/gpu/drm/ttm/ttm_bo.c ++++ b/drivers/gpu/drm/ttm/ttm_bo.c +@@ -557,7 +557,8 @@ static int ttm_bo_evict(struct ttm_buffer_object *bo, + if (ret == -EMULTIHOP) { + ret = ttm_bo_bounce_temp_buffer(bo, &evict_mem, ctx, &hop); + if (ret) { +- pr_err("Buffer eviction failed\n"); ++ if (ret != -ERESTARTSYS && ret != -EINTR) ++ pr_err("Buffer eviction failed\n"); + ttm_resource_free(bo, &evict_mem); + goto out; + } +-- +2.39.2 + diff --git a/queue-5.15/drm-ttm-never-consider-pinned-bos-for-eviction-swap.patch b/queue-5.15/drm-ttm-never-consider-pinned-bos-for-eviction-swap.patch new file mode 100644 index 00000000000..7d73b94c231 --- /dev/null +++ b/queue-5.15/drm-ttm-never-consider-pinned-bos-for-eviction-swap.patch @@ -0,0 +1,46 @@ +From f050822f2bc5bdcf55c3259f2428a89feeba62d4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 7 Jul 2023 11:25:00 +0200 +Subject: drm/ttm: never consider pinned BOs for eviction&swap +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Christian König + +[ Upstream commit a2848d08742c8e8494675892c02c0d22acbe3cf8 ] + +There is a small window where we have already incremented the pin count +but not yet moved the bo from the lru to the pinned list. + +Signed-off-by: Christian König +Reported-by: Pelloux-Prayer, Pierre-Eric +Tested-by: Pelloux-Prayer, Pierre-Eric +Acked-by: Alex Deucher +Cc: stable@vger.kernel.org +Link: https://patchwork.freedesktop.org/patch/msgid/20230707120826.3701-1-christian.koenig@amd.com +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/ttm/ttm_bo.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c +index 6080f4b5c450c..4d0ef5ab25319 100644 +--- a/drivers/gpu/drm/ttm/ttm_bo.c ++++ b/drivers/gpu/drm/ttm/ttm_bo.c +@@ -604,6 +604,12 @@ static bool ttm_bo_evict_swapout_allowable(struct ttm_buffer_object *bo, + { + bool ret = false; + ++ if (bo->pin_count) { ++ *locked = false; ++ *busy = false; ++ return false; ++ } ++ + if (bo->base.resv == ctx->resv) { + dma_resv_assert_held(bo->base.resv); + if (ctx->allow_res_evict) +-- +2.39.2 + diff --git a/queue-5.15/fs-dlm-interrupt-posix-locks-only-when-process-is-ki.patch b/queue-5.15/fs-dlm-interrupt-posix-locks-only-when-process-is-ki.patch new file mode 100644 index 00000000000..6becf6a0820 --- /dev/null +++ b/queue-5.15/fs-dlm-interrupt-posix-locks-only-when-process-is-ki.patch @@ -0,0 +1,44 @@ +From 72ce2ba1a355dc0d473cf395f58a8b1d94e376b1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 19 May 2023 11:21:26 -0400 +Subject: fs: dlm: interrupt posix locks only when process is killed + +From: Alexander Aring + +[ Upstream commit 59e45c758ca1b9893ac923dd63536da946ac333b ] + +If a posix lock request is waiting for a result from user space +(dlm_controld), do not let it be interrupted unless the process +is killed. This reverts commit a6b1533e9a57 ("dlm: make posix locks +interruptible"). The problem with the interruptible change is +that all locks were cleared on any signal interrupt. If a signal +was received that did not terminate the process, the process +could continue running after all its dlm posix locks had been +cleared. A future patch will add cancelation to allow proper +interruption. + +Cc: stable@vger.kernel.org +Fixes: a6b1533e9a57 ("dlm: make posix locks interruptible") +Signed-off-by: Alexander Aring +Signed-off-by: David Teigland +Signed-off-by: Sasha Levin +--- + fs/dlm/plock.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/fs/dlm/plock.c b/fs/dlm/plock.c +index 01fb7d8c0bca5..f3482e936cc25 100644 +--- a/fs/dlm/plock.c ++++ b/fs/dlm/plock.c +@@ -159,7 +159,7 @@ int dlm_posix_lock(dlm_lockspace_t *lockspace, u64 number, struct file *file, + + send_op(op); + +- rv = wait_event_interruptible(recv_wq, (op->done != 0)); ++ rv = wait_event_killable(recv_wq, (op->done != 0)); + if (rv == -ERESTARTSYS) { + log_debug(ls, "%s: wait killed %llx", __func__, + (unsigned long long)number); +-- +2.39.2 + diff --git a/queue-5.15/gpio-mvebu-fix-irq-domain-leak.patch b/queue-5.15/gpio-mvebu-fix-irq-domain-leak.patch new file mode 100644 index 00000000000..9abb393e9a5 --- /dev/null +++ b/queue-5.15/gpio-mvebu-fix-irq-domain-leak.patch @@ -0,0 +1,77 @@ +From 4b97e0208a504563b54b58de395f48e95caf4f3b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 19 Jul 2023 13:41:01 +0200 +Subject: gpio: mvebu: fix irq domain leak +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Bartosz Golaszewski + +[ Upstream commit 644ee70267a934be27370f9aa618b29af7290544 ] + +Uwe Kleine-König pointed out we still have one resource leak in the mvebu +driver triggered on driver detach. Let's address it with a custom devm +action. + +Fixes: 812d47889a8e ("gpio/mvebu: Use irq_domain_add_linear") +Signed-off-by: Bartosz Golaszewski +Reviewed-by: Andy Shevchenko +Reviewed-by: Uwe Kleine-König +Signed-off-by: Sasha Levin +--- + drivers/gpio/gpio-mvebu.c | 18 +++++++++++++----- + 1 file changed, 13 insertions(+), 5 deletions(-) + +diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c +index 4d64b3358c50c..b965513f44fea 100644 +--- a/drivers/gpio/gpio-mvebu.c ++++ b/drivers/gpio/gpio-mvebu.c +@@ -1112,6 +1112,13 @@ static int mvebu_gpio_probe_syscon(struct platform_device *pdev, + return 0; + } + ++static void mvebu_gpio_remove_irq_domain(void *data) ++{ ++ struct irq_domain *domain = data; ++ ++ irq_domain_remove(domain); ++} ++ + static int mvebu_gpio_probe(struct platform_device *pdev) + { + struct mvebu_gpio_chip *mvchip; +@@ -1247,13 +1254,18 @@ static int mvebu_gpio_probe(struct platform_device *pdev) + return -ENODEV; + } + ++ err = devm_add_action_or_reset(&pdev->dev, mvebu_gpio_remove_irq_domain, ++ mvchip->domain); ++ if (err) ++ return err; ++ + err = irq_alloc_domain_generic_chips( + mvchip->domain, ngpios, 2, np->name, handle_level_irq, + IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_LEVEL, 0, 0); + if (err) { + dev_err(&pdev->dev, "couldn't allocate irq chips %s (DT).\n", + mvchip->chip.label); +- goto err_domain; ++ return err; + } + + /* +@@ -1293,10 +1305,6 @@ static int mvebu_gpio_probe(struct platform_device *pdev) + } + + return 0; +- +-err_domain: +- irq_domain_remove(mvchip->domain); +- return err; + } + + static struct platform_driver mvebu_gpio_driver = { +-- +2.39.2 + diff --git a/queue-5.15/gpio-mvebu-make-use-of-devm_pwmchip_add.patch b/queue-5.15/gpio-mvebu-make-use-of-devm_pwmchip_add.patch new file mode 100644 index 00000000000..a0df5352e64 --- /dev/null +++ b/queue-5.15/gpio-mvebu-make-use-of-devm_pwmchip_add.patch @@ -0,0 +1,61 @@ +From 4f63c883d0b08e81d08ca9e9f9473ad6abaac935 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Jul 2023 16:27:43 +0200 +Subject: gpio: mvebu: Make use of devm_pwmchip_add +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Uwe Kleine-König + +[ Upstream commit 1945063eb59e64d2919cb14d54d081476d9e53bb ] + +This allows to get rid of a call to pwmchip_remove() in the error path. There +is no .remove function for this driver, so this change fixes a resource leak +when a gpio-mvebu device is unbound. + +Fixes: 757642f9a584 ("gpio: mvebu: Add limited PWM support") +Signed-off-by: Uwe Kleine-König +Reviewed-by: Andy Shevchenko +Signed-off-by: Bartosz Golaszewski +Signed-off-by: Sasha Levin +--- + drivers/gpio/gpio-mvebu.c | 8 ++------ + 1 file changed, 2 insertions(+), 6 deletions(-) + +diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c +index a245bfd5a6173..4d64b3358c50c 100644 +--- a/drivers/gpio/gpio-mvebu.c ++++ b/drivers/gpio/gpio-mvebu.c +@@ -874,7 +874,7 @@ static int mvebu_pwm_probe(struct platform_device *pdev, + + spin_lock_init(&mvpwm->lock); + +- return pwmchip_add(&mvpwm->chip); ++ return devm_pwmchip_add(dev, &mvpwm->chip); + } + + #ifdef CONFIG_DEBUG_FS +@@ -1244,8 +1244,7 @@ static int mvebu_gpio_probe(struct platform_device *pdev) + if (!mvchip->domain) { + dev_err(&pdev->dev, "couldn't allocate irq domain %s (DT).\n", + mvchip->chip.label); +- err = -ENODEV; +- goto err_pwm; ++ return -ENODEV; + } + + err = irq_alloc_domain_generic_chips( +@@ -1297,9 +1296,6 @@ static int mvebu_gpio_probe(struct platform_device *pdev) + + err_domain: + irq_domain_remove(mvchip->domain); +-err_pwm: +- pwmchip_remove(&mvchip->mvpwm->chip); +- + return err; + } + +-- +2.39.2 + diff --git a/queue-5.15/gpio-tps68470-make-tps68470_gpio_output-always-set-t.patch b/queue-5.15/gpio-tps68470-make-tps68470_gpio_output-always-set-t.patch new file mode 100644 index 00000000000..2478181f6a5 --- /dev/null +++ b/queue-5.15/gpio-tps68470-make-tps68470_gpio_output-always-set-t.patch @@ -0,0 +1,50 @@ +From 5a7247b05210fcc9f1ecad601dcfcc57db3e0cf4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 10 Jul 2023 14:34:25 +0200 +Subject: gpio: tps68470: Make tps68470_gpio_output() always set the initial + value + +From: Hans de Goede + +[ Upstream commit 5a7adc6c1069ce31ef4f606ae9c05592c80a6ab5 ] + +Make tps68470_gpio_output() call tps68470_gpio_set() for output-only pins +too, so that the initial value passed to gpiod_direction_output() is +honored for these pins too. + +Fixes: 275b13a65547 ("gpio: Add support for TPS68470 GPIOs") +Reviewed-by: Andy Shevchenko +Reviewed-by: Daniel Scally +Tested-by: Daniel Scally +Reviewed-by: Sakari Ailus +Signed-off-by: Hans de Goede +Signed-off-by: Bartosz Golaszewski +Signed-off-by: Sasha Levin +--- + drivers/gpio/gpio-tps68470.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/gpio/gpio-tps68470.c b/drivers/gpio/gpio-tps68470.c +index 423b7bc30ae88..03a523a6d6fa4 100644 +--- a/drivers/gpio/gpio-tps68470.c ++++ b/drivers/gpio/gpio-tps68470.c +@@ -91,13 +91,13 @@ static int tps68470_gpio_output(struct gpio_chip *gc, unsigned int offset, + struct tps68470_gpio_data *tps68470_gpio = gpiochip_get_data(gc); + struct regmap *regmap = tps68470_gpio->tps68470_regmap; + ++ /* Set the initial value */ ++ tps68470_gpio_set(gc, offset, value); ++ + /* rest are always outputs */ + if (offset >= TPS68470_N_REGULAR_GPIO) + return 0; + +- /* Set the initial value */ +- tps68470_gpio_set(gc, offset, value); +- + return regmap_update_bits(regmap, TPS68470_GPIO_CTL_REG_A(offset), + TPS68470_GPIO_MODE_MASK, + TPS68470_GPIO_MODE_OUT_CMOS); +-- +2.39.2 + diff --git a/queue-5.15/i2c-delete-error-messages-for-failed-memory-allocati.patch b/queue-5.15/i2c-delete-error-messages-for-failed-memory-allocati.patch new file mode 100644 index 00000000000..5d200db920e --- /dev/null +++ b/queue-5.15/i2c-delete-error-messages-for-failed-memory-allocati.patch @@ -0,0 +1,81 @@ +From 09e26e1759387dfdab7326d4ba381b1f2dddf771 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 2 Feb 2018 17:24:57 +0100 +Subject: i2c: Delete error messages for failed memory allocations + +From: Markus Elfring + +[ Upstream commit 6b3b21a8542fd2fb6ffc61bc13b9419f0c58ebad ] + +These issues were detected by using the Coccinelle software. + +Signed-off-by: Markus Elfring +Signed-off-by: Wolfram Sang +Stable-dep-of: 05f933d5f731 ("i2c: nomadik: Remove a useless call in the remove function") +Signed-off-by: Sasha Levin +--- + drivers/i2c/busses/i2c-ibm_iic.c | 4 +--- + drivers/i2c/busses/i2c-nomadik.c | 1 - + drivers/i2c/busses/i2c-sh7760.c | 1 - + drivers/i2c/busses/i2c-tiny-usb.c | 4 +--- + 4 files changed, 2 insertions(+), 8 deletions(-) + +diff --git a/drivers/i2c/busses/i2c-ibm_iic.c b/drivers/i2c/busses/i2c-ibm_iic.c +index 9f71daf6db64b..c073f5b8833a2 100644 +--- a/drivers/i2c/busses/i2c-ibm_iic.c ++++ b/drivers/i2c/busses/i2c-ibm_iic.c +@@ -694,10 +694,8 @@ static int iic_probe(struct platform_device *ofdev) + int ret; + + dev = kzalloc(sizeof(*dev), GFP_KERNEL); +- if (!dev) { +- dev_err(&ofdev->dev, "failed to allocate device data\n"); ++ if (!dev) + return -ENOMEM; +- } + + platform_set_drvdata(ofdev, dev); + +diff --git a/drivers/i2c/busses/i2c-nomadik.c b/drivers/i2c/busses/i2c-nomadik.c +index a2d12a5b1c34c..05eaae5aeb180 100644 +--- a/drivers/i2c/busses/i2c-nomadik.c ++++ b/drivers/i2c/busses/i2c-nomadik.c +@@ -972,7 +972,6 @@ static int nmk_i2c_probe(struct amba_device *adev, const struct amba_id *id) + + dev = devm_kzalloc(&adev->dev, sizeof(struct nmk_i2c_dev), GFP_KERNEL); + if (!dev) { +- dev_err(&adev->dev, "cannot allocate memory\n"); + ret = -ENOMEM; + goto err_no_mem; + } +diff --git a/drivers/i2c/busses/i2c-sh7760.c b/drivers/i2c/busses/i2c-sh7760.c +index 319d1fa617c88..a0ccc5d009874 100644 +--- a/drivers/i2c/busses/i2c-sh7760.c ++++ b/drivers/i2c/busses/i2c-sh7760.c +@@ -445,7 +445,6 @@ static int sh7760_i2c_probe(struct platform_device *pdev) + + id = kzalloc(sizeof(struct cami2c), GFP_KERNEL); + if (!id) { +- dev_err(&pdev->dev, "no mem for private data\n"); + ret = -ENOMEM; + goto out0; + } +diff --git a/drivers/i2c/busses/i2c-tiny-usb.c b/drivers/i2c/busses/i2c-tiny-usb.c +index 7279ca0eaa2d0..d1fa9ff5aeab4 100644 +--- a/drivers/i2c/busses/i2c-tiny-usb.c ++++ b/drivers/i2c/busses/i2c-tiny-usb.c +@@ -226,10 +226,8 @@ static int i2c_tiny_usb_probe(struct usb_interface *interface, + + /* allocate memory for our device state and initialize it */ + dev = kzalloc(sizeof(*dev), GFP_KERNEL); +- if (dev == NULL) { +- dev_err(&interface->dev, "Out of memory\n"); ++ if (!dev) + goto error; +- } + + dev->usb_dev = usb_get_dev(interface_to_usbdev(interface)); + dev->interface = interface; +-- +2.39.2 + diff --git a/queue-5.15/i2c-improve-size-determinations.patch b/queue-5.15/i2c-improve-size-determinations.patch new file mode 100644 index 00000000000..391f411fc30 --- /dev/null +++ b/queue-5.15/i2c-improve-size-determinations.patch @@ -0,0 +1,54 @@ +From 50ea2a0b7ebd12da80211ce37177e490e2e056c9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 2 Feb 2018 14:50:09 +0100 +Subject: i2c: Improve size determinations + +From: Markus Elfring + +[ Upstream commit 06e989578232da33a7fe96b04191b862af8b2cec ] + +Replace the specification of a data structure by a pointer dereference +as the parameter for the operator "sizeof" to make the corresponding +size determination a bit safer according to the Linux coding style +convention. + +This issue was detected by using the Coccinelle software. + +Signed-off-by: Markus Elfring +Signed-off-by: Wolfram Sang +Stable-dep-of: 05f933d5f731 ("i2c: nomadik: Remove a useless call in the remove function") +Signed-off-by: Sasha Levin +--- + drivers/i2c/busses/i2c-nomadik.c | 2 +- + drivers/i2c/busses/i2c-sh7760.c | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/i2c/busses/i2c-nomadik.c b/drivers/i2c/busses/i2c-nomadik.c +index 05eaae5aeb180..5004b9dd98563 100644 +--- a/drivers/i2c/busses/i2c-nomadik.c ++++ b/drivers/i2c/busses/i2c-nomadik.c +@@ -970,7 +970,7 @@ static int nmk_i2c_probe(struct amba_device *adev, const struct amba_id *id) + struct i2c_vendor_data *vendor = id->data; + u32 max_fifo_threshold = (vendor->fifodepth / 2) - 1; + +- dev = devm_kzalloc(&adev->dev, sizeof(struct nmk_i2c_dev), GFP_KERNEL); ++ dev = devm_kzalloc(&adev->dev, sizeof(*dev), GFP_KERNEL); + if (!dev) { + ret = -ENOMEM; + goto err_no_mem; +diff --git a/drivers/i2c/busses/i2c-sh7760.c b/drivers/i2c/busses/i2c-sh7760.c +index a0ccc5d009874..051b904cb35f6 100644 +--- a/drivers/i2c/busses/i2c-sh7760.c ++++ b/drivers/i2c/busses/i2c-sh7760.c +@@ -443,7 +443,7 @@ static int sh7760_i2c_probe(struct platform_device *pdev) + goto out0; + } + +- id = kzalloc(sizeof(struct cami2c), GFP_KERNEL); ++ id = kzalloc(sizeof(*id), GFP_KERNEL); + if (!id) { + ret = -ENOMEM; + goto out0; +-- +2.39.2 + diff --git a/queue-5.15/i2c-nomadik-remove-a-useless-call-in-the-remove-func.patch b/queue-5.15/i2c-nomadik-remove-a-useless-call-in-the-remove-func.patch new file mode 100644 index 00000000000..53ed3109767 --- /dev/null +++ b/queue-5.15/i2c-nomadik-remove-a-useless-call-in-the-remove-func.patch @@ -0,0 +1,49 @@ +From 34a60f664ab617a1caf611af6355eeb3b51a9f0c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 4 Jul 2023 21:50:28 +0200 +Subject: i2c: nomadik: Remove a useless call in the remove function + +From: Christophe JAILLET + +[ Upstream commit 05f933d5f7318b03ff2028c1704dc867ac16f2c7 ] + +Since commit 235602146ec9 ("i2c-nomadik: turn the platform driver to an amba +driver"), there is no more request_mem_region() call in this driver. + +So remove the release_mem_region() call from the remove function which is +likely a left over. + +Fixes: 235602146ec9 ("i2c-nomadik: turn the platform driver to an amba driver") +Cc: # v3.6+ +Acked-by: Linus Walleij +Reviewed-by: Andi Shyti +Signed-off-by: Christophe JAILLET +Signed-off-by: Wolfram Sang +Signed-off-by: Sasha Levin +--- + drivers/i2c/busses/i2c-nomadik.c | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/drivers/i2c/busses/i2c-nomadik.c b/drivers/i2c/busses/i2c-nomadik.c +index 2141ba05dfece..9c5d66bd6dc1c 100644 +--- a/drivers/i2c/busses/i2c-nomadik.c ++++ b/drivers/i2c/busses/i2c-nomadik.c +@@ -1040,7 +1040,6 @@ static int nmk_i2c_probe(struct amba_device *adev, const struct amba_id *id) + + static void nmk_i2c_remove(struct amba_device *adev) + { +- struct resource *res = &adev->res; + struct nmk_i2c_dev *dev = amba_get_drvdata(adev); + + i2c_del_adapter(&dev->adap); +@@ -1049,7 +1048,6 @@ static void nmk_i2c_remove(struct amba_device *adev) + clear_all_interrupts(dev); + /* disable the controller */ + i2c_clr_bit(dev->virtbase + I2C_CR, I2C_CR_PE); +- release_mem_region(res->start, resource_size(res)); + } + + static struct i2c_vendor_data vendor_stn8815 = { +-- +2.39.2 + diff --git a/queue-5.15/i2c-nomadik-remove-unnecessary-goto-label.patch b/queue-5.15/i2c-nomadik-remove-unnecessary-goto-label.patch new file mode 100644 index 00000000000..1f8328d3193 --- /dev/null +++ b/queue-5.15/i2c-nomadik-remove-unnecessary-goto-label.patch @@ -0,0 +1,85 @@ +From 655c28066fa458bcb6ff3a4a156e7494256f2041 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 11 Jun 2023 03:36:59 +0200 +Subject: i2c: nomadik: Remove unnecessary goto label + +From: Andi Shyti + +[ Upstream commit 1c5d33fff0d375e4ab7c4261dc62a286babbb4c6 ] + +The err_no_mem goto label doesn't do anything. Remove it. + +Signed-off-by: Andi Shyti +Reviewed-by: Linus Walleij +Signed-off-by: Wolfram Sang +Stable-dep-of: 05f933d5f731 ("i2c: nomadik: Remove a useless call in the remove function") +Signed-off-by: Sasha Levin +--- + drivers/i2c/busses/i2c-nomadik.c | 21 ++++++++------------- + 1 file changed, 8 insertions(+), 13 deletions(-) + +diff --git a/drivers/i2c/busses/i2c-nomadik.c b/drivers/i2c/busses/i2c-nomadik.c +index 5004b9dd98563..8b9577318388e 100644 +--- a/drivers/i2c/busses/i2c-nomadik.c ++++ b/drivers/i2c/busses/i2c-nomadik.c +@@ -971,10 +971,9 @@ static int nmk_i2c_probe(struct amba_device *adev, const struct amba_id *id) + u32 max_fifo_threshold = (vendor->fifodepth / 2) - 1; + + dev = devm_kzalloc(&adev->dev, sizeof(*dev), GFP_KERNEL); +- if (!dev) { +- ret = -ENOMEM; +- goto err_no_mem; +- } ++ if (!dev) ++ return -ENOMEM; ++ + dev->vendor = vendor; + dev->adev = adev; + nmk_i2c_of_probe(np, dev); +@@ -995,30 +994,27 @@ static int nmk_i2c_probe(struct amba_device *adev, const struct amba_id *id) + + dev->virtbase = devm_ioremap(&adev->dev, adev->res.start, + resource_size(&adev->res)); +- if (!dev->virtbase) { +- ret = -ENOMEM; +- goto err_no_mem; +- } ++ if (!dev->virtbase) ++ return -ENOMEM; + + dev->irq = adev->irq[0]; + ret = devm_request_irq(&adev->dev, dev->irq, i2c_irq_handler, 0, + DRIVER_NAME, dev); + if (ret) { + dev_err(&adev->dev, "cannot claim the irq %d\n", dev->irq); +- goto err_no_mem; ++ return ret; + } + + dev->clk = devm_clk_get(&adev->dev, NULL); + if (IS_ERR(dev->clk)) { + dev_err(&adev->dev, "could not get i2c clock\n"); +- ret = PTR_ERR(dev->clk); +- goto err_no_mem; ++ return PTR_ERR(dev->clk); + } + + ret = clk_prepare_enable(dev->clk); + if (ret) { + dev_err(&adev->dev, "can't prepare_enable clock\n"); +- goto err_no_mem; ++ return ret; + } + + init_hw(dev); +@@ -1049,7 +1045,6 @@ static int nmk_i2c_probe(struct amba_device *adev, const struct amba_id *id) + + err_no_adap: + clk_disable_unprepare(dev->clk); +- err_no_mem: + + return ret; + } +-- +2.39.2 + diff --git a/queue-5.15/i2c-nomadik-use-devm_clk_get_enabled.patch b/queue-5.15/i2c-nomadik-use-devm_clk_get_enabled.patch new file mode 100644 index 00000000000..f62a85bba7e --- /dev/null +++ b/queue-5.15/i2c-nomadik-use-devm_clk_get_enabled.patch @@ -0,0 +1,76 @@ +From 497a487c66fefe6d04f96f9d4acc070d8689565f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 11 Jun 2023 03:37:00 +0200 +Subject: i2c: nomadik: Use devm_clk_get_enabled() + +From: Andi Shyti + +[ Upstream commit 9c7174db4cdd111e10d19eed5c36fd978a14c8a2 ] + +Replace the pair of functions, devm_clk_get() and +clk_prepare_enable(), with a single function +devm_clk_get_enabled(). + +Signed-off-by: Andi Shyti +Reviewed-by: Linus Walleij +Signed-off-by: Wolfram Sang +Stable-dep-of: 05f933d5f731 ("i2c: nomadik: Remove a useless call in the remove function") +Signed-off-by: Sasha Levin +--- + drivers/i2c/busses/i2c-nomadik.c | 18 +++--------------- + 1 file changed, 3 insertions(+), 15 deletions(-) + +diff --git a/drivers/i2c/busses/i2c-nomadik.c b/drivers/i2c/busses/i2c-nomadik.c +index 8b9577318388e..2141ba05dfece 100644 +--- a/drivers/i2c/busses/i2c-nomadik.c ++++ b/drivers/i2c/busses/i2c-nomadik.c +@@ -1005,18 +1005,12 @@ static int nmk_i2c_probe(struct amba_device *adev, const struct amba_id *id) + return ret; + } + +- dev->clk = devm_clk_get(&adev->dev, NULL); ++ dev->clk = devm_clk_get_enabled(&adev->dev, NULL); + if (IS_ERR(dev->clk)) { +- dev_err(&adev->dev, "could not get i2c clock\n"); ++ dev_err(&adev->dev, "could enable i2c clock\n"); + return PTR_ERR(dev->clk); + } + +- ret = clk_prepare_enable(dev->clk); +- if (ret) { +- dev_err(&adev->dev, "can't prepare_enable clock\n"); +- return ret; +- } +- + init_hw(dev); + + adap = &dev->adap; +@@ -1037,16 +1031,11 @@ static int nmk_i2c_probe(struct amba_device *adev, const struct amba_id *id) + + ret = i2c_add_adapter(adap); + if (ret) +- goto err_no_adap; ++ return ret; + + pm_runtime_put(&adev->dev); + + return 0; +- +- err_no_adap: +- clk_disable_unprepare(dev->clk); +- +- return ret; + } + + static void nmk_i2c_remove(struct amba_device *adev) +@@ -1060,7 +1049,6 @@ static void nmk_i2c_remove(struct amba_device *adev) + clear_all_interrupts(dev); + /* disable the controller */ + i2c_clr_bit(dev->virtbase + I2C_CR, I2C_CR_PE); +- clk_disable_unprepare(dev->clk); + release_mem_region(res->start, resource_size(res)); + } + +-- +2.39.2 + diff --git a/queue-5.15/io_uring-don-t-audit-the-capability-check-in-io_urin.patch b/queue-5.15/io_uring-don-t-audit-the-capability-check-in-io_urin.patch new file mode 100644 index 00000000000..fce195a39ed --- /dev/null +++ b/queue-5.15/io_uring-don-t-audit-the-capability-check-in-io_urin.patch @@ -0,0 +1,47 @@ +From 4b74f1cbdf97d18a5afa9ae0bcae7b211dbc1e02 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 18 Jul 2023 13:56:07 +0200 +Subject: io_uring: don't audit the capability check in io_uring_create() + +From: Ondrej Mosnacek + +[ Upstream commit 6adc2272aaaf84f34b652cf77f770c6fcc4b8336 ] + +The check being unconditional may lead to unwanted denials reported by +LSMs when a process has the capability granted by DAC, but denied by an +LSM. In the case of SELinux such denials are a problem, since they can't +be effectively filtered out via the policy and when not silenced, they +produce noise that may hide a true problem or an attack. + +Since not having the capability merely means that the created io_uring +context will be accounted against the current user's RLIMIT_MEMLOCK +limit, we can disable auditing of denials for this check by using +ns_capable_noaudit() instead of capable(). + +Fixes: 2b188cc1bb85 ("Add io_uring IO interface") +Link: https://bugzilla.redhat.com/show_bug.cgi?id=2193317 +Signed-off-by: Ondrej Mosnacek +Reviewed-by: Jeff Moyer +Link: https://lore.kernel.org/r/20230718115607.65652-1-omosnace@redhat.com +Signed-off-by: Jens Axboe +Signed-off-by: Sasha Levin +--- + io_uring/io_uring.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/io_uring/io_uring.c b/io_uring/io_uring.c +index d7f87157be9aa..f65c6811ede81 100644 +--- a/io_uring/io_uring.c ++++ b/io_uring/io_uring.c +@@ -10602,7 +10602,7 @@ static int io_uring_create(unsigned entries, struct io_uring_params *p, + if (!ctx) + return -ENOMEM; + ctx->compat = in_compat_syscall(); +- if (!capable(CAP_IPC_LOCK)) ++ if (!ns_capable_noaudit(&init_user_ns, CAP_IPC_LOCK)) + ctx->user = get_uid(current_user()); + + /* +-- +2.39.2 + diff --git a/queue-5.15/jbd2-fix-a-race-when-checking-checkpoint-buffer-busy.patch b/queue-5.15/jbd2-fix-a-race-when-checking-checkpoint-buffer-busy.patch new file mode 100644 index 00000000000..f169b4a44e3 --- /dev/null +++ b/queue-5.15/jbd2-fix-a-race-when-checking-checkpoint-buffer-busy.patch @@ -0,0 +1,150 @@ +From b756a018ae344b7a50133eec86185342030b7e89 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 6 Jun 2023 21:59:27 +0800 +Subject: jbd2: fix a race when checking checkpoint buffer busy + +From: Zhang Yi + +[ Upstream commit 46f881b5b1758dc4a35fba4a643c10717d0cf427 ] + +Before removing checkpoint buffer from the t_checkpoint_list, we have to +check both BH_Dirty and BH_Lock bits together to distinguish buffers +have not been or were being written back. But __cp_buffer_busy() checks +them separately, it first check lock state and then check dirty, the +window between these two checks could be raced by writing back +procedure, which locks buffer and clears buffer dirty before I/O +completes. So it cannot guarantee checkpointing buffers been written +back to disk if some error happens later. Finally, it may clean +checkpoint transactions and lead to inconsistent filesystem. + +jbd2_journal_forget() and __journal_try_to_free_buffer() also have the +same problem (journal_unmap_buffer() escape from this issue since it's +running under the buffer lock), so fix them through introducing a new +helper to try holding the buffer lock and remove really clean buffer. + +Link: https://bugzilla.kernel.org/show_bug.cgi?id=217490 +Cc: stable@vger.kernel.org +Suggested-by: Jan Kara +Signed-off-by: Zhang Yi +Reviewed-by: Jan Kara +Link: https://lore.kernel.org/r/20230606135928.434610-6-yi.zhang@huaweicloud.com +Signed-off-by: Theodore Ts'o +Signed-off-by: Sasha Levin +--- + fs/jbd2/checkpoint.c | 38 +++++++++++++++++++++++++++++++++++--- + fs/jbd2/transaction.c | 17 +++++------------ + include/linux/jbd2.h | 1 + + 3 files changed, 41 insertions(+), 15 deletions(-) + +diff --git a/fs/jbd2/checkpoint.c b/fs/jbd2/checkpoint.c +index ab72aeb766a74..fc6989e7a8c51 100644 +--- a/fs/jbd2/checkpoint.c ++++ b/fs/jbd2/checkpoint.c +@@ -376,11 +376,15 @@ static unsigned long journal_shrink_one_cp_list(struct journal_head *jh, + jh = next_jh; + next_jh = jh->b_cpnext; + +- if (!destroy && __cp_buffer_busy(jh)) +- continue; ++ if (destroy) { ++ ret = __jbd2_journal_remove_checkpoint(jh); ++ } else { ++ ret = jbd2_journal_try_remove_checkpoint(jh); ++ if (ret < 0) ++ continue; ++ } + + nr_freed++; +- ret = __jbd2_journal_remove_checkpoint(jh); + if (ret) { + *released = true; + break; +@@ -616,6 +620,34 @@ int __jbd2_journal_remove_checkpoint(struct journal_head *jh) + return 1; + } + ++/* ++ * Check the checkpoint buffer and try to remove it from the checkpoint ++ * list if it's clean. Returns -EBUSY if it is not clean, returns 1 if ++ * it frees the transaction, 0 otherwise. ++ * ++ * This function is called with j_list_lock held. ++ */ ++int jbd2_journal_try_remove_checkpoint(struct journal_head *jh) ++{ ++ struct buffer_head *bh = jh2bh(jh); ++ ++ if (!trylock_buffer(bh)) ++ return -EBUSY; ++ if (buffer_dirty(bh)) { ++ unlock_buffer(bh); ++ return -EBUSY; ++ } ++ unlock_buffer(bh); ++ ++ /* ++ * Buffer is clean and the IO has finished (we held the buffer ++ * lock) so the checkpoint is done. We can safely remove the ++ * buffer from this transaction. ++ */ ++ JBUFFER_TRACE(jh, "remove from checkpoint list"); ++ return __jbd2_journal_remove_checkpoint(jh); ++} ++ + /* + * journal_insert_checkpoint: put a committed buffer onto a checkpoint + * list so that we know when it is safe to clean the transaction out of +diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c +index ce4a5ccadeff4..62e68c5b8ec3d 100644 +--- a/fs/jbd2/transaction.c ++++ b/fs/jbd2/transaction.c +@@ -1775,8 +1775,7 @@ int jbd2_journal_forget(handle_t *handle, struct buffer_head *bh) + * Otherwise, if the buffer has been written to disk, + * it is safe to remove the checkpoint and drop it. + */ +- if (!buffer_dirty(bh)) { +- __jbd2_journal_remove_checkpoint(jh); ++ if (jbd2_journal_try_remove_checkpoint(jh) >= 0) { + spin_unlock(&journal->j_list_lock); + goto drop; + } +@@ -2103,20 +2102,14 @@ __journal_try_to_free_buffer(journal_t *journal, struct buffer_head *bh) + + jh = bh2jh(bh); + +- if (buffer_locked(bh) || buffer_dirty(bh)) +- goto out; +- + if (jh->b_next_transaction != NULL || jh->b_transaction != NULL) +- goto out; ++ return; + + spin_lock(&journal->j_list_lock); +- if (jh->b_cp_transaction != NULL) { +- /* written-back checkpointed metadata buffer */ +- JBUFFER_TRACE(jh, "remove from checkpoint list"); +- __jbd2_journal_remove_checkpoint(jh); +- } ++ /* Remove written-back checkpointed metadata buffer */ ++ if (jh->b_cp_transaction != NULL) ++ jbd2_journal_try_remove_checkpoint(jh); + spin_unlock(&journal->j_list_lock); +-out: + return; + } + +diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h +index e6cfbcde96f29..ade8a6d7acff9 100644 +--- a/include/linux/jbd2.h ++++ b/include/linux/jbd2.h +@@ -1441,6 +1441,7 @@ extern void jbd2_journal_commit_transaction(journal_t *); + void __jbd2_journal_clean_checkpoint_list(journal_t *journal, bool destroy); + unsigned long jbd2_journal_shrink_checkpoint_list(journal_t *journal, unsigned long *nr_to_scan); + int __jbd2_journal_remove_checkpoint(struct journal_head *); ++int jbd2_journal_try_remove_checkpoint(struct journal_head *jh); + void jbd2_journal_destroy_checkpoint(journal_t *journal); + void __jbd2_journal_insert_checkpoint(struct journal_head *, transaction_t *); + +-- +2.39.2 + diff --git a/queue-5.15/jbd2-fix-wrongly-judgement-for-buffer-head-removing-.patch b/queue-5.15/jbd2-fix-wrongly-judgement-for-buffer-head-removing-.patch new file mode 100644 index 00000000000..0ce4dd39366 --- /dev/null +++ b/queue-5.15/jbd2-fix-wrongly-judgement-for-buffer-head-removing-.patch @@ -0,0 +1,106 @@ +From 8ef166c955d5e1682826ea7a9cd405ad77cc5240 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 6 Jun 2023 21:59:26 +0800 +Subject: jbd2: Fix wrongly judgement for buffer head removing while doing + checkpoint + +From: Zhihao Cheng + +[ Upstream commit e34c8dd238d0c9368b746480f313055f5bab5040 ] + +Following process, + +jbd2_journal_commit_transaction +// there are several dirty buffer heads in transaction->t_checkpoint_list + P1 wb_workfn +jbd2_log_do_checkpoint + if (buffer_locked(bh)) // false + __block_write_full_page + trylock_buffer(bh) + test_clear_buffer_dirty(bh) + if (!buffer_dirty(bh)) + __jbd2_journal_remove_checkpoint(jh) + if (buffer_write_io_error(bh)) // false + >> bh IO error occurs << + jbd2_cleanup_journal_tail + __jbd2_update_log_tail + jbd2_write_superblock + // The bh won't be replayed in next mount. +, which could corrupt the ext4 image, fetch a reproducer in [Link]. + +Since writeback process clears buffer dirty after locking buffer head, +we can fix it by try locking buffer and check dirtiness while buffer is +locked, the buffer head can be removed if it is neither dirty nor locked. + +Link: https://bugzilla.kernel.org/show_bug.cgi?id=217490 +Fixes: 470decc613ab ("[PATCH] jbd2: initial copy of files from jbd") +Signed-off-by: Zhihao Cheng +Signed-off-by: Zhang Yi +Reviewed-by: Jan Kara +Link: https://lore.kernel.org/r/20230606135928.434610-5-yi.zhang@huaweicloud.com +Signed-off-by: Theodore Ts'o +Signed-off-by: Sasha Levin +--- + fs/jbd2/checkpoint.c | 32 +++++++++++++++++--------------- + 1 file changed, 17 insertions(+), 15 deletions(-) + +diff --git a/fs/jbd2/checkpoint.c b/fs/jbd2/checkpoint.c +index fe8bb031b7d7f..d2aba55833f92 100644 +--- a/fs/jbd2/checkpoint.c ++++ b/fs/jbd2/checkpoint.c +@@ -221,20 +221,6 @@ int jbd2_log_do_checkpoint(journal_t *journal) + jh = transaction->t_checkpoint_list; + bh = jh2bh(jh); + +- /* +- * The buffer may be writing back, or flushing out in the +- * last couple of cycles, or re-adding into a new transaction, +- * need to check it again until it's unlocked. +- */ +- if (buffer_locked(bh)) { +- get_bh(bh); +- spin_unlock(&journal->j_list_lock); +- wait_on_buffer(bh); +- /* the journal_head may have gone by now */ +- BUFFER_TRACE(bh, "brelse"); +- __brelse(bh); +- goto retry; +- } + if (jh->b_transaction != NULL) { + transaction_t *t = jh->b_transaction; + tid_t tid = t->t_tid; +@@ -269,7 +255,22 @@ int jbd2_log_do_checkpoint(journal_t *journal) + spin_lock(&journal->j_list_lock); + goto restart; + } +- if (!buffer_dirty(bh)) { ++ if (!trylock_buffer(bh)) { ++ /* ++ * The buffer is locked, it may be writing back, or ++ * flushing out in the last couple of cycles, or ++ * re-adding into a new transaction, need to check ++ * it again until it's unlocked. ++ */ ++ get_bh(bh); ++ spin_unlock(&journal->j_list_lock); ++ wait_on_buffer(bh); ++ /* the journal_head may have gone by now */ ++ BUFFER_TRACE(bh, "brelse"); ++ __brelse(bh); ++ goto retry; ++ } else if (!buffer_dirty(bh)) { ++ unlock_buffer(bh); + BUFFER_TRACE(bh, "remove from checkpoint"); + /* + * If the transaction was released or the checkpoint +@@ -279,6 +280,7 @@ int jbd2_log_do_checkpoint(journal_t *journal) + !transaction->t_checkpoint_list) + goto out; + } else { ++ unlock_buffer(bh); + /* + * We are about to write the buffer, it could be + * raced by some other transaction shrink or buffer +-- +2.39.2 + diff --git a/queue-5.15/jbd2-remove-journal_clean_one_cp_list.patch b/queue-5.15/jbd2-remove-journal_clean_one_cp_list.patch new file mode 100644 index 00000000000..7bdc682848a --- /dev/null +++ b/queue-5.15/jbd2-remove-journal_clean_one_cp_list.patch @@ -0,0 +1,235 @@ +From aecb975234f28cd552c2716b840cb4df901d3027 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 6 Jun 2023 21:59:25 +0800 +Subject: jbd2: remove journal_clean_one_cp_list() + +From: Zhang Yi + +[ Upstream commit b98dba273a0e47dbfade89c9af73c5b012a4eabb ] + +journal_clean_one_cp_list() and journal_shrink_one_cp_list() are almost +the same, so merge them into journal_shrink_one_cp_list(), remove the +nr_to_scan parameter, always scan and try to free the whole checkpoint +list. + +Signed-off-by: Zhang Yi +Reviewed-by: Jan Kara +Link: https://lore.kernel.org/r/20230606135928.434610-4-yi.zhang@huaweicloud.com +Signed-off-by: Theodore Ts'o +Stable-dep-of: 46f881b5b175 ("jbd2: fix a race when checking checkpoint buffer busy") +Signed-off-by: Sasha Levin +--- + fs/jbd2/checkpoint.c | 75 +++++++++---------------------------- + include/trace/events/jbd2.h | 12 ++---- + 2 files changed, 21 insertions(+), 66 deletions(-) + +diff --git a/fs/jbd2/checkpoint.c b/fs/jbd2/checkpoint.c +index c1f543e86170a..ab72aeb766a74 100644 +--- a/fs/jbd2/checkpoint.c ++++ b/fs/jbd2/checkpoint.c +@@ -349,50 +349,10 @@ int jbd2_cleanup_journal_tail(journal_t *journal) + + /* Checkpoint list management */ + +-/* +- * journal_clean_one_cp_list +- * +- * Find all the written-back checkpoint buffers in the given list and +- * release them. If 'destroy' is set, clean all buffers unconditionally. +- * +- * Called with j_list_lock held. +- * Returns 1 if we freed the transaction, 0 otherwise. +- */ +-static int journal_clean_one_cp_list(struct journal_head *jh, bool destroy) +-{ +- struct journal_head *last_jh; +- struct journal_head *next_jh = jh; +- +- if (!jh) +- return 0; +- +- last_jh = jh->b_cpprev; +- do { +- jh = next_jh; +- next_jh = jh->b_cpnext; +- +- if (!destroy && __cp_buffer_busy(jh)) +- return 0; +- +- if (__jbd2_journal_remove_checkpoint(jh)) +- return 1; +- /* +- * This function only frees up some memory +- * if possible so we dont have an obligation +- * to finish processing. Bail out if preemption +- * requested: +- */ +- if (need_resched()) +- return 0; +- } while (jh != last_jh); +- +- return 0; +-} +- + /* + * journal_shrink_one_cp_list + * +- * Find 'nr_to_scan' written-back checkpoint buffers in the given list ++ * Find all the written-back checkpoint buffers in the given list + * and try to release them. If the whole transaction is released, set + * the 'released' parameter. Return the number of released checkpointed + * buffers. +@@ -400,15 +360,15 @@ static int journal_clean_one_cp_list(struct journal_head *jh, bool destroy) + * Called with j_list_lock held. + */ + static unsigned long journal_shrink_one_cp_list(struct journal_head *jh, +- unsigned long *nr_to_scan, +- bool *released) ++ bool destroy, bool *released) + { + struct journal_head *last_jh; + struct journal_head *next_jh = jh; + unsigned long nr_freed = 0; + int ret; + +- if (!jh || *nr_to_scan == 0) ++ *released = false; ++ if (!jh) + return 0; + + last_jh = jh->b_cpprev; +@@ -416,8 +376,7 @@ static unsigned long journal_shrink_one_cp_list(struct journal_head *jh, + jh = next_jh; + next_jh = jh->b_cpnext; + +- (*nr_to_scan)--; +- if (__cp_buffer_busy(jh)) ++ if (!destroy && __cp_buffer_busy(jh)) + continue; + + nr_freed++; +@@ -429,7 +388,7 @@ static unsigned long journal_shrink_one_cp_list(struct journal_head *jh, + + if (need_resched()) + break; +- } while (jh != last_jh && *nr_to_scan); ++ } while (jh != last_jh); + + return nr_freed; + } +@@ -447,11 +406,11 @@ unsigned long jbd2_journal_shrink_checkpoint_list(journal_t *journal, + unsigned long *nr_to_scan) + { + transaction_t *transaction, *last_transaction, *next_transaction; +- bool released; ++ bool __maybe_unused released; + tid_t first_tid = 0, last_tid = 0, next_tid = 0; + tid_t tid = 0; + unsigned long nr_freed = 0; +- unsigned long nr_scanned = *nr_to_scan; ++ unsigned long freed; + + again: + spin_lock(&journal->j_list_lock); +@@ -480,10 +439,11 @@ unsigned long jbd2_journal_shrink_checkpoint_list(journal_t *journal, + transaction = next_transaction; + next_transaction = transaction->t_cpnext; + tid = transaction->t_tid; +- released = false; + +- nr_freed += journal_shrink_one_cp_list(transaction->t_checkpoint_list, +- nr_to_scan, &released); ++ freed = journal_shrink_one_cp_list(transaction->t_checkpoint_list, ++ false, &released); ++ nr_freed += freed; ++ (*nr_to_scan) -= min(*nr_to_scan, freed); + if (*nr_to_scan == 0) + break; + if (need_resched() || spin_needbreak(&journal->j_list_lock)) +@@ -504,9 +464,8 @@ unsigned long jbd2_journal_shrink_checkpoint_list(journal_t *journal, + if (*nr_to_scan && next_tid) + goto again; + out: +- nr_scanned -= *nr_to_scan; + trace_jbd2_shrink_checkpoint_list(journal, first_tid, tid, last_tid, +- nr_freed, nr_scanned, next_tid); ++ nr_freed, next_tid); + + return nr_freed; + } +@@ -522,7 +481,7 @@ unsigned long jbd2_journal_shrink_checkpoint_list(journal_t *journal, + void __jbd2_journal_clean_checkpoint_list(journal_t *journal, bool destroy) + { + transaction_t *transaction, *last_transaction, *next_transaction; +- int ret; ++ bool released; + + transaction = journal->j_checkpoint_transactions; + if (!transaction) +@@ -533,8 +492,8 @@ void __jbd2_journal_clean_checkpoint_list(journal_t *journal, bool destroy) + do { + transaction = next_transaction; + next_transaction = transaction->t_cpnext; +- ret = journal_clean_one_cp_list(transaction->t_checkpoint_list, +- destroy); ++ journal_shrink_one_cp_list(transaction->t_checkpoint_list, ++ destroy, &released); + /* + * This function only frees up some memory if possible so we + * dont have an obligation to finish processing. Bail out if +@@ -547,7 +506,7 @@ void __jbd2_journal_clean_checkpoint_list(journal_t *journal, bool destroy) + * avoids pointless scanning of transactions which still + * weren't checkpointed. + */ +- if (!ret) ++ if (!released) + return; + } while (transaction != last_transaction); + } +diff --git a/include/trace/events/jbd2.h b/include/trace/events/jbd2.h +index 29414288ea3e0..34ce197bd76e0 100644 +--- a/include/trace/events/jbd2.h ++++ b/include/trace/events/jbd2.h +@@ -462,11 +462,9 @@ TRACE_EVENT(jbd2_shrink_scan_exit, + TRACE_EVENT(jbd2_shrink_checkpoint_list, + + TP_PROTO(journal_t *journal, tid_t first_tid, tid_t tid, tid_t last_tid, +- unsigned long nr_freed, unsigned long nr_scanned, +- tid_t next_tid), ++ unsigned long nr_freed, tid_t next_tid), + +- TP_ARGS(journal, first_tid, tid, last_tid, nr_freed, +- nr_scanned, next_tid), ++ TP_ARGS(journal, first_tid, tid, last_tid, nr_freed, next_tid), + + TP_STRUCT__entry( + __field(dev_t, dev) +@@ -474,7 +472,6 @@ TRACE_EVENT(jbd2_shrink_checkpoint_list, + __field(tid_t, tid) + __field(tid_t, last_tid) + __field(unsigned long, nr_freed) +- __field(unsigned long, nr_scanned) + __field(tid_t, next_tid) + ), + +@@ -484,15 +481,14 @@ TRACE_EVENT(jbd2_shrink_checkpoint_list, + __entry->tid = tid; + __entry->last_tid = last_tid; + __entry->nr_freed = nr_freed; +- __entry->nr_scanned = nr_scanned; + __entry->next_tid = next_tid; + ), + + TP_printk("dev %d,%d shrink transaction %u-%u(%u) freed %lu " +- "scanned %lu next transaction %u", ++ "next transaction %u", + MAJOR(__entry->dev), MINOR(__entry->dev), + __entry->first_tid, __entry->tid, __entry->last_tid, +- __entry->nr_freed, __entry->nr_scanned, __entry->next_tid) ++ __entry->nr_freed, __entry->next_tid) + ); + + #endif /* _TRACE_JBD2_H */ +-- +2.39.2 + diff --git a/queue-5.15/jbd2-remove-t_checkpoint_io_list.patch b/queue-5.15/jbd2-remove-t_checkpoint_io_list.patch new file mode 100644 index 00000000000..a399ebafb8c --- /dev/null +++ b/queue-5.15/jbd2-remove-t_checkpoint_io_list.patch @@ -0,0 +1,146 @@ +From 92d4d5454f0734d09f34beaae5f86cf3dcc3087f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 6 Jun 2023 21:59:24 +0800 +Subject: jbd2: remove t_checkpoint_io_list + +From: Zhang Yi + +[ Upstream commit be22255360f80d3af789daad00025171a65424a5 ] + +Since t_checkpoint_io_list was stop using in jbd2_log_do_checkpoint() +now, it's time to remove the whole t_checkpoint_io_list logic. + +Signed-off-by: Zhang Yi +Reviewed-by: Jan Kara +Link: https://lore.kernel.org/r/20230606135928.434610-3-yi.zhang@huaweicloud.com +Signed-off-by: Theodore Ts'o +Stable-dep-of: 46f881b5b175 ("jbd2: fix a race when checking checkpoint buffer busy") +Signed-off-by: Sasha Levin +--- + fs/jbd2/checkpoint.c | 42 ++---------------------------------------- + fs/jbd2/commit.c | 3 +-- + include/linux/jbd2.h | 6 ------ + 3 files changed, 3 insertions(+), 48 deletions(-) + +diff --git a/fs/jbd2/checkpoint.c b/fs/jbd2/checkpoint.c +index d2aba55833f92..c1f543e86170a 100644 +--- a/fs/jbd2/checkpoint.c ++++ b/fs/jbd2/checkpoint.c +@@ -27,7 +27,7 @@ + * + * Called with j_list_lock held. + */ +-static inline void __buffer_unlink_first(struct journal_head *jh) ++static inline void __buffer_unlink(struct journal_head *jh) + { + transaction_t *transaction = jh->b_cp_transaction; + +@@ -40,23 +40,6 @@ static inline void __buffer_unlink_first(struct journal_head *jh) + } + } + +-/* +- * Unlink a buffer from a transaction checkpoint(io) list. +- * +- * Called with j_list_lock held. +- */ +-static inline void __buffer_unlink(struct journal_head *jh) +-{ +- transaction_t *transaction = jh->b_cp_transaction; +- +- __buffer_unlink_first(jh); +- if (transaction->t_checkpoint_io_list == jh) { +- transaction->t_checkpoint_io_list = jh->b_cpnext; +- if (transaction->t_checkpoint_io_list == jh) +- transaction->t_checkpoint_io_list = NULL; +- } +-} +- + /* + * Check a checkpoint buffer could be release or not. + * +@@ -505,15 +488,6 @@ unsigned long jbd2_journal_shrink_checkpoint_list(journal_t *journal, + break; + if (need_resched() || spin_needbreak(&journal->j_list_lock)) + break; +- if (released) +- continue; +- +- nr_freed += journal_shrink_one_cp_list(transaction->t_checkpoint_io_list, +- nr_to_scan, &released); +- if (*nr_to_scan == 0) +- break; +- if (need_resched() || spin_needbreak(&journal->j_list_lock)) +- break; + } while (transaction != last_transaction); + + if (transaction != last_transaction) { +@@ -568,17 +542,6 @@ void __jbd2_journal_clean_checkpoint_list(journal_t *journal, bool destroy) + */ + if (need_resched()) + return; +- if (ret) +- continue; +- /* +- * It is essential that we are as careful as in the case of +- * t_checkpoint_list with removing the buffer from the list as +- * we can possibly see not yet submitted buffers on io_list +- */ +- ret = journal_clean_one_cp_list(transaction-> +- t_checkpoint_io_list, destroy); +- if (need_resched()) +- return; + /* + * Stop scanning if we couldn't free the transaction. This + * avoids pointless scanning of transactions which still +@@ -663,7 +626,7 @@ int __jbd2_journal_remove_checkpoint(struct journal_head *jh) + jbd2_journal_put_journal_head(jh); + + /* Is this transaction empty? */ +- if (transaction->t_checkpoint_list || transaction->t_checkpoint_io_list) ++ if (transaction->t_checkpoint_list) + return 0; + + /* +@@ -755,7 +718,6 @@ void __jbd2_journal_drop_transaction(journal_t *journal, transaction_t *transact + J_ASSERT(transaction->t_forget == NULL); + J_ASSERT(transaction->t_shadow_list == NULL); + J_ASSERT(transaction->t_checkpoint_list == NULL); +- J_ASSERT(transaction->t_checkpoint_io_list == NULL); + J_ASSERT(atomic_read(&transaction->t_updates) == 0); + J_ASSERT(journal->j_committing_transaction != transaction); + J_ASSERT(journal->j_running_transaction != transaction); +diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c +index ac328e3321242..20294c1bbeab7 100644 +--- a/fs/jbd2/commit.c ++++ b/fs/jbd2/commit.c +@@ -1184,8 +1184,7 @@ void jbd2_journal_commit_transaction(journal_t *journal) + spin_lock(&journal->j_list_lock); + commit_transaction->t_state = T_FINISHED; + /* Check if the transaction can be dropped now that we are finished */ +- if (commit_transaction->t_checkpoint_list == NULL && +- commit_transaction->t_checkpoint_io_list == NULL) { ++ if (commit_transaction->t_checkpoint_list == NULL) { + __jbd2_journal_drop_transaction(journal, commit_transaction); + jbd2_journal_free_transaction(commit_transaction); + } +diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h +index d63b8106796e2..e6cfbcde96f29 100644 +--- a/include/linux/jbd2.h ++++ b/include/linux/jbd2.h +@@ -626,12 +626,6 @@ struct transaction_s + */ + struct journal_head *t_checkpoint_list; + +- /* +- * Doubly-linked circular list of all buffers submitted for IO while +- * checkpointing. [j_list_lock] +- */ +- struct journal_head *t_checkpoint_io_list; +- + /* + * Doubly-linked circular list of metadata buffers being + * shadowed by log IO. The IO buffers on the iobuf list and +-- +2.39.2 + diff --git a/queue-5.15/ksmbd-remove-internal.h-include.patch b/queue-5.15/ksmbd-remove-internal.h-include.patch new file mode 100644 index 00000000000..54575c1eca0 --- /dev/null +++ b/queue-5.15/ksmbd-remove-internal.h-include.patch @@ -0,0 +1,66 @@ +From d9c75a1623fdb440b59aae1d3bc66d6a49841d68 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 16 Mar 2023 07:34:33 +0900 +Subject: ksmbd: remove internal.h include + +From: Namjae Jeon + +[ Upstream commit 211db0ac9e3dc6c46f2dd53395b34d76af929faf ] + +Since vfs_path_lookup is exported, It should not be internal. +Move vfs_path_lookup prototype in internal.h to linux/namei.h. + +Suggested-by: Al Viro +Reviewed-by: Christian Brauner +Signed-off-by: Namjae Jeon +Signed-off-by: Al Viro +Stable-dep-of: df9d70c18616 ("cifs: if deferred close is disabled then close files immediately") +Signed-off-by: Sasha Levin +--- + fs/internal.h | 2 -- + fs/ksmbd/vfs.c | 2 -- + include/linux/namei.h | 2 ++ + 3 files changed, 2 insertions(+), 4 deletions(-) + +diff --git a/fs/internal.h b/fs/internal.h +index ceb154583a3c4..1ff8cfc94467b 100644 +--- a/fs/internal.h ++++ b/fs/internal.h +@@ -58,8 +58,6 @@ extern int finish_clean_context(struct fs_context *fc); + */ + extern int filename_lookup(int dfd, struct filename *name, unsigned flags, + struct path *path, struct path *root); +-extern int vfs_path_lookup(struct dentry *, struct vfsmount *, +- const char *, unsigned int, struct path *); + int do_rmdir(int dfd, struct filename *name); + int do_unlinkat(int dfd, struct filename *name); + int may_linkat(struct user_namespace *mnt_userns, struct path *link); +diff --git a/fs/ksmbd/vfs.c b/fs/ksmbd/vfs.c +index 52cc6a9627ed7..f76acd83c2944 100644 +--- a/fs/ksmbd/vfs.c ++++ b/fs/ksmbd/vfs.c +@@ -19,8 +19,6 @@ + #include + #include + +-#include "../internal.h" /* for vfs_path_lookup */ +- + #include "glob.h" + #include "oplock.h" + #include "connection.h" +diff --git a/include/linux/namei.h b/include/linux/namei.h +index caeb08a98536c..40c693525f796 100644 +--- a/include/linux/namei.h ++++ b/include/linux/namei.h +@@ -63,6 +63,8 @@ extern struct dentry *kern_path_create(int, const char *, struct path *, unsigne + extern struct dentry *user_path_create(int, const char __user *, struct path *, unsigned int); + extern void done_path_create(struct path *, struct dentry *); + extern struct dentry *kern_path_locked(const char *, struct path *); ++int vfs_path_lookup(struct dentry *, struct vfsmount *, const char *, ++ unsigned int, struct path *); + + extern struct dentry *try_lookup_one_len(const char *, struct dentry *, int); + extern struct dentry *lookup_one_len(const char *, struct dentry *, int); +-- +2.39.2 + diff --git a/queue-5.15/kvm-s390-pv-fix-index-value-of-replaced-asce.patch b/queue-5.15/kvm-s390-pv-fix-index-value-of-replaced-asce.patch new file mode 100644 index 00000000000..dad26695f7d --- /dev/null +++ b/queue-5.15/kvm-s390-pv-fix-index-value-of-replaced-asce.patch @@ -0,0 +1,46 @@ +From b295b7e4014dd96e83bfd9f8778f82dd01044ef5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Jul 2023 13:19:37 +0200 +Subject: KVM: s390: pv: fix index value of replaced ASCE +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Claudio Imbrenda + +[ Upstream commit c2fceb59bbda16468bda82b002383bff59de89ab ] + +The index field of the struct page corresponding to a guest ASCE should +be 0. When replacing the ASCE in s390_replace_asce(), the index of the +new ASCE should also be set to 0. + +Having the wrong index might lead to the wrong addresses being passed +around when notifying pte invalidations, and eventually to validity +intercepts (VM crash) if the prefix gets unmapped and the notifier gets +called with the wrong address. + +Reviewed-by: Philippe Mathieu-Daudé +Fixes: faa2f72cb356 ("KVM: s390: pv: leak the topmost page table when destroy fails") +Reviewed-by: Janosch Frank +Signed-off-by: Claudio Imbrenda +Message-ID: <20230705111937.33472-3-imbrenda@linux.ibm.com> +Signed-off-by: Sasha Levin +--- + arch/s390/mm/gmap.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/arch/s390/mm/gmap.c b/arch/s390/mm/gmap.c +index ff40bf92db43a..a2c872de29a66 100644 +--- a/arch/s390/mm/gmap.c ++++ b/arch/s390/mm/gmap.c +@@ -2791,6 +2791,7 @@ int s390_replace_asce(struct gmap *gmap) + page = alloc_pages(GFP_KERNEL_ACCOUNT, CRST_ALLOC_ORDER); + if (!page) + return -ENOMEM; ++ page->index = 0; + table = page_to_virt(page); + memcpy(table, gmap->table, 1UL << (CRST_ALLOC_ORDER + PAGE_SHIFT)); + +-- +2.39.2 + diff --git a/queue-5.15/n_tty-rename-tail-to-old_tail-in-n_tty_read.patch b/queue-5.15/n_tty-rename-tail-to-old_tail-in-n_tty_read.patch new file mode 100644 index 00000000000..ebea0c06eb0 --- /dev/null +++ b/queue-5.15/n_tty-rename-tail-to-old_tail-in-n_tty_read.patch @@ -0,0 +1,60 @@ +From 46947742388959c672d059772208ccb938fef065 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 11 Nov 2022 16:25:02 +0200 +Subject: n_tty: Rename tail to old_tail in n_tty_read() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Ilpo Järvinen + +[ Upstream commit 947d66b68f3c4e7cf8f3f3500807b9d2a0de28ce ] + +The local tail variable in n_tty_read() is used for one purpose, it +keeps the old tail. Thus, rename it appropriately to improve code +readability. + +Signed-off-by: Ilpo Järvinen +Reviewed-by: Jiri Slaby +Link: https://lore.kernel.org/r/22b37499-ff9a-7fc1-f6e0-58411328d122@linux.intel.com +Signed-off-by: Greg Kroah-Hartman +Stable-dep-of: 4903fde8047a ("tty: fix hang on tty device with no_room set") +Signed-off-by: Sasha Levin +--- + drivers/tty/n_tty.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c +index 891036bd9f897..8f57448e1ce46 100644 +--- a/drivers/tty/n_tty.c ++++ b/drivers/tty/n_tty.c +@@ -2100,7 +2100,7 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file, + ssize_t retval = 0; + long timeout; + bool packet; +- size_t tail; ++ size_t old_tail; + + /* + * Is this a continuation of a read started earler? +@@ -2163,7 +2163,7 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file, + } + + packet = tty->ctrl.packet; +- tail = ldata->read_tail; ++ old_tail = ldata->read_tail; + + add_wait_queue(&tty->read_wait, &wait); + while (nr) { +@@ -2252,7 +2252,7 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file, + if (time) + timeout = time; + } +- if (tail != ldata->read_tail) ++ if (old_tail != ldata->read_tail) + n_tty_kick_worker(tty); + up_read(&tty->termios_rwsem); + +-- +2.39.2 + diff --git a/queue-5.15/pci-aspm-avoid-link-retraining-race.patch b/queue-5.15/pci-aspm-avoid-link-retraining-race.patch new file mode 100644 index 00000000000..00e88dece3e --- /dev/null +++ b/queue-5.15/pci-aspm-avoid-link-retraining-race.patch @@ -0,0 +1,64 @@ +From e8d78a001d6cd99367d133ad691f99306ade7ae0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 2 May 2023 11:39:23 +0300 +Subject: PCI/ASPM: Avoid link retraining race +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Ilpo Järvinen + +[ Upstream commit e7e39756363ad5bd83ddeae1063193d0f13870fd ] + +PCIe r6.0.1, sec 7.5.3.7, recommends setting the link control parameters, +then waiting for the Link Training bit to be clear before setting the +Retrain Link bit. + +This avoids a race where the LTSSM may not use the updated parameters if it +is already in the midst of link training because of other normal link +activity. + +Wait for the Link Training bit to be clear before toggling the Retrain Link +bit to ensure that the LTSSM uses the updated link control parameters. + +[bhelgaas: commit log, return 0 (success)/-ETIMEDOUT instead of bool for +both pcie_wait_for_retrain() and the existing pcie_retrain_link()] +Suggested-by: Lukas Wunner +Fixes: 7d715a6c1ae5 ("PCI: add PCI Express ASPM support") +Link: https://lore.kernel.org/r/20230502083923.34562-1-ilpo.jarvinen@linux.intel.com +Signed-off-by: Ilpo Järvinen +Signed-off-by: Bjorn Helgaas +Reviewed-by: Lukas Wunner +Cc: stable@vger.kernel.org +Signed-off-by: Sasha Levin +--- + drivers/pci/pcie/aspm.c | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c +index 5e09cbb563366..3078de668f911 100644 +--- a/drivers/pci/pcie/aspm.c ++++ b/drivers/pci/pcie/aspm.c +@@ -212,8 +212,19 @@ static int pcie_wait_for_retrain(struct pci_dev *pdev) + static int pcie_retrain_link(struct pcie_link_state *link) + { + struct pci_dev *parent = link->pdev; ++ int rc; + u16 reg16; + ++ /* ++ * Ensure the updated LNKCTL parameters are used during link ++ * training by checking that there is no ongoing link training to ++ * avoid LTSSM race as recommended in Implementation Note at the ++ * end of PCIe r6.0.1 sec 7.5.3.7. ++ */ ++ rc = pcie_wait_for_retrain(parent); ++ if (rc) ++ return rc; ++ + pcie_capability_read_word(parent, PCI_EXP_LNKCTL, ®16); + reg16 |= PCI_EXP_LNKCTL_RL; + pcie_capability_write_word(parent, PCI_EXP_LNKCTL, reg16); +-- +2.39.2 + diff --git a/queue-5.15/pci-aspm-factor-out-pcie_wait_for_retrain.patch b/queue-5.15/pci-aspm-factor-out-pcie_wait_for_retrain.patch new file mode 100644 index 00000000000..96a97905545 --- /dev/null +++ b/queue-5.15/pci-aspm-factor-out-pcie_wait_for_retrain.patch @@ -0,0 +1,79 @@ +From 36264db8f61aace836eefc44d4b4ce6f14df5392 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 20 Jun 2023 14:49:33 -0500 +Subject: PCI/ASPM: Factor out pcie_wait_for_retrain() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Ilpo Järvinen + +[ Upstream commit 9c7f136433d26592cb4d9cd00b4e15c33d9797c6 ] + +Factor pcie_wait_for_retrain() out from pcie_retrain_link(). No functional +change intended. + +[bhelgaas: split out from +https: //lore.kernel.org/r/20230502083923.34562-1-ilpo.jarvinen@linux.intel.com] +Signed-off-by: Ilpo Järvinen +Signed-off-by: Bjorn Helgaas +Stable-dep-of: e7e39756363a ("PCI/ASPM: Avoid link retraining race") +Signed-off-by: Sasha Levin +--- + drivers/pci/pcie/aspm.c | 30 ++++++++++++++++++------------ + 1 file changed, 18 insertions(+), 12 deletions(-) + +diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c +index e7f742ff31c3c..5e09cbb563366 100644 +--- a/drivers/pci/pcie/aspm.c ++++ b/drivers/pci/pcie/aspm.c +@@ -192,10 +192,26 @@ static void pcie_clkpm_cap_init(struct pcie_link_state *link, int blacklist) + link->clkpm_disable = blacklist ? 1 : 0; + } + ++static int pcie_wait_for_retrain(struct pci_dev *pdev) ++{ ++ unsigned long end_jiffies; ++ u16 reg16; ++ ++ /* Wait for Link Training to be cleared by hardware */ ++ end_jiffies = jiffies + LINK_RETRAIN_TIMEOUT; ++ do { ++ pcie_capability_read_word(pdev, PCI_EXP_LNKSTA, ®16); ++ if (!(reg16 & PCI_EXP_LNKSTA_LT)) ++ return 0; ++ msleep(1); ++ } while (time_before(jiffies, end_jiffies)); ++ ++ return -ETIMEDOUT; ++} ++ + static int pcie_retrain_link(struct pcie_link_state *link) + { + struct pci_dev *parent = link->pdev; +- unsigned long end_jiffies; + u16 reg16; + + pcie_capability_read_word(parent, PCI_EXP_LNKCTL, ®16); +@@ -211,17 +227,7 @@ static int pcie_retrain_link(struct pcie_link_state *link) + pcie_capability_write_word(parent, PCI_EXP_LNKCTL, reg16); + } + +- /* Wait for link training end. Break out after waiting for timeout */ +- end_jiffies = jiffies + LINK_RETRAIN_TIMEOUT; +- do { +- pcie_capability_read_word(parent, PCI_EXP_LNKSTA, ®16); +- if (!(reg16 & PCI_EXP_LNKSTA_LT)) +- break; +- msleep(1); +- } while (time_before(jiffies, end_jiffies)); +- if (reg16 & PCI_EXP_LNKSTA_LT) +- return -ETIMEDOUT; +- return 0; ++ return pcie_wait_for_retrain(parent); + } + + /* +-- +2.39.2 + diff --git a/queue-5.15/pci-aspm-return-0-or-etimedout-from-pcie_retrain_lin.patch b/queue-5.15/pci-aspm-return-0-or-etimedout-from-pcie_retrain_lin.patch new file mode 100644 index 00000000000..5fa4b88af9b --- /dev/null +++ b/queue-5.15/pci-aspm-return-0-or-etimedout-from-pcie_retrain_lin.patch @@ -0,0 +1,72 @@ +From 786317a4aaccf786bfb06a38f742fc49680c4ae3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 20 Jun 2023 14:44:55 -0500 +Subject: PCI/ASPM: Return 0 or -ETIMEDOUT from pcie_retrain_link() + +From: Bjorn Helgaas + +[ Upstream commit f5297a01ee805d7fa569d288ed65fc0f9ac9b03d ] + +"pcie_retrain_link" is not a question with a true/false answer, so "bool" +isn't quite the right return type. Return 0 for success or -ETIMEDOUT if +the retrain failed. No functional change intended. + +[bhelgaas: based on Ilpo's patch below] +Link: https://lore.kernel.org/r/20230502083923.34562-1-ilpo.jarvinen@linux.intel.com +Signed-off-by: Bjorn Helgaas +Stable-dep-of: e7e39756363a ("PCI/ASPM: Avoid link retraining race") +Signed-off-by: Sasha Levin +--- + drivers/pci/pcie/aspm.c | 20 +++++++++++--------- + 1 file changed, 11 insertions(+), 9 deletions(-) + +diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c +index c58294f53fcd1..e7f742ff31c3c 100644 +--- a/drivers/pci/pcie/aspm.c ++++ b/drivers/pci/pcie/aspm.c +@@ -192,7 +192,7 @@ static void pcie_clkpm_cap_init(struct pcie_link_state *link, int blacklist) + link->clkpm_disable = blacklist ? 1 : 0; + } + +-static bool pcie_retrain_link(struct pcie_link_state *link) ++static int pcie_retrain_link(struct pcie_link_state *link) + { + struct pci_dev *parent = link->pdev; + unsigned long end_jiffies; +@@ -219,7 +219,9 @@ static bool pcie_retrain_link(struct pcie_link_state *link) + break; + msleep(1); + } while (time_before(jiffies, end_jiffies)); +- return !(reg16 & PCI_EXP_LNKSTA_LT); ++ if (reg16 & PCI_EXP_LNKSTA_LT) ++ return -ETIMEDOUT; ++ return 0; + } + + /* +@@ -288,15 +290,15 @@ static void pcie_aspm_configure_common_clock(struct pcie_link_state *link) + reg16 &= ~PCI_EXP_LNKCTL_CCC; + pcie_capability_write_word(parent, PCI_EXP_LNKCTL, reg16); + +- if (pcie_retrain_link(link)) +- return; ++ if (pcie_retrain_link(link)) { + +- /* Training failed. Restore common clock configurations */ +- pci_err(parent, "ASPM: Could not configure common clock\n"); +- list_for_each_entry(child, &linkbus->devices, bus_list) +- pcie_capability_write_word(child, PCI_EXP_LNKCTL, ++ /* Training failed. Restore common clock configurations */ ++ pci_err(parent, "ASPM: Could not configure common clock\n"); ++ list_for_each_entry(child, &linkbus->devices, bus_list) ++ pcie_capability_write_word(child, PCI_EXP_LNKCTL, + child_reg[PCI_FUNC(child->devfn)]); +- pcie_capability_write_word(parent, PCI_EXP_LNKCTL, parent_reg); ++ pcie_capability_write_word(parent, PCI_EXP_LNKCTL, parent_reg); ++ } + } + + /* Convert L0s latency encoding to ns */ +-- +2.39.2 + diff --git a/queue-5.15/pci-rockchip-don-t-advertise-msi-x-in-pcie-capabilit.patch b/queue-5.15/pci-rockchip-don-t-advertise-msi-x-in-pcie-capabilit.patch new file mode 100644 index 00000000000..1e5f3fd89a6 --- /dev/null +++ b/queue-5.15/pci-rockchip-don-t-advertise-msi-x-in-pcie-capabilit.patch @@ -0,0 +1,103 @@ +From 30c4c68808b06e28cf438684c3c0d54ab8a181b4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 18 Apr 2023 09:46:57 +0200 +Subject: PCI: rockchip: Don't advertise MSI-X in PCIe capabilities + +From: Rick Wertenbroek + +[ Upstream commit a52587e0bee14cbeeadf48a24013828cb04b8df8 ] + +The RK3399 PCIe endpoint controller cannot generate MSI-X IRQs. +This is documented in the RK3399 technical reference manual (TRM) +section 17.5.9 "Interrupt Support". + +MSI-X capability should therefore not be advertised. Remove the +MSI-X capability by editing the capability linked-list. The +previous entry is the MSI capability, therefore get the next +entry from the MSI-X capability entry and set it as next entry +for the MSI capability. This in effect removes MSI-X from the list. + +Linked list before : MSI cap -> MSI-X cap -> PCIe Device cap -> ... +Linked list now : MSI cap -> PCIe Device cap -> ... + +Link: https://lore.kernel.org/r/20230418074700.1083505-11-rick.wertenbroek@gmail.com +Fixes: cf590b078391 ("PCI: rockchip: Add EP driver for Rockchip PCIe controller") +Tested-by: Damien Le Moal +Signed-off-by: Rick Wertenbroek +Signed-off-by: Lorenzo Pieralisi +Reviewed-by: Damien Le Moal +Cc: stable@vger.kernel.org +Signed-off-by: Sasha Levin +--- + drivers/pci/controller/pcie-rockchip-ep.c | 24 +++++++++++++++++++++++ + drivers/pci/controller/pcie-rockchip.h | 5 +++++ + 2 files changed, 29 insertions(+) + +diff --git a/drivers/pci/controller/pcie-rockchip-ep.c b/drivers/pci/controller/pcie-rockchip-ep.c +index 3d6f828d29fc2..0af0e965fb57e 100644 +--- a/drivers/pci/controller/pcie-rockchip-ep.c ++++ b/drivers/pci/controller/pcie-rockchip-ep.c +@@ -508,6 +508,7 @@ static int rockchip_pcie_ep_probe(struct platform_device *pdev) + size_t max_regions; + struct pci_epc_mem_window *windows = NULL; + int err, i; ++ u32 cfg_msi, cfg_msix_cp; + + ep = devm_kzalloc(dev, sizeof(*ep), GFP_KERNEL); + if (!ep) +@@ -583,6 +584,29 @@ static int rockchip_pcie_ep_probe(struct platform_device *pdev) + + ep->irq_pci_addr = ROCKCHIP_PCIE_EP_DUMMY_IRQ_ADDR; + ++ /* ++ * MSI-X is not supported but the controller still advertises the MSI-X ++ * capability by default, which can lead to the Root Complex side ++ * allocating MSI-X vectors which cannot be used. Avoid this by skipping ++ * the MSI-X capability entry in the PCIe capabilities linked-list: get ++ * the next pointer from the MSI-X entry and set that in the MSI ++ * capability entry (which is the previous entry). This way the MSI-X ++ * entry is skipped (left out of the linked-list) and not advertised. ++ */ ++ cfg_msi = rockchip_pcie_read(rockchip, PCIE_EP_CONFIG_BASE + ++ ROCKCHIP_PCIE_EP_MSI_CTRL_REG); ++ ++ cfg_msi &= ~ROCKCHIP_PCIE_EP_MSI_CP1_MASK; ++ ++ cfg_msix_cp = rockchip_pcie_read(rockchip, PCIE_EP_CONFIG_BASE + ++ ROCKCHIP_PCIE_EP_MSIX_CAP_REG) & ++ ROCKCHIP_PCIE_EP_MSIX_CAP_CP_MASK; ++ ++ cfg_msi |= cfg_msix_cp; ++ ++ rockchip_pcie_write(rockchip, cfg_msi, ++ PCIE_EP_CONFIG_BASE + ROCKCHIP_PCIE_EP_MSI_CTRL_REG); ++ + rockchip_pcie_write(rockchip, PCIE_CLIENT_CONF_ENABLE, + PCIE_CLIENT_CONFIG); + +diff --git a/drivers/pci/controller/pcie-rockchip.h b/drivers/pci/controller/pcie-rockchip.h +index 498a40251d0be..88e2bf65e433a 100644 +--- a/drivers/pci/controller/pcie-rockchip.h ++++ b/drivers/pci/controller/pcie-rockchip.h +@@ -228,6 +228,8 @@ + #define ROCKCHIP_PCIE_EP_CMD_STATUS 0x4 + #define ROCKCHIP_PCIE_EP_CMD_STATUS_IS BIT(19) + #define ROCKCHIP_PCIE_EP_MSI_CTRL_REG 0x90 ++#define ROCKCHIP_PCIE_EP_MSI_CP1_OFFSET 8 ++#define ROCKCHIP_PCIE_EP_MSI_CP1_MASK GENMASK(15, 8) + #define ROCKCHIP_PCIE_EP_MSI_FLAGS_OFFSET 16 + #define ROCKCHIP_PCIE_EP_MSI_CTRL_MMC_OFFSET 17 + #define ROCKCHIP_PCIE_EP_MSI_CTRL_MMC_MASK GENMASK(19, 17) +@@ -235,6 +237,9 @@ + #define ROCKCHIP_PCIE_EP_MSI_CTRL_MME_MASK GENMASK(22, 20) + #define ROCKCHIP_PCIE_EP_MSI_CTRL_ME BIT(16) + #define ROCKCHIP_PCIE_EP_MSI_CTRL_MASK_MSI_CAP BIT(24) ++#define ROCKCHIP_PCIE_EP_MSIX_CAP_REG 0xb0 ++#define ROCKCHIP_PCIE_EP_MSIX_CAP_CP_OFFSET 8 ++#define ROCKCHIP_PCIE_EP_MSIX_CAP_CP_MASK GENMASK(15, 8) + #define ROCKCHIP_PCIE_EP_DUMMY_IRQ_ADDR 0x1 + #define ROCKCHIP_PCIE_EP_PCI_LEGACY_IRQ_ADDR 0x3 + #define ROCKCHIP_PCIE_EP_FUNC_BASE(fn) \ +-- +2.39.2 + diff --git a/queue-5.15/pci-rockchip-fix-window-mapping-and-address-translat.patch b/queue-5.15/pci-rockchip-fix-window-mapping-and-address-translat.patch new file mode 100644 index 00000000000..1d1827631ae --- /dev/null +++ b/queue-5.15/pci-rockchip-fix-window-mapping-and-address-translat.patch @@ -0,0 +1,340 @@ +From 654fa12adc6b26111c6aea4f41edab940ae82f85 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 18 Apr 2023 09:46:55 +0200 +Subject: PCI: rockchip: Fix window mapping and address translation for + endpoint + +From: Rick Wertenbroek + +[ Upstream commit dc73ed0f1b8bddd7f2bf70d123e68ffc99ad71ce ] + +The RK3399 PCI endpoint core has 33 windows for PCIe space, now in the +driver up to 32 fixed size (1M) windows are used and pages are allocated +and mapped accordingly. The driver first used a single window and allocated +space inside which caused translation issues (between CPU space and PCI +space) because a window can only have a single translation at a given +time, which if multiple pages are allocated inside will cause conflicts. +Now each window is a single region of 1M which will always guarantee that +the translation is not in conflict. + +Set the translation register addresses for physical function. As documented +in the technical reference manual (TRM) section 17.5.5 "PCIe Address +Translation" and section 17.6.8 "Address Translation Registers Description" + +Link: https://lore.kernel.org/r/20230418074700.1083505-9-rick.wertenbroek@gmail.com +Fixes: cf590b078391 ("PCI: rockchip: Add EP driver for Rockchip PCIe controller") +Tested-by: Damien Le Moal +Signed-off-by: Rick Wertenbroek +Signed-off-by: Lorenzo Pieralisi +Reviewed-by: Damien Le Moal +Cc: stable@vger.kernel.org +Signed-off-by: Sasha Levin +--- + drivers/pci/controller/pcie-rockchip-ep.c | 128 ++++++++++------------ + drivers/pci/controller/pcie-rockchip.h | 35 +++--- + 2 files changed, 75 insertions(+), 88 deletions(-) + +diff --git a/drivers/pci/controller/pcie-rockchip-ep.c b/drivers/pci/controller/pcie-rockchip-ep.c +index 9e17f3dba743a..3d6f828d29fc2 100644 +--- a/drivers/pci/controller/pcie-rockchip-ep.c ++++ b/drivers/pci/controller/pcie-rockchip-ep.c +@@ -64,52 +64,29 @@ static void rockchip_pcie_clear_ep_ob_atu(struct rockchip_pcie *rockchip, + } + + static void rockchip_pcie_prog_ep_ob_atu(struct rockchip_pcie *rockchip, u8 fn, +- u32 r, u32 type, u64 cpu_addr, +- u64 pci_addr, size_t size) ++ u32 r, u64 cpu_addr, u64 pci_addr, ++ size_t size) + { +- u64 sz = 1ULL << fls64(size - 1); +- int num_pass_bits = ilog2(sz); +- u32 addr0, addr1, desc0, desc1; +- bool is_nor_msg = (type == AXI_WRAPPER_NOR_MSG); ++ int num_pass_bits = fls64(size - 1); ++ u32 addr0, addr1, desc0; + +- /* The minimal region size is 1MB */ + if (num_pass_bits < 8) + num_pass_bits = 8; + +- cpu_addr -= rockchip->mem_res->start; +- addr0 = ((is_nor_msg ? 0x10 : (num_pass_bits - 1)) & +- PCIE_CORE_OB_REGION_ADDR0_NUM_BITS) | +- (lower_32_bits(cpu_addr) & PCIE_CORE_OB_REGION_ADDR0_LO_ADDR); +- addr1 = upper_32_bits(is_nor_msg ? cpu_addr : pci_addr); +- desc0 = ROCKCHIP_PCIE_AT_OB_REGION_DESC0_DEVFN(fn) | type; +- desc1 = 0; +- +- if (is_nor_msg) { +- rockchip_pcie_write(rockchip, 0, +- ROCKCHIP_PCIE_AT_OB_REGION_PCI_ADDR0(r)); +- rockchip_pcie_write(rockchip, 0, +- ROCKCHIP_PCIE_AT_OB_REGION_PCI_ADDR1(r)); +- rockchip_pcie_write(rockchip, desc0, +- ROCKCHIP_PCIE_AT_OB_REGION_DESC0(r)); +- rockchip_pcie_write(rockchip, desc1, +- ROCKCHIP_PCIE_AT_OB_REGION_DESC1(r)); +- } else { +- /* PCI bus address region */ +- rockchip_pcie_write(rockchip, addr0, +- ROCKCHIP_PCIE_AT_OB_REGION_PCI_ADDR0(r)); +- rockchip_pcie_write(rockchip, addr1, +- ROCKCHIP_PCIE_AT_OB_REGION_PCI_ADDR1(r)); +- rockchip_pcie_write(rockchip, desc0, +- ROCKCHIP_PCIE_AT_OB_REGION_DESC0(r)); +- rockchip_pcie_write(rockchip, desc1, +- ROCKCHIP_PCIE_AT_OB_REGION_DESC1(r)); +- +- addr0 = +- ((num_pass_bits - 1) & PCIE_CORE_OB_REGION_ADDR0_NUM_BITS) | +- (lower_32_bits(cpu_addr) & +- PCIE_CORE_OB_REGION_ADDR0_LO_ADDR); +- addr1 = upper_32_bits(cpu_addr); +- } ++ addr0 = ((num_pass_bits - 1) & PCIE_CORE_OB_REGION_ADDR0_NUM_BITS) | ++ (lower_32_bits(pci_addr) & PCIE_CORE_OB_REGION_ADDR0_LO_ADDR); ++ addr1 = upper_32_bits(pci_addr); ++ desc0 = ROCKCHIP_PCIE_AT_OB_REGION_DESC0_DEVFN(fn) | AXI_WRAPPER_MEM_WRITE; ++ ++ /* PCI bus address region */ ++ rockchip_pcie_write(rockchip, addr0, ++ ROCKCHIP_PCIE_AT_OB_REGION_PCI_ADDR0(r)); ++ rockchip_pcie_write(rockchip, addr1, ++ ROCKCHIP_PCIE_AT_OB_REGION_PCI_ADDR1(r)); ++ rockchip_pcie_write(rockchip, desc0, ++ ROCKCHIP_PCIE_AT_OB_REGION_DESC0(r)); ++ rockchip_pcie_write(rockchip, 0, ++ ROCKCHIP_PCIE_AT_OB_REGION_DESC1(r)); + } + + static int rockchip_pcie_ep_write_header(struct pci_epc *epc, u8 fn, u8 vfn, +@@ -248,26 +225,20 @@ static void rockchip_pcie_ep_clear_bar(struct pci_epc *epc, u8 fn, u8 vfn, + ROCKCHIP_PCIE_AT_IB_EP_FUNC_BAR_ADDR1(fn, bar)); + } + ++static inline u32 rockchip_ob_region(phys_addr_t addr) ++{ ++ return (addr >> ilog2(SZ_1M)) & 0x1f; ++} ++ + static int rockchip_pcie_ep_map_addr(struct pci_epc *epc, u8 fn, u8 vfn, + phys_addr_t addr, u64 pci_addr, + size_t size) + { + struct rockchip_pcie_ep *ep = epc_get_drvdata(epc); + struct rockchip_pcie *pcie = &ep->rockchip; +- u32 r; ++ u32 r = rockchip_ob_region(addr); + +- r = find_first_zero_bit(&ep->ob_region_map, BITS_PER_LONG); +- /* +- * Region 0 is reserved for configuration space and shouldn't +- * be used elsewhere per TRM, so leave it out. +- */ +- if (r >= ep->max_regions - 1) { +- dev_err(&epc->dev, "no free outbound region\n"); +- return -EINVAL; +- } +- +- rockchip_pcie_prog_ep_ob_atu(pcie, fn, r, AXI_WRAPPER_MEM_WRITE, addr, +- pci_addr, size); ++ rockchip_pcie_prog_ep_ob_atu(pcie, fn, r, addr, pci_addr, size); + + set_bit(r, &ep->ob_region_map); + ep->ob_addr[r] = addr; +@@ -282,15 +253,11 @@ static void rockchip_pcie_ep_unmap_addr(struct pci_epc *epc, u8 fn, u8 vfn, + struct rockchip_pcie *rockchip = &ep->rockchip; + u32 r; + +- for (r = 0; r < ep->max_regions - 1; r++) ++ for (r = 0; r < ep->max_regions; r++) + if (ep->ob_addr[r] == addr) + break; + +- /* +- * Region 0 is reserved for configuration space and shouldn't +- * be used elsewhere per TRM, so leave it out. +- */ +- if (r == ep->max_regions - 1) ++ if (r == ep->max_regions) + return; + + rockchip_pcie_clear_ep_ob_atu(rockchip, r); +@@ -387,7 +354,8 @@ static int rockchip_pcie_ep_send_msi_irq(struct rockchip_pcie_ep *ep, u8 fn, + struct rockchip_pcie *rockchip = &ep->rockchip; + u32 flags, mme, data, data_mask; + u8 msi_count; +- u64 pci_addr, pci_addr_mask = 0xff; ++ u64 pci_addr; ++ u32 r; + + /* Check MSI enable bit */ + flags = rockchip_pcie_read(&ep->rockchip, +@@ -421,21 +389,20 @@ static int rockchip_pcie_ep_send_msi_irq(struct rockchip_pcie_ep *ep, u8 fn, + ROCKCHIP_PCIE_EP_FUNC_BASE(fn) + + ROCKCHIP_PCIE_EP_MSI_CTRL_REG + + PCI_MSI_ADDRESS_LO); +- pci_addr &= GENMASK_ULL(63, 2); + + /* Set the outbound region if needed. */ +- if (unlikely(ep->irq_pci_addr != (pci_addr & ~pci_addr_mask) || ++ if (unlikely(ep->irq_pci_addr != (pci_addr & PCIE_ADDR_MASK) || + ep->irq_pci_fn != fn)) { +- rockchip_pcie_prog_ep_ob_atu(rockchip, fn, ep->max_regions - 1, +- AXI_WRAPPER_MEM_WRITE, ++ r = rockchip_ob_region(ep->irq_phys_addr); ++ rockchip_pcie_prog_ep_ob_atu(rockchip, fn, r, + ep->irq_phys_addr, +- pci_addr & ~pci_addr_mask, +- pci_addr_mask + 1); +- ep->irq_pci_addr = (pci_addr & ~pci_addr_mask); ++ pci_addr & PCIE_ADDR_MASK, ++ ~PCIE_ADDR_MASK + 1); ++ ep->irq_pci_addr = (pci_addr & PCIE_ADDR_MASK); + ep->irq_pci_fn = fn; + } + +- writew(data, ep->irq_cpu_addr + (pci_addr & pci_addr_mask)); ++ writew(data, ep->irq_cpu_addr + (pci_addr & ~PCIE_ADDR_MASK)); + return 0; + } + +@@ -517,6 +484,8 @@ static int rockchip_pcie_parse_ep_dt(struct rockchip_pcie *rockchip, + if (err < 0 || ep->max_regions > MAX_REGION_LIMIT) + ep->max_regions = MAX_REGION_LIMIT; + ++ ep->ob_region_map = 0; ++ + err = of_property_read_u8(dev->of_node, "max-functions", + &ep->epc->max_functions); + if (err < 0) +@@ -537,7 +506,8 @@ static int rockchip_pcie_ep_probe(struct platform_device *pdev) + struct rockchip_pcie *rockchip; + struct pci_epc *epc; + size_t max_regions; +- int err; ++ struct pci_epc_mem_window *windows = NULL; ++ int err, i; + + ep = devm_kzalloc(dev, sizeof(*ep), GFP_KERNEL); + if (!ep) +@@ -584,15 +554,27 @@ static int rockchip_pcie_ep_probe(struct platform_device *pdev) + /* Only enable function 0 by default */ + rockchip_pcie_write(rockchip, BIT(0), PCIE_CORE_PHY_FUNC_CFG); + +- err = pci_epc_mem_init(epc, rockchip->mem_res->start, +- resource_size(rockchip->mem_res), PAGE_SIZE); ++ windows = devm_kcalloc(dev, ep->max_regions, ++ sizeof(struct pci_epc_mem_window), GFP_KERNEL); ++ if (!windows) { ++ err = -ENOMEM; ++ goto err_uninit_port; ++ } ++ for (i = 0; i < ep->max_regions; i++) { ++ windows[i].phys_base = rockchip->mem_res->start + (SZ_1M * i); ++ windows[i].size = SZ_1M; ++ windows[i].page_size = SZ_1M; ++ } ++ err = pci_epc_multi_mem_init(epc, windows, ep->max_regions); ++ devm_kfree(dev, windows); ++ + if (err < 0) { + dev_err(dev, "failed to initialize the memory space\n"); + goto err_uninit_port; + } + + ep->irq_cpu_addr = pci_epc_mem_alloc_addr(epc, &ep->irq_phys_addr, +- SZ_128K); ++ SZ_1M); + if (!ep->irq_cpu_addr) { + dev_err(dev, "failed to reserve memory space for MSI\n"); + err = -ENOMEM; +diff --git a/drivers/pci/controller/pcie-rockchip.h b/drivers/pci/controller/pcie-rockchip.h +index cbd2fd25ba761..498a40251d0be 100644 +--- a/drivers/pci/controller/pcie-rockchip.h ++++ b/drivers/pci/controller/pcie-rockchip.h +@@ -139,6 +139,7 @@ + + #define PCIE_RC_RP_ATS_BASE 0x400000 + #define PCIE_RC_CONFIG_NORMAL_BASE 0x800000 ++#define PCIE_EP_PF_CONFIG_REGS_BASE 0x800000 + #define PCIE_RC_CONFIG_BASE 0xa00000 + #define PCIE_EP_CONFIG_BASE 0xa00000 + #define PCIE_EP_CONFIG_DID_VID (PCIE_EP_CONFIG_BASE + 0x00) +@@ -158,10 +159,11 @@ + #define PCIE_RC_CONFIG_THP_CAP (PCIE_RC_CONFIG_BASE + 0x274) + #define PCIE_RC_CONFIG_THP_CAP_NEXT_MASK GENMASK(31, 20) + ++#define PCIE_ADDR_MASK 0xffffff00 + #define PCIE_CORE_AXI_CONF_BASE 0xc00000 + #define PCIE_CORE_OB_REGION_ADDR0 (PCIE_CORE_AXI_CONF_BASE + 0x0) + #define PCIE_CORE_OB_REGION_ADDR0_NUM_BITS 0x3f +-#define PCIE_CORE_OB_REGION_ADDR0_LO_ADDR 0xffffff00 ++#define PCIE_CORE_OB_REGION_ADDR0_LO_ADDR PCIE_ADDR_MASK + #define PCIE_CORE_OB_REGION_ADDR1 (PCIE_CORE_AXI_CONF_BASE + 0x4) + #define PCIE_CORE_OB_REGION_DESC0 (PCIE_CORE_AXI_CONF_BASE + 0x8) + #define PCIE_CORE_OB_REGION_DESC1 (PCIE_CORE_AXI_CONF_BASE + 0xc) +@@ -169,7 +171,7 @@ + #define PCIE_CORE_AXI_INBOUND_BASE 0xc00800 + #define PCIE_RP_IB_ADDR0 (PCIE_CORE_AXI_INBOUND_BASE + 0x0) + #define PCIE_CORE_IB_REGION_ADDR0_NUM_BITS 0x3f +-#define PCIE_CORE_IB_REGION_ADDR0_LO_ADDR 0xffffff00 ++#define PCIE_CORE_IB_REGION_ADDR0_LO_ADDR PCIE_ADDR_MASK + #define PCIE_RP_IB_ADDR1 (PCIE_CORE_AXI_INBOUND_BASE + 0x4) + + /* Size of one AXI Region (not Region 0) */ +@@ -234,13 +236,15 @@ + #define ROCKCHIP_PCIE_EP_MSI_CTRL_ME BIT(16) + #define ROCKCHIP_PCIE_EP_MSI_CTRL_MASK_MSI_CAP BIT(24) + #define ROCKCHIP_PCIE_EP_DUMMY_IRQ_ADDR 0x1 +-#define ROCKCHIP_PCIE_EP_FUNC_BASE(fn) (((fn) << 12) & GENMASK(19, 12)) ++#define ROCKCHIP_PCIE_EP_PCI_LEGACY_IRQ_ADDR 0x3 ++#define ROCKCHIP_PCIE_EP_FUNC_BASE(fn) \ ++ (PCIE_EP_PF_CONFIG_REGS_BASE + (((fn) << 12) & GENMASK(19, 12))) ++#define ROCKCHIP_PCIE_EP_VIRT_FUNC_BASE(fn) \ ++ (PCIE_EP_PF_CONFIG_REGS_BASE + 0x10000 + (((fn) << 12) & GENMASK(19, 12))) + #define ROCKCHIP_PCIE_AT_IB_EP_FUNC_BAR_ADDR0(fn, bar) \ +- (PCIE_RC_RP_ATS_BASE + 0x0840 + (fn) * 0x0040 + (bar) * 0x0008) ++ (PCIE_CORE_AXI_CONF_BASE + 0x0828 + (fn) * 0x0040 + (bar) * 0x0008) + #define ROCKCHIP_PCIE_AT_IB_EP_FUNC_BAR_ADDR1(fn, bar) \ +- (PCIE_RC_RP_ATS_BASE + 0x0844 + (fn) * 0x0040 + (bar) * 0x0008) +-#define ROCKCHIP_PCIE_AT_OB_REGION_PCI_ADDR0(r) \ +- (PCIE_RC_RP_ATS_BASE + 0x0000 + ((r) & 0x1f) * 0x0020) ++ (PCIE_CORE_AXI_CONF_BASE + 0x082c + (fn) * 0x0040 + (bar) * 0x0008) + #define ROCKCHIP_PCIE_AT_OB_REGION_PCI_ADDR0_DEVFN_MASK GENMASK(19, 12) + #define ROCKCHIP_PCIE_AT_OB_REGION_PCI_ADDR0_DEVFN(devfn) \ + (((devfn) << 12) & \ +@@ -248,20 +252,21 @@ + #define ROCKCHIP_PCIE_AT_OB_REGION_PCI_ADDR0_BUS_MASK GENMASK(27, 20) + #define ROCKCHIP_PCIE_AT_OB_REGION_PCI_ADDR0_BUS(bus) \ + (((bus) << 20) & ROCKCHIP_PCIE_AT_OB_REGION_PCI_ADDR0_BUS_MASK) ++#define PCIE_RC_EP_ATR_OB_REGIONS_1_32 (PCIE_CORE_AXI_CONF_BASE + 0x0020) ++#define ROCKCHIP_PCIE_AT_OB_REGION_PCI_ADDR0(r) \ ++ (PCIE_RC_EP_ATR_OB_REGIONS_1_32 + 0x0000 + ((r) & 0x1f) * 0x0020) + #define ROCKCHIP_PCIE_AT_OB_REGION_PCI_ADDR1(r) \ +- (PCIE_RC_RP_ATS_BASE + 0x0004 + ((r) & 0x1f) * 0x0020) ++ (PCIE_RC_EP_ATR_OB_REGIONS_1_32 + 0x0004 + ((r) & 0x1f) * 0x0020) + #define ROCKCHIP_PCIE_AT_OB_REGION_DESC0_HARDCODED_RID BIT(23) + #define ROCKCHIP_PCIE_AT_OB_REGION_DESC0_DEVFN_MASK GENMASK(31, 24) + #define ROCKCHIP_PCIE_AT_OB_REGION_DESC0_DEVFN(devfn) \ + (((devfn) << 24) & ROCKCHIP_PCIE_AT_OB_REGION_DESC0_DEVFN_MASK) + #define ROCKCHIP_PCIE_AT_OB_REGION_DESC0(r) \ +- (PCIE_RC_RP_ATS_BASE + 0x0008 + ((r) & 0x1f) * 0x0020) +-#define ROCKCHIP_PCIE_AT_OB_REGION_DESC1(r) \ +- (PCIE_RC_RP_ATS_BASE + 0x000c + ((r) & 0x1f) * 0x0020) +-#define ROCKCHIP_PCIE_AT_OB_REGION_CPU_ADDR0(r) \ +- (PCIE_RC_RP_ATS_BASE + 0x0018 + ((r) & 0x1f) * 0x0020) +-#define ROCKCHIP_PCIE_AT_OB_REGION_CPU_ADDR1(r) \ +- (PCIE_RC_RP_ATS_BASE + 0x001c + ((r) & 0x1f) * 0x0020) ++ (PCIE_RC_EP_ATR_OB_REGIONS_1_32 + 0x0008 + ((r) & 0x1f) * 0x0020) ++#define ROCKCHIP_PCIE_AT_OB_REGION_DESC1(r) \ ++ (PCIE_RC_EP_ATR_OB_REGIONS_1_32 + 0x000c + ((r) & 0x1f) * 0x0020) ++#define ROCKCHIP_PCIE_AT_OB_REGION_DESC2(r) \ ++ (PCIE_RC_EP_ATR_OB_REGIONS_1_32 + 0x0010 + ((r) & 0x1f) * 0x0020) + + #define ROCKCHIP_PCIE_CORE_EP_FUNC_BAR_CFG0(fn) \ + (PCIE_CORE_CTRL_MGMT_BASE + 0x0240 + (fn) * 0x0008) +-- +2.39.2 + diff --git a/queue-5.15/pci-rockchip-remove-writes-to-unused-registers.patch b/queue-5.15/pci-rockchip-remove-writes-to-unused-registers.patch new file mode 100644 index 00000000000..e394e40fe34 --- /dev/null +++ b/queue-5.15/pci-rockchip-remove-writes-to-unused-registers.patch @@ -0,0 +1,55 @@ +From 3c396e7e23569e81b99a721c937a676dc265af4a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 18 Apr 2023 09:46:48 +0200 +Subject: PCI: rockchip: Remove writes to unused registers + +From: Rick Wertenbroek + +[ Upstream commit 92a9c57c325dd51682d428ba960d961fec3c8a08 ] + +Remove write accesses to registers that are marked "unused" (and +therefore read-only) in the technical reference manual (TRM) +(see RK3399 TRM 17.6.8.1) + +Link: https://lore.kernel.org/r/20230418074700.1083505-2-rick.wertenbroek@gmail.com +Tested-by: Damien Le Moal +Signed-off-by: Rick Wertenbroek +Signed-off-by: Lorenzo Pieralisi +Reviewed-by: Damien Le Moal +Stable-dep-of: dc73ed0f1b8b ("PCI: rockchip: Fix window mapping and address translation for endpoint") +Signed-off-by: Sasha Levin +--- + drivers/pci/controller/pcie-rockchip-ep.c | 10 ---------- + 1 file changed, 10 deletions(-) + +diff --git a/drivers/pci/controller/pcie-rockchip-ep.c b/drivers/pci/controller/pcie-rockchip-ep.c +index 827d91e73efab..9e17f3dba743a 100644 +--- a/drivers/pci/controller/pcie-rockchip-ep.c ++++ b/drivers/pci/controller/pcie-rockchip-ep.c +@@ -61,10 +61,6 @@ static void rockchip_pcie_clear_ep_ob_atu(struct rockchip_pcie *rockchip, + ROCKCHIP_PCIE_AT_OB_REGION_DESC0(region)); + rockchip_pcie_write(rockchip, 0, + ROCKCHIP_PCIE_AT_OB_REGION_DESC1(region)); +- rockchip_pcie_write(rockchip, 0, +- ROCKCHIP_PCIE_AT_OB_REGION_CPU_ADDR0(region)); +- rockchip_pcie_write(rockchip, 0, +- ROCKCHIP_PCIE_AT_OB_REGION_CPU_ADDR1(region)); + } + + static void rockchip_pcie_prog_ep_ob_atu(struct rockchip_pcie *rockchip, u8 fn, +@@ -114,12 +110,6 @@ static void rockchip_pcie_prog_ep_ob_atu(struct rockchip_pcie *rockchip, u8 fn, + PCIE_CORE_OB_REGION_ADDR0_LO_ADDR); + addr1 = upper_32_bits(cpu_addr); + } +- +- /* CPU bus address region */ +- rockchip_pcie_write(rockchip, addr0, +- ROCKCHIP_PCIE_AT_OB_REGION_CPU_ADDR0(r)); +- rockchip_pcie_write(rockchip, addr1, +- ROCKCHIP_PCIE_AT_OB_REGION_CPU_ADDR1(r)); + } + + static int rockchip_pcie_ep_write_header(struct pci_epc *epc, u8 fn, u8 vfn, +-- +2.39.2 + diff --git a/queue-5.15/pwm-meson-fix-handling-of-period-duty-if-greater-tha.patch b/queue-5.15/pwm-meson-fix-handling-of-period-duty-if-greater-tha.patch new file mode 100644 index 00000000000..37921f3b1bc --- /dev/null +++ b/queue-5.15/pwm-meson-fix-handling-of-period-duty-if-greater-tha.patch @@ -0,0 +1,85 @@ +From d3bef08736704119bf87858580b0a9539083d322 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 24 May 2023 21:48:36 +0200 +Subject: pwm: meson: fix handling of period/duty if greater than UINT_MAX +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Heiner Kallweit + +[ Upstream commit 87a2cbf02d7701255f9fcca7e5bd864a7bb397cf ] + +state->period/duty are of type u64, and if their value is greater than +UINT_MAX, then the cast to uint will cause problems. Fix this by +changing the type of the respective local variables to u64. + +Fixes: b79c3670e120 ("pwm: meson: Don't duplicate the polarity internally") +Cc: stable@vger.kernel.org +Suggested-by: Uwe Kleine-König +Reviewed-by: Martin Blumenstingl +Signed-off-by: Heiner Kallweit +Signed-off-by: Thierry Reding +Signed-off-by: Sasha Levin +--- + drivers/pwm/pwm-meson.c | 14 +++++++------- + 1 file changed, 7 insertions(+), 7 deletions(-) + +diff --git a/drivers/pwm/pwm-meson.c b/drivers/pwm/pwm-meson.c +index 37bbad88a3ee5..ec6a544d6f526 100644 +--- a/drivers/pwm/pwm-meson.c ++++ b/drivers/pwm/pwm-meson.c +@@ -163,8 +163,9 @@ static int meson_pwm_calc(struct meson_pwm *meson, struct pwm_device *pwm, + const struct pwm_state *state) + { + struct meson_pwm_channel *channel = &meson->channels[pwm->hwpwm]; +- unsigned int duty, period, pre_div, cnt, duty_cnt; ++ unsigned int pre_div, cnt, duty_cnt; + unsigned long fin_freq; ++ u64 duty, period; + + duty = state->duty_cycle; + period = state->period; +@@ -186,19 +187,19 @@ static int meson_pwm_calc(struct meson_pwm *meson, struct pwm_device *pwm, + + dev_dbg(meson->chip.dev, "fin_freq: %lu Hz\n", fin_freq); + +- pre_div = div64_u64(fin_freq * (u64)period, NSEC_PER_SEC * 0xffffLL); ++ pre_div = div64_u64(fin_freq * period, NSEC_PER_SEC * 0xffffLL); + if (pre_div > MISC_CLK_DIV_MASK) { + dev_err(meson->chip.dev, "unable to get period pre_div\n"); + return -EINVAL; + } + +- cnt = div64_u64(fin_freq * (u64)period, NSEC_PER_SEC * (pre_div + 1)); ++ cnt = div64_u64(fin_freq * period, NSEC_PER_SEC * (pre_div + 1)); + if (cnt > 0xffff) { + dev_err(meson->chip.dev, "unable to get period cnt\n"); + return -EINVAL; + } + +- dev_dbg(meson->chip.dev, "period=%u pre_div=%u cnt=%u\n", period, ++ dev_dbg(meson->chip.dev, "period=%llu pre_div=%u cnt=%u\n", period, + pre_div, cnt); + + if (duty == period) { +@@ -211,14 +212,13 @@ static int meson_pwm_calc(struct meson_pwm *meson, struct pwm_device *pwm, + channel->lo = cnt; + } else { + /* Then check is we can have the duty with the same pre_div */ +- duty_cnt = div64_u64(fin_freq * (u64)duty, +- NSEC_PER_SEC * (pre_div + 1)); ++ duty_cnt = div64_u64(fin_freq * duty, NSEC_PER_SEC * (pre_div + 1)); + if (duty_cnt > 0xffff) { + dev_err(meson->chip.dev, "unable to get duty cycle\n"); + return -EINVAL; + } + +- dev_dbg(meson->chip.dev, "duty=%u pre_div=%u duty_cnt=%u\n", ++ dev_dbg(meson->chip.dev, "duty=%llu pre_div=%u duty_cnt=%u\n", + duty, pre_div, duty_cnt); + + channel->pre_div = pre_div; +-- +2.39.2 + diff --git a/queue-5.15/pwm-meson-simplify-duplicated-per-channel-tracking.patch b/queue-5.15/pwm-meson-simplify-duplicated-per-channel-tracking.patch new file mode 100644 index 00000000000..1b587841e91 --- /dev/null +++ b/queue-5.15/pwm-meson-simplify-duplicated-per-channel-tracking.patch @@ -0,0 +1,77 @@ +From ca49b41a11f321f87f3aa9271261b5a23699911d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 8 Nov 2021 14:46:26 +0100 +Subject: pwm: meson: Simplify duplicated per-channel tracking +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Uwe Kleine-König + +[ Upstream commit 5f97f18feac9bd5a8163b108aee52d783114b36f ] + +The driver tracks per-channel data via struct pwm_device::chip_data and +struct meson_pwm::channels[]. The latter holds the actual data, the former +is only a pointer to the latter. So simplify by using struct +meson_pwm::channels[] consistently. + +Signed-off-by: Uwe Kleine-König +Reviewed-by: Martin Blumenstingl +Signed-off-by: Thierry Reding +Stable-dep-of: 87a2cbf02d77 ("pwm: meson: fix handling of period/duty if greater than UINT_MAX") +Signed-off-by: Sasha Levin +--- + drivers/pwm/pwm-meson.c | 11 ++++++----- + 1 file changed, 6 insertions(+), 5 deletions(-) + +diff --git a/drivers/pwm/pwm-meson.c b/drivers/pwm/pwm-meson.c +index 76f702c43cbc3..37bbad88a3ee5 100644 +--- a/drivers/pwm/pwm-meson.c ++++ b/drivers/pwm/pwm-meson.c +@@ -147,12 +147,13 @@ static int meson_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm) + return err; + } + +- return pwm_set_chip_data(pwm, channel); ++ return 0; + } + + static void meson_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm) + { +- struct meson_pwm_channel *channel = pwm_get_chip_data(pwm); ++ struct meson_pwm *meson = to_meson_pwm(chip); ++ struct meson_pwm_channel *channel = &meson->channels[pwm->hwpwm]; + + if (channel) + clk_disable_unprepare(channel->clk); +@@ -161,7 +162,7 @@ static void meson_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm) + static int meson_pwm_calc(struct meson_pwm *meson, struct pwm_device *pwm, + const struct pwm_state *state) + { +- struct meson_pwm_channel *channel = pwm_get_chip_data(pwm); ++ struct meson_pwm_channel *channel = &meson->channels[pwm->hwpwm]; + unsigned int duty, period, pre_div, cnt, duty_cnt; + unsigned long fin_freq; + +@@ -230,7 +231,7 @@ static int meson_pwm_calc(struct meson_pwm *meson, struct pwm_device *pwm, + + static void meson_pwm_enable(struct meson_pwm *meson, struct pwm_device *pwm) + { +- struct meson_pwm_channel *channel = pwm_get_chip_data(pwm); ++ struct meson_pwm_channel *channel = &meson->channels[pwm->hwpwm]; + struct meson_pwm_channel_data *channel_data; + unsigned long flags; + u32 value; +@@ -273,8 +274,8 @@ static void meson_pwm_disable(struct meson_pwm *meson, struct pwm_device *pwm) + static int meson_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, + const struct pwm_state *state) + { +- struct meson_pwm_channel *channel = pwm_get_chip_data(pwm); + struct meson_pwm *meson = to_meson_pwm(chip); ++ struct meson_pwm_channel *channel = &meson->channels[pwm->hwpwm]; + int err = 0; + + if (!state) +-- +2.39.2 + diff --git a/queue-5.15/revert-tracing-add-fault-name-injection-to-kernel-pr.patch b/queue-5.15/revert-tracing-add-fault-name-injection-to-kernel-pr.patch new file mode 100644 index 00000000000..77109342772 --- /dev/null +++ b/queue-5.15/revert-tracing-add-fault-name-injection-to-kernel-pr.patch @@ -0,0 +1,135 @@ +From 5a71e3f9d94ce54053dfb0cee214a0ac6766835f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 11 Jul 2023 23:15:57 +0900 +Subject: Revert "tracing: Add "(fault)" name injection to kernel probes" + +From: Masami Hiramatsu (Google) + +[ Upstream commit 4ed8f337dee32df71435689c19d22e4ee846e15a ] + +This reverts commit 2e9906f84fc7c99388bb7123ade167250d50f1c0. + +It was turned out that commit 2e9906f84fc7 ("tracing: Add "(fault)" +name injection to kernel probes") did not work correctly and probe +events still show just '(fault)' (instead of '"(fault)"'). Also, +current '(fault)' is more explicit that it faulted. + +This also moves FAULT_STRING macro to trace.h so that synthetic +event can keep using it, and uses it in trace_probe.c too. + +Link: https://lore.kernel.org/all/168908495772.123124.1250788051922100079.stgit@devnote2/ +Link: https://lore.kernel.org/all/20230706230642.3793a593@rorschach.local.home/ + +Cc: stable@vger.kernel.org +Cc: Andrew Morton +Cc: Tom Zanussi +Signed-off-by: Masami Hiramatsu (Google) +Reviewed-by: Steven Rostedt (Google) +Stable-dep-of: 797311bce5c2 ("tracing/probes: Fix to record 0-length data_loc in fetch_store_string*() if fails") +Signed-off-by: Sasha Levin +--- + kernel/trace/trace.h | 2 ++ + kernel/trace/trace_probe.c | 2 +- + kernel/trace/trace_probe_kernel.h | 31 ++++++------------------------- + 3 files changed, 9 insertions(+), 26 deletions(-) + +diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h +index 33c55c8826a7e..43058077a4def 100644 +--- a/kernel/trace/trace.h ++++ b/kernel/trace/trace.h +@@ -113,6 +113,8 @@ enum trace_type { + #define MEM_FAIL(condition, fmt, ...) \ + DO_ONCE_LITE_IF(condition, pr_err, "ERROR: " fmt, ##__VA_ARGS__) + ++#define FAULT_STRING "(fault)" ++ + #define HIST_STACKTRACE_DEPTH 16 + #define HIST_STACKTRACE_SIZE (HIST_STACKTRACE_DEPTH * sizeof(unsigned long)) + #define HIST_STACKTRACE_SKIP 5 +diff --git a/kernel/trace/trace_probe.c b/kernel/trace/trace_probe.c +index 90bae188d0928..0888f0644d257 100644 +--- a/kernel/trace/trace_probe.c ++++ b/kernel/trace/trace_probe.c +@@ -64,7 +64,7 @@ int PRINT_TYPE_FUNC_NAME(string)(struct trace_seq *s, void *data, void *ent) + int len = *(u32 *)data >> 16; + + if (!len) +- trace_seq_puts(s, "(fault)"); ++ trace_seq_puts(s, FAULT_STRING); + else + trace_seq_printf(s, "\"%s\"", + (const char *)get_loc_data(data, ent)); +diff --git a/kernel/trace/trace_probe_kernel.h b/kernel/trace/trace_probe_kernel.h +index 77dbd9ff97826..1d43df29a1f8e 100644 +--- a/kernel/trace/trace_probe_kernel.h ++++ b/kernel/trace/trace_probe_kernel.h +@@ -2,8 +2,6 @@ + #ifndef __TRACE_PROBE_KERNEL_H_ + #define __TRACE_PROBE_KERNEL_H_ + +-#define FAULT_STRING "(fault)" +- + /* + * This depends on trace_probe.h, but can not include it due to + * the way trace_probe_tmpl.h is used by trace_kprobe.c and trace_eprobe.c. +@@ -15,16 +13,8 @@ static nokprobe_inline int + kern_fetch_store_strlen_user(unsigned long addr) + { + const void __user *uaddr = (__force const void __user *)addr; +- int ret; + +- ret = strnlen_user_nofault(uaddr, MAX_STRING_SIZE); +- /* +- * strnlen_user_nofault returns zero on fault, insert the +- * FAULT_STRING when that occurs. +- */ +- if (ret <= 0) +- return strlen(FAULT_STRING) + 1; +- return ret; ++ return strnlen_user_nofault(uaddr, MAX_STRING_SIZE); + } + + /* Return the length of string -- including null terminal byte */ +@@ -44,18 +34,7 @@ kern_fetch_store_strlen(unsigned long addr) + len++; + } while (c && ret == 0 && len < MAX_STRING_SIZE); + +- /* For faults, return enough to hold the FAULT_STRING */ +- return (ret < 0) ? strlen(FAULT_STRING) + 1 : len; +-} +- +-static nokprobe_inline void set_data_loc(int ret, void *dest, void *__dest, void *base, int len) +-{ +- if (ret >= 0) { +- *(u32 *)dest = make_data_loc(ret, __dest - base); +- } else { +- strscpy(__dest, FAULT_STRING, len); +- ret = strlen(__dest) + 1; +- } ++ return (ret < 0) ? ret : len; + } + + /* +@@ -76,7 +55,8 @@ kern_fetch_store_string_user(unsigned long addr, void *dest, void *base) + __dest = get_loc_data(dest, base); + + ret = strncpy_from_user_nofault(__dest, uaddr, maxlen); +- set_data_loc(ret, dest, __dest, base, maxlen); ++ if (ret >= 0) ++ *(u32 *)dest = make_data_loc(ret, __dest - base); + + return ret; + } +@@ -107,7 +87,8 @@ kern_fetch_store_string(unsigned long addr, void *dest, void *base) + * probing. + */ + ret = strncpy_from_kernel_nofault(__dest, (void *)addr, maxlen); +- set_data_loc(ret, dest, __dest, base, maxlen); ++ if (ret >= 0) ++ *(u32 *)dest = make_data_loc(ret, __dest - base); + + return ret; + } +-- +2.39.2 + diff --git a/queue-5.15/scsi-qla2xxx-add-debug-prints-in-the-device-remove-p.patch b/queue-5.15/scsi-qla2xxx-add-debug-prints-in-the-device-remove-p.patch new file mode 100644 index 00000000000..edbce59aef8 --- /dev/null +++ b/queue-5.15/scsi-qla2xxx-add-debug-prints-in-the-device-remove-p.patch @@ -0,0 +1,54 @@ +From ca965bfd92d47bf2d16a179681e1779d841b71c4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 15 Jun 2022 22:35:05 -0700 +Subject: scsi: qla2xxx: Add debug prints in the device remove path + +From: Arun Easi + +[ Upstream commit f12d2d130efc49464ef0666789bfeb9073162743 ] + +Add a debug print in the devloss callback. + +Link: https://lore.kernel.org/r/20220616053508.27186-9-njavali@marvell.com +Signed-off-by: Arun Easi +Signed-off-by: Nilesh Javali +Signed-off-by: Martin K. Petersen +Stable-dep-of: 9ae615c5bfd3 ("scsi: qla2xxx: Fix hang in task management") +Signed-off-by: Sasha Levin +--- + drivers/scsi/qla2xxx/qla_attr.c | 3 +++ + drivers/scsi/qla2xxx/qla_def.h | 6 ++++++ + 2 files changed, 9 insertions(+) + +diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c +index de57d45ffc5cb..4a5df867057bc 100644 +--- a/drivers/scsi/qla2xxx/qla_attr.c ++++ b/drivers/scsi/qla2xxx/qla_attr.c +@@ -2705,6 +2705,9 @@ qla2x00_dev_loss_tmo_callbk(struct fc_rport *rport) + if (!fcport) + return; + ++ ql_dbg(ql_dbg_async, fcport->vha, 0x5101, ++ DBG_FCPORT_PRFMT(fcport, "dev_loss_tmo expiry, rport_state=%d", ++ rport->port_state)); + + /* + * Now that the rport has been deleted, set the fcport state to +diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h +index bbeb116c16cc3..2a2bca2fb57ee 100644 +--- a/drivers/scsi/qla2xxx/qla_def.h ++++ b/drivers/scsi/qla2xxx/qla_def.h +@@ -5475,4 +5475,10 @@ struct ql_vnd_tgt_stats_resp { + #define IS_SESSION_DELETED(_fcport) (_fcport->disc_state == DSC_DELETE_PEND || \ + _fcport->disc_state == DSC_DELETED) + ++#define DBG_FCPORT_PRFMT(_fp, _fmt, _args...) \ ++ "%s: %8phC: " _fmt " (state=%d disc_state=%d scan_state=%d loopid=0x%x deleted=%d flags=0x%x)\n", \ ++ __func__, _fp->port_name, ##_args, atomic_read(&_fp->state), \ ++ _fp->disc_state, _fp->scan_state, _fp->loop_id, _fp->deleted, \ ++ _fp->flags ++ + #endif +-- +2.39.2 + diff --git a/queue-5.15/scsi-qla2xxx-fix-hang-in-task-management.patch b/queue-5.15/scsi-qla2xxx-fix-hang-in-task-management.patch new file mode 100644 index 00000000000..1805d7f1b53 --- /dev/null +++ b/queue-5.15/scsi-qla2xxx-fix-hang-in-task-management.patch @@ -0,0 +1,195 @@ +From 92c8ae8a606aee9eeeb8e31aa58d646a6665bbfb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 28 Apr 2023 00:53:36 -0700 +Subject: scsi: qla2xxx: Fix hang in task management + +From: Quinn Tran + +[ Upstream commit 9ae615c5bfd37bd091772969b1153de5335ea986 ] + +Task management command hangs where a side +band chip reset failed to nudge the TMF +from it's current send path. + +Add additional error check to block TMF +from entering during chip reset and along +the TMF path to cause it to bail out, skip +over abort of marker. + +Cc: stable@vger.kernel.org +Signed-off-by: Quinn Tran +Signed-off-by: Nilesh Javali +Link: https://lore.kernel.org/r/20230428075339.32551-5-njavali@marvell.com +Reviewed-by: Himanshu Madhani +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + drivers/scsi/qla2xxx/qla_def.h | 4 +++ + drivers/scsi/qla2xxx/qla_init.c | 60 +++++++++++++++++++++++++++++++-- + 2 files changed, 61 insertions(+), 3 deletions(-) + +diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h +index 2a2bca2fb57ee..83228ce822af3 100644 +--- a/drivers/scsi/qla2xxx/qla_def.h ++++ b/drivers/scsi/qla2xxx/qla_def.h +@@ -5481,4 +5481,8 @@ struct ql_vnd_tgt_stats_resp { + _fp->disc_state, _fp->scan_state, _fp->loop_id, _fp->deleted, \ + _fp->flags + ++#define TMF_NOT_READY(_fcport) \ ++ (!_fcport || IS_SESSION_DELETED(_fcport) || atomic_read(&_fcport->state) != FCS_ONLINE || \ ++ !_fcport->vha->hw->flags.fw_started) ++ + #endif +diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c +index 2c42ecb2a64a5..a97872b6350ca 100644 +--- a/drivers/scsi/qla2xxx/qla_init.c ++++ b/drivers/scsi/qla2xxx/qla_init.c +@@ -1998,6 +1998,11 @@ qla2x00_tmf_iocb_timeout(void *data) + int rc, h; + unsigned long flags; + ++ if (sp->type == SRB_MARKER) { ++ complete(&tmf->u.tmf.comp); ++ return; ++ } ++ + rc = qla24xx_async_abort_cmd(sp, false); + if (rc) { + spin_lock_irqsave(sp->qpair->qp_lock_ptr, flags); +@@ -2025,6 +2030,7 @@ static void qla_marker_sp_done(srb_t *sp, int res) + sp->handle, sp->fcport->d_id.b24, sp->u.iocb_cmd.u.tmf.flags, + sp->u.iocb_cmd.u.tmf.lun, sp->qpair->id); + ++ sp->u.iocb_cmd.u.tmf.data = res; + complete(&tmf->u.tmf.comp); + } + +@@ -2041,6 +2047,11 @@ static void qla_marker_sp_done(srb_t *sp, int res) + } while (cnt); \ + } + ++/** ++ * qla26xx_marker: send marker IOCB and wait for the completion of it. ++ * @arg: pointer to argument list. ++ * It is assume caller will provide an fcport pointer and modifier ++ */ + static int + qla26xx_marker(struct tmf_arg *arg) + { +@@ -2050,6 +2061,14 @@ qla26xx_marker(struct tmf_arg *arg) + int rval = QLA_FUNCTION_FAILED; + fc_port_t *fcport = arg->fcport; + ++ if (TMF_NOT_READY(arg->fcport)) { ++ ql_dbg(ql_dbg_taskm, vha, 0x8039, ++ "FC port not ready for marker loop-id=%x portid=%06x modifier=%x lun=%lld qp=%d.\n", ++ fcport->loop_id, fcport->d_id.b24, ++ arg->modifier, arg->lun, arg->qpair->id); ++ return QLA_SUSPENDED; ++ } ++ + /* ref: INIT */ + sp = qla2xxx_get_qpair_sp(vha, arg->qpair, fcport, GFP_KERNEL); + if (!sp) +@@ -2076,11 +2095,19 @@ qla26xx_marker(struct tmf_arg *arg) + + if (rval != QLA_SUCCESS) { + ql_log(ql_log_warn, vha, 0x8031, +- "Marker IOCB failed (%x).\n", rval); ++ "Marker IOCB send failure (%x).\n", rval); + goto done_free_sp; + } + + wait_for_completion(&tm_iocb->u.tmf.comp); ++ rval = tm_iocb->u.tmf.data; ++ ++ if (rval != QLA_SUCCESS) { ++ ql_log(ql_log_warn, vha, 0x8019, ++ "Marker failed hdl=%x loop-id=%x portid=%06x modifier=%x lun=%lld qp=%d rval %d.\n", ++ sp->handle, fcport->loop_id, fcport->d_id.b24, ++ arg->modifier, arg->lun, sp->qpair->id, rval); ++ } + + done_free_sp: + /* ref: INIT */ +@@ -2093,6 +2120,8 @@ static void qla2x00_tmf_sp_done(srb_t *sp, int res) + { + struct srb_iocb *tmf = &sp->u.iocb_cmd; + ++ if (res) ++ tmf->u.tmf.data = res; + complete(&tmf->u.tmf.comp); + } + +@@ -2106,6 +2135,14 @@ __qla2x00_async_tm_cmd(struct tmf_arg *arg) + + fc_port_t *fcport = arg->fcport; + ++ if (TMF_NOT_READY(arg->fcport)) { ++ ql_dbg(ql_dbg_taskm, vha, 0x8032, ++ "FC port not ready for TM command loop-id=%x portid=%06x modifier=%x lun=%lld qp=%d.\n", ++ fcport->loop_id, fcport->d_id.b24, ++ arg->modifier, arg->lun, arg->qpair->id); ++ return QLA_SUSPENDED; ++ } ++ + /* ref: INIT */ + sp = qla2xxx_get_qpair_sp(vha, arg->qpair, fcport, GFP_KERNEL); + if (!sp) +@@ -2180,7 +2217,9 @@ int qla_get_tmf(fc_port_t *fcport) + msleep(1); + + spin_lock_irqsave(&ha->tgt.sess_lock, flags); +- if (fcport->deleted) { ++ if (TMF_NOT_READY(fcport)) { ++ ql_log(ql_log_warn, vha, 0x802c, ++ "Unable to acquire TM resource due to disruption.\n"); + rc = EIO; + break; + } +@@ -2206,7 +2245,10 @@ qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint64_t lun, + struct scsi_qla_host *vha = fcport->vha; + struct qla_qpair *qpair; + struct tmf_arg a; +- int i, rval; ++ int i, rval = QLA_SUCCESS; ++ ++ if (TMF_NOT_READY(fcport)) ++ return QLA_SUSPENDED; + + a.vha = fcport->vha; + a.fcport = fcport; +@@ -2225,6 +2267,14 @@ qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint64_t lun, + qpair = vha->hw->queue_pair_map[i]; + if (!qpair) + continue; ++ ++ if (TMF_NOT_READY(fcport)) { ++ ql_log(ql_log_warn, vha, 0x8026, ++ "Unable to send TM due to disruption.\n"); ++ rval = QLA_SUSPENDED; ++ break; ++ } ++ + a.qpair = qpair; + a.flags = flags|TCF_NOTMCMD_TO_TARGET; + rval = __qla2x00_async_tm_cmd(&a); +@@ -2233,10 +2283,14 @@ qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint64_t lun, + } + } + ++ if (rval) ++ goto bailout; ++ + a.qpair = vha->hw->base_qpair; + a.flags = flags; + rval = __qla2x00_async_tm_cmd(&a); + ++bailout: + if (a.modifier == MK_SYNC_ID_LUN) + qla_put_tmf(fcport); + +-- +2.39.2 + diff --git a/queue-5.15/scsi-qla2xxx-fix-task-management-cmd-fail-due-to-una.patch b/queue-5.15/scsi-qla2xxx-fix-task-management-cmd-fail-due-to-una.patch new file mode 100644 index 00000000000..995c1aeb497 --- /dev/null +++ b/queue-5.15/scsi-qla2xxx-fix-task-management-cmd-fail-due-to-una.patch @@ -0,0 +1,155 @@ +From cc2d6f72c6b995159aecc843410b558cf9f36ee8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 28 Apr 2023 00:53:35 -0700 +Subject: scsi: qla2xxx: Fix task management cmd fail due to unavailable + resource + +From: Quinn Tran + +[ Upstream commit 6a87679626b51b53fbb6be417ad8eb083030b617 ] + +Task management command failed with status 2Ch which is +a result of too many task management commands sent +to the same target. Hence limit task management commands +to 8 per target. + +Reported-by: kernel test robot +Link: https://lore.kernel.org/oe-kbuild-all/202304271952.NKNmoFzv-lkp@intel.com/ +Cc: stable@vger.kernel.org +Signed-off-by: Quinn Tran +Signed-off-by: Nilesh Javali +Link: https://lore.kernel.org/r/20230428075339.32551-4-njavali@marvell.com +Reviewed-by: Himanshu Madhani +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + drivers/scsi/qla2xxx/qla_def.h | 3 ++ + drivers/scsi/qla2xxx/qla_init.c | 63 ++++++++++++++++++++++++++++++--- + 2 files changed, 61 insertions(+), 5 deletions(-) + +diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h +index ca63aa8f33b5d..bbeb116c16cc3 100644 +--- a/drivers/scsi/qla2xxx/qla_def.h ++++ b/drivers/scsi/qla2xxx/qla_def.h +@@ -2523,6 +2523,7 @@ enum rscn_addr_format { + typedef struct fc_port { + struct list_head list; + struct scsi_qla_host *vha; ++ struct list_head tmf_pending; + + unsigned int conf_compl_supported:1; + unsigned int deleted:2; +@@ -2543,6 +2544,8 @@ typedef struct fc_port { + unsigned int do_prli_nvme:1; + + uint8_t nvme_flag; ++ uint8_t active_tmf; ++#define MAX_ACTIVE_TMF 8 + + uint8_t node_name[WWN_SIZE]; + uint8_t port_name[WWN_SIZE]; +diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c +index 9d9b16f7f34a6..2c42ecb2a64a5 100644 +--- a/drivers/scsi/qla2xxx/qla_init.c ++++ b/drivers/scsi/qla2xxx/qla_init.c +@@ -2151,6 +2151,54 @@ __qla2x00_async_tm_cmd(struct tmf_arg *arg) + return rval; + } + ++static void qla_put_tmf(fc_port_t *fcport) ++{ ++ struct scsi_qla_host *vha = fcport->vha; ++ struct qla_hw_data *ha = vha->hw; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&ha->tgt.sess_lock, flags); ++ fcport->active_tmf--; ++ spin_unlock_irqrestore(&ha->tgt.sess_lock, flags); ++} ++ ++static ++int qla_get_tmf(fc_port_t *fcport) ++{ ++ struct scsi_qla_host *vha = fcport->vha; ++ struct qla_hw_data *ha = vha->hw; ++ unsigned long flags; ++ int rc = 0; ++ LIST_HEAD(tmf_elem); ++ ++ spin_lock_irqsave(&ha->tgt.sess_lock, flags); ++ list_add_tail(&tmf_elem, &fcport->tmf_pending); ++ ++ while (fcport->active_tmf >= MAX_ACTIVE_TMF) { ++ spin_unlock_irqrestore(&ha->tgt.sess_lock, flags); ++ ++ msleep(1); ++ ++ spin_lock_irqsave(&ha->tgt.sess_lock, flags); ++ if (fcport->deleted) { ++ rc = EIO; ++ break; ++ } ++ if (fcport->active_tmf < MAX_ACTIVE_TMF && ++ list_is_first(&tmf_elem, &fcport->tmf_pending)) ++ break; ++ } ++ ++ list_del(&tmf_elem); ++ ++ if (!rc) ++ fcport->active_tmf++; ++ ++ spin_unlock_irqrestore(&ha->tgt.sess_lock, flags); ++ ++ return rc; ++} ++ + int + qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint64_t lun, + uint32_t tag) +@@ -2158,18 +2206,19 @@ qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint64_t lun, + struct scsi_qla_host *vha = fcport->vha; + struct qla_qpair *qpair; + struct tmf_arg a; +- struct completion comp; + int i, rval; + +- init_completion(&comp); + a.vha = fcport->vha; + a.fcport = fcport; + a.lun = lun; +- +- if (flags & (TCF_LUN_RESET|TCF_ABORT_TASK_SET|TCF_CLEAR_TASK_SET|TCF_CLEAR_ACA)) ++ if (flags & (TCF_LUN_RESET|TCF_ABORT_TASK_SET|TCF_CLEAR_TASK_SET|TCF_CLEAR_ACA)) { + a.modifier = MK_SYNC_ID_LUN; +- else ++ ++ if (qla_get_tmf(fcport)) ++ return QLA_FUNCTION_FAILED; ++ } else { + a.modifier = MK_SYNC_ID; ++ } + + if (vha->hw->mqenable) { + for (i = 0; i < vha->hw->num_qpairs; i++) { +@@ -2188,6 +2237,9 @@ qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint64_t lun, + a.flags = flags; + rval = __qla2x00_async_tm_cmd(&a); + ++ if (a.modifier == MK_SYNC_ID_LUN) ++ qla_put_tmf(fcport); ++ + return rval; + } + +@@ -5423,6 +5475,7 @@ qla2x00_alloc_fcport(scsi_qla_host_t *vha, gfp_t flags) + INIT_WORK(&fcport->reg_work, qla_register_fcport_fn); + INIT_LIST_HEAD(&fcport->gnl_entry); + INIT_LIST_HEAD(&fcport->list); ++ INIT_LIST_HEAD(&fcport->tmf_pending); + + INIT_LIST_HEAD(&fcport->sess_cmd_list); + spin_lock_init(&fcport->sess_cmd_lock); +-- +2.39.2 + diff --git a/queue-5.15/scsi-qla2xxx-fix-task-management-cmd-failure.patch b/queue-5.15/scsi-qla2xxx-fix-task-management-cmd-failure.patch new file mode 100644 index 00000000000..5e644c39105 --- /dev/null +++ b/queue-5.15/scsi-qla2xxx-fix-task-management-cmd-failure.patch @@ -0,0 +1,325 @@ +From 2f94cf7340cc56172560a73a72eb3964522f88e0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 28 Apr 2023 00:53:34 -0700 +Subject: scsi: qla2xxx: Fix task management cmd failure + +From: Quinn Tran + +[ Upstream commit 9803fb5d27597ea98f2e05b0b6cfc48ae808458e ] + +Task management cmd failed with status 30h which means +FW is not able to finish processing one task management +before another task management for the same lun. +Hence add wait for completion of marker to space it out. + +Reported-by: kernel test robot +Link: https://lore.kernel.org/oe-kbuild-all/202304271802.uCZfwQC1-lkp@intel.com/ +Cc: stable@vger.kernel.org +Signed-off-by: Quinn Tran +Signed-off-by: Nilesh Javali +Link: https://lore.kernel.org/r/20230428075339.32551-3-njavali@marvell.com +Reviewed-by: Himanshu Madhani > +Signed-off-by: Martin K. Petersen +Stable-dep-of: 6a87679626b5 ("scsi: qla2xxx: Fix task management cmd fail due to unavailable resource") +Signed-off-by: Sasha Levin +--- + drivers/scsi/qla2xxx/qla_def.h | 6 ++ + drivers/scsi/qla2xxx/qla_init.c | 102 +++++++++++++++++++++++++++----- + drivers/scsi/qla2xxx/qla_iocb.c | 28 +++++++-- + drivers/scsi/qla2xxx/qla_isr.c | 26 +++++++- + 4 files changed, 139 insertions(+), 23 deletions(-) + +diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h +index d4b8d9dd8106d..ca63aa8f33b5d 100644 +--- a/drivers/scsi/qla2xxx/qla_def.h ++++ b/drivers/scsi/qla2xxx/qla_def.h +@@ -458,6 +458,7 @@ struct tmf_arg { + struct scsi_qla_host *vha; + u64 lun; + u32 flags; ++ uint8_t modifier; + }; + + struct els_logo_payload { +@@ -539,6 +540,10 @@ struct srb_iocb { + uint32_t data; + struct completion comp; + __le16 comp_status; ++ ++ uint8_t modifier; ++ uint8_t vp_index; ++ uint16_t loop_id; + } tmf; + struct { + #define SRB_FXDISC_REQ_DMA_VALID BIT_0 +@@ -642,6 +647,7 @@ struct srb_iocb { + #define SRB_SA_UPDATE 25 + #define SRB_ELS_CMD_HST_NOLOGIN 26 + #define SRB_SA_REPLACE 27 ++#define SRB_MARKER 28 + + struct qla_els_pt_arg { + u8 els_opcode; +diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c +index f64c238e3a45b..9d9b16f7f34a6 100644 +--- a/drivers/scsi/qla2xxx/qla_init.c ++++ b/drivers/scsi/qla2xxx/qla_init.c +@@ -2015,6 +2015,80 @@ qla2x00_tmf_iocb_timeout(void *data) + } + } + ++static void qla_marker_sp_done(srb_t *sp, int res) ++{ ++ struct srb_iocb *tmf = &sp->u.iocb_cmd; ++ ++ if (res != QLA_SUCCESS) ++ ql_dbg(ql_dbg_taskm, sp->vha, 0x8004, ++ "Async-marker fail hdl=%x portid=%06x ctrl=%x lun=%lld qp=%d.\n", ++ sp->handle, sp->fcport->d_id.b24, sp->u.iocb_cmd.u.tmf.flags, ++ sp->u.iocb_cmd.u.tmf.lun, sp->qpair->id); ++ ++ complete(&tmf->u.tmf.comp); ++} ++ ++#define START_SP_W_RETRIES(_sp, _rval) \ ++{\ ++ int cnt = 5; \ ++ do { \ ++ _rval = qla2x00_start_sp(_sp); \ ++ if (_rval == EAGAIN) \ ++ msleep(1); \ ++ else \ ++ break; \ ++ cnt--; \ ++ } while (cnt); \ ++} ++ ++static int ++qla26xx_marker(struct tmf_arg *arg) ++{ ++ struct scsi_qla_host *vha = arg->vha; ++ struct srb_iocb *tm_iocb; ++ srb_t *sp; ++ int rval = QLA_FUNCTION_FAILED; ++ fc_port_t *fcport = arg->fcport; ++ ++ /* ref: INIT */ ++ sp = qla2xxx_get_qpair_sp(vha, arg->qpair, fcport, GFP_KERNEL); ++ if (!sp) ++ goto done; ++ ++ sp->type = SRB_MARKER; ++ sp->name = "marker"; ++ qla2x00_init_async_sp(sp, qla2x00_get_async_timeout(vha), qla_marker_sp_done); ++ sp->u.iocb_cmd.timeout = qla2x00_tmf_iocb_timeout; ++ ++ tm_iocb = &sp->u.iocb_cmd; ++ init_completion(&tm_iocb->u.tmf.comp); ++ tm_iocb->u.tmf.modifier = arg->modifier; ++ tm_iocb->u.tmf.lun = arg->lun; ++ tm_iocb->u.tmf.loop_id = fcport->loop_id; ++ tm_iocb->u.tmf.vp_index = vha->vp_idx; ++ ++ START_SP_W_RETRIES(sp, rval); ++ ++ ql_dbg(ql_dbg_taskm, vha, 0x8006, ++ "Async-marker hdl=%x loop-id=%x portid=%06x modifier=%x lun=%lld qp=%d rval %d.\n", ++ sp->handle, fcport->loop_id, fcport->d_id.b24, ++ arg->modifier, arg->lun, sp->qpair->id, rval); ++ ++ if (rval != QLA_SUCCESS) { ++ ql_log(ql_log_warn, vha, 0x8031, ++ "Marker IOCB failed (%x).\n", rval); ++ goto done_free_sp; ++ } ++ ++ wait_for_completion(&tm_iocb->u.tmf.comp); ++ ++done_free_sp: ++ /* ref: INIT */ ++ kref_put(&sp->cmd_kref, qla2x00_sp_release); ++done: ++ return rval; ++} ++ + static void qla2x00_tmf_sp_done(srb_t *sp, int res) + { + struct srb_iocb *tmf = &sp->u.iocb_cmd; +@@ -2028,7 +2102,6 @@ __qla2x00_async_tm_cmd(struct tmf_arg *arg) + struct scsi_qla_host *vha = arg->vha; + struct srb_iocb *tm_iocb; + srb_t *sp; +- unsigned long flags; + int rval = QLA_FUNCTION_FAILED; + + fc_port_t *fcport = arg->fcport; +@@ -2050,11 +2123,12 @@ __qla2x00_async_tm_cmd(struct tmf_arg *arg) + tm_iocb->u.tmf.flags = arg->flags; + tm_iocb->u.tmf.lun = arg->lun; + +- rval = qla2x00_start_sp(sp); ++ START_SP_W_RETRIES(sp, rval); ++ + ql_dbg(ql_dbg_taskm, vha, 0x802f, +- "Async-tmf hdl=%x loop-id=%x portid=%02x%02x%02x ctrl=%x.\n", +- sp->handle, fcport->loop_id, fcport->d_id.b.domain, +- fcport->d_id.b.area, fcport->d_id.b.al_pa, arg->flags); ++ "Async-tmf hdl=%x loop-id=%x portid=%06x ctrl=%x lun=%lld qp=%d rval=%x.\n", ++ sp->handle, fcport->loop_id, fcport->d_id.b24, ++ arg->flags, arg->lun, sp->qpair->id, rval); + + if (rval != QLA_SUCCESS) + goto done_free_sp; +@@ -2067,17 +2141,8 @@ __qla2x00_async_tm_cmd(struct tmf_arg *arg) + "TM IOCB failed (%x).\n", rval); + } + +- if (!test_bit(UNLOADING, &vha->dpc_flags) && !IS_QLAFX00(vha->hw)) { +- flags = tm_iocb->u.tmf.flags; +- if (flags & (TCF_LUN_RESET|TCF_ABORT_TASK_SET| +- TCF_CLEAR_TASK_SET|TCF_CLEAR_ACA)) +- flags = MK_SYNC_ID_LUN; +- else +- flags = MK_SYNC_ID; +- +- qla2x00_marker(vha, sp->qpair, +- sp->fcport->loop_id, arg->lun, flags); +- } ++ if (!test_bit(UNLOADING, &vha->dpc_flags) && !IS_QLAFX00(vha->hw)) ++ rval = qla26xx_marker(arg); + + done_free_sp: + /* ref: INIT */ +@@ -2101,6 +2166,11 @@ qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint64_t lun, + a.fcport = fcport; + a.lun = lun; + ++ if (flags & (TCF_LUN_RESET|TCF_ABORT_TASK_SET|TCF_CLEAR_TASK_SET|TCF_CLEAR_ACA)) ++ a.modifier = MK_SYNC_ID_LUN; ++ else ++ a.modifier = MK_SYNC_ID; ++ + if (vha->hw->mqenable) { + for (i = 0; i < vha->hw->num_qpairs; i++) { + qpair = vha->hw->queue_pair_map[i]; +diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c +index ac82392c22eed..c9a686f06d29d 100644 +--- a/drivers/scsi/qla2xxx/qla_iocb.c ++++ b/drivers/scsi/qla2xxx/qla_iocb.c +@@ -522,21 +522,25 @@ __qla2x00_marker(struct scsi_qla_host *vha, struct qla_qpair *qpair, + return (QLA_FUNCTION_FAILED); + } + ++ mrk24 = (struct mrk_entry_24xx *)mrk; ++ + mrk->entry_type = MARKER_TYPE; + mrk->modifier = type; + if (type != MK_SYNC_ALL) { + if (IS_FWI2_CAPABLE(ha)) { +- mrk24 = (struct mrk_entry_24xx *) mrk; + mrk24->nport_handle = cpu_to_le16(loop_id); + int_to_scsilun(lun, (struct scsi_lun *)&mrk24->lun); + host_to_fcp_swap(mrk24->lun, sizeof(mrk24->lun)); + mrk24->vp_index = vha->vp_idx; +- mrk24->handle = make_handle(req->id, mrk24->handle); + } else { + SET_TARGET_ID(ha, mrk->target, loop_id); + mrk->lun = cpu_to_le16((uint16_t)lun); + } + } ++ ++ if (IS_FWI2_CAPABLE(ha)) ++ mrk24->handle = QLA_SKIP_HANDLE; ++ + wmb(); + + qla2x00_start_iocbs(vha, req); +@@ -3860,9 +3864,9 @@ int qla_get_iocbs_resource(struct srb *sp) + case SRB_NACK_LOGO: + case SRB_LOGOUT_CMD: + case SRB_CTRL_VP: +- push_it_through = true; +- fallthrough; ++ case SRB_MARKER: + default: ++ push_it_through = true; + get_exch = false; + } + +@@ -3878,6 +3882,19 @@ int qla_get_iocbs_resource(struct srb *sp) + return qla_get_fw_resources(sp->qpair, &sp->iores); + } + ++static void ++qla_marker_iocb(srb_t *sp, struct mrk_entry_24xx *mrk) ++{ ++ mrk->entry_type = MARKER_TYPE; ++ mrk->modifier = sp->u.iocb_cmd.u.tmf.modifier; ++ if (sp->u.iocb_cmd.u.tmf.modifier != MK_SYNC_ALL) { ++ mrk->nport_handle = cpu_to_le16(sp->u.iocb_cmd.u.tmf.loop_id); ++ int_to_scsilun(sp->u.iocb_cmd.u.tmf.lun, (struct scsi_lun *)&mrk->lun); ++ host_to_fcp_swap(mrk->lun, sizeof(mrk->lun)); ++ mrk->vp_index = sp->u.iocb_cmd.u.tmf.vp_index; ++ } ++} ++ + int + qla2x00_start_sp(srb_t *sp) + { +@@ -3981,6 +3998,9 @@ qla2x00_start_sp(srb_t *sp) + case SRB_SA_REPLACE: + qla24xx_sa_replace_iocb(sp, pkt); + break; ++ case SRB_MARKER: ++ qla_marker_iocb(sp, pkt); ++ break; + default: + break; + } +diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c +index 665959938e5e3..08d43f43995ef 100644 +--- a/drivers/scsi/qla2xxx/qla_isr.c ++++ b/drivers/scsi/qla2xxx/qla_isr.c +@@ -3737,6 +3737,28 @@ static int qla_chk_cont_iocb_avail(struct scsi_qla_host *vha, + return rc; + } + ++static void qla_marker_iocb_entry(scsi_qla_host_t *vha, struct req_que *req, ++ struct mrk_entry_24xx *pkt) ++{ ++ const char func[] = "MRK-IOCB"; ++ srb_t *sp; ++ int res = QLA_SUCCESS; ++ ++ if (!IS_FWI2_CAPABLE(vha->hw)) ++ return; ++ ++ sp = qla2x00_get_sp_from_handle(vha, func, req, pkt); ++ if (!sp) ++ return; ++ ++ if (pkt->entry_status) { ++ ql_dbg(ql_dbg_taskm, vha, 0x8025, "marker failure.\n"); ++ res = QLA_COMMAND_ERROR; ++ } ++ sp->u.iocb_cmd.u.tmf.data = res; ++ sp->done(sp, res); ++} ++ + /** + * qla24xx_process_response_queue() - Process response queue entries. + * @vha: SCSI driver HA context +@@ -3858,9 +3880,7 @@ void qla24xx_process_response_queue(struct scsi_qla_host *vha, + (struct nack_to_isp *)pkt); + break; + case MARKER_TYPE: +- /* Do nothing in this case, this check is to prevent it +- * from falling into default case +- */ ++ qla_marker_iocb_entry(vha, rsp->req, (struct mrk_entry_24xx *)pkt); + break; + case ABORT_IOCB_TYPE: + qla24xx_abort_iocb_entry(vha, rsp->req, +-- +2.39.2 + diff --git a/queue-5.15/scsi-qla2xxx-multi-que-support-for-tmf.patch b/queue-5.15/scsi-qla2xxx-multi-que-support-for-tmf.patch new file mode 100644 index 00000000000..edb0b3c95f8 --- /dev/null +++ b/queue-5.15/scsi-qla2xxx-multi-que-support-for-tmf.patch @@ -0,0 +1,200 @@ +From 7a5ff7d37980768885f42d099c91a9a258a920fd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 28 Apr 2023 00:53:33 -0700 +Subject: scsi: qla2xxx: Multi-que support for TMF + +From: Quinn Tran + +[ Upstream commit d90171dd0da50212f5950cc708240831e82f2f91 ] + +Add queue flush for task management command, before +placing it on the wire. +Do IO flush for all Request Q's. + +Reported-by: kernel test robot +Link: https://lore.kernel.org/oe-kbuild-all/202304271702.GpIL391S-lkp@intel.com/ +Cc: stable@vger.kernel.org +Signed-off-by: Quinn Tran +Signed-off-by: Nilesh Javali +Link: https://lore.kernel.org/r/20230428075339.32551-2-njavali@marvell.com +Reviewed-by: Himanshu Madhani > +Signed-off-by: Martin K. Petersen +Stable-dep-of: 6a87679626b5 ("scsi: qla2xxx: Fix task management cmd fail due to unavailable resource") +Signed-off-by: Sasha Levin +--- + drivers/scsi/qla2xxx/qla_def.h | 8 ++++ + drivers/scsi/qla2xxx/qla_gbl.h | 2 +- + drivers/scsi/qla2xxx/qla_init.c | 69 ++++++++++++++++++++++++++------- + drivers/scsi/qla2xxx/qla_iocb.c | 5 ++- + 4 files changed, 66 insertions(+), 18 deletions(-) + +diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h +index e674d3fb59269..d4b8d9dd8106d 100644 +--- a/drivers/scsi/qla2xxx/qla_def.h ++++ b/drivers/scsi/qla2xxx/qla_def.h +@@ -452,6 +452,14 @@ static inline be_id_t port_id_to_be_id(port_id_t port_id) + return res; + } + ++struct tmf_arg { ++ struct qla_qpair *qpair; ++ struct fc_port *fcport; ++ struct scsi_qla_host *vha; ++ u64 lun; ++ u32 flags; ++}; ++ + struct els_logo_payload { + uint8_t opcode; + uint8_t rsvd[3]; +diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h +index 4ed0777cd2a6f..9e467262c0f17 100644 +--- a/drivers/scsi/qla2xxx/qla_gbl.h ++++ b/drivers/scsi/qla2xxx/qla_gbl.h +@@ -69,7 +69,7 @@ extern int qla2x00_async_logout(struct scsi_qla_host *, fc_port_t *); + extern int qla2x00_async_prlo(struct scsi_qla_host *, fc_port_t *); + extern int qla2x00_async_adisc(struct scsi_qla_host *, fc_port_t *, + uint16_t *); +-extern int qla2x00_async_tm_cmd(fc_port_t *, uint32_t, uint32_t, uint32_t); ++extern int qla2x00_async_tm_cmd(fc_port_t *, uint32_t, uint64_t, uint32_t); + struct qla_work_evt *qla2x00_alloc_work(struct scsi_qla_host *, + enum qla_work_type); + extern int qla24xx_async_gnl(struct scsi_qla_host *, fc_port_t *); +diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c +index 37cb469dc9257..f64c238e3a45b 100644 +--- a/drivers/scsi/qla2xxx/qla_init.c ++++ b/drivers/scsi/qla2xxx/qla_init.c +@@ -2022,17 +2022,19 @@ static void qla2x00_tmf_sp_done(srb_t *sp, int res) + complete(&tmf->u.tmf.comp); + } + +-int +-qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint32_t lun, +- uint32_t tag) ++static int ++__qla2x00_async_tm_cmd(struct tmf_arg *arg) + { +- struct scsi_qla_host *vha = fcport->vha; ++ struct scsi_qla_host *vha = arg->vha; + struct srb_iocb *tm_iocb; + srb_t *sp; ++ unsigned long flags; + int rval = QLA_FUNCTION_FAILED; + ++ fc_port_t *fcport = arg->fcport; ++ + /* ref: INIT */ +- sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL); ++ sp = qla2xxx_get_qpair_sp(vha, arg->qpair, fcport, GFP_KERNEL); + if (!sp) + goto done; + +@@ -2045,15 +2047,15 @@ qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint32_t lun, + + tm_iocb = &sp->u.iocb_cmd; + init_completion(&tm_iocb->u.tmf.comp); +- tm_iocb->u.tmf.flags = flags; +- tm_iocb->u.tmf.lun = lun; ++ tm_iocb->u.tmf.flags = arg->flags; ++ tm_iocb->u.tmf.lun = arg->lun; + ++ rval = qla2x00_start_sp(sp); + ql_dbg(ql_dbg_taskm, vha, 0x802f, +- "Async-tmf hdl=%x loop-id=%x portid=%02x%02x%02x.\n", ++ "Async-tmf hdl=%x loop-id=%x portid=%02x%02x%02x ctrl=%x.\n", + sp->handle, fcport->loop_id, fcport->d_id.b.domain, +- fcport->d_id.b.area, fcport->d_id.b.al_pa); ++ fcport->d_id.b.area, fcport->d_id.b.al_pa, arg->flags); + +- rval = qla2x00_start_sp(sp); + if (rval != QLA_SUCCESS) + goto done_free_sp; + wait_for_completion(&tm_iocb->u.tmf.comp); +@@ -2067,12 +2069,14 @@ qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint32_t lun, + + if (!test_bit(UNLOADING, &vha->dpc_flags) && !IS_QLAFX00(vha->hw)) { + flags = tm_iocb->u.tmf.flags; +- lun = (uint16_t)tm_iocb->u.tmf.lun; ++ if (flags & (TCF_LUN_RESET|TCF_ABORT_TASK_SET| ++ TCF_CLEAR_TASK_SET|TCF_CLEAR_ACA)) ++ flags = MK_SYNC_ID_LUN; ++ else ++ flags = MK_SYNC_ID; + +- /* Issue Marker IOCB */ +- qla2x00_marker(vha, vha->hw->base_qpair, +- fcport->loop_id, lun, +- flags == TCF_LUN_RESET ? MK_SYNC_ID_LUN : MK_SYNC_ID); ++ qla2x00_marker(vha, sp->qpair, ++ sp->fcport->loop_id, arg->lun, flags); + } + + done_free_sp: +@@ -2082,6 +2086,41 @@ qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint32_t lun, + return rval; + } + ++int ++qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint64_t lun, ++ uint32_t tag) ++{ ++ struct scsi_qla_host *vha = fcport->vha; ++ struct qla_qpair *qpair; ++ struct tmf_arg a; ++ struct completion comp; ++ int i, rval; ++ ++ init_completion(&comp); ++ a.vha = fcport->vha; ++ a.fcport = fcport; ++ a.lun = lun; ++ ++ if (vha->hw->mqenable) { ++ for (i = 0; i < vha->hw->num_qpairs; i++) { ++ qpair = vha->hw->queue_pair_map[i]; ++ if (!qpair) ++ continue; ++ a.qpair = qpair; ++ a.flags = flags|TCF_NOTMCMD_TO_TARGET; ++ rval = __qla2x00_async_tm_cmd(&a); ++ if (rval) ++ break; ++ } ++ } ++ ++ a.qpair = vha->hw->base_qpair; ++ a.flags = flags; ++ rval = __qla2x00_async_tm_cmd(&a); ++ ++ return rval; ++} ++ + int + qla24xx_async_abort_command(srb_t *sp) + { +diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c +index 7a4298388ef1d..ac82392c22eed 100644 +--- a/drivers/scsi/qla2xxx/qla_iocb.c ++++ b/drivers/scsi/qla2xxx/qla_iocb.c +@@ -2542,7 +2542,7 @@ qla24xx_tm_iocb(srb_t *sp, struct tsk_mgmt_entry *tsk) + scsi_qla_host_t *vha = fcport->vha; + struct qla_hw_data *ha = vha->hw; + struct srb_iocb *iocb = &sp->u.iocb_cmd; +- struct req_que *req = vha->req; ++ struct req_que *req = sp->qpair->req; + + flags = iocb->u.tmf.flags; + lun = iocb->u.tmf.lun; +@@ -2558,7 +2558,8 @@ qla24xx_tm_iocb(srb_t *sp, struct tsk_mgmt_entry *tsk) + tsk->port_id[2] = fcport->d_id.b.domain; + tsk->vp_index = fcport->vha->vp_idx; + +- if (flags == TCF_LUN_RESET) { ++ if (flags & (TCF_LUN_RESET | TCF_ABORT_TASK_SET| ++ TCF_CLEAR_TASK_SET|TCF_CLEAR_ACA)) { + int_to_scsilun(lun, &tsk->lun); + host_to_fcp_swap((uint8_t *)&tsk->lun, + sizeof(tsk->lun)); +-- +2.39.2 + diff --git a/queue-5.15/scsi-qla2xxx-remove-unused-declarations-for-qla2xxx.patch b/queue-5.15/scsi-qla2xxx-remove-unused-declarations-for-qla2xxx.patch new file mode 100644 index 00000000000..154db334ab5 --- /dev/null +++ b/queue-5.15/scsi-qla2xxx-remove-unused-declarations-for-qla2xxx.patch @@ -0,0 +1,109 @@ +From 13832700de34ab55520788122d5f1451b2dc51a8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 13 Sep 2022 10:37:21 +0800 +Subject: scsi: qla2xxx: Remove unused declarations for qla2xxx + +From: Gaosheng Cui + +[ Upstream commit 1b80addaae099dc33e683d971aba90eeeaf887a3 ] + +qla2x00_get_fw_version_str() has been removed since commit abbd8870b9cb +("[SCSI] qla2xxx: Factor-out ISP specific functions to method-based call +tables."). + +qla2x00_release_nvram_protection() has been removed since commit +459c537807bd ("[SCSI] qla2xxx: Add ISP24xx flash-manipulation routines."). + +qla82xx_rdmem() and qla82xx_wrmem() have been removed since commit +3711333dfbee ("[SCSI] qla2xxx: Updates for ISP82xx."). + +qla25xx_rd_req_reg(), qla24xx_rd_req_reg(), qla25xx_wrt_rsp_reg(), +qla24xx_wrt_rsp_reg(), qla25xx_wrt_req_reg() and qla24xx_wrt_req_reg() have +been removed since commit 08029990b25b ("[SCSI] qla2xxx: Refactor +request/response-queue register handling."). + +qla2x00_async_login_done() has been removed since commit 726b85487067 +("qla2xxx: Add framework for async fabric discovery"). + +qlt_24xx_process_response_error() has been removed since commit +c5419e2618b9 ("scsi: qla2xxx: Combine Active command arrays."). + +Remove the declarations for them from header file. + +Link: https://lore.kernel.org/r/20220913023722.547249-2-cuigaosheng1@huawei.com +Signed-off-by: Gaosheng Cui +Signed-off-by: Martin K. Petersen +Stable-dep-of: 6a87679626b5 ("scsi: qla2xxx: Fix task management cmd fail due to unavailable resource") +Signed-off-by: Sasha Levin +--- + drivers/scsi/qla2xxx/qla_gbl.h | 12 ------------ + drivers/scsi/qla2xxx/qla_target.h | 2 -- + 2 files changed, 14 deletions(-) + +diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h +index f82e4a348330a..4ed0777cd2a6f 100644 +--- a/drivers/scsi/qla2xxx/qla_gbl.h ++++ b/drivers/scsi/qla2xxx/qla_gbl.h +@@ -70,8 +70,6 @@ extern int qla2x00_async_prlo(struct scsi_qla_host *, fc_port_t *); + extern int qla2x00_async_adisc(struct scsi_qla_host *, fc_port_t *, + uint16_t *); + extern int qla2x00_async_tm_cmd(fc_port_t *, uint32_t, uint32_t, uint32_t); +-extern void qla2x00_async_login_done(struct scsi_qla_host *, fc_port_t *, +- uint16_t *); + struct qla_work_evt *qla2x00_alloc_work(struct scsi_qla_host *, + enum qla_work_type); + extern int qla24xx_async_gnl(struct scsi_qla_host *, fc_port_t *); +@@ -278,7 +276,6 @@ extern int qla24xx_vport_create_req_sanity_check(struct fc_vport *); + extern scsi_qla_host_t *qla24xx_create_vhost(struct fc_vport *); + + extern void qla2x00_sp_free_dma(srb_t *sp); +-extern char *qla2x00_get_fw_version_str(struct scsi_qla_host *, char *); + + extern void qla2x00_mark_device_lost(scsi_qla_host_t *, fc_port_t *, int); + extern void qla2x00_mark_all_devices_lost(scsi_qla_host_t *); +@@ -611,7 +608,6 @@ void __qla_consume_iocb(struct scsi_qla_host *vha, void **pkt, struct rsp_que ** + /* + * Global Function Prototypes in qla_sup.c source file. + */ +-extern void qla2x00_release_nvram_protection(scsi_qla_host_t *); + extern int qla24xx_read_flash_data(scsi_qla_host_t *, uint32_t *, + uint32_t, uint32_t); + extern uint8_t *qla2x00_read_nvram_data(scsi_qla_host_t *, void *, uint32_t, +@@ -781,12 +777,6 @@ extern void qla2x00_init_response_q_entries(struct rsp_que *); + extern int qla25xx_delete_req_que(struct scsi_qla_host *, struct req_que *); + extern int qla25xx_delete_rsp_que(struct scsi_qla_host *, struct rsp_que *); + extern int qla25xx_delete_queues(struct scsi_qla_host *); +-extern uint16_t qla24xx_rd_req_reg(struct qla_hw_data *, uint16_t); +-extern uint16_t qla25xx_rd_req_reg(struct qla_hw_data *, uint16_t); +-extern void qla24xx_wrt_req_reg(struct qla_hw_data *, uint16_t, uint16_t); +-extern void qla25xx_wrt_req_reg(struct qla_hw_data *, uint16_t, uint16_t); +-extern void qla25xx_wrt_rsp_reg(struct qla_hw_data *, uint16_t, uint16_t); +-extern void qla24xx_wrt_rsp_reg(struct qla_hw_data *, uint16_t, uint16_t); + + /* qlafx00 related functions */ + extern int qlafx00_pci_config(struct scsi_qla_host *); +@@ -871,8 +861,6 @@ extern void qla82xx_init_flags(struct qla_hw_data *); + extern void qla82xx_set_drv_active(scsi_qla_host_t *); + extern int qla82xx_wr_32(struct qla_hw_data *, ulong, u32); + extern int qla82xx_rd_32(struct qla_hw_data *, ulong); +-extern int qla82xx_rdmem(struct qla_hw_data *, u64, void *, int); +-extern int qla82xx_wrmem(struct qla_hw_data *, u64, void *, int); + + /* ISP 8021 IDC */ + extern void qla82xx_clear_drv_active(struct qla_hw_data *); +diff --git a/drivers/scsi/qla2xxx/qla_target.h b/drivers/scsi/qla2xxx/qla_target.h +index 156b950ca7e72..aa83434448377 100644 +--- a/drivers/scsi/qla2xxx/qla_target.h ++++ b/drivers/scsi/qla2xxx/qla_target.h +@@ -1080,8 +1080,6 @@ extern void qlt_81xx_config_nvram_stage2(struct scsi_qla_host *, + struct init_cb_81xx *); + extern void qlt_81xx_config_nvram_stage1(struct scsi_qla_host *, + struct nvram_81xx *); +-extern int qlt_24xx_process_response_error(struct scsi_qla_host *, +- struct sts_entry_24xx *); + extern void qlt_modify_vp_config(struct scsi_qla_host *, + struct vp_config_entry_24xx *); + extern void qlt_probe_one_stage1(struct scsi_qla_host *, struct qla_hw_data *); +-- +2.39.2 + diff --git a/queue-5.15/series b/queue-5.15/series index e69de29bb2d..e9527f72dbb 100644 --- a/queue-5.15/series +++ b/queue-5.15/series @@ -0,0 +1,48 @@ +jbd2-fix-wrongly-judgement-for-buffer-head-removing-.patch +kvm-s390-pv-fix-index-value-of-replaced-asce.patch +io_uring-don-t-audit-the-capability-check-in-io_urin.patch +gpio-tps68470-make-tps68470_gpio_output-always-set-t.patch +gpio-mvebu-make-use-of-devm_pwmchip_add.patch +gpio-mvebu-fix-irq-domain-leak.patch +btrfs-fix-race-between-quota-disable-and-relocation.patch +i2c-delete-error-messages-for-failed-memory-allocati.patch +i2c-improve-size-determinations.patch +i2c-nomadik-remove-unnecessary-goto-label.patch +i2c-nomadik-use-devm_clk_get_enabled.patch +i2c-nomadik-remove-a-useless-call-in-the-remove-func.patch +pci-aspm-return-0-or-etimedout-from-pcie_retrain_lin.patch +pci-aspm-factor-out-pcie_wait_for_retrain.patch +pci-aspm-avoid-link-retraining-race.patch +pci-rockchip-remove-writes-to-unused-registers.patch +pci-rockchip-fix-window-mapping-and-address-translat.patch +pci-rockchip-don-t-advertise-msi-x-in-pcie-capabilit.patch +dlm-cleanup-plock_op-vs-plock_xop.patch +dlm-rearrange-async-condition-return.patch +fs-dlm-interrupt-posix-locks-only-when-process-is-ki.patch +drm-ttm-don-t-print-error-message-if-eviction-was-in.patch +drm-ttm-don-t-leak-a-resource-on-eviction-error.patch +n_tty-rename-tail-to-old_tail-in-n_tty_read.patch +tty-fix-hang-on-tty-device-with-no_room-set.patch +drm-ttm-never-consider-pinned-bos-for-eviction-swap.patch +cifs-missing-directory-in-maintainers-file.patch +cifs-use-fs_context-for-automounts.patch +ksmbd-remove-internal.h-include.patch +cifs-if-deferred-close-is-disabled-then-close-files-.patch +pwm-meson-simplify-duplicated-per-channel-tracking.patch +pwm-meson-fix-handling-of-period-duty-if-greater-tha.patch +tracing-probes-add-symstr-type-for-dynamic-events.patch +tracing-probes-fix-to-avoid-double-count-of-the-stri.patch +tracing-allow-synthetic-events-to-pass-around-stackt.patch +revert-tracing-add-fault-name-injection-to-kernel-pr.patch +tracing-probes-fix-to-record-0-length-data_loc-in-fe.patch +scsi-qla2xxx-remove-unused-declarations-for-qla2xxx.patch +scsi-qla2xxx-multi-que-support-for-tmf.patch +scsi-qla2xxx-fix-task-management-cmd-failure.patch +scsi-qla2xxx-fix-task-management-cmd-fail-due-to-una.patch +scsi-qla2xxx-add-debug-prints-in-the-device-remove-p.patch +scsi-qla2xxx-fix-hang-in-task-management.patch +drm-amdgpu-fix-vkms-crtc-settings.patch +drm-amdgpu-vkms-relax-timer-deactivation-by-hrtimer_.patch +jbd2-remove-t_checkpoint_io_list.patch +jbd2-remove-journal_clean_one_cp_list.patch +jbd2-fix-a-race-when-checking-checkpoint-buffer-busy.patch diff --git a/queue-5.15/tracing-allow-synthetic-events-to-pass-around-stackt.patch b/queue-5.15/tracing-allow-synthetic-events-to-pass-around-stackt.patch new file mode 100644 index 00000000000..e4a3307a9f0 --- /dev/null +++ b/queue-5.15/tracing-allow-synthetic-events-to-pass-around-stackt.patch @@ -0,0 +1,282 @@ +From e79460fddac99eb405ecd2ce0c248072680cbd60 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 17 Jan 2023 10:21:28 -0500 +Subject: tracing: Allow synthetic events to pass around stacktraces + +From: Steven Rostedt (Google) + +[ Upstream commit 00cf3d672a9dd409418647e9f98784c339c3ff63 ] + +Allow a stacktrace from one event to be displayed by the end event of a +synthetic event. This is very useful when looking for the longest latency +of a sleep or something blocked on I/O. + + # cd /sys/kernel/tracing/ + # echo 's:block_lat pid_t pid; u64 delta; unsigned long[] stack;' > dynamic_events + # echo 'hist:keys=next_pid:ts=common_timestamp.usecs,st=stacktrace if prev_state == 1||prev_state == 2' > events/sched/sched_switch/trigger + # echo 'hist:keys=prev_pid:delta=common_timestamp.usecs-$ts,s=$st:onmax($delta).trace(block_lat,prev_pid,$delta,$s)' >> events/sched/sched_switch/trigger + +The above creates a "block_lat" synthetic event that take the stacktrace of +when a task schedules out in either the interruptible or uninterruptible +states, and on a new per process max $delta (the time it was scheduled +out), will print the process id and the stacktrace. + + # echo 1 > events/synthetic/block_lat/enable + # cat trace + # TASK-PID CPU# ||||| TIMESTAMP FUNCTION + # | | | ||||| | | + kworker/u16:0-767 [006] d..4. 560.645045: block_lat: pid=767 delta=66 stack=STACK: + => __schedule + => schedule + => pipe_read + => vfs_read + => ksys_read + => do_syscall_64 + => 0x966000aa + + -0 [003] d..4. 561.132117: block_lat: pid=0 delta=413787 stack=STACK: + => __schedule + => schedule + => schedule_hrtimeout_range_clock + => do_sys_poll + => __x64_sys_poll + => do_syscall_64 + => 0x966000aa + + <...>-153 [006] d..4. 562.068407: block_lat: pid=153 delta=54 stack=STACK: + => __schedule + => schedule + => io_schedule + => rq_qos_wait + => wbt_wait + => __rq_qos_throttle + => blk_mq_submit_bio + => submit_bio_noacct_nocheck + => ext4_bio_write_page + => mpage_submit_page + => mpage_process_page_bufs + => mpage_prepare_extent_to_map + => ext4_do_writepages + => ext4_writepages + => do_writepages + => __writeback_single_inode + +Link: https://lkml.kernel.org/r/20230117152236.010941267@goodmis.org + +Cc: Masami Hiramatsu +Cc: Andrew Morton +Cc: Tom Zanussi +Cc: Ross Zwisler +Cc: Ching-lin Yu +Signed-off-by: Steven Rostedt (Google) +Stable-dep-of: 797311bce5c2 ("tracing/probes: Fix to record 0-length data_loc in fetch_store_string*() if fails") +Signed-off-by: Sasha Levin +--- + kernel/trace/trace.h | 4 ++ + kernel/trace/trace_events_hist.c | 7 ++- + kernel/trace/trace_events_synth.c | 80 ++++++++++++++++++++++++++++++- + kernel/trace/trace_synth.h | 1 + + 4 files changed, 87 insertions(+), 5 deletions(-) + +diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h +index 2c3d9b6ce1485..33c55c8826a7e 100644 +--- a/kernel/trace/trace.h ++++ b/kernel/trace/trace.h +@@ -113,6 +113,10 @@ enum trace_type { + #define MEM_FAIL(condition, fmt, ...) \ + DO_ONCE_LITE_IF(condition, pr_err, "ERROR: " fmt, ##__VA_ARGS__) + ++#define HIST_STACKTRACE_DEPTH 16 ++#define HIST_STACKTRACE_SIZE (HIST_STACKTRACE_DEPTH * sizeof(unsigned long)) ++#define HIST_STACKTRACE_SKIP 5 ++ + /* + * syscalls are special, and need special handling, this is why + * they are not included in trace_entries.h +diff --git a/kernel/trace/trace_events_hist.c b/kernel/trace/trace_events_hist.c +index 1b70fc4c703f7..c32a53f089229 100644 +--- a/kernel/trace/trace_events_hist.c ++++ b/kernel/trace/trace_events_hist.c +@@ -315,10 +315,6 @@ DEFINE_HIST_FIELD_FN(u8); + #define for_each_hist_key_field(i, hist_data) \ + for ((i) = (hist_data)->n_vals; (i) < (hist_data)->n_fields; (i)++) + +-#define HIST_STACKTRACE_DEPTH 16 +-#define HIST_STACKTRACE_SIZE (HIST_STACKTRACE_DEPTH * sizeof(unsigned long)) +-#define HIST_STACKTRACE_SKIP 5 +- + #define HITCOUNT_IDX 0 + #define HIST_KEY_SIZE_MAX (MAX_FILTER_STR_VAL + HIST_STACKTRACE_SIZE) + +@@ -3431,6 +3427,9 @@ static int check_synth_field(struct synth_event *event, + && field->is_dynamic) + return 0; + ++ if (strstr(hist_field->type, "long[") && field->is_stack) ++ return 0; ++ + if (strcmp(field->type, hist_field->type) != 0) { + if (field->size != hist_field->size || + (!field->is_string && field->is_signed != hist_field->is_signed)) +diff --git a/kernel/trace/trace_events_synth.c b/kernel/trace/trace_events_synth.c +index 08c7df42ade7e..ce8fad956b38d 100644 +--- a/kernel/trace/trace_events_synth.c ++++ b/kernel/trace/trace_events_synth.c +@@ -165,6 +165,14 @@ static int synth_field_is_string(char *type) + return false; + } + ++static int synth_field_is_stack(char *type) ++{ ++ if (strstr(type, "long[") != NULL) ++ return true; ++ ++ return false; ++} ++ + static int synth_field_string_size(char *type) + { + char buf[4], *end, *start; +@@ -240,6 +248,8 @@ static int synth_field_size(char *type) + size = sizeof(gfp_t); + else if (synth_field_is_string(type)) + size = synth_field_string_size(type); ++ else if (synth_field_is_stack(type)) ++ size = 0; + + return size; + } +@@ -284,6 +294,8 @@ static const char *synth_field_fmt(char *type) + fmt = "%x"; + else if (synth_field_is_string(type)) + fmt = "%.*s"; ++ else if (synth_field_is_stack(type)) ++ fmt = "%s"; + + return fmt; + } +@@ -363,6 +375,23 @@ static enum print_line_t print_synth_event(struct trace_iterator *iter, + i == se->n_fields - 1 ? "" : " "); + n_u64 += STR_VAR_LEN_MAX / sizeof(u64); + } ++ } else if (se->fields[i]->is_stack) { ++ u32 offset, data_offset, len; ++ unsigned long *p, *end; ++ ++ offset = (u32)entry->fields[n_u64]; ++ data_offset = offset & 0xffff; ++ len = offset >> 16; ++ ++ p = (void *)entry + data_offset; ++ end = (void *)p + len - (sizeof(long) - 1); ++ ++ trace_seq_printf(s, "%s=STACK:\n", se->fields[i]->name); ++ ++ for (; *p && p < end; p++) ++ trace_seq_printf(s, "=> %pS\n", (void *)*p); ++ n_u64++; ++ + } else { + struct trace_print_flags __flags[] = { + __def_gfpflag_names, {-1, NULL} }; +@@ -439,6 +468,43 @@ static unsigned int trace_string(struct synth_trace_event *entry, + return len; + } + ++static unsigned int trace_stack(struct synth_trace_event *entry, ++ struct synth_event *event, ++ long *stack, ++ unsigned int data_size, ++ unsigned int *n_u64) ++{ ++ unsigned int len; ++ u32 data_offset; ++ void *data_loc; ++ ++ data_offset = struct_size(entry, fields, event->n_u64); ++ data_offset += data_size; ++ ++ for (len = 0; len < HIST_STACKTRACE_DEPTH; len++) { ++ if (!stack[len]) ++ break; ++ } ++ ++ /* Include the zero'd element if it fits */ ++ if (len < HIST_STACKTRACE_DEPTH) ++ len++; ++ ++ len *= sizeof(long); ++ ++ /* Find the dynamic section to copy the stack into. */ ++ data_loc = (void *)entry + data_offset; ++ memcpy(data_loc, stack, len); ++ ++ /* Fill in the field that holds the offset/len combo */ ++ data_offset |= len << 16; ++ *(u32 *)&entry->fields[*n_u64] = data_offset; ++ ++ (*n_u64)++; ++ ++ return len; ++} ++ + static notrace void trace_event_raw_event_synth(void *__data, + u64 *var_ref_vals, + unsigned int *var_ref_idx) +@@ -491,6 +557,12 @@ static notrace void trace_event_raw_event_synth(void *__data, + event->fields[i]->is_dynamic, + data_size, &n_u64); + data_size += len; /* only dynamic string increments */ ++ } if (event->fields[i]->is_stack) { ++ long *stack = (long *)(long)var_ref_vals[val_idx]; ++ ++ len = trace_stack(entry, event, stack, ++ data_size, &n_u64); ++ data_size += len; + } else { + struct synth_field *field = event->fields[i]; + u64 val = var_ref_vals[val_idx]; +@@ -553,6 +625,9 @@ static int __set_synth_event_print_fmt(struct synth_event *event, + event->fields[i]->is_dynamic) + pos += snprintf(buf + pos, LEN_OR_ZERO, + ", __get_str(%s)", event->fields[i]->name); ++ else if (event->fields[i]->is_stack) ++ pos += snprintf(buf + pos, LEN_OR_ZERO, ++ ", __get_stacktrace(%s)", event->fields[i]->name); + else + pos += snprintf(buf + pos, LEN_OR_ZERO, + ", REC->%s", event->fields[i]->name); +@@ -689,7 +764,8 @@ static struct synth_field *parse_synth_field(int argc, char **argv, + ret = -EINVAL; + goto free; + } else if (size == 0) { +- if (synth_field_is_string(field->type)) { ++ if (synth_field_is_string(field->type) || ++ synth_field_is_stack(field->type)) { + char *type; + + len = sizeof("__data_loc ") + strlen(field->type) + 1; +@@ -720,6 +796,8 @@ static struct synth_field *parse_synth_field(int argc, char **argv, + + if (synth_field_is_string(field->type)) + field->is_string = true; ++ else if (synth_field_is_stack(field->type)) ++ field->is_stack = true; + + field->is_signed = synth_field_signed(field->type); + out: +diff --git a/kernel/trace/trace_synth.h b/kernel/trace/trace_synth.h +index b29595fe3ac5a..43f6fb6078dbf 100644 +--- a/kernel/trace/trace_synth.h ++++ b/kernel/trace/trace_synth.h +@@ -18,6 +18,7 @@ struct synth_field { + bool is_signed; + bool is_string; + bool is_dynamic; ++ bool is_stack; + }; + + struct synth_event { +-- +2.39.2 + diff --git a/queue-5.15/tracing-probes-add-symstr-type-for-dynamic-events.patch b/queue-5.15/tracing-probes-add-symstr-type-for-dynamic-events.patch new file mode 100644 index 00000000000..f90ec62abdf --- /dev/null +++ b/queue-5.15/tracing-probes-add-symstr-type-for-dynamic-events.patch @@ -0,0 +1,313 @@ +From 2042d57a437472c231b19ad0094733936e7981ed Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 14 Nov 2022 13:47:56 +0900 +Subject: tracing/probes: Add symstr type for dynamic events + +From: Masami Hiramatsu (Google) + +[ Upstream commit b26a124cbfa80f42bfc4e63e1d5643ca98159d66 ] + +Add 'symstr' type for storing the kernel symbol as a string data +instead of the symbol address. This allows us to filter the +events by wildcard symbol name. + +e.g. + # echo 'e:wqfunc workqueue.workqueue_execute_start symname=$function:symstr' >> dynamic_events + # cat events/eprobes/wqfunc/format + name: wqfunc + ID: 2110 + format: + field:unsigned short common_type; offset:0; size:2; signed:0; + field:unsigned char common_flags; offset:2; size:1; signed:0; + field:unsigned char common_preempt_count; offset:3; size:1; signed:0; + field:int common_pid; offset:4; size:4; signed:1; + + field:__data_loc char[] symname; offset:8; size:4; signed:1; + + print fmt: " symname=\"%s\"", __get_str(symname) + +Note that there is already 'symbol' type which just change the +print format (so it still stores the symbol address in the tracing +ring buffer.) On the other hand, 'symstr' type stores the actual +"symbol+offset/size" data as a string. + +Link: https://lore.kernel.org/all/166679930847.1528100.4124308529180235965.stgit@devnote3/ + +Signed-off-by: Masami Hiramatsu (Google) +Stable-dep-of: 66bcf65d6cf0 ("tracing/probes: Fix to avoid double count of the string length on the array") +Signed-off-by: Sasha Levin +--- + Documentation/trace/kprobetrace.rst | 8 +++-- + kernel/trace/trace.c | 2 +- + kernel/trace/trace_probe.c | 44 ++++++++++++++++++--------- + kernel/trace/trace_probe.h | 16 +++++++--- + kernel/trace/trace_probe_tmpl.h | 47 +++++++++++++++++++++++++++-- + 5 files changed, 91 insertions(+), 26 deletions(-) + +diff --git a/Documentation/trace/kprobetrace.rst b/Documentation/trace/kprobetrace.rst +index b175d88f31ebb..15e4bfa2bd83c 100644 +--- a/Documentation/trace/kprobetrace.rst ++++ b/Documentation/trace/kprobetrace.rst +@@ -58,8 +58,8 @@ Synopsis of kprobe_events + NAME=FETCHARG : Set NAME as the argument name of FETCHARG. + FETCHARG:TYPE : Set TYPE as the type of FETCHARG. Currently, basic types + (u8/u16/u32/u64/s8/s16/s32/s64), hexadecimal types +- (x8/x16/x32/x64), "string", "ustring" and bitfield +- are supported. ++ (x8/x16/x32/x64), "string", "ustring", "symbol", "symstr" ++ and bitfield are supported. + + (\*1) only for the probe on function entry (offs == 0). + (\*2) only for return probe. +@@ -96,6 +96,10 @@ offset, and container-size (usually 32). The syntax is:: + + Symbol type('symbol') is an alias of u32 or u64 type (depends on BITS_PER_LONG) + which shows given pointer in "symbol+offset" style. ++On the other hand, symbol-string type ('symstr') converts the given address to ++"symbol+offset/symbolsize" style and stores it as a null-terminated string. ++With 'symstr' type, you can filter the event with wildcard pattern of the ++symbols, and you don't need to solve symbol name by yourself. + For $comm, the default type is "string"; any other type is invalid. + + .. _user_mem_access: +diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c +index 1dda36c7e5eb5..ae7005af78c34 100644 +--- a/kernel/trace/trace.c ++++ b/kernel/trace/trace.c +@@ -5609,7 +5609,7 @@ static const char readme_msg[] = + "\t +|-[u](), \\imm-value, \\\"imm-string\"\n" + "\t type: s8/16/32/64, u8/16/32/64, x8/16/32/64, string, symbol,\n" + "\t b@/, ustring,\n" +- "\t \\[\\]\n" ++ "\t symstr, \\[\\]\n" + #ifdef CONFIG_HIST_TRIGGERS + "\t field: ;\n" + "\t stype: u8/u16/u32/u64, s8/s16/s32/s64, pid_t,\n" +diff --git a/kernel/trace/trace_probe.c b/kernel/trace/trace_probe.c +index cb8f9fe5669ad..90bae188d0928 100644 +--- a/kernel/trace/trace_probe.c ++++ b/kernel/trace/trace_probe.c +@@ -76,9 +76,11 @@ const char PRINT_TYPE_FMT_NAME(string)[] = "\\\"%s\\\""; + /* Fetch type information table */ + static const struct fetch_type probe_fetch_types[] = { + /* Special types */ +- __ASSIGN_FETCH_TYPE("string", string, string, sizeof(u32), 1, ++ __ASSIGN_FETCH_TYPE("string", string, string, sizeof(u32), 1, 1, + "__data_loc char[]"), +- __ASSIGN_FETCH_TYPE("ustring", string, string, sizeof(u32), 1, ++ __ASSIGN_FETCH_TYPE("ustring", string, string, sizeof(u32), 1, 1, ++ "__data_loc char[]"), ++ __ASSIGN_FETCH_TYPE("symstr", string, string, sizeof(u32), 1, 1, + "__data_loc char[]"), + /* Basic types */ + ASSIGN_FETCH_TYPE(u8, u8, 0), +@@ -658,16 +660,26 @@ static int traceprobe_parse_probe_arg_body(const char *argv, ssize_t *size, + + ret = -EINVAL; + /* Store operation */ +- if (!strcmp(parg->type->name, "string") || +- !strcmp(parg->type->name, "ustring")) { +- if (code->op != FETCH_OP_DEREF && code->op != FETCH_OP_UDEREF && +- code->op != FETCH_OP_IMM && code->op != FETCH_OP_COMM && +- code->op != FETCH_OP_DATA && code->op != FETCH_OP_TP_ARG) { +- trace_probe_log_err(offset + (t ? (t - arg) : 0), +- BAD_STRING); +- goto fail; ++ if (parg->type->is_string) { ++ if (!strcmp(parg->type->name, "symstr")) { ++ if (code->op != FETCH_OP_REG && code->op != FETCH_OP_STACK && ++ code->op != FETCH_OP_RETVAL && code->op != FETCH_OP_ARG && ++ code->op != FETCH_OP_DEREF && code->op != FETCH_OP_TP_ARG) { ++ trace_probe_log_err(offset + (t ? (t - arg) : 0), ++ BAD_SYMSTRING); ++ goto fail; ++ } ++ } else { ++ if (code->op != FETCH_OP_DEREF && code->op != FETCH_OP_UDEREF && ++ code->op != FETCH_OP_IMM && code->op != FETCH_OP_COMM && ++ code->op != FETCH_OP_DATA && code->op != FETCH_OP_TP_ARG) { ++ trace_probe_log_err(offset + (t ? (t - arg) : 0), ++ BAD_STRING); ++ goto fail; ++ } + } +- if ((code->op == FETCH_OP_IMM || code->op == FETCH_OP_COMM || ++ if (!strcmp(parg->type->name, "symstr") || ++ (code->op == FETCH_OP_IMM || code->op == FETCH_OP_COMM || + code->op == FETCH_OP_DATA) || code->op == FETCH_OP_TP_ARG || + parg->count) { + /* +@@ -675,6 +687,8 @@ static int traceprobe_parse_probe_arg_body(const char *argv, ssize_t *size, + * must be kept, and if parg->count != 0, this is an + * array of string pointers instead of string address + * itself. ++ * For the symstr, it doesn't need to dereference, thus ++ * it just get the value. + */ + code++; + if (code->op != FETCH_OP_NOP) { +@@ -686,6 +700,8 @@ static int traceprobe_parse_probe_arg_body(const char *argv, ssize_t *size, + if (!strcmp(parg->type->name, "ustring") || + code->op == FETCH_OP_UDEREF) + code->op = FETCH_OP_ST_USTRING; ++ else if (!strcmp(parg->type->name, "symstr")) ++ code->op = FETCH_OP_ST_SYMSTR; + else + code->op = FETCH_OP_ST_STRING; + code->size = parg->type->size; +@@ -915,8 +931,7 @@ static int __set_print_fmt(struct trace_probe *tp, char *buf, int len, + for (i = 0; i < tp->nr_args; i++) { + parg = tp->args + i; + if (parg->count) { +- if ((strcmp(parg->type->name, "string") == 0) || +- (strcmp(parg->type->name, "ustring") == 0)) ++ if (parg->type->is_string) + fmt = ", __get_str(%s[%d])"; + else + fmt = ", REC->%s[%d]"; +@@ -924,8 +939,7 @@ static int __set_print_fmt(struct trace_probe *tp, char *buf, int len, + pos += snprintf(buf + pos, LEN_OR_ZERO, + fmt, parg->name, j); + } else { +- if ((strcmp(parg->type->name, "string") == 0) || +- (strcmp(parg->type->name, "ustring") == 0)) ++ if (parg->type->is_string) + fmt = ", __get_str(%s)"; + else + fmt = ", REC->%s"; +diff --git a/kernel/trace/trace_probe.h b/kernel/trace/trace_probe.h +index 84d495cbd876a..0f0e5005b97a0 100644 +--- a/kernel/trace/trace_probe.h ++++ b/kernel/trace/trace_probe.h +@@ -99,6 +99,7 @@ enum fetch_op { + FETCH_OP_ST_UMEM, /* Mem: .offset, .size */ + FETCH_OP_ST_STRING, /* String: .offset, .size */ + FETCH_OP_ST_USTRING, /* User String: .offset, .size */ ++ FETCH_OP_ST_SYMSTR, /* Kernel Symbol String: .offset, .size */ + // Stage 4 (modify) op + FETCH_OP_MOD_BF, /* Bitfield: .basesize, .lshift, .rshift */ + // Stage 5 (loop) op +@@ -134,7 +135,8 @@ struct fetch_insn { + struct fetch_type { + const char *name; /* Name of type */ + size_t size; /* Byte size of type */ +- int is_signed; /* Signed flag */ ++ bool is_signed; /* Signed flag */ ++ bool is_string; /* String flag */ + print_type_func_t print; /* Print functions */ + const char *fmt; /* Format string */ + const char *fmttype; /* Name in format file */ +@@ -178,16 +180,19 @@ DECLARE_BASIC_PRINT_TYPE_FUNC(symbol); + #define _ADDR_FETCH_TYPE(t) __ADDR_FETCH_TYPE(t) + #define ADDR_FETCH_TYPE _ADDR_FETCH_TYPE(BITS_PER_LONG) + +-#define __ASSIGN_FETCH_TYPE(_name, ptype, ftype, _size, sign, _fmttype) \ +- {.name = _name, \ ++#define __ASSIGN_FETCH_TYPE(_name, ptype, ftype, _size, sign, str, _fmttype) \ ++ {.name = _name, \ + .size = _size, \ +- .is_signed = sign, \ ++ .is_signed = (bool)sign, \ ++ .is_string = (bool)str, \ + .print = PRINT_TYPE_FUNC_NAME(ptype), \ + .fmt = PRINT_TYPE_FMT_NAME(ptype), \ + .fmttype = _fmttype, \ + } ++ ++/* Non string types can use these macros */ + #define _ASSIGN_FETCH_TYPE(_name, ptype, ftype, _size, sign, _fmttype) \ +- __ASSIGN_FETCH_TYPE(_name, ptype, ftype, _size, sign, #_fmttype) ++ __ASSIGN_FETCH_TYPE(_name, ptype, ftype, _size, sign, 0, #_fmttype) + #define ASSIGN_FETCH_TYPE(ptype, ftype, sign) \ + _ASSIGN_FETCH_TYPE(#ptype, ptype, ftype, sizeof(ftype), sign, ptype) + +@@ -432,6 +437,7 @@ extern int traceprobe_define_arg_fields(struct trace_event_call *event_call, + C(ARRAY_TOO_BIG, "Array number is too big"), \ + C(BAD_TYPE, "Unknown type is specified"), \ + C(BAD_STRING, "String accepts only memory argument"), \ ++ C(BAD_SYMSTRING, "Symbol String doesn't accept data/userdata"), \ + C(BAD_BITFIELD, "Invalid bitfield"), \ + C(ARG_NAME_TOO_LONG, "Argument name is too long"), \ + C(NO_ARG_NAME, "Argument name is not specified"), \ +diff --git a/kernel/trace/trace_probe_tmpl.h b/kernel/trace/trace_probe_tmpl.h +index c293a607d5366..21799fa813ca8 100644 +--- a/kernel/trace/trace_probe_tmpl.h ++++ b/kernel/trace/trace_probe_tmpl.h +@@ -67,6 +67,37 @@ probe_mem_read(void *dest, void *src, size_t size); + static nokprobe_inline int + probe_mem_read_user(void *dest, void *src, size_t size); + ++static nokprobe_inline int ++fetch_store_symstrlen(unsigned long addr) ++{ ++ char namebuf[KSYM_SYMBOL_LEN]; ++ int ret; ++ ++ ret = sprint_symbol(namebuf, addr); ++ if (ret < 0) ++ return 0; ++ ++ return ret + 1; ++} ++ ++/* ++ * Fetch a null-terminated symbol string + offset. Caller MUST set *(u32 *)buf ++ * with max length and relative data location. ++ */ ++static nokprobe_inline int ++fetch_store_symstring(unsigned long addr, void *dest, void *base) ++{ ++ int maxlen = get_loc_len(*(u32 *)dest); ++ void *__dest; ++ ++ if (unlikely(!maxlen)) ++ return -ENOMEM; ++ ++ __dest = get_loc_data(dest, base); ++ ++ return sprint_symbol(__dest, addr); ++} ++ + /* From the 2nd stage, routine is same */ + static nokprobe_inline int + process_fetch_insn_bottom(struct fetch_insn *code, unsigned long val, +@@ -99,16 +130,22 @@ process_fetch_insn_bottom(struct fetch_insn *code, unsigned long val, + stage3: + /* 3rd stage: store value to buffer */ + if (unlikely(!dest)) { +- if (code->op == FETCH_OP_ST_STRING) { ++ switch (code->op) { ++ case FETCH_OP_ST_STRING: + ret = fetch_store_strlen(val + code->offset); + code++; + goto array; +- } else if (code->op == FETCH_OP_ST_USTRING) { ++ case FETCH_OP_ST_USTRING: + ret += fetch_store_strlen_user(val + code->offset); + code++; + goto array; +- } else ++ case FETCH_OP_ST_SYMSTR: ++ ret += fetch_store_symstrlen(val + code->offset); ++ code++; ++ goto array; ++ default: + return -EILSEQ; ++ } + } + + switch (code->op) { +@@ -129,6 +166,10 @@ process_fetch_insn_bottom(struct fetch_insn *code, unsigned long val, + loc = *(u32 *)dest; + ret = fetch_store_string_user(val + code->offset, dest, base); + break; ++ case FETCH_OP_ST_SYMSTR: ++ loc = *(u32 *)dest; ++ ret = fetch_store_symstring(val + code->offset, dest, base); ++ break; + default: + return -EILSEQ; + } +-- +2.39.2 + diff --git a/queue-5.15/tracing-probes-fix-to-avoid-double-count-of-the-stri.patch b/queue-5.15/tracing-probes-fix-to-avoid-double-count-of-the-stri.patch new file mode 100644 index 00000000000..75b02f23e42 --- /dev/null +++ b/queue-5.15/tracing-probes-fix-to-avoid-double-count-of-the-stri.patch @@ -0,0 +1,49 @@ +From 59d2bace78087a3c5992fcad7bc5ae9dcecb68de Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 11 Jul 2023 23:15:29 +0900 +Subject: tracing/probes: Fix to avoid double count of the string length on the + array + +From: Masami Hiramatsu (Google) + +[ Upstream commit 66bcf65d6cf0ca6540e2341e88ee7ef02dbdda08 ] + +If an array is specified with the ustring or symstr, the length of the +strings are accumlated on both of 'ret' and 'total', which means the +length is double counted. +Just set the length to the 'ret' value for avoiding double counting. + +Link: https://lore.kernel.org/all/168908492917.123124.15076463491122036025.stgit@devnote2/ + +Reported-by: Dan Carpenter +Closes: https://lore.kernel.org/all/8819b154-2ba1-43c3-98a2-cbde20892023@moroto.mountain/ +Fixes: 88903c464321 ("tracing/probe: Add ustring type for user-space string") +Cc: stable@vger.kernel.org +Signed-off-by: Masami Hiramatsu (Google) +Reviewed-by: Steven Rostedt (Google) +Signed-off-by: Sasha Levin +--- + kernel/trace/trace_probe_tmpl.h | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/kernel/trace/trace_probe_tmpl.h b/kernel/trace/trace_probe_tmpl.h +index 21799fa813ca8..98ac09052fea4 100644 +--- a/kernel/trace/trace_probe_tmpl.h ++++ b/kernel/trace/trace_probe_tmpl.h +@@ -136,11 +136,11 @@ process_fetch_insn_bottom(struct fetch_insn *code, unsigned long val, + code++; + goto array; + case FETCH_OP_ST_USTRING: +- ret += fetch_store_strlen_user(val + code->offset); ++ ret = fetch_store_strlen_user(val + code->offset); + code++; + goto array; + case FETCH_OP_ST_SYMSTR: +- ret += fetch_store_symstrlen(val + code->offset); ++ ret = fetch_store_symstrlen(val + code->offset); + code++; + goto array; + default: +-- +2.39.2 + diff --git a/queue-5.15/tracing-probes-fix-to-record-0-length-data_loc-in-fe.patch b/queue-5.15/tracing-probes-fix-to-record-0-length-data_loc-in-fe.patch new file mode 100644 index 00000000000..f0862cfeaa6 --- /dev/null +++ b/queue-5.15/tracing-probes-fix-to-record-0-length-data_loc-in-fe.patch @@ -0,0 +1,109 @@ +From 8de4149670d00bd10367a4990957857868abf239 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 11 Jul 2023 23:16:07 +0900 +Subject: tracing/probes: Fix to record 0-length data_loc in + fetch_store_string*() if fails + +From: Masami Hiramatsu (Google) + +[ Upstream commit 797311bce5c2ac90b8d65e357603cfd410d36ebb ] + +Fix to record 0-length data to data_loc in fetch_store_string*() if it fails +to get the string data. +Currently those expect that the data_loc is updated by store_trace_args() if +it returns the error code. However, that does not work correctly if the +argument is an array of strings. In that case, store_trace_args() only clears +the first entry of the array (which may have no error) and leaves other +entries. So it should be cleared by fetch_store_string*() itself. +Also, 'dyndata' and 'maxlen' in store_trace_args() should be updated +only if it is used (ret > 0 and argument is a dynamic data.) + +Link: https://lore.kernel.org/all/168908496683.123124.4761206188794205601.stgit@devnote2/ + +Fixes: 40b53b771806 ("tracing: probeevent: Add array type support") +Cc: stable@vger.kernel.org +Reviewed-by: Steven Rostedt (Google) +Signed-off-by: Masami Hiramatsu (Google) +Signed-off-by: Sasha Levin +--- + kernel/trace/trace_probe_kernel.h | 13 +++++++++---- + kernel/trace/trace_probe_tmpl.h | 10 +++------- + kernel/trace/trace_uprobe.c | 3 ++- + 3 files changed, 14 insertions(+), 12 deletions(-) + +diff --git a/kernel/trace/trace_probe_kernel.h b/kernel/trace/trace_probe_kernel.h +index 1d43df29a1f8e..2da70be83831c 100644 +--- a/kernel/trace/trace_probe_kernel.h ++++ b/kernel/trace/trace_probe_kernel.h +@@ -37,6 +37,13 @@ kern_fetch_store_strlen(unsigned long addr) + return (ret < 0) ? ret : len; + } + ++static nokprobe_inline void set_data_loc(int ret, void *dest, void *__dest, void *base) ++{ ++ if (ret < 0) ++ ret = 0; ++ *(u32 *)dest = make_data_loc(ret, __dest - base); ++} ++ + /* + * Fetch a null-terminated string from user. Caller MUST set *(u32 *)buf + * with max length and relative data location. +@@ -55,8 +62,7 @@ kern_fetch_store_string_user(unsigned long addr, void *dest, void *base) + __dest = get_loc_data(dest, base); + + ret = strncpy_from_user_nofault(__dest, uaddr, maxlen); +- if (ret >= 0) +- *(u32 *)dest = make_data_loc(ret, __dest - base); ++ set_data_loc(ret, dest, __dest, base); + + return ret; + } +@@ -87,8 +93,7 @@ kern_fetch_store_string(unsigned long addr, void *dest, void *base) + * probing. + */ + ret = strncpy_from_kernel_nofault(__dest, (void *)addr, maxlen); +- if (ret >= 0) +- *(u32 *)dest = make_data_loc(ret, __dest - base); ++ set_data_loc(ret, dest, __dest, base); + + return ret; + } +diff --git a/kernel/trace/trace_probe_tmpl.h b/kernel/trace/trace_probe_tmpl.h +index 98ac09052fea4..3e2f5a43b974c 100644 +--- a/kernel/trace/trace_probe_tmpl.h ++++ b/kernel/trace/trace_probe_tmpl.h +@@ -247,13 +247,9 @@ store_trace_args(void *data, struct trace_probe *tp, void *rec, + if (unlikely(arg->dynamic)) + *dl = make_data_loc(maxlen, dyndata - base); + ret = process_fetch_insn(arg->code, rec, dl, base); +- if (arg->dynamic) { +- if (unlikely(ret < 0)) { +- *dl = make_data_loc(0, dyndata - base); +- } else { +- dyndata += ret; +- maxlen -= ret; +- } ++ if (arg->dynamic && likely(ret > 0)) { ++ dyndata += ret; ++ maxlen -= ret; + } + } + } +diff --git a/kernel/trace/trace_uprobe.c b/kernel/trace/trace_uprobe.c +index 78ec1c16ccf4b..debc651015489 100644 +--- a/kernel/trace/trace_uprobe.c ++++ b/kernel/trace/trace_uprobe.c +@@ -168,7 +168,8 @@ fetch_store_string(unsigned long addr, void *dest, void *base) + */ + ret++; + *(u32 *)dest = make_data_loc(ret, (void *)dst - base); +- } ++ } else ++ *(u32 *)dest = make_data_loc(0, (void *)dst - base); + + return ret; + } +-- +2.39.2 + diff --git a/queue-5.15/tty-fix-hang-on-tty-device-with-no_room-set.patch b/queue-5.15/tty-fix-hang-on-tty-device-with-no_room-set.patch new file mode 100644 index 00000000000..17db7ceed3c --- /dev/null +++ b/queue-5.15/tty-fix-hang-on-tty-device-with-no_room-set.patch @@ -0,0 +1,116 @@ +From 04ea13fcf5ac39d5faed5c4a0f51f20aa9d4816a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Apr 2023 10:44:50 +0800 +Subject: tty: fix hang on tty device with no_room set +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Hui Li + +[ Upstream commit 4903fde8047a28299d1fc79c1a0dcc255e928f12 ] + +It is possible to hang pty devices in this case, the reader was +blocking at epoll on master side, the writer was sleeping at +wait_woken inside n_tty_write on slave side, and the write buffer +on tty_port was full, we found that the reader and writer would +never be woken again and blocked forever. + +The problem was caused by a race between reader and kworker: +n_tty_read(reader): n_tty_receive_buf_common(kworker): +copy_from_read_buf()| + |room = N_TTY_BUF_SIZE - (ldata->read_head - tail) + |room <= 0 +n_tty_kick_worker() | + |ldata->no_room = true + +After writing to slave device, writer wakes up kworker to flush +data on tty_port to reader, and the kworker finds that reader +has no room to store data so room <= 0 is met. At this moment, +reader consumes all the data on reader buffer and calls +n_tty_kick_worker to check ldata->no_room which is false and +reader quits reading. Then kworker sets ldata->no_room=true +and quits too. + +If write buffer is not full, writer will wake kworker to flush data +again after following writes, but if write buffer is full and writer +goes to sleep, kworker will never be woken again and tty device is +blocked. + +This problem can be solved with a check for read buffer size inside +n_tty_receive_buf_common, if read buffer is empty and ldata->no_room +is true, a call to n_tty_kick_worker is necessary to keep flushing +data to reader. + +Cc: +Fixes: 42458f41d08f ("n_tty: Ensure reader restarts worker for next reader") +Reviewed-by: Ilpo Järvinen +Signed-off-by: Hui Li +Message-ID: <1680749090-14106-1-git-send-email-caelli@tencent.com> +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/tty/n_tty.c | 25 +++++++++++++++++++++---- + 1 file changed, 21 insertions(+), 4 deletions(-) + +diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c +index 8f57448e1ce46..6259249b11670 100644 +--- a/drivers/tty/n_tty.c ++++ b/drivers/tty/n_tty.c +@@ -202,8 +202,8 @@ static void n_tty_kick_worker(struct tty_struct *tty) + struct n_tty_data *ldata = tty->disc_data; + + /* Did the input worker stop? Restart it */ +- if (unlikely(ldata->no_room)) { +- ldata->no_room = 0; ++ if (unlikely(READ_ONCE(ldata->no_room))) { ++ WRITE_ONCE(ldata->no_room, 0); + + WARN_RATELIMIT(tty->port->itty == NULL, + "scheduling with invalid itty\n"); +@@ -1661,7 +1661,7 @@ n_tty_receive_buf_common(struct tty_struct *tty, const unsigned char *cp, + if (overflow && room < 0) + ldata->read_head--; + room = overflow; +- ldata->no_room = flow && !room; ++ WRITE_ONCE(ldata->no_room, flow && !room); + } else + overflow = 0; + +@@ -1692,6 +1692,17 @@ n_tty_receive_buf_common(struct tty_struct *tty, const unsigned char *cp, + } else + n_tty_check_throttle(tty); + ++ if (unlikely(ldata->no_room)) { ++ /* ++ * Barrier here is to ensure to read the latest read_tail in ++ * chars_in_buffer() and to make sure that read_tail is not loaded ++ * before ldata->no_room is set. ++ */ ++ smp_mb(); ++ if (!chars_in_buffer(tty)) ++ n_tty_kick_worker(tty); ++ } ++ + up_read(&tty->termios_rwsem); + + return rcvd; +@@ -2252,8 +2263,14 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file, + if (time) + timeout = time; + } +- if (old_tail != ldata->read_tail) ++ if (old_tail != ldata->read_tail) { ++ /* ++ * Make sure no_room is not read in n_tty_kick_worker() ++ * before setting ldata->read_tail in copy_from_read_buf(). ++ */ ++ smp_mb(); + n_tty_kick_worker(tty); ++ } + up_read(&tty->termios_rwsem); + + remove_wait_queue(&tty->read_wait, &wait); +-- +2.39.2 + -- 2.47.3