From: Sasha Levin Date: Fri, 4 Nov 2022 14:54:40 +0000 (-0400) Subject: Fixes for 5.15 X-Git-Tag: v4.9.333~93 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=b2af32b61fcd6004d2ef834932153e425481e9db;p=thirdparty%2Fkernel%2Fstable-queue.git Fixes for 5.15 Signed-off-by: Sasha Levin --- diff --git a/queue-5.15/drm-amd-display-explicitly-disable-psr_feature_enabl.patch b/queue-5.15/drm-amd-display-explicitly-disable-psr_feature_enabl.patch new file mode 100644 index 00000000000..bc5460201e6 --- /dev/null +++ b/queue-5.15/drm-amd-display-explicitly-disable-psr_feature_enabl.patch @@ -0,0 +1,51 @@ +From 2c75de21de35cbc361b0bc2d4212f3c0c3a16a26 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 7 Oct 2022 20:31:49 +0530 +Subject: drm/amd/display: explicitly disable psr_feature_enable appropriately + +From: Shirish S + +[ 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 +Reviewed-by: Leo Li +Reviewed-by: Mario Limonciello +Signed-off-by: Alex Deucher +Cc: stable@vger.kernel.org # 5.15+ +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/hid-playstation-add-initial-dualsense-edge-controlle.patch b/queue-5.15/hid-playstation-add-initial-dualsense-edge-controlle.patch new file mode 100644 index 00000000000..4ecd07be702 --- /dev/null +++ b/queue-5.15/hid-playstation-add-initial-dualsense-edge-controlle.patch @@ -0,0 +1,61 @@ +From bc6e2a685db9dbe094ac02c5c507c0e2666e01c4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 10 Oct 2022 14:23:12 -0700 +Subject: HID: playstation: add initial DualSense Edge controller support + +From: Roderick Colenbrander + +[ 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 +CC: stable@vger.kernel.org +Signed-off-by: Benjamin Tissoires +Link: https://lore.kernel.org/r/20221010212313.78275-3-roderick.colenbrander@sony.com +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/kvm-x86-add-compat-handler-for-kvm_x86_set_msr_filte.patch b/queue-5.15/kvm-x86-add-compat-handler-for-kvm_x86_set_msr_filte.patch new file mode 100644 index 00000000000..12f2ed58559 --- /dev/null +++ b/queue-5.15/kvm-x86-add-compat-handler-for-kvm_x86_set_msr_filte.patch @@ -0,0 +1,99 @@ +From a8c3e222a6fc6264831dcd5d72e37f2d4cfe4e5f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Oct 2022 20:45:41 +0200 +Subject: KVM: x86: Add compat handler for KVM_X86_SET_MSR_FILTER + +From: Alexander Graf + +[ 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 +Fixes: 1a155254ff937 ("KVM: x86: Introduce MSR filtering") +Signed-off-by: Alexander Graf +Message-Id: <20221017184541.2658-4-graf@amazon.com> +Cc: stable@vger.kernel.org +Signed-off-by: Paolo Bonzini +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/kvm-x86-copy-filter-arg-outside-kvm_vm_ioctl_set_msr.patch b/queue-5.15/kvm-x86-copy-filter-arg-outside-kvm_vm_ioctl_set_msr.patch new file mode 100644 index 00000000000..d664108356d --- /dev/null +++ b/queue-5.15/kvm-x86-copy-filter-arg-outside-kvm_vm_ioctl_set_msr.patch @@ -0,0 +1,93 @@ +From 41c5ac8e175ad38425af5ec5a673d39dad4d4f40 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Message-Id: <20221017184541.2658-3-graf@amazon.com> +Cc: stable@vger.kernel.org +Signed-off-by: Paolo Bonzini +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/kvm-x86-protect-the-unused-bits-in-msr-exiting-flags.patch b/queue-5.15/kvm-x86-protect-the-unused-bits-in-msr-exiting-flags.patch new file mode 100644 index 00000000000..f287f9448ae --- /dev/null +++ b/queue-5.15/kvm-x86-protect-the-unused-bits-in-msr-exiting-flags.patch @@ -0,0 +1,52 @@ +From d7e4dee6e86072b2f59d7e01f6ca0e5a0c7205de Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 14 Jul 2022 16:13:15 +0000 +Subject: KVM: x86: Protect the unused bits in MSR exiting flags + +From: Aaron Lewis + +[ 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 +Message-Id: <20220714161314.1715227-1-aaronlewis@google.com> +Signed-off-by: Paolo Bonzini +Stable-dep-of: 2e3272bc1790 ("KVM: x86: Copy filter arg outside kvm_vm_ioctl_set_msr_filter()") +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/kvm-x86-trace-re-injected-exceptions.patch b/queue-5.15/kvm-x86-trace-re-injected-exceptions.patch new file mode 100644 index 00000000000..ac9653ac8b2 --- /dev/null +++ b/queue-5.15/kvm-x86-trace-re-injected-exceptions.patch @@ -0,0 +1,111 @@ +From a467d873bcb9e4b1b756937e6d6d02f7ce6283e8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 2 May 2022 00:07:31 +0200 +Subject: KVM: x86: Trace re-injected exceptions + +From: Sean Christopherson + +[ 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 +Reviewed-by: Maxim Levitsky +Signed-off-by: Maciej S. Szmigiero +Message-Id: <25470690a38b4d2b32b6204875dd35676c65c9f2.1651440202.git.maciej.szmigiero@oracle.com> +Signed-off-by: Paolo Bonzini +Stable-dep-of: 5623f751bd9c ("KVM: x86: Treat #DBs from the emulator as fault-like (code and DR7.GD=1)") +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/kvm-x86-treat-dbs-from-the-emulator-as-fault-like-co.patch b/queue-5.15/kvm-x86-treat-dbs-from-the-emulator-as-fault-like-co.patch new file mode 100644 index 00000000000..4652865eeea --- /dev/null +++ b/queue-5.15/kvm-x86-treat-dbs-from-the-emulator-as-fault-like-co.patch @@ -0,0 +1,101 @@ +From bfc17e5d1035ad471aaef5b77baacac96cf54597 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Reviewed-by: Maxim Levitsky +Link: https://lore.kernel.org/r/20220830231614.3580124-9-seanjc@google.com +Signed-off-by: Paolo Bonzini +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/mm-hugetlb-fix-races-when-looking-up-a-cont-pte-pmd-.patch b/queue-5.15/mm-hugetlb-fix-races-when-looking-up-a-cont-pte-pmd-.patch new file mode 100644 index 00000000000..771789bd4bc --- /dev/null +++ b/queue-5.15/mm-hugetlb-fix-races-when-looking-up-a-cont-pte-pmd-.patch @@ -0,0 +1,180 @@ +From 8dc2ed7f7f38d46d077ebc92e20fcd8af49ca671 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Suggested-by: Mike Kravetz +Reviewed-by: Mike Kravetz +Cc: David Hildenbrand +Cc: Muchun Song +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/scsi-lpfc-adjust-bytes-received-vales-during-cmf-tim.patch b/queue-5.15/scsi-lpfc-adjust-bytes-received-vales-during-cmf-tim.patch new file mode 100644 index 00000000000..f71e68c8e56 --- /dev/null +++ b/queue-5.15/scsi-lpfc-adjust-bytes-received-vales-during-cmf-tim.patch @@ -0,0 +1,64 @@ +From 98dc1b78d661fcfd799d9eb79ec83301d9b882f5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 10 Sep 2021 16:31:55 -0700 +Subject: scsi: lpfc: Adjust bytes received vales during cmf timer interval + +From: James Smart + +[ 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 +Signed-off-by: Justin Tee +Signed-off-by: James Smart +Signed-off-by: Martin K. Petersen +Stable-dep-of: bd269188ea94 ("scsi: lpfc: Rework MIB Rx Monitor debug info logic") +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/scsi-lpfc-adjust-cmf-total-bytes-and-rxmonitor.patch b/queue-5.15/scsi-lpfc-adjust-cmf-total-bytes-and-rxmonitor.patch new file mode 100644 index 00000000000..3e626f33015 --- /dev/null +++ b/queue-5.15/scsi-lpfc-adjust-cmf-total-bytes-and-rxmonitor.patch @@ -0,0 +1,144 @@ +From cd8e65a24380fdf2ceb02b1fce8bd31fe298843f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 3 Dec 2021 16:26:41 -0800 +Subject: scsi: lpfc: Adjust CMF total bytes and rxmonitor + +From: James Smart + +[ 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 +Signed-off-by: Justin Tee +Signed-off-by: James Smart +Signed-off-by: Martin K. Petersen +Stable-dep-of: bd269188ea94 ("scsi: lpfc: Rework MIB Rx Monitor debug info logic") +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/scsi-lpfc-rework-mib-rx-monitor-debug-info-logic.patch b/queue-5.15/scsi-lpfc-rework-mib-rx-monitor-debug-info-logic.patch new file mode 100644 index 00000000000..83449da6259 --- /dev/null +++ b/queue-5.15/scsi-lpfc-rework-mib-rx-monitor-debug-info-logic.patch @@ -0,0 +1,546 @@ +From de2e558fcdd27d40ca8dab14aa33f5ec3dfb5ad6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 18 Aug 2022 18:17:32 -0700 +Subject: scsi: lpfc: Rework MIB Rx Monitor debug info logic + +From: James Smart + +[ 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: # v5.15+ +Co-developed-by: Justin Tee +Signed-off-by: Justin Tee +Signed-off-by: James Smart +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/scsi-qla2xxx-define-static-symbols.patch b/queue-5.15/scsi-qla2xxx-define-static-symbols.patch new file mode 100644 index 00000000000..9c325a3f43e --- /dev/null +++ b/queue-5.15/scsi-qla2xxx-define-static-symbols.patch @@ -0,0 +1,54 @@ +From 42f252f2e326827b9fa5a41d0a2a0f7dbcf8a496 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 26 Aug 2022 03:25:58 -0700 +Subject: scsi: qla2xxx: Define static symbols + +From: Nilesh Javali + +[ 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 +Reviewed-by: Himanshu Madhani +Signed-off-by: Nilesh Javali +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/scsi-qla2xxx-enhance-driver-tracing-with-separate-tu.patch b/queue-5.15/scsi-qla2xxx-enhance-driver-tracing-with-separate-tu.patch new file mode 100644 index 00000000000..a28e8e99417 --- /dev/null +++ b/queue-5.15/scsi-qla2xxx-enhance-driver-tracing-with-separate-tu.patch @@ -0,0 +1,341 @@ +From 67f47c36511ed0d76b6944f3d10747f6da300191 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 26 Aug 2022 03:25:57 -0700 +Subject: scsi: qla2xxx: Enhance driver tracing with separate tunable and more + +From: Arun Easi + +[ 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 +Suggested-by: Steven Rostedt +Tested-by: Himanshu Madhani +Reviewed-by: Himanshu Madhani +Reviewed-by: Daniel Wagner +Signed-off-by: Arun Easi +Signed-off-by: Nilesh Javali +Signed-off-by: Martin K. Petersen +Stable-dep-of: 2c57d0defa22 ("scsi: qla2xxx: Define static symbols") +Signed-off-by: Sasha Levin +--- + 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, + /* []-:: */ + 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 { + /* []-: : */ + 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 + #include + #include ++#include ++#include + + #include + #include +@@ -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 + diff --git a/queue-5.15/serial-ar933x-deassert-transmit-enable-on-rs485_conf.patch b/queue-5.15/serial-ar933x-deassert-transmit-enable-on-rs485_conf.patch new file mode 100644 index 00000000000..445d54619ae --- /dev/null +++ b/queue-5.15/serial-ar933x-deassert-transmit-enable-on-rs485_conf.patch @@ -0,0 +1,48 @@ +From c737ecf2d493533f6062300c0ada22c5788ce0c5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Reviewed-by: Ilpo Järvinen +Signed-off-by: Lukas Wunner +Link: https://lore.kernel.org/r/5b36af26e57553f084334666e7d24c7fd131a01e.1662887231.git.lukas@wunner.de +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/serial-ar933x-remove-superfluous-code-in-ar933x_conf.patch b/queue-5.15/serial-ar933x-remove-superfluous-code-in-ar933x_conf.patch new file mode 100644 index 00000000000..04a2f1aad20 --- /dev/null +++ b/queue-5.15/serial-ar933x-remove-superfluous-code-in-ar933x_conf.patch @@ -0,0 +1,50 @@ +From 5aa54b067a13313f3088aed18bcc55bbe955e38c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 10 Jul 2022 18:44:36 +0200 +Subject: serial: ar933x: Remove superfluous code in ar933x_config_rs485() + +From: Lino Sanfilippo + +[ 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 +Link: https://lore.kernel.org/r/20220710164442.2958979-3-LinoSanfilippo@gmx.de +Signed-off-by: Greg Kroah-Hartman +Stable-dep-of: 3a939433ddc1 ("serial: ar933x: Deassert Transmit Enable on ->rs485_config()") +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/series b/queue-5.15/series new file mode 100644 index 00000000000..7b7c3c169af --- /dev/null +++ b/queue-5.15/series @@ -0,0 +1,15 @@ +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