--- /dev/null
+From 2c75de21de35cbc361b0bc2d4212f3c0c3a16a26 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 7 Oct 2022 20:31:49 +0530
+Subject: drm/amd/display: explicitly disable psr_feature_enable appropriately
+
+From: Shirish S <shirish.s@amd.com>
+
+[ Upstream commit 6094b9136ca9038b61e9c4b5d25cd5512ce50b34 ]
+
+[Why]
+If psr_feature_enable is set to true by default, it continues to be enabled
+for non capable links.
+
+[How]
+explicitly disable the feature on links that are not capable of the same.
+
+Fixes: 8c322309e48e9 ("drm/amd/display: Enable PSR")
+Signed-off-by: Shirish S <shirish.s@amd.com>
+Reviewed-by: Leo Li <sunpeng.li@amd.com>
+Reviewed-by: Mario Limonciello <mario.limonciello@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Cc: stable@vger.kernel.org # 5.15+
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_psr.c | 8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_psr.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_psr.c
+index 7072fb2ec07f..278ff281a1bd 100644
+--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_psr.c
++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_psr.c
+@@ -36,10 +36,14 @@ void amdgpu_dm_set_psr_caps(struct dc_link *link)
+ {
+ uint8_t dpcd_data[EDP_PSR_RECEIVER_CAP_SIZE];
+
+- if (!(link->connector_signal & SIGNAL_TYPE_EDP))
++ if (!(link->connector_signal & SIGNAL_TYPE_EDP)) {
++ link->psr_settings.psr_feature_enabled = false;
+ return;
+- if (link->type == dc_connection_none)
++ }
++ if (link->type == dc_connection_none) {
++ link->psr_settings.psr_feature_enabled = false;
+ return;
++ }
+ if (dm_helpers_dp_read_dpcd(NULL, link, DP_PSR_SUPPORT,
+ dpcd_data, sizeof(dpcd_data))) {
+ link->dpcd_caps.psr_caps.psr_version = dpcd_data[0];
+--
+2.35.1
+
--- /dev/null
+From bc6e2a685db9dbe094ac02c5c507c0e2666e01c4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 10 Oct 2022 14:23:12 -0700
+Subject: HID: playstation: add initial DualSense Edge controller support
+
+From: Roderick Colenbrander <roderick@gaikai.com>
+
+[ Upstream commit b8a968efab301743fd659b5649c5d7d3e30e63a6 ]
+
+Provide initial support for the DualSense Edge controller. The brings
+support up to the level of the original DualSense, but won't yet provide
+support for new features (e.g. reprogrammable buttons).
+
+Signed-off-by: Roderick Colenbrander <roderick.colenbrander@sony.com>
+CC: stable@vger.kernel.org
+Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
+Link: https://lore.kernel.org/r/20221010212313.78275-3-roderick.colenbrander@sony.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hid/hid-ids.h | 1 +
+ drivers/hid/hid-playstation.c | 5 ++++-
+ 2 files changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
+index cb2b48d6915e..a5aac9cc2075 100644
+--- a/drivers/hid/hid-ids.h
++++ b/drivers/hid/hid-ids.h
+@@ -1109,6 +1109,7 @@
+ #define USB_DEVICE_ID_SONY_PS4_CONTROLLER_2 0x09cc
+ #define USB_DEVICE_ID_SONY_PS4_CONTROLLER_DONGLE 0x0ba0
+ #define USB_DEVICE_ID_SONY_PS5_CONTROLLER 0x0ce6
++#define USB_DEVICE_ID_SONY_PS5_CONTROLLER_2 0x0df2
+ #define USB_DEVICE_ID_SONY_MOTION_CONTROLLER 0x03d5
+ #define USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER 0x042f
+ #define USB_DEVICE_ID_SONY_BUZZ_CONTROLLER 0x0002
+diff --git a/drivers/hid/hid-playstation.c b/drivers/hid/hid-playstation.c
+index ab7c82c2e886..bd0e0fe2f627 100644
+--- a/drivers/hid/hid-playstation.c
++++ b/drivers/hid/hid-playstation.c
+@@ -1282,7 +1282,8 @@ static int ps_probe(struct hid_device *hdev, const struct hid_device_id *id)
+ goto err_stop;
+ }
+
+- if (hdev->product == USB_DEVICE_ID_SONY_PS5_CONTROLLER) {
++ if (hdev->product == USB_DEVICE_ID_SONY_PS5_CONTROLLER ||
++ hdev->product == USB_DEVICE_ID_SONY_PS5_CONTROLLER_2) {
+ dev = dualsense_create(hdev);
+ if (IS_ERR(dev)) {
+ hid_err(hdev, "Failed to create dualsense.\n");
+@@ -1320,6 +1321,8 @@ static void ps_remove(struct hid_device *hdev)
+ static const struct hid_device_id ps_devices[] = {
+ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS5_CONTROLLER) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS5_CONTROLLER) },
++ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS5_CONTROLLER_2) },
++ { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS5_CONTROLLER_2) },
+ { }
+ };
+ MODULE_DEVICE_TABLE(hid, ps_devices);
+--
+2.35.1
+
--- /dev/null
+From a8c3e222a6fc6264831dcd5d72e37f2d4cfe4e5f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 17 Oct 2022 20:45:41 +0200
+Subject: KVM: x86: Add compat handler for KVM_X86_SET_MSR_FILTER
+
+From: Alexander Graf <graf@amazon.com>
+
+[ Upstream commit 1739c7017fb1d759965dcbab925ff5980a5318cb ]
+
+The KVM_X86_SET_MSR_FILTER ioctls contains a pointer in the passed in
+struct which means it has a different struct size depending on whether
+it gets called from 32bit or 64bit code.
+
+This patch introduces compat code that converts from the 32bit struct to
+its 64bit counterpart which then gets used going forward internally.
+With this applied, 32bit QEMU can successfully set MSR bitmaps when
+running on 64bit kernels.
+
+Reported-by: Andrew Randrianasulu <randrianasulu@gmail.com>
+Fixes: 1a155254ff937 ("KVM: x86: Introduce MSR filtering")
+Signed-off-by: Alexander Graf <graf@amazon.com>
+Message-Id: <20221017184541.2658-4-graf@amazon.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/kvm/x86.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 56 insertions(+)
+
+diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
+index 5d165f793f44..ec2a37ba07e6 100644
+--- a/arch/x86/kvm/x86.c
++++ b/arch/x86/kvm/x86.c
+@@ -5942,6 +5942,62 @@ static int kvm_vm_ioctl_set_msr_filter(struct kvm *kvm,
+ return 0;
+ }
+
++#ifdef CONFIG_KVM_COMPAT
++/* for KVM_X86_SET_MSR_FILTER */
++struct kvm_msr_filter_range_compat {
++ __u32 flags;
++ __u32 nmsrs;
++ __u32 base;
++ __u32 bitmap;
++};
++
++struct kvm_msr_filter_compat {
++ __u32 flags;
++ struct kvm_msr_filter_range_compat ranges[KVM_MSR_FILTER_MAX_RANGES];
++};
++
++#define KVM_X86_SET_MSR_FILTER_COMPAT _IOW(KVMIO, 0xc6, struct kvm_msr_filter_compat)
++
++long kvm_arch_vm_compat_ioctl(struct file *filp, unsigned int ioctl,
++ unsigned long arg)
++{
++ void __user *argp = (void __user *)arg;
++ struct kvm *kvm = filp->private_data;
++ long r = -ENOTTY;
++
++ switch (ioctl) {
++ case KVM_X86_SET_MSR_FILTER_COMPAT: {
++ struct kvm_msr_filter __user *user_msr_filter = argp;
++ struct kvm_msr_filter_compat filter_compat;
++ struct kvm_msr_filter filter;
++ int i;
++
++ if (copy_from_user(&filter_compat, user_msr_filter,
++ sizeof(filter_compat)))
++ return -EFAULT;
++
++ filter.flags = filter_compat.flags;
++ for (i = 0; i < ARRAY_SIZE(filter.ranges); i++) {
++ struct kvm_msr_filter_range_compat *cr;
++
++ cr = &filter_compat.ranges[i];
++ filter.ranges[i] = (struct kvm_msr_filter_range) {
++ .flags = cr->flags,
++ .nmsrs = cr->nmsrs,
++ .base = cr->base,
++ .bitmap = (__u8 *)(ulong)cr->bitmap,
++ };
++ }
++
++ r = kvm_vm_ioctl_set_msr_filter(kvm, &filter);
++ break;
++ }
++ }
++
++ return r;
++}
++#endif
++
+ #ifdef CONFIG_HAVE_KVM_PM_NOTIFIER
+ static int kvm_arch_suspend_notifier(struct kvm *kvm)
+ {
+--
+2.35.1
+
--- /dev/null
+From 41c5ac8e175ad38425af5ec5a673d39dad4d4f40 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 17 Oct 2022 20:45:40 +0200
+Subject: KVM: x86: Copy filter arg outside kvm_vm_ioctl_set_msr_filter()
+
+From: Alexander Graf <graf@amazon.com>
+
+[ Upstream commit 2e3272bc1790825c43d2c39690bf2836b81c6d36 ]
+
+In the next patch we want to introduce a second caller to
+set_msr_filter() which constructs its own filter list on the stack.
+Refactor the original function so it takes it as argument instead of
+reading it through copy_from_user().
+
+Signed-off-by: Alexander Graf <graf@amazon.com>
+Message-Id: <20221017184541.2658-3-graf@amazon.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/kvm/x86.c | 31 +++++++++++++++++--------------
+ 1 file changed, 17 insertions(+), 14 deletions(-)
+
+diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
+index 59c9eb55e6d1..5d165f793f44 100644
+--- a/arch/x86/kvm/x86.c
++++ b/arch/x86/kvm/x86.c
+@@ -5895,26 +5895,22 @@ static int kvm_add_msr_filter(struct kvm_x86_msr_filter *msr_filter,
+ return 0;
+ }
+
+-static int kvm_vm_ioctl_set_msr_filter(struct kvm *kvm, void __user *argp)
++static int kvm_vm_ioctl_set_msr_filter(struct kvm *kvm,
++ struct kvm_msr_filter *filter)
+ {
+- struct kvm_msr_filter __user *user_msr_filter = argp;
+ struct kvm_x86_msr_filter *new_filter, *old_filter;
+- struct kvm_msr_filter filter;
+ bool default_allow;
+ bool empty = true;
+ int r = 0;
+ u32 i;
+
+- if (copy_from_user(&filter, user_msr_filter, sizeof(filter)))
+- return -EFAULT;
+-
+- if (filter.flags & ~KVM_MSR_FILTER_DEFAULT_DENY)
++ if (filter->flags & ~KVM_MSR_FILTER_DEFAULT_DENY)
+ return -EINVAL;
+
+- for (i = 0; i < ARRAY_SIZE(filter.ranges); i++)
+- empty &= !filter.ranges[i].nmsrs;
++ for (i = 0; i < ARRAY_SIZE(filter->ranges); i++)
++ empty &= !filter->ranges[i].nmsrs;
+
+- default_allow = !(filter.flags & KVM_MSR_FILTER_DEFAULT_DENY);
++ default_allow = !(filter->flags & KVM_MSR_FILTER_DEFAULT_DENY);
+ if (empty && !default_allow)
+ return -EINVAL;
+
+@@ -5922,8 +5918,8 @@ static int kvm_vm_ioctl_set_msr_filter(struct kvm *kvm, void __user *argp)
+ if (!new_filter)
+ return -ENOMEM;
+
+- for (i = 0; i < ARRAY_SIZE(filter.ranges); i++) {
+- r = kvm_add_msr_filter(new_filter, &filter.ranges[i]);
++ for (i = 0; i < ARRAY_SIZE(filter->ranges); i++) {
++ r = kvm_add_msr_filter(new_filter, &filter->ranges[i]);
+ if (r) {
+ kvm_free_msr_filter(new_filter);
+ return r;
+@@ -6320,9 +6316,16 @@ long kvm_arch_vm_ioctl(struct file *filp,
+ case KVM_SET_PMU_EVENT_FILTER:
+ r = kvm_vm_ioctl_set_pmu_event_filter(kvm, argp);
+ break;
+- case KVM_X86_SET_MSR_FILTER:
+- r = kvm_vm_ioctl_set_msr_filter(kvm, argp);
++ case KVM_X86_SET_MSR_FILTER: {
++ struct kvm_msr_filter __user *user_msr_filter = argp;
++ struct kvm_msr_filter filter;
++
++ if (copy_from_user(&filter, user_msr_filter, sizeof(filter)))
++ return -EFAULT;
++
++ r = kvm_vm_ioctl_set_msr_filter(kvm, &filter);
+ break;
++ }
+ default:
+ r = -ENOTTY;
+ }
+--
+2.35.1
+
--- /dev/null
+From d7e4dee6e86072b2f59d7e01f6ca0e5a0c7205de Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 14 Jul 2022 16:13:15 +0000
+Subject: KVM: x86: Protect the unused bits in MSR exiting flags
+
+From: Aaron Lewis <aaronlewis@google.com>
+
+[ Upstream commit cf5029d5dd7cb0aaa53250fa9e389abd231606b3 ]
+
+The flags for KVM_CAP_X86_USER_SPACE_MSR and KVM_X86_SET_MSR_FILTER
+have no protection for their unused bits. Without protection, future
+development for these features will be difficult. Add the protection
+needed to make it possible to extend these features in the future.
+
+Signed-off-by: Aaron Lewis <aaronlewis@google.com>
+Message-Id: <20220714161314.1715227-1-aaronlewis@google.com>
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+Stable-dep-of: 2e3272bc1790 ("KVM: x86: Copy filter arg outside kvm_vm_ioctl_set_msr_filter()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/kvm/x86.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
+index cd22557e2645..59c9eb55e6d1 100644
+--- a/arch/x86/kvm/x86.c
++++ b/arch/x86/kvm/x86.c
+@@ -5770,6 +5770,11 @@ int kvm_vm_ioctl_enable_cap(struct kvm *kvm,
+ r = 0;
+ break;
+ case KVM_CAP_X86_USER_SPACE_MSR:
++ r = -EINVAL;
++ if (cap->args[0] & ~(KVM_MSR_EXIT_REASON_INVAL |
++ KVM_MSR_EXIT_REASON_UNKNOWN |
++ KVM_MSR_EXIT_REASON_FILTER))
++ break;
+ kvm->arch.user_space_msr_mask = cap->args[0];
+ r = 0;
+ break;
+@@ -5903,6 +5908,9 @@ static int kvm_vm_ioctl_set_msr_filter(struct kvm *kvm, void __user *argp)
+ if (copy_from_user(&filter, user_msr_filter, sizeof(filter)))
+ return -EFAULT;
+
++ if (filter.flags & ~KVM_MSR_FILTER_DEFAULT_DENY)
++ return -EINVAL;
++
+ for (i = 0; i < ARRAY_SIZE(filter.ranges); i++)
+ empty &= !filter.ranges[i].nmsrs;
+
+--
+2.35.1
+
--- /dev/null
+From a467d873bcb9e4b1b756937e6d6d02f7ce6283e8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 2 May 2022 00:07:31 +0200
+Subject: KVM: x86: Trace re-injected exceptions
+
+From: Sean Christopherson <seanjc@google.com>
+
+[ Upstream commit a61d7c5432ac5a953bbcec17af031661c2bd201d ]
+
+Trace exceptions that are re-injected, not just those that KVM is
+injecting for the first time. Debugging re-injection bugs is painful
+enough as is, not having visibility into what KVM is doing only makes
+things worse.
+
+Delay propagating pending=>injected in the non-reinjection path so that
+the tracing can properly identify reinjected exceptions.
+
+Signed-off-by: Sean Christopherson <seanjc@google.com>
+Reviewed-by: Maxim Levitsky <mlevitsk@redhat.com>
+Signed-off-by: Maciej S. Szmigiero <maciej.szmigiero@oracle.com>
+Message-Id: <25470690a38b4d2b32b6204875dd35676c65c9f2.1651440202.git.maciej.szmigiero@oracle.com>
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+Stable-dep-of: 5623f751bd9c ("KVM: x86: Treat #DBs from the emulator as fault-like (code and DR7.GD=1)")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/kvm/trace.h | 12 ++++++++----
+ arch/x86/kvm/x86.c | 16 +++++++++-------
+ 2 files changed, 17 insertions(+), 11 deletions(-)
+
+diff --git a/arch/x86/kvm/trace.h b/arch/x86/kvm/trace.h
+index 03ebe368333e..c41506ed8c7d 100644
+--- a/arch/x86/kvm/trace.h
++++ b/arch/x86/kvm/trace.h
+@@ -355,25 +355,29 @@ TRACE_EVENT(kvm_inj_virq,
+ * Tracepoint for kvm interrupt injection:
+ */
+ TRACE_EVENT(kvm_inj_exception,
+- TP_PROTO(unsigned exception, bool has_error, unsigned error_code),
+- TP_ARGS(exception, has_error, error_code),
++ TP_PROTO(unsigned exception, bool has_error, unsigned error_code,
++ bool reinjected),
++ TP_ARGS(exception, has_error, error_code, reinjected),
+
+ TP_STRUCT__entry(
+ __field( u8, exception )
+ __field( u8, has_error )
+ __field( u32, error_code )
++ __field( bool, reinjected )
+ ),
+
+ TP_fast_assign(
+ __entry->exception = exception;
+ __entry->has_error = has_error;
+ __entry->error_code = error_code;
++ __entry->reinjected = reinjected;
+ ),
+
+- TP_printk("%s (0x%x)",
++ TP_printk("%s (0x%x)%s",
+ __print_symbolic(__entry->exception, kvm_trace_sym_exc),
+ /* FIXME: don't print error_code if not present */
+- __entry->has_error ? __entry->error_code : 0)
++ __entry->has_error ? __entry->error_code : 0,
++ __entry->reinjected ? " [reinjected]" : "")
+ );
+
+ /*
+diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
+index 8648799d48f8..c171ca2bb85a 100644
+--- a/arch/x86/kvm/x86.c
++++ b/arch/x86/kvm/x86.c
+@@ -9010,6 +9010,11 @@ int kvm_check_nested_events(struct kvm_vcpu *vcpu)
+
+ static void kvm_inject_exception(struct kvm_vcpu *vcpu)
+ {
++ trace_kvm_inj_exception(vcpu->arch.exception.nr,
++ vcpu->arch.exception.has_error_code,
++ vcpu->arch.exception.error_code,
++ vcpu->arch.exception.injected);
++
+ if (vcpu->arch.exception.error_code && !is_protmode(vcpu))
+ vcpu->arch.exception.error_code = false;
+ static_call(kvm_x86_queue_exception)(vcpu);
+@@ -9067,13 +9072,6 @@ static int inject_pending_event(struct kvm_vcpu *vcpu, bool *req_immediate_exit)
+
+ /* try to inject new event if pending */
+ if (vcpu->arch.exception.pending) {
+- trace_kvm_inj_exception(vcpu->arch.exception.nr,
+- vcpu->arch.exception.has_error_code,
+- vcpu->arch.exception.error_code);
+-
+- vcpu->arch.exception.pending = false;
+- vcpu->arch.exception.injected = true;
+-
+ if (exception_type(vcpu->arch.exception.nr) == EXCPT_FAULT)
+ __kvm_set_rflags(vcpu, kvm_get_rflags(vcpu) |
+ X86_EFLAGS_RF);
+@@ -9087,6 +9085,10 @@ static int inject_pending_event(struct kvm_vcpu *vcpu, bool *req_immediate_exit)
+ }
+
+ kvm_inject_exception(vcpu);
++
++ vcpu->arch.exception.pending = false;
++ vcpu->arch.exception.injected = true;
++
+ can_inject = false;
+ }
+
+--
+2.35.1
+
--- /dev/null
+From bfc17e5d1035ad471aaef5b77baacac96cf54597 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 30 Aug 2022 23:15:55 +0000
+Subject: KVM: x86: Treat #DBs from the emulator as fault-like (code and
+ DR7.GD=1)
+
+From: Sean Christopherson <seanjc@google.com>
+
+[ Upstream commit 5623f751bd9c438ed12840e086f33c4646440d19 ]
+
+Add a dedicated "exception type" for #DBs, as #DBs can be fault-like or
+trap-like depending the sub-type of #DB, and effectively defer the
+decision of what to do with the #DB to the caller.
+
+For the emulator's two calls to exception_type(), treat the #DB as
+fault-like, as the emulator handles only code breakpoint and general
+detect #DBs, both of which are fault-like.
+
+For event injection, which uses exception_type() to determine whether to
+set EFLAGS.RF=1 on the stack, keep the current behavior of not setting
+RF=1 for #DBs. Intel and AMD explicitly state RF isn't set on code #DBs,
+so exempting by failing the "== EXCPT_FAULT" check is correct. The only
+other fault-like #DB is General Detect, and despite Intel and AMD both
+strongly implying (through omission) that General Detect #DBs should set
+RF=1, hardware (multiple generations of both Intel and AMD), in fact does
+not. Through insider knowledge, extreme foresight, sheer dumb luck, or
+some combination thereof, KVM correctly handled RF for General Detect #DBs.
+
+Fixes: 38827dbd3fb8 ("KVM: x86: Do not update EFLAGS on faulting emulation")
+Cc: stable@vger.kernel.org
+Signed-off-by: Sean Christopherson <seanjc@google.com>
+Reviewed-by: Maxim Levitsky <mlevitsk@redhat.com>
+Link: https://lore.kernel.org/r/20220830231614.3580124-9-seanjc@google.com
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/kvm/x86.c | 27 +++++++++++++++++++++++++--
+ 1 file changed, 25 insertions(+), 2 deletions(-)
+
+diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
+index c171ca2bb85a..cd22557e2645 100644
+--- a/arch/x86/kvm/x86.c
++++ b/arch/x86/kvm/x86.c
+@@ -525,6 +525,7 @@ static int exception_class(int vector)
+ #define EXCPT_TRAP 1
+ #define EXCPT_ABORT 2
+ #define EXCPT_INTERRUPT 3
++#define EXCPT_DB 4
+
+ static int exception_type(int vector)
+ {
+@@ -535,8 +536,14 @@ static int exception_type(int vector)
+
+ mask = 1 << vector;
+
+- /* #DB is trap, as instruction watchpoints are handled elsewhere */
+- if (mask & ((1 << DB_VECTOR) | (1 << BP_VECTOR) | (1 << OF_VECTOR)))
++ /*
++ * #DBs can be trap-like or fault-like, the caller must check other CPU
++ * state, e.g. DR6, to determine whether a #DB is a trap or fault.
++ */
++ if (mask & (1 << DB_VECTOR))
++ return EXCPT_DB;
++
++ if (mask & ((1 << BP_VECTOR) | (1 << OF_VECTOR)))
+ return EXCPT_TRAP;
+
+ if (mask & ((1 << DF_VECTOR) | (1 << MC_VECTOR)))
+@@ -8134,6 +8141,12 @@ int x86_emulate_instruction(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa,
+ unsigned long rflags = static_call(kvm_x86_get_rflags)(vcpu);
+ toggle_interruptibility(vcpu, ctxt->interruptibility);
+ vcpu->arch.emulate_regs_need_sync_to_vcpu = false;
++
++ /*
++ * Note, EXCPT_DB is assumed to be fault-like as the emulator
++ * only supports code breakpoints and general detect #DB, both
++ * of which are fault-like.
++ */
+ if (!ctxt->have_exception ||
+ exception_type(ctxt->exception.vector) == EXCPT_TRAP) {
+ kvm_rip_write(vcpu, ctxt->eip);
+@@ -9072,6 +9085,16 @@ static int inject_pending_event(struct kvm_vcpu *vcpu, bool *req_immediate_exit)
+
+ /* try to inject new event if pending */
+ if (vcpu->arch.exception.pending) {
++ /*
++ * Fault-class exceptions, except #DBs, set RF=1 in the RFLAGS
++ * value pushed on the stack. Trap-like exception and all #DBs
++ * leave RF as-is (KVM follows Intel's behavior in this regard;
++ * AMD states that code breakpoint #DBs excplitly clear RF=0).
++ *
++ * Note, most versions of Intel's SDM and AMD's APM incorrectly
++ * describe the behavior of General Detect #DBs, which are
++ * fault-like. They do _not_ set RF, a la code breakpoints.
++ */
+ if (exception_type(vcpu->arch.exception.nr) == EXCPT_FAULT)
+ __kvm_set_rflags(vcpu, kvm_get_rflags(vcpu) |
+ X86_EFLAGS_RF);
+--
+2.35.1
+
--- /dev/null
+From 8dc2ed7f7f38d46d077ebc92e20fcd8af49ca671 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 1 Sep 2022 18:41:31 +0800
+Subject: mm/hugetlb: fix races when looking up a CONT-PTE/PMD size hugetlb
+ page
+
+From: Baolin Wang <baolin.wang@linux.alibaba.com>
+
+[ Upstream commit fac35ba763ed07ba93154c95ffc0c4a55023707f ]
+
+On some architectures (like ARM64), it can support CONT-PTE/PMD size
+hugetlb, which means it can support not only PMD/PUD size hugetlb (2M and
+1G), but also CONT-PTE/PMD size(64K and 32M) if a 4K page size specified.
+
+So when looking up a CONT-PTE size hugetlb page by follow_page(), it will
+use pte_offset_map_lock() to get the pte entry lock for the CONT-PTE size
+hugetlb in follow_page_pte(). However this pte entry lock is incorrect
+for the CONT-PTE size hugetlb, since we should use huge_pte_lock() to get
+the correct lock, which is mm->page_table_lock.
+
+That means the pte entry of the CONT-PTE size hugetlb under current pte
+lock is unstable in follow_page_pte(), we can continue to migrate or
+poison the pte entry of the CONT-PTE size hugetlb, which can cause some
+potential race issues, even though they are under the 'pte lock'.
+
+For example, suppose thread A is trying to look up a CONT-PTE size hugetlb
+page by move_pages() syscall under the lock, however antoher thread B can
+migrate the CONT-PTE hugetlb page at the same time, which will cause
+thread A to get an incorrect page, if thread A also wants to do page
+migration, then data inconsistency error occurs.
+
+Moreover we have the same issue for CONT-PMD size hugetlb in
+follow_huge_pmd().
+
+To fix above issues, rename the follow_huge_pmd() as follow_huge_pmd_pte()
+to handle PMD and PTE level size hugetlb, which uses huge_pte_lock() to
+get the correct pte entry lock to make the pte entry stable.
+
+Mike said:
+
+Support for CONT_PMD/_PTE was added with bb9dd3df8ee9 ("arm64: hugetlb:
+refactor find_num_contig()"). Patch series "Support for contiguous pte
+hugepages", v4. However, I do not believe these code paths were
+executed until migration support was added with 5480280d3f2d ("arm64/mm:
+enable HugeTLB migration for contiguous bit HugeTLB pages") I would go
+with 5480280d3f2d for the Fixes: targe.
+
+Link: https://lkml.kernel.org/r/635f43bdd85ac2615a58405da82b4d33c6e5eb05.1662017562.git.baolin.wang@linux.alibaba.com
+Fixes: 5480280d3f2d ("arm64/mm: enable HugeTLB migration for contiguous bit HugeTLB pages")
+Signed-off-by: Baolin Wang <baolin.wang@linux.alibaba.com>
+Suggested-by: Mike Kravetz <mike.kravetz@oracle.com>
+Reviewed-by: Mike Kravetz <mike.kravetz@oracle.com>
+Cc: David Hildenbrand <david@redhat.com>
+Cc: Muchun Song <songmuchun@bytedance.com>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/linux/hugetlb.h | 8 ++++----
+ mm/gup.c | 14 +++++++++++++-
+ mm/hugetlb.c | 27 +++++++++++++--------------
+ 3 files changed, 30 insertions(+), 19 deletions(-)
+
+diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h
+index 22c1d935e22d..af8e7045017f 100644
+--- a/include/linux/hugetlb.h
++++ b/include/linux/hugetlb.h
+@@ -198,8 +198,8 @@ struct page *follow_huge_addr(struct mm_struct *mm, unsigned long address,
+ struct page *follow_huge_pd(struct vm_area_struct *vma,
+ unsigned long address, hugepd_t hpd,
+ int flags, int pdshift);
+-struct page *follow_huge_pmd(struct mm_struct *mm, unsigned long address,
+- pmd_t *pmd, int flags);
++struct page *follow_huge_pmd_pte(struct vm_area_struct *vma, unsigned long address,
++ int flags);
+ struct page *follow_huge_pud(struct mm_struct *mm, unsigned long address,
+ pud_t *pud, int flags);
+ struct page *follow_huge_pgd(struct mm_struct *mm, unsigned long address,
+@@ -286,8 +286,8 @@ static inline struct page *follow_huge_pd(struct vm_area_struct *vma,
+ return NULL;
+ }
+
+-static inline struct page *follow_huge_pmd(struct mm_struct *mm,
+- unsigned long address, pmd_t *pmd, int flags)
++static inline struct page *follow_huge_pmd_pte(struct vm_area_struct *vma,
++ unsigned long address, int flags)
+ {
+ return NULL;
+ }
+diff --git a/mm/gup.c b/mm/gup.c
+index 1a23cd0b4fba..69e45cbe58f8 100644
+--- a/mm/gup.c
++++ b/mm/gup.c
+@@ -509,6 +509,18 @@ static struct page *follow_page_pte(struct vm_area_struct *vma,
+ if (WARN_ON_ONCE((flags & (FOLL_PIN | FOLL_GET)) ==
+ (FOLL_PIN | FOLL_GET)))
+ return ERR_PTR(-EINVAL);
++
++ /*
++ * Considering PTE level hugetlb, like continuous-PTE hugetlb on
++ * ARM64 architecture.
++ */
++ if (is_vm_hugetlb_page(vma)) {
++ page = follow_huge_pmd_pte(vma, address, flags);
++ if (page)
++ return page;
++ return no_page_table(vma, flags);
++ }
++
+ retry:
+ if (unlikely(pmd_bad(*pmd)))
+ return no_page_table(vma, flags);
+@@ -652,7 +664,7 @@ static struct page *follow_pmd_mask(struct vm_area_struct *vma,
+ if (pmd_none(pmdval))
+ return no_page_table(vma, flags);
+ if (pmd_huge(pmdval) && is_vm_hugetlb_page(vma)) {
+- page = follow_huge_pmd(mm, address, pmd, flags);
++ page = follow_huge_pmd_pte(vma, address, flags);
+ if (page)
+ return page;
+ return no_page_table(vma, flags);
+diff --git a/mm/hugetlb.c b/mm/hugetlb.c
+index f5f8929fad51..dbb63ec3b5fa 100644
+--- a/mm/hugetlb.c
++++ b/mm/hugetlb.c
+@@ -6182,12 +6182,13 @@ follow_huge_pd(struct vm_area_struct *vma,
+ }
+
+ struct page * __weak
+-follow_huge_pmd(struct mm_struct *mm, unsigned long address,
+- pmd_t *pmd, int flags)
++follow_huge_pmd_pte(struct vm_area_struct *vma, unsigned long address, int flags)
+ {
++ struct hstate *h = hstate_vma(vma);
++ struct mm_struct *mm = vma->vm_mm;
+ struct page *page = NULL;
+ spinlock_t *ptl;
+- pte_t pte;
++ pte_t *ptep, pte;
+
+ /* FOLL_GET and FOLL_PIN are mutually exclusive. */
+ if (WARN_ON_ONCE((flags & (FOLL_PIN | FOLL_GET)) ==
+@@ -6195,17 +6196,15 @@ follow_huge_pmd(struct mm_struct *mm, unsigned long address,
+ return NULL;
+
+ retry:
+- ptl = pmd_lockptr(mm, pmd);
+- spin_lock(ptl);
+- /*
+- * make sure that the address range covered by this pmd is not
+- * unmapped from other threads.
+- */
+- if (!pmd_huge(*pmd))
+- goto out;
+- pte = huge_ptep_get((pte_t *)pmd);
++ ptep = huge_pte_offset(mm, address, huge_page_size(h));
++ if (!ptep)
++ return NULL;
++
++ ptl = huge_pte_lock(h, mm, ptep);
++ pte = huge_ptep_get(ptep);
+ if (pte_present(pte)) {
+- page = pmd_page(*pmd) + ((address & ~PMD_MASK) >> PAGE_SHIFT);
++ page = pte_page(pte) +
++ ((address & ~huge_page_mask(h)) >> PAGE_SHIFT);
+ /*
+ * try_grab_page() should always succeed here, because: a) we
+ * hold the pmd (ptl) lock, and b) we've just checked that the
+@@ -6221,7 +6220,7 @@ follow_huge_pmd(struct mm_struct *mm, unsigned long address,
+ } else {
+ if (is_hugetlb_entry_migration(pte)) {
+ spin_unlock(ptl);
+- __migration_entry_wait(mm, (pte_t *)pmd, ptl);
++ __migration_entry_wait(mm, ptep, ptl);
+ goto retry;
+ }
+ /*
+--
+2.35.1
+
--- /dev/null
+From 98dc1b78d661fcfd799d9eb79ec83301d9b882f5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 10 Sep 2021 16:31:55 -0700
+Subject: scsi: lpfc: Adjust bytes received vales during cmf timer interval
+
+From: James Smart <jsmart2021@gmail.com>
+
+[ Upstream commit d5ac69b332d8859d1f8bd5d4dee31f3267f6b0d2 ]
+
+The newly added congestion mgmt framework is seeing unexpected congestion
+FPINs and signals. In analysis, time values given to the adapter are not
+at hard time intervals. Thus the drift vs the transfer count seen is
+affecting how the framework manages things.
+
+Adjust counters to cover the drift.
+
+Link: https://lore.kernel.org/r/20210910233159.115896-11-jsmart2021@gmail.com
+Co-developed-by: Justin Tee <justin.tee@broadcom.com>
+Signed-off-by: Justin Tee <justin.tee@broadcom.com>
+Signed-off-by: James Smart <jsmart2021@gmail.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Stable-dep-of: bd269188ea94 ("scsi: lpfc: Rework MIB Rx Monitor debug info logic")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/scsi/lpfc/lpfc_init.c | 16 ++++++++++++++--
+ 1 file changed, 14 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
+index fe8b4258cdc0..38bd58fb2044 100644
+--- a/drivers/scsi/lpfc/lpfc_init.c
++++ b/drivers/scsi/lpfc/lpfc_init.c
+@@ -5870,7 +5870,7 @@ lpfc_cmf_timer(struct hrtimer *timer)
+ uint32_t io_cnt;
+ uint32_t head, tail;
+ uint32_t busy, max_read;
+- uint64_t total, rcv, lat, mbpi;
++ uint64_t total, rcv, lat, mbpi, extra;
+ int timer_interval = LPFC_CMF_INTERVAL;
+ uint32_t ms;
+ struct lpfc_cgn_stat *cgs;
+@@ -5937,7 +5937,19 @@ lpfc_cmf_timer(struct hrtimer *timer)
+ phba->hba_flag & HBA_SETUP) {
+ mbpi = phba->cmf_last_sync_bw;
+ phba->cmf_last_sync_bw = 0;
+- lpfc_issue_cmf_sync_wqe(phba, LPFC_CMF_INTERVAL, total);
++ extra = 0;
++
++ /* Calculate any extra bytes needed to account for the
++ * timer accuracy. If we are less than LPFC_CMF_INTERVAL
++ * add an extra 3% slop factor, equal to LPFC_CMF_INTERVAL
++ * add an extra 2%. The goal is to equalize total with a
++ * time > LPFC_CMF_INTERVAL or <= LPFC_CMF_INTERVAL + 1
++ */
++ if (ms == LPFC_CMF_INTERVAL)
++ extra = div_u64(total, 50);
++ else if (ms < LPFC_CMF_INTERVAL)
++ extra = div_u64(total, 33);
++ lpfc_issue_cmf_sync_wqe(phba, LPFC_CMF_INTERVAL, total + extra);
+ } else {
+ /* For Monitor mode or link down we want mbpi
+ * to be the full link speed
+--
+2.35.1
+
--- /dev/null
+From cd8e65a24380fdf2ceb02b1fce8bd31fe298843f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 3 Dec 2021 16:26:41 -0800
+Subject: scsi: lpfc: Adjust CMF total bytes and rxmonitor
+
+From: James Smart <jsmart2021@gmail.com>
+
+[ Upstream commit a6269f837045acb02904f31f05acde847ec8f8a7 ]
+
+Calculate any extra bytes needed to account for timer accuracy. If we are
+less than LPFC_CMF_INTERVAL, then calculate the adjustment needed for total
+to reflect a full LPFC_CMF_INTERVAL.
+
+Add additional info to rxmonitor, and adjust some log formatting.
+
+Link: https://lore.kernel.org/r/20211204002644.116455-7-jsmart2021@gmail.com
+Co-developed-by: Justin Tee <justin.tee@broadcom.com>
+Signed-off-by: Justin Tee <justin.tee@broadcom.com>
+Signed-off-by: James Smart <jsmart2021@gmail.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Stable-dep-of: bd269188ea94 ("scsi: lpfc: Rework MIB Rx Monitor debug info logic")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/scsi/lpfc/lpfc.h | 1 +
+ drivers/scsi/lpfc/lpfc_debugfs.c | 14 ++++++++------
+ drivers/scsi/lpfc/lpfc_debugfs.h | 2 +-
+ drivers/scsi/lpfc/lpfc_init.c | 20 ++++++++++++--------
+ 4 files changed, 22 insertions(+), 15 deletions(-)
+
+diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h
+index b2508a00bafd..924483368037 100644
+--- a/drivers/scsi/lpfc/lpfc.h
++++ b/drivers/scsi/lpfc/lpfc.h
+@@ -1611,6 +1611,7 @@ struct lpfc_hba {
+ #define LPFC_MAX_RXMONITOR_ENTRY 800
+ #define LPFC_MAX_RXMONITOR_DUMP 32
+ struct rxtable_entry {
++ uint64_t cmf_bytes; /* Total no of read bytes for CMF_SYNC_WQE */
+ uint64_t total_bytes; /* Total no of read bytes requested */
+ uint64_t rcv_bytes; /* Total no of read bytes completed */
+ uint64_t avg_io_size;
+diff --git a/drivers/scsi/lpfc/lpfc_debugfs.c b/drivers/scsi/lpfc/lpfc_debugfs.c
+index 79bc86ba59b3..61f8dcd072ac 100644
+--- a/drivers/scsi/lpfc/lpfc_debugfs.c
++++ b/drivers/scsi/lpfc/lpfc_debugfs.c
+@@ -5561,22 +5561,24 @@ lpfc_rx_monitor_read(struct file *file, char __user *buf, size_t nbytes,
+ start = tail;
+
+ len += scnprintf(buffer + len, MAX_DEBUGFS_RX_TABLE_SIZE - len,
+- " MaxBPI\t Total Data Cmd Total Data Cmpl "
+- " Latency(us) Avg IO Size\tMax IO Size IO cnt "
+- "Info BWutil(ms)\n");
++ " MaxBPI Tot_Data_CMF Tot_Data_Cmd "
++ "Tot_Data_Cmpl Lat(us) Avg_IO Max_IO "
++ "Bsy IO_cnt Info BWutil(ms)\n");
+ get_table:
+ for (i = start; i < last; i++) {
+ entry = &phba->rxtable[i];
+ len += scnprintf(buffer + len, MAX_DEBUGFS_RX_TABLE_SIZE - len,
+- "%3d:%12lld %12lld\t%12lld\t"
+- "%8lldus\t%8lld\t%10lld "
+- "%8d %2d %2d(%2d)\n",
++ "%3d:%12lld %12lld %12lld %12lld "
++ "%7lldus %8lld %7lld "
++ "%2d %4d %2d %2d(%2d)\n",
+ i, entry->max_bytes_per_interval,
++ entry->cmf_bytes,
+ entry->total_bytes,
+ entry->rcv_bytes,
+ entry->avg_io_latency,
+ entry->avg_io_size,
+ entry->max_read_cnt,
++ entry->cmf_busy,
+ entry->io_cnt,
+ entry->cmf_info,
+ entry->timer_utilization,
+diff --git a/drivers/scsi/lpfc/lpfc_debugfs.h b/drivers/scsi/lpfc/lpfc_debugfs.h
+index a5bf71b34972..6dd361c1fd31 100644
+--- a/drivers/scsi/lpfc/lpfc_debugfs.h
++++ b/drivers/scsi/lpfc/lpfc_debugfs.h
+@@ -282,7 +282,7 @@ struct lpfc_idiag {
+ void *ptr_private;
+ };
+
+-#define MAX_DEBUGFS_RX_TABLE_SIZE (100 * LPFC_MAX_RXMONITOR_ENTRY)
++#define MAX_DEBUGFS_RX_TABLE_SIZE (128 * LPFC_MAX_RXMONITOR_ENTRY)
+ struct lpfc_rx_monitor_debug {
+ char *i_private;
+ char *buffer;
+diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
+index 38bd58fb2044..5dad0b07953f 100644
+--- a/drivers/scsi/lpfc/lpfc_init.c
++++ b/drivers/scsi/lpfc/lpfc_init.c
+@@ -5870,7 +5870,7 @@ lpfc_cmf_timer(struct hrtimer *timer)
+ uint32_t io_cnt;
+ uint32_t head, tail;
+ uint32_t busy, max_read;
+- uint64_t total, rcv, lat, mbpi, extra;
++ uint64_t total, rcv, lat, mbpi, extra, cnt;
+ int timer_interval = LPFC_CMF_INTERVAL;
+ uint32_t ms;
+ struct lpfc_cgn_stat *cgs;
+@@ -5941,20 +5941,23 @@ lpfc_cmf_timer(struct hrtimer *timer)
+
+ /* Calculate any extra bytes needed to account for the
+ * timer accuracy. If we are less than LPFC_CMF_INTERVAL
+- * add an extra 3% slop factor, equal to LPFC_CMF_INTERVAL
+- * add an extra 2%. The goal is to equalize total with a
+- * time > LPFC_CMF_INTERVAL or <= LPFC_CMF_INTERVAL + 1
++ * calculate the adjustment needed for total to reflect
++ * a full LPFC_CMF_INTERVAL.
+ */
+- if (ms == LPFC_CMF_INTERVAL)
+- extra = div_u64(total, 50);
+- else if (ms < LPFC_CMF_INTERVAL)
+- extra = div_u64(total, 33);
++ if (ms && ms < LPFC_CMF_INTERVAL) {
++ cnt = div_u64(total, ms); /* bytes per ms */
++ cnt *= LPFC_CMF_INTERVAL; /* what total should be */
++ if (cnt > mbpi)
++ cnt = mbpi;
++ extra = cnt - total;
++ }
+ lpfc_issue_cmf_sync_wqe(phba, LPFC_CMF_INTERVAL, total + extra);
+ } else {
+ /* For Monitor mode or link down we want mbpi
+ * to be the full link speed
+ */
+ mbpi = phba->cmf_link_byte_count;
++ extra = 0;
+ }
+ phba->cmf_timer_cnt++;
+
+@@ -5985,6 +5988,7 @@ lpfc_cmf_timer(struct hrtimer *timer)
+ LPFC_RXMONITOR_TABLE_IN_USE);
+ entry = &phba->rxtable[head];
+ entry->total_bytes = total;
++ entry->cmf_bytes = total + extra;
+ entry->rcv_bytes = rcv;
+ entry->cmf_busy = busy;
+ entry->cmf_info = phba->cmf_active_info;
+--
+2.35.1
+
--- /dev/null
+From de2e558fcdd27d40ca8dab14aa33f5ec3dfb5ad6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 18 Aug 2022 18:17:32 -0700
+Subject: scsi: lpfc: Rework MIB Rx Monitor debug info logic
+
+From: James Smart <jsmart2021@gmail.com>
+
+[ Upstream commit bd269188ea94e40ab002cad7b0df8f12b8f0de54 ]
+
+The kernel test robot reported the following sparse warning:
+
+arch/arm64/include/asm/cmpxchg.h:88:1: sparse: sparse: cast truncates
+ bits from constant value (369 becomes 69)
+
+On arm64, atomic_xchg only works on 8-bit byte fields. Thus, the macro
+usage of LPFC_RXMONITOR_TABLE_IN_USE can be unintentionally truncated
+leading to all logic involving the LPFC_RXMONITOR_TABLE_IN_USE macro to not
+work properly.
+
+Replace the Rx Table atomic_t indexing logic with a new
+lpfc_rx_info_monitor structure that holds a circular ring buffer. For
+locking semantics, a spinlock_t is used.
+
+Link: https://lore.kernel.org/r/20220819011736.14141-4-jsmart2021@gmail.com
+Fixes: 17b27ac59224 ("scsi: lpfc: Add rx monitoring statistics")
+Cc: <stable@vger.kernel.org> # v5.15+
+Co-developed-by: Justin Tee <justin.tee@broadcom.com>
+Signed-off-by: Justin Tee <justin.tee@broadcom.com>
+Signed-off-by: James Smart <jsmart2021@gmail.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/scsi/lpfc/lpfc.h | 14 ++-
+ drivers/scsi/lpfc/lpfc_crtn.h | 8 ++
+ drivers/scsi/lpfc/lpfc_debugfs.c | 59 ++--------
+ drivers/scsi/lpfc/lpfc_debugfs.h | 2 +-
+ drivers/scsi/lpfc/lpfc_init.c | 83 ++++----------
+ drivers/scsi/lpfc/lpfc_mem.c | 9 +-
+ drivers/scsi/lpfc/lpfc_sli.c | 190 +++++++++++++++++++++++++++++--
+ 7 files changed, 240 insertions(+), 125 deletions(-)
+
+diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h
+index 924483368037..457ff86e02b3 100644
+--- a/drivers/scsi/lpfc/lpfc.h
++++ b/drivers/scsi/lpfc/lpfc.h
+@@ -1558,10 +1558,7 @@ struct lpfc_hba {
+ u32 cgn_acqe_cnt;
+
+ /* RX monitor handling for CMF */
+- struct rxtable_entry *rxtable; /* RX_monitor information */
+- atomic_t rxtable_idx_head;
+-#define LPFC_RXMONITOR_TABLE_IN_USE (LPFC_MAX_RXMONITOR_ENTRY + 73)
+- atomic_t rxtable_idx_tail;
++ struct lpfc_rx_info_monitor *rx_monitor;
+ atomic_t rx_max_read_cnt; /* Maximum read bytes */
+ uint64_t rx_block_cnt;
+
+@@ -1610,7 +1607,7 @@ struct lpfc_hba {
+
+ #define LPFC_MAX_RXMONITOR_ENTRY 800
+ #define LPFC_MAX_RXMONITOR_DUMP 32
+-struct rxtable_entry {
++struct rx_info_entry {
+ uint64_t cmf_bytes; /* Total no of read bytes for CMF_SYNC_WQE */
+ uint64_t total_bytes; /* Total no of read bytes requested */
+ uint64_t rcv_bytes; /* Total no of read bytes completed */
+@@ -1625,6 +1622,13 @@ struct rxtable_entry {
+ uint32_t timer_interval;
+ };
+
++struct lpfc_rx_info_monitor {
++ struct rx_info_entry *ring; /* info organized in a circular buffer */
++ u32 head_idx, tail_idx; /* index to head/tail of ring */
++ spinlock_t lock; /* spinlock for ring */
++ u32 entries; /* storing number entries/size of ring */
++};
++
+ static inline struct Scsi_Host *
+ lpfc_shost_from_vport(struct lpfc_vport *vport)
+ {
+diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h
+index c9770b1d2366..470239394e64 100644
+--- a/drivers/scsi/lpfc/lpfc_crtn.h
++++ b/drivers/scsi/lpfc/lpfc_crtn.h
+@@ -90,6 +90,14 @@ void lpfc_cgn_dump_rxmonitor(struct lpfc_hba *phba);
+ void lpfc_cgn_update_stat(struct lpfc_hba *phba, uint32_t dtag);
+ void lpfc_unblock_requests(struct lpfc_hba *phba);
+ void lpfc_block_requests(struct lpfc_hba *phba);
++int lpfc_rx_monitor_create_ring(struct lpfc_rx_info_monitor *rx_monitor,
++ u32 entries);
++void lpfc_rx_monitor_destroy_ring(struct lpfc_rx_info_monitor *rx_monitor);
++void lpfc_rx_monitor_record(struct lpfc_rx_info_monitor *rx_monitor,
++ struct rx_info_entry *entry);
++u32 lpfc_rx_monitor_report(struct lpfc_hba *phba,
++ struct lpfc_rx_info_monitor *rx_monitor, char *buf,
++ u32 buf_len, u32 max_read_entries);
+
+ void lpfc_mbx_cmpl_local_config_link(struct lpfc_hba *, LPFC_MBOXQ_t *);
+ void lpfc_mbx_cmpl_reg_login(struct lpfc_hba *, LPFC_MBOXQ_t *);
+diff --git a/drivers/scsi/lpfc/lpfc_debugfs.c b/drivers/scsi/lpfc/lpfc_debugfs.c
+index 61f8dcd072ac..8e8bbe734e87 100644
+--- a/drivers/scsi/lpfc/lpfc_debugfs.c
++++ b/drivers/scsi/lpfc/lpfc_debugfs.c
+@@ -5520,7 +5520,7 @@ lpfc_rx_monitor_open(struct inode *inode, struct file *file)
+ if (!debug)
+ goto out;
+
+- debug->buffer = vmalloc(MAX_DEBUGFS_RX_TABLE_SIZE);
++ debug->buffer = vmalloc(MAX_DEBUGFS_RX_INFO_SIZE);
+ if (!debug->buffer) {
+ kfree(debug);
+ goto out;
+@@ -5541,57 +5541,18 @@ lpfc_rx_monitor_read(struct file *file, char __user *buf, size_t nbytes,
+ struct lpfc_rx_monitor_debug *debug = file->private_data;
+ struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private;
+ char *buffer = debug->buffer;
+- struct rxtable_entry *entry;
+- int i, len = 0, head, tail, last, start;
+-
+- head = atomic_read(&phba->rxtable_idx_head);
+- while (head == LPFC_RXMONITOR_TABLE_IN_USE) {
+- /* Table is getting updated */
+- msleep(20);
+- head = atomic_read(&phba->rxtable_idx_head);
+- }
+
+- tail = atomic_xchg(&phba->rxtable_idx_tail, head);
+- if (!phba->rxtable || head == tail) {
+- len += scnprintf(buffer + len, MAX_DEBUGFS_RX_TABLE_SIZE - len,
+- "Rxtable is empty\n");
+- goto out;
+- }
+- last = (head > tail) ? head : LPFC_MAX_RXMONITOR_ENTRY;
+- start = tail;
+-
+- len += scnprintf(buffer + len, MAX_DEBUGFS_RX_TABLE_SIZE - len,
+- " MaxBPI Tot_Data_CMF Tot_Data_Cmd "
+- "Tot_Data_Cmpl Lat(us) Avg_IO Max_IO "
+- "Bsy IO_cnt Info BWutil(ms)\n");
+-get_table:
+- for (i = start; i < last; i++) {
+- entry = &phba->rxtable[i];
+- len += scnprintf(buffer + len, MAX_DEBUGFS_RX_TABLE_SIZE - len,
+- "%3d:%12lld %12lld %12lld %12lld "
+- "%7lldus %8lld %7lld "
+- "%2d %4d %2d %2d(%2d)\n",
+- i, entry->max_bytes_per_interval,
+- entry->cmf_bytes,
+- entry->total_bytes,
+- entry->rcv_bytes,
+- entry->avg_io_latency,
+- entry->avg_io_size,
+- entry->max_read_cnt,
+- entry->cmf_busy,
+- entry->io_cnt,
+- entry->cmf_info,
+- entry->timer_utilization,
+- entry->timer_interval);
++ if (!phba->rx_monitor) {
++ scnprintf(buffer, MAX_DEBUGFS_RX_INFO_SIZE,
++ "Rx Monitor Info is empty.\n");
++ } else {
++ lpfc_rx_monitor_report(phba, phba->rx_monitor, buffer,
++ MAX_DEBUGFS_RX_INFO_SIZE,
++ LPFC_MAX_RXMONITOR_ENTRY);
+ }
+
+- if (head != last) {
+- start = 0;
+- last = head;
+- goto get_table;
+- }
+-out:
+- return simple_read_from_buffer(buf, nbytes, ppos, buffer, len);
++ return simple_read_from_buffer(buf, nbytes, ppos, buffer,
++ strlen(buffer));
+ }
+
+ static int
+diff --git a/drivers/scsi/lpfc/lpfc_debugfs.h b/drivers/scsi/lpfc/lpfc_debugfs.h
+index 6dd361c1fd31..f71e5b6311ac 100644
+--- a/drivers/scsi/lpfc/lpfc_debugfs.h
++++ b/drivers/scsi/lpfc/lpfc_debugfs.h
+@@ -282,7 +282,7 @@ struct lpfc_idiag {
+ void *ptr_private;
+ };
+
+-#define MAX_DEBUGFS_RX_TABLE_SIZE (128 * LPFC_MAX_RXMONITOR_ENTRY)
++#define MAX_DEBUGFS_RX_INFO_SIZE (128 * LPFC_MAX_RXMONITOR_ENTRY)
+ struct lpfc_rx_monitor_debug {
+ char *i_private;
+ char *buffer;
+diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
+index 5dad0b07953f..855817f6fe67 100644
+--- a/drivers/scsi/lpfc/lpfc_init.c
++++ b/drivers/scsi/lpfc/lpfc_init.c
+@@ -5428,38 +5428,12 @@ lpfc_async_link_speed_to_read_top(struct lpfc_hba *phba, uint8_t speed_code)
+ void
+ lpfc_cgn_dump_rxmonitor(struct lpfc_hba *phba)
+ {
+- struct rxtable_entry *entry;
+- int cnt = 0, head, tail, last, start;
+-
+- head = atomic_read(&phba->rxtable_idx_head);
+- tail = atomic_read(&phba->rxtable_idx_tail);
+- if (!phba->rxtable || head == tail) {
+- lpfc_printf_log(phba, KERN_ERR, LOG_CGN_MGMT,
+- "4411 Rxtable is empty\n");
+- return;
+- }
+- last = tail;
+- start = head;
+-
+- /* Display the last LPFC_MAX_RXMONITOR_DUMP entries from the rxtable */
+- while (start != last) {
+- if (start)
+- start--;
+- else
+- start = LPFC_MAX_RXMONITOR_ENTRY - 1;
+- entry = &phba->rxtable[start];
++ if (!phba->rx_monitor) {
+ lpfc_printf_log(phba, KERN_INFO, LOG_CGN_MGMT,
+- "4410 %02d: MBPI %lld Xmit %lld Cmpl %lld "
+- "Lat %lld ASz %lld Info %02d BWUtil %d "
+- "Int %d slot %d\n",
+- cnt, entry->max_bytes_per_interval,
+- entry->total_bytes, entry->rcv_bytes,
+- entry->avg_io_latency, entry->avg_io_size,
+- entry->cmf_info, entry->timer_utilization,
+- entry->timer_interval, start);
+- cnt++;
+- if (cnt >= LPFC_MAX_RXMONITOR_DUMP)
+- return;
++ "4411 Rx Monitor Info is empty.\n");
++ } else {
++ lpfc_rx_monitor_report(phba, phba->rx_monitor, NULL, 0,
++ LPFC_MAX_RXMONITOR_DUMP);
+ }
+ }
+
+@@ -5866,9 +5840,8 @@ lpfc_cmf_timer(struct hrtimer *timer)
+ {
+ struct lpfc_hba *phba = container_of(timer, struct lpfc_hba,
+ cmf_timer);
+- struct rxtable_entry *entry;
++ struct rx_info_entry entry;
+ uint32_t io_cnt;
+- uint32_t head, tail;
+ uint32_t busy, max_read;
+ uint64_t total, rcv, lat, mbpi, extra, cnt;
+ int timer_interval = LPFC_CMF_INTERVAL;
+@@ -5983,40 +5956,30 @@ lpfc_cmf_timer(struct hrtimer *timer)
+ }
+
+ /* Save rxmonitor information for debug */
+- if (phba->rxtable) {
+- head = atomic_xchg(&phba->rxtable_idx_head,
+- LPFC_RXMONITOR_TABLE_IN_USE);
+- entry = &phba->rxtable[head];
+- entry->total_bytes = total;
+- entry->cmf_bytes = total + extra;
+- entry->rcv_bytes = rcv;
+- entry->cmf_busy = busy;
+- entry->cmf_info = phba->cmf_active_info;
++ if (phba->rx_monitor) {
++ entry.total_bytes = total;
++ entry.cmf_bytes = total + extra;
++ entry.rcv_bytes = rcv;
++ entry.cmf_busy = busy;
++ entry.cmf_info = phba->cmf_active_info;
+ if (io_cnt) {
+- entry->avg_io_latency = div_u64(lat, io_cnt);
+- entry->avg_io_size = div_u64(rcv, io_cnt);
++ entry.avg_io_latency = div_u64(lat, io_cnt);
++ entry.avg_io_size = div_u64(rcv, io_cnt);
+ } else {
+- entry->avg_io_latency = 0;
+- entry->avg_io_size = 0;
++ entry.avg_io_latency = 0;
++ entry.avg_io_size = 0;
+ }
+- entry->max_read_cnt = max_read;
+- entry->io_cnt = io_cnt;
+- entry->max_bytes_per_interval = mbpi;
++ entry.max_read_cnt = max_read;
++ entry.io_cnt = io_cnt;
++ entry.max_bytes_per_interval = mbpi;
+ if (phba->cmf_active_mode == LPFC_CFG_MANAGED)
+- entry->timer_utilization = phba->cmf_last_ts;
++ entry.timer_utilization = phba->cmf_last_ts;
+ else
+- entry->timer_utilization = ms;
+- entry->timer_interval = ms;
++ entry.timer_utilization = ms;
++ entry.timer_interval = ms;
+ phba->cmf_last_ts = 0;
+
+- /* Increment rxtable index */
+- head = (head + 1) % LPFC_MAX_RXMONITOR_ENTRY;
+- tail = atomic_read(&phba->rxtable_idx_tail);
+- if (head == tail) {
+- tail = (tail + 1) % LPFC_MAX_RXMONITOR_ENTRY;
+- atomic_set(&phba->rxtable_idx_tail, tail);
+- }
+- atomic_set(&phba->rxtable_idx_head, head);
++ lpfc_rx_monitor_record(phba->rx_monitor, &entry);
+ }
+
+ if (phba->cmf_active_mode == LPFC_CFG_MONITOR) {
+diff --git a/drivers/scsi/lpfc/lpfc_mem.c b/drivers/scsi/lpfc/lpfc_mem.c
+index 870e53b8f81d..5d36b3514864 100644
+--- a/drivers/scsi/lpfc/lpfc_mem.c
++++ b/drivers/scsi/lpfc/lpfc_mem.c
+@@ -344,9 +344,12 @@ lpfc_mem_free_all(struct lpfc_hba *phba)
+ phba->cgn_i = NULL;
+ }
+
+- /* Free RX table */
+- kfree(phba->rxtable);
+- phba->rxtable = NULL;
++ /* Free RX Monitor */
++ if (phba->rx_monitor) {
++ lpfc_rx_monitor_destroy_ring(phba->rx_monitor);
++ kfree(phba->rx_monitor);
++ phba->rx_monitor = NULL;
++ }
+
+ /* Free the iocb lookup array */
+ kfree(psli->iocbq_lookup);
+diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
+index 0024c0e0afd3..d6e761adf1f1 100644
+--- a/drivers/scsi/lpfc/lpfc_sli.c
++++ b/drivers/scsi/lpfc/lpfc_sli.c
+@@ -7878,6 +7878,172 @@ static void lpfc_sli4_dip(struct lpfc_hba *phba)
+ }
+ }
+
++/**
++ * lpfc_rx_monitor_create_ring - Initialize ring buffer for rx_monitor
++ * @rx_monitor: Pointer to lpfc_rx_info_monitor object
++ * @entries: Number of rx_info_entry objects to allocate in ring
++ *
++ * Return:
++ * 0 - Success
++ * ENOMEM - Failure to kmalloc
++ **/
++int lpfc_rx_monitor_create_ring(struct lpfc_rx_info_monitor *rx_monitor,
++ u32 entries)
++{
++ rx_monitor->ring = kmalloc_array(entries, sizeof(struct rx_info_entry),
++ GFP_KERNEL);
++ if (!rx_monitor->ring)
++ return -ENOMEM;
++
++ rx_monitor->head_idx = 0;
++ rx_monitor->tail_idx = 0;
++ spin_lock_init(&rx_monitor->lock);
++ rx_monitor->entries = entries;
++
++ return 0;
++}
++
++/**
++ * lpfc_rx_monitor_destroy_ring - Free ring buffer for rx_monitor
++ * @rx_monitor: Pointer to lpfc_rx_info_monitor object
++ **/
++void lpfc_rx_monitor_destroy_ring(struct lpfc_rx_info_monitor *rx_monitor)
++{
++ spin_lock(&rx_monitor->lock);
++ kfree(rx_monitor->ring);
++ rx_monitor->ring = NULL;
++ rx_monitor->entries = 0;
++ rx_monitor->head_idx = 0;
++ rx_monitor->tail_idx = 0;
++ spin_unlock(&rx_monitor->lock);
++}
++
++/**
++ * lpfc_rx_monitor_record - Insert an entry into rx_monitor's ring
++ * @rx_monitor: Pointer to lpfc_rx_info_monitor object
++ * @entry: Pointer to rx_info_entry
++ *
++ * Used to insert an rx_info_entry into rx_monitor's ring. Note that this is a
++ * deep copy of rx_info_entry not a shallow copy of the rx_info_entry ptr.
++ *
++ * This is called from lpfc_cmf_timer, which is in timer/softirq context.
++ *
++ * In cases of old data overflow, we do a best effort of FIFO order.
++ **/
++void lpfc_rx_monitor_record(struct lpfc_rx_info_monitor *rx_monitor,
++ struct rx_info_entry *entry)
++{
++ struct rx_info_entry *ring = rx_monitor->ring;
++ u32 *head_idx = &rx_monitor->head_idx;
++ u32 *tail_idx = &rx_monitor->tail_idx;
++ spinlock_t *ring_lock = &rx_monitor->lock;
++ u32 ring_size = rx_monitor->entries;
++
++ spin_lock(ring_lock);
++ memcpy(&ring[*tail_idx], entry, sizeof(*entry));
++ *tail_idx = (*tail_idx + 1) % ring_size;
++
++ /* Best effort of FIFO saved data */
++ if (*tail_idx == *head_idx)
++ *head_idx = (*head_idx + 1) % ring_size;
++
++ spin_unlock(ring_lock);
++}
++
++/**
++ * lpfc_rx_monitor_report - Read out rx_monitor's ring
++ * @phba: Pointer to lpfc_hba object
++ * @rx_monitor: Pointer to lpfc_rx_info_monitor object
++ * @buf: Pointer to char buffer that will contain rx monitor info data
++ * @buf_len: Length buf including null char
++ * @max_read_entries: Maximum number of entries to read out of ring
++ *
++ * Used to dump/read what's in rx_monitor's ring buffer.
++ *
++ * If buf is NULL || buf_len == 0, then it is implied that we want to log the
++ * information to kmsg instead of filling out buf.
++ *
++ * Return:
++ * Number of entries read out of the ring
++ **/
++u32 lpfc_rx_monitor_report(struct lpfc_hba *phba,
++ struct lpfc_rx_info_monitor *rx_monitor, char *buf,
++ u32 buf_len, u32 max_read_entries)
++{
++ struct rx_info_entry *ring = rx_monitor->ring;
++ struct rx_info_entry *entry;
++ u32 *head_idx = &rx_monitor->head_idx;
++ u32 *tail_idx = &rx_monitor->tail_idx;
++ spinlock_t *ring_lock = &rx_monitor->lock;
++ u32 ring_size = rx_monitor->entries;
++ u32 cnt = 0;
++ char tmp[DBG_LOG_STR_SZ] = {0};
++ bool log_to_kmsg = (!buf || !buf_len) ? true : false;
++
++ if (!log_to_kmsg) {
++ /* clear the buffer to be sure */
++ memset(buf, 0, buf_len);
++
++ scnprintf(buf, buf_len, "\t%-16s%-16s%-16s%-16s%-8s%-8s%-8s"
++ "%-8s%-8s%-8s%-16s\n",
++ "MaxBPI", "Tot_Data_CMF",
++ "Tot_Data_Cmd", "Tot_Data_Cmpl",
++ "Lat(us)", "Avg_IO", "Max_IO", "Bsy",
++ "IO_cnt", "Info", "BWutil(ms)");
++ }
++
++ /* Needs to be _bh because record is called from timer interrupt
++ * context
++ */
++ spin_lock_bh(ring_lock);
++ while (*head_idx != *tail_idx) {
++ entry = &ring[*head_idx];
++
++ /* Read out this entry's data. */
++ if (!log_to_kmsg) {
++ /* If !log_to_kmsg, then store to buf. */
++ scnprintf(tmp, sizeof(tmp),
++ "%03d:\t%-16llu%-16llu%-16llu%-16llu%-8llu"
++ "%-8llu%-8llu%-8u%-8u%-8u%u(%u)\n",
++ *head_idx, entry->max_bytes_per_interval,
++ entry->cmf_bytes, entry->total_bytes,
++ entry->rcv_bytes, entry->avg_io_latency,
++ entry->avg_io_size, entry->max_read_cnt,
++ entry->cmf_busy, entry->io_cnt,
++ entry->cmf_info, entry->timer_utilization,
++ entry->timer_interval);
++
++ /* Check for buffer overflow */
++ if ((strlen(buf) + strlen(tmp)) >= buf_len)
++ break;
++
++ /* Append entry's data to buffer */
++ strlcat(buf, tmp, buf_len);
++ } else {
++ lpfc_printf_log(phba, KERN_INFO, LOG_CGN_MGMT,
++ "4410 %02u: MBPI %llu Xmit %llu "
++ "Cmpl %llu Lat %llu ASz %llu Info %02u "
++ "BWUtil %u Int %u slot %u\n",
++ cnt, entry->max_bytes_per_interval,
++ entry->total_bytes, entry->rcv_bytes,
++ entry->avg_io_latency,
++ entry->avg_io_size, entry->cmf_info,
++ entry->timer_utilization,
++ entry->timer_interval, *head_idx);
++ }
++
++ *head_idx = (*head_idx + 1) % ring_size;
++
++ /* Don't feed more than max_read_entries */
++ cnt++;
++ if (cnt >= max_read_entries)
++ break;
++ }
++ spin_unlock_bh(ring_lock);
++
++ return cnt;
++}
++
+ /**
+ * lpfc_cmf_setup - Initialize idle_stat tracking
+ * @phba: Pointer to HBA context object.
+@@ -8069,19 +8235,29 @@ lpfc_cmf_setup(struct lpfc_hba *phba)
+ phba->cmf_interval_rate = LPFC_CMF_INTERVAL;
+
+ /* Allocate RX Monitor Buffer */
+- if (!phba->rxtable) {
+- phba->rxtable = kmalloc_array(LPFC_MAX_RXMONITOR_ENTRY,
+- sizeof(struct rxtable_entry),
+- GFP_KERNEL);
+- if (!phba->rxtable) {
++ if (!phba->rx_monitor) {
++ phba->rx_monitor = kzalloc(sizeof(*phba->rx_monitor),
++ GFP_KERNEL);
++
++ if (!phba->rx_monitor) {
+ lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ "2644 Failed to alloc memory "
+ "for RX Monitor Buffer\n");
+ return -ENOMEM;
+ }
++
++ /* Instruct the rx_monitor object to instantiate its ring */
++ if (lpfc_rx_monitor_create_ring(phba->rx_monitor,
++ LPFC_MAX_RXMONITOR_ENTRY)) {
++ kfree(phba->rx_monitor);
++ phba->rx_monitor = NULL;
++ lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
++ "2645 Failed to alloc memory "
++ "for RX Monitor's Ring\n");
++ return -ENOMEM;
++ }
+ }
+- atomic_set(&phba->rxtable_idx_head, 0);
+- atomic_set(&phba->rxtable_idx_tail, 0);
++
+ return 0;
+ }
+
+--
+2.35.1
+
--- /dev/null
+From 42f252f2e326827b9fa5a41d0a2a0f7dbcf8a496 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 26 Aug 2022 03:25:58 -0700
+Subject: scsi: qla2xxx: Define static symbols
+
+From: Nilesh Javali <njavali@marvell.com>
+
+[ Upstream commit 2c57d0defa22b2339c06364a275bcc9048a77255 ]
+
+drivers/scsi/qla2xxx/qla_os.c:40:20: warning: symbol 'qla_trc_array'
+was not declared. Should it be static?
+drivers/scsi/qla2xxx/qla_os.c:345:5: warning: symbol
+'ql2xdelay_before_pci_error_handling' was not declared.
+Should it be static?
+
+Define qla_trc_array and ql2xdelay_before_pci_error_handling as static to
+fix sparse warnings.
+
+Link: https://lore.kernel.org/r/20220826102559.17474-7-njavali@marvell.com
+Cc: stable@vger.kernel.org
+Reported-by: kernel test robot <lkp@intel.com>
+Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com>
+Signed-off-by: Nilesh Javali <njavali@marvell.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/scsi/qla2xxx/qla_os.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
+index abb13176e4f1..84c36b58f4eb 100644
+--- a/drivers/scsi/qla2xxx/qla_os.c
++++ b/drivers/scsi/qla2xxx/qla_os.c
+@@ -37,7 +37,7 @@ static int apidev_major;
+ */
+ struct kmem_cache *srb_cachep;
+
+-struct trace_array *qla_trc_array;
++static struct trace_array *qla_trc_array;
+
+ int ql2xfulldump_on_mpifail;
+ module_param(ql2xfulldump_on_mpifail, int, S_IRUGO | S_IWUSR);
+@@ -342,7 +342,7 @@ MODULE_PARM_DESC(ql2xabts_wait_nvme,
+ "To wait for ABTS response on I/O timeouts for NVMe. (default: 1)");
+
+
+-u32 ql2xdelay_before_pci_error_handling = 5;
++static u32 ql2xdelay_before_pci_error_handling = 5;
+ module_param(ql2xdelay_before_pci_error_handling, uint, 0644);
+ MODULE_PARM_DESC(ql2xdelay_before_pci_error_handling,
+ "Number of seconds delayed before qla begin PCI error self-handling (default: 5).\n");
+--
+2.35.1
+
--- /dev/null
+From 67f47c36511ed0d76b6944f3d10747f6da300191 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 26 Aug 2022 03:25:57 -0700
+Subject: scsi: qla2xxx: Enhance driver tracing with separate tunable and more
+
+From: Arun Easi <aeasi@marvell.com>
+
+[ Upstream commit 8bfc149ba24cb985d593c0b2ddcf03ce42febe0c ]
+
+Older tracing of driver messages was to:
+
+ - log only debug messages to kernel main trace buffer; and
+
+ - log only if extended logging bits corresponding to this message is
+ off
+
+This has been modified and extended as follows:
+
+ - Tracing is now controlled via ql2xextended_error_logging_ktrace
+ module parameter. Bit usages same as ql2xextended_error_logging.
+
+ - Tracing uses "qla2xxx" trace instance, unless instance creation have
+ issues.
+
+ - Tracing is enabled (compile time tunable).
+
+ - All driver messages, include debug and log messages are now traced in
+ kernel trace buffer.
+
+Trace messages can be viewed by looking at the qla2xxx instance at:
+
+ /sys/kernel/tracing/instances/qla2xxx/trace
+
+Trace tunable that takes the same bit mask as ql2xextended_error_logging
+is:
+
+ ql2xextended_error_logging_ktrace (default=1)
+
+Link: https://lore.kernel.org/r/20220826102559.17474-6-njavali@marvell.com
+Suggested-by: Daniel Wagner <dwagner@suse.de>
+Suggested-by: Steven Rostedt <rostedt@goodmis.org>
+Tested-by: Himanshu Madhani <himanshu.madhani@oracle.com>
+Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com>
+Reviewed-by: Daniel Wagner <dwagner@suse.de>
+Signed-off-by: Arun Easi <aeasi@marvell.com>
+Signed-off-by: Nilesh Javali <njavali@marvell.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Stable-dep-of: 2c57d0defa22 ("scsi: qla2xxx: Define static symbols")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/scsi/qla2xxx/qla_dbg.c | 50 ++++++++++++++++++++++++----------
+ drivers/scsi/qla2xxx/qla_dbg.h | 43 +++++++++++++++++++++++++++++
+ drivers/scsi/qla2xxx/qla_gbl.h | 1 +
+ drivers/scsi/qla2xxx/qla_os.c | 35 ++++++++++++++++++++++++
+ 4 files changed, 115 insertions(+), 14 deletions(-)
+
+diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c
+index 7cf1f78cbaee..d7e8454304ce 100644
+--- a/drivers/scsi/qla2xxx/qla_dbg.c
++++ b/drivers/scsi/qla2xxx/qla_dbg.c
+@@ -2455,7 +2455,7 @@ qla83xx_fw_dump(scsi_qla_host_t *vha)
+ /****************************************************************************/
+
+ /* Write the debug message prefix into @pbuf. */
+-static void ql_dbg_prefix(char *pbuf, int pbuf_size,
++static void ql_dbg_prefix(char *pbuf, int pbuf_size, struct pci_dev *pdev,
+ const scsi_qla_host_t *vha, uint msg_id)
+ {
+ if (vha) {
+@@ -2464,6 +2464,9 @@ static void ql_dbg_prefix(char *pbuf, int pbuf_size,
+ /* <module-name> [<dev-name>]-<msg-id>:<host>: */
+ snprintf(pbuf, pbuf_size, "%s [%s]-%04x:%lu: ", QL_MSGHDR,
+ dev_name(&(pdev->dev)), msg_id, vha->host_no);
++ } else if (pdev) {
++ snprintf(pbuf, pbuf_size, "%s [%s]-%04x: : ", QL_MSGHDR,
++ dev_name(&pdev->dev), msg_id);
+ } else {
+ /* <module-name> [<dev-name>]-<msg-id>: : */
+ snprintf(pbuf, pbuf_size, "%s [%s]-%04x: : ", QL_MSGHDR,
+@@ -2491,20 +2494,20 @@ ql_dbg(uint level, scsi_qla_host_t *vha, uint id, const char *fmt, ...)
+ struct va_format vaf;
+ char pbuf[64];
+
+- if (!ql_mask_match(level) && !trace_ql_dbg_log_enabled())
++ ql_ktrace(1, level, pbuf, NULL, vha, id, fmt);
++
++ if (!ql_mask_match(level))
+ return;
+
++ if (!pbuf[0]) /* set by ql_ktrace */
++ ql_dbg_prefix(pbuf, ARRAY_SIZE(pbuf), NULL, vha, id);
++
+ va_start(va, fmt);
+
+ vaf.fmt = fmt;
+ vaf.va = &va;
+
+- ql_dbg_prefix(pbuf, ARRAY_SIZE(pbuf), vha, id);
+-
+- if (!ql_mask_match(level))
+- trace_ql_dbg_log(pbuf, &vaf);
+- else
+- pr_warn("%s%pV", pbuf, &vaf);
++ pr_warn("%s%pV", pbuf, &vaf);
+
+ va_end(va);
+
+@@ -2533,6 +2536,9 @@ ql_dbg_pci(uint level, struct pci_dev *pdev, uint id, const char *fmt, ...)
+
+ if (pdev == NULL)
+ return;
++
++ ql_ktrace(1, level, pbuf, pdev, NULL, id, fmt);
++
+ if (!ql_mask_match(level))
+ return;
+
+@@ -2541,7 +2547,9 @@ ql_dbg_pci(uint level, struct pci_dev *pdev, uint id, const char *fmt, ...)
+ vaf.fmt = fmt;
+ vaf.va = &va;
+
+- ql_dbg_prefix(pbuf, ARRAY_SIZE(pbuf), NULL, id + ql_dbg_offset);
++ if (!pbuf[0]) /* set by ql_ktrace */
++ ql_dbg_prefix(pbuf, ARRAY_SIZE(pbuf), pdev, NULL,
++ id + ql_dbg_offset);
+ pr_warn("%s%pV", pbuf, &vaf);
+
+ va_end(va);
+@@ -2570,7 +2578,10 @@ ql_log(uint level, scsi_qla_host_t *vha, uint id, const char *fmt, ...)
+ if (level > ql_errlev)
+ return;
+
+- ql_dbg_prefix(pbuf, ARRAY_SIZE(pbuf), vha, id);
++ ql_ktrace(0, level, pbuf, NULL, vha, id, fmt);
++
++ if (!pbuf[0]) /* set by ql_ktrace */
++ ql_dbg_prefix(pbuf, ARRAY_SIZE(pbuf), NULL, vha, id);
+
+ va_start(va, fmt);
+
+@@ -2621,7 +2632,10 @@ ql_log_pci(uint level, struct pci_dev *pdev, uint id, const char *fmt, ...)
+ if (level > ql_errlev)
+ return;
+
+- ql_dbg_prefix(pbuf, ARRAY_SIZE(pbuf), NULL, id);
++ ql_ktrace(0, level, pbuf, pdev, NULL, id, fmt);
++
++ if (!pbuf[0]) /* set by ql_ktrace */
++ ql_dbg_prefix(pbuf, ARRAY_SIZE(pbuf), pdev, NULL, id);
+
+ va_start(va, fmt);
+
+@@ -2716,7 +2730,11 @@ ql_log_qp(uint32_t level, struct qla_qpair *qpair, int32_t id,
+ if (level > ql_errlev)
+ return;
+
+- ql_dbg_prefix(pbuf, ARRAY_SIZE(pbuf), qpair ? qpair->vha : NULL, id);
++ ql_ktrace(0, level, pbuf, NULL, qpair ? qpair->vha : NULL, id, fmt);
++
++ if (!pbuf[0]) /* set by ql_ktrace */
++ ql_dbg_prefix(pbuf, ARRAY_SIZE(pbuf), NULL,
++ qpair ? qpair->vha : NULL, id);
+
+ va_start(va, fmt);
+
+@@ -2762,6 +2780,8 @@ ql_dbg_qp(uint32_t level, struct qla_qpair *qpair, int32_t id,
+ struct va_format vaf;
+ char pbuf[128];
+
++ ql_ktrace(1, level, pbuf, NULL, qpair ? qpair->vha : NULL, id, fmt);
++
+ if (!ql_mask_match(level))
+ return;
+
+@@ -2770,8 +2790,10 @@ ql_dbg_qp(uint32_t level, struct qla_qpair *qpair, int32_t id,
+ vaf.fmt = fmt;
+ vaf.va = &va;
+
+- ql_dbg_prefix(pbuf, ARRAY_SIZE(pbuf), qpair ? qpair->vha : NULL,
+- id + ql_dbg_offset);
++ if (!pbuf[0]) /* set by ql_ktrace */
++ ql_dbg_prefix(pbuf, ARRAY_SIZE(pbuf), NULL,
++ qpair ? qpair->vha : NULL, id + ql_dbg_offset);
++
+ pr_warn("%s%pV", pbuf, &vaf);
+
+ va_end(va);
+diff --git a/drivers/scsi/qla2xxx/qla_dbg.h b/drivers/scsi/qla2xxx/qla_dbg.h
+index f1f6c740bdcd..1c6a99ff356a 100644
+--- a/drivers/scsi/qla2xxx/qla_dbg.h
++++ b/drivers/scsi/qla2xxx/qla_dbg.h
+@@ -385,3 +385,46 @@ ql_mask_match(uint level)
+
+ return (level & ql2xextended_error_logging) == level;
+ }
++
++static inline int
++ql_mask_match_ext(uint level, int *log_tunable)
++{
++ if (*log_tunable == 1)
++ *log_tunable = QL_DBG_DEFAULT1_MASK;
++
++ return (level & *log_tunable) == level;
++}
++
++/* Assumes local variable pbuf and pbuf_ready present. */
++#define ql_ktrace(dbg_msg, level, pbuf, pdev, vha, id, fmt) do { \
++ struct va_format _vaf; \
++ va_list _va; \
++ u32 dbg_off = dbg_msg ? ql_dbg_offset : 0; \
++ \
++ pbuf[0] = 0; \
++ if (!trace_ql_dbg_log_enabled()) \
++ break; \
++ \
++ if (dbg_msg && !ql_mask_match_ext(level, \
++ &ql2xextended_error_logging_ktrace)) \
++ break; \
++ \
++ ql_dbg_prefix(pbuf, ARRAY_SIZE(pbuf), pdev, vha, id + dbg_off); \
++ \
++ va_start(_va, fmt); \
++ _vaf.fmt = fmt; \
++ _vaf.va = &_va; \
++ \
++ trace_ql_dbg_log(pbuf, &_vaf); \
++ \
++ va_end(_va); \
++} while (0)
++
++#define QLA_ENABLE_KERNEL_TRACING
++
++#ifdef QLA_ENABLE_KERNEL_TRACING
++#define QLA_TRACE_ENABLE(_tr) \
++ trace_array_set_clr_event(_tr, "qla", NULL, true)
++#else /* QLA_ENABLE_KERNEL_TRACING */
++#define QLA_TRACE_ENABLE(_tr)
++#endif /* QLA_ENABLE_KERNEL_TRACING */
+diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
+index f82e4a348330..f699bdbe5839 100644
+--- a/drivers/scsi/qla2xxx/qla_gbl.h
++++ b/drivers/scsi/qla2xxx/qla_gbl.h
+@@ -163,6 +163,7 @@ extern int ql2xrdpenable;
+ extern int ql2xsmartsan;
+ extern int ql2xallocfwdump;
+ extern int ql2xextended_error_logging;
++extern int ql2xextended_error_logging_ktrace;
+ extern int ql2xiidmaenable;
+ extern int ql2xmqsupport;
+ extern int ql2xfwloadbin;
+diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
+index 00e97f0a07eb..abb13176e4f1 100644
+--- a/drivers/scsi/qla2xxx/qla_os.c
++++ b/drivers/scsi/qla2xxx/qla_os.c
+@@ -15,6 +15,8 @@
+ #include <linux/blk-mq-pci.h>
+ #include <linux/refcount.h>
+ #include <linux/crash_dump.h>
++#include <linux/trace_events.h>
++#include <linux/trace.h>
+
+ #include <scsi/scsi_tcq.h>
+ #include <scsi/scsicam.h>
+@@ -35,6 +37,8 @@ static int apidev_major;
+ */
+ struct kmem_cache *srb_cachep;
+
++struct trace_array *qla_trc_array;
++
+ int ql2xfulldump_on_mpifail;
+ module_param(ql2xfulldump_on_mpifail, int, S_IRUGO | S_IWUSR);
+ MODULE_PARM_DESC(ql2xfulldump_on_mpifail,
+@@ -117,6 +121,11 @@ MODULE_PARM_DESC(ql2xextended_error_logging,
+ "ql2xextended_error_logging=1).\n"
+ "\t\tDo LOGICAL OR of the value to enable more than one level");
+
++int ql2xextended_error_logging_ktrace = 1;
++module_param(ql2xextended_error_logging_ktrace, int, S_IRUGO|S_IWUSR);
++MODULE_PARM_DESC(ql2xextended_error_logging_ktrace,
++ "Same BIT definiton as ql2xextended_error_logging, but used to control logging to kernel trace buffer (default=1).\n");
++
+ int ql2xshiftctondsd = 6;
+ module_param(ql2xshiftctondsd, int, S_IRUGO);
+ MODULE_PARM_DESC(ql2xshiftctondsd,
+@@ -2845,6 +2854,27 @@ static void qla2x00_iocb_work_fn(struct work_struct *work)
+ spin_unlock_irqrestore(&vha->work_lock, flags);
+ }
+
++static void
++qla_trace_init(void)
++{
++ qla_trc_array = trace_array_get_by_name("qla2xxx");
++ if (!qla_trc_array) {
++ ql_log(ql_log_fatal, NULL, 0x0001,
++ "Unable to create qla2xxx trace instance, instance logging will be disabled.\n");
++ return;
++ }
++
++ QLA_TRACE_ENABLE(qla_trc_array);
++}
++
++static void
++qla_trace_uninit(void)
++{
++ if (!qla_trc_array)
++ return;
++ trace_array_put(qla_trc_array);
++}
++
+ /*
+ * PCI driver interface
+ */
+@@ -8185,6 +8215,8 @@ qla2x00_module_init(void)
+ BUILD_BUG_ON(sizeof(sw_info_t) != 32);
+ BUILD_BUG_ON(sizeof(target_id_t) != 2);
+
++ qla_trace_init();
++
+ /* Allocate cache for SRBs. */
+ srb_cachep = kmem_cache_create("qla2xxx_srbs", sizeof(srb_t), 0,
+ SLAB_HWCACHE_ALIGN, NULL);
+@@ -8266,6 +8298,8 @@ qla2x00_module_init(void)
+
+ destroy_cache:
+ kmem_cache_destroy(srb_cachep);
++
++ qla_trace_uninit();
+ return ret;
+ }
+
+@@ -8284,6 +8318,7 @@ qla2x00_module_exit(void)
+ fc_release_transport(qla2xxx_transport_template);
+ qlt_exit();
+ kmem_cache_destroy(srb_cachep);
++ qla_trace_uninit();
+ }
+
+ module_init(qla2x00_module_init);
+--
+2.35.1
+
--- /dev/null
+From c737ecf2d493533f6062300c0ada22c5788ce0c5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 11 Sep 2022 11:12:15 +0200
+Subject: serial: ar933x: Deassert Transmit Enable on ->rs485_config()
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Lukas Wunner <lukas@wunner.de>
+
+[ Upstream commit 3a939433ddc1bab98be028903aaa286e5e7461d7 ]
+
+The ar933x_uart driver neglects to deassert Transmit Enable when
+->rs485_config() is invoked. Fix it.
+
+Fixes: 9be1064fe524 ("serial: ar933x_uart: add RS485 support")
+Cc: stable@vger.kernel.org # v5.7+
+Cc: Daniel Golle <daniel@makrotopia.org>
+Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+Signed-off-by: Lukas Wunner <lukas@wunner.de>
+Link: https://lore.kernel.org/r/5b36af26e57553f084334666e7d24c7fd131a01e.1662887231.git.lukas@wunner.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/tty/serial/ar933x_uart.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/drivers/tty/serial/ar933x_uart.c b/drivers/tty/serial/ar933x_uart.c
+index 7e89e563359a..394e960fd33c 100644
+--- a/drivers/tty/serial/ar933x_uart.c
++++ b/drivers/tty/serial/ar933x_uart.c
+@@ -583,6 +583,13 @@ static const struct uart_ops ar933x_uart_ops = {
+ static int ar933x_config_rs485(struct uart_port *port,
+ struct serial_rs485 *rs485conf)
+ {
++ struct ar933x_uart_port *up =
++ container_of(port, struct ar933x_uart_port, port);
++
++ if (port->rs485.flags & SER_RS485_ENABLED)
++ gpiod_set_value(up->rts_gpiod,
++ !!(rs485conf->flags & SER_RS485_RTS_AFTER_SEND));
++
+ return 0;
+ }
+
+--
+2.35.1
+
--- /dev/null
+From 5aa54b067a13313f3088aed18bcc55bbe955e38c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 10 Jul 2022 18:44:36 +0200
+Subject: serial: ar933x: Remove superfluous code in ar933x_config_rs485()
+
+From: Lino Sanfilippo <l.sanfilippo@kunbus.com>
+
+[ Upstream commit 184842622c97da2f88f365a981af05432baa5385 ]
+
+In ar933x_config_rs485() the check for the RTS GPIO is not needed since in
+case the GPIO is not available at driver init ar933x_no_rs485 is assigned
+to port->rs485_supported and this function is never called. So remove the
+check.
+
+Also in uart_set_rs485_config() the serial core already assigns the passed
+serial_rs485 struct to the uart port. So remove the assignment in the
+drivers rs485_config() function to avoid redundancy.
+
+Signed-off-by: Lino Sanfilippo <l.sanfilippo@kunbus.com>
+Link: https://lore.kernel.org/r/20220710164442.2958979-3-LinoSanfilippo@gmx.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Stable-dep-of: 3a939433ddc1 ("serial: ar933x: Deassert Transmit Enable on ->rs485_config()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/tty/serial/ar933x_uart.c | 9 ---------
+ 1 file changed, 9 deletions(-)
+
+diff --git a/drivers/tty/serial/ar933x_uart.c b/drivers/tty/serial/ar933x_uart.c
+index 4379ca4842ae..7e89e563359a 100644
+--- a/drivers/tty/serial/ar933x_uart.c
++++ b/drivers/tty/serial/ar933x_uart.c
+@@ -583,15 +583,6 @@ static const struct uart_ops ar933x_uart_ops = {
+ static int ar933x_config_rs485(struct uart_port *port,
+ struct serial_rs485 *rs485conf)
+ {
+- struct ar933x_uart_port *up =
+- container_of(port, struct ar933x_uart_port, port);
+-
+- if ((rs485conf->flags & SER_RS485_ENABLED) &&
+- !up->rts_gpiod) {
+- dev_err(port->dev, "RS485 needs rts-gpio\n");
+- return 1;
+- }
+- port->rs485 = *rs485conf;
+ return 0;
+ }
+
+--
+2.35.1
+
--- /dev/null
+scsi-lpfc-adjust-bytes-received-vales-during-cmf-tim.patch
+scsi-lpfc-adjust-cmf-total-bytes-and-rxmonitor.patch
+scsi-lpfc-rework-mib-rx-monitor-debug-info-logic.patch
+scsi-qla2xxx-enhance-driver-tracing-with-separate-tu.patch
+scsi-qla2xxx-define-static-symbols.patch
+serial-ar933x-remove-superfluous-code-in-ar933x_conf.patch
+serial-ar933x-deassert-transmit-enable-on-rs485_conf.patch
+kvm-x86-trace-re-injected-exceptions.patch
+kvm-x86-treat-dbs-from-the-emulator-as-fault-like-co.patch
+drm-amd-display-explicitly-disable-psr_feature_enabl.patch
+mm-hugetlb-fix-races-when-looking-up-a-cont-pte-pmd-.patch
+hid-playstation-add-initial-dualsense-edge-controlle.patch
+kvm-x86-protect-the-unused-bits-in-msr-exiting-flags.patch
+kvm-x86-copy-filter-arg-outside-kvm_vm_ioctl_set_msr.patch
+kvm-x86-add-compat-handler-for-kvm_x86_set_msr_filte.patch