From: Greg Kroah-Hartman Date: Tue, 21 Jul 2026 13:56:59 +0000 (+0200) Subject: 5.10-stable patches X-Git-Url: http://git.ipfire.org/gitweb/index.cgi?a=commitdiff_plain;h=fc3b004b5e9ed0dd2e0b279320ffe990eb183061;p=thirdparty%2Fkernel%2Fstable-queue.git 5.10-stable patches added patches: acpi-nfit-core-fix-acpi_nfit_init-error-cleanup.patch alsa-aoa-check-snd_ctl_new1-return-value.patch audit-add-audit_log_nf_skb-helper-function.patch audit-fix-potential-integer-overflow-in-audit_log_n_hex.patch binder-fix-uaf-in-binder_free_transaction.patch bitops-make-bytes_to_bits-treewide-available.patch bluetooth-btintel-check-firmware-version-before-download.patch bluetooth-btintel-fix-offset-calculation-boot-address-parameter.patch bluetooth-btusb-fix-use-after-free-on-marvell-probe-failure.patch bluetooth-btusb-fix-wakeup-source-leak-on-probe-failure.patch bluetooth-l2cap-cancel-pending_rx_work-before-taking-conn-lock.patch bluetooth-l2cap-fix-deadlock-in-l2cap_conn_del.patch bluetooth-l2cap-fix-not-tracking-outstanding-tx-ident.patch btrfs-do-not-trim-a-device-which-is-not-writeable.patch cifs-create-a-new-shared-file-holding-smb2-pdu-definitions.patch cifs-remove-check-of-list-iterator-against-head-past-the-loop-body.patch cifs-remove-unused-server-parameter-from-calc_smb_size.patch coresight-etb10-restore-atomic_t-for-shared-reading-state.patch cpufreq-intel_pstate-sync-policy-cur-during-cpu-offline.patch crypto-atmel-drop-explicit-initialization-of-struct-i2c_device_id-driver_data-to-0.patch crypto-atmel-sha204a-drop-hwrng-quality-reduction-for-atsha204a.patch crypto-atmel-sha204a-mark-of-related-data-as-maybe-unused.patch crypto-qat-fix-restarting-state-leak-on-allocation-failure.patch crypto-qat-fix-vf2pf-work-teardown-race-in-adf_disable_sriov.patch crypto-qat-validate-rsa-crt-component-lengths.patch drm-i2c-sil164-drop-no-op-remove-function.patch gpio-pca953x-make-platform-teardown-callback-return-void.patch hfs-hfsplus-fix-u32-overflow-in-check_and_correct_requested_length.patch hfs-hfsplus-prevent-getting-negative-values-of-offset-length.patch hid-add-haptics-page-defines.patch hid-appleir-fix-uaf-on-pending-key_up_timer-in-remove.patch hid-multitouch-fix-out-of-bounds-bit-access-on-mt_io_flags.patch iio-common-st_sensors-honour-channel-endianness-in-read_axis_data.patch iio-hid-sensor-rotation-fix-stale-or-zero-output-when-reading-raw-values.patch iio-imu-adis-add-irqf_no_thread-to-non-fifo-trigger-irq.patch iio-imu-inv_icm42600-fix-timestamping-by-limiting-fifo-reading.patch iio-imu-inv_icm42600-make-timestamp-module-chip-independent.patch iio-imu-inv_icm42600-stabilized-timestamp-in-interrupt.patch iio-imu-inv_mpu6050-use-the-common-inv_sensors-timestamp-module.patch iio-invensense-fix-timestamp-glitches-when-switching-frequency.patch iio-invensense-remove-redundant-initialization-of-variable-period.patch iio-make-invensense-timestamp-module-generic.patch iio-move-inv_icm42600-timestamp-module-in-common.patch leds-lm3601x-improve-error-reporting-for-problems-during-.remove.patch leds-lm3697-remove-duplicated-error-reporting-in-.remove.patch media-atomisp-replace-boolean-comparison-of-values-with-bool-variables.patch media-staging-media-atomisp-fix-alignment-and-line-length-issues.patch media-staging-media-atomisp-fix-sh_css.c-brace-coding-style-issues.patch media-staging-media-atomisp-fix-the-rest-of-sh_css.c-brace-issues.patch media-staging-media-atomisp-replace-if-else-clause-with-a-ternary.patch netfilter-ebtables-use-vmalloc_array-to-improve-code.patch netfilter-ebtables-zero-chainstack-array.patch pci-add-kerneldoc-for-pci_resize_resource.patch pci-altera-fix-resource-leaks-on-probe-failure.patch pci-controller-use-dev_fwnode-instead-of-of_fwnode_handle.patch pci-fix-restoring-bars-on-bar-resize-rollback-path.patch pci-free-saved-list-without-holding-pci_bus_sem.patch pci-imx6-fix-imx6sx_gpr12_pcie_test_powerdown-handling.patch pci-mediatek-convert-bool-to-single-quirks-entry-and-bitmap.patch pci-mediatek-fix-irq-domain-leak-when-port-fails-to-enable.patch pci-move-resizable-bar-code-to-rebar.c.patch pci-prevent-resource-tree-corruption-when-bar-resize-fails.patch pci-skip-resizable-bar-restore-on-read-error.patch proc-protect-ptrace_may_access-with-exec_update_lock-fd-links.patch proc-protect-ptrace_may_access-with-exec_update_lock-part-1.patch proc-rename-proc_setattr-to-proc_nochmod_setattr.patch proc-use-generic-setattr-for-proc-pid-net.patch serial-8250_mid-disable-dma-for-selected-platforms.patch serial-8250_mid-remove-8250_pci-usage.patch smb-client-fix-next-buffer-leak-in-receive_encrypted_standard.patch smb-client-harden-posix-sid-length-parsing.patch smb-client-mask-server-provided-mode-to-07777-in-modefromsid.patch smb-client-restrict-implied-bcc-exemption-to-responses-without-data-area.patch smb-client-use-unaligned-reads-in-parse_posix_ctxt.patch smb2-small-refactor-in-smb2_check_message.patch staging-media-atomisp-reduce-load_primary_binaries-stack-usage.patch staging-rtl8723bs-clean-up-comparsions-to-null.patch staging-rtl8723bs-fix-heap-buffer-overflow-in-rtw_cfg80211_set_wpa_ie.patch staging-rtl8723bs-fix-oob-reads-in-ie-loops-in-issue_assocreq-and-join_cmd_hdl.patch staging-rtl8723bs-fix-space-issues.patch staging-rtl8723bs-fix-wep-length-underflow-and-oob-read-in-onauth.patch staging-rtl8723bs-remove-5ghz-code-blocks.patch staging-rtl8723bs-remove-5ghz-code-related-to-channel-plan-definition.patch staging-rtl8723bs-remove-all-5ghz-network-types.patch staging-rtl8723bs-remove-commented-out-condition.patch staging-rtl8723bs-remove-commented-out-rt_assert-occurrences.patch staging-rtl8723bs-remove-dbg_871x-log-argument.patch staging-rtl8723bs-split-too-long-line.patch usb-atm-ueagle-atm-wait-for-pre-firmware-load-in-.disconnect.patch usb-free-iso-schedules-on-failed-submit.patch usb-gadget-f_fs-initialize-reset_work-at-allocation-time.patch usb-gadget-f_fs-tie-read_buffer-lifetime-to-ffs_epfile.patch usb-gadget-f_printer-take-kref-only-for-successful-open.patch usb-gadget-function-simplify-diagnostic-messaging-in-printer.patch usb-iowarrior-remove-inherent-race-with-minor-number.patch usb-serial-digi_acceleport-fix-write-buffer-corruption.patch usb-typec-tcpm-fix-vdm-type-for-enter-mode-commands.patch usb-typec-ucsi-ccg-fix-use-after-free-of-ucsi-on-remove.patch vfio-pci-release-the-vga-arbiter-client-on-register_device-failure.patch writeback-fix-race-between-cgroup_writeback_umount-and-inode_switch_wbs.patch x.509-fix-validation-of-asn.1-certificate-header.patch xfs-fix-unreachable-bigtime-check-in-dquot-flush-validation.patch xfs-reflect-sb-features-in-xfs_mount.patch xfs-use-null-daddr-for-unset-first-bad-log-block.patch --- diff --git a/queue-5.10/acpi-nfit-core-fix-acpi_nfit_init-error-cleanup.patch b/queue-5.10/acpi-nfit-core-fix-acpi_nfit_init-error-cleanup.patch new file mode 100644 index 0000000000..8c114829f5 --- /dev/null +++ b/queue-5.10/acpi-nfit-core-fix-acpi_nfit_init-error-cleanup.patch @@ -0,0 +1,103 @@ +From stable+bounces-273267-greg=kroah.com@vger.kernel.org Fri Jul 10 17:49:15 2026 +From: Sasha Levin +Date: Fri, 10 Jul 2026 11:42:05 -0400 +Subject: ACPI: NFIT: core: Fix acpi_nfit_init() error cleanup +To: stable@vger.kernel.org +Cc: "Rafael J. Wysocki" , Dave Jiang , Sasha Levin +Message-ID: <20260710154205.284338-1-sashal@kernel.org> + +From: "Rafael J. Wysocki" + +[ Upstream commit 38bf27511ef41bffebd157ec3eba41fc89ba59cd ] + +If acpi_nfit_init() fails after adding the acpi_desc object to the +acpi_descs list, that object is never removed from that list because +the acpi_nfit_shutdown() devm action is not added for the NFIT device +in that case. Next, the acpi_nfit_init() failure causes +acpi_nfit_probe() to fail, the acpi_desc object is freed, and a +dangling pointer is left behind in the acpi_descs. Any subsequent +ACPI Machine Check Exception will trigger nfit_handle_mce() which +iterates over acpi_descs and so a use-after-free will occur. + +Moreover, if acpi_nfit_probe() returns 0 after installing a notify +handler for the NFIT device and without allocating the acpi_desc +object and setting the NFIT device's driver data pointer, the +acpi_desc object will be allocated by acpi_nfit_update_notify() +and acpi_nfit_init() will be called to initialize it. Regardless +of whether or not acpi_nfit_init() fails in that case, the +acpi_nfit_shutdown() devm action is not added for the NFIT device +and acpi_desc is never removed from the acpi_descs list. If the +acpi_desc object is freed subsequently on driver removal, any +subsequent ACPI MCE will lead to a use-after-free like in the +previous case. + +To address the first issue mentioned above, make acpi_nfit_probe() +call acpi_nfit_shutdown() directly on acpi_nfit_init() failures and +to address the other one, add a remove callback to the driver and +make it call acpi_nfit_shutdown(). Also, since it is now possible to +pass NULL to acpi_nfit_shutdown() or the acpi_desc object passed to it +may not have been initialized, add checks against NULL for acpi_desc and +its nvdimm_bus field to that function and make acpi_nfit_unregister() +clear the latter after unregistering the NVDIMM bus. + +Fixes: a61fe6f7902e ("nfit, tools/testing/nvdimm: unify common init for acpi_nfit_desc") +Fixes: fbabd829fe76 ("acpi, nfit: fix module unload vs workqueue shutdown race") +Signed-off-by: Rafael J. Wysocki +Cc: All applicable +Reviewed-by: Dave Jiang +Link: https://patch.msgid.link/1963615.tdWV9SEqCh@rafael.j.wysocki +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/acpi/nfit/core.c | 15 +++++++++++---- + 1 file changed, 11 insertions(+), 4 deletions(-) + +--- a/drivers/acpi/nfit/core.c ++++ b/drivers/acpi/nfit/core.c +@@ -3456,6 +3456,8 @@ static void acpi_nfit_unregister(void *d + struct acpi_nfit_desc *acpi_desc = data; + + nvdimm_bus_unregister(acpi_desc->nvdimm_bus); ++ /* The nvdimm_bus object may have been freed, so clear the pointer. */ ++ acpi_desc->nvdimm_bus = NULL; + } + + int acpi_nfit_init(struct acpi_nfit_desc *acpi_desc, void *data, acpi_size sz) +@@ -3680,7 +3682,10 @@ static void acpi_nfit_put_table(void *ta + void acpi_nfit_shutdown(void *data) + { + struct acpi_nfit_desc *acpi_desc = data; +- struct device *bus_dev = to_nvdimm_bus_dev(acpi_desc->nvdimm_bus); ++ struct device *bus_dev; ++ ++ if (!acpi_desc || !acpi_desc->nvdimm_bus) ++ return; + + /* + * Destruct under acpi_desc_lock so that nfit_handle_mce does not +@@ -3695,6 +3700,7 @@ void acpi_nfit_shutdown(void *data) + mutex_unlock(&acpi_desc->init_mutex); + cancel_delayed_work_sync(&acpi_desc->dwork); + ++ bus_dev = to_nvdimm_bus_dev(acpi_desc->nvdimm_bus); + /* + * Bounce the nvdimm bus lock to make sure any in-flight + * acpi_nfit_ars_rescan() submissions have had a chance to +@@ -3762,13 +3768,14 @@ static int acpi_nfit_add(struct acpi_dev + sz - sizeof(struct acpi_table_nfit)); + + if (rc) +- return rc; +- return devm_add_action_or_reset(dev, acpi_nfit_shutdown, acpi_desc); ++ acpi_nfit_shutdown(acpi_desc); ++ ++ return rc; + } + + static int acpi_nfit_remove(struct acpi_device *adev) + { +- /* see acpi_nfit_unregister */ ++ acpi_nfit_shutdown(dev_get_drvdata(&adev->dev)); + return 0; + } + diff --git a/queue-5.10/alsa-aoa-check-snd_ctl_new1-return-value.patch b/queue-5.10/alsa-aoa-check-snd_ctl_new1-return-value.patch new file mode 100644 index 0000000000..6e4d13a171 --- /dev/null +++ b/queue-5.10/alsa-aoa-check-snd_ctl_new1-return-value.patch @@ -0,0 +1,61 @@ +From stable+bounces-274100-greg=kroah.com@vger.kernel.org Tue Jul 14 05:06:56 2026 +From: Sasha Levin +Date: Mon, 13 Jul 2026 23:04:53 -0400 +Subject: ALSA: aoa: check snd_ctl_new1() return value +To: stable@vger.kernel.org +Cc: Zhao Dongdong , Takashi Iwai , Sasha Levin +Message-ID: <20260714030453.2382650-1-sashal@kernel.org> + +From: Zhao Dongdong + +[ Upstream commit 8df560fefe6fed6a20b7e06720eeaeccec349ac0 ] + +snd_ctl_new1() can return NULL when memory allocation fails. In +layout.c, the function does not check the return value before +dereferencing ctl->id.name or passing to aoa_snd_ctl_add(), which can +lead to a NULL pointer dereference. + +Add NULL checks after snd_ctl_new1() calls and return early if any +fails. + +Assisted-by: Opencode:DeepSeek-V4-Flash +Cc: stable@vger.kernel.org +Fixes: f3d9478b2ce4 ("[ALSA] snd-aoa: add snd-aoa") +Signed-off-by: Zhao Dongdong +Link: https://patch.msgid.link/tencent_35F3A25FEEBF190A2E15ED787754C57E3708@qq.com +Signed-off-by: Takashi Iwai +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + sound/aoa/fabrics/layout.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +--- a/sound/aoa/fabrics/layout.c ++++ b/sound/aoa/fabrics/layout.c +@@ -947,6 +947,8 @@ static void layout_attached_codec(struct + if (lineout == 1) + ldev->gpio.methods->set_lineout(codec->gpio, 1); + ctl = snd_ctl_new1(&lineout_ctl, codec->gpio); ++ if (!ctl) ++ return; + if (cc->connected & CC_LINEOUT_LABELLED_HEADPHONE) + strlcpy(ctl->id.name, + "Headphone Switch", sizeof(ctl->id.name)); +@@ -961,6 +963,8 @@ static void layout_attached_codec(struct + if (ldev->have_lineout_detect) { + ctl = snd_ctl_new1(&lineout_detect_choice, + ldev); ++ if (!ctl) ++ return; + if (cc->connected & CC_LINEOUT_LABELLED_HEADPHONE) + strlcpy(ctl->id.name, + "Headphone Detect Autoswitch", +@@ -968,6 +972,8 @@ static void layout_attached_codec(struct + aoa_snd_ctl_add(ctl); + ctl = snd_ctl_new1(&lineout_detected, + ldev); ++ if (!ctl) ++ return; + if (cc->connected & CC_LINEOUT_LABELLED_HEADPHONE) + strlcpy(ctl->id.name, + "Headphone Detected", diff --git a/queue-5.10/audit-add-audit_log_nf_skb-helper-function.patch b/queue-5.10/audit-add-audit_log_nf_skb-helper-function.patch new file mode 100644 index 0000000000..b5e9dc14be --- /dev/null +++ b/queue-5.10/audit-add-audit_log_nf_skb-helper-function.patch @@ -0,0 +1,296 @@ +From stable+bounces-278575-greg=kroah.com@vger.kernel.org Tue Jul 21 14:02:36 2026 +From: Sasha Levin +Date: Tue, 21 Jul 2026 07:56:41 -0400 +Subject: audit: add audit_log_nf_skb helper function +To: stable@vger.kernel.org +Cc: Ricardo Robaina , Florian Westphal , Paul Moore , Sasha Levin +Message-ID: <20260721115642.3699441-1-sashal@kernel.org> + +From: Ricardo Robaina + +[ Upstream commit f19590b07cb620be1fcd5474c49515e21a05d406 ] + +Netfilter code (net/netfilter/nft_log.c and net/netfilter/xt_AUDIT.c) +have to be kept in sync. Both source files had duplicated versions of +audit_ip4() and audit_ip6() functions, which can result in lack of +consistency and/or duplicated work. + +This patch adds a helper function in audit.c that can be called by +netfilter code commonly, aiming to improve maintainability and +consistency. + +Suggested-by: Florian Westphal +Suggested-by: Paul Moore +Signed-off-by: Ricardo Robaina +Acked-by: Florian Westphal +Signed-off-by: Paul Moore +Stable-dep-of: 65dfde57d1e2 ("audit: fix potential integer overflow in audit_log_n_hex()") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + include/linux/audit.h | 8 +++++ + kernel/audit.c | 64 +++++++++++++++++++++++++++++++++++++++++++++++ + net/netfilter/nft_log.c | 58 ------------------------------------------ + net/netfilter/xt_AUDIT.c | 58 ------------------------------------------ + 4 files changed, 74 insertions(+), 114 deletions(-) + +--- a/include/linux/audit.h ++++ b/include/linux/audit.h +@@ -186,6 +186,8 @@ extern void audit_log_lost(const ch + + extern int audit_log_task_context(struct audit_buffer *ab); + extern void audit_log_task_info(struct audit_buffer *ab); ++extern int audit_log_nf_skb(struct audit_buffer *ab, ++ const struct sk_buff *skb, u8 nfproto); + + extern int audit_update_lsm_rules(void); + +@@ -251,6 +253,12 @@ static inline int audit_log_task_context + static inline void audit_log_task_info(struct audit_buffer *ab) + { } + ++static inline int audit_log_nf_skb(struct audit_buffer *ab, ++ const struct sk_buff *skb, u8 nfproto) ++{ ++ return 0; ++} ++ + static inline kuid_t audit_get_loginuid(struct task_struct *tsk) + { + return INVALID_UID; +--- a/kernel/audit.c ++++ b/kernel/audit.c +@@ -59,6 +59,8 @@ + #include + #include + #include ++#include ++#include + + #include "audit.h" + +@@ -2304,6 +2306,68 @@ void audit_log_path_denied(int type, con + audit_log_end(ab); + } + ++int audit_log_nf_skb(struct audit_buffer *ab, ++ const struct sk_buff *skb, u8 nfproto) ++{ ++ /* find the IP protocol in the case of NFPROTO_BRIDGE */ ++ if (nfproto == NFPROTO_BRIDGE) { ++ switch (eth_hdr(skb)->h_proto) { ++ case htons(ETH_P_IP): ++ nfproto = NFPROTO_IPV4; ++ break; ++ case htons(ETH_P_IPV6): ++ nfproto = NFPROTO_IPV6; ++ break; ++ default: ++ goto unknown_proto; ++ } ++ } ++ ++ switch (nfproto) { ++ case NFPROTO_IPV4: { ++ struct iphdr iph; ++ const struct iphdr *ih; ++ ++ ih = skb_header_pointer(skb, skb_network_offset(skb), ++ sizeof(iph), &iph); ++ if (!ih) ++ return -ENOMEM; ++ ++ audit_log_format(ab, " saddr=%pI4 daddr=%pI4 proto=%hhu", ++ &ih->saddr, &ih->daddr, ih->protocol); ++ break; ++ } ++ case NFPROTO_IPV6: { ++ struct ipv6hdr iph; ++ const struct ipv6hdr *ih; ++ u8 nexthdr; ++ __be16 frag_off; ++ ++ ih = skb_header_pointer(skb, skb_network_offset(skb), ++ sizeof(iph), &iph); ++ if (!ih) ++ return -ENOMEM; ++ ++ nexthdr = ih->nexthdr; ++ ipv6_skip_exthdr(skb, skb_network_offset(skb) + sizeof(iph), ++ &nexthdr, &frag_off); ++ ++ audit_log_format(ab, " saddr=%pI6c daddr=%pI6c proto=%hhu", ++ &ih->saddr, &ih->daddr, nexthdr); ++ break; ++ } ++ default: ++ goto unknown_proto; ++ } ++ ++ return 0; ++ ++unknown_proto: ++ audit_log_format(ab, " saddr=? daddr=? proto=?"); ++ return -EPFNOSUPPORT; ++} ++EXPORT_SYMBOL(audit_log_nf_skb); ++ + /* global counter which is incremented every time something logs in */ + static atomic_t session_id = ATOMIC_INIT(0); + +--- a/net/netfilter/nft_log.c ++++ b/net/netfilter/nft_log.c +@@ -26,46 +26,10 @@ struct nft_log { + char *prefix; + }; + +-static bool audit_ip4(struct audit_buffer *ab, struct sk_buff *skb) +-{ +- struct iphdr _iph; +- const struct iphdr *ih; +- +- ih = skb_header_pointer(skb, skb_network_offset(skb), sizeof(_iph), &_iph); +- if (!ih) +- return false; +- +- audit_log_format(ab, " saddr=%pI4 daddr=%pI4 proto=%hhu", +- &ih->saddr, &ih->daddr, ih->protocol); +- +- return true; +-} +- +-static bool audit_ip6(struct audit_buffer *ab, struct sk_buff *skb) +-{ +- struct ipv6hdr _ip6h; +- const struct ipv6hdr *ih; +- u8 nexthdr; +- __be16 frag_off; +- +- ih = skb_header_pointer(skb, skb_network_offset(skb), sizeof(_ip6h), &_ip6h); +- if (!ih) +- return false; +- +- nexthdr = ih->nexthdr; +- ipv6_skip_exthdr(skb, skb_network_offset(skb) + sizeof(_ip6h), &nexthdr, &frag_off); +- +- audit_log_format(ab, " saddr=%pI6c daddr=%pI6c proto=%hhu", +- &ih->saddr, &ih->daddr, nexthdr); +- +- return true; +-} +- + static void nft_log_eval_audit(const struct nft_pktinfo *pkt) + { + struct sk_buff *skb = pkt->skb; + struct audit_buffer *ab; +- int fam = -1; + + if (!audit_enabled) + return; +@@ -76,27 +40,7 @@ static void nft_log_eval_audit(const str + + audit_log_format(ab, "mark=%#x", skb->mark); + +- switch (nft_pf(pkt)) { +- case NFPROTO_BRIDGE: +- switch (eth_hdr(skb)->h_proto) { +- case htons(ETH_P_IP): +- fam = audit_ip4(ab, skb) ? NFPROTO_IPV4 : -1; +- break; +- case htons(ETH_P_IPV6): +- fam = audit_ip6(ab, skb) ? NFPROTO_IPV6 : -1; +- break; +- } +- break; +- case NFPROTO_IPV4: +- fam = audit_ip4(ab, skb) ? NFPROTO_IPV4 : -1; +- break; +- case NFPROTO_IPV6: +- fam = audit_ip6(ab, skb) ? NFPROTO_IPV6 : -1; +- break; +- } +- +- if (fam == -1) +- audit_log_format(ab, " saddr=? daddr=? proto=-1"); ++ audit_log_nf_skb(ab, skb, nft_pf(pkt)); + + audit_log_end(ab); + } +--- a/net/netfilter/xt_AUDIT.c ++++ b/net/netfilter/xt_AUDIT.c +@@ -28,46 +28,10 @@ MODULE_ALIAS("ip6t_AUDIT"); + MODULE_ALIAS("ebt_AUDIT"); + MODULE_ALIAS("arpt_AUDIT"); + +-static bool audit_ip4(struct audit_buffer *ab, struct sk_buff *skb) +-{ +- struct iphdr _iph; +- const struct iphdr *ih; +- +- ih = skb_header_pointer(skb, skb_network_offset(skb), sizeof(_iph), &_iph); +- if (!ih) +- return false; +- +- audit_log_format(ab, " saddr=%pI4 daddr=%pI4 proto=%hhu", +- &ih->saddr, &ih->daddr, ih->protocol); +- +- return true; +-} +- +-static bool audit_ip6(struct audit_buffer *ab, struct sk_buff *skb) +-{ +- struct ipv6hdr _ip6h; +- const struct ipv6hdr *ih; +- u8 nexthdr; +- __be16 frag_off; +- +- ih = skb_header_pointer(skb, skb_network_offset(skb), sizeof(_ip6h), &_ip6h); +- if (!ih) +- return false; +- +- nexthdr = ih->nexthdr; +- ipv6_skip_exthdr(skb, skb_network_offset(skb) + sizeof(_ip6h), &nexthdr, &frag_off); +- +- audit_log_format(ab, " saddr=%pI6c daddr=%pI6c proto=%hhu", +- &ih->saddr, &ih->daddr, nexthdr); +- +- return true; +-} +- + static unsigned int + audit_tg(struct sk_buff *skb, const struct xt_action_param *par) + { + struct audit_buffer *ab; +- int fam = -1; + + if (audit_enabled == AUDIT_OFF) + goto errout; +@@ -77,27 +41,7 @@ audit_tg(struct sk_buff *skb, const stru + + audit_log_format(ab, "mark=%#x", skb->mark); + +- switch (xt_family(par)) { +- case NFPROTO_BRIDGE: +- switch (eth_hdr(skb)->h_proto) { +- case htons(ETH_P_IP): +- fam = audit_ip4(ab, skb) ? NFPROTO_IPV4 : -1; +- break; +- case htons(ETH_P_IPV6): +- fam = audit_ip6(ab, skb) ? NFPROTO_IPV6 : -1; +- break; +- } +- break; +- case NFPROTO_IPV4: +- fam = audit_ip4(ab, skb) ? NFPROTO_IPV4 : -1; +- break; +- case NFPROTO_IPV6: +- fam = audit_ip6(ab, skb) ? NFPROTO_IPV6 : -1; +- break; +- } +- +- if (fam == -1) +- audit_log_format(ab, " saddr=? daddr=? proto=-1"); ++ audit_log_nf_skb(ab, skb, xt_family(par)); + + audit_log_end(ab); + diff --git a/queue-5.10/audit-fix-potential-integer-overflow-in-audit_log_n_hex.patch b/queue-5.10/audit-fix-potential-integer-overflow-in-audit_log_n_hex.patch new file mode 100644 index 0000000000..6dfa054084 --- /dev/null +++ b/queue-5.10/audit-fix-potential-integer-overflow-in-audit_log_n_hex.patch @@ -0,0 +1,66 @@ +From stable+bounces-278576-greg=kroah.com@vger.kernel.org Tue Jul 21 13:56:50 2026 +From: Sasha Levin +Date: Tue, 21 Jul 2026 07:56:42 -0400 +Subject: audit: fix potential integer overflow in audit_log_n_hex() +To: stable@vger.kernel.org +Cc: Ricardo Robaina , Richard Guy Briggs , Paul Moore , Sasha Levin +Message-ID: <20260721115642.3699441-2-sashal@kernel.org> + +From: Ricardo Robaina + +[ Upstream commit 65dfde57d1e29ce2b76fc23dd565eccd5c0bc0f0 ] + +The function calculates new_len as len << 1 for hex encoding. This +has two overflow risks: the shift itself can overflow when len is +large, and the result can be truncated when assigned to new_len +(declared as int) from the size_t calculation. + +Fix by using check_shl_overflow() to catch shift overflow and +changing new_len and loop counter i to size_t to prevent truncation. + +Cc: stable@vger.kernel.org +Fixes: 168b7173959f ("AUDIT: Clean up logging of untrusted strings") +Reviewed-by: Richard Guy Briggs +Signed-off-by: Ricardo Robaina +[PM: remove vertical whitspace noise] +Signed-off-by: Paul Moore +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + kernel/audit.c | 11 +++++++++-- + 1 file changed, 9 insertions(+), 2 deletions(-) + +--- a/kernel/audit.c ++++ b/kernel/audit.c +@@ -61,6 +61,7 @@ + #include + #include + #include ++#include + + #include "audit.h" + +@@ -2034,7 +2035,8 @@ void audit_log_format(struct audit_buffe + void audit_log_n_hex(struct audit_buffer *ab, const unsigned char *buf, + size_t len) + { +- int i, avail, new_len; ++ int avail; ++ size_t i, new_len; + unsigned char *ptr; + struct sk_buff *skb; + +@@ -2044,7 +2046,12 @@ void audit_log_n_hex(struct audit_buffer + BUG_ON(!ab->skb); + skb = ab->skb; + avail = skb_tailroom(skb); +- new_len = len<<1; ++ ++ if (check_shl_overflow(len, 1, &new_len)) { ++ audit_log_format(ab, "?"); ++ return; ++ } ++ + if (new_len >= avail) { + /* Round the buffer request up to the next multiple */ + new_len = AUDIT_BUFSIZ*(((new_len-avail)/AUDIT_BUFSIZ) + 1); diff --git a/queue-5.10/binder-fix-uaf-in-binder_free_transaction.patch b/queue-5.10/binder-fix-uaf-in-binder_free_transaction.patch new file mode 100644 index 0000000000..6f121c9fc5 --- /dev/null +++ b/queue-5.10/binder-fix-uaf-in-binder_free_transaction.patch @@ -0,0 +1,99 @@ +From sashal@kernel.org Tue Jul 14 16:06:19 2026 +From: Sasha Levin +Date: Tue, 14 Jul 2026 10:06:12 -0400 +Subject: binder: fix UAF in binder_free_transaction() +To: stable@vger.kernel.org +Cc: Carlos Llamas , stable , Alice Ryhl , Greg Kroah-Hartman , Sasha Levin +Message-ID: <20260714140612.2729754-2-sashal@kernel.org> + +From: Carlos Llamas + +[ Upstream commit f223d27a546c1e1f48d38fd67760e78f068fe8c4 ] + +In binder_free_transaction(), the t->to_proc is read under the t->lock. +However, once the t->lock is dropped, the to_proc can die in parallel. +This leads to a use-after-free error when we attempt to acquire its +inner lock right afterwards: + + ================================================================== + BUG: KASAN: slab-use-after-free in _raw_spin_lock+0xe4/0x1a0 + Write of size 4 at addr ffff00001125da70 by task B/672 + + CPU: 20 UID: 0 PID: 672 Comm: B Not tainted 7.1.0-rc6-00284-g8e65320d91cd #4 PREEMPT + Hardware name: linux,dummy-virt (DT) + Call trace: + _raw_spin_lock+0xe4/0x1a0 + binder_free_transaction+0x8c/0x320 + binder_send_failed_reply+0x21c/0x2f8 + binder_thread_release+0x488/0x7e0 + binder_ioctl+0x12c0/0x29a0 + [...] + + Allocated by task 675: + __kmalloc_cache_noprof+0x174/0x444 + binder_open+0x118/0xb70 + do_dentry_open+0x374/0x1040 + vfs_open+0x58/0x3bc + [...] + + Freed by task 212: + __kasan_slab_free+0x58/0x80 + kfree+0x1a0/0x4a4 + binder_proc_dec_tmpref+0x32c/0x5e0 + binder_deferred_func+0xc48/0x104c + process_one_work+0x53c/0xbc0 + [...] + ================================================================== + +To prevent this, pin the target thread (t->to_thread) to guarantee the +target process remains alive. Undelivered transactions without a target +thread are already safe, as the target process can only be the current +context in those paths. + +Cc: stable +Reported-by: Alice Ryhl +Closes: https://lore.kernel.org/all/aikJKVuny_eOivwN@google.com/ +Fixes: a370003cc301 ("binder: fix possible UAF when freeing buffer") +Signed-off-by: Carlos Llamas +Reviewed-by: Alice Ryhl +Link: https://patch.msgid.link/20260619185233.2194678-2-cmllamas@google.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/android/binder.c | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +--- a/drivers/android/binder.c ++++ b/drivers/android/binder.c +@@ -1909,10 +1909,19 @@ static void binder_free_txn_fixups(struc + + static void binder_free_transaction(struct binder_transaction *t) + { ++ struct binder_thread *target_thread; + struct binder_proc *target_proc; + + spin_lock(&t->lock); + target_proc = t->to_proc; ++ target_thread = t->to_thread; ++ /* ++ * Pin target_thread to keep target_proc alive. Undelivered ++ * transactions with !target_thread are safe, as target_proc ++ * can only be the current context there. ++ */ ++ if (target_thread) ++ atomic_inc(&target_thread->tmp_ref); + spin_unlock(&t->lock); + + if (target_proc) { +@@ -1921,6 +1930,10 @@ static void binder_free_transaction(stru + t->buffer->transaction = NULL; + binder_inner_proc_unlock(target_proc); + } ++ ++ if (target_thread) ++ binder_thread_dec_tmpref(target_thread); ++ + /* + * If the transaction has no target_proc, then + * t->buffer->transaction has already been cleared. diff --git a/queue-5.10/bitops-make-bytes_to_bits-treewide-available.patch b/queue-5.10/bitops-make-bytes_to_bits-treewide-available.patch new file mode 100644 index 0000000000..a2cd5753e4 --- /dev/null +++ b/queue-5.10/bitops-make-bytes_to_bits-treewide-available.patch @@ -0,0 +1,90 @@ +From stable+bounces-274097-greg=kroah.com@vger.kernel.org Tue Jul 14 05:06:45 2026 +From: Sasha Levin +Date: Mon, 13 Jul 2026 23:04:47 -0400 +Subject: bitops: make BYTES_TO_BITS() treewide-available +To: stable@vger.kernel.org +Cc: Alexander Lobakin , Andy Shevchenko , Przemek Kitszel , Yury Norov , "David S. Miller" , Sasha Levin +Message-ID: <20260714030448.2382602-1-sashal@kernel.org> + +From: Alexander Lobakin + +[ Upstream commit 7d8296b250f2eed73f1758607926d4d258dea5d4 ] + +Avoid open-coding that simple expression each time by moving +BYTES_TO_BITS() from the probes code to to export +it to the rest of the kernel. +Simplify the macro while at it. `BITS_PER_LONG / sizeof(long)` always +equals to %BITS_PER_BYTE, regardless of the target architecture. +Do the same for the tools ecosystem as well (incl. its version of +bitops.h). The previous implementation had its implicit type of long, +while the new one is int, so adjust the format literal accordingly in +the perf code. + +Suggested-by: Andy Shevchenko +Reviewed-by: Przemek Kitszel +Acked-by: Yury Norov +Signed-off-by: Alexander Lobakin +Signed-off-by: David S. Miller +Stable-dep-of: 55052184ac90 ("iio: common: st_sensors: honour channel endianness in read_axis_data") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + include/linux/bitops.h | 2 ++ + kernel/trace/trace_probe.c | 2 -- + tools/include/linux/bitops.h | 2 ++ + tools/perf/util/probe-finder.c | 4 +--- + 4 files changed, 5 insertions(+), 5 deletions(-) + +--- a/include/linux/bitops.h ++++ b/include/linux/bitops.h +@@ -17,6 +17,8 @@ + #define BITS_TO_U32(nr) DIV_ROUND_UP(nr, BITS_PER_TYPE(u32)) + #define BITS_TO_BYTES(nr) DIV_ROUND_UP(nr, BITS_PER_TYPE(char)) + ++#define BYTES_TO_BITS(nb) ((nb) * BITS_PER_BYTE) ++ + extern unsigned int __sw_hweight8(unsigned int w); + extern unsigned int __sw_hweight16(unsigned int w); + extern unsigned int __sw_hweight32(unsigned int w); +--- a/kernel/trace/trace_probe.c ++++ b/kernel/trace/trace_probe.c +@@ -503,8 +503,6 @@ parse_probe_arg(char *arg, const struct + return ret; + } + +-#define BYTES_TO_BITS(nb) ((BITS_PER_LONG * (nb)) / sizeof(long)) +- + /* Bitfield type needs to be parsed into a fetch function */ + static int __parse_bitfield_probe_arg(const char *bf, + const struct fetch_type *t, +--- a/tools/include/linux/bitops.h ++++ b/tools/include/linux/bitops.h +@@ -20,6 +20,8 @@ + #define BITS_TO_U32(nr) DIV_ROUND_UP(nr, BITS_PER_TYPE(u32)) + #define BITS_TO_BYTES(nr) DIV_ROUND_UP(nr, BITS_PER_TYPE(char)) + ++#define BYTES_TO_BITS(nb) ((nb) * BITS_PER_BYTE) ++ + extern unsigned int __sw_hweight8(unsigned int w); + extern unsigned int __sw_hweight16(unsigned int w); + extern unsigned int __sw_hweight32(unsigned int w); +--- a/tools/perf/util/probe-finder.c ++++ b/tools/perf/util/probe-finder.c +@@ -299,8 +299,6 @@ static_var: + return ret2; + } + +-#define BYTES_TO_BITS(nb) ((nb) * BITS_PER_LONG / sizeof(long)) +- + static int convert_variable_type(Dwarf_Die *vr_die, + struct probe_trace_arg *tvar, + const char *cast, bool user_access) +@@ -330,7 +328,7 @@ static int convert_variable_type(Dwarf_D + total = dwarf_bytesize(vr_die); + if (boffs < 0 || total < 0) + return -ENOENT; +- ret = snprintf(buf, 16, "b%d@%d/%zd", bsize, boffs, ++ ret = snprintf(buf, 16, "b%d@%d/%d", bsize, boffs, + BYTES_TO_BITS(total)); + goto formatted; + } diff --git a/queue-5.10/bluetooth-btintel-check-firmware-version-before-download.patch b/queue-5.10/bluetooth-btintel-check-firmware-version-before-download.patch new file mode 100644 index 0000000000..d61168318b --- /dev/null +++ b/queue-5.10/bluetooth-btintel-check-firmware-version-before-download.patch @@ -0,0 +1,263 @@ +From stable+bounces-274238-greg=kroah.com@vger.kernel.org Tue Jul 14 15:31:51 2026 +From: Sasha Levin +Date: Tue, 14 Jul 2026 09:26:48 -0400 +Subject: Bluetooth: btintel: Check firmware version before download +To: stable@vger.kernel.org +Cc: Luiz Augusto von Dentz , Tedd Ho-Jeong An , Marcel Holtmann , Sasha Levin +Message-ID: <20260714132650.2663656-2-sashal@kernel.org> + +From: Luiz Augusto von Dentz + +[ Upstream commit ac0565462e330a2b762ca5849a4140b29d725786 ] + +This checks the firmware build number, week and year against the +repective loaded version. If details are a match, skip the download +process. + +Signed-off-by: Luiz Augusto von Dentz +Tested-by: Tedd Ho-Jeong An +Signed-off-by: Marcel Holtmann +Stable-dep-of: c5b600a3c05b ("Bluetooth: btusb: fix use-after-free on marvell probe failure") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/bluetooth/btintel.c | 106 +++++++++++++++++++++++++++++++++--------- + drivers/bluetooth/btintel.h | 5 + + drivers/bluetooth/btusb.c | 9 +++ + drivers/bluetooth/hci_intel.c | 7 +- + 4 files changed, 101 insertions(+), 26 deletions(-) + +--- a/drivers/bluetooth/btintel.c ++++ b/drivers/bluetooth/btintel.c +@@ -24,6 +24,14 @@ + #define ECDSA_OFFSET 644 + #define ECDSA_HEADER_LEN 320 + ++#define CMD_WRITE_BOOT_PARAMS 0xfc0e ++struct cmd_write_boot_params { ++ u32 boot_addr; ++ u8 fw_build_num; ++ u8 fw_build_ww; ++ u8 fw_build_yy; ++} __packed; ++ + int btintel_check_bdaddr(struct hci_dev *hdev) + { + struct hci_rp_read_bd_addr *bda; +@@ -841,7 +849,7 @@ static int btintel_sfi_ecdsa_header_secu + + static int btintel_download_firmware_payload(struct hci_dev *hdev, + const struct firmware *fw, +- u32 *boot_param, size_t offset) ++ size_t offset) + { + int err; + const u8 *fw_ptr; +@@ -854,21 +862,6 @@ static int btintel_download_firmware_pay + while (fw_ptr - fw->data < fw->size) { + struct hci_command_hdr *cmd = (void *)(fw_ptr + frag_len); + +- /* Each SKU has a different reset parameter to use in the +- * HCI_Intel_Reset command and it is embedded in the firmware +- * data. So, instead of using static value per SKU, check +- * the firmware data and save it for later use. +- */ +- if (le16_to_cpu(cmd->opcode) == 0xfc0e) { +- /* The boot parameter is the first 32-bit value +- * and rest of 3 octets are reserved. +- */ +- *boot_param = get_unaligned_le32(fw_ptr + frag_len + +- sizeof(*cmd)); +- +- bt_dev_dbg(hdev, "boot_param=0x%x", *boot_param); +- } +- + frag_len += sizeof(*cmd) + cmd->plen; + + /* The parameter length of the secure send command requires +@@ -897,28 +890,101 @@ done: + return err; + } + ++static bool btintel_firmware_version(struct hci_dev *hdev, ++ u8 num, u8 ww, u8 yy, ++ const struct firmware *fw, ++ u32 *boot_addr) ++{ ++ const u8 *fw_ptr; ++ ++ fw_ptr = fw->data; ++ ++ while (fw_ptr - fw->data < fw->size) { ++ struct hci_command_hdr *cmd = (void *)(fw_ptr); ++ ++ /* Each SKU has a different reset parameter to use in the ++ * HCI_Intel_Reset command and it is embedded in the firmware ++ * data. So, instead of using static value per SKU, check ++ * the firmware data and save it for later use. ++ */ ++ if (le16_to_cpu(cmd->opcode) == CMD_WRITE_BOOT_PARAMS) { ++ struct cmd_write_boot_params *params; ++ ++ params = (void *)(fw_ptr + sizeof(*cmd)); ++ ++ bt_dev_info(hdev, "Boot Address: 0x%x", ++ le32_to_cpu(params->boot_addr)); ++ ++ bt_dev_info(hdev, "Firmware Version: %u-%u.%u", ++ params->fw_build_num, params->fw_build_ww, ++ params->fw_build_yy); ++ ++ return (num == params->fw_build_num && ++ ww == params->fw_build_ww && ++ yy == params->fw_build_yy); ++ } ++ ++ fw_ptr += sizeof(*cmd) + cmd->plen; ++ } ++ ++ return false; ++} ++ + int btintel_download_firmware(struct hci_dev *hdev, ++ struct intel_version *ver, + const struct firmware *fw, + u32 *boot_param) + { + int err; + ++ /* SfP and WsP don't seem to update the firmware version on file ++ * so version checking is currently not possible. ++ */ ++ switch (ver->hw_variant) { ++ case 0x0b: /* SfP */ ++ case 0x0c: /* WsP */ ++ /* Skip version checking */ ++ break; ++ default: ++ /* Skip download if firmware has the same version */ ++ if (btintel_firmware_version(hdev, ver->fw_build_num, ++ ver->fw_build_ww, ver->fw_build_yy, ++ fw, boot_param)) { ++ bt_dev_info(hdev, "Firmware already loaded"); ++ /* Return -EALREADY to indicate that the firmware has ++ * already been loaded. ++ */ ++ return -EALREADY; ++ } ++ } ++ + err = btintel_sfi_rsa_header_secure_send(hdev, fw); + if (err) + return err; + +- return btintel_download_firmware_payload(hdev, fw, boot_param, +- RSA_HEADER_LEN); ++ return btintel_download_firmware_payload(hdev, fw, RSA_HEADER_LEN); + } + EXPORT_SYMBOL_GPL(btintel_download_firmware); + + int btintel_download_firmware_newgen(struct hci_dev *hdev, ++ struct intel_version_tlv *ver, + const struct firmware *fw, u32 *boot_param, + u8 hw_variant, u8 sbe_type) + { + int err; + u32 css_header_ver; + ++ /* Skip download if firmware has the same version */ ++ if (btintel_firmware_version(hdev, ver->min_fw_build_nn, ++ ver->min_fw_build_cw, ver->min_fw_build_yy, ++ fw, boot_param)) { ++ bt_dev_info(hdev, "Firmware already loaded"); ++ /* Return -EALREADY to indicate that firmware has already been ++ * loaded. ++ */ ++ return -EALREADY; ++ } ++ + /* iBT hardware variants 0x0b, 0x0c, 0x11, 0x12, 0x13, 0x14 support + * only RSA secure boot engine. Hence, the corresponding sfi file will + * have RSA header of 644 bytes followed by Command Buffer. +@@ -948,7 +1014,7 @@ int btintel_download_firmware_newgen(str + if (err) + return err; + +- err = btintel_download_firmware_payload(hdev, fw, boot_param, RSA_HEADER_LEN); ++ err = btintel_download_firmware_payload(hdev, fw, RSA_HEADER_LEN); + if (err) + return err; + } else if (hw_variant >= 0x17) { +@@ -969,7 +1035,6 @@ int btintel_download_firmware_newgen(str + return err; + + err = btintel_download_firmware_payload(hdev, fw, +- boot_param, + RSA_HEADER_LEN + ECDSA_HEADER_LEN); + if (err) + return err; +@@ -979,7 +1044,6 @@ int btintel_download_firmware_newgen(str + return err; + + err = btintel_download_firmware_payload(hdev, fw, +- boot_param, + RSA_HEADER_LEN + ECDSA_HEADER_LEN); + if (err) + return err; +--- a/drivers/bluetooth/btintel.h ++++ b/drivers/bluetooth/btintel.h +@@ -157,9 +157,10 @@ struct regmap *btintel_regmap_init(struc + int btintel_send_intel_reset(struct hci_dev *hdev, u32 boot_param); + int btintel_read_boot_params(struct hci_dev *hdev, + struct intel_boot_params *params); +-int btintel_download_firmware(struct hci_dev *dev, const struct firmware *fw, +- u32 *boot_param); ++int btintel_download_firmware(struct hci_dev *dev, struct intel_version *ver, ++ const struct firmware *fw, u32 *boot_param); + int btintel_download_firmware_newgen(struct hci_dev *hdev, ++ struct intel_version_tlv *ver, + const struct firmware *fw, + u32 *boot_param, u8 hw_variant, + u8 sbe_type); +--- a/drivers/bluetooth/btusb.c ++++ b/drivers/bluetooth/btusb.c +@@ -2602,8 +2602,15 @@ static int btusb_intel_download_firmware + set_bit(BTUSB_DOWNLOADING, &data->flags); + + /* Start firmware downloading and get boot parameter */ +- err = btintel_download_firmware(hdev, fw, boot_param); ++ err = btintel_download_firmware(hdev, ver, fw, boot_param); + if (err < 0) { ++ if (err == -EALREADY) { ++ /* Firmware has already been loaded */ ++ set_bit(BTUSB_FIRMWARE_LOADED, &data->flags); ++ err = 0; ++ goto done; ++ } ++ + /* When FW download fails, send Intel Reset to retry + * FW download. + */ +--- a/drivers/bluetooth/hci_intel.c ++++ b/drivers/bluetooth/hci_intel.c +@@ -735,7 +735,7 @@ static int intel_setup(struct hci_uart * + set_bit(STATE_DOWNLOADING, &intel->flags); + + /* Start firmware downloading and get boot parameter */ +- err = btintel_download_firmware(hdev, fw, &boot_param); ++ err = btintel_download_firmware(hdev, &ver, fw, &boot_param); + if (err < 0) + goto done; + +@@ -784,7 +784,10 @@ static int intel_setup(struct hci_uart * + done: + release_firmware(fw); + +- if (err < 0) ++ /* Check if there was an error and if is not -EALREADY which means the ++ * firmware has already been loaded. ++ */ ++ if (err < 0 && err != -EALREADY) + return err; + + /* We need to restore the default speed before Intel reset */ diff --git a/queue-5.10/bluetooth-btintel-fix-offset-calculation-boot-address-parameter.patch b/queue-5.10/bluetooth-btintel-fix-offset-calculation-boot-address-parameter.patch new file mode 100644 index 0000000000..60fdd448ad --- /dev/null +++ b/queue-5.10/bluetooth-btintel-fix-offset-calculation-boot-address-parameter.patch @@ -0,0 +1,36 @@ +From stable+bounces-274237-greg=kroah.com@vger.kernel.org Tue Jul 14 15:35:43 2026 +From: Sasha Levin +Date: Tue, 14 Jul 2026 09:26:47 -0400 +Subject: Bluetooth: btintel: Fix offset calculation boot address parameter +To: stable@vger.kernel.org +Cc: Kiran K , Marcel Holtmann , Sasha Levin +Message-ID: <20260714132650.2663656-1-sashal@kernel.org> + +From: Kiran K + +[ Upstream commit d00745da644d42c2f97293eb3fe19cfd5c0b073c ] + +Boot address parameter was not getting updated properly +due to wrong offset + +Signed-off-by: Kiran K +Signed-off-by: Marcel Holtmann +Stable-dep-of: c5b600a3c05b ("Bluetooth: btusb: fix use-after-free on marvell probe failure") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/bluetooth/btintel.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/bluetooth/btintel.c ++++ b/drivers/bluetooth/btintel.c +@@ -863,7 +863,8 @@ static int btintel_download_firmware_pay + /* The boot parameter is the first 32-bit value + * and rest of 3 octets are reserved. + */ +- *boot_param = get_unaligned_le32(fw_ptr + sizeof(*cmd)); ++ *boot_param = get_unaligned_le32(fw_ptr + frag_len + ++ sizeof(*cmd)); + + bt_dev_dbg(hdev, "boot_param=0x%x", *boot_param); + } diff --git a/queue-5.10/bluetooth-btusb-fix-use-after-free-on-marvell-probe-failure.patch b/queue-5.10/bluetooth-btusb-fix-use-after-free-on-marvell-probe-failure.patch new file mode 100644 index 0000000000..a5fed6e37d --- /dev/null +++ b/queue-5.10/bluetooth-btusb-fix-use-after-free-on-marvell-probe-failure.patch @@ -0,0 +1,60 @@ +From stable+bounces-274240-greg=kroah.com@vger.kernel.org Tue Jul 14 15:31:58 2026 +From: Sasha Levin +Date: Tue, 14 Jul 2026 09:26:50 -0400 +Subject: Bluetooth: btusb: fix use-after-free on marvell probe failure +To: stable@vger.kernel.org +Cc: Johan Hovold , Rajat Jain , Luiz Augusto von Dentz , Sasha Levin +Message-ID: <20260714132650.2663656-4-sashal@kernel.org> + +From: Johan Hovold + +[ Upstream commit c5b600a3c05b1a7a110d558df935a8fc8a471c79 ] + +Make sure to stop any TX URBs submitted during Marvell OOB wakeup +configuration on later probe failures to avoid use-after-free in the +completion callback. + +This issue was reported by Sashiko while reviewing a fix for a wakeup +source leak in the btusb probe errors paths. + +Link: https://sashiko.dev/#/patchset/20260402092704.2346710-1-johan%40kernel.org +Fixes: a4ccc9e33d2f ("Bluetooth: btusb: Configure Marvell to use one of the pins for oob wakeup") +Cc: stable@vger.kernel.org # 4.11 +Cc: Rajat Jain +Signed-off-by: Johan Hovold +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/bluetooth/btusb.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +--- a/drivers/bluetooth/btusb.c ++++ b/drivers/bluetooth/btusb.c +@@ -4352,7 +4352,7 @@ static int btusb_probe(struct usb_interf + err = usb_set_interface(data->udev, 0, 0); + if (err < 0) { + BT_ERR("failed to set interface 0, alt 0 %d", err); +- goto out_free_dev; ++ goto err_kill_tx_urbs; + } + } + +@@ -4360,7 +4360,7 @@ static int btusb_probe(struct usb_interf + err = usb_driver_claim_interface(&btusb_driver, + data->isoc, data); + if (err < 0) +- goto out_free_dev; ++ goto err_kill_tx_urbs; + } + + if (IS_ENABLED(CONFIG_BT_HCIBTUSB_BCM) && data->diag) { +@@ -4391,6 +4391,8 @@ err_release_siblings: + usb_set_intfdata(data->isoc, NULL); + usb_driver_release_interface(&btusb_driver, data->isoc); + } ++err_kill_tx_urbs: ++ usb_kill_anchored_urbs(&data->tx_anchor); + out_free_dev: + if (data->reset_gpio) + gpiod_put(data->reset_gpio); diff --git a/queue-5.10/bluetooth-btusb-fix-wakeup-source-leak-on-probe-failure.patch b/queue-5.10/bluetooth-btusb-fix-wakeup-source-leak-on-probe-failure.patch new file mode 100644 index 0000000000..b3a53f7a74 --- /dev/null +++ b/queue-5.10/bluetooth-btusb-fix-wakeup-source-leak-on-probe-failure.patch @@ -0,0 +1,82 @@ +From stable+bounces-274245-greg=kroah.com@vger.kernel.org Tue Jul 14 15:27:22 2026 +From: Sasha Levin +Date: Tue, 14 Jul 2026 09:26:57 -0400 +Subject: Bluetooth: btusb: fix wakeup source leak on probe failure +To: stable@vger.kernel.org +Cc: Johan Hovold , Rajat Jain , Luiz Augusto von Dentz , Sasha Levin +Message-ID: <20260714132657.2663805-5-sashal@kernel.org> + +From: Johan Hovold + +[ Upstream commit 3d93e1bb0fb881fe3ef961d1120556658e9cac4d ] + +Make sure to disable wakeup on probe failure to avoid leaking the wakeup +source. + +Fixes: fd913ef7ce61 ("Bluetooth: btusb: Add out-of-band wakeup support") +Cc: stable@vger.kernel.org # 4.11 +Cc: Rajat Jain +Signed-off-by: Johan Hovold +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/bluetooth/btusb.c | 18 +++++++++++++++--- + 1 file changed, 15 insertions(+), 3 deletions(-) + +--- a/drivers/bluetooth/btusb.c ++++ b/drivers/bluetooth/btusb.c +@@ -3501,6 +3501,11 @@ static int marvell_config_oob_wake(struc + + return 0; + } ++#else ++static inline int marvell_config_oob_wake(struct hci_dev *hdev) ++{ ++ return 0; ++} + #endif + + static int btusb_set_bdaddr_marvell(struct hci_dev *hdev, +@@ -4011,6 +4016,11 @@ static int btusb_config_oob_wake(struct + bt_dev_info(hdev, "OOB Wake-on-BT configured at IRQ %u", irq); + return 0; + } ++#else ++static inline int btusb_config_oob_wake(struct hci_dev *hdev) ++{ ++ return 0; ++} + #endif + + static void btusb_check_needs_reset_resume(struct usb_interface *intf) +@@ -4164,7 +4174,6 @@ static int btusb_probe(struct usb_interf + hdev->notify = btusb_notify; + hdev->prevent_wake = btusb_prevent_wake; + +-#ifdef CONFIG_PM + err = btusb_config_oob_wake(hdev); + if (err) + goto out_free_dev; +@@ -4173,9 +4182,9 @@ static int btusb_probe(struct usb_interf + if (id->driver_info & BTUSB_MARVELL && data->oob_wake_irq) { + err = marvell_config_oob_wake(hdev); + if (err) +- goto out_free_dev; ++ goto err_disable_wakeup; + } +-#endif ++ + if (id->driver_info & BTUSB_CW6622) + set_bit(HCI_QUIRK_BROKEN_STORED_LINK_KEY, &hdev->quirks); + +@@ -4393,6 +4402,9 @@ err_release_siblings: + } + err_kill_tx_urbs: + usb_kill_anchored_urbs(&data->tx_anchor); ++err_disable_wakeup: ++ if (data->oob_wake_irq) ++ device_init_wakeup(&data->udev->dev, false); + out_free_dev: + if (data->reset_gpio) + gpiod_put(data->reset_gpio); diff --git a/queue-5.10/bluetooth-l2cap-cancel-pending_rx_work-before-taking-conn-lock.patch b/queue-5.10/bluetooth-l2cap-cancel-pending_rx_work-before-taking-conn-lock.patch new file mode 100644 index 0000000000..13fdb41742 --- /dev/null +++ b/queue-5.10/bluetooth-l2cap-cancel-pending_rx_work-before-taking-conn-lock.patch @@ -0,0 +1,67 @@ +From stable+bounces-275107-greg=kroah.com@vger.kernel.org Thu Jul 16 02:17:01 2026 +From: Sasha Levin +Date: Wed, 15 Jul 2026 20:16:50 -0400 +Subject: Bluetooth: L2CAP: cancel pending_rx_work before taking conn->lock +To: stable@vger.kernel.org +Cc: Runyu Xiao , Luiz Augusto von Dentz , Sasha Levin +Message-ID: <20260716001650.589781-3-sashal@kernel.org> + +From: Runyu Xiao + +[ Upstream commit 2641a9e0a1dd4af2e21995470a21d55dd35e5203 ] + +l2cap_conn_del() takes conn->lock and then calls cancel_work_sync() for +pending_rx_work. process_pending_rx() takes the same mutex, so teardown +can deadlock against the worker it is flushing. + +This issue was found by our static analysis tool and then manually +reviewed against the current tree. + +The grounded PoC kept the l2cap_conn_ready() -> queue_work(..., +&conn->pending_rx_work) submit path, the l2cap_conn_del() -> +cancel_work_sync(&conn->pending_rx_work) teardown path, and the +process_pending_rx() -> mutex_lock(&conn->lock) worker edge. Lockdep +reported: + + WARNING: possible circular locking dependency detected + process_pending_rx+0x21/0x2a [vuln_msv] + l2cap_conn_del.constprop.0+0x3f/0x4e [vuln_msv] + *** DEADLOCK *** + +Cancel pending_rx_work before taking conn->lock, matching the existing +lock-before-drain ordering used for the two delayed works in the same +teardown path. The pending_rx queue is still purged after the work has +been cancelled and conn->lock has been acquired. + +Fixes: 7ab56c3a6ecc ("Bluetooth: Fix deadlock in l2cap_conn_del()") +Cc: stable@vger.kernel.org +Signed-off-by: Runyu Xiao +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + net/bluetooth/l2cap_core.c | 10 ++-------- + 1 file changed, 2 insertions(+), 8 deletions(-) + +--- a/net/bluetooth/l2cap_core.c ++++ b/net/bluetooth/l2cap_core.c +@@ -1901,17 +1901,11 @@ static void l2cap_conn_del(struct hci_co + cancel_delayed_work_sync(&conn->info_timer); + cancel_work_sync(&conn->id_addr_update_work); + ++ cancel_work_sync(&conn->pending_rx_work); ++ + kfree_skb(conn->rx_skb); + + skb_queue_purge(&conn->pending_rx); +- +- /* We can not call flush_work(&conn->pending_rx_work) here since we +- * might block if we are running on a worker from the same workqueue +- * pending_rx_work is waiting on. +- */ +- if (work_pending(&conn->pending_rx_work)) +- cancel_work_sync(&conn->pending_rx_work); +- + ida_destroy(&conn->tx_ida); + + l2cap_unregister_all_users(conn); diff --git a/queue-5.10/bluetooth-l2cap-fix-deadlock-in-l2cap_conn_del.patch b/queue-5.10/bluetooth-l2cap-fix-deadlock-in-l2cap_conn_del.patch new file mode 100644 index 0000000000..6d0554b833 --- /dev/null +++ b/queue-5.10/bluetooth-l2cap-fix-deadlock-in-l2cap_conn_del.patch @@ -0,0 +1,65 @@ +From stable+bounces-275106-greg=kroah.com@vger.kernel.org Thu Jul 16 02:16:59 2026 +From: Sasha Levin +Date: Wed, 15 Jul 2026 20:16:49 -0400 +Subject: Bluetooth: L2CAP: Fix deadlock in l2cap_conn_del() +To: stable@vger.kernel.org +Cc: Hyunwoo Kim , Luiz Augusto von Dentz , Sasha Levin +Message-ID: <20260716001650.589781-2-sashal@kernel.org> + +From: Hyunwoo Kim + +[ Upstream commit 00fdebbbc557a2fc21321ff2eaa22fd70c078608 ] + +l2cap_conn_del() calls cancel_delayed_work_sync() for both info_timer +and id_addr_timer while holding conn->lock. However, the work functions +l2cap_info_timeout() and l2cap_conn_update_id_addr() both acquire +conn->lock, creating a potential AB-BA deadlock if the work is already +executing when l2cap_conn_del() takes the lock. + +Move the work cancellations before acquiring conn->lock and use +disable_delayed_work_sync() to additionally prevent the works from +being rearmed after cancellation, consistent with the pattern used in +hci_conn_del(). + +Fixes: ab4eedb790ca ("Bluetooth: L2CAP: Fix corrupted list in hci_chan_del") +Signed-off-by: Hyunwoo Kim +Signed-off-by: Luiz Augusto von Dentz +Stable-dep-of: 2641a9e0a1dd ("Bluetooth: L2CAP: cancel pending_rx_work before taking conn->lock") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + net/bluetooth/l2cap_core.c | 9 +++------ + 1 file changed, 3 insertions(+), 6 deletions(-) + +--- a/net/bluetooth/l2cap_core.c ++++ b/net/bluetooth/l2cap_core.c +@@ -1898,6 +1898,9 @@ static void l2cap_conn_del(struct hci_co + + BT_DBG("hcon %p conn %p, err %d", hcon, conn, err); + ++ cancel_delayed_work_sync(&conn->info_timer); ++ cancel_work_sync(&conn->id_addr_update_work); ++ + kfree_skb(conn->rx_skb); + + skb_queue_purge(&conn->pending_rx); +@@ -1911,9 +1914,6 @@ static void l2cap_conn_del(struct hci_co + + ida_destroy(&conn->tx_ida); + +- if (work_pending(&conn->id_addr_update_work)) +- cancel_work_sync(&conn->id_addr_update_work); +- + l2cap_unregister_all_users(conn); + + /* Force the connection to be immediately dropped */ +@@ -1938,9 +1938,6 @@ static void l2cap_conn_del(struct hci_co + + hci_chan_del(conn->hchan); + +- if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) +- cancel_delayed_work_sync(&conn->info_timer); +- + hcon->l2cap_data = NULL; + conn->hchan = NULL; + l2cap_conn_put(conn); diff --git a/queue-5.10/bluetooth-l2cap-fix-not-tracking-outstanding-tx-ident.patch b/queue-5.10/bluetooth-l2cap-fix-not-tracking-outstanding-tx-ident.patch new file mode 100644 index 0000000000..35bf8ecd4e --- /dev/null +++ b/queue-5.10/bluetooth-l2cap-fix-not-tracking-outstanding-tx-ident.patch @@ -0,0 +1,154 @@ +From stable+bounces-275105-greg=kroah.com@vger.kernel.org Thu Jul 16 02:16:57 2026 +From: Sasha Levin +Date: Wed, 15 Jul 2026 20:16:48 -0400 +Subject: Bluetooth: L2CAP: Fix not tracking outstanding TX ident +To: stable@vger.kernel.org +Cc: Luiz Augusto von Dentz , Paul Menzel , Sasha Levin +Message-ID: <20260716001650.589781-1-sashal@kernel.org> + +From: Luiz Augusto von Dentz + +[ Upstream commit 6c3ea155e5ee3e56606233acde8309afda66d483 ] + +This attempts to proper track outstanding request by using struct ida +and allocating from it in l2cap_get_ident using ida_alloc_range which +would reuse ids as they are free, then upon completion release +the id using ida_free. + +This fixes the qualification test case L2CAP/COS/CED/BI-29-C which +attempts to check if the host stack is able to work after 256 attempts +to connect which requires Ident field to use the full range of possible +values in order to pass the test. + +Link: https://github.com/bluez/bluez/issues/1829 +Signed-off-by: Luiz Augusto von Dentz +Reviewed-by: Paul Menzel +Stable-dep-of: 2641a9e0a1dd ("Bluetooth: L2CAP: cancel pending_rx_work before taking conn->lock") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + include/net/bluetooth/l2cap.h | 3 -- + net/bluetooth/l2cap_core.c | 53 ++++++++++++++++++++++++++++++------------ + 2 files changed, 40 insertions(+), 16 deletions(-) + +--- a/include/net/bluetooth/l2cap.h ++++ b/include/net/bluetooth/l2cap.h +@@ -690,8 +690,7 @@ struct l2cap_conn { + + struct sk_buff *rx_skb; + __u32 rx_len; +- __u8 tx_ident; +- struct mutex ident_lock; ++ struct ida tx_ida; + + struct sk_buff_head pending_rx; + struct work_struct pending_rx_work; +--- a/net/bluetooth/l2cap_core.c ++++ b/net/bluetooth/l2cap_core.c +@@ -939,26 +939,18 @@ int l2cap_chan_check_security(struct l2c + initiator); + } + +-static u8 l2cap_get_ident(struct l2cap_conn *conn) ++static int l2cap_get_ident(struct l2cap_conn *conn) + { +- u8 id; ++ /* LE link does not support tools like l2ping so use the full range */ ++ if (conn->hcon->type == LE_LINK) ++ return ida_alloc_range(&conn->tx_ida, 1, 255, GFP_ATOMIC); + + /* Get next available identificator. + * 1 - 128 are used by kernel. + * 129 - 199 are reserved. + * 200 - 254 are used by utilities like l2ping, etc. + */ +- +- mutex_lock(&conn->ident_lock); +- +- if (++conn->tx_ident > 128) +- conn->tx_ident = 1; +- +- id = conn->tx_ident; +- +- mutex_unlock(&conn->ident_lock); +- +- return id; ++ return ida_alloc_range(&conn->tx_ida, 1, 128, GFP_ATOMIC); + } + + static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, +@@ -1917,6 +1909,8 @@ static void l2cap_conn_del(struct hci_co + if (work_pending(&conn->pending_rx_work)) + cancel_work_sync(&conn->pending_rx_work); + ++ ida_destroy(&conn->tx_ida); ++ + if (work_pending(&conn->id_addr_update_work)) + cancel_work_sync(&conn->id_addr_update_work); + +@@ -5788,12 +5782,41 @@ unlock: + return err; + } + ++static void l2cap_put_ident(struct l2cap_conn *conn, u8 code, u8 id) ++{ ++ int ret; ++ ++ switch (code) { ++ case L2CAP_COMMAND_REJ: ++ case L2CAP_CONN_RSP: ++ case L2CAP_CONF_RSP: ++ case L2CAP_DISCONN_RSP: ++ case L2CAP_ECHO_RSP: ++ case L2CAP_INFO_RSP: ++ case L2CAP_CONN_PARAM_UPDATE_RSP: ++ case L2CAP_ECRED_CONN_RSP: ++ case L2CAP_ECRED_RECONF_RSP: ++ /* The remote may send bogus ids that would make ida_free ++ * generate warnings, so only free ids that are actually ++ * allocated: probing the exact id returns -ENOSPC when it ++ * is in use, otherwise the probe allocated it and freeing ++ * is safe either way. Only on -ENOMEM is the id known to ++ * be unallocated and the free must be skipped. ++ */ ++ ret = ida_alloc_range(&conn->tx_ida, id, id, GFP_ATOMIC); ++ if (ret >= 0 || ret == -ENOSPC) ++ ida_free(&conn->tx_ida, id); ++ } ++} ++ + static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn, + struct l2cap_cmd_hdr *cmd, u16 cmd_len, + u8 *data) + { + int err = 0; + ++ l2cap_put_ident(conn, cmd->code, cmd->ident); ++ + switch (cmd->code) { + case L2CAP_COMMAND_REJ: + l2cap_command_rej(conn, cmd, cmd_len, data); +@@ -6532,6 +6555,8 @@ static inline int l2cap_le_sig_cmd(struc + { + int err = 0; + ++ l2cap_put_ident(conn, cmd->code, cmd->ident); ++ + switch (cmd->code) { + case L2CAP_COMMAND_REJ: + l2cap_le_command_rej(conn, cmd, cmd_len, data); +@@ -8085,13 +8110,13 @@ static struct l2cap_conn *l2cap_conn_add + hci_dev_test_flag(hcon->hdev, HCI_FORCE_BREDR_SMP))) + conn->local_fixed_chan |= L2CAP_FC_SMP_BREDR; + +- mutex_init(&conn->ident_lock); + mutex_init(&conn->chan_lock); + + INIT_LIST_HEAD(&conn->chan_l); + INIT_LIST_HEAD(&conn->users); + + INIT_DELAYED_WORK(&conn->info_timer, l2cap_info_timeout); ++ ida_init(&conn->tx_ida); + + skb_queue_head_init(&conn->pending_rx); + INIT_WORK(&conn->pending_rx_work, process_pending_rx); diff --git a/queue-5.10/btrfs-do-not-trim-a-device-which-is-not-writeable.patch b/queue-5.10/btrfs-do-not-trim-a-device-which-is-not-writeable.patch new file mode 100644 index 0000000000..b4b097eea3 --- /dev/null +++ b/queue-5.10/btrfs-do-not-trim-a-device-which-is-not-writeable.patch @@ -0,0 +1,144 @@ +From stable+bounces-278192-greg=kroah.com@vger.kernel.org Mon Jul 20 20:38:45 2026 +From: Sasha Levin +Date: Mon, 20 Jul 2026 14:38:37 -0400 +Subject: btrfs: do not trim a device which is not writeable +To: stable@vger.kernel.org +Cc: Qu Wenruo , Su Yue , Filipe Manana , David Sterba , Sasha Levin +Message-ID: <20260720183837.3080301-1-sashal@kernel.org> + +From: Qu Wenruo + +[ Upstream commit 1b1937eb08f51319bf71575484cde2b8c517aedc ] + +[BUG] +There is a bug report that btrfs/242 can randomly fail with the +following NULL pointer dereference: + + run fstests btrfs/242 at 2026-06-01 10:25:08 + BTRFS: device fsid d4d7f234-487c-4787-88e4-47a8b68c9874 devid 1 transid 9 /dev/sdc (8:32) scanned by mount (122609) + BTRFS info (device sdc): first mount of filesystem d4d7f234-487c-4787-88e4-47a8b68c9874 + BTRFS info (device sdc): using crc32c checksum algorithm + BTRFS warning (device sdc): devid 2 uuid fbe72d72-3272-482d-80fb-ab88ed398192 is missing + BTRFS warning (device sdc): devid 2 uuid fbe72d72-3272-482d-80fb-ab88ed398192 is missing + BTRFS info (device sdc): allowing degraded mounts + BTRFS info (device sdc): turning on async discard + BTRFS info (device sdc): enabling free space tree + Unable to handle kernel NULL pointer dereference at virtual address 0000000000000018 + user pgtable: 4k pages, 48-bit VAs, pgdp=000000013fd6b000 + CPU: 4 UID: 0 PID: 122625 Comm: fstrim Not tainted 7.0.10-2-default #1 PREEMPT(full) openSUSE Tumbleweed e9a5f6b24978fba3bf015a992f865837fdfff3dd + Hardware name: QEMU KVM Virtual Machine, BIOS edk2-20250812-19.fc42 08/12/2025 + pstate: 01400005 (nzcv daif +PAN -UAO -TCO +DIT -SSBS BTYPE=--) + pc : btrfs_trim_fs+0x34c/0xa00 [btrfs] + lr : btrfs_trim_fs+0x1f0/0xa00 [btrfs] + Call trace: + btrfs_trim_fs+0x34c/0xa00 [btrfs f02c1d570ceea621c69d302ba75dd61868083840] (P) + btrfs_ioctl_fitrim+0xe8/0x178 [btrfs f02c1d570ceea621c69d302ba75dd61868083840] + btrfs_ioctl+0xdd4/0x2bd8 [btrfs f02c1d570ceea621c69d302ba75dd61868083840] + __arm64_sys_ioctl+0xac/0x108 + invoke_syscall.constprop.0+0x5c/0xd0 + el0_svc_common.constprop.0+0x40/0xf0 + do_el0_svc+0x24/0x40 + el0_svc+0x40/0x1d0 + el0t_64_sync_handler+0xa0/0xe8 + el0t_64_sync+0x1b0/0x1b8 + Code: 17ffff83 f94017e0 f9002be0 f9402ea0 (f9400c00) + ---[ end trace 0000000000000000 ]--- + +Also the reporter is very kind to test the following ASSERT() added to +btrfs_trim_free_extents_throttle(): + + ASSERT(device->bdev, + "devid=%llu path=%s dev_state=0x%lx\n", + device->devid, btrfs_dev_name(device), device->dev_state); + +And it shows the following output: + + assertion failed: device->bdev, in extent-tree.c:6630 (devid=2 path=/dev/sdd dev_state=0x82) + +Which means the device->bdev is NULL, and the dev_state is +BTRFS_DEV_STATE_IN_FS_METADATA | BTRFS_DEV_STATE_ITEM_FOUND, without +BTRFS_DEV_STATE_WRITEABLE flag set. + +[CAUSE] +The pc points to the following call chain: + + btrfs_trim_fs() + |- btrfs_trim_free_extents() + |- btrfs_trim_free_extents_throttle() + |- bdev_max_discard_sectors(device->bdev) + +So the NULL pointer dereference is caused by device->bdev being NULL. + +This looks impossible by a quick glance, as just before calling +btrfs_trim_free_extents_throttle(), we have skipped any device that has +BTRFS_DEV_STATE_MISSING flag set. + +However in this particular case, there is a window where the missing +device is later re-scanned, causing btrfs to remove the +BTRFS_DEV_STATE_MISSING flag: + + btrfs_control_ioctl() + |- btrfs_scan_one_device() + |- device_list_add() + |- rcu_assign_pointer(device->name, name); + | This updates the missing device's path to the new good path. + | + |- clear_bit(BTRFS_DEV_STATE_MISSING, &device->dev_state) + This removes the BTRFS_DEV_STATE_MISSING flag. + +This allows the missing device to re-appear and clear the +BTRFS_DEV_STATE_MISSING flag. However the device still does not have +the BTRFS_DEV_STATE_WRITEABLE flag set, nor is its bdev pointer updated. + +The bdev pointer remains NULL, triggering the crash later. + +[FIX] +This is a big de-synchronization between BTRFS_DEV_STATE_MISSING and +device->bdev pointer, and shows a gap in btrfs's re-appearing-device +handling. + +The proper handling of re-appearing device will need quite some extra +work, which is out of the context of this small fix. + +Thankfully the regular bbio submission path has already handled it well +by checking if the device->bdev is NULL before submitting. + +So here we just fix the crash by checking if the device is writeable and +has a bdev pointer before calling bdev_max_discard_sectors(). + +Reported-by: Su Yue +Link: https://lore.kernel.org/linux-btrfs/wlwir19t.fsf@damenly.org/ +Fixes: 499f377f49f0 ("btrfs: iterate over unused chunk space in FITRIM") +CC: stable@vger.kernel.org # 5.10+ +Reviewed-by: Filipe Manana +Signed-off-by: Qu Wenruo +Signed-off-by: David Sterba +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + fs/btrfs/extent-tree.c | 12 ++++++++---- + 1 file changed, 8 insertions(+), 4 deletions(-) + +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -5762,12 +5762,16 @@ static int btrfs_trim_free_extents(struc + + *trimmed = 0; + +- /* Discard not supported = nothing to do. */ +- if (!blk_queue_discard(bdev_get_queue(device->bdev))) ++ /* ++ * The caller only filters out MISSING devices, but a device that was ++ * missing at mount and later rescanned has MISSING cleared while bdev ++ * is still NULL and WRITEABLE is still unset. Skip those here. ++ */ ++ if (!test_bit(BTRFS_DEV_STATE_WRITEABLE, &device->dev_state) || !device->bdev) + return 0; + +- /* Not writable = nothing to do. */ +- if (!test_bit(BTRFS_DEV_STATE_WRITEABLE, &device->dev_state)) ++ /* Discard not supported = nothing to do. */ ++ if (!blk_queue_discard(bdev_get_queue(device->bdev))) + return 0; + + /* No free space = nothing to do. */ diff --git a/queue-5.10/cifs-create-a-new-shared-file-holding-smb2-pdu-definitions.patch b/queue-5.10/cifs-create-a-new-shared-file-holding-smb2-pdu-definitions.patch new file mode 100644 index 0000000000..b69e2dc3b5 --- /dev/null +++ b/queue-5.10/cifs-create-a-new-shared-file-holding-smb2-pdu-definitions.patch @@ -0,0 +1,2030 @@ +From stable+bounces-274571-greg=kroah.com@vger.kernel.org Wed Jul 15 00:04:19 2026 +From: Sasha Levin +Date: Tue, 14 Jul 2026 18:04:01 -0400 +Subject: cifs: Create a new shared file holding smb2 pdu definitions +To: stable@vger.kernel.org +Cc: Ronnie Sahlberg , Namjae Jeon , Steve French , Sasha Levin +Message-ID: <20260714220405.3333589-1-sashal@kernel.org> + +From: Ronnie Sahlberg + +[ Upstream commit 0d35e382e4e96a4fd97a1438bc1b11a91d2d85a6 ] + +This file will contain all the definitions we need for SMB2 packets +and will follow the naming convention of MS-SMB2.PDF as closely +as possible to make it easier to cross-reference beween the definitions +and the standard. + +The content of this file will mostly consist of migration of existing +definitions in the cifs/smb2.pdu.h and ksmbd/smb2pdu.h files +with some additional tweaks as the two files have diverged. + +This patch introduces the new smbfs_common/smb2pdu.h file +and migrates the SMB2 header as well as TREE_CONNECT and TREE_DISCONNECT +to the shared file. + +Signed-off-by: Ronnie Sahlberg +Reviewed-by: Namjae Jeon +Signed-off-by: Steve French +Stable-dep-of: 53b7c271f06b ("smb: client: restrict implied bcc[0] exemption to responses without data area") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + fs/cifs/cifsfs.c | 1 + fs/cifs/cifsglob.h | 3 + fs/cifs/connect.c | 4 + fs/cifs/misc.c | 2 + fs/cifs/smb2maperror.c | 16 +- + fs/cifs/smb2misc.c | 43 ++--- + fs/cifs/smb2ops.c | 61 +++---- + fs/cifs/smb2pdu.c | 106 ++++++------- + fs/cifs/smb2pdu.h | 365 ++++------------------------------------------ + fs/cifs/smb2proto.h | 2 + fs/cifs/smb2transport.c | 36 ++-- + fs/smbfs_common/smb2pdu.h | 318 ++++++++++++++++++++++++++++++++++++++++ + 12 files changed, 491 insertions(+), 466 deletions(-) + create mode 100644 fs/smbfs_common/smb2pdu.h + +--- a/fs/cifs/cifsfs.c ++++ b/fs/cifs/cifsfs.c +@@ -51,7 +51,6 @@ + #include + #include "cifs_spnego.h" + #include "fscache.h" +-#include "smb2pdu.h" + #ifdef CONFIG_CIFS_DFS_UPCALL + #include "dfs_cache.h" + #endif +--- a/fs/cifs/cifsglob.h ++++ b/fs/cifs/cifsglob.h +@@ -32,6 +32,7 @@ + #include + #include + #include ++#include "../smbfs_common/smb2pdu.h" + #include "smb2pdu.h" + #include "smb2glob.h" + +@@ -866,7 +867,7 @@ revert_current_mid(struct TCP_Server_Inf + + static inline void + revert_current_mid_from_hdr(struct TCP_Server_Info *server, +- const struct smb2_sync_hdr *shdr) ++ const struct smb2_hdr *shdr) + { + unsigned int num = le16_to_cpu(shdr->CreditCharge); + +--- a/fs/cifs/connect.c ++++ b/fs/cifs/connect.c +@@ -848,7 +848,7 @@ dequeue_mid(struct mid_q_entry *mid, boo + static unsigned int + smb2_get_credits_from_hdr(char *buffer, struct TCP_Server_Info *server) + { +- struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buffer; ++ struct smb2_hdr *shdr = (struct smb2_hdr *)buffer; + + /* + * SMB1 does not use credits. +@@ -1048,7 +1048,7 @@ cifs_handle_standard(struct TCP_Server_I + static void + smb2_add_credits_from_hdr(char *buffer, struct TCP_Server_Info *server) + { +- struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buffer; ++ struct smb2_hdr *shdr = (struct smb2_hdr *)buffer; + + /* + * SMB1 does not use credits. +--- a/fs/cifs/misc.c ++++ b/fs/cifs/misc.c +@@ -164,7 +164,7 @@ cifs_buf_get(void) + * SMB2 header is bigger than CIFS one - no problems to clean some + * more bytes for CIFS. + */ +- size_t buf_size = sizeof(struct smb2_sync_hdr); ++ size_t buf_size = sizeof(struct smb2_hdr); + + /* + * We could use negotiated size instead of max_msgsize - +--- a/fs/cifs/smb2maperror.c ++++ b/fs/cifs/smb2maperror.c +@@ -2452,14 +2452,16 @@ smb2_print_status(__le32 status) + int + map_smb2_to_linux_error(char *buf, bool log_err) + { +- struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buf; ++ struct smb2_hdr *shdr = (struct smb2_hdr *)buf; + unsigned int i; + int rc = -EIO; + __le32 smb2err = shdr->Status; + + if (smb2err == 0) { +- trace_smb3_cmd_done(shdr->TreeId, shdr->SessionId, +- le16_to_cpu(shdr->Command), le64_to_cpu(shdr->MessageId)); ++ trace_smb3_cmd_done(le32_to_cpu(shdr->Id.SyncId.TreeId), ++ le64_to_cpu(shdr->SessionId), ++ le16_to_cpu(shdr->Command), ++ le64_to_cpu(shdr->MessageId)); + return 0; + } + +@@ -2483,8 +2485,10 @@ map_smb2_to_linux_error(char *buf, bool + cifs_dbg(FYI, "Mapping SMB2 status code 0x%08x to POSIX err %d\n", + __le32_to_cpu(smb2err), rc); + +- trace_smb3_cmd_err(shdr->TreeId, shdr->SessionId, +- le16_to_cpu(shdr->Command), +- le64_to_cpu(shdr->MessageId), le32_to_cpu(smb2err), rc); ++ trace_smb3_cmd_err(le32_to_cpu(shdr->Id.SyncId.TreeId), ++ le64_to_cpu(shdr->SessionId), ++ le16_to_cpu(shdr->Command), ++ le64_to_cpu(shdr->MessageId), ++ le32_to_cpu(smb2err), rc); + return rc; + } +--- a/fs/cifs/smb2misc.c ++++ b/fs/cifs/smb2misc.c +@@ -21,7 +21,6 @@ + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + #include +-#include "smb2pdu.h" + #include "cifsglob.h" + #include "cifsproto.h" + #include "smb2proto.h" +@@ -32,7 +31,7 @@ + #include "nterr.h" + + static int +-check_smb2_hdr(struct smb2_sync_hdr *shdr, __u64 mid) ++check_smb2_hdr(struct smb2_hdr *shdr, __u64 mid) + { + __u64 wire_mid = le64_to_cpu(shdr->MessageId); + +@@ -94,9 +93,9 @@ static const __le16 smb2_rsp_struct_size + /* SMB2_OPLOCK_BREAK */ cpu_to_le16(24) + }; + +-#define SMB311_NEGPROT_BASE_SIZE (sizeof(struct smb2_sync_hdr) + sizeof(struct smb2_negotiate_rsp)) ++#define SMB311_NEGPROT_BASE_SIZE (sizeof(struct smb2_hdr) + sizeof(struct smb2_negotiate_rsp)) + +-static __u32 get_neg_ctxt_len(struct smb2_sync_hdr *hdr, __u32 len, ++static __u32 get_neg_ctxt_len(struct smb2_hdr *hdr, __u32 len, + __u32 non_ctxlen) + { + __u16 neg_count; +@@ -139,13 +138,13 @@ static __u32 get_neg_ctxt_len(struct smb + int + smb2_check_message(char *buf, unsigned int len, struct TCP_Server_Info *srvr) + { +- struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buf; +- struct smb2_sync_pdu *pdu = (struct smb2_sync_pdu *)shdr; ++ struct smb2_hdr *shdr = (struct smb2_hdr *)buf; ++ struct smb2_pdu *pdu = (struct smb2_pdu *)shdr; + __u64 mid; + __u32 clc_len; /* calculated length */ + int command; +- int pdu_size = sizeof(struct smb2_sync_pdu); +- int hdr_size = sizeof(struct smb2_sync_hdr); ++ int pdu_size = sizeof(struct smb2_pdu); ++ int hdr_size = sizeof(struct smb2_hdr); + + /* + * Add function to do table lookup of StructureSize by command +@@ -161,7 +160,7 @@ smb2_check_message(char *buf, unsigned i + spin_lock(&cifs_tcp_ses_lock); + list_for_each(tmp, &srvr->smb_ses_list) { + ses = list_entry(tmp, struct cifs_ses, smb_ses_list); +- if (ses->Suid == thdr->SessionId) ++ if (ses->Suid == le64_to_cpu(thdr->SessionId)) + break; + + ses = NULL; +@@ -303,7 +302,7 @@ static const bool has_smb2_data_area[NUM + * area and the offset to it (from the beginning of the smb are also returned. + */ + char * +-smb2_get_data_area_len(int *off, int *len, struct smb2_sync_hdr *shdr) ++smb2_get_data_area_len(int *off, int *len, struct smb2_hdr *shdr) + { + const int max_off = 4096; + const int max_len = 128 * 1024; +@@ -402,8 +401,8 @@ smb2_get_data_area_len(int *off, int *le + unsigned int + smb2_calc_size(void *buf, struct TCP_Server_Info *srvr) + { +- struct smb2_sync_pdu *pdu = (struct smb2_sync_pdu *)buf; +- struct smb2_sync_hdr *shdr = &pdu->sync_hdr; ++ struct smb2_pdu *pdu = (struct smb2_pdu *)buf; ++ struct smb2_hdr *shdr = &pdu->hdr; + int offset; /* the offset from the beginning of SMB to data area */ + int data_length; /* the length of the variable length data area */ + /* Structure Size has already been checked to make sure it is 64 */ +@@ -679,7 +678,7 @@ smb2_is_valid_oplock_break(char *buffer, + + cifs_dbg(FYI, "Checking for oplock break\n"); + +- if (rsp->sync_hdr.Command != SMB2_OPLOCK_BREAK) ++ if (rsp->hdr.Command != SMB2_OPLOCK_BREAK) + return false; + + if (rsp->StructureSize != +@@ -832,23 +831,23 @@ smb2_handle_cancelled_close(struct cifs_ + int + smb2_handle_cancelled_mid(struct mid_q_entry *mid, struct TCP_Server_Info *server) + { +- struct smb2_sync_hdr *sync_hdr = mid->resp_buf; ++ struct smb2_hdr *hdr = mid->resp_buf; + struct smb2_create_rsp *rsp = mid->resp_buf; + struct cifs_tcon *tcon; + int rc; + +- if ((mid->optype & CIFS_CP_CREATE_CLOSE_OP) || sync_hdr->Command != SMB2_CREATE || +- sync_hdr->Status != STATUS_SUCCESS) ++ if ((mid->optype & CIFS_CP_CREATE_CLOSE_OP) || hdr->Command != SMB2_CREATE || ++ hdr->Status != STATUS_SUCCESS) + return 0; + +- tcon = smb2_find_smb_tcon(server, sync_hdr->SessionId, +- sync_hdr->TreeId); ++ tcon = smb2_find_smb_tcon(server, le64_to_cpu(hdr->SessionId), ++ le32_to_cpu(hdr->Id.SyncId.TreeId)); + if (!tcon) + return -ENOENT; + + rc = __smb2_handle_cancelled_cmd(tcon, +- le16_to_cpu(sync_hdr->Command), +- le64_to_cpu(sync_hdr->MessageId), ++ le16_to_cpu(hdr->Command), ++ le64_to_cpu(hdr->MessageId), + rsp->PersistentFileId, + rsp->VolatileFileId); + if (rc) +@@ -868,10 +867,10 @@ smb311_update_preauth_hash(struct cifs_s + { + int i, rc; + struct sdesc *d; +- struct smb2_sync_hdr *hdr; ++ struct smb2_hdr *hdr; + struct TCP_Server_Info *server = cifs_ses_server(ses); + +- hdr = (struct smb2_sync_hdr *)iov[0].iov_base; ++ hdr = (struct smb2_hdr *)iov[0].iov_base; + /* neg prot are always taken */ + if (hdr->Command == SMB2_NEGOTIATE) + goto ok; +--- a/fs/cifs/smb2ops.c ++++ b/fs/cifs/smb2ops.c +@@ -268,7 +268,7 @@ static struct mid_q_entry * + __smb2_find_mid(struct TCP_Server_Info *server, char *buf, bool dequeue) + { + struct mid_q_entry *mid; +- struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buf; ++ struct smb2_hdr *shdr = (struct smb2_hdr *)buf; + __u64 wire_mid = le64_to_cpu(shdr->MessageId); + + if (shdr->ProtocolId == SMB2_TRANSFORM_PROTO_NUM) { +@@ -310,11 +310,11 @@ static void + smb2_dump_detail(void *buf, struct TCP_Server_Info *server) + { + #ifdef CONFIG_CIFS_DEBUG2 +- struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buf; ++ struct smb2_hdr *shdr = (struct smb2_hdr *)buf; + + cifs_server_dbg(VFS, "Cmd: %d Err: 0x%x Flags: 0x%x Mid: %llu Pid: %d\n", + shdr->Command, shdr->Status, shdr->Flags, shdr->MessageId, +- shdr->ProcessId); ++ shdr->Id.SyncId.ProcessId); + cifs_server_dbg(VFS, "smb buf %p len %u\n", buf, + server->ops->calc_smb_size(buf, server)); + #endif +@@ -817,7 +817,7 @@ int open_shroot(unsigned int xid, struct + oparms.fid->persistent_fid = o_rsp->PersistentFileId; + oparms.fid->volatile_fid = o_rsp->VolatileFileId; + #ifdef CONFIG_CIFS_DEBUG2 +- oparms.fid->mid = le64_to_cpu(o_rsp->sync_hdr.MessageId); ++ oparms.fid->mid = le64_to_cpu(o_rsp->hdr.MessageId); + #endif /* CIFS_DEBUG2 */ + + memcpy(tcon->crfid.fid, pfid, sizeof(struct cifs_fid)); +@@ -2318,7 +2318,7 @@ smb2_query_dir_first(const unsigned int + + /* If the open failed there is nothing to do */ + op_rsp = (struct smb2_create_rsp *)rsp_iov[0].iov_base; +- if (op_rsp == NULL || op_rsp->sync_hdr.Status != STATUS_SUCCESS) { ++ if (op_rsp == NULL || op_rsp->hdr.Status != STATUS_SUCCESS) { + cifs_dbg(FYI, "query_dir_first: open failed rc=%d\n", rc); + goto qdf_free; + } +@@ -2337,7 +2337,7 @@ smb2_query_dir_first(const unsigned int + atomic_inc(&tcon->num_remote_opens); + + qd_rsp = (struct smb2_query_directory_rsp *)rsp_iov[1].iov_base; +- if (qd_rsp->sync_hdr.Status == STATUS_NO_MORE_FILES) { ++ if (qd_rsp->hdr.Status == STATUS_NO_MORE_FILES) { + trace_smb3_query_dir_done(xid, fid->persistent_fid, + tcon->tid, tcon->ses->Suid, 0, 0); + srch_inf->endOfSearch = true; +@@ -2389,7 +2389,7 @@ smb2_close_dir(const unsigned int xid, s + static bool + smb2_is_status_pending(char *buf, struct TCP_Server_Info *server) + { +- struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buf; ++ struct smb2_hdr *shdr = (struct smb2_hdr *)buf; + + if (shdr->Status != STATUS_PENDING) + return false; +@@ -2407,13 +2407,14 @@ smb2_is_status_pending(char *buf, struct + static bool + smb2_is_session_expired(char *buf) + { +- struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buf; ++ struct smb2_hdr *shdr = (struct smb2_hdr *)buf; + + if (shdr->Status != STATUS_NETWORK_SESSION_EXPIRED && + shdr->Status != STATUS_USER_SESSION_DELETED) + return false; + +- trace_smb3_ses_expired(shdr->TreeId, shdr->SessionId, ++ trace_smb3_ses_expired(le32_to_cpu(shdr->Id.SyncId.TreeId), ++ le64_to_cpu(shdr->SessionId), + le16_to_cpu(shdr->Command), + le64_to_cpu(shdr->MessageId)); + cifs_dbg(FYI, "Session expired or deleted\n"); +@@ -2424,7 +2425,7 @@ smb2_is_session_expired(char *buf) + static bool + smb2_is_status_io_timeout(char *buf) + { +- struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buf; ++ struct smb2_hdr *shdr = (struct smb2_hdr *)buf; + + if (shdr->Status == STATUS_IO_TIMEOUT) + return true; +@@ -2448,9 +2449,9 @@ smb2_oplock_response(struct cifs_tcon *t + void + smb2_set_related(struct smb_rqst *rqst) + { +- struct smb2_sync_hdr *shdr; ++ struct smb2_hdr *shdr; + +- shdr = (struct smb2_sync_hdr *)(rqst->rq_iov[0].iov_base); ++ shdr = (struct smb2_hdr *)(rqst->rq_iov[0].iov_base); + if (shdr == NULL) { + cifs_dbg(FYI, "shdr NULL in smb2_set_related\n"); + return; +@@ -2463,13 +2464,13 @@ char smb2_padding[7] = {0, 0, 0, 0, 0, 0 + void + smb2_set_next_command(struct cifs_tcon *tcon, struct smb_rqst *rqst) + { +- struct smb2_sync_hdr *shdr; ++ struct smb2_hdr *shdr; + struct cifs_ses *ses = tcon->ses; + struct TCP_Server_Info *server = ses->server; + unsigned long len = smb_rqst_len(server, rqst); + int i, num_padding; + +- shdr = (struct smb2_sync_hdr *)(rqst->rq_iov[0].iov_base); ++ shdr = (struct smb2_hdr *)(rqst->rq_iov[0].iov_base); + if (shdr == NULL) { + cifs_dbg(FYI, "shdr NULL in smb2_set_next_command\n"); + return; +@@ -3018,7 +3019,7 @@ smb2_query_symlink(const unsigned int xi + resp_buftype, rsp_iov); + + create_rsp = rsp_iov[0].iov_base; +- if (create_rsp && create_rsp->sync_hdr.Status) ++ if (create_rsp && create_rsp->hdr.Status) + err_iov = rsp_iov[0]; + ioctl_rsp = rsp_iov[1].iov_base; + +@@ -4183,8 +4184,8 @@ static void + fill_transform_hdr(struct smb2_transform_hdr *tr_hdr, unsigned int orig_len, + struct smb_rqst *old_rq, __le16 cipher_type) + { +- struct smb2_sync_hdr *shdr = +- (struct smb2_sync_hdr *)old_rq->rq_iov[0].iov_base; ++ struct smb2_hdr *shdr = ++ (struct smb2_hdr *)old_rq->rq_iov[0].iov_base; + + memset(tr_hdr, 0, sizeof(struct smb2_transform_hdr)); + tr_hdr->ProtocolId = SMB2_TRANSFORM_PROTO_NUM; +@@ -4322,7 +4323,7 @@ crypt_message(struct TCP_Server_Info *se + unsigned int crypt_len = le32_to_cpu(tr_hdr->OriginalMessageSize); + void *creq; + +- rc = smb2_get_enc_key(server, tr_hdr->SessionId, enc, key); ++ rc = smb2_get_enc_key(server, le64_to_cpu(tr_hdr->SessionId), enc, key); + if (rc) { + cifs_server_dbg(VFS, "%s: Could not get %scryption key\n", __func__, + enc ? "en" : "de"); +@@ -4608,7 +4609,7 @@ handle_read_data(struct TCP_Server_Info + unsigned int cur_page_idx; + unsigned int pad_len; + struct cifs_readdata *rdata = mid->callback_data; +- struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buf; ++ struct smb2_hdr *shdr = (struct smb2_hdr *)buf; + struct bio_vec *bvec = NULL; + struct iov_iter iter; + struct kvec iov; +@@ -4927,7 +4928,7 @@ receive_encrypted_standard(struct TCP_Se + { + int ret, length; + char *buf = server->smallbuf; +- struct smb2_sync_hdr *shdr; ++ struct smb2_hdr *shdr; + unsigned int pdu_length = server->pdu_size; + unsigned int buf_size; + unsigned int next_cmd; +@@ -4958,7 +4959,7 @@ receive_encrypted_standard(struct TCP_Se + + next_is_large = server->large_buf; + one_more: +- shdr = (struct smb2_sync_hdr *)buf; ++ shdr = (struct smb2_hdr *)buf; + next_cmd = le32_to_cpu(shdr->NextCommand); + if (next_cmd) { + if (WARN_ON_ONCE(next_cmd > pdu_length)) +@@ -5029,7 +5030,7 @@ smb3_receive_transform(struct TCP_Server + unsigned int orig_len = le32_to_cpu(tr_hdr->OriginalMessageSize); + + if (pdu_length < sizeof(struct smb2_transform_hdr) + +- sizeof(struct smb2_sync_hdr)) { ++ sizeof(struct smb2_hdr)) { + cifs_server_dbg(VFS, "Transform message is too small (%u)\n", + pdu_length); + cifs_reconnect(server); +@@ -5062,7 +5063,7 @@ smb3_handle_read_data(struct TCP_Server_ + static int + smb2_next_header(char *buf) + { +- struct smb2_sync_hdr *hdr = (struct smb2_sync_hdr *)buf; ++ struct smb2_hdr *hdr = (struct smb2_hdr *)buf; + struct smb2_transform_hdr *t_hdr = (struct smb2_transform_hdr *)buf; + + if (hdr->ProtocolId == SMB2_TRANSFORM_PROTO_NUM) +@@ -5602,7 +5603,7 @@ struct smb_version_values smb20_values = + .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE_LOCK, + .shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK, + .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK, +- .header_size = sizeof(struct smb2_sync_hdr), ++ .header_size = sizeof(struct smb2_hdr), + .header_preamble_size = 0, + .max_header_size = MAX_SMB2_HDR_SIZE, + .read_rsp_size = sizeof(struct smb2_read_rsp), +@@ -5624,7 +5625,7 @@ struct smb_version_values smb21_values = + .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE_LOCK, + .shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK, + .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK, +- .header_size = sizeof(struct smb2_sync_hdr), ++ .header_size = sizeof(struct smb2_hdr), + .header_preamble_size = 0, + .max_header_size = MAX_SMB2_HDR_SIZE, + .read_rsp_size = sizeof(struct smb2_read_rsp), +@@ -5645,7 +5646,7 @@ struct smb_version_values smb3any_values + .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE_LOCK, + .shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK, + .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK, +- .header_size = sizeof(struct smb2_sync_hdr), ++ .header_size = sizeof(struct smb2_hdr), + .header_preamble_size = 0, + .max_header_size = MAX_SMB2_HDR_SIZE, + .read_rsp_size = sizeof(struct smb2_read_rsp), +@@ -5666,7 +5667,7 @@ struct smb_version_values smbdefault_val + .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE_LOCK, + .shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK, + .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK, +- .header_size = sizeof(struct smb2_sync_hdr), ++ .header_size = sizeof(struct smb2_hdr), + .header_preamble_size = 0, + .max_header_size = MAX_SMB2_HDR_SIZE, + .read_rsp_size = sizeof(struct smb2_read_rsp), +@@ -5687,7 +5688,7 @@ struct smb_version_values smb30_values = + .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE_LOCK, + .shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK, + .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK, +- .header_size = sizeof(struct smb2_sync_hdr), ++ .header_size = sizeof(struct smb2_hdr), + .header_preamble_size = 0, + .max_header_size = MAX_SMB2_HDR_SIZE, + .read_rsp_size = sizeof(struct smb2_read_rsp), +@@ -5708,7 +5709,7 @@ struct smb_version_values smb302_values + .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE_LOCK, + .shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK, + .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK, +- .header_size = sizeof(struct smb2_sync_hdr), ++ .header_size = sizeof(struct smb2_hdr), + .header_preamble_size = 0, + .max_header_size = MAX_SMB2_HDR_SIZE, + .read_rsp_size = sizeof(struct smb2_read_rsp), +@@ -5729,7 +5730,7 @@ struct smb_version_values smb311_values + .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE_LOCK, + .shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK, + .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK, +- .header_size = sizeof(struct smb2_sync_hdr), ++ .header_size = sizeof(struct smb2_hdr), + .header_preamble_size = 0, + .max_header_size = MAX_SMB2_HDR_SIZE, + .read_rsp_size = sizeof(struct smb2_read_rsp), +--- a/fs/cifs/smb2pdu.c ++++ b/fs/cifs/smb2pdu.c +@@ -36,7 +36,6 @@ + #include + #include + #include +-#include "smb2pdu.h" + #include "cifsglob.h" + #include "cifsacl.h" + #include "cifsproto.h" +@@ -97,7 +96,7 @@ int smb3_encryption_required(const struc + } + + static void +-smb2_hdr_assemble(struct smb2_sync_hdr *shdr, __le16 smb2_cmd, ++smb2_hdr_assemble(struct smb2_hdr *shdr, __le16 smb2_cmd, + const struct cifs_tcon *tcon, + struct TCP_Server_Info *server) + { +@@ -117,7 +116,7 @@ smb2_hdr_assemble(struct smb2_sync_hdr * + } else { + shdr->CreditRequest = cpu_to_le16(2); + } +- shdr->ProcessId = cpu_to_le32((__u16)current->tgid); ++ shdr->Id.SyncId.ProcessId = cpu_to_le32((__u16)current->tgid); + + if (!tcon) + goto out; +@@ -128,10 +127,10 @@ smb2_hdr_assemble(struct smb2_sync_hdr * + shdr->CreditCharge = cpu_to_le16(1); + /* else CreditCharge MBZ */ + +- shdr->TreeId = tcon->tid; ++ shdr->Id.SyncId.TreeId = cpu_to_le32(tcon->tid); + /* Uid is not converted */ + if (tcon->ses) +- shdr->SessionId = tcon->ses->Suid; ++ shdr->SessionId = cpu_to_le64(tcon->ses->Suid); + + /* + * If we would set SMB2_FLAGS_DFS_OPERATIONS on open we also would have +@@ -347,7 +346,7 @@ fill_small_buf(__le16 smb2_command, stru + void *buf, + unsigned int *total_len) + { +- struct smb2_sync_pdu *spdu = (struct smb2_sync_pdu *)buf; ++ struct smb2_pdu *spdu = (struct smb2_pdu *)buf; + /* lookup word count ie StructureSize from table */ + __u16 parmsize = smb2_req_struct_sizes[le16_to_cpu(smb2_command)]; + +@@ -357,10 +356,10 @@ fill_small_buf(__le16 smb2_command, stru + */ + memset(buf, 0, 256); + +- smb2_hdr_assemble(&spdu->sync_hdr, smb2_command, tcon, server); ++ smb2_hdr_assemble(&spdu->hdr, smb2_command, tcon, server); + spdu->StructureSize2 = cpu_to_le16(parmsize); + +- *total_len = parmsize + sizeof(struct smb2_sync_hdr); ++ *total_len = parmsize + sizeof(struct smb2_hdr); + } + + /* +@@ -388,7 +387,7 @@ static int __smb2_plain_req_init(__le16 + } + + fill_small_buf(smb2_command, tcon, server, +- (struct smb2_sync_hdr *)(*request_buf), ++ (struct smb2_hdr *)(*request_buf), + total_len); + + if (tcon != NULL) { +@@ -813,7 +812,7 @@ SMB2_negotiate(const unsigned int xid, s + if (rc) + return rc; + +- req->sync_hdr.SessionId = 0; ++ req->hdr.SessionId = 0; + + memset(server->preauth_sha_hash, 0, SMB2_PREAUTH_HASH_SIZE); + memset(ses->preauth_sha_hash, 0, SMB2_PREAUTH_HASH_SIZE); +@@ -969,7 +968,7 @@ SMB2_negotiate(const unsigned int xid, s + server->cipher_type = SMB2_ENCRYPTION_AES128_CCM; + + security_blob = smb2_get_data_area_len(&blob_offset, &blob_length, +- (struct smb2_sync_hdr *)rsp); ++ (struct smb2_hdr *)rsp); + /* + * See MS-SMB2 section 2.2.4: if no blob, client picks default which + * for us will be +@@ -1206,13 +1205,13 @@ SMB2_sess_alloc_buffer(struct SMB2_sess_ + return rc; + + if (sess_data->ses->binding) { +- req->sync_hdr.SessionId = sess_data->ses->Suid; +- req->sync_hdr.Flags |= SMB2_FLAGS_SIGNED; ++ req->hdr.SessionId = cpu_to_le64(sess_data->ses->Suid); ++ req->hdr.Flags |= SMB2_FLAGS_SIGNED; + req->PreviousSessionId = 0; + req->Flags = SMB2_SESSION_REQ_FLAG_BINDING; + } else { + /* First session, not a reauthenticate */ +- req->sync_hdr.SessionId = 0; ++ req->hdr.SessionId = 0; + /* + * if reconnect, we need to send previous sess id + * otherwise it is 0 +@@ -1222,7 +1221,7 @@ SMB2_sess_alloc_buffer(struct SMB2_sess_ + } + + /* enough to enable echos and oplocks and one max size write */ +- req->sync_hdr.CreditRequest = cpu_to_le16(130); ++ req->hdr.CreditRequest = cpu_to_le16(130); + + /* only one of SMB2 signing flags may be set in SMB2 request */ + if (server->sign) +@@ -1381,7 +1380,7 @@ SMB2_auth_kerberos(struct SMB2_sess_data + rsp = (struct smb2_sess_setup_rsp *)sess_data->iov[0].iov_base; + /* keep session id and flags if binding */ + if (!ses->binding) { +- ses->Suid = rsp->sync_hdr.SessionId; ++ ses->Suid = le64_to_cpu(rsp->hdr.SessionId); + ses->session_flags = le16_to_cpu(rsp->SessionFlags); + } + +@@ -1457,7 +1456,7 @@ SMB2_sess_auth_rawntlmssp_negotiate(stru + + /* If true, rc here is expected and not an error */ + if (sess_data->buf0_type != CIFS_NO_BUFFER && +- rsp->sync_hdr.Status == STATUS_MORE_PROCESSING_REQUIRED) ++ rsp->hdr.Status == STATUS_MORE_PROCESSING_REQUIRED) + rc = 0; + + if (rc) +@@ -1479,7 +1478,7 @@ SMB2_sess_auth_rawntlmssp_negotiate(stru + + /* keep existing ses id and flags if binding */ + if (!ses->binding) { +- ses->Suid = rsp->sync_hdr.SessionId; ++ ses->Suid = le64_to_cpu(rsp->hdr.SessionId); + ses->session_flags = le16_to_cpu(rsp->SessionFlags); + } + +@@ -1514,7 +1513,7 @@ SMB2_sess_auth_rawntlmssp_authenticate(s + goto out; + + req = (struct smb2_sess_setup_req *) sess_data->iov[0].iov_base; +- req->sync_hdr.SessionId = ses->Suid; ++ req->hdr.SessionId = cpu_to_le64(ses->Suid); + + rc = build_ntlmssp_auth_blob(&ntlmssp_blob, &blob_length, ses, + sess_data->nls_cp); +@@ -1540,7 +1539,7 @@ SMB2_sess_auth_rawntlmssp_authenticate(s + + /* keep existing ses id and flags if binding */ + if (!ses->binding) { +- ses->Suid = rsp->sync_hdr.SessionId; ++ ses->Suid = le64_to_cpu(rsp->hdr.SessionId); + ses->session_flags = le16_to_cpu(rsp->SessionFlags); + } + +@@ -1671,12 +1670,12 @@ SMB2_logoff(const unsigned int xid, stru + return rc; + + /* since no tcon, smb2_init can not do this, so do here */ +- req->sync_hdr.SessionId = ses->Suid; ++ req->hdr.SessionId = cpu_to_le64(ses->Suid); + + if (ses->session_flags & SMB2_SESSION_FLAG_ENCRYPT_DATA) + flags |= CIFS_TRANSFORM_REQ; + else if (server->sign) +- req->sync_hdr.Flags |= SMB2_FLAGS_SIGNED; ++ req->hdr.Flags |= SMB2_FLAGS_SIGNED; + + flags |= CIFS_NO_RSP_BUF; + +@@ -1783,14 +1782,14 @@ SMB2_tcon(const unsigned int xid, struct + !(ses->session_flags & + (SMB2_SESSION_FLAG_IS_GUEST|SMB2_SESSION_FLAG_IS_NULL)) && + ((ses->user_name != NULL) || (ses->sectype == Kerberos))) +- req->sync_hdr.Flags |= SMB2_FLAGS_SIGNED; ++ req->hdr.Flags |= SMB2_FLAGS_SIGNED; + + memset(&rqst, 0, sizeof(struct smb_rqst)); + rqst.rq_iov = iov; + rqst.rq_nvec = 2; + + /* Need 64 for max size write so ask for more in case not there yet */ +- req->sync_hdr.CreditRequest = cpu_to_le16(64); ++ req->hdr.CreditRequest = cpu_to_le16(64); + + rc = cifs_send_recv(xid, ses, server, + &rqst, &resp_buftype, flags, &rsp_iov); +@@ -1828,7 +1827,7 @@ SMB2_tcon(const unsigned int xid, struct + tcon->maximal_access = le32_to_cpu(rsp->MaximalAccess); + tcon->tidStatus = CifsGood; + tcon->need_reconnect = false; +- tcon->tid = rsp->sync_hdr.TreeId; ++ tcon->tid = le32_to_cpu(rsp->hdr.Id.SyncId.TreeId); + strlcpy(tcon->treeName, tree, sizeof(tcon->treeName)); + + if ((rsp->Capabilities & SMB2_SHARE_CAP_DFS) && +@@ -1849,9 +1848,8 @@ tcon_exit: + return rc; + + tcon_error_exit: +- if (rsp && rsp->sync_hdr.Status == STATUS_BAD_NETWORK_NAME) { ++ if (rsp && rsp->hdr.Status == STATUS_BAD_NETWORK_NAME) + cifs_tcon_dbg(VFS, "BAD_NETWORK_NAME: %s\n", tree); +- } + goto tcon_exit; + } + +@@ -2585,7 +2583,7 @@ int smb311_posix_mkdir(const unsigned in + if (tcon->share_flags & SHI1005_FLAGS_DFS) { + int name_len; + +- req->sync_hdr.Flags |= SMB2_FLAGS_DFS_OPERATIONS; ++ req->hdr.Flags |= SMB2_FLAGS_DFS_OPERATIONS; + rc = alloc_path_with_tree_prefix(©_path, ©_size, + &name_len, + tcon->treeName, utf16_path); +@@ -2717,7 +2715,7 @@ SMB2_open_init(struct cifs_tcon *tcon, s + if (tcon->share_flags & SHI1005_FLAGS_DFS) { + int name_len; + +- req->sync_hdr.Flags |= SMB2_FLAGS_DFS_OPERATIONS; ++ req->hdr.Flags |= SMB2_FLAGS_DFS_OPERATIONS; + rc = alloc_path_with_tree_prefix(©_path, ©_size, + &name_len, + tcon->treeName, path); +@@ -2929,7 +2927,7 @@ SMB2_open(const unsigned int xid, struct + oparms->fid->volatile_fid = rsp->VolatileFileId; + oparms->fid->access = oparms->desired_access; + #ifdef CONFIG_CIFS_DEBUG2 +- oparms->fid->mid = le64_to_cpu(rsp->sync_hdr.MessageId); ++ oparms->fid->mid = le64_to_cpu(rsp->hdr.MessageId); + #endif /* CIFS_DEBUG2 */ + + if (buf) { +@@ -3035,7 +3033,7 @@ SMB2_ioctl_init(struct cifs_tcon *tcon, + * response size smaller. + */ + req->MaxOutputResponse = cpu_to_le32(max_response_size); +- req->sync_hdr.CreditCharge = ++ req->hdr.CreditCharge = + cpu_to_le16(DIV_ROUND_UP(max(indatalen, max_response_size), + SMB2_MAX_BUFFER_SIZE)); + /* always an FSCTL (for now) */ +@@ -3043,7 +3041,7 @@ SMB2_ioctl_init(struct cifs_tcon *tcon, + + /* validate negotiate request must be signed - see MS-SMB2 3.2.5.5 */ + if (opcode == FSCTL_VALIDATE_NEGOTIATE_INFO) +- req->sync_hdr.Flags |= SMB2_FLAGS_SIGNED; ++ req->hdr.Flags |= SMB2_FLAGS_SIGNED; + + return 0; + } +@@ -3668,7 +3666,7 @@ smb2_echo_callback(struct mid_q_entry *m + + if (mid->mid_state == MID_RESPONSE_RECEIVED + || mid->mid_state == MID_RESPONSE_MALFORMED) { +- credits.value = le16_to_cpu(rsp->sync_hdr.CreditRequest); ++ credits.value = le16_to_cpu(rsp->hdr.CreditRequest); + credits.instance = server->reconnect_instance; + } + +@@ -3768,7 +3766,7 @@ SMB2_echo(struct TCP_Server_Info *server + if (rc) + return rc; + +- req->sync_hdr.CreditRequest = cpu_to_le16(1); ++ req->hdr.CreditRequest = cpu_to_le16(1); + + iov[0].iov_len = total_len; + iov[0].iov_base = (char *)req; +@@ -3872,7 +3870,7 @@ smb2_new_read_req(void **buf, unsigned i + { + int rc = -EACCES; + struct smb2_read_plain_req *req = NULL; +- struct smb2_sync_hdr *shdr; ++ struct smb2_hdr *shdr; + struct TCP_Server_Info *server = io_parms->server; + + rc = smb2_plain_req_init(SMB2_READ, io_parms->tcon, server, +@@ -3883,8 +3881,8 @@ smb2_new_read_req(void **buf, unsigned i + if (server == NULL) + return -ECONNABORTED; + +- shdr = &req->sync_hdr; +- shdr->ProcessId = cpu_to_le32(io_parms->pid); ++ shdr = &req->hdr; ++ shdr->Id.SyncId.ProcessId = cpu_to_le32(io_parms->pid); + + req->PersistentFileId = io_parms->persistent_fid; + req->VolatileFileId = io_parms->volatile_fid; +@@ -3945,8 +3943,8 @@ smb2_new_read_req(void **buf, unsigned i + * Related requests use info from previous read request + * in chain. + */ +- shdr->SessionId = 0xFFFFFFFFFFFFFFFF; +- shdr->TreeId = 0xFFFFFFFF; ++ shdr->SessionId = cpu_to_le64(0xFFFFFFFFFFFFFFFF); ++ shdr->Id.SyncId.TreeId = cpu_to_le32(0xFFFFFFFF); + req->PersistentFileId = 0xFFFFFFFFFFFFFFFF; + req->VolatileFileId = 0xFFFFFFFFFFFFFFFF; + } +@@ -3966,8 +3964,8 @@ smb2_readv_callback(struct mid_q_entry * + struct cifs_readdata *rdata = mid->callback_data; + struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink); + struct TCP_Server_Info *server = rdata->server; +- struct smb2_sync_hdr *shdr = +- (struct smb2_sync_hdr *)rdata->iov[0].iov_base; ++ struct smb2_hdr *shdr = ++ (struct smb2_hdr *)rdata->iov[0].iov_base; + struct cifs_credits credits = { .value = 0, .instance = 0 }; + struct smb_rqst rqst = { .rq_iov = &rdata->iov[1], + .rq_nvec = 1, }; +@@ -4056,7 +4054,7 @@ smb2_async_readv(struct cifs_readdata *r + { + int rc, flags = 0; + char *buf; +- struct smb2_sync_hdr *shdr; ++ struct smb2_hdr *shdr; + struct cifs_io_parms io_parms; + struct smb_rqst rqst = { .rq_iov = rdata->iov, + .rq_nvec = 1 }; +@@ -4089,7 +4087,7 @@ smb2_async_readv(struct cifs_readdata *r + rdata->iov[0].iov_base = buf; + rdata->iov[0].iov_len = total_len; + +- shdr = (struct smb2_sync_hdr *)buf; ++ shdr = (struct smb2_hdr *)buf; + + if (rdata->credits.value > 0) { + shdr->CreditCharge = cpu_to_le16(DIV_ROUND_UP(rdata->bytes, +@@ -4222,7 +4220,7 @@ smb2_writev_callback(struct mid_q_entry + + switch (mid->mid_state) { + case MID_RESPONSE_RECEIVED: +- credits.value = le16_to_cpu(rsp->sync_hdr.CreditRequest); ++ credits.value = le16_to_cpu(rsp->hdr.CreditRequest); + credits.instance = server->reconnect_instance; + wdata->result = smb2_check_receive(mid, server, 0); + if (wdata->result != 0) +@@ -4248,7 +4246,7 @@ smb2_writev_callback(struct mid_q_entry + wdata->result = -EAGAIN; + break; + case MID_RESPONSE_MALFORMED: +- credits.value = le16_to_cpu(rsp->sync_hdr.CreditRequest); ++ credits.value = le16_to_cpu(rsp->hdr.CreditRequest); + credits.instance = server->reconnect_instance; + fallthrough; + default: +@@ -4295,7 +4293,7 @@ smb2_async_writev(struct cifs_writedata + { + int rc = -EACCES, flags = 0; + struct smb2_write_req *req = NULL; +- struct smb2_sync_hdr *shdr; ++ struct smb2_hdr *shdr; + struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink); + struct TCP_Server_Info *server = wdata->server; + struct kvec iov[1]; +@@ -4313,8 +4311,8 @@ smb2_async_writev(struct cifs_writedata + if (smb3_encryption_required(tcon)) + flags |= CIFS_TRANSFORM_REQ; + +- shdr = (struct smb2_sync_hdr *)req; +- shdr->ProcessId = cpu_to_le32(wdata->cfile->pid); ++ shdr = (struct smb2_hdr *)req; ++ shdr->Id.SyncId.ProcessId = cpu_to_le32(wdata->cfile->pid); + + req->PersistentFileId = wdata->cfile->fid.persistent_fid; + req->VolatileFileId = wdata->cfile->fid.volatile_fid; +@@ -4465,7 +4463,7 @@ SMB2_write(const unsigned int xid, struc + if (smb3_encryption_required(io_parms->tcon)) + flags |= CIFS_TRANSFORM_REQ; + +- req->sync_hdr.ProcessId = cpu_to_le32(io_parms->pid); ++ req->hdr.Id.SyncId.ProcessId = cpu_to_le32(io_parms->pid); + + req->PersistentFileId = io_parms->persistent_fid; + req->VolatileFileId = io_parms->volatile_fid; +@@ -4852,7 +4850,7 @@ SMB2_query_directory(const unsigned int + + if (rc) { + if (rc == -ENODATA && +- rsp->sync_hdr.Status == STATUS_NO_MORE_FILES) { ++ rsp->hdr.Status == STATUS_NO_MORE_FILES) { + trace_smb3_query_dir_done(xid, persistent_fid, + tcon->tid, tcon->ses->Suid, index, 0); + srch_inf->endOfSearch = true; +@@ -4900,7 +4898,7 @@ SMB2_set_info_init(struct cifs_tcon *tco + if (rc) + return rc; + +- req->sync_hdr.ProcessId = cpu_to_le32(pid); ++ req->hdr.Id.SyncId.ProcessId = cpu_to_le32(pid); + req->InfoType = info_type; + req->FileInfoClass = info_class; + req->PersistentFileId = persistent_fid; +@@ -5060,7 +5058,7 @@ SMB2_oplock_break(const unsigned int xid + req->VolatileFid = volatile_fid; + req->PersistentFid = persistent_fid; + req->OplockLevel = oplock_level; +- req->sync_hdr.CreditRequest = cpu_to_le16(1); ++ req->hdr.CreditRequest = cpu_to_le16(1); + + flags |= CIFS_NO_RSP_BUF; + +@@ -5367,7 +5365,7 @@ smb2_lockv(const unsigned int xid, struc + if (smb3_encryption_required(tcon)) + flags |= CIFS_TRANSFORM_REQ; + +- req->sync_hdr.ProcessId = cpu_to_le32(pid); ++ req->hdr.Id.SyncId.ProcessId = cpu_to_le32(pid); + req->LockCount = cpu_to_le16(num_lock); + + req->PersistentFileId = persist_fid; +@@ -5443,7 +5441,7 @@ SMB2_lease_break(const unsigned int xid, + if (smb3_encryption_required(tcon)) + flags |= CIFS_TRANSFORM_REQ; + +- req->sync_hdr.CreditRequest = cpu_to_le16(1); ++ req->hdr.CreditRequest = cpu_to_le16(1); + req->StructureSize = cpu_to_le16(36); + total_len += 12; + +--- a/fs/cifs/smb2pdu.h ++++ b/fs/cifs/smb2pdu.h +@@ -27,149 +27,12 @@ + #include + #include + +-/* +- * Note that, due to trying to use names similar to the protocol specifications, +- * there are many mixed case field names in the structures below. Although +- * this does not match typical Linux kernel style, it is necessary to be +- * able to match against the protocol specfication. +- * +- * SMB2 commands +- * Some commands have minimal (wct=0,bcc=0), or uninteresting, responses +- * (ie no useful data other than the SMB error code itself) and are marked such. +- * Knowing this helps avoid response buffer allocations and copy in some cases. +- */ +- +-/* List of commands in host endian */ +-#define SMB2_NEGOTIATE_HE 0x0000 +-#define SMB2_SESSION_SETUP_HE 0x0001 +-#define SMB2_LOGOFF_HE 0x0002 /* trivial request/resp */ +-#define SMB2_TREE_CONNECT_HE 0x0003 +-#define SMB2_TREE_DISCONNECT_HE 0x0004 /* trivial req/resp */ +-#define SMB2_CREATE_HE 0x0005 +-#define SMB2_CLOSE_HE 0x0006 +-#define SMB2_FLUSH_HE 0x0007 /* trivial resp */ +-#define SMB2_READ_HE 0x0008 +-#define SMB2_WRITE_HE 0x0009 +-#define SMB2_LOCK_HE 0x000A +-#define SMB2_IOCTL_HE 0x000B +-#define SMB2_CANCEL_HE 0x000C +-#define SMB2_ECHO_HE 0x000D +-#define SMB2_QUERY_DIRECTORY_HE 0x000E +-#define SMB2_CHANGE_NOTIFY_HE 0x000F +-#define SMB2_QUERY_INFO_HE 0x0010 +-#define SMB2_SET_INFO_HE 0x0011 +-#define SMB2_OPLOCK_BREAK_HE 0x0012 +- +-/* The same list in little endian */ +-#define SMB2_NEGOTIATE cpu_to_le16(SMB2_NEGOTIATE_HE) +-#define SMB2_SESSION_SETUP cpu_to_le16(SMB2_SESSION_SETUP_HE) +-#define SMB2_LOGOFF cpu_to_le16(SMB2_LOGOFF_HE) +-#define SMB2_TREE_CONNECT cpu_to_le16(SMB2_TREE_CONNECT_HE) +-#define SMB2_TREE_DISCONNECT cpu_to_le16(SMB2_TREE_DISCONNECT_HE) +-#define SMB2_CREATE cpu_to_le16(SMB2_CREATE_HE) +-#define SMB2_CLOSE cpu_to_le16(SMB2_CLOSE_HE) +-#define SMB2_FLUSH cpu_to_le16(SMB2_FLUSH_HE) +-#define SMB2_READ cpu_to_le16(SMB2_READ_HE) +-#define SMB2_WRITE cpu_to_le16(SMB2_WRITE_HE) +-#define SMB2_LOCK cpu_to_le16(SMB2_LOCK_HE) +-#define SMB2_IOCTL cpu_to_le16(SMB2_IOCTL_HE) +-#define SMB2_CANCEL cpu_to_le16(SMB2_CANCEL_HE) +-#define SMB2_ECHO cpu_to_le16(SMB2_ECHO_HE) +-#define SMB2_QUERY_DIRECTORY cpu_to_le16(SMB2_QUERY_DIRECTORY_HE) +-#define SMB2_CHANGE_NOTIFY cpu_to_le16(SMB2_CHANGE_NOTIFY_HE) +-#define SMB2_QUERY_INFO cpu_to_le16(SMB2_QUERY_INFO_HE) +-#define SMB2_SET_INFO cpu_to_le16(SMB2_SET_INFO_HE) +-#define SMB2_OPLOCK_BREAK cpu_to_le16(SMB2_OPLOCK_BREAK_HE) +- +-#define SMB2_INTERNAL_CMD cpu_to_le16(0xFFFF) +- +-#define NUMBER_OF_SMB2_COMMANDS 0x0013 +- + /* 52 transform hdr + 64 hdr + 88 create rsp */ + #define SMB2_TRANSFORM_HEADER_SIZE 52 + #define MAX_SMB2_HDR_SIZE 204 + +-#define SMB2_PROTO_NUMBER cpu_to_le32(0x424d53fe) +-#define SMB2_TRANSFORM_PROTO_NUM cpu_to_le32(0x424d53fd) +-#define SMB2_COMPRESSION_TRANSFORM_ID cpu_to_le32(0x424d53fc) +- +-/* +- * SMB2 Header Definition +- * +- * "MBZ" : Must be Zero +- * "BB" : BugBug, Something to check/review/analyze later +- * "PDU" : "Protocol Data Unit" (ie a network "frame") +- * +- */ +- +-#define SMB2_HEADER_STRUCTURE_SIZE cpu_to_le16(64) +- +-struct smb2_sync_hdr { +- __le32 ProtocolId; /* 0xFE 'S' 'M' 'B' */ +- __le16 StructureSize; /* 64 */ +- __le16 CreditCharge; /* MBZ */ +- __le32 Status; /* Error from server */ +- __le16 Command; +- __le16 CreditRequest; /* CreditResponse */ +- __le32 Flags; +- __le32 NextCommand; +- __le64 MessageId; +- __le32 ProcessId; +- __u32 TreeId; /* opaque - so do not make little endian */ +- __u64 SessionId; /* opaque - so do not make little endian */ +- __u8 Signature[16]; +-} __packed; +- + /* The total header size for SMB2 read and write */ +-#define SMB2_READWRITE_PDU_HEADER_SIZE (48 + sizeof(struct smb2_sync_hdr)) +- +-struct smb2_sync_pdu { +- struct smb2_sync_hdr sync_hdr; +- __le16 StructureSize2; /* size of wct area (varies, request specific) */ +-} __packed; +- +-#define SMB3_AES_CCM_NONCE 11 +-#define SMB3_AES_GCM_NONCE 12 +- +-/* Transform flags (for 3.0 dialect this flag indicates CCM */ +-#define TRANSFORM_FLAG_ENCRYPTED 0x0001 +-struct smb2_transform_hdr { +- __le32 ProtocolId; /* 0xFD 'S' 'M' 'B' */ +- __u8 Signature[16]; +- __u8 Nonce[16]; +- __le32 OriginalMessageSize; +- __u16 Reserved1; +- __le16 Flags; /* EncryptionAlgorithm for 3.0, enc enabled for 3.1.1 */ +- __u64 SessionId; +-} __packed; +- +-/* See MS-SMB2 2.2.42 */ +-struct smb2_compression_transform_hdr { +- __le32 ProtocolId; /* 0xFC 'S' 'M' 'B' */ +- __le32 OriginalCompressedSegmentSize; +- __le16 CompressionAlgorithm; +- __le16 Flags; +- __le16 Length; /* if chained it is length, else offset */ +-} __packed; +- +-/* See MS-SMB2 2.2.42.1 */ +-#define SMB2_COMPRESSION_FLAG_NONE 0x0000 +-#define SMB2_COMPRESSION_FLAG_CHAINED 0x0001 +- +-struct compression_payload_header { +- __le16 CompressionAlgorithm; +- __le16 Flags; +- __le32 Length; /* length of compressed playload including field below if present */ +- /* __le32 OriginalPayloadSize; */ /* optional */ +-} __packed; +- +-/* See MS-SMB2 2.2.42.2 */ +-struct compression_pattern_payload_v1 { +- __le16 Pattern; +- __le16 Reserved1; +- __le16 Reserved2; +- __le32 Repetitions; +-} __packed; ++#define SMB2_READWRITE_PDU_HEADER_SIZE (48 + sizeof(struct smb2_hdr)) + + /* See MS-SMB2 2.2.43 */ + struct smb2_rdma_transform { +@@ -192,17 +55,6 @@ struct smb2_rdma_encryption_transform { + } __packed; + + /* +- * SMB2 flag definitions +- */ +-#define SMB2_FLAGS_SERVER_TO_REDIR cpu_to_le32(0x00000001) +-#define SMB2_FLAGS_ASYNC_COMMAND cpu_to_le32(0x00000002) +-#define SMB2_FLAGS_RELATED_OPERATIONS cpu_to_le32(0x00000004) +-#define SMB2_FLAGS_SIGNED cpu_to_le32(0x00000008) +-#define SMB2_FLAGS_PRIORITY_MASK cpu_to_le32(0x00000070) /* SMB3.1.1 */ +-#define SMB2_FLAGS_DFS_OPERATIONS cpu_to_le32(0x10000000) +-#define SMB2_FLAGS_REPLAY_OPERATION cpu_to_le32(0x20000000) /* SMB3 & up */ +- +-/* + * Definitions for SMB2 Protocol Data Units (network frames) + * + * See MS-SMB2.PDF specification for protocol details. +@@ -216,7 +68,7 @@ struct smb2_rdma_encryption_transform { + #define SMB2_ERROR_STRUCTURE_SIZE2 cpu_to_le16(9) + + struct smb2_err_rsp { +- struct smb2_sync_hdr sync_hdr; ++ struct smb2_hdr hdr; + __le16 StructureSize; + __le16 Reserved; /* MBZ */ + __le32 ByteCount; /* even if zero, at least one byte follows */ +@@ -275,7 +127,7 @@ struct share_redirect_error_context_rsp + #define SMB2_CLIENT_GUID_SIZE 16 + + struct smb2_negotiate_req { +- struct smb2_sync_hdr sync_hdr; ++ struct smb2_hdr hdr; + __le16 StructureSize; /* Must be 36 */ + __le16 DialectCount; + __le16 SecurityMode; +@@ -449,7 +301,7 @@ struct smb2_posix_neg_context { + } __packed; + + struct smb2_negotiate_rsp { +- struct smb2_sync_hdr sync_hdr; ++ struct smb2_hdr hdr; + __le16 StructureSize; /* Must be 65 */ + __le16 SecurityMode; + __le16 DialectRevision; +@@ -472,7 +324,7 @@ struct smb2_negotiate_rsp { + #define SMB2_SESSION_REQ_FLAG_ENCRYPT_DATA 0x04 + + struct smb2_sess_setup_req { +- struct smb2_sync_hdr sync_hdr; ++ struct smb2_hdr hdr; + __le16 StructureSize; /* Must be 25 */ + __u8 Flags; + __u8 SecurityMode; +@@ -489,7 +341,7 @@ struct smb2_sess_setup_req { + #define SMB2_SESSION_FLAG_IS_NULL 0x0002 + #define SMB2_SESSION_FLAG_ENCRYPT_DATA 0x0004 + struct smb2_sess_setup_rsp { +- struct smb2_sync_hdr sync_hdr; ++ struct smb2_hdr hdr; + __le16 StructureSize; /* Must be 9 */ + __le16 SessionFlags; + __le16 SecurityBufferOffset; +@@ -498,160 +350,13 @@ struct smb2_sess_setup_rsp { + } __packed; + + struct smb2_logoff_req { +- struct smb2_sync_hdr sync_hdr; ++ struct smb2_hdr hdr; + __le16 StructureSize; /* Must be 4 */ + __le16 Reserved; + } __packed; + + struct smb2_logoff_rsp { +- struct smb2_sync_hdr sync_hdr; +- __le16 StructureSize; /* Must be 4 */ +- __le16 Reserved; +-} __packed; +- +-/* Flags/Reserved for SMB3.1.1 */ +-#define SMB2_TREE_CONNECT_FLAG_CLUSTER_RECONNECT cpu_to_le16(0x0001) +-#define SMB2_TREE_CONNECT_FLAG_REDIRECT_TO_OWNER cpu_to_le16(0x0002) +-#define SMB2_TREE_CONNECT_FLAG_EXTENSION_PRESENT cpu_to_le16(0x0004) +- +-struct smb2_tree_connect_req { +- struct smb2_sync_hdr sync_hdr; +- __le16 StructureSize; /* Must be 9 */ +- __le16 Flags; /* Reserved MBZ for dialects prior to SMB3.1.1 */ +- __le16 PathOffset; +- __le16 PathLength; +- __u8 Buffer[]; /* variable length */ +-} __packed; +- +-/* See MS-SMB2 section 2.2.9.2 */ +-/* Context Types */ +-#define SMB2_RESERVED_TREE_CONNECT_CONTEXT_ID 0x0000 +-#define SMB2_REMOTED_IDENTITY_TREE_CONNECT_CONTEXT_ID cpu_to_le16(0x0001) +- +-struct tree_connect_contexts { +- __le16 ContextType; +- __le16 DataLength; +- __le32 Reserved; +- __u8 Data[]; +-} __packed; +- +-/* Remoted identity tree connect context structures - see MS-SMB2 2.2.9.2.1 */ +-struct smb3_blob_data { +- __le16 BlobSize; +- __u8 BlobData[]; +-} __packed; +- +-/* Valid values for Attr */ +-#define SE_GROUP_MANDATORY 0x00000001 +-#define SE_GROUP_ENABLED_BY_DEFAULT 0x00000002 +-#define SE_GROUP_ENABLED 0x00000004 +-#define SE_GROUP_OWNER 0x00000008 +-#define SE_GROUP_USE_FOR_DENY_ONLY 0x00000010 +-#define SE_GROUP_INTEGRITY 0x00000020 +-#define SE_GROUP_INTEGRITY_ENABLED 0x00000040 +-#define SE_GROUP_RESOURCE 0x20000000 +-#define SE_GROUP_LOGON_ID 0xC0000000 +- +-/* struct sid_attr_data is SidData array in BlobData format then le32 Attr */ +- +-struct sid_array_data { +- __le16 SidAttrCount; +- /* SidAttrList - array of sid_attr_data structs */ +-} __packed; +- +-struct luid_attr_data { +- +-} __packed; +- +-/* +- * struct privilege_data is the same as BLOB_DATA - see MS-SMB2 2.2.9.2.1.5 +- * but with size of LUID_ATTR_DATA struct and BlobData set to LUID_ATTR DATA +- */ +- +-struct privilege_array_data { +- __le16 PrivilegeCount; +- /* array of privilege_data structs */ +-} __packed; +- +-struct remoted_identity_tcon_context { +- __le16 TicketType; /* must be 0x0001 */ +- __le16 TicketSize; /* total size of this struct */ +- __le16 User; /* offset to SID_ATTR_DATA struct with user info */ +- __le16 UserName; /* offset to null terminated Unicode username string */ +- __le16 Domain; /* offset to null terminated Unicode domain name */ +- __le16 Groups; /* offset to SID_ARRAY_DATA struct with group info */ +- __le16 RestrictedGroups; /* similar to above */ +- __le16 Privileges; /* offset to PRIVILEGE_ARRAY_DATA struct */ +- __le16 PrimaryGroup; /* offset to SID_ARRAY_DATA struct */ +- __le16 Owner; /* offset to BLOB_DATA struct */ +- __le16 DefaultDacl; /* offset to BLOB_DATA struct */ +- __le16 DeviceGroups; /* offset to SID_ARRAY_DATA struct */ +- __le16 UserClaims; /* offset to BLOB_DATA struct */ +- __le16 DeviceClaims; /* offset to BLOB_DATA struct */ +- __u8 TicketInfo[]; /* variable length buf - remoted identity data */ +-} __packed; +- +-struct smb2_tree_connect_req_extension { +- __le32 TreeConnectContextOffset; +- __le16 TreeConnectContextCount; +- __u8 Reserved[10]; +- __u8 PathName[]; /* variable sized array */ +- /* followed by array of TreeConnectContexts */ +-} __packed; +- +-struct smb2_tree_connect_rsp { +- struct smb2_sync_hdr sync_hdr; +- __le16 StructureSize; /* Must be 16 */ +- __u8 ShareType; /* see below */ +- __u8 Reserved; +- __le32 ShareFlags; /* see below */ +- __le32 Capabilities; /* see below */ +- __le32 MaximalAccess; +-} __packed; +- +-/* Possible ShareType values */ +-#define SMB2_SHARE_TYPE_DISK 0x01 +-#define SMB2_SHARE_TYPE_PIPE 0x02 +-#define SMB2_SHARE_TYPE_PRINT 0x03 +- +-/* +- * Possible ShareFlags - exactly one and only one of the first 4 caching flags +- * must be set (any of the remaining, SHI1005, flags may be set individually +- * or in combination. +- */ +-#define SMB2_SHAREFLAG_MANUAL_CACHING 0x00000000 +-#define SMB2_SHAREFLAG_AUTO_CACHING 0x00000010 +-#define SMB2_SHAREFLAG_VDO_CACHING 0x00000020 +-#define SMB2_SHAREFLAG_NO_CACHING 0x00000030 +-#define SHI1005_FLAGS_DFS 0x00000001 +-#define SHI1005_FLAGS_DFS_ROOT 0x00000002 +-#define SHI1005_FLAGS_RESTRICT_EXCLUSIVE_OPENS 0x00000100 +-#define SHI1005_FLAGS_FORCE_SHARED_DELETE 0x00000200 +-#define SHI1005_FLAGS_ALLOW_NAMESPACE_CACHING 0x00000400 +-#define SHI1005_FLAGS_ACCESS_BASED_DIRECTORY_ENUM 0x00000800 +-#define SHI1005_FLAGS_FORCE_LEVELII_OPLOCK 0x00001000 +-#define SHI1005_FLAGS_ENABLE_HASH_V1 0x00002000 +-#define SHI1005_FLAGS_ENABLE_HASH_V2 0x00004000 +-#define SHI1005_FLAGS_ENCRYPT_DATA 0x00008000 +-#define SMB2_SHAREFLAG_IDENTITY_REMOTING 0x00040000 /* 3.1.1 */ +-#define SHI1005_FLAGS_ALL 0x0004FF33 +- +-/* Possible share capabilities */ +-#define SMB2_SHARE_CAP_DFS cpu_to_le32(0x00000008) /* all dialects */ +-#define SMB2_SHARE_CAP_CONTINUOUS_AVAILABILITY cpu_to_le32(0x00000010) /* 3.0 */ +-#define SMB2_SHARE_CAP_SCALEOUT cpu_to_le32(0x00000020) /* 3.0 */ +-#define SMB2_SHARE_CAP_CLUSTER cpu_to_le32(0x00000040) /* 3.0 */ +-#define SMB2_SHARE_CAP_ASYMMETRIC cpu_to_le32(0x00000080) /* 3.02 */ +-#define SMB2_SHARE_CAP_REDIRECT_TO_OWNER cpu_to_le32(0x00000100) /* 3.1.1 */ +- +-struct smb2_tree_disconnect_req { +- struct smb2_sync_hdr sync_hdr; +- __le16 StructureSize; /* Must be 4 */ +- __le16 Reserved; +-} __packed; +- +-struct smb2_tree_disconnect_rsp { +- struct smb2_sync_hdr sync_hdr; ++ struct smb2_hdr hdr; + __le16 StructureSize; /* Must be 4 */ + __le16 Reserved; + } __packed; +@@ -784,7 +489,7 @@ struct smb2_tree_disconnect_rsp { + #define SMB2_CREATE_IOV_SIZE 8 + + struct smb2_create_req { +- struct smb2_sync_hdr sync_hdr; ++ struct smb2_hdr hdr; + __le16 StructureSize; /* Must be 57 */ + __u8 SecurityFlags; + __u8 RequestedOplockLevel; +@@ -811,7 +516,7 @@ struct smb2_create_req { + #define MAX_SMB2_CREATE_RESPONSE_SIZE 880 + + struct smb2_create_rsp { +- struct smb2_sync_hdr sync_hdr; ++ struct smb2_hdr hdr; + __le16 StructureSize; /* Must be 89 */ + __u8 OplockLevel; + __u8 Flag; /* 0x01 if reparse point */ +@@ -1186,7 +891,7 @@ struct duplicate_extents_to_file { + #define SMB2_IOCTL_IOV_SIZE 2 + + struct smb2_ioctl_req { +- struct smb2_sync_hdr sync_hdr; ++ struct smb2_hdr hdr; + __le16 StructureSize; /* Must be 57 */ + __u16 Reserved; + __le32 CtlCode; +@@ -1204,7 +909,7 @@ struct smb2_ioctl_req { + } __packed; + + struct smb2_ioctl_rsp { +- struct smb2_sync_hdr sync_hdr; ++ struct smb2_hdr hdr; + __le16 StructureSize; /* Must be 57 */ + __u16 Reserved; + __le32 CtlCode; +@@ -1222,7 +927,7 @@ struct smb2_ioctl_rsp { + /* Currently defined values for close flags */ + #define SMB2_CLOSE_FLAG_POSTQUERY_ATTRIB cpu_to_le16(0x0001) + struct smb2_close_req { +- struct smb2_sync_hdr sync_hdr; ++ struct smb2_hdr hdr; + __le16 StructureSize; /* Must be 24 */ + __le16 Flags; + __le32 Reserved; +@@ -1236,7 +941,7 @@ struct smb2_close_req { + #define MAX_SMB2_CLOSE_RESPONSE_SIZE 124 + + struct smb2_close_rsp { +- struct smb2_sync_hdr sync_hdr; ++ struct smb2_hdr hdr; + __le16 StructureSize; /* 60 */ + __le16 Flags; + __le32 Reserved; +@@ -1250,7 +955,7 @@ struct smb2_close_rsp { + } __packed; + + struct smb2_flush_req { +- struct smb2_sync_hdr sync_hdr; ++ struct smb2_hdr hdr; + __le16 StructureSize; /* Must be 24 */ + __le16 Reserved1; + __le32 Reserved2; +@@ -1259,7 +964,7 @@ struct smb2_flush_req { + } __packed; + + struct smb2_flush_rsp { +- struct smb2_sync_hdr sync_hdr; ++ struct smb2_hdr hdr; + __le16 StructureSize; + __le16 Reserved; + } __packed; +@@ -1276,7 +981,7 @@ struct smb2_flush_rsp { + + /* SMB2 read request without RFC1001 length at the beginning */ + struct smb2_read_plain_req { +- struct smb2_sync_hdr sync_hdr; ++ struct smb2_hdr hdr; + __le16 StructureSize; /* Must be 49 */ + __u8 Padding; /* offset from start of SMB2 header to place read */ + __u8 Flags; /* MBZ unless SMB3.02 or later */ +@@ -1297,7 +1002,7 @@ struct smb2_read_plain_req { + #define SMB2_READFLAG_RESPONSE_RDMA_TRANSFORM 0x00000001 + + struct smb2_read_rsp { +- struct smb2_sync_hdr sync_hdr; ++ struct smb2_hdr hdr; + __le16 StructureSize; /* Must be 17 */ + __u8 DataOffset; + __u8 Reserved; +@@ -1312,7 +1017,7 @@ struct smb2_read_rsp { + #define SMB2_WRITEFLAG_WRITE_UNBUFFERED 0x00000002 /* SMB3.02 or later */ + + struct smb2_write_req { +- struct smb2_sync_hdr sync_hdr; ++ struct smb2_hdr hdr; + __le16 StructureSize; /* Must be 49 */ + __le16 DataOffset; /* offset from start of SMB2 header to write data */ + __le32 Length; +@@ -1328,7 +1033,7 @@ struct smb2_write_req { + } __packed; + + struct smb2_write_rsp { +- struct smb2_sync_hdr sync_hdr; ++ struct smb2_hdr hdr; + __le16 StructureSize; /* Must be 17 */ + __u8 DataOffset; + __u8 Reserved; +@@ -1356,7 +1061,7 @@ struct smb2_write_rsp { + #define FILE_NOTIFY_CHANGE_STREAM_WRITE 0x00000800 + + struct smb2_change_notify_req { +- struct smb2_sync_hdr sync_hdr; ++ struct smb2_hdr hdr; + __le16 StructureSize; + __le16 Flags; + __le32 OutputBufferLength; +@@ -1367,7 +1072,7 @@ struct smb2_change_notify_req { + } __packed; + + struct smb2_change_notify_rsp { +- struct smb2_sync_hdr sync_hdr; ++ struct smb2_hdr hdr; + __le16 StructureSize; /* Must be 9 */ + __le16 OutputBufferOffset; + __le32 OutputBufferLength; +@@ -1387,7 +1092,7 @@ struct smb2_lock_element { + } __packed; + + struct smb2_lock_req { +- struct smb2_sync_hdr sync_hdr; ++ struct smb2_hdr hdr; + __le16 StructureSize; /* Must be 48 */ + __le16 LockCount; + __le32 Reserved; +@@ -1401,19 +1106,19 @@ struct smb2_lock_req { + } __packed; + + struct smb2_lock_rsp { +- struct smb2_sync_hdr sync_hdr; ++ struct smb2_hdr hdr; + __le16 StructureSize; /* Must be 4 */ + __le16 Reserved; + } __packed; + + struct smb2_echo_req { +- struct smb2_sync_hdr sync_hdr; ++ struct smb2_hdr hdr; + __le16 StructureSize; /* Must be 4 */ + __u16 Reserved; + } __packed; + + struct smb2_echo_rsp { +- struct smb2_sync_hdr sync_hdr; ++ struct smb2_hdr hdr; + __le16 StructureSize; /* Must be 4 */ + __u16 Reserved; + } __packed; +@@ -1427,7 +1132,7 @@ struct smb2_echo_rsp { + #define SMB2_QUERY_DIRECTORY_IOV_SIZE 2 + + struct smb2_query_directory_req { +- struct smb2_sync_hdr sync_hdr; ++ struct smb2_hdr hdr; + __le16 StructureSize; /* Must be 33 */ + __u8 FileInformationClass; + __u8 Flags; +@@ -1441,7 +1146,7 @@ struct smb2_query_directory_req { + } __packed; + + struct smb2_query_directory_rsp { +- struct smb2_sync_hdr sync_hdr; ++ struct smb2_hdr hdr; + __le16 StructureSize; /* Must be 9 */ + __le16 OutputBufferOffset; + __le32 OutputBufferLength; +@@ -1474,7 +1179,7 @@ struct smb2_query_directory_rsp { + #define SL_INDEX_SPECIFIED 0x00000004 + + struct smb2_query_info_req { +- struct smb2_sync_hdr sync_hdr; ++ struct smb2_hdr hdr; + __le16 StructureSize; /* Must be 41 */ + __u8 InfoType; + __u8 FileInfoClass; +@@ -1490,7 +1195,7 @@ struct smb2_query_info_req { + } __packed; + + struct smb2_query_info_rsp { +- struct smb2_sync_hdr sync_hdr; ++ struct smb2_hdr hdr; + __le16 StructureSize; /* Must be 9 */ + __le16 OutputBufferOffset; + __le32 OutputBufferLength; +@@ -1507,7 +1212,7 @@ struct smb2_query_info_rsp { + #define SMB2_SET_INFO_IOV_SIZE 3 + + struct smb2_set_info_req { +- struct smb2_sync_hdr sync_hdr; ++ struct smb2_hdr hdr; + __le16 StructureSize; /* Must be 33 */ + __u8 InfoType; + __u8 FileInfoClass; +@@ -1521,12 +1226,12 @@ struct smb2_set_info_req { + } __packed; + + struct smb2_set_info_rsp { +- struct smb2_sync_hdr sync_hdr; ++ struct smb2_hdr hdr; + __le16 StructureSize; /* Must be 2 */ + } __packed; + + struct smb2_oplock_break { +- struct smb2_sync_hdr sync_hdr; ++ struct smb2_hdr hdr; + __le16 StructureSize; /* Must be 24 */ + __u8 OplockLevel; + __u8 Reserved; +@@ -1538,7 +1243,7 @@ struct smb2_oplock_break { + #define SMB2_NOTIFY_BREAK_LEASE_FLAG_ACK_REQUIRED cpu_to_le32(0x01) + + struct smb2_lease_break { +- struct smb2_sync_hdr sync_hdr; ++ struct smb2_hdr hdr; + __le16 StructureSize; /* Must be 44 */ + __le16 Epoch; + __le32 Flags; +@@ -1551,7 +1256,7 @@ struct smb2_lease_break { + } __packed; + + struct smb2_lease_ack { +- struct smb2_sync_hdr sync_hdr; ++ struct smb2_hdr hdr; + __le16 StructureSize; /* Must be 36 */ + __le16 Reserved; + __le32 Flags; +--- a/fs/cifs/smb2proto.h ++++ b/fs/cifs/smb2proto.h +@@ -38,7 +38,7 @@ extern int smb2_check_message(char *buf, + struct TCP_Server_Info *server); + extern unsigned int smb2_calc_size(void *buf, struct TCP_Server_Info *server); + extern char *smb2_get_data_area_len(int *off, int *len, +- struct smb2_sync_hdr *shdr); ++ struct smb2_hdr *shdr); + extern __le16 *cifs_convert_path_to_utf16(const char *from, + struct cifs_sb_info *cifs_sb); + +--- a/fs/cifs/smb2transport.c ++++ b/fs/cifs/smb2transport.c +@@ -33,7 +33,6 @@ + #include + #include + #include +-#include "smb2pdu.h" + #include "cifsglob.h" + #include "cifsproto.h" + #include "smb2proto.h" +@@ -227,14 +226,14 @@ smb2_calc_signature(struct smb_rqst *rqs + unsigned char smb2_signature[SMB2_HMACSHA256_SIZE]; + unsigned char *sigptr = smb2_signature; + struct kvec *iov = rqst->rq_iov; +- struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)iov[0].iov_base; ++ struct smb2_hdr *shdr = (struct smb2_hdr *)iov[0].iov_base; + struct cifs_ses *ses; + struct shash_desc *shash; + struct crypto_shash *hash; + struct sdesc *sdesc = NULL; + struct smb_rqst drqst; + +- ses = smb2_find_smb_ses(server, shdr->SessionId); ++ ses = smb2_find_smb_ses(server, le64_to_cpu(shdr->SessionId)); + if (!ses) { + cifs_server_dbg(VFS, "%s: Could not find session\n", __func__); + return 0; +@@ -563,14 +562,14 @@ smb3_calc_signature(struct smb_rqst *rqs + unsigned char smb3_signature[SMB2_CMACAES_SIZE]; + unsigned char *sigptr = smb3_signature; + struct kvec *iov = rqst->rq_iov; +- struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)iov[0].iov_base; ++ struct smb2_hdr *shdr = (struct smb2_hdr *)iov[0].iov_base; + struct shash_desc *shash; + struct crypto_shash *hash; + struct sdesc *sdesc = NULL; + struct smb_rqst drqst; + u8 key[SMB3_SIGN_KEY_SIZE]; + +- rc = smb2_get_sign_key(shdr->SessionId, server, key); ++ rc = smb2_get_sign_key(le64_to_cpu(shdr->SessionId), server, key); + if (rc) + return 0; + +@@ -640,12 +639,12 @@ static int + smb2_sign_rqst(struct smb_rqst *rqst, struct TCP_Server_Info *server) + { + int rc = 0; +- struct smb2_sync_hdr *shdr; ++ struct smb2_hdr *shdr; + struct smb2_sess_setup_req *ssr; + bool is_binding; + bool is_signed; + +- shdr = (struct smb2_sync_hdr *)rqst->rq_iov[0].iov_base; ++ shdr = (struct smb2_hdr *)rqst->rq_iov[0].iov_base; + ssr = (struct smb2_sess_setup_req *)shdr; + + is_binding = shdr->Command == SMB2_SESSION_SETUP && +@@ -671,8 +670,8 @@ smb2_verify_signature(struct smb_rqst *r + { + unsigned int rc; + char server_response_sig[SMB2_SIGNATURE_SIZE]; +- struct smb2_sync_hdr *shdr = +- (struct smb2_sync_hdr *)rqst->rq_iov[0].iov_base; ++ struct smb2_hdr *shdr = ++ (struct smb2_hdr *)rqst->rq_iov[0].iov_base; + + if ((shdr->Command == SMB2_NEGOTIATE) || + (shdr->Command == SMB2_SESSION_SETUP) || +@@ -719,7 +718,7 @@ smb2_verify_signature(struct smb_rqst *r + */ + static inline void + smb2_seq_num_into_buf(struct TCP_Server_Info *server, +- struct smb2_sync_hdr *shdr) ++ struct smb2_hdr *shdr) + { + unsigned int i, num = le16_to_cpu(shdr->CreditCharge); + +@@ -730,7 +729,7 @@ smb2_seq_num_into_buf(struct TCP_Server_ + } + + static struct mid_q_entry * +-smb2_mid_entry_alloc(const struct smb2_sync_hdr *shdr, ++smb2_mid_entry_alloc(const struct smb2_hdr *shdr, + struct TCP_Server_Info *server) + { + struct mid_q_entry *temp; +@@ -762,14 +761,15 @@ smb2_mid_entry_alloc(const struct smb2_s + + atomic_inc(&midCount); + temp->mid_state = MID_REQUEST_ALLOCATED; +- trace_smb3_cmd_enter(shdr->TreeId, shdr->SessionId, +- le16_to_cpu(shdr->Command), temp->mid); ++ trace_smb3_cmd_enter(le32_to_cpu(shdr->Id.SyncId.TreeId), ++ le64_to_cpu(shdr->SessionId), ++ le16_to_cpu(shdr->Command), temp->mid); + return temp; + } + + static int + smb2_get_mid_entry(struct cifs_ses *ses, struct TCP_Server_Info *server, +- struct smb2_sync_hdr *shdr, struct mid_q_entry **mid) ++ struct smb2_hdr *shdr, struct mid_q_entry **mid) + { + if (server->tcpStatus == CifsExiting) + return -ENOENT; +@@ -837,8 +837,8 @@ smb2_setup_request(struct cifs_ses *ses, + struct smb_rqst *rqst) + { + int rc; +- struct smb2_sync_hdr *shdr = +- (struct smb2_sync_hdr *)rqst->rq_iov[0].iov_base; ++ struct smb2_hdr *shdr = ++ (struct smb2_hdr *)rqst->rq_iov[0].iov_base; + struct mid_q_entry *mid; + + smb2_seq_num_into_buf(server, shdr); +@@ -863,8 +863,8 @@ struct mid_q_entry * + smb2_setup_async_request(struct TCP_Server_Info *server, struct smb_rqst *rqst) + { + int rc; +- struct smb2_sync_hdr *shdr = +- (struct smb2_sync_hdr *)rqst->rq_iov[0].iov_base; ++ struct smb2_hdr *shdr = ++ (struct smb2_hdr *)rqst->rq_iov[0].iov_base; + struct mid_q_entry *mid; + + if (server->tcpStatus == CifsNeedNegotiate && +--- /dev/null ++++ b/fs/smbfs_common/smb2pdu.h +@@ -0,0 +1,318 @@ ++/* SPDX-License-Identifier: LGPL-2.1 */ ++#ifndef _COMMON_SMB2PDU_H ++#define _COMMON_SMB2PDU_H ++ ++/* ++ * Note that, due to trying to use names similar to the protocol specifications, ++ * there are many mixed case field names in the structures below. Although ++ * this does not match typical Linux kernel style, it is necessary to be ++ * able to match against the protocol specfication. ++ * ++ * SMB2 commands ++ * Some commands have minimal (wct=0,bcc=0), or uninteresting, responses ++ * (ie no useful data other than the SMB error code itself) and are marked such. ++ * Knowing this helps avoid response buffer allocations and copy in some cases. ++ */ ++ ++/* List of commands in host endian */ ++#define SMB2_NEGOTIATE_HE 0x0000 ++#define SMB2_SESSION_SETUP_HE 0x0001 ++#define SMB2_LOGOFF_HE 0x0002 /* trivial request/resp */ ++#define SMB2_TREE_CONNECT_HE 0x0003 ++#define SMB2_TREE_DISCONNECT_HE 0x0004 /* trivial req/resp */ ++#define SMB2_CREATE_HE 0x0005 ++#define SMB2_CLOSE_HE 0x0006 ++#define SMB2_FLUSH_HE 0x0007 /* trivial resp */ ++#define SMB2_READ_HE 0x0008 ++#define SMB2_WRITE_HE 0x0009 ++#define SMB2_LOCK_HE 0x000A ++#define SMB2_IOCTL_HE 0x000B ++#define SMB2_CANCEL_HE 0x000C ++#define SMB2_ECHO_HE 0x000D ++#define SMB2_QUERY_DIRECTORY_HE 0x000E ++#define SMB2_CHANGE_NOTIFY_HE 0x000F ++#define SMB2_QUERY_INFO_HE 0x0010 ++#define SMB2_SET_INFO_HE 0x0011 ++#define SMB2_OPLOCK_BREAK_HE 0x0012 ++ ++/* The same list in little endian */ ++#define SMB2_NEGOTIATE cpu_to_le16(SMB2_NEGOTIATE_HE) ++#define SMB2_SESSION_SETUP cpu_to_le16(SMB2_SESSION_SETUP_HE) ++#define SMB2_LOGOFF cpu_to_le16(SMB2_LOGOFF_HE) ++#define SMB2_TREE_CONNECT cpu_to_le16(SMB2_TREE_CONNECT_HE) ++#define SMB2_TREE_DISCONNECT cpu_to_le16(SMB2_TREE_DISCONNECT_HE) ++#define SMB2_CREATE cpu_to_le16(SMB2_CREATE_HE) ++#define SMB2_CLOSE cpu_to_le16(SMB2_CLOSE_HE) ++#define SMB2_FLUSH cpu_to_le16(SMB2_FLUSH_HE) ++#define SMB2_READ cpu_to_le16(SMB2_READ_HE) ++#define SMB2_WRITE cpu_to_le16(SMB2_WRITE_HE) ++#define SMB2_LOCK cpu_to_le16(SMB2_LOCK_HE) ++#define SMB2_IOCTL cpu_to_le16(SMB2_IOCTL_HE) ++#define SMB2_CANCEL cpu_to_le16(SMB2_CANCEL_HE) ++#define SMB2_ECHO cpu_to_le16(SMB2_ECHO_HE) ++#define SMB2_QUERY_DIRECTORY cpu_to_le16(SMB2_QUERY_DIRECTORY_HE) ++#define SMB2_CHANGE_NOTIFY cpu_to_le16(SMB2_CHANGE_NOTIFY_HE) ++#define SMB2_QUERY_INFO cpu_to_le16(SMB2_QUERY_INFO_HE) ++#define SMB2_SET_INFO cpu_to_le16(SMB2_SET_INFO_HE) ++#define SMB2_OPLOCK_BREAK cpu_to_le16(SMB2_OPLOCK_BREAK_HE) ++ ++#define SMB2_INTERNAL_CMD cpu_to_le16(0xFFFF) ++ ++#define NUMBER_OF_SMB2_COMMANDS 0x0013 ++ ++/* ++ * SMB2 Header Definition ++ * ++ * "MBZ" : Must be Zero ++ * "BB" : BugBug, Something to check/review/analyze later ++ * "PDU" : "Protocol Data Unit" (ie a network "frame") ++ * ++ */ ++ ++#define __SMB2_HEADER_STRUCTURE_SIZE 64 ++#define SMB2_HEADER_STRUCTURE_SIZE \ ++ cpu_to_le16(__SMB2_HEADER_STRUCTURE_SIZE) ++ ++#define SMB2_PROTO_NUMBER cpu_to_le32(0x424d53fe) ++#define SMB2_TRANSFORM_PROTO_NUM cpu_to_le32(0x424d53fd) ++#define SMB2_COMPRESSION_TRANSFORM_ID cpu_to_le32(0x424d53fc) ++ ++/* ++ * SMB2 flag definitions ++ */ ++#define SMB2_FLAGS_SERVER_TO_REDIR cpu_to_le32(0x00000001) ++#define SMB2_FLAGS_ASYNC_COMMAND cpu_to_le32(0x00000002) ++#define SMB2_FLAGS_RELATED_OPERATIONS cpu_to_le32(0x00000004) ++#define SMB2_FLAGS_SIGNED cpu_to_le32(0x00000008) ++#define SMB2_FLAGS_PRIORITY_MASK cpu_to_le32(0x00000070) /* SMB3.1.1 */ ++#define SMB2_FLAGS_DFS_OPERATIONS cpu_to_le32(0x10000000) ++#define SMB2_FLAGS_REPLAY_OPERATION cpu_to_le32(0x20000000) /* SMB3 & up */ ++ ++/* See MS-SMB2 section 2.2.1 */ ++struct smb2_hdr { ++ __le32 ProtocolId; /* 0xFE 'S' 'M' 'B' */ ++ __le16 StructureSize; /* 64 */ ++ __le16 CreditCharge; /* MBZ */ ++ __le32 Status; /* Error from server */ ++ __le16 Command; ++ __le16 CreditRequest; /* CreditResponse */ ++ __le32 Flags; ++ __le32 NextCommand; ++ __le64 MessageId; ++ union { ++ struct { ++ __le32 ProcessId; ++ __le32 TreeId; ++ } __packed SyncId; ++ __le64 AsyncId; ++ } __packed Id; ++ __le64 SessionId; ++ __u8 Signature[16]; ++} __packed; ++ ++struct smb2_pdu { ++ struct smb2_hdr hdr; ++ __le16 StructureSize2; /* size of wct area (varies, request specific) */ ++} __packed; ++ ++#define SMB3_AES_CCM_NONCE 11 ++#define SMB3_AES_GCM_NONCE 12 ++ ++/* Transform flags (for 3.0 dialect this flag indicates CCM */ ++#define TRANSFORM_FLAG_ENCRYPTED 0x0001 ++struct smb2_transform_hdr { ++ __le32 ProtocolId; /* 0xFD 'S' 'M' 'B' */ ++ __u8 Signature[16]; ++ __u8 Nonce[16]; ++ __le32 OriginalMessageSize; ++ __u16 Reserved1; ++ __le16 Flags; /* EncryptionAlgorithm for 3.0, enc enabled for 3.1.1 */ ++ __le64 SessionId; ++} __packed; ++ ++ ++/* See MS-SMB2 2.2.42 */ ++struct smb2_compression_transform_hdr_unchained { ++ __le32 ProtocolId; /* 0xFC 'S' 'M' 'B' */ ++ __le32 OriginalCompressedSegmentSize; ++ __le16 CompressionAlgorithm; ++ __le16 Flags; ++ __le16 Length; /* if chained it is length, else offset */ ++} __packed; ++ ++/* See MS-SMB2 2.2.42.1 */ ++#define SMB2_COMPRESSION_FLAG_NONE 0x0000 ++#define SMB2_COMPRESSION_FLAG_CHAINED 0x0001 ++ ++struct compression_payload_header { ++ __le16 CompressionAlgorithm; ++ __le16 Flags; ++ __le32 Length; /* length of compressed playload including field below if present */ ++ /* __le32 OriginalPayloadSize; */ /* optional, present when LZNT1, LZ77, LZ77+Huffman */ ++} __packed; ++ ++/* See MS-SMB2 2.2.42.2 */ ++struct smb2_compression_transform_hdr_chained { ++ __le32 ProtocolId; /* 0xFC 'S' 'M' 'B' */ ++ __le32 OriginalCompressedSegmentSize; ++ /* struct compression_payload_header[] */ ++} __packed; ++ ++/* See MS-SMB2 2.2.42.2.2 */ ++struct compression_pattern_payload_v1 { ++ __le16 Pattern; ++ __le16 Reserved1; ++ __le16 Reserved2; ++ __le32 Repetitions; ++} __packed; ++ ++/* See MS-SMB2 section 2.2.9.2 */ ++/* Context Types */ ++#define SMB2_RESERVED_TREE_CONNECT_CONTEXT_ID 0x0000 ++#define SMB2_REMOTED_IDENTITY_TREE_CONNECT_CONTEXT_ID cpu_to_le16(0x0001) ++ ++struct tree_connect_contexts { ++ __le16 ContextType; ++ __le16 DataLength; ++ __le32 Reserved; ++ __u8 Data[]; ++} __packed; ++ ++/* Remoted identity tree connect context structures - see MS-SMB2 2.2.9.2.1 */ ++struct smb3_blob_data { ++ __le16 BlobSize; ++ __u8 BlobData[]; ++} __packed; ++ ++/* Valid values for Attr */ ++#define SE_GROUP_MANDATORY 0x00000001 ++#define SE_GROUP_ENABLED_BY_DEFAULT 0x00000002 ++#define SE_GROUP_ENABLED 0x00000004 ++#define SE_GROUP_OWNER 0x00000008 ++#define SE_GROUP_USE_FOR_DENY_ONLY 0x00000010 ++#define SE_GROUP_INTEGRITY 0x00000020 ++#define SE_GROUP_INTEGRITY_ENABLED 0x00000040 ++#define SE_GROUP_RESOURCE 0x20000000 ++#define SE_GROUP_LOGON_ID 0xC0000000 ++ ++/* struct sid_attr_data is SidData array in BlobData format then le32 Attr */ ++ ++struct sid_array_data { ++ __le16 SidAttrCount; ++ /* SidAttrList - array of sid_attr_data structs */ ++} __packed; ++ ++struct luid_attr_data { ++ ++} __packed; ++ ++/* ++ * struct privilege_data is the same as BLOB_DATA - see MS-SMB2 2.2.9.2.1.5 ++ * but with size of LUID_ATTR_DATA struct and BlobData set to LUID_ATTR DATA ++ */ ++ ++struct privilege_array_data { ++ __le16 PrivilegeCount; ++ /* array of privilege_data structs */ ++} __packed; ++ ++struct remoted_identity_tcon_context { ++ __le16 TicketType; /* must be 0x0001 */ ++ __le16 TicketSize; /* total size of this struct */ ++ __le16 User; /* offset to SID_ATTR_DATA struct with user info */ ++ __le16 UserName; /* offset to null terminated Unicode username string */ ++ __le16 Domain; /* offset to null terminated Unicode domain name */ ++ __le16 Groups; /* offset to SID_ARRAY_DATA struct with group info */ ++ __le16 RestrictedGroups; /* similar to above */ ++ __le16 Privileges; /* offset to PRIVILEGE_ARRAY_DATA struct */ ++ __le16 PrimaryGroup; /* offset to SID_ARRAY_DATA struct */ ++ __le16 Owner; /* offset to BLOB_DATA struct */ ++ __le16 DefaultDacl; /* offset to BLOB_DATA struct */ ++ __le16 DeviceGroups; /* offset to SID_ARRAY_DATA struct */ ++ __le16 UserClaims; /* offset to BLOB_DATA struct */ ++ __le16 DeviceClaims; /* offset to BLOB_DATA struct */ ++ __u8 TicketInfo[]; /* variable length buf - remoted identity data */ ++} __packed; ++ ++struct smb2_tree_connect_req_extension { ++ __le32 TreeConnectContextOffset; ++ __le16 TreeConnectContextCount; ++ __u8 Reserved[10]; ++ __u8 PathName[]; /* variable sized array */ ++ /* followed by array of TreeConnectContexts */ ++} __packed; ++ ++/* Flags/Reserved for SMB3.1.1 */ ++#define SMB2_TREE_CONNECT_FLAG_CLUSTER_RECONNECT cpu_to_le16(0x0001) ++#define SMB2_TREE_CONNECT_FLAG_REDIRECT_TO_OWNER cpu_to_le16(0x0002) ++#define SMB2_TREE_CONNECT_FLAG_EXTENSION_PRESENT cpu_to_le16(0x0004) ++ ++struct smb2_tree_connect_req { ++ struct smb2_hdr hdr; ++ __le16 StructureSize; /* Must be 9 */ ++ __le16 Flags; /* Flags in SMB3.1.1 */ ++ __le16 PathOffset; ++ __le16 PathLength; ++ __u8 Buffer[]; /* variable length */ ++} __packed; ++ ++/* Possible ShareType values */ ++#define SMB2_SHARE_TYPE_DISK 0x01 ++#define SMB2_SHARE_TYPE_PIPE 0x02 ++#define SMB2_SHARE_TYPE_PRINT 0x03 ++ ++/* ++ * Possible ShareFlags - exactly one and only one of the first 4 caching flags ++ * must be set (any of the remaining, SHI1005, flags may be set individually ++ * or in combination. ++ */ ++#define SMB2_SHAREFLAG_MANUAL_CACHING 0x00000000 ++#define SMB2_SHAREFLAG_AUTO_CACHING 0x00000010 ++#define SMB2_SHAREFLAG_VDO_CACHING 0x00000020 ++#define SMB2_SHAREFLAG_NO_CACHING 0x00000030 ++#define SHI1005_FLAGS_DFS 0x00000001 ++#define SHI1005_FLAGS_DFS_ROOT 0x00000002 ++#define SHI1005_FLAGS_RESTRICT_EXCLUSIVE_OPENS 0x00000100 ++#define SHI1005_FLAGS_FORCE_SHARED_DELETE 0x00000200 ++#define SHI1005_FLAGS_ALLOW_NAMESPACE_CACHING 0x00000400 ++#define SHI1005_FLAGS_ACCESS_BASED_DIRECTORY_ENUM 0x00000800 ++#define SHI1005_FLAGS_FORCE_LEVELII_OPLOCK 0x00001000 ++#define SHI1005_FLAGS_ENABLE_HASH_V1 0x00002000 ++#define SHI1005_FLAGS_ENABLE_HASH_V2 0x00004000 ++#define SHI1005_FLAGS_ENCRYPT_DATA 0x00008000 ++#define SMB2_SHAREFLAG_IDENTITY_REMOTING 0x00040000 /* 3.1.1 */ ++#define SMB2_SHAREFLAG_COMPRESS_DATA 0x00100000 /* 3.1.1 */ ++#define SHI1005_FLAGS_ALL 0x0014FF33 ++ ++/* Possible share capabilities */ ++#define SMB2_SHARE_CAP_DFS cpu_to_le32(0x00000008) /* all dialects */ ++#define SMB2_SHARE_CAP_CONTINUOUS_AVAILABILITY cpu_to_le32(0x00000010) /* 3.0 */ ++#define SMB2_SHARE_CAP_SCALEOUT cpu_to_le32(0x00000020) /* 3.0 */ ++#define SMB2_SHARE_CAP_CLUSTER cpu_to_le32(0x00000040) /* 3.0 */ ++#define SMB2_SHARE_CAP_ASYMMETRIC cpu_to_le32(0x00000080) /* 3.02 */ ++#define SMB2_SHARE_CAP_REDIRECT_TO_OWNER cpu_to_le32(0x00000100) /* 3.1.1 */ ++ ++struct smb2_tree_connect_rsp { ++ struct smb2_hdr hdr; ++ __le16 StructureSize; /* Must be 16 */ ++ __u8 ShareType; /* see below */ ++ __u8 Reserved; ++ __le32 ShareFlags; /* see below */ ++ __le32 Capabilities; /* see below */ ++ __le32 MaximalAccess; ++} __packed; ++ ++struct smb2_tree_disconnect_req { ++ struct smb2_hdr hdr; ++ __le16 StructureSize; /* Must be 4 */ ++ __le16 Reserved; ++} __packed; ++ ++struct smb2_tree_disconnect_rsp { ++ struct smb2_hdr hdr; ++ __le16 StructureSize; /* Must be 4 */ ++ __le16 Reserved; ++} __packed; ++ ++ ++#endif /* _COMMON_SMB2PDU_H */ diff --git a/queue-5.10/cifs-remove-check-of-list-iterator-against-head-past-the-loop-body.patch b/queue-5.10/cifs-remove-check-of-list-iterator-against-head-past-the-loop-body.patch new file mode 100644 index 0000000000..8cc53a896c --- /dev/null +++ b/queue-5.10/cifs-remove-check-of-list-iterator-against-head-past-the-loop-body.patch @@ -0,0 +1,63 @@ +From stable+bounces-274568-greg=kroah.com@vger.kernel.org Wed Jul 15 00:04:17 2026 +From: Sasha Levin +Date: Tue, 14 Jul 2026 18:04:02 -0400 +Subject: cifs: remove check of list iterator against head past the loop body +To: stable@vger.kernel.org +Cc: Jakob Koschel , "Paulo Alcantara (SUSE)" , Steve French , Sasha Levin +Message-ID: <20260714220405.3333589-2-sashal@kernel.org> + +From: Jakob Koschel + +[ Upstream commit 00c796eecba4898194ea549679797ee28f89a92f ] + +When list_for_each_entry() completes the iteration over the whole list +without breaking the loop, the iterator value will be a bogus pointer +computed based on the head element. + +While it is safe to use the pointer to determine if it was computed +based on the head element, either with list_entry_is_head() or +&pos->member == head, using the iterator variable after the loop should +be avoided. + +In preparation to limit the scope of a list iterator to the list +traversal loop, use a dedicated pointer to point to the found element [1]. + +Link: https://lore.kernel.org/all/CAHk-=wgRr_D8CB-D9Kg-c=EHreAsk5SqXPwr9Y7k9sA6cWXJ6w@mail.gmail.com/ [1] +Reviewed-by: Paulo Alcantara (SUSE) +Signed-off-by: Jakob Koschel +Signed-off-by: Steve French +Stable-dep-of: 53b7c271f06b ("smb: client: restrict implied bcc[0] exemption to responses without data area") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + fs/cifs/smb2misc.c | 13 ++++++------- + 1 file changed, 6 insertions(+), 7 deletions(-) + +--- a/fs/cifs/smb2misc.c ++++ b/fs/cifs/smb2misc.c +@@ -154,19 +154,18 @@ smb2_check_message(char *buf, unsigned i + struct smb2_transform_hdr *thdr = + (struct smb2_transform_hdr *)buf; + struct cifs_ses *ses = NULL; +- struct list_head *tmp; ++ struct cifs_ses *iter; + + /* decrypt frame now that it is completely read in */ + spin_lock(&cifs_tcp_ses_lock); +- list_for_each(tmp, &srvr->smb_ses_list) { +- ses = list_entry(tmp, struct cifs_ses, smb_ses_list); +- if (ses->Suid == le64_to_cpu(thdr->SessionId)) ++ list_for_each_entry(iter, &srvr->smb_ses_list, smb_ses_list) { ++ if (iter->Suid == le64_to_cpu(thdr->SessionId)) { ++ ses = iter; + break; +- +- ses = NULL; ++ } + } + spin_unlock(&cifs_tcp_ses_lock); +- if (ses == NULL) { ++ if (!ses) { + cifs_dbg(VFS, "no decryption - session id not found\n"); + return 1; + } diff --git a/queue-5.10/cifs-remove-unused-server-parameter-from-calc_smb_size.patch b/queue-5.10/cifs-remove-unused-server-parameter-from-calc_smb_size.patch new file mode 100644 index 0000000000..7bd0ae5352 --- /dev/null +++ b/queue-5.10/cifs-remove-unused-server-parameter-from-calc_smb_size.patch @@ -0,0 +1,151 @@ +From stable+bounces-274570-greg=kroah.com@vger.kernel.org Wed Jul 15 00:04:16 2026 +From: Sasha Levin +Date: Tue, 14 Jul 2026 18:04:04 -0400 +Subject: cifs: remove unused server parameter from calc_smb_size() +To: stable@vger.kernel.org +Cc: Enzo Matsumiya , "Paulo Alcantara (SUSE)" , Steve French , Sasha Levin +Message-ID: <20260714220405.3333589-4-sashal@kernel.org> + +From: Enzo Matsumiya + +[ Upstream commit 68ed14496b032b0c9ef21b38ee45c6c8f3a18ff1 ] + +This parameter is unused by the called function + +Reviewed-by: Paulo Alcantara (SUSE) +Signed-off-by: Enzo Matsumiya +Signed-off-by: Steve French +Stable-dep-of: 53b7c271f06b ("smb: client: restrict implied bcc[0] exemption to responses without data area") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + fs/cifs/cifs_debug.c | 2 +- + fs/cifs/cifsglob.h | 2 +- + fs/cifs/cifsproto.h | 2 +- + fs/cifs/misc.c | 2 +- + fs/cifs/netmisc.c | 2 +- + fs/cifs/readdir.c | 6 ++---- + fs/cifs/smb2misc.c | 4 ++-- + fs/cifs/smb2ops.c | 2 +- + fs/cifs/smb2proto.h | 2 +- + 9 files changed, 11 insertions(+), 13 deletions(-) + +--- a/fs/cifs/cifs_debug.c ++++ b/fs/cifs/cifs_debug.c +@@ -41,7 +41,7 @@ void cifs_dump_detail(void *buf, struct + smb->Command, smb->Status.CifsError, + smb->Flags, smb->Flags2, smb->Mid, smb->Pid); + cifs_dbg(VFS, "smb buf %p len %u\n", smb, +- server->ops->calc_smb_size(smb, server)); ++ server->ops->calc_smb_size(smb)); + #endif /* CONFIG_CIFS_DEBUG2 */ + } + +--- a/fs/cifs/cifsglob.h ++++ b/fs/cifs/cifsglob.h +@@ -397,7 +397,7 @@ struct smb_version_operations { + int (*close_dir)(const unsigned int, struct cifs_tcon *, + struct cifs_fid *); + /* calculate a size of SMB message */ +- unsigned int (*calc_smb_size)(void *buf, struct TCP_Server_Info *ptcpi); ++ unsigned int (*calc_smb_size)(void *buf); + /* check for STATUS_PENDING and process the response if yes */ + bool (*is_status_pending)(char *buf, struct TCP_Server_Info *server); + /* check for STATUS_NETWORK_SESSION_EXPIRED */ +--- a/fs/cifs/cifsproto.h ++++ b/fs/cifs/cifsproto.h +@@ -148,7 +148,7 @@ extern int cifs_get_writable_path(struct + extern struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *, bool); + extern int cifs_get_readable_path(struct cifs_tcon *tcon, const char *name, + struct cifsFileInfo **ret_file); +-extern unsigned int smbCalcSize(void *buf, struct TCP_Server_Info *server); ++extern unsigned int smbCalcSize(void *buf); + extern int decode_negTokenInit(unsigned char *security_blob, int length, + struct TCP_Server_Info *server); + extern int cifs_convert_address(struct sockaddr *dst, const char *src, int len); +--- a/fs/cifs/misc.c ++++ b/fs/cifs/misc.c +@@ -370,7 +370,7 @@ checkSMB(char *buf, unsigned int total_r + /* otherwise, there is enough to get to the BCC */ + if (check_smb_hdr(smb)) + return -EIO; +- clc_len = smbCalcSize(smb, server); ++ clc_len = smbCalcSize(smb); + + if (4 + rfclen != total_read) { + cifs_dbg(VFS, "Length read does not match RFC1001 length %d\n", +--- a/fs/cifs/netmisc.c ++++ b/fs/cifs/netmisc.c +@@ -913,7 +913,7 @@ map_and_check_smb_error(struct mid_q_ent + * portion, the number of word parameters and the data portion of the message + */ + unsigned int +-smbCalcSize(void *buf, struct TCP_Server_Info *server) ++smbCalcSize(void *buf) + { + struct smb_hdr *ptr = (struct smb_hdr *)buf; + return (sizeof(struct smb_hdr) + (2 * ptr->WordCount) + +--- a/fs/cifs/readdir.c ++++ b/fs/cifs/readdir.c +@@ -801,8 +801,7 @@ find_cifs_entry(const unsigned int xid, + + end_of_smb = cfile->srch_inf.ntwrk_buf_start + + server->ops->calc_smb_size( +- cfile->srch_inf.ntwrk_buf_start, +- server); ++ cfile->srch_inf.ntwrk_buf_start); + + cur_ent = cfile->srch_inf.srch_entries_start; + first_entry_in_buffer = cfile->srch_inf.index_of_last_entry +@@ -1000,8 +999,7 @@ int cifs_readdir(struct file *file, stru + cifs_dbg(FYI, "loop through %d times filling dir for net buf %p\n", + num_to_fill, cifsFile->srch_inf.ntwrk_buf_start); + max_len = tcon->ses->server->ops->calc_smb_size( +- cifsFile->srch_inf.ntwrk_buf_start, +- tcon->ses->server); ++ cifsFile->srch_inf.ntwrk_buf_start); + end_of_smb = cifsFile->srch_inf.ntwrk_buf_start + max_len; + + tmp_buf = kmalloc(UNICODE_NAME_MAX, GFP_KERNEL); +--- a/fs/cifs/smb2misc.c ++++ b/fs/cifs/smb2misc.c +@@ -225,7 +225,7 @@ smb2_check_message(char *buf, unsigned i + } + } + +- calc_len = smb2_calc_size(buf, server); ++ calc_len = smb2_calc_size(buf); + + /* For SMB2_IOCTL, OutputOffset and OutputLength are optional, so might + * be 0, and not a real miscalculation */ +@@ -407,7 +407,7 @@ smb2_get_data_area_len(int *off, int *le + * portion, the number of word parameters and the data portion of the message. + */ + unsigned int +-smb2_calc_size(void *buf, struct TCP_Server_Info *srvr) ++smb2_calc_size(void *buf) + { + struct smb2_pdu *pdu = (struct smb2_pdu *)buf; + struct smb2_hdr *shdr = &pdu->hdr; +--- a/fs/cifs/smb2ops.c ++++ b/fs/cifs/smb2ops.c +@@ -316,7 +316,7 @@ smb2_dump_detail(void *buf, struct TCP_S + shdr->Command, shdr->Status, shdr->Flags, shdr->MessageId, + shdr->Id.SyncId.ProcessId); + cifs_server_dbg(VFS, "smb buf %p len %u\n", buf, +- server->ops->calc_smb_size(buf, server)); ++ server->ops->calc_smb_size(buf)); + #endif + } + +--- a/fs/cifs/smb2proto.h ++++ b/fs/cifs/smb2proto.h +@@ -36,7 +36,7 @@ struct smb_rqst; + extern int map_smb2_to_linux_error(char *buf, bool log_err); + extern int smb2_check_message(char *buf, unsigned int length, + struct TCP_Server_Info *server); +-extern unsigned int smb2_calc_size(void *buf, struct TCP_Server_Info *server); ++extern unsigned int smb2_calc_size(void *buf); + extern char *smb2_get_data_area_len(int *off, int *len, + struct smb2_hdr *shdr); + extern __le16 *cifs_convert_path_to_utf16(const char *from, diff --git a/queue-5.10/coresight-etb10-restore-atomic_t-for-shared-reading-state.patch b/queue-5.10/coresight-etb10-restore-atomic_t-for-shared-reading-state.patch new file mode 100644 index 0000000000..9a88ae2be1 --- /dev/null +++ b/queue-5.10/coresight-etb10-restore-atomic_t-for-shared-reading-state.patch @@ -0,0 +1,123 @@ +From stable+bounces-275001-greg=kroah.com@vger.kernel.org Wed Jul 15 18:54:20 2026 +From: Sasha Levin +Date: Wed, 15 Jul 2026 12:54:05 -0400 +Subject: coresight: etb10: restore atomic_t for shared reading state +To: stable@vger.kernel.org +Cc: Runyu Xiao , James Clark , Suzuki K Poulose , Sasha Levin +Message-ID: <20260715165405.963048-1-sashal@kernel.org> + +From: Runyu Xiao + +[ Upstream commit fa09f08ede3db3050ae16ae1ed92c902d0cada23 ] + +The etb10 miscdevice uses drvdata->reading as a shared exclusivity gate +for userspace buffer access. etb_open() claims that gate with +local_cmpxchg(), and etb_release() clears it with local_set(). + +That gate is shared per-device state rather than CPU-local state. A +running system can reach it whenever /dev/ is opened, closed, and +reopened by different tasks while the device remains registered, so the +same drvdata->reading variable may be claimed on one CPU and later +cleared on another. + +This code used to use atomic_t for the same gate, but commit +27b10da8fff2 ("coresight: etb10: moving to local atomic operations") +changed it to local_t even though the access pattern remained cross-task +and cross-CPU. Restore atomic_t together with atomic_cmpxchg() and +atomic_set() so the exclusivity gate again uses a primitive intended +for shared state. + +The issue was found on Linux v6.18.21 by our static analysis tool while +scanning surviving local_t-on-shared-state sites, and then manually +reviewed against the live etb10 file-op path. + +It was runtime-validated with a reproducible QEMU no-device KCSAN PoC +that kept the same report-local contract: + + 1. use one shared struct etb_drvdata carrier and its + drvdata->reading gate; + 2. call etb_open() and etb_release() sequentially on that gate to + confirm the original claim/clear path; + 3. bind the open side to CPU0 and the release side to CPU1 for the + same gate to show cross-CPU ownership; + 4. run bound workers that repeatedly race etb_open() and + etb_release() on the same gate until KCSAN reports a target hit. + +The harness recorded: + + L1 passed open=1 release=1 + reading_after_open=1 reading_after_release=0 + L2 passed open_cpu=0 release_cpu=1 + cross_cpu_release=1 reading_after=0 open_ret=0 + +Representative KCSAN excerpt from the no-device validation run: + + BUG: KCSAN: data-race in etb_open.constprop.0.isra.0 [vuln_msv] + + write to 0xffffffffc0003810 of 4 bytes by task 216 on cpu 1: + etb_open.constprop.0.isra.0+0x38/0x80 [vuln_msv] + l3_worker_thread_fn+0x4f/0xf0 [vuln_msv] + kthread+0x17e/0x1c0 + ret_from_fork+0x22/0x30 + + read to 0xffffffffc0003810 of 4 bytes by task 215 on cpu 0: + etb_open.constprop.0.isra.0+0x18/0x80 [vuln_msv] + l3_worker_thread_fn+0x4f/0xf0 [vuln_msv] + kthread+0x17e/0x1c0 + ret_from_fork+0x22/0x30 + + value changed: 0x00000000 -> 0x00000001 + + Reported by Kernel Concurrency Sanitizer on: + CPU: 0 PID: 215 Comm: etb10_l3_a Tainted: G O 6.1.66 #2 + +This no-device harness is not a real ETB10 hardware end-to-end run, but +it preserves the same shared drvdata->reading gate and the same +etb_open()/etb_release() claim/clear contract. No real ETB10 hardware +was available for runtime testing. + +Build-tested with: + make olddefconfig + make -j"$(nproc)" drivers/hwtracing/coresight/coresight-etb10.o + +Fixes: 27b10da8fff2 ("coresight: etb10: moving to local atomic operations") +Cc: stable@vger.kernel.org +Signed-off-by: Runyu Xiao +Reviewed-by: James Clark +Signed-off-by: Suzuki K Poulose +Link: https://lore.kernel.org/r/20260528165201.319452-1-runyu.xiao@seu.edu.cn +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/hwtracing/coresight/coresight-etb10.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/drivers/hwtracing/coresight/coresight-etb10.c ++++ b/drivers/hwtracing/coresight/coresight-etb10.c +@@ -86,7 +86,7 @@ struct etb_drvdata { + struct coresight_device *csdev; + struct miscdevice miscdev; + spinlock_t spinlock; +- local_t reading; ++ atomic_t reading; + pid_t pid; + u8 *buf; + u32 mode; +@@ -603,7 +603,7 @@ static int etb_open(struct inode *inode, + struct etb_drvdata *drvdata = container_of(file->private_data, + struct etb_drvdata, miscdev); + +- if (local_cmpxchg(&drvdata->reading, 0, 1)) ++ if (atomic_cmpxchg(&drvdata->reading, 0, 1)) + return -EBUSY; + + dev_dbg(&drvdata->csdev->dev, "%s: successfully opened\n", __func__); +@@ -641,7 +641,7 @@ static int etb_release(struct inode *ino + { + struct etb_drvdata *drvdata = container_of(file->private_data, + struct etb_drvdata, miscdev); +- local_set(&drvdata->reading, 0); ++ atomic_set(&drvdata->reading, 0); + + dev_dbg(&drvdata->csdev->dev, "%s: released\n", __func__); + return 0; diff --git a/queue-5.10/cpufreq-intel_pstate-sync-policy-cur-during-cpu-offline.patch b/queue-5.10/cpufreq-intel_pstate-sync-policy-cur-during-cpu-offline.patch new file mode 100644 index 0000000000..fc2b922254 --- /dev/null +++ b/queue-5.10/cpufreq-intel_pstate-sync-policy-cur-during-cpu-offline.patch @@ -0,0 +1,56 @@ +From stable+bounces-277188-greg=kroah.com@vger.kernel.org Fri Jul 17 21:23:55 2026 +From: Sasha Levin +Date: Fri, 17 Jul 2026 15:23:48 -0400 +Subject: cpufreq: intel_pstate: Sync policy->cur during CPU offline +To: stable@vger.kernel.org +Cc: Fushuai Wang , Srinivas Pandruvada , "Rafael J. Wysocki" , Sasha Levin +Message-ID: <20260717192348.2131400-1-sashal@kernel.org> + +From: Fushuai Wang + +[ Upstream commit bcbdaa1086c25a8a5d48e04e1b82fdfb0682b681 ] + +When a CPU goes offline with HWP disabled, intel_pstate_set_min_pstate() +sets the MSR_IA32_PERF_CTL to minimum frequency to prevent SMT siblings +from being restricted. However, the policy->cur value was not updated, +leaving it at the previous value. + +When the CPU comes back online, governor->limits() checks if target_freq +equals policy->cur and skips the frequency adjustment if they match. Since +policy->cur still holds the previous value, the governor does not call +cpufreq_driver->target to update MSR_IA32_PERF_CTL. + +Fix this by synchronizing policy->cur with the hardware state when setting +minimum pstate during CPU offline. + +Fixes: bb18008f8086 ("intel_pstate: Set core to min P state during core offline") +Cc: stable@vger.kernel.org # 3.15+ +Suggested-by: Srinivas Pandruvada +Signed-off-by: Fushuai Wang +[ rjw: Subject refinement ] +Link: https://patch.msgid.link/20260520032119.30615-1-fushuai.wang@linux.dev +Signed-off-by: Rafael J. Wysocki +[ replaced `cpu->pstate.min_freq` with `cpu->pstate.min_pstate * cpu->pstate.scaling` since 5.10 lacks the min_freq field ] +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/cpufreq/intel_pstate.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +--- a/drivers/cpufreq/intel_pstate.c ++++ b/drivers/cpufreq/intel_pstate.c +@@ -2355,10 +2355,12 @@ static int intel_pstate_cpu_offline(stru + * from getting to lower performance levels, so force the minimum + * performance on CPU offline to prevent that from happening. + */ +- if (hwp_active) ++ if (hwp_active) { + intel_pstate_hwp_offline(cpu); +- else ++ } else { + intel_pstate_set_min_pstate(cpu); ++ policy->cur = cpu->pstate.min_pstate * cpu->pstate.scaling; ++ } + + intel_pstate_exit_perf_limits(policy); + diff --git a/queue-5.10/crypto-atmel-drop-explicit-initialization-of-struct-i2c_device_id-driver_data-to-0.patch b/queue-5.10/crypto-atmel-drop-explicit-initialization-of-struct-i2c_device_id-driver_data-to-0.patch new file mode 100644 index 0000000000..615da35b9f --- /dev/null +++ b/queue-5.10/crypto-atmel-drop-explicit-initialization-of-struct-i2c_device_id-driver_data-to-0.patch @@ -0,0 +1,39 @@ +From stable+bounces-278069-greg=kroah.com@vger.kernel.org Mon Jul 20 18:03:54 2026 +From: Sasha Levin +Date: Mon, 20 Jul 2026 11:48:12 -0400 +Subject: crypto: atmel - Drop explicit initialization of struct i2c_device_id::driver_data to 0 +To: stable@vger.kernel.org +Cc: "Uwe Kleine-König" , "Herbert Xu" , "Sasha Levin" +Message-ID: <20260720154813.2319486-2-sashal@kernel.org> + +From: Uwe Kleine-König + +[ Upstream commit d86ad3911a5d4549297ed810ee450e5772fd665f ] + +These drivers don't use the driver_data member of struct i2c_device_id, +so don't explicitly initialize this member. + +This prepares putting driver_data in an anonymous union which requires +either no initialization or named designators. But it's also a nice +cleanup on its own. + +Signed-off-by: Uwe Kleine-König +Signed-off-by: Herbert Xu +Stable-dep-of: ea5e57cc9718 ("crypto: atmel-sha204a - drop hwrng quality reduction for ATSHA204A") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/crypto/atmel-ecc.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/crypto/atmel-ecc.c ++++ b/drivers/crypto/atmel-ecc.c +@@ -387,7 +387,7 @@ MODULE_DEVICE_TABLE(of, atmel_ecc_dt_ids + #endif + + static const struct i2c_device_id atmel_ecc_id[] = { +- { "atecc508a", 0 }, ++ { "atecc508a" }, + { } + }; + MODULE_DEVICE_TABLE(i2c, atmel_ecc_id); diff --git a/queue-5.10/crypto-atmel-sha204a-drop-hwrng-quality-reduction-for-atsha204a.patch b/queue-5.10/crypto-atmel-sha204a-drop-hwrng-quality-reduction-for-atsha204a.patch new file mode 100644 index 0000000000..c9c6af20ff --- /dev/null +++ b/queue-5.10/crypto-atmel-sha204a-drop-hwrng-quality-reduction-for-atsha204a.patch @@ -0,0 +1,101 @@ +From stable+bounces-278070-greg=kroah.com@vger.kernel.org Mon Jul 20 17:48:33 2026 +From: Sasha Levin +Date: Mon, 20 Jul 2026 11:48:13 -0400 +Subject: crypto: atmel-sha204a - drop hwrng quality reduction for ATSHA204A +To: stable@vger.kernel.org +Cc: Thorsten Blum , Ard Biesheuvel , Herbert Xu , Sasha Levin +Message-ID: <20260720154813.2319486-3-sashal@kernel.org> + +From: Thorsten Blum + +[ Upstream commit ea5e57cc97185329dcc5ebdcaae7e1500bf0ad0b ] + +Commit 8006aff15516 ("crypto: atmel-sha204a - Set hwrng quality to +lowest possible") reduced the hwrng quality to 1 based on a review by +Bill Cox [1]. However, despite its title, the review only tested the +ATSHA204, not the ATSHA204A. + +In the same thread, Atmel engineer Landon Cox wrote "this behavior has +been eliminated entirely"[2] in the ATSHA204A and "this problem does not +affect the ATECC108 or the ATECC108A (or the ATSHA204A)"[3]. + +According to the official ATSHA204A datasheet [4], the device contains a +high-quality hardware RNG that combines its output with an internal seed +value stored in EEPROM or SRAM to generate random numbers. The device +also implements all security functions using SHA-256, and the driver +uses the chip's Random command in seed-update mode. + +Keep 'quality = 1' for ATSHA204, but drop the explicit hwrng quality +reduction for ATSHA204A and fall back to the hwrng core default. + +[1] https://www.metzdowd.com/pipermail/cryptography/2014-December/023858.html +[2] https://www.metzdowd.com/pipermail/cryptography/2014-December/023852.html +[3] https://www.metzdowd.com/pipermail/cryptography/2014-December/023886.html +[4] https://ww1.microchip.com/downloads/en/DeviceDoc/ATSHA204A-Data-Sheet-40002025A.pdf + +Fixes: 8006aff15516 ("crypto: atmel-sha204a - Set hwrng quality to lowest possible") +Cc: stable@vger.kernel.org +Signed-off-by: Thorsten Blum +Reviewed-by: Ard Biesheuvel +Signed-off-by: Herbert Xu +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/crypto/atmel-sha204a.c | 19 ++++++++++++------- + 1 file changed, 12 insertions(+), 7 deletions(-) + +--- a/drivers/crypto/atmel-sha204a.c ++++ b/drivers/crypto/atmel-sha204a.c +@@ -18,6 +18,12 @@ + #include + #include "atmel-i2c.h" + ++/* ++ * According to review by Bill Cox [1], the ATSHA204 has very low entropy. ++ * [1] https://www.metzdowd.com/pipermail/cryptography/2014-December/023858.html ++ */ ++static const unsigned short atsha204_quality = 1; ++ + static void atmel_sha204a_rng_done(struct atmel_i2c_work_data *work_data, + void *areq, int status) + { +@@ -96,6 +102,7 @@ static int atmel_sha204a_probe(struct i2 + const struct i2c_device_id *id) + { + struct atmel_i2c_client_priv *i2c_priv; ++ const unsigned short *quality; + int ret; + + ret = atmel_i2c_probe(client, id); +@@ -109,11 +116,9 @@ static int atmel_sha204a_probe(struct i2 + i2c_priv->hwrng.name = dev_name(&client->dev); + i2c_priv->hwrng.read = atmel_sha204a_rng_read; + +- /* +- * According to review by Bill Cox [1], this HWRNG has very low entropy. +- * [1] https://www.metzdowd.com/pipermail/cryptography/2014-December/023858.html +- */ +- i2c_priv->hwrng.quality = 1; ++ quality = i2c_get_match_data(client); ++ if (quality) ++ i2c_priv->hwrng.quality = *quality; + + ret = devm_hwrng_register(&client->dev, &i2c_priv->hwrng); + if (ret) +@@ -138,14 +143,14 @@ static int atmel_sha204a_remove(struct i + } + + static const struct of_device_id atmel_sha204a_dt_ids[] __maybe_unused = { +- { .compatible = "atmel,atsha204", }, ++ { .compatible = "atmel,atsha204", .data = &atsha204_quality }, + { .compatible = "atmel,atsha204a", }, + { /* sentinel */ } + }; + MODULE_DEVICE_TABLE(of, atmel_sha204a_dt_ids); + + static const struct i2c_device_id atmel_sha204a_id[] = { +- { "atsha204" }, ++ { "atsha204", (kernel_ulong_t)&atsha204_quality }, + { "atsha204a" }, + { /* sentinel */ } + }; diff --git a/queue-5.10/crypto-atmel-sha204a-mark-of-related-data-as-maybe-unused.patch b/queue-5.10/crypto-atmel-sha204a-mark-of-related-data-as-maybe-unused.patch new file mode 100644 index 0000000000..c81c2c8ede --- /dev/null +++ b/queue-5.10/crypto-atmel-sha204a-mark-of-related-data-as-maybe-unused.patch @@ -0,0 +1,47 @@ +From stable+bounces-278068-greg=kroah.com@vger.kernel.org Mon Jul 20 18:03:53 2026 +From: Sasha Levin +Date: Mon, 20 Jul 2026 11:48:11 -0400 +Subject: crypto: atmel-sha204a - Mark OF related data as maybe unused +To: stable@vger.kernel.org +Cc: Krzysztof Kozlowski , Herbert Xu , Sasha Levin +Message-ID: <20260720154813.2319486-1-sashal@kernel.org> + +From: Krzysztof Kozlowski + +[ Upstream commit 75f3d950054389e2556277e42170e37dd97cd872 ] + +The driver can be compile tested with !CONFIG_OF making certain data +unused: + + drivers/crypto/atmel-sha204a.c:129:34: error: ‘atmel_sha204a_dt_ids’ defined but not used [-Werror=unused-const-variable=] + +Signed-off-by: Krzysztof Kozlowski +Signed-off-by: Herbert Xu +Stable-dep-of: ea5e57cc9718 ("crypto: atmel-sha204a - drop hwrng quality reduction for ATSHA204A") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/crypto/atmel-sha204a.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +--- a/drivers/crypto/atmel-sha204a.c ++++ b/drivers/crypto/atmel-sha204a.c +@@ -137,14 +137,16 @@ static int atmel_sha204a_remove(struct i + return 0; + } + +-static const struct of_device_id atmel_sha204a_dt_ids[] = { ++static const struct of_device_id atmel_sha204a_dt_ids[] __maybe_unused = { ++ { .compatible = "atmel,atsha204", }, + { .compatible = "atmel,atsha204a", }, + { /* sentinel */ } + }; + MODULE_DEVICE_TABLE(of, atmel_sha204a_dt_ids); + + static const struct i2c_device_id atmel_sha204a_id[] = { +- { "atsha204a", 0 }, ++ { "atsha204" }, ++ { "atsha204a" }, + { /* sentinel */ } + }; + MODULE_DEVICE_TABLE(i2c, atmel_sha204a_id); diff --git a/queue-5.10/crypto-qat-fix-restarting-state-leak-on-allocation-failure.patch b/queue-5.10/crypto-qat-fix-restarting-state-leak-on-allocation-failure.patch new file mode 100644 index 0000000000..b8a1805cbc --- /dev/null +++ b/queue-5.10/crypto-qat-fix-restarting-state-leak-on-allocation-failure.patch @@ -0,0 +1,57 @@ +From stable+bounces-278234-greg=kroah.com@vger.kernel.org Mon Jul 20 22:46:18 2026 +From: Sasha Levin +Date: Mon, 20 Jul 2026 16:44:29 -0400 +Subject: crypto: qat - fix restarting state leak on allocation failure +To: stable@vger.kernel.org +Cc: Ahsan Atta , Maksim Lukoshkov , Giovanni Cabiddu , Herbert Xu , Sasha Levin +Message-ID: <20260720204429.3338926-1-sashal@kernel.org> + +From: Ahsan Atta + +[ Upstream commit 7d3ed20f7e46b3e991936fedd7a28f3ff4aec8d2 ] + +In adf_dev_aer_schedule_reset(), ADF_STATUS_RESTARTING is set before +allocating reset_data. If the allocation fails, the function returns +-ENOMEM without queuing reset work, so nothing ever clears the bit. +This leaves the device permanently stuck in the restarting state, +causing all subsequent reset attempts to be silently skipped. + +Fix this by using test_and_set_bit() to atomically claim the +RESTARTING state, preventing duplicate reset scheduling races under +concurrent fatal error reporting. If the subsequent allocation fails, +clear the bit to restore clean state so future reset attempts can +proceed. + +Cc: stable@vger.kernel.org +Fixes: d8cba25d2c68 ("crypto: qat - Intel(R) QAT driver framework") +Signed-off-by: Ahsan Atta +Co-developed-by: Maksim Lukoshkov +Signed-off-by: Maksim Lukoshkov +Reviewed-by: Giovanni Cabiddu +Signed-off-by: Herbert Xu +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/crypto/qat/qat_common/adf_aer.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +--- a/drivers/crypto/qat/qat_common/adf_aer.c ++++ b/drivers/crypto/qat/qat_common/adf_aer.c +@@ -116,13 +116,14 @@ static int adf_dev_aer_schedule_reset(st + struct adf_reset_dev_data *reset_data; + + if (!adf_dev_started(accel_dev) || +- test_bit(ADF_STATUS_RESTARTING, &accel_dev->status)) ++ test_and_set_bit(ADF_STATUS_RESTARTING, &accel_dev->status)) + return 0; + +- set_bit(ADF_STATUS_RESTARTING, &accel_dev->status); + reset_data = kzalloc(sizeof(*reset_data), GFP_KERNEL); +- if (!reset_data) ++ if (!reset_data) { ++ clear_bit(ADF_STATUS_RESTARTING, &accel_dev->status); + return -ENOMEM; ++ } + reset_data->accel_dev = accel_dev; + init_completion(&reset_data->compl); + reset_data->mode = mode; diff --git a/queue-5.10/crypto-qat-fix-vf2pf-work-teardown-race-in-adf_disable_sriov.patch b/queue-5.10/crypto-qat-fix-vf2pf-work-teardown-race-in-adf_disable_sriov.patch new file mode 100644 index 0000000000..09d21de98d --- /dev/null +++ b/queue-5.10/crypto-qat-fix-vf2pf-work-teardown-race-in-adf_disable_sriov.patch @@ -0,0 +1,251 @@ +From stable+bounces-274890-greg=kroah.com@vger.kernel.org Wed Jul 15 13:15:33 2026 +From: Sasha Levin +Date: Wed, 15 Jul 2026 07:15:23 -0400 +Subject: crypto: qat - fix VF2PF work teardown race in adf_disable_sriov() +To: stable@vger.kernel.org +Cc: Giovanni Cabiddu , Ahsan Atta , Herbert Xu , Sasha Levin +Message-ID: <20260715111523.644545-1-sashal@kernel.org> + +From: Giovanni Cabiddu + +[ Upstream commit 277281c10c63791067d24d421f7c43a15faa9096 ] + +The VF2PF interrupt handler queues PF-side response work that stores a +raw pointer to per-VF state (struct adf_accel_vf_info). Currently, +adf_disable_sriov() destroys per-VF mutexes and frees vf_info without +stopping new VF2PF work or waiting for in-flight workers to complete. A +concurrently scheduled or already queued worker can then dereference +freed memory. + +This manifests as a use-after-free when KASAN is enabled: + + BUG: KASAN: null-ptr-deref in mutex_lock+0x76/0xe0 + Write of size 8 at addr 0000000000000260 by task kworker/24:2/... + Workqueue: qat_pf2vf_resp_wq adf_iov_send_resp [intel_qat] + Call Trace: + kasan_report+0x119/0x140 + mutex_lock+0x76/0xe0 + adf_gen4_pfvf_send+0xd4/0x1f0 [intel_qat] + adf_recv_and_handle_vf2pf_msg+0x290/0x360 [intel_qat] + adf_iov_send_resp+0x8c/0xe0 [intel_qat] + process_one_work+0x6ac/0xfd0 + worker_thread+0x4dd/0xd30 + kthread+0x326/0x410 + ret_from_fork+0x33b/0x670 + +Add a PF-local flag, vf2pf_disabled, that gates work queueing, worker +processing, and interrupt re-enabling during teardown. Set this flag +atomically with the hardware interrupt mask inside +adf_disable_all_vf2pf_interrupts(). After masking, synchronize the AE +cluster MSI-X interrupt and flush the PF response workqueue before +tearing down per-VF locks and state so all in-flight work completes +before vf_info is destroyed. + +Introduce adf_enable_all_vf2pf_interrupts() to clear the flag and +unmask all VF2PF interrupts under the same lock when SR-IOV is +re-enabled. This ensures the software flag and hardware state transition +atomically on both the enable and disable paths. + +Cc: stable@vger.kernel.org +Fixes: ed8ccaef52fa ("crypto: qat - Add support for SRIOV") +Signed-off-by: Giovanni Cabiddu +Reviewed-by: Ahsan Atta +Signed-off-by: Herbert Xu +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/crypto/qat/qat_common/adf_accel_devices.h | 2 + + drivers/crypto/qat/qat_common/adf_common_drv.h | 4 ++ + drivers/crypto/qat/qat_common/adf_isr.c | 18 ++++++++++ + drivers/crypto/qat/qat_common/adf_pf2vf_msg.c | 22 ++++++++++++ + drivers/crypto/qat/qat_common/adf_sriov.c | 38 +++++++++++++++++----- + 5 files changed, 76 insertions(+), 8 deletions(-) + +--- a/drivers/crypto/qat/qat_common/adf_accel_devices.h ++++ b/drivers/crypto/qat/qat_common/adf_accel_devices.h +@@ -191,6 +191,8 @@ struct adf_accel_dev { + struct adf_accel_pci accel_pci_dev; + union { + struct { ++ /* prevents VF2PF handling from racing with VF state teardown */ ++ bool vf2pf_disabled; + /* vf_info is non-zero when SR-IOV is init'ed */ + struct adf_accel_vf_info *vf_info; + } pf; +--- a/drivers/crypto/qat/qat_common/adf_common_drv.h ++++ b/drivers/crypto/qat/qat_common/adf_common_drv.h +@@ -125,6 +125,7 @@ void qat_asym_algs_unregister(void); + + int adf_isr_resource_alloc(struct adf_accel_dev *accel_dev); + void adf_isr_resource_free(struct adf_accel_dev *accel_dev); ++void adf_isr_sync_ae_cluster(struct adf_accel_dev *accel_dev); + int adf_vf_isr_resource_alloc(struct adf_accel_dev *accel_dev); + void adf_vf_isr_resource_free(struct adf_accel_dev *accel_dev); + +@@ -189,6 +190,9 @@ void adf_disable_vf2pf_interrupts(struct + u32 vf_mask); + void adf_enable_vf2pf_interrupts(struct adf_accel_dev *accel_dev, + u32 vf_mask); ++void adf_enable_all_vf2pf_interrupts(struct adf_accel_dev *accel_dev, ++ u32 num_vfs); ++void adf_disable_all_vf2pf_interrupts(struct adf_accel_dev *accel_dev); + void adf_enable_pf2vf_interrupts(struct adf_accel_dev *accel_dev); + void adf_disable_pf2vf_interrupts(struct adf_accel_dev *accel_dev); + +--- a/drivers/crypto/qat/qat_common/adf_isr.c ++++ b/drivers/crypto/qat/qat_common/adf_isr.c +@@ -117,6 +117,24 @@ static irqreturn_t adf_msix_isr_ae(int i + return IRQ_NONE; + } + ++void adf_isr_sync_ae_cluster(struct adf_accel_dev *accel_dev) ++{ ++ struct adf_accel_pci *pci_dev_info = &accel_dev->accel_pci_dev; ++ struct adf_hw_device_data *hw_data = accel_dev->hw_device; ++ struct msix_entry *msixe = pci_dev_info->msix_entries.entries; ++ u32 num_entries = pci_dev_info->msix_entries.num_entries; ++ u32 irq_idx; ++ ++ if (!test_bit(ADF_STATUS_IRQ_ALLOCATED, &accel_dev->status) || !msixe) ++ return; ++ ++ irq_idx = num_entries > 1 ? hw_data->num_banks : 0; ++ if (irq_idx >= num_entries) ++ return; ++ ++ synchronize_irq(msixe[irq_idx].vector); ++} ++ + static int adf_request_irqs(struct adf_accel_dev *accel_dev) + { + struct adf_accel_pci *pci_dev_info = &accel_dev->accel_pci_dev; +--- a/drivers/crypto/qat/qat_common/adf_pf2vf_msg.c ++++ b/drivers/crypto/qat/qat_common/adf_pf2vf_msg.c +@@ -40,6 +40,9 @@ void adf_enable_vf2pf_interrupts(struct + void __iomem *pmisc_addr = pmisc->virt_addr; + u32 reg; + ++ if (READ_ONCE(accel_dev->pf.vf2pf_disabled)) ++ return; ++ + /* Enable VF2PF Messaging Ints - VFs 1 through 16 per vf_mask[15:0] */ + if (vf_mask & 0xFFFF) { + reg = ADF_CSR_RD(pmisc_addr, ADF_DH895XCC_ERRMSK3); +@@ -55,6 +58,19 @@ void adf_enable_vf2pf_interrupts(struct + } + } + ++void adf_enable_all_vf2pf_interrupts(struct adf_accel_dev *accel_dev, ++ u32 num_vfs) ++{ ++ u32 vf_mask; ++ ++ vf_mask = BIT_ULL(num_vfs) - 1; ++ if (!vf_mask) ++ return; ++ ++ WRITE_ONCE(accel_dev->pf.vf2pf_disabled, false); ++ adf_enable_vf2pf_interrupts(accel_dev, vf_mask); ++} ++ + void adf_disable_vf2pf_interrupts(struct adf_accel_dev *accel_dev, u32 vf_mask) + { + struct adf_hw_device_data *hw_data = accel_dev->hw_device; +@@ -78,6 +94,12 @@ void adf_disable_vf2pf_interrupts(struct + } + } + ++void adf_disable_all_vf2pf_interrupts(struct adf_accel_dev *accel_dev) ++{ ++ WRITE_ONCE(accel_dev->pf.vf2pf_disabled, true); ++ adf_disable_vf2pf_interrupts(accel_dev, GENMASK(31, 0)); ++} ++ + static int __adf_iov_putmsg(struct adf_accel_dev *accel_dev, u32 msg, u8 vf_nr) + { + struct adf_accel_pci *pci_info = &accel_dev->accel_pci_dev; +--- a/drivers/crypto/qat/qat_common/adf_sriov.c ++++ b/drivers/crypto/qat/qat_common/adf_sriov.c +@@ -44,16 +44,27 @@ static void adf_iov_send_resp(struct wor + { + struct adf_pf2vf_resp *pf2vf_resp = + container_of(work, struct adf_pf2vf_resp, pf2vf_resp_work); ++ struct adf_accel_vf_info *vf_info = pf2vf_resp->vf_info; ++ struct adf_accel_dev *accel_dev = vf_info->accel_dev; + +- adf_vf2pf_req_hndl(pf2vf_resp->vf_info); ++ if (READ_ONCE(accel_dev->pf.vf2pf_disabled)) ++ goto out; ++ ++ adf_vf2pf_req_hndl(vf_info); ++ ++out: + kfree(pf2vf_resp); + } + + static void adf_vf2pf_bh_handler(void *data) + { + struct adf_accel_vf_info *vf_info = (struct adf_accel_vf_info *)data; ++ struct adf_accel_dev *accel_dev = vf_info->accel_dev; + struct adf_pf2vf_resp *pf2vf_resp; + ++ if (READ_ONCE(accel_dev->pf.vf2pf_disabled)) ++ return; ++ + pf2vf_resp = kzalloc(sizeof(*pf2vf_resp), GFP_ATOMIC); + if (!pf2vf_resp) + return; +@@ -63,6 +74,12 @@ static void adf_vf2pf_bh_handler(void *d + queue_work(pf2vf_resp_wq, &pf2vf_resp->pf2vf_resp_work); + } + ++static void adf_flush_pf2vf_resp_wq(void) ++{ ++ if (pf2vf_resp_wq) ++ flush_workqueue(pf2vf_resp_wq); ++} ++ + static int adf_enable_sriov(struct adf_accel_dev *accel_dev) + { + struct pci_dev *pdev = accel_to_pci_dev(accel_dev); +@@ -105,7 +122,7 @@ static int adf_enable_sriov(struct adf_a + } + + /* Enable VF to PF interrupts for all VFs */ +- adf_enable_vf2pf_interrupts(accel_dev, GENMASK_ULL(totalvfs - 1, 0)); ++ adf_enable_all_vf2pf_interrupts(accel_dev, totalvfs); + + /* + * Due to the hardware design, when SR-IOV and the ring arbiter +@@ -142,8 +159,16 @@ void adf_disable_sriov(struct adf_accel_ + + pci_disable_sriov(accel_to_pci_dev(accel_dev)); + +- /* Disable VF to PF interrupts */ +- adf_disable_vf2pf_interrupts(accel_dev, 0xFFFFFFFF); ++ /* Block VF2PF work and disable VF to PF interrupts */ ++ adf_disable_all_vf2pf_interrupts(accel_dev); ++ adf_isr_sync_ae_cluster(accel_dev); ++ ++ for (i = 0, vf = accel_dev->pf.vf_info; i < totalvfs; i++, vf++) { ++ tasklet_disable(&vf->vf2pf_bh_tasklet); ++ tasklet_kill(&vf->vf2pf_bh_tasklet); ++ } ++ ++ adf_flush_pf2vf_resp_wq(); + + /* Clear Valid bits in ME Thread to PCIe Function Mapping Group A */ + for (i = 0; i < ME2FUNCTION_MAP_A_NUM_REGS; i++) { +@@ -159,11 +184,8 @@ void adf_disable_sriov(struct adf_accel_ + WRITE_CSR_ME2FUNCTION_MAP_B(pmisc_addr, i, reg); + } + +- for (i = 0, vf = accel_dev->pf.vf_info; i < totalvfs; i++, vf++) { +- tasklet_disable(&vf->vf2pf_bh_tasklet); +- tasklet_kill(&vf->vf2pf_bh_tasklet); ++ for (i = 0, vf = accel_dev->pf.vf_info; i < totalvfs; i++, vf++) + mutex_destroy(&vf->pf2vf_lock); +- } + + kfree(accel_dev->pf.vf_info); + accel_dev->pf.vf_info = NULL; diff --git a/queue-5.10/crypto-qat-validate-rsa-crt-component-lengths.patch b/queue-5.10/crypto-qat-validate-rsa-crt-component-lengths.patch new file mode 100644 index 0000000000..4b2cd054b8 --- /dev/null +++ b/queue-5.10/crypto-qat-validate-rsa-crt-component-lengths.patch @@ -0,0 +1,87 @@ +From stable+bounces-278317-greg=kroah.com@vger.kernel.org Tue Jul 21 03:28:07 2026 +From: Sasha Levin +Date: Mon, 20 Jul 2026 21:27:55 -0400 +Subject: crypto: qat - validate RSA CRT component lengths +To: stable@vger.kernel.org +Cc: Giovanni Cabiddu , Ahsan Atta , Laurent M Coquerel , Herbert Xu , Sasha Levin +Message-ID: <20260721012755.3458522-1-sashal@kernel.org> + +From: Giovanni Cabiddu + +[ Upstream commit b3ac78756588059729b9195fcc9f4b37d54057a5 ] + +The generic RSA key parser (rsa_helper.c) bounds each CRT component (p, +q, dp, dq, qinv) by the modulus size n_sz, but qat_rsa_setkey_crt() +allocates half-size DMA buffers (key_sz / 2) and right-aligns each +component with: + + memcpy(dst + half_key_sz - len, src, len) + +When a CRT component is larger than half_key_sz the subtraction +underflows and memcpy writes past the DMA buffer, causing memory +corruption. + +Add a len > half_key_sz check next to the existing !len check for each +of the five CRT components so the driver falls back to the non-CRT path +instead of writing out of bounds. + +Fixes: 879f77e9071f ("crypto: qat - Add RSA CRT mode") +Cc: stable@vger.kernel.org +Signed-off-by: Giovanni Cabiddu +Reviewed-by: Ahsan Atta +Reviewed-by: Laurent M Coquerel +Tested-by: Laurent M Coquerel +Signed-off-by: Herbert Xu +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/crypto/qat/qat_common/qat_asym_algs.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +--- a/drivers/crypto/qat/qat_common/qat_asym_algs.c ++++ b/drivers/crypto/qat/qat_common/qat_asym_algs.c +@@ -1030,7 +1030,7 @@ static void qat_rsa_setkey_crt(struct qa + ptr = rsa_key->p; + len = rsa_key->p_sz; + qat_rsa_drop_leading_zeros(&ptr, &len); +- if (!len) ++ if (!len || len > half_key_sz) + goto err; + ctx->p = dma_alloc_coherent(dev, half_key_sz, &ctx->dma_p, GFP_KERNEL); + if (!ctx->p) +@@ -1041,7 +1041,7 @@ static void qat_rsa_setkey_crt(struct qa + ptr = rsa_key->q; + len = rsa_key->q_sz; + qat_rsa_drop_leading_zeros(&ptr, &len); +- if (!len) ++ if (!len || len > half_key_sz) + goto free_p; + ctx->q = dma_alloc_coherent(dev, half_key_sz, &ctx->dma_q, GFP_KERNEL); + if (!ctx->q) +@@ -1052,7 +1052,7 @@ static void qat_rsa_setkey_crt(struct qa + ptr = rsa_key->dp; + len = rsa_key->dp_sz; + qat_rsa_drop_leading_zeros(&ptr, &len); +- if (!len) ++ if (!len || len > half_key_sz) + goto free_q; + ctx->dp = dma_alloc_coherent(dev, half_key_sz, &ctx->dma_dp, + GFP_KERNEL); +@@ -1064,7 +1064,7 @@ static void qat_rsa_setkey_crt(struct qa + ptr = rsa_key->dq; + len = rsa_key->dq_sz; + qat_rsa_drop_leading_zeros(&ptr, &len); +- if (!len) ++ if (!len || len > half_key_sz) + goto free_dp; + ctx->dq = dma_alloc_coherent(dev, half_key_sz, &ctx->dma_dq, + GFP_KERNEL); +@@ -1076,7 +1076,7 @@ static void qat_rsa_setkey_crt(struct qa + ptr = rsa_key->qinv; + len = rsa_key->qinv_sz; + qat_rsa_drop_leading_zeros(&ptr, &len); +- if (!len) ++ if (!len || len > half_key_sz) + goto free_dq; + ctx->qinv = dma_alloc_coherent(dev, half_key_sz, &ctx->dma_qinv, + GFP_KERNEL); diff --git a/queue-5.10/drm-i2c-sil164-drop-no-op-remove-function.patch b/queue-5.10/drm-i2c-sil164-drop-no-op-remove-function.patch new file mode 100644 index 0000000000..f7bd60413a --- /dev/null +++ b/queue-5.10/drm-i2c-sil164-drop-no-op-remove-function.patch @@ -0,0 +1,47 @@ +From stable+bounces-277535-greg=kroah.com@vger.kernel.org Mon Jul 20 04:35:47 2026 +From: Sasha Levin +Date: Sun, 19 Jul 2026 22:35:35 -0400 +Subject: drm/i2c/sil164: Drop no-op remove function +To: stable@vger.kernel.org +Cc: "Uwe Kleine-König" , "Wolfram Sang" , "Sasha Levin" +Message-ID: <20260720023539.2968115-1-sashal@kernel.org> + +From: Uwe Kleine-König + +[ Upstream commit eb09882d64807c24228ed1d005dbbae70860ca3f ] + +A remove callback that just returns 0 is equivalent to no callback at all +as can be seen in i2c_device_remove(). So simplify accordingly. + +Signed-off-by: Uwe Kleine-König +Signed-off-by: Wolfram Sang +Stable-dep-of: 1f0bdc2884b6 ("usb: typec: ucsi: ccg: Fix use-after-free of ucsi on remove") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/i2c/sil164_drv.c | 7 ------- + 1 file changed, 7 deletions(-) + +--- a/drivers/gpu/drm/i2c/sil164_drv.c ++++ b/drivers/gpu/drm/i2c/sil164_drv.c +@@ -370,12 +370,6 @@ sil164_probe(struct i2c_client *client, + return 0; + } + +-static int +-sil164_remove(struct i2c_client *client) +-{ +- return 0; +-} +- + static struct i2c_client * + sil164_detect_slave(struct i2c_client *client) + { +@@ -427,7 +421,6 @@ MODULE_DEVICE_TABLE(i2c, sil164_ids); + static struct drm_i2c_encoder_driver sil164_driver = { + .i2c_driver = { + .probe = sil164_probe, +- .remove = sil164_remove, + .driver = { + .name = "sil164", + }, diff --git a/queue-5.10/gpio-pca953x-make-platform-teardown-callback-return-void.patch b/queue-5.10/gpio-pca953x-make-platform-teardown-callback-return-void.patch new file mode 100644 index 0000000000..a8561faa0a --- /dev/null +++ b/queue-5.10/gpio-pca953x-make-platform-teardown-callback-return-void.patch @@ -0,0 +1,106 @@ +From stable+bounces-277538-greg=kroah.com@vger.kernel.org Mon Jul 20 04:35:51 2026 +From: Sasha Levin +Date: Sun, 19 Jul 2026 22:35:38 -0400 +Subject: gpio: pca953x: Make platform teardown callback return void +To: stable@vger.kernel.org +Cc: "Uwe Kleine-König" , "Andy Shevchenko" , "Bartosz Golaszewski" , "Wolfram Sang" , "Sasha Levin" +Message-ID: <20260720023539.2968115-4-sashal@kernel.org> + +From: Uwe Kleine-König + +[ Upstream commit 6a8f359c3132e4f51bdb263ad74ec632c65e55fd ] + +All platforms that provide a teardown callback return 0. New users are +supposed to not make use of platform support, so there is no +functionality lost. + +This patch is a preparation for making i2c remove callbacks return void. + +Reviewed-by: Andy Shevchenko +Signed-off-by: Uwe Kleine-König +Acked-by: Bartosz Golaszewski +Signed-off-by: Wolfram Sang +Stable-dep-of: 1f0bdc2884b6 ("usb: typec: ucsi: ccg: Fix use-after-free of ucsi on remove") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + arch/arm/mach-davinci/board-da850-evm.c | 12 ++++-------- + drivers/gpio/gpio-pca953x.c | 11 +++-------- + include/linux/platform_data/pca953x.h | 2 +- + 3 files changed, 8 insertions(+), 17 deletions(-) + +--- a/arch/arm/mach-davinci/board-da850-evm.c ++++ b/arch/arm/mach-davinci/board-da850-evm.c +@@ -519,8 +519,8 @@ exp_setup_sela_fail: + return ret; + } + +-static int da850_evm_ui_expander_teardown(struct i2c_client *client, +- unsigned gpio, unsigned ngpio, void *c) ++static void da850_evm_ui_expander_teardown(struct i2c_client *client, ++ unsigned gpio, unsigned ngpio, void *c) + { + platform_device_unregister(&da850_evm_ui_keys_device); + +@@ -532,8 +532,6 @@ static int da850_evm_ui_expander_teardow + gpio_free(gpio + DA850_EVM_UI_EXP_SEL_C); + gpio_free(gpio + DA850_EVM_UI_EXP_SEL_B); + gpio_free(gpio + DA850_EVM_UI_EXP_SEL_A); +- +- return 0; + } + + /* assign the baseboard expander's GPIOs after the UI board's */ +@@ -700,13 +698,11 @@ io_exp_setup_sw_fail: + return ret; + } + +-static int da850_evm_bb_expander_teardown(struct i2c_client *client, +- unsigned gpio, unsigned ngpio, void *c) ++static void da850_evm_bb_expander_teardown(struct i2c_client *client, ++ unsigned gpio, unsigned ngpio, void *c) + { + platform_device_unregister(&da850_evm_bb_leds_device); + platform_device_unregister(&da850_evm_bb_keys_device); +- +- return 0; + } + + static struct pca953x_platform_data da850_evm_ui_expander_info = { +--- a/drivers/gpio/gpio-pca953x.c ++++ b/drivers/gpio/gpio-pca953x.c +@@ -1073,20 +1073,15 @@ static int pca953x_remove(struct i2c_cli + { + struct pca953x_platform_data *pdata = dev_get_platdata(&client->dev); + struct pca953x_chip *chip = i2c_get_clientdata(client); +- int ret; + + if (pdata && pdata->teardown) { +- ret = pdata->teardown(client, chip->gpio_chip.base, +- chip->gpio_chip.ngpio, pdata->context); +- if (ret < 0) +- dev_err(&client->dev, "teardown failed, %d\n", ret); +- } else { +- ret = 0; ++ pdata->teardown(client, chip->gpio_chip.base, ++ chip->gpio_chip.ngpio, pdata->context); + } + + regulator_disable(chip->regulator); + +- return ret; ++ return 0; + } + + #ifdef CONFIG_PM_SLEEP +--- a/include/linux/platform_data/pca953x.h ++++ b/include/linux/platform_data/pca953x.h +@@ -22,7 +22,7 @@ struct pca953x_platform_data { + int (*setup)(struct i2c_client *client, + unsigned gpio, unsigned ngpio, + void *context); +- int (*teardown)(struct i2c_client *client, ++ void (*teardown)(struct i2c_client *client, + unsigned gpio, unsigned ngpio, + void *context); + const char *const *names; diff --git a/queue-5.10/hfs-hfsplus-fix-u32-overflow-in-check_and_correct_requested_length.patch b/queue-5.10/hfs-hfsplus-fix-u32-overflow-in-check_and_correct_requested_length.patch new file mode 100644 index 0000000000..1bf92a9899 --- /dev/null +++ b/queue-5.10/hfs-hfsplus-fix-u32-overflow-in-check_and_correct_requested_length.patch @@ -0,0 +1,69 @@ +From stable+bounces-277336-greg=kroah.com@vger.kernel.org Sat Jul 18 17:13:09 2026 +From: Sasha Levin +Date: Sat, 18 Jul 2026 11:12:56 -0400 +Subject: hfs/hfsplus: fix u32 overflow in check_and_correct_requested_length +To: stable@vger.kernel.org +Cc: Tristan Madani , syzbot+6df204b70bf3261691c5@syzkaller.appspotmail.com, syzbot+e76bf3d19b85350571ac@syzkaller.appspotmail.com, Viacheslav Dubeyko , Sasha Levin +Message-ID: <20260718151256.3269669-2-sashal@kernel.org> + +From: Tristan Madani + +[ Upstream commit 966cb76fb2857a4242cab6ea2ea17acf818a3da7 ] + +check_and_correct_requested_length() compares (off + len) against +node_size using u32 arithmetic. When the caller passes a large len +value (e.g. from an underflowed subtraction in hfs_brec_remove()), +off + len can wrap past 2^32 and produce a small result, causing the +bounds check to pass when it should fail. + +For example, with off=14 and len=0xFFFFFFF2 (underflowed from +data_off - keyoffset - size in hfs_brec_remove), off + len wraps to 6, +which is less than a typical node_size of 512, so the check passes and +the subsequent memmove reads ~4GB past the node buffer. + +Fix this by widening the addition to u64 before comparing against +node_size. This prevents the u32 wrap while keeping the logic +straightforward. + +Reported-by: syzbot+6df204b70bf3261691c5@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=6df204b70bf3261691c5 +Tested-by: syzbot+6df204b70bf3261691c5@syzkaller.appspotmail.com +Reported-by: syzbot+e76bf3d19b85350571ac@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=e76bf3d19b85350571ac +Tested-by: syzbot+e76bf3d19b85350571ac@syzkaller.appspotmail.com +Fixes: a431930c9bac ("hfs: fix slab-out-of-bounds in hfs_bnode_read()") +Cc: stable@vger.kernel.org +Signed-off-by: Tristan Madani +Reviewed-by: Viacheslav Dubeyko +Signed-off-by: Viacheslav Dubeyko +Link: https://lore.kernel.org/r/20260505111300.3592757-2-tristmd@gmail.com +Signed-off-by: Viacheslav Dubeyko +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + fs/hfs/bnode.c | 2 +- + fs/hfsplus/hfsplus_fs.h | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +--- a/fs/hfs/bnode.c ++++ b/fs/hfs/bnode.c +@@ -41,7 +41,7 @@ u32 check_and_correct_requested_length(s + + node_size = node->tree->node_size; + +- if ((off + len) > node_size) { ++ if ((u64)off + len > node_size) { + u32 new_len = node_size - off; + + pr_err("requested length has been corrected: " +--- a/fs/hfsplus/hfsplus_fs.h ++++ b/fs/hfsplus/hfsplus_fs.h +@@ -614,7 +614,7 @@ u32 check_and_correct_requested_length(s + + node_size = node->tree->node_size; + +- if ((off + len) > node_size) { ++ if ((u64)off + len > node_size) { + u32 new_len = node_size - off; + + pr_err("requested length has been corrected: " diff --git a/queue-5.10/hfs-hfsplus-prevent-getting-negative-values-of-offset-length.patch b/queue-5.10/hfs-hfsplus-prevent-getting-negative-values-of-offset-length.patch new file mode 100644 index 0000000000..68c526bf83 --- /dev/null +++ b/queue-5.10/hfs-hfsplus-prevent-getting-negative-values-of-offset-length.patch @@ -0,0 +1,956 @@ +From stable+bounces-277337-greg=kroah.com@vger.kernel.org Sat Jul 18 17:13:07 2026 +From: Sasha Levin +Date: Sat, 18 Jul 2026 11:12:55 -0400 +Subject: hfs/hfsplus: prevent getting negative values of offset/length +To: stable@vger.kernel.org +Cc: Viacheslav Dubeyko , John Paul Adrian Glaubitz , Yangtao Li , linux-fsdevel@vger.kernel.org, Sasha Levin +Message-ID: <20260718151256.3269669-1-sashal@kernel.org> + +From: Viacheslav Dubeyko + +[ Upstream commit 00c14a09a70e10ae18eb3707d0059291425c04bd ] + +The syzbot reported KASAN out-of-bounds issue in +hfs_bnode_move(): + +[ 45.588165][ T9821] hfs: dst 14, src 65536, len -65536 +[ 45.588895][ T9821] ================================================================== +[ 45.590114][ T9821] BUG: KASAN: out-of-bounds in hfs_bnode_move+0xfd/0x140 +[ 45.591127][ T9821] Read of size 18446744073709486080 at addr ffff888035935400 by task repro/9821 +[ 45.592207][ T9821] +[ 45.592420][ T9821] CPU: 0 UID: 0 PID: 9821 Comm: repro Not tainted 6.16.0-rc7-dirty #42 PREEMPT(full) +[ 45.592428][ T9821] Hardware name: QEMU Ubuntu 24.04 PC (i440FX + PIIX, 1996), BIOS 1.16.3-debian-1.16.3-2 04/01/2014 +[ 45.592431][ T9821] Call Trace: +[ 45.592434][ T9821] +[ 45.592437][ T9821] dump_stack_lvl+0x1c1/0x2a0 +[ 45.592446][ T9821] ? __virt_addr_valid+0x1c8/0x5c0 +[ 45.592454][ T9821] ? __pfx_dump_stack_lvl+0x10/0x10 +[ 45.592461][ T9821] ? rcu_is_watching+0x15/0xb0 +[ 45.592469][ T9821] ? lock_release+0x4b/0x3e0 +[ 45.592476][ T9821] ? __virt_addr_valid+0x1c8/0x5c0 +[ 45.592483][ T9821] ? __virt_addr_valid+0x4a5/0x5c0 +[ 45.592491][ T9821] print_report+0x17e/0x7c0 +[ 45.592497][ T9821] ? __virt_addr_valid+0x1c8/0x5c0 +[ 45.592504][ T9821] ? __virt_addr_valid+0x4a5/0x5c0 +[ 45.592511][ T9821] ? __phys_addr+0xd3/0x180 +[ 45.592519][ T9821] ? hfs_bnode_move+0xfd/0x140 +[ 45.592526][ T9821] kasan_report+0x147/0x180 +[ 45.592531][ T9821] ? _printk+0xcf/0x120 +[ 45.592537][ T9821] ? hfs_bnode_move+0xfd/0x140 +[ 45.592544][ T9821] ? hfs_bnode_move+0xfd/0x140 +[ 45.592552][ T9821] kasan_check_range+0x2b0/0x2c0 +[ 45.592557][ T9821] ? hfs_bnode_move+0xfd/0x140 +[ 45.592565][ T9821] __asan_memmove+0x29/0x70 +[ 45.592572][ T9821] hfs_bnode_move+0xfd/0x140 +[ 45.592580][ T9821] hfs_brec_remove+0x473/0x560 +[ 45.592589][ T9821] hfs_cat_move+0x6fb/0x960 +[ 45.592598][ T9821] ? __pfx_hfs_cat_move+0x10/0x10 +[ 45.592607][ T9821] ? seqcount_lockdep_reader_access+0x122/0x1c0 +[ 45.592614][ T9821] ? lockdep_hardirqs_on+0x9c/0x150 +[ 45.592631][ T9821] ? __lock_acquire+0xaec/0xd80 +[ 45.592641][ T9821] hfs_rename+0x1dc/0x2d0 +[ 45.592649][ T9821] ? __pfx_hfs_rename+0x10/0x10 +[ 45.592657][ T9821] vfs_rename+0xac6/0xed0 +[ 45.592664][ T9821] ? __pfx_vfs_rename+0x10/0x10 +[ 45.592670][ T9821] ? d_alloc+0x144/0x190 +[ 45.592677][ T9821] ? bpf_lsm_path_rename+0x9/0x20 +[ 45.592683][ T9821] ? security_path_rename+0x17d/0x490 +[ 45.592691][ T9821] do_renameat2+0x890/0xc50 +[ 45.592699][ T9821] ? __pfx_do_renameat2+0x10/0x10 +[ 45.592707][ T9821] ? getname_flags+0x1e5/0x540 +[ 45.592714][ T9821] __x64_sys_rename+0x82/0x90 +[ 45.592720][ T9821] ? entry_SYSCALL_64_after_hwframe+0x77/0x7f +[ 45.592725][ T9821] do_syscall_64+0xf3/0x3a0 +[ 45.592741][ T9821] ? exc_page_fault+0x9f/0xf0 +[ 45.592748][ T9821] entry_SYSCALL_64_after_hwframe+0x77/0x7f +[ 45.592754][ T9821] RIP: 0033:0x7f7f73fe3fc9 +[ 45.592760][ T9821] Code: 00 c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 44 00 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 48 +[ 45.592765][ T9821] RSP: 002b:00007ffc7e116cf8 EFLAGS: 00000283 ORIG_RAX: 0000000000000052 +[ 45.592772][ T9821] RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 00007f7f73fe3fc9 +[ 45.592776][ T9821] RDX: 0000200000000871 RSI: 0000200000000780 RDI: 00002000000003c0 +[ 45.592781][ T9821] RBP: 00007ffc7e116d00 R08: 0000000000000000 R09: 00007ffc7e116d30 +[ 45.592784][ T9821] R10: fffffffffffffff0 R11: 0000000000000283 R12: 00005557e81f8250 +[ 45.592788][ T9821] R13: 0000000000000000 R14: 0000000000000000 R15: 0000000000000000 +[ 45.592795][ T9821] +[ 45.592797][ T9821] +[ 45.619721][ T9821] The buggy address belongs to the physical page: +[ 45.620300][ T9821] page: refcount:1 mapcount:1 mapping:0000000000000000 index:0x559a88174 pfn:0x35935 +[ 45.621150][ T9821] memcg:ffff88810a1d5b00 +[ 45.621531][ T9821] anon flags: 0xfff60000020838(uptodate|dirty|lru|owner_2|swapbacked|node=0|zone=1|lastcpupid=0x7ff) +[ 45.622496][ T9821] raw: 00fff60000020838 ffffea0000d64d88 ffff888021753e10 ffff888029da0771 +[ 45.623260][ T9821] raw: 0000000559a88174 0000000000000000 0000000100000000 ffff88810a1d5b00 +[ 45.624030][ T9821] page dumped because: kasan: bad access detected +[ 45.624602][ T9821] page_owner tracks the page as allocated +[ 45.625115][ T9821] page last allocated via order 0, migratetype Movable, gfp_mask 0x140dca(GFP_HIGHUSER_MOVABLE|__GFP_ZERO0 +[ 45.626685][ T9821] post_alloc_hook+0x240/0x2a0 +[ 45.627127][ T9821] get_page_from_freelist+0x2101/0x21e0 +[ 45.627628][ T9821] __alloc_frozen_pages_noprof+0x274/0x380 +[ 45.628154][ T9821] alloc_pages_mpol+0x241/0x4b0 +[ 45.628593][ T9821] vma_alloc_folio_noprof+0xe4/0x210 +[ 45.629066][ T9821] folio_prealloc+0x30/0x180 +[ 45.629487][ T9821] __handle_mm_fault+0x34bd/0x5640 +[ 45.629957][ T9821] handle_mm_fault+0x40e/0x8e0 +[ 45.630392][ T9821] do_user_addr_fault+0xa81/0x1390 +[ 45.630862][ T9821] exc_page_fault+0x76/0xf0 +[ 45.631273][ T9821] asm_exc_page_fault+0x26/0x30 +[ 45.631712][ T9821] page last free pid 5269 tgid 5269 stack trace: +[ 45.632281][ T9821] free_unref_folios+0xc73/0x14c0 +[ 45.632740][ T9821] folios_put_refs+0x55b/0x640 +[ 45.633177][ T9821] free_pages_and_swap_cache+0x26d/0x510 +[ 45.633685][ T9821] tlb_flush_mmu+0x3a0/0x680 +[ 45.634105][ T9821] tlb_finish_mmu+0xd4/0x200 +[ 45.634525][ T9821] exit_mmap+0x44c/0xb70 +[ 45.634914][ T9821] __mmput+0x118/0x420 +[ 45.635286][ T9821] exit_mm+0x1da/0x2c0 +[ 45.635659][ T9821] do_exit+0x652/0x2330 +[ 45.636039][ T9821] do_group_exit+0x21c/0x2d0 +[ 45.636457][ T9821] __x64_sys_exit_group+0x3f/0x40 +[ 45.636915][ T9821] x64_sys_call+0x21ba/0x21c0 +[ 45.637342][ T9821] do_syscall_64+0xf3/0x3a0 +[ 45.637756][ T9821] entry_SYSCALL_64_after_hwframe+0x77/0x7f +[ 45.638290][ T9821] page has been migrated, last migrate reason: numa_misplaced +[ 45.638956][ T9821] +[ 45.639173][ T9821] Memory state around the buggy address: +[ 45.639677][ T9821] ffff888035935300: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +[ 45.640397][ T9821] ffff888035935380: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +[ 45.641117][ T9821] >ffff888035935400: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +[ 45.641837][ T9821] ^ +[ 45.642207][ T9821] ffff888035935480: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +[ 45.642929][ T9821] ffff888035935500: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +[ 45.643650][ T9821] ================================================================== + +This commit [1] fixes the issue if an offset inside of b-tree node +or length of the request is bigger than b-tree node. However, +this fix is still not ready for negative values +of the offset or length. Moreover, negative values of +the offset or length doesn't make sense for b-tree's +operations. Because we could try to access the memory address +outside of the beginning of memory page's addresses range. +Also, using of negative values make logic very complicated, +unpredictable, and we could access the wrong item(s) +in the b-tree node. + +This patch changes b-tree interface by means of converting +signed integer arguments of offset and length on u32 type. +Such conversion has goal to prevent of using negative values +unintentionally or by mistake in b-tree operations. + +[1] 'commit a431930c9bac ("hfs: fix slab-out-of-bounds in hfs_bnode_read()")' + +Signed-off-by: Viacheslav Dubeyko +cc: John Paul Adrian Glaubitz +cc: Yangtao Li +cc: linux-fsdevel@vger.kernel.org +Link: https://lore.kernel.org/r/20251002200020.2578311-1-slava@dubeyko.com +Signed-off-by: Viacheslav Dubeyko +Stable-dep-of: 966cb76fb285 ("hfs/hfsplus: fix u32 overflow in check_and_correct_requested_length") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + fs/hfs/bfind.c | 2 - + fs/hfs/bnode.c | 52 +++++++++++++++--------------- + fs/hfs/brec.c | 2 - + fs/hfs/btree.c | 2 - + fs/hfs/btree.h | 71 ++++++++++++++++++++--------------------- + fs/hfs/hfs_fs.h | 83 ++++++++++++++++++++++++++++-------------------- + fs/hfs/inode.c | 2 - + fs/hfsplus/bfind.c | 2 - + fs/hfsplus/bnode.c | 60 +++++++++++++++++----------------- + fs/hfsplus/brec.c | 2 - + fs/hfsplus/btree.c | 2 - + fs/hfsplus/hfsplus_fs.h | 38 ++++++++++----------- + 12 files changed, 167 insertions(+), 151 deletions(-) + +--- a/fs/hfs/bfind.c ++++ b/fs/hfs/bfind.c +@@ -164,7 +164,7 @@ release: + return res; + } + +-int hfs_brec_read(struct hfs_find_data *fd, void *rec, int rec_len) ++int hfs_brec_read(struct hfs_find_data *fd, void *rec, u32 rec_len) + { + int res; + +--- a/fs/hfs/bnode.c ++++ b/fs/hfs/bnode.c +@@ -16,14 +16,14 @@ + #include "btree.h" + + static inline +-bool is_bnode_offset_valid(struct hfs_bnode *node, int off) ++bool is_bnode_offset_valid(struct hfs_bnode *node, u32 off) + { + bool is_valid = off < node->tree->node_size; + + if (!is_valid) { + pr_err("requested invalid offset: " + "NODE: id %u, type %#x, height %u, " +- "node_size %u, offset %d\n", ++ "node_size %u, offset %u\n", + node->this, node->type, node->height, + node->tree->node_size, off); + } +@@ -32,7 +32,7 @@ bool is_bnode_offset_valid(struct hfs_bn + } + + static inline +-int check_and_correct_requested_length(struct hfs_bnode *node, int off, int len) ++u32 check_and_correct_requested_length(struct hfs_bnode *node, u32 off, u32 len) + { + unsigned int node_size; + +@@ -42,12 +42,12 @@ int check_and_correct_requested_length(s + node_size = node->tree->node_size; + + if ((off + len) > node_size) { +- int new_len = (int)node_size - off; ++ u32 new_len = node_size - off; + + pr_err("requested length has been corrected: " + "NODE: id %u, type %#x, height %u, " +- "node_size %u, offset %d, " +- "requested_len %d, corrected_len %d\n", ++ "node_size %u, offset %u, " ++ "requested_len %u, corrected_len %u\n", + node->this, node->type, node->height, + node->tree->node_size, off, len, new_len); + +@@ -57,12 +57,12 @@ int check_and_correct_requested_length(s + return len; + } + +-void hfs_bnode_read(struct hfs_bnode *node, void *buf, int off, int len) ++void hfs_bnode_read(struct hfs_bnode *node, void *buf, u32 off, u32 len) + { + struct page *page; +- int pagenum; +- int bytes_read; +- int bytes_to_read; ++ u32 pagenum; ++ u32 bytes_read; ++ u32 bytes_to_read; + void *vaddr; + + memset(buf, 0, len); +@@ -73,7 +73,7 @@ void hfs_bnode_read(struct hfs_bnode *no + if (len == 0) { + pr_err("requested zero length: " + "NODE: id %u, type %#x, height %u, " +- "node_size %u, offset %d, len %d\n", ++ "node_size %u, offset %u, len %u\n", + node->this, node->type, node->height, + node->tree->node_size, off, len); + return; +@@ -89,7 +89,7 @@ void hfs_bnode_read(struct hfs_bnode *no + if (pagenum >= node->tree->pages_per_bnode) + break; + page = node->page[pagenum]; +- bytes_to_read = min_t(int, len - bytes_read, PAGE_SIZE - off); ++ bytes_to_read = min_t(u32, len - bytes_read, PAGE_SIZE - off); + + vaddr = kmap_atomic(page); + memcpy(buf + bytes_read, vaddr + off, bytes_to_read); +@@ -100,7 +100,7 @@ void hfs_bnode_read(struct hfs_bnode *no + } + } + +-u16 hfs_bnode_read_u16(struct hfs_bnode *node, int off) ++u16 hfs_bnode_read_u16(struct hfs_bnode *node, u32 off) + { + __be16 data; + // optimize later... +@@ -108,7 +108,7 @@ u16 hfs_bnode_read_u16(struct hfs_bnode + return be16_to_cpu(data); + } + +-u8 hfs_bnode_read_u8(struct hfs_bnode *node, int off) ++u8 hfs_bnode_read_u8(struct hfs_bnode *node, u32 off) + { + u8 data; + // optimize later... +@@ -116,10 +116,10 @@ u8 hfs_bnode_read_u8(struct hfs_bnode *n + return data; + } + +-void hfs_bnode_read_key(struct hfs_bnode *node, void *key, int off) ++void hfs_bnode_read_key(struct hfs_bnode *node, void *key, u32 off) + { + struct hfs_btree *tree; +- int key_len; ++ u32 key_len; + + tree = node->tree; + if (node->type == HFS_NODE_LEAF || +@@ -130,14 +130,14 @@ void hfs_bnode_read_key(struct hfs_bnode + + if (key_len > sizeof(hfs_btree_key) || key_len < 1) { + memset(key, 0, sizeof(hfs_btree_key)); +- pr_err("hfs: Invalid key length: %d\n", key_len); ++ pr_err("hfs: Invalid key length: %u\n", key_len); + return; + } + + hfs_bnode_read(node, key, off, key_len); + } + +-void hfs_bnode_write(struct hfs_bnode *node, void *buf, int off, int len) ++void hfs_bnode_write(struct hfs_bnode *node, void *buf, u32 off, u32 len) + { + struct page *page; + +@@ -147,7 +147,7 @@ void hfs_bnode_write(struct hfs_bnode *n + if (len == 0) { + pr_err("requested zero length: " + "NODE: id %u, type %#x, height %u, " +- "node_size %u, offset %d, len %d\n", ++ "node_size %u, offset %u, len %u\n", + node->this, node->type, node->height, + node->tree->node_size, off, len); + return; +@@ -163,20 +163,20 @@ void hfs_bnode_write(struct hfs_bnode *n + set_page_dirty(page); + } + +-void hfs_bnode_write_u16(struct hfs_bnode *node, int off, u16 data) ++void hfs_bnode_write_u16(struct hfs_bnode *node, u32 off, u16 data) + { + __be16 v = cpu_to_be16(data); + // optimize later... + hfs_bnode_write(node, &v, off, 2); + } + +-void hfs_bnode_write_u8(struct hfs_bnode *node, int off, u8 data) ++void hfs_bnode_write_u8(struct hfs_bnode *node, u32 off, u8 data) + { + // optimize later... + hfs_bnode_write(node, &data, off, 1); + } + +-void hfs_bnode_clear(struct hfs_bnode *node, int off, int len) ++void hfs_bnode_clear(struct hfs_bnode *node, u32 off, u32 len) + { + struct page *page; + +@@ -186,7 +186,7 @@ void hfs_bnode_clear(struct hfs_bnode *n + if (len == 0) { + pr_err("requested zero length: " + "NODE: id %u, type %#x, height %u, " +- "node_size %u, offset %d, len %d\n", ++ "node_size %u, offset %u, len %u\n", + node->this, node->type, node->height, + node->tree->node_size, off, len); + return; +@@ -202,8 +202,8 @@ void hfs_bnode_clear(struct hfs_bnode *n + set_page_dirty(page); + } + +-void hfs_bnode_copy(struct hfs_bnode *dst_node, int dst, +- struct hfs_bnode *src_node, int src, int len) ++void hfs_bnode_copy(struct hfs_bnode *dst_node, u32 dst, ++ struct hfs_bnode *src_node, u32 src, u32 len) + { + struct page *src_page, *dst_page; + +@@ -225,7 +225,7 @@ void hfs_bnode_copy(struct hfs_bnode *ds + set_page_dirty(dst_page); + } + +-void hfs_bnode_move(struct hfs_bnode *node, int dst, int src, int len) ++void hfs_bnode_move(struct hfs_bnode *node, u32 dst, u32 src, u32 len) + { + struct page *page; + void *ptr; +--- a/fs/hfs/brec.c ++++ b/fs/hfs/brec.c +@@ -62,7 +62,7 @@ u16 hfs_brec_keylen(struct hfs_bnode *no + return retval; + } + +-int hfs_brec_insert(struct hfs_find_data *fd, void *entry, int entry_len) ++int hfs_brec_insert(struct hfs_find_data *fd, void *entry, u32 entry_len) + { + struct hfs_btree *tree; + struct hfs_bnode *node, *new_node; +--- a/fs/hfs/btree.c ++++ b/fs/hfs/btree.c +@@ -221,7 +221,7 @@ static struct hfs_bnode *hfs_bmap_new_bm + } + + /* Make sure @tree has enough space for the @rsvd_nodes */ +-int hfs_bmap_reserve(struct hfs_btree *tree, int rsvd_nodes) ++int hfs_bmap_reserve(struct hfs_btree *tree, u32 rsvd_nodes) + { + struct inode *inode = tree->inode; + u32 count; +--- a/fs/hfs/btree.h ++++ b/fs/hfs/btree.h +@@ -86,48 +86,49 @@ struct hfs_find_data { + + + /* btree.c */ +-extern struct hfs_btree *hfs_btree_open(struct super_block *, u32, btree_keycmp); +-extern void hfs_btree_close(struct hfs_btree *); +-extern void hfs_btree_write(struct hfs_btree *); +-extern int hfs_bmap_reserve(struct hfs_btree *, int); +-extern struct hfs_bnode * hfs_bmap_alloc(struct hfs_btree *); ++extern struct hfs_btree *hfs_btree_open(struct super_block *sb, u32 id, ++ btree_keycmp keycmp); ++extern void hfs_btree_close(struct hfs_btree *tree); ++extern void hfs_btree_write(struct hfs_btree *tree); ++extern int hfs_bmap_reserve(struct hfs_btree *tree, u32 rsvd_nodes); ++extern struct hfs_bnode *hfs_bmap_alloc(struct hfs_btree *tree); + extern void hfs_bmap_free(struct hfs_bnode *node); + + /* bnode.c */ +-extern void hfs_bnode_read(struct hfs_bnode *, void *, int, int); +-extern u16 hfs_bnode_read_u16(struct hfs_bnode *, int); +-extern u8 hfs_bnode_read_u8(struct hfs_bnode *, int); +-extern void hfs_bnode_read_key(struct hfs_bnode *, void *, int); +-extern void hfs_bnode_write(struct hfs_bnode *, void *, int, int); +-extern void hfs_bnode_write_u16(struct hfs_bnode *, int, u16); +-extern void hfs_bnode_write_u8(struct hfs_bnode *, int, u8); +-extern void hfs_bnode_clear(struct hfs_bnode *, int, int); +-extern void hfs_bnode_copy(struct hfs_bnode *, int, +- struct hfs_bnode *, int, int); +-extern void hfs_bnode_move(struct hfs_bnode *, int, int, int); +-extern void hfs_bnode_dump(struct hfs_bnode *); +-extern void hfs_bnode_unlink(struct hfs_bnode *); +-extern struct hfs_bnode *hfs_bnode_findhash(struct hfs_btree *, u32); +-extern struct hfs_bnode *hfs_bnode_find(struct hfs_btree *, u32); +-extern void hfs_bnode_unhash(struct hfs_bnode *); +-extern void hfs_bnode_free(struct hfs_bnode *); +-extern struct hfs_bnode *hfs_bnode_create(struct hfs_btree *, u32); +-extern void hfs_bnode_get(struct hfs_bnode *); +-extern void hfs_bnode_put(struct hfs_bnode *); ++extern void hfs_bnode_read(struct hfs_bnode *node, void *buf, u32 off, u32 len); ++extern u16 hfs_bnode_read_u16(struct hfs_bnode *node, u32 off); ++extern u8 hfs_bnode_read_u8(struct hfs_bnode *node, u32 off); ++extern void hfs_bnode_read_key(struct hfs_bnode *node, void *key, u32 off); ++extern void hfs_bnode_write(struct hfs_bnode *node, void *buf, u32 off, u32 len); ++extern void hfs_bnode_write_u16(struct hfs_bnode *node, u32 off, u16 data); ++extern void hfs_bnode_write_u8(struct hfs_bnode *node, u32 off, u8 data); ++extern void hfs_bnode_clear(struct hfs_bnode *node, u32 off, u32 len); ++extern void hfs_bnode_copy(struct hfs_bnode *dst_node, u32 dst, ++ struct hfs_bnode *src_node, u32 src, u32 len); ++extern void hfs_bnode_move(struct hfs_bnode *node, u32 dst, u32 src, u32 len); ++extern void hfs_bnode_dump(struct hfs_bnode *node); ++extern void hfs_bnode_unlink(struct hfs_bnode *node); ++extern struct hfs_bnode *hfs_bnode_findhash(struct hfs_btree *tree, u32 cnid); ++extern struct hfs_bnode *hfs_bnode_find(struct hfs_btree *tree, u32 num); ++extern void hfs_bnode_unhash(struct hfs_bnode *node); ++extern void hfs_bnode_free(struct hfs_bnode *node); ++extern struct hfs_bnode *hfs_bnode_create(struct hfs_btree *tree, u32 num); ++extern void hfs_bnode_get(struct hfs_bnode *node); ++extern void hfs_bnode_put(struct hfs_bnode *node); + + /* brec.c */ +-extern u16 hfs_brec_lenoff(struct hfs_bnode *, u16, u16 *); +-extern u16 hfs_brec_keylen(struct hfs_bnode *, u16); +-extern int hfs_brec_insert(struct hfs_find_data *, void *, int); +-extern int hfs_brec_remove(struct hfs_find_data *); ++extern u16 hfs_brec_lenoff(struct hfs_bnode *node, u16 rec, u16 *off); ++extern u16 hfs_brec_keylen(struct hfs_bnode *node, u16 rec); ++extern int hfs_brec_insert(struct hfs_find_data *fd, void *entry, u32 entry_len); ++extern int hfs_brec_remove(struct hfs_find_data *fd); + + /* bfind.c */ +-extern int hfs_find_init(struct hfs_btree *, struct hfs_find_data *); +-extern void hfs_find_exit(struct hfs_find_data *); +-extern int __hfs_brec_find(struct hfs_bnode *, struct hfs_find_data *); +-extern int hfs_brec_find(struct hfs_find_data *); +-extern int hfs_brec_read(struct hfs_find_data *, void *, int); +-extern int hfs_brec_goto(struct hfs_find_data *, int); ++extern int hfs_find_init(struct hfs_btree *tree, struct hfs_find_data *fd); ++extern void hfs_find_exit(struct hfs_find_data *fd); ++extern int __hfs_brec_find(struct hfs_bnode *bnode, struct hfs_find_data *fd); ++extern int hfs_brec_find(struct hfs_find_data *fd); ++extern int hfs_brec_read(struct hfs_find_data *fd, void *rec, u32 rec_len); ++extern int hfs_brec_goto(struct hfs_find_data *fd, int cnt); + + + struct hfs_bnode_desc { +--- a/fs/hfs/hfs_fs.h ++++ b/fs/hfs/hfs_fs.h +@@ -171,70 +171,85 @@ struct hfs_sb_info { + #define HFS_FLG_ALT_MDB_DIRTY 2 + + /* bitmap.c */ +-extern u32 hfs_vbm_search_free(struct super_block *, u32, u32 *); +-extern int hfs_clear_vbm_bits(struct super_block *, u16, u16); ++extern u32 hfs_vbm_search_free(struct super_block *sb, u32 goal, u32 *num_bits); ++extern int hfs_clear_vbm_bits(struct super_block *sb, u16 start, u16 count); + + /* catalog.c */ +-extern int hfs_cat_keycmp(const btree_key *, const btree_key *); ++extern int hfs_cat_keycmp(const btree_key *key1, const btree_key *key2); + struct hfs_find_data; +-extern int hfs_cat_find_brec(struct super_block *, u32, struct hfs_find_data *); +-extern int hfs_cat_create(u32, struct inode *, const struct qstr *, struct inode *); +-extern int hfs_cat_delete(u32, struct inode *, const struct qstr *); +-extern int hfs_cat_move(u32, struct inode *, const struct qstr *, +- struct inode *, const struct qstr *); +-extern void hfs_cat_build_key(struct super_block *, btree_key *, u32, const struct qstr *); ++extern int hfs_cat_find_brec(struct super_block *sb, u32 cnid, ++ struct hfs_find_data *fd); ++extern int hfs_cat_create(u32 cnid, struct inode *dir, ++ const struct qstr *str, struct inode *inode); ++extern int hfs_cat_delete(u32 cnid, struct inode *dir, const struct qstr *str); ++extern int hfs_cat_move(u32 cnid, struct inode *src_dir, ++ const struct qstr *src_name, ++ struct inode *dst_dir, ++ const struct qstr *dst_name); ++extern void hfs_cat_build_key(struct super_block *sb, btree_key *key, ++ u32 parent, const struct qstr *name); + + /* dir.c */ + extern const struct file_operations hfs_dir_operations; + extern const struct inode_operations hfs_dir_inode_operations; + + /* extent.c */ +-extern int hfs_ext_keycmp(const btree_key *, const btree_key *); +-extern int hfs_free_fork(struct super_block *, struct hfs_cat_file *, int); +-extern int hfs_ext_write_extent(struct inode *); +-extern int hfs_extend_file(struct inode *); +-extern void hfs_file_truncate(struct inode *); ++extern int hfs_ext_keycmp(const btree_key *key1, const btree_key *key2); ++extern int hfs_free_fork(struct super_block *sb, ++ struct hfs_cat_file *file, int type); ++extern int hfs_ext_write_extent(struct inode *inode); ++extern int hfs_extend_file(struct inode *inode); ++extern void hfs_file_truncate(struct inode *inode); + +-extern int hfs_get_block(struct inode *, sector_t, struct buffer_head *, int); ++extern int hfs_get_block(struct inode *inode, sector_t block, ++ struct buffer_head *bh_result, int create); + + /* inode.c */ + extern const struct address_space_operations hfs_aops; + extern const struct address_space_operations hfs_btree_aops; + +-extern struct inode *hfs_new_inode(struct inode *, const struct qstr *, umode_t); +-extern void hfs_inode_write_fork(struct inode *, struct hfs_extent *, __be32 *, __be32 *); +-extern int hfs_write_inode(struct inode *, struct writeback_control *); +-extern int hfs_inode_setattr(struct dentry *, struct iattr *); ++extern struct inode *hfs_new_inode(struct inode *dir, const struct qstr *name, ++ umode_t mode); ++extern void hfs_inode_write_fork(struct inode *inode, struct hfs_extent *ext, ++ __be32 *log_size, __be32 *phys_size); ++extern int hfs_write_inode(struct inode *inode, struct writeback_control *wbc); ++extern int hfs_inode_setattr(struct dentry *dentry, struct iattr *attr); + extern void hfs_inode_read_fork(struct inode *inode, struct hfs_extent *ext, +- __be32 log_size, __be32 phys_size, u32 clump_size); +-extern struct inode *hfs_iget(struct super_block *, struct hfs_cat_key *, hfs_cat_rec *); +-extern void hfs_evict_inode(struct inode *); +-extern void hfs_delete_inode(struct inode *); ++ __be32 __log_size, __be32 phys_size, ++ u32 clump_size); ++extern struct inode *hfs_iget(struct super_block *sb, struct hfs_cat_key *key, ++ hfs_cat_rec *rec); ++extern void hfs_evict_inode(struct inode *inode); ++extern void hfs_delete_inode(struct inode *inode); + + /* attr.c */ + extern const struct xattr_handler *hfs_xattr_handlers[]; + + /* mdb.c */ +-extern int hfs_mdb_get(struct super_block *); +-extern void hfs_mdb_commit(struct super_block *); +-extern void hfs_mdb_close(struct super_block *); +-extern void hfs_mdb_put(struct super_block *); ++extern int hfs_mdb_get(struct super_block *sb); ++extern void hfs_mdb_commit(struct super_block *sb); ++extern void hfs_mdb_close(struct super_block *sb); ++extern void hfs_mdb_put(struct super_block *sb); + + /* part_tbl.c */ +-extern int hfs_part_find(struct super_block *, sector_t *, sector_t *); ++extern int hfs_part_find(struct super_block *sb, ++ sector_t *part_start, sector_t *part_size); + + /* string.c */ + extern const struct dentry_operations hfs_dentry_operations; + +-extern int hfs_hash_dentry(const struct dentry *, struct qstr *); +-extern int hfs_strcmp(const unsigned char *, unsigned int, +- const unsigned char *, unsigned int); ++extern int hfs_hash_dentry(const struct dentry *dentry, struct qstr *this); ++extern int hfs_strcmp(const unsigned char *s1, unsigned int len1, ++ const unsigned char *s2, unsigned int len2); + extern int hfs_compare_dentry(const struct dentry *dentry, +- unsigned int len, const char *str, const struct qstr *name); ++ unsigned int len, const char *str, ++ const struct qstr *name); + + /* trans.c */ +-extern void hfs_asc2mac(struct super_block *, struct hfs_name *, const struct qstr *); +-extern int hfs_mac2asc(struct super_block *, char *, const struct hfs_name *); ++extern void hfs_asc2mac(struct super_block *sb, ++ struct hfs_name *out, const struct qstr *in); ++extern int hfs_mac2asc(struct super_block *sb, ++ char *out, const struct hfs_name *in); + + /* super.c */ + extern void hfs_mark_mdb_dirty(struct super_block *sb); +--- a/fs/hfs/inode.c ++++ b/fs/hfs/inode.c +@@ -50,7 +50,7 @@ static void hfs_write_failed(struct addr + } + + static int hfs_write_begin(struct file *file, struct address_space *mapping, +- loff_t pos, unsigned len, unsigned flags, ++ loff_t pos, unsigned int len, unsigned flags, + struct page **pagep, void **fsdata) + { + int ret; +--- a/fs/hfsplus/bfind.c ++++ b/fs/hfsplus/bfind.c +@@ -210,7 +210,7 @@ release: + return res; + } + +-int hfs_brec_read(struct hfs_find_data *fd, void *rec, int rec_len) ++int hfs_brec_read(struct hfs_find_data *fd, void *rec, u32 rec_len) + { + int res; + +--- a/fs/hfsplus/bnode.c ++++ b/fs/hfsplus/bnode.c +@@ -20,10 +20,10 @@ + + + /* Copy a specified range of bytes from the raw data of a node */ +-void hfs_bnode_read(struct hfs_bnode *node, void *buf, int off, int len) ++void hfs_bnode_read(struct hfs_bnode *node, void *buf, u32 off, u32 len) + { + struct page **pagep; +- int l; ++ u32 l; + + memset(buf, 0, len); + +@@ -33,7 +33,7 @@ void hfs_bnode_read(struct hfs_bnode *no + if (len == 0) { + pr_err("requested zero length: " + "NODE: id %u, type %#x, height %u, " +- "node_size %u, offset %d, len %d\n", ++ "node_size %u, offset %u, len %u\n", + node->this, node->type, node->height, + node->tree->node_size, off, len); + return; +@@ -45,19 +45,19 @@ void hfs_bnode_read(struct hfs_bnode *no + pagep = node->page + (off >> PAGE_SHIFT); + off &= ~PAGE_MASK; + +- l = min_t(int, len, PAGE_SIZE - off); ++ l = min_t(u32, len, PAGE_SIZE - off); + memcpy(buf, kmap(*pagep) + off, l); + kunmap(*pagep); + + while ((len -= l) != 0) { + buf += l; +- l = min_t(int, len, PAGE_SIZE); ++ l = min_t(u32, len, PAGE_SIZE); + memcpy(buf, kmap(*++pagep), l); + kunmap(*pagep); + } + } + +-u16 hfs_bnode_read_u16(struct hfs_bnode *node, int off) ++u16 hfs_bnode_read_u16(struct hfs_bnode *node, u32 off) + { + __be16 data; + /* TODO: optimize later... */ +@@ -65,7 +65,7 @@ u16 hfs_bnode_read_u16(struct hfs_bnode + return be16_to_cpu(data); + } + +-u8 hfs_bnode_read_u8(struct hfs_bnode *node, int off) ++u8 hfs_bnode_read_u8(struct hfs_bnode *node, u32 off) + { + u8 data; + /* TODO: optimize later... */ +@@ -73,10 +73,10 @@ u8 hfs_bnode_read_u8(struct hfs_bnode *n + return data; + } + +-void hfs_bnode_read_key(struct hfs_bnode *node, void *key, int off) ++void hfs_bnode_read_key(struct hfs_bnode *node, void *key, u32 off) + { + struct hfs_btree *tree; +- int key_len; ++ u32 key_len; + + tree = node->tree; + if (node->type == HFS_NODE_LEAF || +@@ -88,17 +88,17 @@ void hfs_bnode_read_key(struct hfs_bnode + + if (key_len > sizeof(hfsplus_btree_key) || key_len < 1) { + memset(key, 0, sizeof(hfsplus_btree_key)); +- pr_err("hfsplus: Invalid key length: %d\n", key_len); ++ pr_err("hfsplus: Invalid key length: %u\n", key_len); + return; + } + + hfs_bnode_read(node, key, off, key_len); + } + +-void hfs_bnode_write(struct hfs_bnode *node, void *buf, int off, int len) ++void hfs_bnode_write(struct hfs_bnode *node, void *buf, u32 off, u32 len) + { + struct page **pagep; +- int l; ++ u32 l; + + if (!is_bnode_offset_valid(node, off)) + return; +@@ -106,7 +106,7 @@ void hfs_bnode_write(struct hfs_bnode *n + if (len == 0) { + pr_err("requested zero length: " + "NODE: id %u, type %#x, height %u, " +- "node_size %u, offset %d, len %d\n", ++ "node_size %u, offset %u, len %u\n", + node->this, node->type, node->height, + node->tree->node_size, off, len); + return; +@@ -118,31 +118,31 @@ void hfs_bnode_write(struct hfs_bnode *n + pagep = node->page + (off >> PAGE_SHIFT); + off &= ~PAGE_MASK; + +- l = min_t(int, len, PAGE_SIZE - off); ++ l = min_t(u32, len, PAGE_SIZE - off); + memcpy(kmap(*pagep) + off, buf, l); + set_page_dirty(*pagep); + kunmap(*pagep); + + while ((len -= l) != 0) { + buf += l; +- l = min_t(int, len, PAGE_SIZE); ++ l = min_t(u32, len, PAGE_SIZE); + memcpy(kmap(*++pagep), buf, l); + set_page_dirty(*pagep); + kunmap(*pagep); + } + } + +-void hfs_bnode_write_u16(struct hfs_bnode *node, int off, u16 data) ++void hfs_bnode_write_u16(struct hfs_bnode *node, u32 off, u16 data) + { + __be16 v = cpu_to_be16(data); + /* TODO: optimize later... */ + hfs_bnode_write(node, &v, off, 2); + } + +-void hfs_bnode_clear(struct hfs_bnode *node, int off, int len) ++void hfs_bnode_clear(struct hfs_bnode *node, u32 off, u32 len) + { + struct page **pagep; +- int l; ++ u32 l; + + if (!is_bnode_offset_valid(node, off)) + return; +@@ -150,7 +150,7 @@ void hfs_bnode_clear(struct hfs_bnode *n + if (len == 0) { + pr_err("requested zero length: " + "NODE: id %u, type %#x, height %u, " +- "node_size %u, offset %d, len %d\n", ++ "node_size %u, offset %u, len %u\n", + node->this, node->type, node->height, + node->tree->node_size, off, len); + return; +@@ -162,24 +162,24 @@ void hfs_bnode_clear(struct hfs_bnode *n + pagep = node->page + (off >> PAGE_SHIFT); + off &= ~PAGE_MASK; + +- l = min_t(int, len, PAGE_SIZE - off); ++ l = min_t(u32, len, PAGE_SIZE - off); + memset(kmap(*pagep) + off, 0, l); + set_page_dirty(*pagep); + kunmap(*pagep); + + while ((len -= l) != 0) { +- l = min_t(int, len, PAGE_SIZE); ++ l = min_t(u32, len, PAGE_SIZE); + memset(kmap(*++pagep), 0, l); + set_page_dirty(*pagep); + kunmap(*pagep); + } + } + +-void hfs_bnode_copy(struct hfs_bnode *dst_node, int dst, +- struct hfs_bnode *src_node, int src, int len) ++void hfs_bnode_copy(struct hfs_bnode *dst_node, u32 dst, ++ struct hfs_bnode *src_node, u32 src, u32 len) + { + struct page **src_page, **dst_page; +- int l; ++ u32 l; + + hfs_dbg(BNODE_MOD, "copybytes: %u,%u,%u\n", dst, src, len); + if (!len) +@@ -196,14 +196,14 @@ void hfs_bnode_copy(struct hfs_bnode *ds + dst &= ~PAGE_MASK; + + if (src == dst) { +- l = min_t(int, len, PAGE_SIZE - src); ++ l = min_t(u32, len, PAGE_SIZE - src); + memcpy(kmap(*dst_page) + src, kmap(*src_page) + src, l); + kunmap(*src_page); + set_page_dirty(*dst_page); + kunmap(*dst_page); + + while ((len -= l) != 0) { +- l = min_t(int, len, PAGE_SIZE); ++ l = min_t(u32, len, PAGE_SIZE); + memcpy(kmap(*++dst_page), kmap(*++src_page), l); + kunmap(*src_page); + set_page_dirty(*dst_page); +@@ -237,10 +237,10 @@ void hfs_bnode_copy(struct hfs_bnode *ds + } + } + +-void hfs_bnode_move(struct hfs_bnode *node, int dst, int src, int len) ++void hfs_bnode_move(struct hfs_bnode *node, u32 dst, u32 src, u32 len) + { + struct page **src_page, **dst_page; +- int l; ++ u32 l; + + hfs_dbg(BNODE_MOD, "movebytes: %u,%u,%u\n", dst, src, len); + if (!len) +@@ -309,7 +309,7 @@ void hfs_bnode_move(struct hfs_bnode *no + dst &= ~PAGE_MASK; + + if (src == dst) { +- l = min_t(int, len, PAGE_SIZE - src); ++ l = min_t(u32, len, PAGE_SIZE - src); + memmove(kmap(*dst_page) + src, + kmap(*src_page) + src, l); + kunmap(*src_page); +@@ -317,7 +317,7 @@ void hfs_bnode_move(struct hfs_bnode *no + kunmap(*dst_page); + + while ((len -= l) != 0) { +- l = min_t(int, len, PAGE_SIZE); ++ l = min_t(u32, len, PAGE_SIZE); + memmove(kmap(*++dst_page), + kmap(*++src_page), l); + kunmap(*src_page); +--- a/fs/hfsplus/brec.c ++++ b/fs/hfsplus/brec.c +@@ -60,7 +60,7 @@ u16 hfs_brec_keylen(struct hfs_bnode *no + return retval; + } + +-int hfs_brec_insert(struct hfs_find_data *fd, void *entry, int entry_len) ++int hfs_brec_insert(struct hfs_find_data *fd, void *entry, u32 entry_len) + { + struct hfs_btree *tree; + struct hfs_bnode *node, *new_node; +--- a/fs/hfsplus/btree.c ++++ b/fs/hfsplus/btree.c +@@ -343,7 +343,7 @@ static struct hfs_bnode *hfs_bmap_new_bm + } + + /* Make sure @tree has enough space for the @rsvd_nodes */ +-int hfs_bmap_reserve(struct hfs_btree *tree, int rsvd_nodes) ++int hfs_bmap_reserve(struct hfs_btree *tree, u32 rsvd_nodes) + { + struct inode *inode = tree->inode; + struct hfsplus_inode_info *hip = HFSPLUS_I(inode); +--- a/fs/hfsplus/hfsplus_fs.h ++++ b/fs/hfsplus/hfsplus_fs.h +@@ -399,21 +399,21 @@ u32 hfsplus_calc_btree_clump_size(u32 bl + struct hfs_btree *hfs_btree_open(struct super_block *sb, u32 id); + void hfs_btree_close(struct hfs_btree *tree); + int hfs_btree_write(struct hfs_btree *tree); +-int hfs_bmap_reserve(struct hfs_btree *tree, int rsvd_nodes); ++int hfs_bmap_reserve(struct hfs_btree *tree, u32 rsvd_nodes); + struct hfs_bnode *hfs_bmap_alloc(struct hfs_btree *tree); + void hfs_bmap_free(struct hfs_bnode *node); + + /* bnode.c */ +-void hfs_bnode_read(struct hfs_bnode *node, void *buf, int off, int len); +-u16 hfs_bnode_read_u16(struct hfs_bnode *node, int off); +-u8 hfs_bnode_read_u8(struct hfs_bnode *node, int off); +-void hfs_bnode_read_key(struct hfs_bnode *node, void *key, int off); +-void hfs_bnode_write(struct hfs_bnode *node, void *buf, int off, int len); +-void hfs_bnode_write_u16(struct hfs_bnode *node, int off, u16 data); +-void hfs_bnode_clear(struct hfs_bnode *node, int off, int len); +-void hfs_bnode_copy(struct hfs_bnode *dst_node, int dst, +- struct hfs_bnode *src_node, int src, int len); +-void hfs_bnode_move(struct hfs_bnode *node, int dst, int src, int len); ++void hfs_bnode_read(struct hfs_bnode *node, void *buf, u32 off, u32 len); ++u16 hfs_bnode_read_u16(struct hfs_bnode *node, u32 off); ++u8 hfs_bnode_read_u8(struct hfs_bnode *node, u32 off); ++void hfs_bnode_read_key(struct hfs_bnode *node, void *key, u32 off); ++void hfs_bnode_write(struct hfs_bnode *node, void *buf, u32 off, u32 len); ++void hfs_bnode_write_u16(struct hfs_bnode *node, u32 off, u16 data); ++void hfs_bnode_clear(struct hfs_bnode *node, u32 off, u32 len); ++void hfs_bnode_copy(struct hfs_bnode *dst_node, u32 dst, ++ struct hfs_bnode *src_node, u32 src, u32 len); ++void hfs_bnode_move(struct hfs_bnode *node, u32 dst, u32 src, u32 len); + void hfs_bnode_dump(struct hfs_bnode *node); + void hfs_bnode_unlink(struct hfs_bnode *node); + struct hfs_bnode *hfs_bnode_findhash(struct hfs_btree *tree, u32 cnid); +@@ -428,7 +428,7 @@ bool hfs_bnode_need_zeroout(struct hfs_b + /* brec.c */ + u16 hfs_brec_lenoff(struct hfs_bnode *node, u16 rec, u16 *off); + u16 hfs_brec_keylen(struct hfs_bnode *node, u16 rec); +-int hfs_brec_insert(struct hfs_find_data *fd, void *entry, int entry_len); ++int hfs_brec_insert(struct hfs_find_data *fd, void *entry, u32 entry_len); + int hfs_brec_remove(struct hfs_find_data *fd); + + /* bfind.c */ +@@ -441,7 +441,7 @@ int hfs_find_rec_by_key(struct hfs_bnode + int __hfs_brec_find(struct hfs_bnode *bnode, struct hfs_find_data *fd, + search_strategy_t rec_found); + int hfs_brec_find(struct hfs_find_data *fd, search_strategy_t do_key_compare); +-int hfs_brec_read(struct hfs_find_data *fd, void *rec, int rec_len); ++int hfs_brec_read(struct hfs_find_data *fd, void *rec, u32 rec_len); + int hfs_brec_goto(struct hfs_find_data *fd, int cnt); + + /* catalog.c */ +@@ -589,14 +589,14 @@ hfsplus_btree_lock_class(struct hfs_btre + } + + static inline +-bool is_bnode_offset_valid(struct hfs_bnode *node, int off) ++bool is_bnode_offset_valid(struct hfs_bnode *node, u32 off) + { + bool is_valid = off < node->tree->node_size; + + if (!is_valid) { + pr_err("requested invalid offset: " + "NODE: id %u, type %#x, height %u, " +- "node_size %u, offset %d\n", ++ "node_size %u, offset %u\n", + node->this, node->type, node->height, + node->tree->node_size, off); + } +@@ -605,7 +605,7 @@ bool is_bnode_offset_valid(struct hfs_bn + } + + static inline +-int check_and_correct_requested_length(struct hfs_bnode *node, int off, int len) ++u32 check_and_correct_requested_length(struct hfs_bnode *node, u32 off, u32 len) + { + unsigned int node_size; + +@@ -615,12 +615,12 @@ int check_and_correct_requested_length(s + node_size = node->tree->node_size; + + if ((off + len) > node_size) { +- int new_len = (int)node_size - off; ++ u32 new_len = node_size - off; + + pr_err("requested length has been corrected: " + "NODE: id %u, type %#x, height %u, " +- "node_size %u, offset %d, " +- "requested_len %d, corrected_len %d\n", ++ "node_size %u, offset %u, " ++ "requested_len %u, corrected_len %u\n", + node->this, node->type, node->height, + node->tree->node_size, off, len, new_len); + diff --git a/queue-5.10/hid-add-haptics-page-defines.patch b/queue-5.10/hid-add-haptics-page-defines.patch new file mode 100644 index 0000000000..eb51e32839 --- /dev/null +++ b/queue-5.10/hid-add-haptics-page-defines.patch @@ -0,0 +1,78 @@ +From stable+bounces-277172-greg=kroah.com@vger.kernel.org Fri Jul 17 20:11:41 2026 +From: Sasha Levin +Date: Fri, 17 Jul 2026 14:11:32 -0400 +Subject: HID: add haptics page defines +To: stable@vger.kernel.org +Cc: Angela Czubak , Jonathan Denose , Benjamin Tissoires , Sasha Levin +Message-ID: <20260717181133.2086215-1-sashal@kernel.org> + +From: Angela Czubak + +[ Upstream commit 5e0ae59159e3a07391a35865bb79ff335473fa79 ] + +Introduce haptic usages as defined in HID Usage Tables specification. +Add HID units for newton and gram. + +Signed-off-by: Angela Czubak +Co-developed-by: Jonathan Denose +Signed-off-by: Jonathan Denose +Signed-off-by: Benjamin Tissoires +Stable-dep-of: 8813b0612275 ("HID: multitouch: fix out-of-bounds bit access on mt_io_flags") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + include/linux/hid.h | 29 +++++++++++++++++++++++++++++ + 1 file changed, 29 insertions(+) + +--- a/include/linux/hid.h ++++ b/include/linux/hid.h +@@ -152,6 +152,7 @@ struct hid_item { + #define HID_UP_TELEPHONY 0x000b0000 + #define HID_UP_CONSUMER 0x000c0000 + #define HID_UP_DIGITIZER 0x000d0000 ++#define HID_UP_HAPTIC 0x000e0000 + #define HID_UP_PID 0x000f0000 + #define HID_UP_HPVENDOR 0xff7f0000 + #define HID_UP_HPVENDOR2 0xff010000 +@@ -299,6 +300,28 @@ struct hid_item { + #define HID_DG_TOOLSERIALNUMBER 0x000d005b + #define HID_DG_LATENCYMODE 0x000d0060 + ++#define HID_HP_SIMPLECONTROLLER 0x000e0001 ++#define HID_HP_WAVEFORMLIST 0x000e0010 ++#define HID_HP_DURATIONLIST 0x000e0011 ++#define HID_HP_AUTOTRIGGER 0x000e0020 ++#define HID_HP_MANUALTRIGGER 0x000e0021 ++#define HID_HP_AUTOTRIGGERASSOCIATEDCONTROL 0x000e0022 ++#define HID_HP_INTENSITY 0x000e0023 ++#define HID_HP_REPEATCOUNT 0x000e0024 ++#define HID_HP_RETRIGGERPERIOD 0x000e0025 ++#define HID_HP_WAVEFORMVENDORPAGE 0x000e0026 ++#define HID_HP_WAVEFORMVENDORID 0x000e0027 ++#define HID_HP_WAVEFORMCUTOFFTIME 0x000e0028 ++#define HID_HP_WAVEFORMNONE 0x000e1001 ++#define HID_HP_WAVEFORMSTOP 0x000e1002 ++#define HID_HP_WAVEFORMCLICK 0x000e1003 ++#define HID_HP_WAVEFORMBUZZCONTINUOUS 0x000e1004 ++#define HID_HP_WAVEFORMRUMBLECONTINUOUS 0x000e1005 ++#define HID_HP_WAVEFORMPRESS 0x000e1006 ++#define HID_HP_WAVEFORMRELEASE 0x000e1007 ++#define HID_HP_VENDORWAVEFORMMIN 0x000e2001 ++#define HID_HP_VENDORWAVEFORMMAX 0x000e2fff ++ + #define HID_VD_ASUS_CUSTOM_MEDIA_KEYS 0xff310076 + /* + * HID report types --- Ouch! HID spec says 1 2 3! +@@ -385,6 +408,12 @@ struct hid_item { + #define HID_BOOT_PROTOCOL 0 + + /* ++ * HID units ++ */ ++#define HID_UNIT_GRAM 0x0101 ++#define HID_UNIT_NEWTON 0xe111 ++ ++/* + * This is the global environment of the parser. This information is + * persistent for main-items. The global environment can be saved and + * restored with PUSH/POP statements. diff --git a/queue-5.10/hid-appleir-fix-uaf-on-pending-key_up_timer-in-remove.patch b/queue-5.10/hid-appleir-fix-uaf-on-pending-key_up_timer-in-remove.patch new file mode 100644 index 0000000000..5da544132f --- /dev/null +++ b/queue-5.10/hid-appleir-fix-uaf-on-pending-key_up_timer-in-remove.patch @@ -0,0 +1,150 @@ +From stable+bounces-277229-greg=kroah.com@vger.kernel.org Sat Jul 18 02:51:46 2026 +From: Sasha Levin +Date: Fri, 17 Jul 2026 20:51:23 -0400 +Subject: HID: appleir: fix UAF on pending key_up_timer in remove() +To: stable@vger.kernel.org +Cc: Manish Khadka , Jiri Kosina , Sasha Levin +Message-ID: <20260718005123.2484926-1-sashal@kernel.org> + +From: Manish Khadka + +[ Upstream commit 75fe87e19d8aff81eb2c64d15d244ab8da4de945 ] + +appleir_remove() runs hid_hw_stop() before timer_delete_sync(). +hid_hw_stop() synchronously unregisters the HID input device via +hid_disconnect() -> hidinput_disconnect() -> input_unregister_device(), +which drops the last reference and frees the underlying input_dev when +no userspace handle holds it open. + +key_up_tick() reads appleir->input_dev and calls input_report_key() / +input_sync() on it. The timer is armed from appleir_raw_event() with +a HZ/8 (~125 ms) timeout on every keydown and key-repeat report. If a +key was pressed shortly before the device is disconnected, the timer +can fire after hid_hw_stop() has freed input_dev but before the +teardown drains it. + +A simple reorder is not sufficient. Putting the timer drain first +still leaves a window where a USB URB completion (raw_event) running +during hid_hw_stop() can call mod_timer() and re-arm the timer, which +then fires after hidinput_disconnect() has freed input_dev. The same +URB-completion window also lets raw_event() reach key_up(), key_down() +and battery_flat() directly, all of which dereference +appleir->input_dev. + +Introduce a 'removing' flag on struct appleir, gated by the existing +spinlock. appleir_remove() sets the flag under the lock and then +shuts down the timer with timer_shutdown_sync(), which both drains any +in-flight callback and permanently disables further mod_timer() calls. +appleir_raw_event() and key_up_tick() bail out early if the flag is +set, so no path can arm or run the timer, or dereference +appleir->input_dev, after remove() has started tearing down. + +The keyrepeat and flatbattery branches of appleir_raw_event() +previously called into the input layer without holding the spinlock; +take it now so the flag check is well-defined. This incidentally +closes a pre-existing read-side race on appleir->current_key in the +keyrepeat branch. + +This bug is structurally a sibling of commit 4db2af929279 ("HID: +appletb-kbd: fix UAF in inactivity-timer cleanup path") and has been +present since the driver was introduced. + +Fixes: 9a4a5574ce42 ("HID: appleir: add support for Apple ir devices") +Cc: stable@vger.kernel.org +Signed-off-by: Manish Khadka +Signed-off-by: Jiri Kosina +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/hid/hid-appleir.c | 45 +++++++++++++++++++++++++++++++++++---------- + 1 file changed, 35 insertions(+), 10 deletions(-) + +--- a/drivers/hid/hid-appleir.c ++++ b/drivers/hid/hid-appleir.c +@@ -109,9 +109,10 @@ struct appleir { + struct hid_device *hid; + unsigned short keymap[ARRAY_SIZE(appleir_key_table)]; + struct timer_list key_up_timer; /* timer for key up */ +- spinlock_t lock; /* protects .current_key */ ++ spinlock_t lock; /* protects .current_key, .removing */ + int current_key; /* the currently pressed key */ + int prev_key_idx; /* key index in a 2 packets message */ ++ bool removing; /* set during teardown; gates input_dev access */ + }; + + static int get_key(int data) +@@ -172,7 +173,7 @@ static void key_up_tick(struct timer_lis + unsigned long flags; + + spin_lock_irqsave(&appleir->lock, flags); +- if (appleir->current_key) { ++ if (!appleir->removing && appleir->current_key) { + key_up(hid, appleir, appleir->current_key); + appleir->current_key = 0; + } +@@ -195,6 +196,10 @@ static int appleir_raw_event(struct hid_ + int index; + + spin_lock_irqsave(&appleir->lock, flags); ++ if (appleir->removing) { ++ spin_unlock_irqrestore(&appleir->lock, flags); ++ goto out; ++ } + /* + * If we already have a key down, take it up before marking + * this one down +@@ -229,17 +234,25 @@ static int appleir_raw_event(struct hid_ + appleir->prev_key_idx = 0; + + if (!memcmp(data, keyrepeat, sizeof(keyrepeat))) { +- key_down(hid, appleir, appleir->current_key); +- /* +- * Remote doesn't do key up, either pull them up, in the test +- * above, or here set a timer which pulls them up after 1/8 s +- */ +- mod_timer(&appleir->key_up_timer, jiffies + HZ / 8); ++ spin_lock_irqsave(&appleir->lock, flags); ++ if (!appleir->removing) { ++ key_down(hid, appleir, appleir->current_key); ++ /* ++ * Remote doesn't do key up, either pull them up, in ++ * the test above, or here set a timer which pulls them ++ * up after 1/8 s ++ */ ++ mod_timer(&appleir->key_up_timer, jiffies + HZ / 8); ++ } ++ spin_unlock_irqrestore(&appleir->lock, flags); + goto out; + } + + if (!memcmp(data, flatbattery, sizeof(flatbattery))) { +- battery_flat(appleir); ++ spin_lock_irqsave(&appleir->lock, flags); ++ if (!appleir->removing) ++ battery_flat(appleir); ++ spin_unlock_irqrestore(&appleir->lock, flags); + /* Fall through */ + } + +@@ -318,8 +331,20 @@ fail: + static void appleir_remove(struct hid_device *hid) + { + struct appleir *appleir = hid_get_drvdata(hid); ++ unsigned long flags; ++ ++ /* ++ * Mark the driver as tearing down so that any concurrent raw_event ++ * (e.g. from a USB URB completion that hid_hw_stop() has not yet ++ * killed) and the key_up_timer softirq stop touching input_dev ++ * before hid_hw_stop() frees it via hidinput_disconnect(). ++ */ ++ spin_lock_irqsave(&appleir->lock, flags); ++ appleir->removing = true; ++ spin_unlock_irqrestore(&appleir->lock, flags); ++ ++ timer_delete_sync(&appleir->key_up_timer); + hid_hw_stop(hid); +- del_timer_sync(&appleir->key_up_timer); + } + + static const struct hid_device_id appleir_devices[] = { diff --git a/queue-5.10/hid-multitouch-fix-out-of-bounds-bit-access-on-mt_io_flags.patch b/queue-5.10/hid-multitouch-fix-out-of-bounds-bit-access-on-mt_io_flags.patch new file mode 100644 index 0000000000..a6b4e58e1d --- /dev/null +++ b/queue-5.10/hid-multitouch-fix-out-of-bounds-bit-access-on-mt_io_flags.patch @@ -0,0 +1,158 @@ +From stable+bounces-277173-greg=kroah.com@vger.kernel.org Fri Jul 17 20:19:42 2026 +From: Sasha Levin +Date: Fri, 17 Jul 2026 14:11:33 -0400 +Subject: HID: multitouch: fix out-of-bounds bit access on mt_io_flags +To: stable@vger.kernel.org +Cc: Trung Nguyen , Benjamin Tissoires , Sasha Levin +Message-ID: <20260717181133.2086215-2-sashal@kernel.org> + +From: Trung Nguyen + +[ Upstream commit 8813b0612275cc61fe9e6603d0ee019247ade6be ] + +mt_io_flags is a single unsigned long, but mt_process_slot(), +mt_release_pending_palms() and mt_release_contacts() use it as a +per-slot bitmap indexed by the slot number. That slot number is only +bounded by td->maxcontacts, which is taken from the device's +ContactCountMaximum feature report and can be up to 255, not by +BITS_PER_LONG. + +As a result, a multitouch device that advertises a large contact count +makes set_bit()/clear_bit() operate past the mt_io_flags word and +corrupt the adjacent members of struct mt_device. The sticky-fingers +release timer is the easiest way to reach this. mt_release_contacts() +runs + + for (i = 0; i < mt->num_slots; i++) + clear_bit(i, &td->mt_io_flags); + +with num_slots == maxcontacts. For maxcontacts around 250 the loop +clears the bits that overlap td->applications.next, zeroing that list +head, and the list_for_each_entry() that immediately follows then +dereferences NULL. The kernel panics from timer (softirq) context. On a +KASAN build this shows up as a general protection fault in +mt_release_contacts() with a null-ptr-deref at offset 0x58, which is +offsetof(struct mt_application, num_received). + +The state is reachable from an untrusted USB or Bluetooth HID +multitouch device; no local privileges are required. + +Store the per-slot active state in a separately allocated bitmap sized +for maxcontacts, the same pattern already used for pending_palm_slots, +and keep only MT_IO_FLAGS_RUNNING in mt_io_flags. The two +"mt_io_flags & MT_IO_SLOTS_MASK" arming checks become +bitmap_empty(td->active_slots, td->maxcontacts). + +Move MT_IO_FLAGS_RUNNING back to bit 0. It was bumped to bit 32 by the +same commit to leave the low byte for the slot bits; with the slot bits +gone it fits in bit 0 again, which also keeps it within the unsigned +long on 32-bit. + +Fixes: 46f781e0d151 ("HID: multitouch: fix sticky fingers") +Cc: stable@vger.kernel.org +Signed-off-by: Trung Nguyen +Signed-off-by: Benjamin Tissoires +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/hid/hid-multitouch.c | 32 ++++++++++++++++++++------------ + 1 file changed, 20 insertions(+), 12 deletions(-) + +--- a/drivers/hid/hid-multitouch.c ++++ b/drivers/hid/hid-multitouch.c +@@ -31,6 +31,7 @@ + * [1] https://gitlab.freedesktop.org/libevdev/hid-tools + */ + ++#include + #include + #include + #include +@@ -81,8 +82,7 @@ enum latency_mode { + HID_LATENCY_HIGH = 1, + }; + +-#define MT_IO_SLOTS_MASK GENMASK(7, 0) /* reserve first 8 bits for slot tracking */ +-#define MT_IO_FLAGS_RUNNING 32 ++#define MT_IO_FLAGS_RUNNING 0 + + static const bool mtrue = true; /* default for true */ + static const bool mfalse; /* default for false */ +@@ -158,10 +158,9 @@ struct mt_device { + struct mt_class mtclass; /* our mt device class */ + struct timer_list release_timer; /* to release sticky fingers */ + struct hid_device *hdev; /* hid_device we're attached to */ +- unsigned long mt_io_flags; /* mt flags (MT_IO_FLAGS_RUNNING) +- * first 8 bits are reserved for keeping the slot +- * states, this is fine because we only support up +- * to 250 slots (MT_MAX_MAXCONTACT) ++ unsigned long mt_io_flags; /* mt flags (MT_IO_FLAGS_RUNNING) */ ++ unsigned long *active_slots; /* bitmap of slots with an active ++ * contact, sized for maxcontacts + */ + __u8 inputmode_value; /* InputMode HID feature value */ + __u8 maxcontacts; +@@ -915,7 +914,7 @@ static void mt_release_pending_palms(str + + for_each_set_bit(slotnum, app->pending_palm_slots, td->maxcontacts) { + clear_bit(slotnum, app->pending_palm_slots); +- clear_bit(slotnum, &td->mt_io_flags); ++ clear_bit(slotnum, td->active_slots); + + input_mt_slot(input, slotnum); + input_mt_report_slot_inactive(input); +@@ -1100,9 +1099,9 @@ static int mt_process_slot(struct mt_dev + input_event(input, EV_ABS, ABS_MT_TOUCH_MAJOR, major); + input_event(input, EV_ABS, ABS_MT_TOUCH_MINOR, minor); + +- set_bit(slotnum, &td->mt_io_flags); ++ set_bit(slotnum, td->active_slots); + } else { +- clear_bit(slotnum, &td->mt_io_flags); ++ clear_bit(slotnum, td->active_slots); + } + + return 0; +@@ -1237,7 +1236,7 @@ static void mt_touch_report(struct hid_d + * defect. + */ + if (app->quirks & MT_QUIRK_STICKY_FINGERS) { +- if (td->mt_io_flags & MT_IO_SLOTS_MASK) ++ if (!bitmap_empty(td->active_slots, td->maxcontacts)) + mod_timer(&td->release_timer, + jiffies + msecs_to_jiffies(100)); + else +@@ -1277,6 +1276,15 @@ static int mt_touch_input_configured(str + if (td->is_buttonpad) + __set_bit(INPUT_PROP_BUTTONPAD, input->propbit); + ++ if (!td->active_slots) { ++ td->active_slots = devm_kcalloc(&td->hdev->dev, ++ BITS_TO_LONGS(td->maxcontacts), ++ sizeof(long), ++ GFP_KERNEL); ++ if (!td->active_slots) ++ return -ENOMEM; ++ } ++ + app->pending_palm_slots = devm_kcalloc(&hi->input->dev, + BITS_TO_LONGS(td->maxcontacts), + sizeof(long), +@@ -1655,7 +1663,7 @@ static void mt_release_contacts(struct h + for (i = 0; i < mt->num_slots; i++) { + input_mt_slot(input_dev, i); + input_mt_report_slot_inactive(input_dev); +- clear_bit(i, &td->mt_io_flags); ++ clear_bit(i, td->active_slots); + } + input_mt_sync_frame(input_dev); + input_sync(input_dev); +@@ -1678,7 +1686,7 @@ static void mt_expired_timeout(struct ti + */ + if (test_and_set_bit_lock(MT_IO_FLAGS_RUNNING, &td->mt_io_flags)) + return; +- if (td->mt_io_flags & MT_IO_SLOTS_MASK) ++ if (!bitmap_empty(td->active_slots, td->maxcontacts)) + mt_release_contacts(hdev); + clear_bit_unlock(MT_IO_FLAGS_RUNNING, &td->mt_io_flags); + } diff --git a/queue-5.10/iio-common-st_sensors-honour-channel-endianness-in-read_axis_data.patch b/queue-5.10/iio-common-st_sensors-honour-channel-endianness-in-read_axis_data.patch new file mode 100644 index 0000000000..f53aa667e3 --- /dev/null +++ b/queue-5.10/iio-common-st_sensors-honour-channel-endianness-in-read_axis_data.patch @@ -0,0 +1,109 @@ +From stable+bounces-274099-greg=kroah.com@vger.kernel.org Tue Jul 14 05:05:01 2026 +From: Sasha Levin +Date: Mon, 13 Jul 2026 23:04:48 -0400 +Subject: iio: common: st_sensors: honour channel endianness in read_axis_data +To: stable@vger.kernel.org +Cc: Herman van Hazendonk , Andy Shevchenko , Jonathan Cameron , Sasha Levin +Message-ID: <20260714030448.2382602-2-sashal@kernel.org> + +From: Herman van Hazendonk + +[ Upstream commit 55052184ac9011db2ea983e54d6c21f0b1079a12 ] + +st_sensors_read_axis_data() unconditionally decoded multi-byte +results with get_unaligned_le16() / get_unaligned_le24() regardless +of the channel's declared scan_type.endianness. + +For every ST sensor that has used this helper since it was introduced +this happened to be fine because the ST IMU/accel/gyro/pressure +families publish their data registers as little-endian and the +channel specs in those drivers declare IIO_LE accordingly. + +The LSM303DLH magnetometer however publishes its X/Y/Z output as a +pair of big-endian bytes (the H register sits at the lower address, +0x03/0x05/0x07, and the L register immediately after), and its +channel specs in st_magn_core.c correctly declare IIO_BE -- but +read_axis_data() ignored that and decoded as little-endian, swapping +the high and low bytes of every magnetometer sample. The LSM303DLHC +and LSM303DLM share the same st_magn_16bit_channels (IIO_BE) and +were therefore byte-swapped by the same bug; users of those parts +will see different in_magn_*_raw values after this fix lands. + +The bug is most visible on a stationary chip: in earth's field the +true X reading is small and the high byte sits at 0x00, so swapping +the bytes pins sysfs X at exactly the low byte's pattern (e.g. 0x00F0 += 240). Y and Z still appear "to vary" because their magnitudes are +larger and the noise in the low byte produces big swings in the +swapped high byte: + + before (LSM303DLH flat, sysfs in_magn_*_raw): + X=240 (stuck), Y= 12032..23296, Z=-16128..-9728 + + after (direct i2c-dev big-endian decode, same chip same orientation): + X≈-4096, Y≈210, Z≈80 (sensible values reflecting earth's + ambient field at low gauss range) + +Fix read_axis_data() to dispatch on ch->scan_type.endianness and +call get_unaligned_be16() / get_unaligned_be24() when the channel +declares IIO_BE. Existing IIO_LE consumers (st_accel, st_gyro, +st_pressure, st_lsm6dsx and others) are unaffected because their +channel specs already declare IIO_LE and the LE path is unchanged. + +While restructuring the branches, replace the previously implicit +silent-success-with-uninitialised-*data fall-through for +byte_for_channel outside 1..3 with an explicit return -EINVAL. No +in-tree ST sensor publishes such a channel, but the new behaviour +is strictly safer than handing userspace garbage. + +Fixes: 23491b513bcd ("iio:common: Add STMicroelectronics common library") +Cc: stable@vger.kernel.org +Assisted-by: Claude:claude-opus-4-7 sparse smatch clang-analyzer coccinelle checkpatch +Assisted-by: Sashiko:claude-opus-4-7 +Signed-off-by: Herman van Hazendonk +Reviewed-by: Andy Shevchenko +Signed-off-by: Jonathan Cameron +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/iio/common/st_sensors/st_sensors_core.c | 23 +++++++++++++++++------ + 1 file changed, 17 insertions(+), 6 deletions(-) + +--- a/drivers/iio/common/st_sensors/st_sensors_core.c ++++ b/drivers/iio/common/st_sensors/st_sensors_core.c +@@ -527,6 +527,7 @@ static int st_sensors_read_axis_data(str + u8 *outdata; + struct st_sensor_data *sdata = iio_priv(indio_dev); + unsigned int byte_for_channel; ++ u32 tmp; + + byte_for_channel = DIV_ROUND_UP(ch->scan_type.realbits + + ch->scan_type.shift, 8); +@@ -539,12 +540,22 @@ static int st_sensors_read_axis_data(str + if (err < 0) + goto st_sensors_free_memory; + +- if (byte_for_channel == 1) +- *data = (s8)*outdata; +- else if (byte_for_channel == 2) +- *data = (s16)get_unaligned_le16(outdata); +- else if (byte_for_channel == 3) +- *data = (s32)sign_extend32(get_unaligned_le24(outdata), 23); ++ if (byte_for_channel == 1) { ++ tmp = *outdata; ++ } else if (byte_for_channel == 2) { ++ if (ch->scan_type.endianness == IIO_BE) ++ tmp = get_unaligned_be16(outdata); ++ else ++ tmp = get_unaligned_le16(outdata); ++ } else if (byte_for_channel == 3) { ++ if (ch->scan_type.endianness == IIO_BE) ++ tmp = get_unaligned_be24(outdata); ++ else ++ tmp = get_unaligned_le24(outdata); ++ } else { ++ return -EINVAL; ++ } ++ *data = sign_extend32(tmp, BYTES_TO_BITS(byte_for_channel) - 1); + + st_sensors_free_memory: + kfree(outdata); diff --git a/queue-5.10/iio-hid-sensor-rotation-fix-stale-or-zero-output-when-reading-raw-values.patch b/queue-5.10/iio-hid-sensor-rotation-fix-stale-or-zero-output-when-reading-raw-values.patch new file mode 100644 index 0000000000..faa401eb89 --- /dev/null +++ b/queue-5.10/iio-hid-sensor-rotation-fix-stale-or-zero-output-when-reading-raw-values.patch @@ -0,0 +1,89 @@ +From stable+bounces-273973-greg=kroah.com@vger.kernel.org Mon Jul 13 21:33:45 2026 +From: Sasha Levin +Date: Mon, 13 Jul 2026 15:33:36 -0400 +Subject: iio: hid-sensor-rotation: Fix stale or zero output when reading raw values +To: stable@vger.kernel.org +Cc: Zhang Lixu , Andy Shevchenko , Stable@vger.kernel.org, Jonathan Cameron , Sasha Levin +Message-ID: <20260713193336.2037451-2-sashal@kernel.org> + +From: Zhang Lixu + +[ Upstream commit 3ce8d099e0afc5a7da75a2007a67f67c4f5a4af1 ] + +When reading the raw quaternion attribute (in_rot_quaternion_raw), the +driver currently returns either all zeros (if the sensor was never enabled) +or stale data (if the sensor was previously enabled) because it reads from +the internal buffer without explicitly requesting a new sample from the +sensor. + +To fix this, power up the sensor, call sensor_hub_input_attr_read_values() +to issue a synchronous GET_REPORT and receive the full quaternion data +directly into a local buffer, then decode the four components. + +Fixes: fc18dddc0625 ("iio: hid-sensors: Added device rotation support") +Signed-off-by: Zhang Lixu +Reviewed-by: Andy Shevchenko +Cc: +Signed-off-by: Jonathan Cameron +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/iio/orientation/hid-sensor-rotation.c | 40 ++++++++++++++++++++++++-- + 1 file changed, 38 insertions(+), 2 deletions(-) + +--- a/drivers/iio/orientation/hid-sensor-rotation.c ++++ b/drivers/iio/orientation/hid-sensor-rotation.c +@@ -60,6 +60,13 @@ static int dev_rot_read_raw(struct iio_d + long mask) + { + struct dev_rot_state *rot_state = iio_priv(indio_dev); ++ struct hid_sensor_hub_device *hsdev = rot_state->common_attributes.hsdev; ++ struct hid_sensor_hub_attribute_info *info = &rot_state->quaternion; ++ u32 usage_id = HID_USAGE_SENSOR_ORIENT_QUATERNION; ++ union { ++ s16 val16[4]; ++ s32 val32[4]; ++ } raw_buf; + int ret_type; + int i; + +@@ -69,8 +76,37 @@ static int dev_rot_read_raw(struct iio_d + switch (mask) { + case IIO_CHAN_INFO_RAW: + if (size >= 4) { +- for (i = 0; i < 4; ++i) +- vals[i] = rot_state->sampled_vals[i]; ++ if (info->size <= 0 || info->size > sizeof(raw_buf)) ++ return -EINVAL; ++ ++ hid_sensor_power_state(&rot_state->common_attributes, true); ++ ++ ret_type = sensor_hub_input_attr_read_values(hsdev, ++ hsdev->usage, ++ usage_id, ++ info->report_id, ++ SENSOR_HUB_SYNC, ++ info->size, ++ (u8 *)&raw_buf); ++ ++ hid_sensor_power_state(&rot_state->common_attributes, false); ++ ++ if (ret_type < 0) ++ return ret_type; ++ ++ switch (info->size) { ++ case sizeof(raw_buf.val16): ++ for (i = 0; i < ARRAY_SIZE(raw_buf.val16); i++) ++ vals[i] = raw_buf.val16[i]; ++ break; ++ case sizeof(raw_buf.val32): ++ for (i = 0; i < ARRAY_SIZE(raw_buf.val32); i++) ++ vals[i] = raw_buf.val32[i]; ++ break; ++ default: ++ return -EINVAL; ++ } ++ + ret_type = IIO_VAL_INT_MULTIPLE; + *val_len = 4; + } else diff --git a/queue-5.10/iio-imu-adis-add-irqf_no_thread-to-non-fifo-trigger-irq.patch b/queue-5.10/iio-imu-adis-add-irqf_no_thread-to-non-fifo-trigger-irq.patch new file mode 100644 index 0000000000..ff71cc3d1e --- /dev/null +++ b/queue-5.10/iio-imu-adis-add-irqf_no_thread-to-non-fifo-trigger-irq.patch @@ -0,0 +1,49 @@ +From stable+bounces-273955-greg=kroah.com@vger.kernel.org Mon Jul 13 20:33:39 2026 +From: Sasha Levin +Date: Mon, 13 Jul 2026 14:33:32 -0400 +Subject: iio: imu: adis: add IRQF_NO_THREAD to non-FIFO trigger IRQ +To: stable@vger.kernel.org +Cc: Runyu Xiao , Jonathan Cameron , Sasha Levin +Message-ID: <20260713183332.1950471-1-sashal@kernel.org> + +From: Runyu Xiao + +[ Upstream commit 6e1b9bff1202da55c464e36bd34a2b6863d7fe30 ] + +devm_adis_probe_trigger() registers iio_trigger_generic_data_rdy_poll() +through devm_request_irq() on the non-FIFO path, but it does not add +IRQF_NO_THREAD to the IRQ flags. + +When the kernel is booted with forced IRQ threading, the parent IRQ can +otherwise be threaded by the IRQ core and the subsequent IIO trigger +child IRQ is then dispatched from irq/... thread context instead of +hardirq context. Because iio_trigger_generic_data_rdy_poll() +immediately drives iio_trigger_poll(), this violates the hardirq-only +IIO trigger helper contract and can push downstream trigger consumers +through the wrong execution context. + +Add IRQF_NO_THREAD on top of the existing adis->irq_flag value for the +non-FIFO request_irq() path, while preserving the current trigger +polarity and IRQF_NO_AUTOEN behavior. + +Fixes: fec86c6b8369 ("iio: imu: adis: Add Managed device functions") +Cc: stable@vger.kernel.org +Signed-off-by: Runyu Xiao +Signed-off-by: Jonathan Cameron +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/iio/imu/adis_trigger.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/iio/imu/adis_trigger.c ++++ b/drivers/iio/imu/adis_trigger.c +@@ -84,7 +84,7 @@ int devm_adis_probe_trigger(struct adis + + ret = devm_request_irq(&adis->spi->dev, adis->spi->irq, + &iio_trigger_generic_data_rdy_poll, +- adis->irq_flag, ++ adis->irq_flag | IRQF_NO_THREAD, + indio_dev->name, + adis->trig); + if (ret) diff --git a/queue-5.10/iio-imu-inv_icm42600-fix-timestamping-by-limiting-fifo-reading.patch b/queue-5.10/iio-imu-inv_icm42600-fix-timestamping-by-limiting-fifo-reading.patch new file mode 100644 index 0000000000..2863c76002 --- /dev/null +++ b/queue-5.10/iio-imu-inv_icm42600-fix-timestamping-by-limiting-fifo-reading.patch @@ -0,0 +1,72 @@ +From stable+bounces-274096-greg=kroah.com@vger.kernel.org Tue Jul 14 05:04:57 2026 +From: Sasha Levin +Date: Mon, 13 Jul 2026 23:04:44 -0400 +Subject: iio: imu: inv_icm42600: fix timestamping by limiting FIFO reading +To: stable@vger.kernel.org +Cc: Jean-Baptiste Maneyrol , Jonathan Cameron , Sasha Levin +Message-ID: <20260714030444.2382550-8-sashal@kernel.org> + +From: Jean-Baptiste Maneyrol + +[ Upstream commit affe3f077d7a4eeb25937f5323ff059a54b4712c ] + +Timestamps are made by measuring the chip clock using the watermark +interrupts. If we read more than watermark samples as done today, we +are reducing the period between interrupts and distort the time +measurement. Fix that by reading only watermark samples in the +interrupt case. + +Fixes: 7f85e42a6c54 ("iio: imu: inv_icm42600: add buffer support in iio devices") +Cc: stable@vger.kernel.org +Signed-off-by: Jean-Baptiste Maneyrol +Signed-off-by: Jonathan Cameron +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/iio/imu/inv_icm42600/inv_icm42600_buffer.c | 9 +++++---- + drivers/iio/imu/inv_icm42600/inv_icm42600_buffer.h | 1 + + 2 files changed, 6 insertions(+), 4 deletions(-) + +--- a/drivers/iio/imu/inv_icm42600/inv_icm42600_buffer.c ++++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_buffer.c +@@ -257,6 +257,7 @@ int inv_icm42600_buffer_update_watermark + + /* compute watermark value in bytes */ + wm_size = watermark * packet_size; ++ st->fifo.watermark.value = watermark; + + /* changing FIFO watermark requires to turn off watermark interrupt */ + ret = regmap_update_bits_check(st->map, INV_ICM42600_REG_INT_SOURCE0, +@@ -476,11 +477,10 @@ int inv_icm42600_buffer_fifo_read(struct + st->fifo.nb.accel = 0; + st->fifo.nb.total = 0; + +- /* compute maximum FIFO read size */ ++ /* compute maximum FIFO read size (watermark for max = 0 interrupt case) */ + if (max == 0) +- max_count = sizeof(st->fifo.data); +- else +- max_count = max * inv_icm42600_get_packet_size(st->fifo.en); ++ max = st->fifo.watermark.value; ++ max_count = max * inv_icm42600_get_packet_size(st->fifo.en); + + /* read FIFO count value */ + raw_fifo_count = (__be16 *)st->buffer; +@@ -592,6 +592,7 @@ int inv_icm42600_buffer_init(struct inv_ + + st->fifo.watermark.eff_gyro = 1; + st->fifo.watermark.eff_accel = 1; ++ st->fifo.watermark.value = 1; + + /* + * Default FIFO configuration (bits 7 to 5) +--- a/drivers/iio/imu/inv_icm42600/inv_icm42600_buffer.h ++++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_buffer.h +@@ -34,6 +34,7 @@ struct inv_icm42600_fifo { + unsigned int accel; + unsigned int eff_gyro; + unsigned int eff_accel; ++ unsigned int value; + } watermark; + size_t count; + struct { diff --git a/queue-5.10/iio-imu-inv_icm42600-make-timestamp-module-chip-independent.patch b/queue-5.10/iio-imu-inv_icm42600-make-timestamp-module-chip-independent.patch new file mode 100644 index 0000000000..7cc09b8b00 --- /dev/null +++ b/queue-5.10/iio-imu-inv_icm42600-make-timestamp-module-chip-independent.patch @@ -0,0 +1,103 @@ +From stable+bounces-274090-greg=kroah.com@vger.kernel.org Tue Jul 14 05:06:17 2026 +From: Sasha Levin +Date: Mon, 13 Jul 2026 23:04:37 -0400 +Subject: iio: imu: inv_icm42600: make timestamp module chip independent +To: stable@vger.kernel.org +Cc: Jean-Baptiste Maneyrol , Andy Shevchenko , Jonathan Cameron , Sasha Levin +Message-ID: <20260714030444.2382550-1-sashal@kernel.org> + +From: Jean-Baptiste Maneyrol + +[ Upstream commit 6e9f2d8375cb24ba75e02e0272e9164d06a1522e ] + +Move icm42600 dependent function inside the core module. +Do some headers cleanup at the same time. + +Signed-off-by: Jean-Baptiste Maneyrol +Reviewed-by: Andy Shevchenko +Link: https://lore.kernel.org/r/20230606162147.79667-2-inv.git-commit@tdk.com +Signed-off-by: Jonathan Cameron +Stable-dep-of: affe3f077d7a ("iio: imu: inv_icm42600: fix timestamping by limiting FIFO reading") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/iio/imu/inv_icm42600/inv_icm42600_core.c | 11 +++++++++++ + drivers/iio/imu/inv_icm42600/inv_icm42600_timestamp.c | 14 +------------- + drivers/iio/imu/inv_icm42600/inv_icm42600_timestamp.h | 6 ------ + 3 files changed, 12 insertions(+), 19 deletions(-) + +--- a/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c ++++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c +@@ -522,6 +522,17 @@ static int inv_icm42600_irq_init(struct + "inv_icm42600", st); + } + ++static int inv_icm42600_timestamp_setup(struct inv_icm42600_state *st) ++{ ++ unsigned int val; ++ ++ /* enable timestamp register */ ++ val = INV_ICM42600_TMST_CONFIG_TMST_TO_REGS_EN | ++ INV_ICM42600_TMST_CONFIG_TMST_EN; ++ return regmap_update_bits(st->map, INV_ICM42600_REG_TMST_CONFIG, ++ INV_ICM42600_TMST_CONFIG_MASK, val); ++} ++ + static int inv_icm42600_enable_regulator_vddio(struct inv_icm42600_state *st) + { + int ret; +--- a/drivers/iio/imu/inv_icm42600/inv_icm42600_timestamp.c ++++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_timestamp.c +@@ -3,11 +3,10 @@ + * Copyright (C) 2020 Invensense, Inc. + */ + ++#include + #include +-#include + #include + +-#include "inv_icm42600.h" + #include "inv_icm42600_timestamp.h" + + /* internal chip period is 32kHz, 31250ns */ +@@ -56,17 +55,6 @@ void inv_icm42600_timestamp_init(struct + inv_update_acc(&ts->chip_period, INV_ICM42600_TIMESTAMP_PERIOD); + } + +-int inv_icm42600_timestamp_setup(struct inv_icm42600_state *st) +-{ +- unsigned int val; +- +- /* enable timestamp register */ +- val = INV_ICM42600_TMST_CONFIG_TMST_TO_REGS_EN | +- INV_ICM42600_TMST_CONFIG_TMST_EN; +- return regmap_update_bits(st->map, INV_ICM42600_REG_TMST_CONFIG, +- INV_ICM42600_TMST_CONFIG_MASK, val); +-} +- + int inv_icm42600_timestamp_update_odr(struct inv_icm42600_timestamp *ts, + uint32_t period, bool fifo) + { +--- a/drivers/iio/imu/inv_icm42600/inv_icm42600_timestamp.h ++++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_timestamp.h +@@ -6,10 +6,6 @@ + #ifndef INV_ICM42600_TIMESTAMP_H_ + #define INV_ICM42600_TIMESTAMP_H_ + +-#include +- +-struct inv_icm42600_state; +- + /** + * struct inv_icm42600_timestamp_interval - timestamps interval + * @lo: interval lower bound +@@ -53,8 +49,6 @@ struct inv_icm42600_timestamp { + void inv_icm42600_timestamp_init(struct inv_icm42600_timestamp *ts, + uint32_t period); + +-int inv_icm42600_timestamp_setup(struct inv_icm42600_state *st); +- + int inv_icm42600_timestamp_update_odr(struct inv_icm42600_timestamp *ts, + uint32_t period, bool fifo); + diff --git a/queue-5.10/iio-imu-inv_icm42600-stabilized-timestamp-in-interrupt.patch b/queue-5.10/iio-imu-inv_icm42600-stabilized-timestamp-in-interrupt.patch new file mode 100644 index 0000000000..30328b687d --- /dev/null +++ b/queue-5.10/iio-imu-inv_icm42600-stabilized-timestamp-in-interrupt.patch @@ -0,0 +1,116 @@ +From stable+bounces-274095-greg=kroah.com@vger.kernel.org Tue Jul 14 05:06:38 2026 +From: Sasha Levin +Date: Mon, 13 Jul 2026 23:04:43 -0400 +Subject: iio: imu: inv_icm42600: stabilized timestamp in interrupt +To: stable@vger.kernel.org +Cc: Jean-Baptiste Maneyrol , Jonathan Cameron , Sasha Levin +Message-ID: <20260714030444.2382550-7-sashal@kernel.org> + +From: Jean-Baptiste Maneyrol + +[ Upstream commit d7bd473632d07f8a54655c270c0940cc3671c548 ] + +Use IRQF_ONESHOT flag to ensure the timestamp is not updated in the +hard handler during the thread handler. And compute and use the +effective watermark value that correspond to this first timestamp. + +This way we can ensure the timestamp is always corresponding to the +value used by the timestamping mechanism. Otherwise, it is possible +that between FIFO count read and FIFO processing the timestamp is +overwritten in the hard handler. + +Fixes: ec74ae9fd37c ("iio: imu: inv_icm42600: add accurate timestamping") +Cc: stable@vger.kernel.org +Signed-off-by: Jean-Baptiste Maneyrol +Link: https://lore.kernel.org/r/20240529154717.651863-1-inv.git-commit@tdk.com +Signed-off-by: Jonathan Cameron +Stable-dep-of: affe3f077d7a ("iio: imu: inv_icm42600: fix timestamping by limiting FIFO reading") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/iio/imu/inv_icm42600/inv_icm42600_buffer.c | 19 +++++++++++++++++-- + drivers/iio/imu/inv_icm42600/inv_icm42600_buffer.h | 2 ++ + drivers/iio/imu/inv_icm42600/inv_icm42600_core.c | 1 + + 3 files changed, 20 insertions(+), 2 deletions(-) + +--- a/drivers/iio/imu/inv_icm42600/inv_icm42600_buffer.c ++++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_buffer.c +@@ -222,10 +222,15 @@ int inv_icm42600_buffer_update_watermark + latency_accel = period_accel * wm_accel; + + /* 0 value for watermark means that the sensor is turned off */ ++ if (wm_gyro == 0 && wm_accel == 0) ++ return 0; ++ + if (latency_gyro == 0) { + watermark = wm_accel; ++ st->fifo.watermark.eff_accel = wm_accel; + } else if (latency_accel == 0) { + watermark = wm_gyro; ++ st->fifo.watermark.eff_gyro = wm_gyro; + } else { + /* compute the smallest latency that is a multiple of both */ + if (latency_gyro <= latency_accel) +@@ -241,6 +246,13 @@ int inv_icm42600_buffer_update_watermark + watermark = latency / period; + if (watermark < 1) + watermark = 1; ++ /* update effective watermark */ ++ st->fifo.watermark.eff_gyro = latency / period_gyro; ++ if (st->fifo.watermark.eff_gyro < 1) ++ st->fifo.watermark.eff_gyro = 1; ++ st->fifo.watermark.eff_accel = latency / period_accel; ++ if (st->fifo.watermark.eff_accel < 1) ++ st->fifo.watermark.eff_accel = 1; + } + + /* compute watermark value in bytes */ +@@ -517,7 +529,7 @@ int inv_icm42600_buffer_fifo_parse(struc + /* handle gyroscope timestamp and FIFO data parsing */ + if (st->fifo.nb.gyro > 0) { + ts = iio_priv(st->indio_gyro); +- inv_sensors_timestamp_interrupt(ts, st->fifo.nb.gyro, ++ inv_sensors_timestamp_interrupt(ts, st->fifo.watermark.eff_gyro, + st->timestamp.gyro); + ret = inv_icm42600_gyro_parse_fifo(st->indio_gyro); + if (ret) +@@ -527,7 +539,7 @@ int inv_icm42600_buffer_fifo_parse(struc + /* handle accelerometer timestamp and FIFO data parsing */ + if (st->fifo.nb.accel > 0) { + ts = iio_priv(st->indio_accel); +- inv_sensors_timestamp_interrupt(ts, st->fifo.nb.accel, ++ inv_sensors_timestamp_interrupt(ts, st->fifo.watermark.eff_accel, + st->timestamp.accel); + ret = inv_icm42600_accel_parse_fifo(st->indio_accel); + if (ret) +@@ -578,6 +590,9 @@ int inv_icm42600_buffer_init(struct inv_ + unsigned int val; + int ret; + ++ st->fifo.watermark.eff_gyro = 1; ++ st->fifo.watermark.eff_accel = 1; ++ + /* + * Default FIFO configuration (bits 7 to 5) + * - use invalid value +--- a/drivers/iio/imu/inv_icm42600/inv_icm42600_buffer.h ++++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_buffer.h +@@ -32,6 +32,8 @@ struct inv_icm42600_fifo { + struct { + unsigned int gyro; + unsigned int accel; ++ unsigned int eff_gyro; ++ unsigned int eff_accel; + } watermark; + size_t count; + struct { +--- a/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c ++++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c +@@ -518,6 +518,7 @@ static int inv_icm42600_irq_init(struct + if (ret) + return ret; + ++ irq_type |= IRQF_ONESHOT; + return devm_request_threaded_irq(dev, irq, inv_icm42600_irq_timestamp, + inv_icm42600_irq_handler, irq_type, + "inv_icm42600", st); diff --git a/queue-5.10/iio-imu-inv_mpu6050-use-the-common-inv_sensors-timestamp-module.patch b/queue-5.10/iio-imu-inv_mpu6050-use-the-common-inv_sensors-timestamp-module.patch new file mode 100644 index 0000000000..39a36468d5 --- /dev/null +++ b/queue-5.10/iio-imu-inv_mpu6050-use-the-common-inv_sensors-timestamp-module.patch @@ -0,0 +1,307 @@ +From stable+bounces-274098-greg=kroah.com@vger.kernel.org Tue Jul 14 05:05:00 2026 +From: Sasha Levin +Date: Mon, 13 Jul 2026 23:04:40 -0400 +Subject: iio: imu: inv_mpu6050: use the common inv_sensors timestamp module +To: stable@vger.kernel.org +Cc: Jean-Baptiste Maneyrol , Andy Shevchenko , Jonathan Cameron , Sasha Levin +Message-ID: <20260714030444.2382550-4-sashal@kernel.org> + +From: Jean-Baptiste Maneyrol + +[ Upstream commit 111e1abd00455971f6a568900f033cbddec9d4e5 ] + +Replace timestamping by the new common inv_sensors timestamp +module. The principle behind is the same but the implementation in +the new module is far better providing less jitter and a better +estimation. + +Signed-off-by: Jean-Baptiste Maneyrol +Reviewed-by: Andy Shevchenko +Link: https://lore.kernel.org/r/20230606162147.79667-5-inv.git-commit@tdk.com +Signed-off-by: Jonathan Cameron +Stable-dep-of: affe3f077d7a ("iio: imu: inv_icm42600: fix timestamping by limiting FIFO reading") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/iio/imu/inv_mpu6050/Kconfig | 1 + drivers/iio/imu/inv_mpu6050/inv_mpu_core.c | 30 +++++++-- + drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h | 18 ++--- + drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c | 83 ++------------------------ + drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c | 6 + + 5 files changed, 45 insertions(+), 93 deletions(-) + +--- a/drivers/iio/imu/inv_mpu6050/Kconfig ++++ b/drivers/iio/imu/inv_mpu6050/Kconfig +@@ -7,6 +7,7 @@ config INV_MPU6050_IIO + tristate + select IIO_BUFFER + select IIO_TRIGGERED_BUFFER ++ select IIO_INV_SENSORS_TIMESTAMP + + config INV_MPU6050_I2C + tristate "Invensense MPU6050 devices (I2C)" +--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c ++++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c +@@ -12,12 +12,15 @@ + #include + #include + #include +-#include + #include + #include + #include + #include + #include ++ ++#include ++#include ++ + #include "inv_mpu_iio.h" + #include "inv_mpu_magn.h" + +@@ -481,6 +484,7 @@ static int inv_mpu6050_init_config(struc + int result; + u8 d; + struct inv_mpu6050_state *st = iio_priv(indio_dev); ++ struct inv_sensors_timestamp_chip timestamp; + + result = inv_mpu6050_set_gyro_fsr(st, st->chip_config.fsr); + if (result) +@@ -504,12 +508,12 @@ static int inv_mpu6050_init_config(struc + if (result) + return result; + +- /* +- * Internal chip period is 1ms (1kHz). +- * Let's use at the beginning the theorical value before measuring +- * with interrupt timestamps. +- */ +- st->chip_period = NSEC_PER_MSEC; ++ /* clock jitter is +/- 2% */ ++ timestamp.clock_period = NSEC_PER_SEC / INV_MPU6050_INTERNAL_FREQ_HZ; ++ timestamp.jitter = 20; ++ timestamp.init_period = ++ NSEC_PER_SEC / INV_MPU6050_DIVIDER_TO_FIFO_RATE(st->chip_config.divider); ++ inv_sensors_timestamp_init(&st->timestamp, ×tamp); + + /* magn chip init, noop if not present in the chip */ + result = inv_mpu_magn_probe(st); +@@ -900,6 +904,8 @@ inv_mpu6050_fifo_rate_store(struct devic + const char *buf, size_t count) + { + int fifo_rate; ++ u32 fifo_period; ++ bool fifo_on; + u8 d; + int result; + struct iio_dev *indio_dev = dev_to_iio_dev(dev); +@@ -916,12 +922,21 @@ inv_mpu6050_fifo_rate_store(struct devic + d = INV_MPU6050_FIFO_RATE_TO_DIVIDER(fifo_rate); + /* compute back the fifo rate to handle truncation cases */ + fifo_rate = INV_MPU6050_DIVIDER_TO_FIFO_RATE(d); ++ fifo_period = NSEC_PER_SEC / fifo_rate; + + mutex_lock(&st->lock); + if (d == st->chip_config.divider) { + result = 0; + goto fifo_rate_fail_unlock; + } ++ ++ fifo_on = st->chip_config.accl_fifo_enable || ++ st->chip_config.gyro_fifo_enable || ++ st->chip_config.magn_fifo_enable; ++ result = inv_sensors_timestamp_update_odr(&st->timestamp, fifo_period, fifo_on); ++ if (result) ++ goto fifo_rate_fail_unlock; ++ + result = pm_runtime_get_sync(pdev); + if (result < 0) { + pm_runtime_put_noidle(pdev); +@@ -1741,3 +1756,4 @@ EXPORT_SYMBOL_GPL(inv_mpu_pmops); + MODULE_AUTHOR("Invensense Corporation"); + MODULE_DESCRIPTION("Invensense device MPU6050 driver"); + MODULE_LICENSE("GPL"); ++MODULE_IMPORT_NS(IIO_INV_SENSORS_TIMESTAMP); +--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h ++++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h +@@ -9,15 +9,17 @@ + #include + #include + #include +-#include +-#include ++#include + #include +-#include ++ ++#include ++#include ++#include + #include + #include + #include + #include +-#include ++#include + + /** + * struct inv_mpu6050_reg_map - Notable registers. +@@ -163,9 +165,7 @@ struct inv_mpu6050_hw { + * @map regmap pointer. + * @irq interrupt number. + * @irq_mask the int_pin_cfg mask to configure interrupt type. +- * @chip_period: chip internal period estimation (~1kHz). +- * @it_timestamp: timestamp from previous interrupt. +- * @data_timestamp: timestamp for next data sample. ++ * @timestamp: timestamping module + * @vdd_supply: VDD voltage regulator for the chip. + * @vddio_supply I/O voltage regulator for the chip. + * @magn_disabled: magnetometer disabled for backward compatibility reason. +@@ -189,9 +189,7 @@ struct inv_mpu6050_state { + int irq; + u8 irq_mask; + unsigned skip_samples; +- s64 chip_period; +- s64 it_timestamp; +- s64 data_timestamp; ++ struct inv_sensors_timestamp timestamp; + struct regulator *vdd_supply; + struct regulator *vddio_supply; + bool magn_disabled; +--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c ++++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c +@@ -13,81 +13,10 @@ + #include + #include + #include +-#include "inv_mpu_iio.h" +- +-/** +- * inv_mpu6050_update_period() - Update chip internal period estimation +- * +- * @st: driver state +- * @timestamp: the interrupt timestamp +- * @nb: number of data set in the fifo +- * +- * This function uses interrupt timestamps to estimate the chip period and +- * to choose the data timestamp to come. +- */ +-static void inv_mpu6050_update_period(struct inv_mpu6050_state *st, +- s64 timestamp, size_t nb) +-{ +- /* Period boundaries for accepting timestamp */ +- const s64 period_min = +- (NSEC_PER_MSEC * (100 - INV_MPU6050_TS_PERIOD_JITTER)) / 100; +- const s64 period_max = +- (NSEC_PER_MSEC * (100 + INV_MPU6050_TS_PERIOD_JITTER)) / 100; +- const s32 divider = INV_MPU6050_FREQ_DIVIDER(st); +- s64 delta, interval; +- bool use_it_timestamp = false; +- +- if (st->it_timestamp == 0) { +- /* not initialized, forced to use it_timestamp */ +- use_it_timestamp = true; +- } else if (nb == 1) { +- /* +- * Validate the use of it timestamp by checking if interrupt +- * has been delayed. +- * nb > 1 means interrupt was delayed for more than 1 sample, +- * so it's obviously not good. +- * Compute the chip period between 2 interrupts for validating. +- */ +- delta = div_s64(timestamp - st->it_timestamp, divider); +- if (delta > period_min && delta < period_max) { +- /* update chip period and use it timestamp */ +- st->chip_period = (st->chip_period + delta) / 2; +- use_it_timestamp = true; +- } +- } + +- if (use_it_timestamp) { +- /* +- * Manage case of multiple samples in the fifo (nb > 1): +- * compute timestamp corresponding to the first sample using +- * estimated chip period. +- */ +- interval = (nb - 1) * st->chip_period * divider; +- st->data_timestamp = timestamp - interval; +- } ++#include + +- /* save it timestamp */ +- st->it_timestamp = timestamp; +-} +- +-/** +- * inv_mpu6050_get_timestamp() - Return the current data timestamp +- * +- * @st: driver state +- * @return: current data timestamp +- * +- * This function returns the current data timestamp and prepares for next one. +- */ +-static s64 inv_mpu6050_get_timestamp(struct inv_mpu6050_state *st) +-{ +- s64 ts; +- +- /* return current data timestamp and increment */ +- ts = st->data_timestamp; +- st->data_timestamp += st->chip_period * INV_MPU6050_FREQ_DIVIDER(st); +- +- return ts; +-} ++#include "inv_mpu_iio.h" + + static int inv_reset_fifo(struct iio_dev *indio_dev) + { +@@ -121,6 +50,7 @@ irqreturn_t inv_mpu6050_read_fifo(int ir + size_t bytes_per_datum; + int result; + u16 fifo_count; ++ u32 fifo_period; + s64 timestamp; + int int_status; + size_t i, nb; +@@ -177,7 +107,10 @@ irqreturn_t inv_mpu6050_read_fifo(int ir + + /* compute and process all complete datum */ + nb = fifo_count / bytes_per_datum; +- inv_mpu6050_update_period(st, pf->timestamp, nb); ++ /* Each FIFO data contains all sensors, so same number for FIFO and sensor data */ ++ fifo_period = NSEC_PER_SEC / INV_MPU6050_DIVIDER_TO_FIFO_RATE(st->chip_config.divider); ++ inv_sensors_timestamp_interrupt(&st->timestamp, fifo_period, nb, nb, pf->timestamp); ++ inv_sensors_timestamp_apply_odr(&st->timestamp, fifo_period, nb, 0); + for (i = 0; i < nb; ++i) { + result = regmap_noinc_read(st->map, st->reg->fifo_r_w, + st->data, bytes_per_datum); +@@ -188,7 +121,7 @@ irqreturn_t inv_mpu6050_read_fifo(int ir + st->skip_samples--; + continue; + } +- timestamp = inv_mpu6050_get_timestamp(st); ++ timestamp = inv_sensors_timestamp_pop(&st->timestamp); + iio_push_to_buffers_with_timestamp(indio_dev, st->data, timestamp); + } + +--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c ++++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c +@@ -4,6 +4,9 @@ + */ + + #include ++ ++#include ++ + #include "inv_mpu_iio.h" + + static unsigned int inv_scan_query_mpu6050(struct iio_dev *indio_dev) +@@ -107,7 +110,8 @@ int inv_mpu6050_prepare_fifo(struct inv_ + int ret; + + if (enable) { +- st->it_timestamp = 0; ++ /* reset timestamping */ ++ inv_sensors_timestamp_reset(&st->timestamp); + /* reset FIFO */ + d = st->chip_config.user_ctrl | INV_MPU6050_BIT_FIFO_RST; + ret = regmap_write(st->map, st->reg->user_ctrl, d); diff --git a/queue-5.10/iio-invensense-fix-timestamp-glitches-when-switching-frequency.patch b/queue-5.10/iio-invensense-fix-timestamp-glitches-when-switching-frequency.patch new file mode 100644 index 0000000000..025e828d7a --- /dev/null +++ b/queue-5.10/iio-invensense-fix-timestamp-glitches-when-switching-frequency.patch @@ -0,0 +1,202 @@ +From stable+bounces-274094-greg=kroah.com@vger.kernel.org Tue Jul 14 05:06:33 2026 +From: Sasha Levin +Date: Mon, 13 Jul 2026 23:04:42 -0400 +Subject: iio: invensense: fix timestamp glitches when switching frequency +To: stable@vger.kernel.org +Cc: Jean-Baptiste Maneyrol , Stable@vger.kernel.org, Jonathan Cameron , Sasha Levin +Message-ID: <20260714030444.2382550-6-sashal@kernel.org> + +From: Jean-Baptiste Maneyrol + +[ Upstream commit bf8367b00c33c64a9391c262bb2e11d274c9f2a4 ] + +When a sensor is running and there is a FIFO frequency change due to +another sensor turned on/off, there are glitches on timestamp. Fix that +by using only interrupt timestamp when there is the corresponding sensor +data in the FIFO. + +Delete FIFO period handling and simplify internal functions. + +Update integration inside inv_mpu6050 and inv_icm42600 drivers. + +Fixes: 0ecc363ccea7 ("iio: make invensense timestamp module generic") +Cc: Stable@vger.kernel.org +Signed-off-by: Jean-Baptiste Maneyrol +Link: https://lore.kernel.org/r/20240426094835.138389-1-inv.git-commit@tdk.com +Signed-off-by: Jonathan Cameron +Stable-dep-of: affe3f077d7a ("iio: imu: inv_icm42600: fix timestamping by limiting FIFO reading") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/iio/common/inv_sensors/inv_sensors_timestamp.c | 30 +++++++---------- + drivers/iio/imu/inv_icm42600/inv_icm42600_buffer.c | 20 ++++------- + drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c | 2 - + include/linux/iio/common/inv_sensors_timestamp.h | 3 - + 4 files changed, 23 insertions(+), 32 deletions(-) + +--- a/drivers/iio/common/inv_sensors/inv_sensors_timestamp.c ++++ b/drivers/iio/common/inv_sensors/inv_sensors_timestamp.c +@@ -70,13 +70,13 @@ int inv_sensors_timestamp_update_odr(str + } + EXPORT_SYMBOL_NS_GPL(inv_sensors_timestamp_update_odr, IIO_INV_SENSORS_TIMESTAMP); + +-static bool inv_validate_period(struct inv_sensors_timestamp *ts, uint32_t period, uint32_t mult) ++static bool inv_validate_period(struct inv_sensors_timestamp *ts, uint32_t period) + { + uint32_t period_min, period_max; + + /* check that period is acceptable */ +- period_min = ts->min_period * mult; +- period_max = ts->max_period * mult; ++ period_min = ts->min_period * ts->mult; ++ period_max = ts->max_period * ts->mult; + if (period > period_min && period < period_max) + return true; + else +@@ -84,32 +84,30 @@ static bool inv_validate_period(struct i + } + + static bool inv_compute_chip_period(struct inv_sensors_timestamp *ts, +- uint32_t mult, uint32_t period) ++ uint32_t period) + { + uint32_t new_chip_period; + +- if (!inv_validate_period(ts, period, mult)) ++ if (!inv_validate_period(ts, period)) + return false; + + /* update chip internal period estimation */ +- new_chip_period = period / mult; ++ new_chip_period = period / ts->mult; + inv_update_acc(&ts->chip_period, new_chip_period); + + return true; + } + + void inv_sensors_timestamp_interrupt(struct inv_sensors_timestamp *ts, +- uint32_t fifo_period, size_t fifo_nb, +- size_t sensor_nb, int64_t timestamp) ++ size_t sample_nb, int64_t timestamp) + { + struct inv_sensors_timestamp_interval *it; + int64_t delta, interval; +- const uint32_t fifo_mult = fifo_period / ts->chip.clock_period; + uint32_t period; + int32_t m; + bool valid = false; + +- if (fifo_nb == 0) ++ if (sample_nb == 0) + return; + + /* update interrupt timestamp and compute chip and sensor periods */ +@@ -119,8 +117,8 @@ void inv_sensors_timestamp_interrupt(str + delta = it->up - it->lo; + if (it->lo != 0) { + /* compute period: delta time divided by number of samples */ +- period = div_s64(delta, fifo_nb); +- valid = inv_compute_chip_period(ts, fifo_mult, period); ++ period = div_s64(delta, sample_nb); ++ valid = inv_compute_chip_period(ts, period); + /* update sensor period if chip internal period is updated */ + if (valid) + ts->period = ts->mult * ts->chip_period.val; +@@ -129,20 +127,18 @@ void inv_sensors_timestamp_interrupt(str + /* no previous data, compute theoritical value from interrupt */ + if (ts->timestamp == 0) { + /* elapsed time: sensor period * sensor samples number */ +- interval = (int64_t)ts->period * (int64_t)sensor_nb; ++ interval = (int64_t)ts->period * (int64_t)sample_nb; + ts->timestamp = it->up - interval; + return; + } + + /* if interrupt interval is valid, sync with interrupt timestamp */ + if (valid) { +- /* compute measured fifo_period */ +- fifo_period = fifo_mult * ts->chip_period.val; + /* delta time between last sample and last interrupt */ + delta = it->lo - ts->timestamp; + /* if there are multiple samples, go back to first one */ +- while (delta >= (fifo_period * 3 / 2)) +- delta -= fifo_period; ++ while (delta >= (ts->period * 3 / 2)) ++ delta -= ts->period; + /* compute maximal adjustment value */ + m = INV_SENSORS_TIMESTAMP_JITTER((int64_t)ts->period, ts->chip.jitter); + if (delta > m) +--- a/drivers/iio/imu/inv_icm42600/inv_icm42600_buffer.c ++++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_buffer.c +@@ -515,20 +515,20 @@ int inv_icm42600_buffer_fifo_parse(struc + return 0; + + /* handle gyroscope timestamp and FIFO data parsing */ +- ts = iio_priv(st->indio_gyro); +- inv_sensors_timestamp_interrupt(ts, st->fifo.period, st->fifo.nb.total, +- st->fifo.nb.gyro, st->timestamp.gyro); + if (st->fifo.nb.gyro > 0) { ++ ts = iio_priv(st->indio_gyro); ++ inv_sensors_timestamp_interrupt(ts, st->fifo.nb.gyro, ++ st->timestamp.gyro); + ret = inv_icm42600_gyro_parse_fifo(st->indio_gyro); + if (ret) + return ret; + } + + /* handle accelerometer timestamp and FIFO data parsing */ +- ts = iio_priv(st->indio_accel); +- inv_sensors_timestamp_interrupt(ts, st->fifo.period, st->fifo.nb.total, +- st->fifo.nb.accel, st->timestamp.accel); + if (st->fifo.nb.accel > 0) { ++ ts = iio_priv(st->indio_accel); ++ inv_sensors_timestamp_interrupt(ts, st->fifo.nb.accel, ++ st->timestamp.accel); + ret = inv_icm42600_accel_parse_fifo(st->indio_accel); + if (ret) + return ret; +@@ -556,9 +556,7 @@ int inv_icm42600_buffer_hwfifo_flush(str + + if (st->fifo.nb.gyro > 0) { + ts = iio_priv(st->indio_gyro); +- inv_sensors_timestamp_interrupt(ts, st->fifo.period, +- st->fifo.nb.total, st->fifo.nb.gyro, +- gyro_ts); ++ inv_sensors_timestamp_interrupt(ts, st->fifo.nb.gyro, gyro_ts); + ret = inv_icm42600_gyro_parse_fifo(st->indio_gyro); + if (ret) + return ret; +@@ -566,9 +564,7 @@ int inv_icm42600_buffer_hwfifo_flush(str + + if (st->fifo.nb.accel > 0) { + ts = iio_priv(st->indio_accel); +- inv_sensors_timestamp_interrupt(ts, st->fifo.period, +- st->fifo.nb.total, st->fifo.nb.accel, +- accel_ts); ++ inv_sensors_timestamp_interrupt(ts, st->fifo.nb.accel, accel_ts); + ret = inv_icm42600_accel_parse_fifo(st->indio_accel); + if (ret) + return ret; +--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c ++++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c +@@ -109,7 +109,7 @@ irqreturn_t inv_mpu6050_read_fifo(int ir + nb = fifo_count / bytes_per_datum; + /* Each FIFO data contains all sensors, so same number for FIFO and sensor data */ + fifo_period = NSEC_PER_SEC / INV_MPU6050_DIVIDER_TO_FIFO_RATE(st->chip_config.divider); +- inv_sensors_timestamp_interrupt(&st->timestamp, fifo_period, nb, nb, pf->timestamp); ++ inv_sensors_timestamp_interrupt(&st->timestamp, nb, pf->timestamp); + inv_sensors_timestamp_apply_odr(&st->timestamp, fifo_period, nb, 0); + for (i = 0; i < nb; ++i) { + result = regmap_noinc_read(st->map, st->reg->fifo_r_w, +--- a/include/linux/iio/common/inv_sensors_timestamp.h ++++ b/include/linux/iio/common/inv_sensors_timestamp.h +@@ -71,8 +71,7 @@ int inv_sensors_timestamp_update_odr(str + uint32_t period, bool fifo); + + void inv_sensors_timestamp_interrupt(struct inv_sensors_timestamp *ts, +- uint32_t fifo_period, size_t fifo_nb, +- size_t sensor_nb, int64_t timestamp); ++ size_t sample_nb, int64_t timestamp); + + static inline int64_t inv_sensors_timestamp_pop(struct inv_sensors_timestamp *ts) + { diff --git a/queue-5.10/iio-invensense-remove-redundant-initialization-of-variable-period.patch b/queue-5.10/iio-invensense-remove-redundant-initialization-of-variable-period.patch new file mode 100644 index 0000000000..0bfe88285d --- /dev/null +++ b/queue-5.10/iio-invensense-remove-redundant-initialization-of-variable-period.patch @@ -0,0 +1,42 @@ +From stable+bounces-274093-greg=kroah.com@vger.kernel.org Tue Jul 14 05:06:29 2026 +From: Sasha Levin +Date: Mon, 13 Jul 2026 23:04:41 -0400 +Subject: iio: invensense: remove redundant initialization of variable period +To: stable@vger.kernel.org +Cc: Colin Ian King , Jean-Baptiste Maneyrol , Jonathan Cameron , Sasha Levin +Message-ID: <20260714030444.2382550-5-sashal@kernel.org> + +From: Colin Ian King + +[ Upstream commit b58b13f156c00c2457035b7071eaaac105fe6836 ] + +The variable period is being initialized with a value that is never +read, it is being re-assigned a new value later on before it is read. +The initialization is redundant and can be removed. + +Cleans up clang scan build warning: +Value stored to 'period' during its initialization is never +read [deadcode.DeadStores] + +Signed-off-by: Colin Ian King +Acked-by: Jean-Baptiste Maneyrol +Link: https://lore.kernel.org/r/20240106153202.54861-1-colin.i.king@gmail.com +Signed-off-by: Jonathan Cameron +Stable-dep-of: affe3f077d7a ("iio: imu: inv_icm42600: fix timestamping by limiting FIFO reading") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/iio/common/inv_sensors/inv_sensors_timestamp.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/iio/common/inv_sensors/inv_sensors_timestamp.c ++++ b/drivers/iio/common/inv_sensors/inv_sensors_timestamp.c +@@ -105,7 +105,7 @@ void inv_sensors_timestamp_interrupt(str + struct inv_sensors_timestamp_interval *it; + int64_t delta, interval; + const uint32_t fifo_mult = fifo_period / ts->chip.clock_period; +- uint32_t period = ts->period; ++ uint32_t period; + int32_t m; + bool valid = false; + diff --git a/queue-5.10/iio-make-invensense-timestamp-module-generic.patch b/queue-5.10/iio-make-invensense-timestamp-module-generic.patch new file mode 100644 index 0000000000..74a87d3bc0 --- /dev/null +++ b/queue-5.10/iio-make-invensense-timestamp-module-generic.patch @@ -0,0 +1,962 @@ +From stable+bounces-274092-greg=kroah.com@vger.kernel.org Tue Jul 14 05:06:25 2026 +From: Sasha Levin +Date: Mon, 13 Jul 2026 23:04:39 -0400 +Subject: iio: make invensense timestamp module generic +To: stable@vger.kernel.org +Cc: Jean-Baptiste Maneyrol , Andy Shevchenko , Jonathan Cameron , Sasha Levin +Message-ID: <20260714030444.2382550-3-sashal@kernel.org> + +From: Jean-Baptiste Maneyrol + +[ Upstream commit 0ecc363ccea71eda6a2cceade120489259bcdb33 ] + +Rename common module to inv_sensors_timestamp, add configuration +at init (chip internal clock, acceptable jitter, ...) and update +inv_icm42600 driver integration. + +Signed-off-by: Jean-Baptiste Maneyrol +Reviewed-by: Andy Shevchenko +Link: https://lore.kernel.org/r/20230606162147.79667-4-inv.git-commit@tdk.com +Signed-off-by: Jonathan Cameron +Stable-dep-of: affe3f077d7a ("iio: imu: inv_icm42600: fix timestamping by limiting FIFO reading") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/iio/common/inv_sensors/Makefile | 2 + drivers/iio/common/inv_sensors/inv_icm42600_timestamp.c | 192 ---------------- + drivers/iio/common/inv_sensors/inv_sensors_timestamp.c | 191 +++++++++++++++ + drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c | 32 +- + drivers/iio/imu/inv_icm42600/inv_icm42600_buffer.c | 34 +- + drivers/iio/imu/inv_icm42600/inv_icm42600_core.c | 10 + drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c | 32 +- + include/linux/iio/common/inv_icm42600_timestamp.h | 79 ------ + include/linux/iio/common/inv_sensors_timestamp.h | 95 +++++++ + 9 files changed, 349 insertions(+), 318 deletions(-) + rename drivers/iio/common/inv_sensors/{inv_icm42600_timestamp.c => inv_sensors_timestamp.c} (61%) + delete mode 100644 include/linux/iio/common/inv_icm42600_timestamp.h + create mode 100644 include/linux/iio/common/inv_sensors_timestamp.h + +--- a/drivers/iio/common/inv_sensors/Makefile ++++ b/drivers/iio/common/inv_sensors/Makefile +@@ -3,4 +3,4 @@ + # Makefile for TDK-InvenSense sensors module. + # + +-obj-$(CONFIG_IIO_INV_SENSORS_TIMESTAMP) += inv_icm42600_timestamp.o ++obj-$(CONFIG_IIO_INV_SENSORS_TIMESTAMP) += inv_sensors_timestamp.o +--- a/drivers/iio/common/inv_sensors/inv_icm42600_timestamp.c ++++ /dev/null +@@ -1,192 +0,0 @@ +-// SPDX-License-Identifier: GPL-2.0-or-later +-/* +- * Copyright (C) 2020 Invensense, Inc. +- */ +- +-#include +-#include +-#include +-#include +- +-#include +- +-/* internal chip period is 32kHz, 31250ns */ +-#define INV_ICM42600_TIMESTAMP_PERIOD 31250 +-/* allow a jitter of +/- 2% */ +-#define INV_ICM42600_TIMESTAMP_JITTER 2 +-/* compute min and max periods accepted */ +-#define INV_ICM42600_TIMESTAMP_MIN_PERIOD(_p) \ +- (((_p) * (100 - INV_ICM42600_TIMESTAMP_JITTER)) / 100) +-#define INV_ICM42600_TIMESTAMP_MAX_PERIOD(_p) \ +- (((_p) * (100 + INV_ICM42600_TIMESTAMP_JITTER)) / 100) +- +-/* Add a new value inside an accumulator and update the estimate value */ +-static void inv_update_acc(struct inv_icm42600_timestamp_acc *acc, uint32_t val) +-{ +- uint64_t sum = 0; +- size_t i; +- +- acc->values[acc->idx++] = val; +- if (acc->idx >= ARRAY_SIZE(acc->values)) +- acc->idx = 0; +- +- /* compute the mean of all stored values, use 0 as empty slot */ +- for (i = 0; i < ARRAY_SIZE(acc->values); ++i) { +- if (acc->values[i] == 0) +- break; +- sum += acc->values[i]; +- } +- +- acc->val = div_u64(sum, i); +-} +- +-void inv_icm42600_timestamp_init(struct inv_icm42600_timestamp *ts, +- uint32_t period) +-{ +- /* initial odr for sensor after reset is 1kHz */ +- const uint32_t default_period = 1000000; +- +- /* current multiplier and period values after reset */ +- ts->mult = default_period / INV_ICM42600_TIMESTAMP_PERIOD; +- ts->period = default_period; +- /* new set multiplier is the one from chip initialization */ +- ts->new_mult = period / INV_ICM42600_TIMESTAMP_PERIOD; +- +- /* use theoretical value for chip period */ +- inv_update_acc(&ts->chip_period, INV_ICM42600_TIMESTAMP_PERIOD); +-} +-EXPORT_SYMBOL_NS_GPL(inv_icm42600_timestamp_init, IIO_INV_SENSORS_TIMESTAMP); +- +-int inv_icm42600_timestamp_update_odr(struct inv_icm42600_timestamp *ts, +- uint32_t period, bool fifo) +-{ +- /* when FIFO is on, prevent odr change if one is already pending */ +- if (fifo && ts->new_mult != 0) +- return -EAGAIN; +- +- ts->new_mult = period / INV_ICM42600_TIMESTAMP_PERIOD; +- +- return 0; +-} +-EXPORT_SYMBOL_NS_GPL(inv_icm42600_timestamp_update_odr, IIO_INV_SENSORS_TIMESTAMP); +- +-static bool inv_validate_period(uint32_t period, uint32_t mult) +-{ +- const uint32_t chip_period = INV_ICM42600_TIMESTAMP_PERIOD; +- uint32_t period_min, period_max; +- +- /* check that period is acceptable */ +- period_min = INV_ICM42600_TIMESTAMP_MIN_PERIOD(chip_period) * mult; +- period_max = INV_ICM42600_TIMESTAMP_MAX_PERIOD(chip_period) * mult; +- if (period > period_min && period < period_max) +- return true; +- else +- return false; +-} +- +-static bool inv_compute_chip_period(struct inv_icm42600_timestamp *ts, +- uint32_t mult, uint32_t period) +-{ +- uint32_t new_chip_period; +- +- if (!inv_validate_period(period, mult)) +- return false; +- +- /* update chip internal period estimation */ +- new_chip_period = period / mult; +- inv_update_acc(&ts->chip_period, new_chip_period); +- +- return true; +-} +- +-void inv_icm42600_timestamp_interrupt(struct inv_icm42600_timestamp *ts, +- uint32_t fifo_period, size_t fifo_nb, +- size_t sensor_nb, int64_t timestamp) +-{ +- struct inv_icm42600_timestamp_interval *it; +- int64_t delta, interval; +- const uint32_t fifo_mult = fifo_period / INV_ICM42600_TIMESTAMP_PERIOD; +- uint32_t period = ts->period; +- int32_t m; +- bool valid = false; +- +- if (fifo_nb == 0) +- return; +- +- /* update interrupt timestamp and compute chip and sensor periods */ +- it = &ts->it; +- it->lo = it->up; +- it->up = timestamp; +- delta = it->up - it->lo; +- if (it->lo != 0) { +- /* compute period: delta time divided by number of samples */ +- period = div_s64(delta, fifo_nb); +- valid = inv_compute_chip_period(ts, fifo_mult, period); +- /* update sensor period if chip internal period is updated */ +- if (valid) +- ts->period = ts->mult * ts->chip_period.val; +- } +- +- /* no previous data, compute theoritical value from interrupt */ +- if (ts->timestamp == 0) { +- /* elapsed time: sensor period * sensor samples number */ +- interval = (int64_t)ts->period * (int64_t)sensor_nb; +- ts->timestamp = it->up - interval; +- return; +- } +- +- /* if interrupt interval is valid, sync with interrupt timestamp */ +- if (valid) { +- /* compute measured fifo_period */ +- fifo_period = fifo_mult * ts->chip_period.val; +- /* delta time between last sample and last interrupt */ +- delta = it->lo - ts->timestamp; +- /* if there are multiple samples, go back to first one */ +- while (delta >= (fifo_period * 3 / 2)) +- delta -= fifo_period; +- /* compute maximal adjustment value */ +- m = INV_ICM42600_TIMESTAMP_MAX_PERIOD(ts->period) - ts->period; +- if (delta > m) +- delta = m; +- else if (delta < -m) +- delta = -m; +- ts->timestamp += delta; +- } +-} +-EXPORT_SYMBOL_NS_GPL(inv_icm42600_timestamp_interrupt, IIO_INV_SENSORS_TIMESTAMP); +- +-void inv_icm42600_timestamp_apply_odr(struct inv_icm42600_timestamp *ts, +- uint32_t fifo_period, size_t fifo_nb, +- unsigned int fifo_no) +-{ +- int64_t interval; +- uint32_t fifo_mult; +- +- if (ts->new_mult == 0) +- return; +- +- /* update to new multiplier and update period */ +- ts->mult = ts->new_mult; +- ts->new_mult = 0; +- ts->period = ts->mult * ts->chip_period.val; +- +- /* +- * After ODR change the time interval with the previous sample is +- * undertermined (depends when the change occures). So we compute the +- * timestamp from the current interrupt using the new FIFO period, the +- * total number of samples and the current sample numero. +- */ +- if (ts->timestamp != 0) { +- /* compute measured fifo period */ +- fifo_mult = fifo_period / INV_ICM42600_TIMESTAMP_PERIOD; +- fifo_period = fifo_mult * ts->chip_period.val; +- /* computes time interval between interrupt and this sample */ +- interval = (int64_t)(fifo_nb - fifo_no) * (int64_t)fifo_period; +- ts->timestamp = ts->it.up - interval; +- } +-} +-EXPORT_SYMBOL_NS_GPL(inv_icm42600_timestamp_apply_odr, IIO_INV_SENSORS_TIMESTAMP); +- +-MODULE_AUTHOR("InvenSense, Inc."); +-MODULE_DESCRIPTION("InvenSense sensors timestamp module"); +-MODULE_LICENSE("GPL"); +--- /dev/null ++++ b/drivers/iio/common/inv_sensors/inv_sensors_timestamp.c +@@ -0,0 +1,191 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later ++/* ++ * Copyright (C) 2020 Invensense, Inc. ++ */ ++ ++#include ++#include ++#include ++#include ++ ++#include ++ ++/* compute jitter, min and max following jitter in per mille */ ++#define INV_SENSORS_TIMESTAMP_JITTER(_val, _jitter) \ ++ (div_s64((_val) * (_jitter), 1000)) ++#define INV_SENSORS_TIMESTAMP_MIN(_val, _jitter) \ ++ (((_val) * (1000 - (_jitter))) / 1000) ++#define INV_SENSORS_TIMESTAMP_MAX(_val, _jitter) \ ++ (((_val) * (1000 + (_jitter))) / 1000) ++ ++/* Add a new value inside an accumulator and update the estimate value */ ++static void inv_update_acc(struct inv_sensors_timestamp_acc *acc, uint32_t val) ++{ ++ uint64_t sum = 0; ++ size_t i; ++ ++ acc->values[acc->idx++] = val; ++ if (acc->idx >= ARRAY_SIZE(acc->values)) ++ acc->idx = 0; ++ ++ /* compute the mean of all stored values, use 0 as empty slot */ ++ for (i = 0; i < ARRAY_SIZE(acc->values); ++i) { ++ if (acc->values[i] == 0) ++ break; ++ sum += acc->values[i]; ++ } ++ ++ acc->val = div_u64(sum, i); ++} ++ ++void inv_sensors_timestamp_init(struct inv_sensors_timestamp *ts, ++ const struct inv_sensors_timestamp_chip *chip) ++{ ++ memset(ts, 0, sizeof(*ts)); ++ ++ /* save chip parameters and compute min and max clock period */ ++ ts->chip = *chip; ++ ts->min_period = INV_SENSORS_TIMESTAMP_MIN(chip->clock_period, chip->jitter); ++ ts->max_period = INV_SENSORS_TIMESTAMP_MAX(chip->clock_period, chip->jitter); ++ ++ /* current multiplier and period values after reset */ ++ ts->mult = chip->init_period / chip->clock_period; ++ ts->period = chip->init_period; ++ ++ /* use theoretical value for chip period */ ++ inv_update_acc(&ts->chip_period, chip->clock_period); ++} ++EXPORT_SYMBOL_NS_GPL(inv_sensors_timestamp_init, IIO_INV_SENSORS_TIMESTAMP); ++ ++int inv_sensors_timestamp_update_odr(struct inv_sensors_timestamp *ts, ++ uint32_t period, bool fifo) ++{ ++ /* when FIFO is on, prevent odr change if one is already pending */ ++ if (fifo && ts->new_mult != 0) ++ return -EAGAIN; ++ ++ ts->new_mult = period / ts->chip.clock_period; ++ ++ return 0; ++} ++EXPORT_SYMBOL_NS_GPL(inv_sensors_timestamp_update_odr, IIO_INV_SENSORS_TIMESTAMP); ++ ++static bool inv_validate_period(struct inv_sensors_timestamp *ts, uint32_t period, uint32_t mult) ++{ ++ uint32_t period_min, period_max; ++ ++ /* check that period is acceptable */ ++ period_min = ts->min_period * mult; ++ period_max = ts->max_period * mult; ++ if (period > period_min && period < period_max) ++ return true; ++ else ++ return false; ++} ++ ++static bool inv_compute_chip_period(struct inv_sensors_timestamp *ts, ++ uint32_t mult, uint32_t period) ++{ ++ uint32_t new_chip_period; ++ ++ if (!inv_validate_period(ts, period, mult)) ++ return false; ++ ++ /* update chip internal period estimation */ ++ new_chip_period = period / mult; ++ inv_update_acc(&ts->chip_period, new_chip_period); ++ ++ return true; ++} ++ ++void inv_sensors_timestamp_interrupt(struct inv_sensors_timestamp *ts, ++ uint32_t fifo_period, size_t fifo_nb, ++ size_t sensor_nb, int64_t timestamp) ++{ ++ struct inv_sensors_timestamp_interval *it; ++ int64_t delta, interval; ++ const uint32_t fifo_mult = fifo_period / ts->chip.clock_period; ++ uint32_t period = ts->period; ++ int32_t m; ++ bool valid = false; ++ ++ if (fifo_nb == 0) ++ return; ++ ++ /* update interrupt timestamp and compute chip and sensor periods */ ++ it = &ts->it; ++ it->lo = it->up; ++ it->up = timestamp; ++ delta = it->up - it->lo; ++ if (it->lo != 0) { ++ /* compute period: delta time divided by number of samples */ ++ period = div_s64(delta, fifo_nb); ++ valid = inv_compute_chip_period(ts, fifo_mult, period); ++ /* update sensor period if chip internal period is updated */ ++ if (valid) ++ ts->period = ts->mult * ts->chip_period.val; ++ } ++ ++ /* no previous data, compute theoritical value from interrupt */ ++ if (ts->timestamp == 0) { ++ /* elapsed time: sensor period * sensor samples number */ ++ interval = (int64_t)ts->period * (int64_t)sensor_nb; ++ ts->timestamp = it->up - interval; ++ return; ++ } ++ ++ /* if interrupt interval is valid, sync with interrupt timestamp */ ++ if (valid) { ++ /* compute measured fifo_period */ ++ fifo_period = fifo_mult * ts->chip_period.val; ++ /* delta time between last sample and last interrupt */ ++ delta = it->lo - ts->timestamp; ++ /* if there are multiple samples, go back to first one */ ++ while (delta >= (fifo_period * 3 / 2)) ++ delta -= fifo_period; ++ /* compute maximal adjustment value */ ++ m = INV_SENSORS_TIMESTAMP_JITTER((int64_t)ts->period, ts->chip.jitter); ++ if (delta > m) ++ delta = m; ++ else if (delta < -m) ++ delta = -m; ++ ts->timestamp += delta; ++ } ++} ++EXPORT_SYMBOL_NS_GPL(inv_sensors_timestamp_interrupt, IIO_INV_SENSORS_TIMESTAMP); ++ ++void inv_sensors_timestamp_apply_odr(struct inv_sensors_timestamp *ts, ++ uint32_t fifo_period, size_t fifo_nb, ++ unsigned int fifo_no) ++{ ++ int64_t interval; ++ uint32_t fifo_mult; ++ ++ if (ts->new_mult == 0) ++ return; ++ ++ /* update to new multiplier and update period */ ++ ts->mult = ts->new_mult; ++ ts->new_mult = 0; ++ ts->period = ts->mult * ts->chip_period.val; ++ ++ /* ++ * After ODR change the time interval with the previous sample is ++ * undertermined (depends when the change occures). So we compute the ++ * timestamp from the current interrupt using the new FIFO period, the ++ * total number of samples and the current sample numero. ++ */ ++ if (ts->timestamp != 0) { ++ /* compute measured fifo period */ ++ fifo_mult = fifo_period / ts->chip.clock_period; ++ fifo_period = fifo_mult * ts->chip_period.val; ++ /* computes time interval between interrupt and this sample */ ++ interval = (int64_t)(fifo_nb - fifo_no) * (int64_t)fifo_period; ++ ts->timestamp = ts->it.up - interval; ++ } ++} ++EXPORT_SYMBOL_NS_GPL(inv_sensors_timestamp_apply_odr, IIO_INV_SENSORS_TIMESTAMP); ++ ++MODULE_AUTHOR("InvenSense, Inc."); ++MODULE_DESCRIPTION("InvenSense sensors timestamp module"); ++MODULE_LICENSE("GPL"); +--- a/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c ++++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c +@@ -12,7 +12,7 @@ + #include + + #include +-#include ++#include + #include + #include + +@@ -99,7 +99,7 @@ static int inv_icm42600_accel_update_sca + const unsigned long *scan_mask) + { + struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev); +- struct inv_icm42600_timestamp *ts = iio_priv(indio_dev); ++ struct inv_sensors_timestamp *ts = iio_priv(indio_dev); + struct inv_icm42600_sensor_conf conf = INV_ICM42600_SENSOR_CONF_INIT; + unsigned int fifo_en = 0; + unsigned int sleep_temp = 0; +@@ -127,7 +127,7 @@ static int inv_icm42600_accel_update_sca + } + + /* update data FIFO write */ +- inv_icm42600_timestamp_apply_odr(ts, 0, 0, 0); ++ inv_sensors_timestamp_apply_odr(ts, 0, 0, 0); + ret = inv_icm42600_buffer_set_fifo_en(st, fifo_en | st->fifo.en); + + out_unlock: +@@ -308,7 +308,7 @@ static int inv_icm42600_accel_write_odr( + int val, int val2) + { + struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev); +- struct inv_icm42600_timestamp *ts = iio_priv(indio_dev); ++ struct inv_sensors_timestamp *ts = iio_priv(indio_dev); + struct device *dev = regmap_get_device(st->map); + unsigned int idx; + struct inv_icm42600_sensor_conf conf = INV_ICM42600_SENSOR_CONF_INIT; +@@ -329,8 +329,8 @@ static int inv_icm42600_accel_write_odr( + pm_runtime_get_sync(dev); + mutex_lock(&st->lock); + +- ret = inv_icm42600_timestamp_update_odr(ts, inv_icm42600_odr_to_period(conf.odr), +- iio_buffer_enabled(indio_dev)); ++ ret = inv_sensors_timestamp_update_odr(ts, inv_icm42600_odr_to_period(conf.odr), ++ iio_buffer_enabled(indio_dev)); + if (ret) + goto out_unlock; + +@@ -706,7 +706,8 @@ struct iio_dev *inv_icm42600_accel_init( + { + struct device *dev = regmap_get_device(st->map); + const char *name; +- struct inv_icm42600_timestamp *ts; ++ struct inv_sensors_timestamp_chip ts_chip; ++ struct inv_sensors_timestamp *ts; + struct iio_dev *indio_dev; + struct iio_buffer *buffer; + int ret; +@@ -723,8 +724,15 @@ struct iio_dev *inv_icm42600_accel_init( + if (!buffer) + return ERR_PTR(-ENOMEM); + ++ /* ++ * clock period is 32kHz (31250ns) ++ * jitter is +/- 2% (20 per mille) ++ */ ++ ts_chip.clock_period = 31250; ++ ts_chip.jitter = 20; ++ ts_chip.init_period = inv_icm42600_odr_to_period(st->conf.accel.odr); + ts = iio_priv(indio_dev); +- inv_icm42600_timestamp_init(ts, inv_icm42600_odr_to_period(st->conf.accel.odr)); ++ inv_sensors_timestamp_init(ts, &ts_chip); + + iio_device_set_drvdata(indio_dev, st); + indio_dev->name = name; +@@ -747,7 +755,7 @@ struct iio_dev *inv_icm42600_accel_init( + int inv_icm42600_accel_parse_fifo(struct iio_dev *indio_dev) + { + struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev); +- struct inv_icm42600_timestamp *ts = iio_priv(indio_dev); ++ struct inv_sensors_timestamp *ts = iio_priv(indio_dev); + ssize_t i, size; + unsigned int no; + const void *accel, *gyro, *timestamp; +@@ -771,13 +779,13 @@ int inv_icm42600_accel_parse_fifo(struct + + /* update odr */ + if (odr & INV_ICM42600_SENSOR_ACCEL) +- inv_icm42600_timestamp_apply_odr(ts, st->fifo.period, +- st->fifo.nb.total, no); ++ inv_sensors_timestamp_apply_odr(ts, st->fifo.period, ++ st->fifo.nb.total, no); + + memcpy(&buffer.accel, accel, sizeof(buffer.accel)); + /* convert 8 bits FIFO temperature in high resolution format */ + buffer.temp = temp ? (*temp * 64) : 0; +- ts_val = inv_icm42600_timestamp_pop(ts); ++ ts_val = inv_sensors_timestamp_pop(ts); + iio_push_to_buffers_with_timestamp(indio_dev, &buffer, ts_val); + } + +--- a/drivers/iio/imu/inv_icm42600/inv_icm42600_buffer.c ++++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_buffer.c +@@ -11,7 +11,7 @@ + #include + + #include +-#include ++#include + #include + + #include "inv_icm42600.h" +@@ -276,12 +276,12 @@ static int inv_icm42600_buffer_preenable + { + struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev); + struct device *dev = regmap_get_device(st->map); +- struct inv_icm42600_timestamp *ts = iio_priv(indio_dev); ++ struct inv_sensors_timestamp *ts = iio_priv(indio_dev); + + pm_runtime_get_sync(dev); + + mutex_lock(&st->lock); +- inv_icm42600_timestamp_reset(ts); ++ inv_sensors_timestamp_reset(ts); + mutex_unlock(&st->lock); + + return 0; +@@ -378,7 +378,7 @@ out_unlock: + static int inv_icm42600_buffer_postdisable(struct iio_dev *indio_dev) + { + struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev); +- struct inv_icm42600_timestamp *ts = iio_priv(indio_dev); ++ struct inv_sensors_timestamp *ts = iio_priv(indio_dev); + struct device *dev = regmap_get_device(st->map); + unsigned int sensor; + unsigned int *watermark; +@@ -400,7 +400,7 @@ static int inv_icm42600_buffer_postdisab + + mutex_lock(&st->lock); + +- inv_icm42600_timestamp_apply_odr(ts, 0, 0, 0); ++ inv_sensors_timestamp_apply_odr(ts, 0, 0, 0); + + ret = inv_icm42600_buffer_set_fifo_en(st, st->fifo.en & ~sensor); + if (ret) +@@ -508,7 +508,7 @@ int inv_icm42600_buffer_fifo_read(struct + + int inv_icm42600_buffer_fifo_parse(struct inv_icm42600_state *st) + { +- struct inv_icm42600_timestamp *ts; ++ struct inv_sensors_timestamp *ts; + int ret; + + if (st->fifo.nb.total == 0) +@@ -516,8 +516,8 @@ int inv_icm42600_buffer_fifo_parse(struc + + /* handle gyroscope timestamp and FIFO data parsing */ + ts = iio_priv(st->indio_gyro); +- inv_icm42600_timestamp_interrupt(ts, st->fifo.period, st->fifo.nb.total, +- st->fifo.nb.gyro, st->timestamp.gyro); ++ inv_sensors_timestamp_interrupt(ts, st->fifo.period, st->fifo.nb.total, ++ st->fifo.nb.gyro, st->timestamp.gyro); + if (st->fifo.nb.gyro > 0) { + ret = inv_icm42600_gyro_parse_fifo(st->indio_gyro); + if (ret) +@@ -526,8 +526,8 @@ int inv_icm42600_buffer_fifo_parse(struc + + /* handle accelerometer timestamp and FIFO data parsing */ + ts = iio_priv(st->indio_accel); +- inv_icm42600_timestamp_interrupt(ts, st->fifo.period, st->fifo.nb.total, +- st->fifo.nb.accel, st->timestamp.accel); ++ inv_sensors_timestamp_interrupt(ts, st->fifo.period, st->fifo.nb.total, ++ st->fifo.nb.accel, st->timestamp.accel); + if (st->fifo.nb.accel > 0) { + ret = inv_icm42600_accel_parse_fifo(st->indio_accel); + if (ret) +@@ -540,7 +540,7 @@ int inv_icm42600_buffer_fifo_parse(struc + int inv_icm42600_buffer_hwfifo_flush(struct inv_icm42600_state *st, + unsigned int count) + { +- struct inv_icm42600_timestamp *ts; ++ struct inv_sensors_timestamp *ts; + int64_t gyro_ts, accel_ts; + int ret; + +@@ -556,9 +556,9 @@ int inv_icm42600_buffer_hwfifo_flush(str + + if (st->fifo.nb.gyro > 0) { + ts = iio_priv(st->indio_gyro); +- inv_icm42600_timestamp_interrupt(ts, st->fifo.period, +- st->fifo.nb.total, st->fifo.nb.gyro, +- gyro_ts); ++ inv_sensors_timestamp_interrupt(ts, st->fifo.period, ++ st->fifo.nb.total, st->fifo.nb.gyro, ++ gyro_ts); + ret = inv_icm42600_gyro_parse_fifo(st->indio_gyro); + if (ret) + return ret; +@@ -566,9 +566,9 @@ int inv_icm42600_buffer_hwfifo_flush(str + + if (st->fifo.nb.accel > 0) { + ts = iio_priv(st->indio_accel); +- inv_icm42600_timestamp_interrupt(ts, st->fifo.period, +- st->fifo.nb.total, st->fifo.nb.accel, +- accel_ts); ++ inv_sensors_timestamp_interrupt(ts, st->fifo.period, ++ st->fifo.nb.total, st->fifo.nb.accel, ++ accel_ts); + ret = inv_icm42600_accel_parse_fifo(st->indio_accel); + if (ret) + return ret; +--- a/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c ++++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c +@@ -16,7 +16,7 @@ + #include + #include + +-#include ++#include + #include + + #include "inv_icm42600.h" +@@ -720,8 +720,8 @@ out_unlock: + static int __maybe_unused inv_icm42600_resume(struct device *dev) + { + struct inv_icm42600_state *st = dev_get_drvdata(dev); +- struct inv_icm42600_timestamp *gyro_ts = iio_priv(st->indio_gyro); +- struct inv_icm42600_timestamp *accel_ts = iio_priv(st->indio_accel); ++ struct inv_sensors_timestamp *gyro_ts = iio_priv(st->indio_gyro); ++ struct inv_sensors_timestamp *accel_ts = iio_priv(st->indio_accel); + int ret = 0; + + mutex_lock(&st->lock); +@@ -742,8 +742,8 @@ static int __maybe_unused inv_icm42600_r + + /* restore FIFO data streaming */ + if (st->fifo.on) { +- inv_icm42600_timestamp_reset(gyro_ts); +- inv_icm42600_timestamp_reset(accel_ts); ++ inv_sensors_timestamp_reset(gyro_ts); ++ inv_sensors_timestamp_reset(accel_ts); + ret = regmap_write(st->map, INV_ICM42600_REG_FIFO_CONFIG, + INV_ICM42600_FIFO_CONFIG_STREAM); + } +--- a/drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c ++++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c +@@ -12,7 +12,7 @@ + #include + + #include +-#include ++#include + #include + #include + +@@ -99,7 +99,7 @@ static int inv_icm42600_gyro_update_scan + const unsigned long *scan_mask) + { + struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev); +- struct inv_icm42600_timestamp *ts = iio_priv(indio_dev); ++ struct inv_sensors_timestamp *ts = iio_priv(indio_dev); + struct inv_icm42600_sensor_conf conf = INV_ICM42600_SENSOR_CONF_INIT; + unsigned int fifo_en = 0; + unsigned int sleep_gyro = 0; +@@ -127,7 +127,7 @@ static int inv_icm42600_gyro_update_scan + } + + /* update data FIFO write */ +- inv_icm42600_timestamp_apply_odr(ts, 0, 0, 0); ++ inv_sensors_timestamp_apply_odr(ts, 0, 0, 0); + ret = inv_icm42600_buffer_set_fifo_en(st, fifo_en | st->fifo.en); + + out_unlock: +@@ -320,7 +320,7 @@ static int inv_icm42600_gyro_write_odr(s + int val, int val2) + { + struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev); +- struct inv_icm42600_timestamp *ts = iio_priv(indio_dev); ++ struct inv_sensors_timestamp *ts = iio_priv(indio_dev); + struct device *dev = regmap_get_device(st->map); + unsigned int idx; + struct inv_icm42600_sensor_conf conf = INV_ICM42600_SENSOR_CONF_INIT; +@@ -341,8 +341,8 @@ static int inv_icm42600_gyro_write_odr(s + pm_runtime_get_sync(dev); + mutex_lock(&st->lock); + +- ret = inv_icm42600_timestamp_update_odr(ts, inv_icm42600_odr_to_period(conf.odr), +- iio_buffer_enabled(indio_dev)); ++ ret = inv_sensors_timestamp_update_odr(ts, inv_icm42600_odr_to_period(conf.odr), ++ iio_buffer_enabled(indio_dev)); + if (ret) + goto out_unlock; + +@@ -717,7 +717,8 @@ struct iio_dev *inv_icm42600_gyro_init(s + { + struct device *dev = regmap_get_device(st->map); + const char *name; +- struct inv_icm42600_timestamp *ts; ++ struct inv_sensors_timestamp_chip ts_chip; ++ struct inv_sensors_timestamp *ts; + struct iio_dev *indio_dev; + struct iio_buffer *buffer; + int ret; +@@ -734,8 +735,15 @@ struct iio_dev *inv_icm42600_gyro_init(s + if (!buffer) + return ERR_PTR(-ENOMEM); + ++ /* ++ * clock period is 32kHz (31250ns) ++ * jitter is +/- 2% (20 per mille) ++ */ ++ ts_chip.clock_period = 31250; ++ ts_chip.jitter = 20; ++ ts_chip.init_period = inv_icm42600_odr_to_period(st->conf.accel.odr); + ts = iio_priv(indio_dev); +- inv_icm42600_timestamp_init(ts, inv_icm42600_odr_to_period(st->conf.gyro.odr)); ++ inv_sensors_timestamp_init(ts, &ts_chip); + + iio_device_set_drvdata(indio_dev, st); + indio_dev->name = name; +@@ -758,7 +766,7 @@ struct iio_dev *inv_icm42600_gyro_init(s + int inv_icm42600_gyro_parse_fifo(struct iio_dev *indio_dev) + { + struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev); +- struct inv_icm42600_timestamp *ts = iio_priv(indio_dev); ++ struct inv_sensors_timestamp *ts = iio_priv(indio_dev); + ssize_t i, size; + unsigned int no; + const void *accel, *gyro, *timestamp; +@@ -782,13 +790,13 @@ int inv_icm42600_gyro_parse_fifo(struct + + /* update odr */ + if (odr & INV_ICM42600_SENSOR_GYRO) +- inv_icm42600_timestamp_apply_odr(ts, st->fifo.period, +- st->fifo.nb.total, no); ++ inv_sensors_timestamp_apply_odr(ts, st->fifo.period, ++ st->fifo.nb.total, no); + + memcpy(&buffer.gyro, gyro, sizeof(buffer.gyro)); + /* convert 8 bits FIFO temperature in high resolution format */ + buffer.temp = temp ? (*temp * 64) : 0; +- ts_val = inv_icm42600_timestamp_pop(ts); ++ ts_val = inv_sensors_timestamp_pop(ts); + iio_push_to_buffers_with_timestamp(indio_dev, &buffer, ts_val); + } + +--- a/include/linux/iio/common/inv_icm42600_timestamp.h ++++ /dev/null +@@ -1,79 +0,0 @@ +-/* SPDX-License-Identifier: GPL-2.0-or-later */ +-/* +- * Copyright (C) 2020 Invensense, Inc. +- */ +- +-#ifndef INV_ICM42600_TIMESTAMP_H_ +-#define INV_ICM42600_TIMESTAMP_H_ +- +-/** +- * struct inv_icm42600_timestamp_interval - timestamps interval +- * @lo: interval lower bound +- * @up: interval upper bound +- */ +-struct inv_icm42600_timestamp_interval { +- int64_t lo; +- int64_t up; +-}; +- +-/** +- * struct inv_icm42600_timestamp_acc - accumulator for computing an estimation +- * @val: current estimation of the value, the mean of all values +- * @idx: current index of the next free place in values table +- * @values: table of all measured values, use for computing the mean +- */ +-struct inv_icm42600_timestamp_acc { +- uint32_t val; +- size_t idx; +- uint32_t values[32]; +-}; +- +-/** +- * struct inv_icm42600_timestamp - timestamp management states +- * @it: interrupts interval timestamps +- * @timestamp: store last timestamp for computing next data timestamp +- * @mult: current internal period multiplier +- * @new_mult: new set internal period multiplier (not yet effective) +- * @period: measured current period of the sensor +- * @chip_period: accumulator for computing internal chip period +- */ +-struct inv_icm42600_timestamp { +- struct inv_icm42600_timestamp_interval it; +- int64_t timestamp; +- uint32_t mult; +- uint32_t new_mult; +- uint32_t period; +- struct inv_icm42600_timestamp_acc chip_period; +-}; +- +-void inv_icm42600_timestamp_init(struct inv_icm42600_timestamp *ts, +- uint32_t period); +- +-int inv_icm42600_timestamp_update_odr(struct inv_icm42600_timestamp *ts, +- uint32_t period, bool fifo); +- +-void inv_icm42600_timestamp_interrupt(struct inv_icm42600_timestamp *ts, +- uint32_t fifo_period, size_t fifo_nb, +- size_t sensor_nb, int64_t timestamp); +- +-static inline int64_t +-inv_icm42600_timestamp_pop(struct inv_icm42600_timestamp *ts) +-{ +- ts->timestamp += ts->period; +- return ts->timestamp; +-} +- +-void inv_icm42600_timestamp_apply_odr(struct inv_icm42600_timestamp *ts, +- uint32_t fifo_period, size_t fifo_nb, +- unsigned int fifo_no); +- +-static inline void +-inv_icm42600_timestamp_reset(struct inv_icm42600_timestamp *ts) +-{ +- const struct inv_icm42600_timestamp_interval interval_init = {0LL, 0LL}; +- +- ts->it = interval_init; +- ts->timestamp = 0; +-} +- +-#endif +--- /dev/null ++++ b/include/linux/iio/common/inv_sensors_timestamp.h +@@ -0,0 +1,95 @@ ++/* SPDX-License-Identifier: GPL-2.0-or-later */ ++/* ++ * Copyright (C) 2020 Invensense, Inc. ++ */ ++ ++#ifndef INV_SENSORS_TIMESTAMP_H_ ++#define INV_SENSORS_TIMESTAMP_H_ ++ ++/** ++ * struct inv_sensors_timestamp_chip - chip internal properties ++ * @clock_period: internal clock period in ns ++ * @jitter: acceptable jitter in per-mille ++ * @init_period: chip initial period at reset in ns ++ */ ++struct inv_sensors_timestamp_chip { ++ uint32_t clock_period; ++ uint32_t jitter; ++ uint32_t init_period; ++}; ++ ++/** ++ * struct inv_sensors_timestamp_interval - timestamps interval ++ * @lo: interval lower bound ++ * @up: interval upper bound ++ */ ++struct inv_sensors_timestamp_interval { ++ int64_t lo; ++ int64_t up; ++}; ++ ++/** ++ * struct inv_sensors_timestamp_acc - accumulator for computing an estimation ++ * @val: current estimation of the value, the mean of all values ++ * @idx: current index of the next free place in values table ++ * @values: table of all measured values, use for computing the mean ++ */ ++struct inv_sensors_timestamp_acc { ++ uint32_t val; ++ size_t idx; ++ uint32_t values[32]; ++}; ++ ++/** ++ * struct inv_sensors_timestamp - timestamp management states ++ * @chip: chip internal characteristics ++ * @min_period: minimal acceptable clock period ++ * @max_period: maximal acceptable clock period ++ * @it: interrupts interval timestamps ++ * @timestamp: store last timestamp for computing next data timestamp ++ * @mult: current internal period multiplier ++ * @new_mult: new set internal period multiplier (not yet effective) ++ * @period: measured current period of the sensor ++ * @chip_period: accumulator for computing internal chip period ++ */ ++struct inv_sensors_timestamp { ++ struct inv_sensors_timestamp_chip chip; ++ uint32_t min_period; ++ uint32_t max_period; ++ struct inv_sensors_timestamp_interval it; ++ int64_t timestamp; ++ uint32_t mult; ++ uint32_t new_mult; ++ uint32_t period; ++ struct inv_sensors_timestamp_acc chip_period; ++}; ++ ++void inv_sensors_timestamp_init(struct inv_sensors_timestamp *ts, ++ const struct inv_sensors_timestamp_chip *chip); ++ ++int inv_sensors_timestamp_update_odr(struct inv_sensors_timestamp *ts, ++ uint32_t period, bool fifo); ++ ++void inv_sensors_timestamp_interrupt(struct inv_sensors_timestamp *ts, ++ uint32_t fifo_period, size_t fifo_nb, ++ size_t sensor_nb, int64_t timestamp); ++ ++static inline int64_t inv_sensors_timestamp_pop(struct inv_sensors_timestamp *ts) ++{ ++ ts->timestamp += ts->period; ++ return ts->timestamp; ++} ++ ++void inv_sensors_timestamp_apply_odr(struct inv_sensors_timestamp *ts, ++ uint32_t fifo_period, size_t fifo_nb, ++ unsigned int fifo_no); ++ ++static inline void inv_sensors_timestamp_reset(struct inv_sensors_timestamp *ts) ++{ ++ const struct inv_sensors_timestamp_interval interval_init = {0LL, 0LL}; ++ ++ ts->it = interval_init; ++ ts->timestamp = 0; ++} ++ ++#endif diff --git a/queue-5.10/iio-move-inv_icm42600-timestamp-module-in-common.patch b/queue-5.10/iio-move-inv_icm42600-timestamp-module-in-common.patch new file mode 100644 index 0000000000..e43e03c954 --- /dev/null +++ b/queue-5.10/iio-move-inv_icm42600-timestamp-module-in-common.patch @@ -0,0 +1,741 @@ +From stable+bounces-274091-greg=kroah.com@vger.kernel.org Tue Jul 14 05:04:51 2026 +From: Sasha Levin +Date: Mon, 13 Jul 2026 23:04:38 -0400 +Subject: iio: move inv_icm42600 timestamp module in common +To: stable@vger.kernel.org +Cc: Jean-Baptiste Maneyrol , Andy Shevchenko , Jonathan Cameron , Sasha Levin +Message-ID: <20260714030444.2382550-2-sashal@kernel.org> + +From: Jean-Baptiste Maneyrol + +[ Upstream commit d99ff463ecf651437e9e4abe68f331dfb6b5bd9d ] + +Create new inv_sensors common modules and move inv_icm42600 +timestamp module inside. This module will be used by IMUs and +also in the future by other chips. + +Modify inv_icm42600 driver to use timestamp module and do some +headers cleanup. + +Signed-off-by: Jean-Baptiste Maneyrol +Reviewed-by: Andy Shevchenko +Link: https://lore.kernel.org/r/20230606162147.79667-3-inv.git-commit@tdk.com +Signed-off-by: Jonathan Cameron +Stable-dep-of: affe3f077d7a ("iio: imu: inv_icm42600: fix timestamping by limiting FIFO reading") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/iio/common/Kconfig | 1 + + drivers/iio/common/Makefile | 1 + + drivers/iio/common/inv_sensors/Kconfig | 7 +++++++ + drivers/iio/common/inv_sensors/Makefile | 6 ++++++ + .../inv_sensors}/inv_icm42600_timestamp.c | 11 ++++++++++- + drivers/iio/imu/inv_icm42600/Kconfig | 1 + + drivers/iio/imu/inv_icm42600/Makefile | 1 - + drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c | 5 +++-- + drivers/iio/imu/inv_icm42600/inv_icm42600_buffer.c | 5 +++-- + drivers/iio/imu/inv_icm42600/inv_icm42600_core.c | 4 +++- + drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c | 5 +++-- + .../linux/iio/common}/inv_icm42600_timestamp.h | 0 + drivers/iio/common/Kconfig | 1 + drivers/iio/common/Makefile | 1 + drivers/iio/common/inv_sensors/Kconfig | 7 + drivers/iio/common/inv_sensors/Makefile | 6 + drivers/iio/common/inv_sensors/inv_icm42600_timestamp.c | 192 ++++++++++++++++ + drivers/iio/imu/inv_icm42600/Kconfig | 1 + drivers/iio/imu/inv_icm42600/Makefile | 1 + drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c | 5 + drivers/iio/imu/inv_icm42600/inv_icm42600_buffer.c | 5 + drivers/iio/imu/inv_icm42600/inv_icm42600_core.c | 4 + drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c | 5 + drivers/iio/imu/inv_icm42600/inv_icm42600_timestamp.c | 183 --------------- + drivers/iio/imu/inv_icm42600/inv_icm42600_timestamp.h | 79 ------ + include/linux/iio/common/inv_icm42600_timestamp.h | 79 ++++++ + 14 files changed, 299 insertions(+), 270 deletions(-) + create mode 100644 drivers/iio/common/inv_sensors/Kconfig + create mode 100644 drivers/iio/common/inv_sensors/Makefile + rename drivers/iio/{imu/inv_icm42600 => common/inv_sensors}/inv_icm42600_timestamp.c (91%) + rename {drivers/iio/imu/inv_icm42600 => include/linux/iio/common}/inv_icm42600_timestamp.h (100%) + +--- a/drivers/iio/common/Kconfig ++++ b/drivers/iio/common/Kconfig +@@ -5,6 +5,7 @@ + + source "drivers/iio/common/cros_ec_sensors/Kconfig" + source "drivers/iio/common/hid-sensors/Kconfig" ++source "drivers/iio/common/inv_sensors/Kconfig" + source "drivers/iio/common/ms_sensors/Kconfig" + source "drivers/iio/common/ssp_sensors/Kconfig" + source "drivers/iio/common/st_sensors/Kconfig" +--- a/drivers/iio/common/Makefile ++++ b/drivers/iio/common/Makefile +@@ -10,6 +10,7 @@ + # When adding new entries keep the list in alphabetical order + obj-y += cros_ec_sensors/ + obj-y += hid-sensors/ ++obj-y += inv_sensors/ + obj-y += ms_sensors/ + obj-y += ssp_sensors/ + obj-y += st_sensors/ +--- /dev/null ++++ b/drivers/iio/common/inv_sensors/Kconfig +@@ -0,0 +1,7 @@ ++# SPDX-License-Identifier: GPL-2.0-only ++# ++# TDK-InvenSense sensors common library ++# ++ ++config IIO_INV_SENSORS_TIMESTAMP ++ tristate +--- /dev/null ++++ b/drivers/iio/common/inv_sensors/Makefile +@@ -0,0 +1,6 @@ ++# SPDX-License-Identifier: GPL-2.0 ++# ++# Makefile for TDK-InvenSense sensors module. ++# ++ ++obj-$(CONFIG_IIO_INV_SENSORS_TIMESTAMP) += inv_icm42600_timestamp.o +--- /dev/null ++++ b/drivers/iio/common/inv_sensors/inv_icm42600_timestamp.c +@@ -0,0 +1,192 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later ++/* ++ * Copyright (C) 2020 Invensense, Inc. ++ */ ++ ++#include ++#include ++#include ++#include ++ ++#include ++ ++/* internal chip period is 32kHz, 31250ns */ ++#define INV_ICM42600_TIMESTAMP_PERIOD 31250 ++/* allow a jitter of +/- 2% */ ++#define INV_ICM42600_TIMESTAMP_JITTER 2 ++/* compute min and max periods accepted */ ++#define INV_ICM42600_TIMESTAMP_MIN_PERIOD(_p) \ ++ (((_p) * (100 - INV_ICM42600_TIMESTAMP_JITTER)) / 100) ++#define INV_ICM42600_TIMESTAMP_MAX_PERIOD(_p) \ ++ (((_p) * (100 + INV_ICM42600_TIMESTAMP_JITTER)) / 100) ++ ++/* Add a new value inside an accumulator and update the estimate value */ ++static void inv_update_acc(struct inv_icm42600_timestamp_acc *acc, uint32_t val) ++{ ++ uint64_t sum = 0; ++ size_t i; ++ ++ acc->values[acc->idx++] = val; ++ if (acc->idx >= ARRAY_SIZE(acc->values)) ++ acc->idx = 0; ++ ++ /* compute the mean of all stored values, use 0 as empty slot */ ++ for (i = 0; i < ARRAY_SIZE(acc->values); ++i) { ++ if (acc->values[i] == 0) ++ break; ++ sum += acc->values[i]; ++ } ++ ++ acc->val = div_u64(sum, i); ++} ++ ++void inv_icm42600_timestamp_init(struct inv_icm42600_timestamp *ts, ++ uint32_t period) ++{ ++ /* initial odr for sensor after reset is 1kHz */ ++ const uint32_t default_period = 1000000; ++ ++ /* current multiplier and period values after reset */ ++ ts->mult = default_period / INV_ICM42600_TIMESTAMP_PERIOD; ++ ts->period = default_period; ++ /* new set multiplier is the one from chip initialization */ ++ ts->new_mult = period / INV_ICM42600_TIMESTAMP_PERIOD; ++ ++ /* use theoretical value for chip period */ ++ inv_update_acc(&ts->chip_period, INV_ICM42600_TIMESTAMP_PERIOD); ++} ++EXPORT_SYMBOL_NS_GPL(inv_icm42600_timestamp_init, IIO_INV_SENSORS_TIMESTAMP); ++ ++int inv_icm42600_timestamp_update_odr(struct inv_icm42600_timestamp *ts, ++ uint32_t period, bool fifo) ++{ ++ /* when FIFO is on, prevent odr change if one is already pending */ ++ if (fifo && ts->new_mult != 0) ++ return -EAGAIN; ++ ++ ts->new_mult = period / INV_ICM42600_TIMESTAMP_PERIOD; ++ ++ return 0; ++} ++EXPORT_SYMBOL_NS_GPL(inv_icm42600_timestamp_update_odr, IIO_INV_SENSORS_TIMESTAMP); ++ ++static bool inv_validate_period(uint32_t period, uint32_t mult) ++{ ++ const uint32_t chip_period = INV_ICM42600_TIMESTAMP_PERIOD; ++ uint32_t period_min, period_max; ++ ++ /* check that period is acceptable */ ++ period_min = INV_ICM42600_TIMESTAMP_MIN_PERIOD(chip_period) * mult; ++ period_max = INV_ICM42600_TIMESTAMP_MAX_PERIOD(chip_period) * mult; ++ if (period > period_min && period < period_max) ++ return true; ++ else ++ return false; ++} ++ ++static bool inv_compute_chip_period(struct inv_icm42600_timestamp *ts, ++ uint32_t mult, uint32_t period) ++{ ++ uint32_t new_chip_period; ++ ++ if (!inv_validate_period(period, mult)) ++ return false; ++ ++ /* update chip internal period estimation */ ++ new_chip_period = period / mult; ++ inv_update_acc(&ts->chip_period, new_chip_period); ++ ++ return true; ++} ++ ++void inv_icm42600_timestamp_interrupt(struct inv_icm42600_timestamp *ts, ++ uint32_t fifo_period, size_t fifo_nb, ++ size_t sensor_nb, int64_t timestamp) ++{ ++ struct inv_icm42600_timestamp_interval *it; ++ int64_t delta, interval; ++ const uint32_t fifo_mult = fifo_period / INV_ICM42600_TIMESTAMP_PERIOD; ++ uint32_t period = ts->period; ++ int32_t m; ++ bool valid = false; ++ ++ if (fifo_nb == 0) ++ return; ++ ++ /* update interrupt timestamp and compute chip and sensor periods */ ++ it = &ts->it; ++ it->lo = it->up; ++ it->up = timestamp; ++ delta = it->up - it->lo; ++ if (it->lo != 0) { ++ /* compute period: delta time divided by number of samples */ ++ period = div_s64(delta, fifo_nb); ++ valid = inv_compute_chip_period(ts, fifo_mult, period); ++ /* update sensor period if chip internal period is updated */ ++ if (valid) ++ ts->period = ts->mult * ts->chip_period.val; ++ } ++ ++ /* no previous data, compute theoritical value from interrupt */ ++ if (ts->timestamp == 0) { ++ /* elapsed time: sensor period * sensor samples number */ ++ interval = (int64_t)ts->period * (int64_t)sensor_nb; ++ ts->timestamp = it->up - interval; ++ return; ++ } ++ ++ /* if interrupt interval is valid, sync with interrupt timestamp */ ++ if (valid) { ++ /* compute measured fifo_period */ ++ fifo_period = fifo_mult * ts->chip_period.val; ++ /* delta time between last sample and last interrupt */ ++ delta = it->lo - ts->timestamp; ++ /* if there are multiple samples, go back to first one */ ++ while (delta >= (fifo_period * 3 / 2)) ++ delta -= fifo_period; ++ /* compute maximal adjustment value */ ++ m = INV_ICM42600_TIMESTAMP_MAX_PERIOD(ts->period) - ts->period; ++ if (delta > m) ++ delta = m; ++ else if (delta < -m) ++ delta = -m; ++ ts->timestamp += delta; ++ } ++} ++EXPORT_SYMBOL_NS_GPL(inv_icm42600_timestamp_interrupt, IIO_INV_SENSORS_TIMESTAMP); ++ ++void inv_icm42600_timestamp_apply_odr(struct inv_icm42600_timestamp *ts, ++ uint32_t fifo_period, size_t fifo_nb, ++ unsigned int fifo_no) ++{ ++ int64_t interval; ++ uint32_t fifo_mult; ++ ++ if (ts->new_mult == 0) ++ return; ++ ++ /* update to new multiplier and update period */ ++ ts->mult = ts->new_mult; ++ ts->new_mult = 0; ++ ts->period = ts->mult * ts->chip_period.val; ++ ++ /* ++ * After ODR change the time interval with the previous sample is ++ * undertermined (depends when the change occures). So we compute the ++ * timestamp from the current interrupt using the new FIFO period, the ++ * total number of samples and the current sample numero. ++ */ ++ if (ts->timestamp != 0) { ++ /* compute measured fifo period */ ++ fifo_mult = fifo_period / INV_ICM42600_TIMESTAMP_PERIOD; ++ fifo_period = fifo_mult * ts->chip_period.val; ++ /* computes time interval between interrupt and this sample */ ++ interval = (int64_t)(fifo_nb - fifo_no) * (int64_t)fifo_period; ++ ts->timestamp = ts->it.up - interval; ++ } ++} ++EXPORT_SYMBOL_NS_GPL(inv_icm42600_timestamp_apply_odr, IIO_INV_SENSORS_TIMESTAMP); ++ ++MODULE_AUTHOR("InvenSense, Inc."); ++MODULE_DESCRIPTION("InvenSense sensors timestamp module"); ++MODULE_LICENSE("GPL"); +--- a/drivers/iio/imu/inv_icm42600/Kconfig ++++ b/drivers/iio/imu/inv_icm42600/Kconfig +@@ -3,6 +3,7 @@ + config INV_ICM42600 + tristate + select IIO_BUFFER ++ select IIO_INV_SENSORS_TIMESTAMP + + config INV_ICM42600_I2C + tristate "InvenSense ICM-426xx I2C driver" +--- a/drivers/iio/imu/inv_icm42600/Makefile ++++ b/drivers/iio/imu/inv_icm42600/Makefile +@@ -6,7 +6,6 @@ inv-icm42600-y += inv_icm42600_gyro.o + inv-icm42600-y += inv_icm42600_accel.o + inv-icm42600-y += inv_icm42600_temp.o + inv-icm42600-y += inv_icm42600_buffer.o +-inv-icm42600-y += inv_icm42600_timestamp.o + + obj-$(CONFIG_INV_ICM42600_I2C) += inv-icm42600-i2c.o + inv-icm42600-i2c-y += inv_icm42600_i2c.o +--- a/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c ++++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c +@@ -10,14 +10,15 @@ + #include + #include + #include +-#include ++ + #include ++#include ++#include + #include + + #include "inv_icm42600.h" + #include "inv_icm42600_temp.h" + #include "inv_icm42600_buffer.h" +-#include "inv_icm42600_timestamp.h" + + #define INV_ICM42600_ACCEL_CHAN(_modifier, _index, _ext_info) \ + { \ +--- a/drivers/iio/imu/inv_icm42600/inv_icm42600_buffer.c ++++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_buffer.c +@@ -9,11 +9,12 @@ + #include + #include + #include +-#include ++ + #include ++#include ++#include + + #include "inv_icm42600.h" +-#include "inv_icm42600_timestamp.h" + #include "inv_icm42600_buffer.h" + + /* FIFO header: 1 byte */ +--- a/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c ++++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c +@@ -15,11 +15,12 @@ + #include + #include + #include ++ ++#include + #include + + #include "inv_icm42600.h" + #include "inv_icm42600_buffer.h" +-#include "inv_icm42600_timestamp.h" + + static const struct regmap_range_cfg inv_icm42600_regmap_ranges[] = { + { +@@ -798,3 +799,4 @@ EXPORT_SYMBOL_GPL(inv_icm42600_pm_ops); + MODULE_AUTHOR("InvenSense, Inc."); + MODULE_DESCRIPTION("InvenSense ICM-426xx device driver"); + MODULE_LICENSE("GPL"); ++MODULE_IMPORT_NS(IIO_INV_SENSORS_TIMESTAMP); +--- a/drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c ++++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c +@@ -10,14 +10,15 @@ + #include + #include + #include +-#include ++ + #include ++#include ++#include + #include + + #include "inv_icm42600.h" + #include "inv_icm42600_temp.h" + #include "inv_icm42600_buffer.h" +-#include "inv_icm42600_timestamp.h" + + #define INV_ICM42600_GYRO_CHAN(_modifier, _index, _ext_info) \ + { \ +--- a/drivers/iio/imu/inv_icm42600/inv_icm42600_timestamp.c ++++ /dev/null +@@ -1,183 +0,0 @@ +-// SPDX-License-Identifier: GPL-2.0-or-later +-/* +- * Copyright (C) 2020 Invensense, Inc. +- */ +- +-#include +-#include +-#include +- +-#include "inv_icm42600_timestamp.h" +- +-/* internal chip period is 32kHz, 31250ns */ +-#define INV_ICM42600_TIMESTAMP_PERIOD 31250 +-/* allow a jitter of +/- 2% */ +-#define INV_ICM42600_TIMESTAMP_JITTER 2 +-/* compute min and max periods accepted */ +-#define INV_ICM42600_TIMESTAMP_MIN_PERIOD(_p) \ +- (((_p) * (100 - INV_ICM42600_TIMESTAMP_JITTER)) / 100) +-#define INV_ICM42600_TIMESTAMP_MAX_PERIOD(_p) \ +- (((_p) * (100 + INV_ICM42600_TIMESTAMP_JITTER)) / 100) +- +-/* Add a new value inside an accumulator and update the estimate value */ +-static void inv_update_acc(struct inv_icm42600_timestamp_acc *acc, uint32_t val) +-{ +- uint64_t sum = 0; +- size_t i; +- +- acc->values[acc->idx++] = val; +- if (acc->idx >= ARRAY_SIZE(acc->values)) +- acc->idx = 0; +- +- /* compute the mean of all stored values, use 0 as empty slot */ +- for (i = 0; i < ARRAY_SIZE(acc->values); ++i) { +- if (acc->values[i] == 0) +- break; +- sum += acc->values[i]; +- } +- +- acc->val = div_u64(sum, i); +-} +- +-void inv_icm42600_timestamp_init(struct inv_icm42600_timestamp *ts, +- uint32_t period) +-{ +- /* initial odr for sensor after reset is 1kHz */ +- const uint32_t default_period = 1000000; +- +- /* current multiplier and period values after reset */ +- ts->mult = default_period / INV_ICM42600_TIMESTAMP_PERIOD; +- ts->period = default_period; +- /* new set multiplier is the one from chip initialization */ +- ts->new_mult = period / INV_ICM42600_TIMESTAMP_PERIOD; +- +- /* use theoretical value for chip period */ +- inv_update_acc(&ts->chip_period, INV_ICM42600_TIMESTAMP_PERIOD); +-} +- +-int inv_icm42600_timestamp_update_odr(struct inv_icm42600_timestamp *ts, +- uint32_t period, bool fifo) +-{ +- /* when FIFO is on, prevent odr change if one is already pending */ +- if (fifo && ts->new_mult != 0) +- return -EAGAIN; +- +- ts->new_mult = period / INV_ICM42600_TIMESTAMP_PERIOD; +- +- return 0; +-} +- +-static bool inv_validate_period(uint32_t period, uint32_t mult) +-{ +- const uint32_t chip_period = INV_ICM42600_TIMESTAMP_PERIOD; +- uint32_t period_min, period_max; +- +- /* check that period is acceptable */ +- period_min = INV_ICM42600_TIMESTAMP_MIN_PERIOD(chip_period) * mult; +- period_max = INV_ICM42600_TIMESTAMP_MAX_PERIOD(chip_period) * mult; +- if (period > period_min && period < period_max) +- return true; +- else +- return false; +-} +- +-static bool inv_compute_chip_period(struct inv_icm42600_timestamp *ts, +- uint32_t mult, uint32_t period) +-{ +- uint32_t new_chip_period; +- +- if (!inv_validate_period(period, mult)) +- return false; +- +- /* update chip internal period estimation */ +- new_chip_period = period / mult; +- inv_update_acc(&ts->chip_period, new_chip_period); +- +- return true; +-} +- +-void inv_icm42600_timestamp_interrupt(struct inv_icm42600_timestamp *ts, +- uint32_t fifo_period, size_t fifo_nb, +- size_t sensor_nb, int64_t timestamp) +-{ +- struct inv_icm42600_timestamp_interval *it; +- int64_t delta, interval; +- const uint32_t fifo_mult = fifo_period / INV_ICM42600_TIMESTAMP_PERIOD; +- uint32_t period = ts->period; +- int32_t m; +- bool valid = false; +- +- if (fifo_nb == 0) +- return; +- +- /* update interrupt timestamp and compute chip and sensor periods */ +- it = &ts->it; +- it->lo = it->up; +- it->up = timestamp; +- delta = it->up - it->lo; +- if (it->lo != 0) { +- /* compute period: delta time divided by number of samples */ +- period = div_s64(delta, fifo_nb); +- valid = inv_compute_chip_period(ts, fifo_mult, period); +- /* update sensor period if chip internal period is updated */ +- if (valid) +- ts->period = ts->mult * ts->chip_period.val; +- } +- +- /* no previous data, compute theoritical value from interrupt */ +- if (ts->timestamp == 0) { +- /* elapsed time: sensor period * sensor samples number */ +- interval = (int64_t)ts->period * (int64_t)sensor_nb; +- ts->timestamp = it->up - interval; +- return; +- } +- +- /* if interrupt interval is valid, sync with interrupt timestamp */ +- if (valid) { +- /* compute measured fifo_period */ +- fifo_period = fifo_mult * ts->chip_period.val; +- /* delta time between last sample and last interrupt */ +- delta = it->lo - ts->timestamp; +- /* if there are multiple samples, go back to first one */ +- while (delta >= (fifo_period * 3 / 2)) +- delta -= fifo_period; +- /* compute maximal adjustment value */ +- m = INV_ICM42600_TIMESTAMP_MAX_PERIOD(ts->period) - ts->period; +- if (delta > m) +- delta = m; +- else if (delta < -m) +- delta = -m; +- ts->timestamp += delta; +- } +-} +- +-void inv_icm42600_timestamp_apply_odr(struct inv_icm42600_timestamp *ts, +- uint32_t fifo_period, size_t fifo_nb, +- unsigned int fifo_no) +-{ +- int64_t interval; +- uint32_t fifo_mult; +- +- if (ts->new_mult == 0) +- return; +- +- /* update to new multiplier and update period */ +- ts->mult = ts->new_mult; +- ts->new_mult = 0; +- ts->period = ts->mult * ts->chip_period.val; +- +- /* +- * After ODR change the time interval with the previous sample is +- * undertermined (depends when the change occures). So we compute the +- * timestamp from the current interrupt using the new FIFO period, the +- * total number of samples and the current sample numero. +- */ +- if (ts->timestamp != 0) { +- /* compute measured fifo period */ +- fifo_mult = fifo_period / INV_ICM42600_TIMESTAMP_PERIOD; +- fifo_period = fifo_mult * ts->chip_period.val; +- /* computes time interval between interrupt and this sample */ +- interval = (int64_t)(fifo_nb - fifo_no) * (int64_t)fifo_period; +- ts->timestamp = ts->it.up - interval; +- } +-} +--- a/drivers/iio/imu/inv_icm42600/inv_icm42600_timestamp.h ++++ /dev/null +@@ -1,79 +0,0 @@ +-/* SPDX-License-Identifier: GPL-2.0-or-later */ +-/* +- * Copyright (C) 2020 Invensense, Inc. +- */ +- +-#ifndef INV_ICM42600_TIMESTAMP_H_ +-#define INV_ICM42600_TIMESTAMP_H_ +- +-/** +- * struct inv_icm42600_timestamp_interval - timestamps interval +- * @lo: interval lower bound +- * @up: interval upper bound +- */ +-struct inv_icm42600_timestamp_interval { +- int64_t lo; +- int64_t up; +-}; +- +-/** +- * struct inv_icm42600_timestamp_acc - accumulator for computing an estimation +- * @val: current estimation of the value, the mean of all values +- * @idx: current index of the next free place in values table +- * @values: table of all measured values, use for computing the mean +- */ +-struct inv_icm42600_timestamp_acc { +- uint32_t val; +- size_t idx; +- uint32_t values[32]; +-}; +- +-/** +- * struct inv_icm42600_timestamp - timestamp management states +- * @it: interrupts interval timestamps +- * @timestamp: store last timestamp for computing next data timestamp +- * @mult: current internal period multiplier +- * @new_mult: new set internal period multiplier (not yet effective) +- * @period: measured current period of the sensor +- * @chip_period: accumulator for computing internal chip period +- */ +-struct inv_icm42600_timestamp { +- struct inv_icm42600_timestamp_interval it; +- int64_t timestamp; +- uint32_t mult; +- uint32_t new_mult; +- uint32_t period; +- struct inv_icm42600_timestamp_acc chip_period; +-}; +- +-void inv_icm42600_timestamp_init(struct inv_icm42600_timestamp *ts, +- uint32_t period); +- +-int inv_icm42600_timestamp_update_odr(struct inv_icm42600_timestamp *ts, +- uint32_t period, bool fifo); +- +-void inv_icm42600_timestamp_interrupt(struct inv_icm42600_timestamp *ts, +- uint32_t fifo_period, size_t fifo_nb, +- size_t sensor_nb, int64_t timestamp); +- +-static inline int64_t +-inv_icm42600_timestamp_pop(struct inv_icm42600_timestamp *ts) +-{ +- ts->timestamp += ts->period; +- return ts->timestamp; +-} +- +-void inv_icm42600_timestamp_apply_odr(struct inv_icm42600_timestamp *ts, +- uint32_t fifo_period, size_t fifo_nb, +- unsigned int fifo_no); +- +-static inline void +-inv_icm42600_timestamp_reset(struct inv_icm42600_timestamp *ts) +-{ +- const struct inv_icm42600_timestamp_interval interval_init = {0LL, 0LL}; +- +- ts->it = interval_init; +- ts->timestamp = 0; +-} +- +-#endif +--- /dev/null ++++ b/include/linux/iio/common/inv_icm42600_timestamp.h +@@ -0,0 +1,79 @@ ++/* SPDX-License-Identifier: GPL-2.0-or-later */ ++/* ++ * Copyright (C) 2020 Invensense, Inc. ++ */ ++ ++#ifndef INV_ICM42600_TIMESTAMP_H_ ++#define INV_ICM42600_TIMESTAMP_H_ ++ ++/** ++ * struct inv_icm42600_timestamp_interval - timestamps interval ++ * @lo: interval lower bound ++ * @up: interval upper bound ++ */ ++struct inv_icm42600_timestamp_interval { ++ int64_t lo; ++ int64_t up; ++}; ++ ++/** ++ * struct inv_icm42600_timestamp_acc - accumulator for computing an estimation ++ * @val: current estimation of the value, the mean of all values ++ * @idx: current index of the next free place in values table ++ * @values: table of all measured values, use for computing the mean ++ */ ++struct inv_icm42600_timestamp_acc { ++ uint32_t val; ++ size_t idx; ++ uint32_t values[32]; ++}; ++ ++/** ++ * struct inv_icm42600_timestamp - timestamp management states ++ * @it: interrupts interval timestamps ++ * @timestamp: store last timestamp for computing next data timestamp ++ * @mult: current internal period multiplier ++ * @new_mult: new set internal period multiplier (not yet effective) ++ * @period: measured current period of the sensor ++ * @chip_period: accumulator for computing internal chip period ++ */ ++struct inv_icm42600_timestamp { ++ struct inv_icm42600_timestamp_interval it; ++ int64_t timestamp; ++ uint32_t mult; ++ uint32_t new_mult; ++ uint32_t period; ++ struct inv_icm42600_timestamp_acc chip_period; ++}; ++ ++void inv_icm42600_timestamp_init(struct inv_icm42600_timestamp *ts, ++ uint32_t period); ++ ++int inv_icm42600_timestamp_update_odr(struct inv_icm42600_timestamp *ts, ++ uint32_t period, bool fifo); ++ ++void inv_icm42600_timestamp_interrupt(struct inv_icm42600_timestamp *ts, ++ uint32_t fifo_period, size_t fifo_nb, ++ size_t sensor_nb, int64_t timestamp); ++ ++static inline int64_t ++inv_icm42600_timestamp_pop(struct inv_icm42600_timestamp *ts) ++{ ++ ts->timestamp += ts->period; ++ return ts->timestamp; ++} ++ ++void inv_icm42600_timestamp_apply_odr(struct inv_icm42600_timestamp *ts, ++ uint32_t fifo_period, size_t fifo_nb, ++ unsigned int fifo_no); ++ ++static inline void ++inv_icm42600_timestamp_reset(struct inv_icm42600_timestamp *ts) ++{ ++ const struct inv_icm42600_timestamp_interval interval_init = {0LL, 0LL}; ++ ++ ts->it = interval_init; ++ ts->timestamp = 0; ++} ++ ++#endif diff --git a/queue-5.10/leds-lm3601x-improve-error-reporting-for-problems-during-.remove.patch b/queue-5.10/leds-lm3601x-improve-error-reporting-for-problems-during-.remove.patch new file mode 100644 index 0000000000..d5e0a79be0 --- /dev/null +++ b/queue-5.10/leds-lm3601x-improve-error-reporting-for-problems-during-.remove.patch @@ -0,0 +1,54 @@ +From stable+bounces-277537-greg=kroah.com@vger.kernel.org Mon Jul 20 04:35:49 2026 +From: Sasha Levin +Date: Sun, 19 Jul 2026 22:35:37 -0400 +Subject: leds: lm3601x: Improve error reporting for problems during .remove() +To: stable@vger.kernel.org +Cc: "Uwe Kleine-König" , "Pavel Machek" , "Wolfram Sang" , "Sasha Levin" +Message-ID: <20260720023539.2968115-3-sashal@kernel.org> + +From: Uwe Kleine-König + +[ Upstream commit 22a23436891886a66d21af3619f4a4e8809f0e0a ] + +Returning an error value in an i2c remove callback results in a generic +error message being emitted by the i2c core, but otherwise it doesn't +make a difference. The device goes away anyhow and the devm cleanups are +called. + +So instead of triggering the generic i2c error message, emit a more +helpful message if a problem occurs and return 0 to suppress the generic +message. + +This patch is a preparation for making i2c remove callbacks return void. + +Acked-by: Pavel Machek +Signed-off-by: Uwe Kleine-König +Signed-off-by: Wolfram Sang +Stable-dep-of: 1f0bdc2884b6 ("usb: typec: ucsi: ccg: Fix use-after-free of ucsi on remove") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/leds/leds-lm3601x.c | 11 ++++++++--- + 1 file changed, 8 insertions(+), 3 deletions(-) + +--- a/drivers/leds/leds-lm3601x.c ++++ b/drivers/leds/leds-lm3601x.c +@@ -443,10 +443,15 @@ static int lm3601x_probe(struct i2c_clie + static int lm3601x_remove(struct i2c_client *client) + { + struct lm3601x_led *led = i2c_get_clientdata(client); ++ int ret; + +- return regmap_update_bits(led->regmap, LM3601X_ENABLE_REG, +- LM3601X_ENABLE_MASK, +- LM3601X_MODE_STANDBY); ++ ret = regmap_update_bits(led->regmap, LM3601X_ENABLE_REG, ++ LM3601X_ENABLE_MASK, LM3601X_MODE_STANDBY); ++ if (ret) ++ dev_warn(&client->dev, ++ "Failed to put into standby (%pe)\n", ERR_PTR(ret)); ++ ++ return 0; + } + + static const struct i2c_device_id lm3601x_id[] = { diff --git a/queue-5.10/leds-lm3697-remove-duplicated-error-reporting-in-.remove.patch b/queue-5.10/leds-lm3697-remove-duplicated-error-reporting-in-.remove.patch new file mode 100644 index 0000000000..362383cbb8 --- /dev/null +++ b/queue-5.10/leds-lm3697-remove-duplicated-error-reporting-in-.remove.patch @@ -0,0 +1,48 @@ +From stable+bounces-277536-greg=kroah.com@vger.kernel.org Mon Jul 20 04:35:48 2026 +From: Sasha Levin +Date: Sun, 19 Jul 2026 22:35:36 -0400 +Subject: leds: lm3697: Remove duplicated error reporting in .remove() +To: stable@vger.kernel.org +Cc: "Uwe Kleine-König" , "Pavel Machek" , "Wolfram Sang" , "Sasha Levin" +Message-ID: <20260720023539.2968115-2-sashal@kernel.org> + +From: Uwe Kleine-König + +[ Upstream commit af89fa11fae1cee4e07453f780e6e5573ef0f477 ] + +Returning an error value from an i2c remove callback results in an error +message being emitted by the i2c core, but otherwise it doesn't make a +difference. The device goes away anyhow and the devm cleanups are +called. + +As lm3697_remove() already emits an error message on failure and the +additional error message by the i2c core doesn't add any useful +information, don't pass the error value up the stack. Instead continue +to clean up and return 0. + +This patch is a preparation for making i2c remove callbacks return void. + +Acked-by: Pavel Machek +Signed-off-by: Uwe Kleine-König +Signed-off-by: Wolfram Sang +Stable-dep-of: 1f0bdc2884b6 ("usb: typec: ucsi: ccg: Fix use-after-free of ucsi on remove") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/leds/leds-lm3697.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +--- a/drivers/leds/leds-lm3697.c ++++ b/drivers/leds/leds-lm3697.c +@@ -337,10 +337,8 @@ static int lm3697_remove(struct i2c_clie + + ret = regmap_update_bits(led->regmap, LM3697_CTRL_ENABLE, + LM3697_CTRL_A_B_EN, 0); +- if (ret) { ++ if (ret) + dev_err(dev, "Failed to disable the device\n"); +- return ret; +- } + + if (led->enable_gpio) + gpiod_direction_output(led->enable_gpio, 0); diff --git a/queue-5.10/media-atomisp-replace-boolean-comparison-of-values-with-bool-variables.patch b/queue-5.10/media-atomisp-replace-boolean-comparison-of-values-with-bool-variables.patch new file mode 100644 index 0000000000..35035ac596 --- /dev/null +++ b/queue-5.10/media-atomisp-replace-boolean-comparison-of-values-with-bool-variables.patch @@ -0,0 +1,153 @@ +From stable+bounces-274527-greg=kroah.com@vger.kernel.org Tue Jul 14 22:02:12 2026 +From: Sasha Levin +Date: Tue, 14 Jul 2026 16:01:53 -0400 +Subject: media: atomisp: replace boolean comparison of values with bool variables +To: stable@vger.kernel.org +Cc: Aditya Srivastava , Mauro Carvalho Chehab , Sasha Levin +Message-ID: <20260714200158.3152137-1-sashal@kernel.org> + +From: Aditya Srivastava + +[ Upstream commit c606970d4250dfb95869a563975c08bab148137a ] + +There are certain expressions in a condition in atomisp, where a boolean +variable is compared with true/false in forms such as (foo == true) +or (false != bar), which does not comply with the coding style rule by +checkpatch.pl (CHK: BOOL_COMPARISON), according to which the boolean +variables should be themselves used in the condition, rather than +comparing with true or false. + +E.g. In drivers/staging/media/atomisp/pci/atomisp_compat_css20.c: + +if (asd->stream_prepared == false) { + +Can be replaced with: +if (!asd->stream_prepared) { + +Replace such expressions with boolean variables appropriately. + +Link: https://lore.kernel.org/linux-media/20201214132716.28157-1-yashsri421@gmail.com +Signed-off-by: Aditya Srivastava +Signed-off-by: Mauro Carvalho Chehab +Stable-dep-of: f4d51e55dd47 ("staging: media: atomisp: reduce load_primary_binaries() stack usage") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/staging/media/atomisp/pci/atomisp_compat_css20.c | 2 - + drivers/staging/media/atomisp/pci/runtime/isys/src/virtual_isys.c | 12 +++++----- + drivers/staging/media/atomisp/pci/sh_css.c | 12 +++++----- + 3 files changed, 13 insertions(+), 13 deletions(-) + +--- a/drivers/staging/media/atomisp/pci/atomisp_compat_css20.c ++++ b/drivers/staging/media/atomisp/pci/atomisp_compat_css20.c +@@ -1142,7 +1142,7 @@ int atomisp_css_start(struct atomisp_sub + * Thus the stream created in set_fmt get destroyed and need to be + * recreated in the next stream on. + */ +- if (asd->stream_prepared == false) { ++ if (!asd->stream_prepared) { + if (__create_pipes(asd)) { + dev_err(isp->dev, "create pipe error.\n"); + return -EINVAL; +--- a/drivers/staging/media/atomisp/pci/runtime/isys/src/virtual_isys.c ++++ b/drivers/staging/media/atomisp/pci/runtime/isys/src/virtual_isys.c +@@ -179,12 +179,12 @@ ia_css_isys_error_t ia_css_isys_stream_c + isys_stream->linked_isys_stream_id = isys_stream_descr->linked_isys_stream_id; + rc = create_input_system_input_port(isys_stream_descr, + &isys_stream->input_port); +- if (rc == false) ++ if (!rc) + return false; + + rc = create_input_system_channel(isys_stream_descr, false, + &isys_stream->channel); +- if (rc == false) { ++ if (!rc) { + destroy_input_system_input_port(&isys_stream->input_port); + return false; + } +@@ -204,7 +204,7 @@ ia_css_isys_error_t ia_css_isys_stream_c + if (isys_stream_descr->metadata.enable) { + rc = create_input_system_channel(isys_stream_descr, true, + &isys_stream->md_channel); +- if (rc == false) { ++ if (!rc) { + destroy_input_system_input_port(&isys_stream->input_port); + destroy_input_system_channel(&isys_stream->channel); + return false; +@@ -248,7 +248,7 @@ ia_css_isys_error_t ia_css_isys_stream_c + isys_stream_descr, + &isys_stream_cfg->channel_cfg, + false); +- if (rc == false) ++ if (!rc) + return false; + + /* configure metadata channel */ +@@ -260,7 +260,7 @@ ia_css_isys_error_t ia_css_isys_stream_c + isys_stream_descr, + &isys_stream_cfg->md_channel_cfg, + true); +- if (rc == false) ++ if (!rc) + return false; + } + +@@ -269,7 +269,7 @@ ia_css_isys_error_t ia_css_isys_stream_c + &isys_stream->input_port, + isys_stream_descr, + &isys_stream_cfg->input_port_cfg); +- if (rc == false) ++ if (!rc) + return false; + + isys_stream->valid = 1; +--- a/drivers/staging/media/atomisp/pci/sh_css.c ++++ b/drivers/staging/media/atomisp/pci/sh_css.c +@@ -1058,7 +1058,7 @@ sh_css_config_input_network(struct ia_cs + ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, + "sh_css_config_input_network() enter 0x%p:\n", stream); + +- if (stream->config.continuous == true) ++ if (stream->config.continuous) + { + if (stream->last_pipe->config.mode == IA_CSS_PIPE_MODE_CAPTURE) { + pipe = stream->last_pipe; +@@ -5622,7 +5622,7 @@ static int load_video_binaries(struct ia + } else { + /* output from main binary is not yuv line. currently this is + * possible only when bci is enabled on vfpp output */ +- assert(pipe->config.enable_vfpp_bci == true); ++ assert(pipe->config.enable_vfpp_bci); + ia_css_pipe_get_yuvscaler_binarydesc(pipe, &vf_pp_descr, + &mycs->video_binary.vf_frame_info, + pipe_vf_out_info, NULL, NULL); +@@ -8068,7 +8068,7 @@ create_host_regular_capture_pipeline(str + struct ia_css_frame *tmp_out_frame = NULL; + + for (i = 0; i < num_yuv_scaler; i++) { +- if (is_output_stage[i] == true) ++ if (is_output_stage[i]) + tmp_out_frame = out_frame; + else + tmp_out_frame = NULL; +@@ -8460,7 +8460,7 @@ sh_css_pipeline_add_acc_stage(struct ia_ + /* In QoS case, load_extension already called, so skipping */ + int err = 0; + +- if (fw->loaded == false) ++ if (!fw->loaded) + err = acc_load_extension(fw); + + ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, +@@ -9697,8 +9697,8 @@ ia_css_stream_destroy(struct ia_css_stre + assert(entry); + if (entry) { + /* get the SP thread id */ +- if (ia_css_pipeline_get_sp_thread_id( +- ia_css_pipe_get_pipe_num(entry), &sp_thread_id) != true) ++ if (!ia_css_pipeline_get_sp_thread_id( ++ ia_css_pipe_get_pipe_num(entry), &sp_thread_id)) + return -EINVAL; + /* get the target input terminal */ + sp_pipeline_input_terminal = diff --git a/queue-5.10/media-staging-media-atomisp-fix-alignment-and-line-length-issues.patch b/queue-5.10/media-staging-media-atomisp-fix-alignment-and-line-length-issues.patch new file mode 100644 index 0000000000..a242b43af8 --- /dev/null +++ b/queue-5.10/media-staging-media-atomisp-fix-alignment-and-line-length-issues.patch @@ -0,0 +1,1519 @@ +From stable+bounces-274531-greg=kroah.com@vger.kernel.org Tue Jul 14 22:02:33 2026 +From: Sasha Levin +Date: Tue, 14 Jul 2026 16:01:57 -0400 +Subject: media: staging: media: atomisp: Fix alignment and line length issues +To: stable@vger.kernel.org +Cc: Martiros Shakhzadyan , Hans Verkuil , Mauro Carvalho Chehab , Sasha Levin +Message-ID: <20260714200158.3152137-5-sashal@kernel.org> + +From: Martiros Shakhzadyan + +[ Upstream commit 7796e455170efa1823457b17a292b1c65bb8c1e0 ] + +Fix alignment style issues and adjacent line length issues in sh_css.c + +Signed-off-by: Martiros Shakhzadyan +Signed-off-by: Hans Verkuil +Signed-off-by: Mauro Carvalho Chehab +Stable-dep-of: f4d51e55dd47 ("staging: media: atomisp: reduce load_primary_binaries() stack usage") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/staging/media/atomisp/pci/sh_css.c | 619 +++++++++++++++-------------- + 1 file changed, 333 insertions(+), 286 deletions(-) + +--- a/drivers/staging/media/atomisp/pci/sh_css.c ++++ b/drivers/staging/media/atomisp/pci/sh_css.c +@@ -242,8 +242,8 @@ ia_css_reset_defaults(struct sh_css *css + static void + sh_css_init_host_sp_control_vars(void); + +-static int set_num_primary_stages(unsigned int *num, +- enum ia_css_pipe_version version); ++static int ++set_num_primary_stages(unsigned int *num, enum ia_css_pipe_version version); + + static bool + need_capture_pp(const struct ia_css_pipe *pipe); +@@ -3002,9 +3002,8 @@ static int add_firmwares( + + ia_css_pipe_get_firmwares_stage_desc(&stage_desc, binary, + out, in, vf, fw, binary_mode); +- err = ia_css_pipeline_create_and_add_stage(me, +- &stage_desc, +- &extra_stage); ++ err = ia_css_pipeline_create_and_add_stage(me, &stage_desc, ++ &extra_stage); + if (err) + return err; + if (fw->info.isp.sp.enable.output != 0) +@@ -3112,9 +3111,8 @@ static int add_yuv_scaler_stage( + ia_css_pipe_get_generic_stage_desc(&stage_desc, + yuv_scaler_binary, out_frames, in_frame, vf_frame); + } +- err = ia_css_pipeline_create_and_add_stage(me, +- &stage_desc, +- pre_vf_pp_stage); ++ err = ia_css_pipeline_create_and_add_stage(me, &stage_desc, ++ pre_vf_pp_stage); + if (err) + return err; + in_frame = (*pre_vf_pp_stage)->args.out_frame[0]; +@@ -3172,9 +3170,8 @@ static int add_capture_pp_stage( + ia_css_pipe_get_generic_stage_desc(&stage_desc, + capture_pp_binary, out_frames, NULL, vf_frame); + } +- err = ia_css_pipeline_create_and_add_stage(me, +- &stage_desc, +- capture_pp_stage); ++ err = ia_css_pipeline_create_and_add_stage(me, &stage_desc, ++ capture_pp_stage); + if (err) + return err; + err = add_firmwares(me, capture_pp_binary, pipe->output_stage, last_fw, +@@ -3529,9 +3526,8 @@ static int create_host_video_pipeline(st + ia_css_pipe_util_set_output_frames(out_frames, 0, NULL); + ia_css_pipe_get_generic_stage_desc(&stage_desc, copy_binary, + out_frames, NULL, NULL); +- err = ia_css_pipeline_create_and_add_stage(me, +- &stage_desc, +- ©_stage); ++ err = ia_css_pipeline_create_and_add_stage(me, &stage_desc, ++ ©_stage); + if (err) + goto ERR; + in_frame = me->stages->args.out_frame[0]; +@@ -3558,9 +3554,8 @@ static int create_host_video_pipeline(st + ia_css_pipe_get_generic_stage_desc(&stage_desc, video_binary, + out_frames, in_frame, vf_frame); + } +- err = ia_css_pipeline_create_and_add_stage(me, +- &stage_desc, +- &video_stage); ++ err = ia_css_pipeline_create_and_add_stage(me, &stage_desc, ++ &video_stage); + if (err) + goto ERR; + +@@ -3625,8 +3620,8 @@ static int create_host_video_pipeline(st + for (i = 0; i < num_yuv_scaler; i++) { + tmp_out_frame = is_output_stage[i] ? out_frame : NULL; + +- err = add_yuv_scaler_stage(pipe, me, tmp_in_frame, tmp_out_frame, +- NULL, ++ err = add_yuv_scaler_stage(pipe, me, tmp_in_frame, ++ tmp_out_frame, NULL, + &yuv_scaler_binary[i], + &yuv_scaler_stage); + +@@ -3765,9 +3760,8 @@ create_host_preview_pipeline(struct ia_c + ia_css_pipe_util_set_output_frames(out_frames, 0, NULL); + ia_css_pipe_get_generic_stage_desc(&stage_desc, copy_binary, + out_frames, NULL, NULL); +- err = ia_css_pipeline_create_and_add_stage(me, +- &stage_desc, +- ©_stage); ++ err = ia_css_pipeline_create_and_add_stage(me, &stage_desc, ++ ©_stage); + if (err) + goto ERR; + in_frame = me->stages->args.out_frame[0]; +@@ -3793,9 +3787,8 @@ create_host_preview_pipeline(struct ia_c + ia_css_pipe_get_generic_stage_desc(&stage_desc, preview_binary, + out_frames, in_frame, NULL); + } +- err = ia_css_pipeline_create_and_add_stage(me, +- &stage_desc, +- &preview_stage); ++ err = ia_css_pipeline_create_and_add_stage(me, &stage_desc, ++ &preview_stage); + if (err) + goto ERR; + /* If we use copy iso preview, the input must be yuv iso raw */ +@@ -4131,8 +4124,8 @@ ia_css_pipe_enqueue_buffer(struct ia_css + } + + hmm_store(h_vbuf->vptr, +- (void *)(&ddr_buffer), +- sizeof(struct sh_css_hmm_buffer)); ++ (void *)(&ddr_buffer), ++ sizeof(struct sh_css_hmm_buffer)); + if ((buf_type == IA_CSS_BUFFER_TYPE_3A_STATISTICS) + || (buf_type == IA_CSS_BUFFER_TYPE_DIS_STATISTICS) + || (buf_type == IA_CSS_BUFFER_TYPE_LACE_STATISTICS)) { +@@ -4293,8 +4286,8 @@ ia_css_pipe_dequeue_buffer(struct ia_css + } + + hmm_load(ddr_buffer_addr, +- &ddr_buffer, +- sizeof(struct sh_css_hmm_buffer)); ++ &ddr_buffer, ++ sizeof(struct sh_css_hmm_buffer)); + + /* if the kernel_ptr is 0 or an invalid, return an error. + * do not access the buffer via the kernal_ptr. +@@ -4949,7 +4942,7 @@ sh_css_pipes_stop(struct ia_css_stream * + for (i = 0; i < stream->num_pipes; i++) { + /* send the "stop" request to the "ia_css_pipe" instance */ + IA_CSS_LOG("Send the stop-request to the pipe: pipe_id=%d", +- stream->pipes[i]->pipeline.pipe_id); ++ stream->pipes[i]->pipeline.pipe_id); + err = ia_css_pipeline_request_stop(&stream->pipes[i]->pipeline); + + /* +@@ -4999,7 +4992,7 @@ sh_css_pipes_stop(struct ia_css_stream * + + /* send the "stop" request to "Copy Pipe" */ + IA_CSS_LOG("Send the stop-request to the pipe: pipe_id=%d", +- copy_pipe->pipeline.pipe_id); ++ copy_pipe->pipeline.pipe_id); + err = ia_css_pipeline_request_stop(©_pipe->pipeline); + } + +@@ -5832,7 +5825,7 @@ static bool need_capt_ldc( + } + + static int set_num_primary_stages(unsigned int *num, +- enum ia_css_pipe_version version) ++ enum ia_css_pipe_version version) + { + int err = 0; + +@@ -6032,10 +6025,13 @@ static int load_primary_binaries( + capt_pp_in_info = &prim_out_info; + + ia_css_pipe_get_capturepp_binarydesc(pipe, +- &capture_pp_descr, capt_pp_in_info, +- &capt_pp_out_info, &vf_info); ++ &capture_pp_descr, ++ capt_pp_in_info, ++ &capt_pp_out_info, ++ &vf_info); ++ + err = ia_css_binary_find(&capture_pp_descr, +- &mycs->capture_pp_binary); ++ &mycs->capture_pp_binary); + if (err) { + IA_CSS_LEAVE_ERR_PRIVATE(err); + return err; +@@ -6045,11 +6041,12 @@ static int load_primary_binaries( + struct ia_css_binary_descr capt_ldc_descr; + + ia_css_pipe_get_ldc_binarydesc(pipe, +- &capt_ldc_descr, &prim_out_info, +- &capt_ldc_out_info); ++ &capt_ldc_descr, ++ &prim_out_info, ++ &capt_ldc_out_info); + + err = ia_css_binary_find(&capt_ldc_descr, +- &mycs->capture_ldc_binary); ++ &mycs->capture_ldc_binary); + if (err) { + IA_CSS_LEAVE_ERR_PRIVATE(err); + return err; +@@ -6066,8 +6063,9 @@ static int load_primary_binaries( + if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0] && + (i == mycs->num_primary_stage - 1)) + local_vf_info = &vf_info; +- ia_css_pipe_get_primary_binarydesc(pipe, &prim_descr[i], &prim_in_info, +- &prim_out_info, local_vf_info, i); ++ ia_css_pipe_get_primary_binarydesc(pipe, &prim_descr[i], ++ &prim_in_info, &prim_out_info, ++ local_vf_info, i); + err = ia_css_binary_find(&prim_descr[i], &mycs->primary_binary[i]); + if (err) { + IA_CSS_LEAVE_ERR_PRIVATE(err); +@@ -6119,8 +6117,8 @@ static int load_primary_binaries( + /* ISP Copy */ + if (need_isp_copy_binary) { + err = load_copy_binary(pipe, +- &mycs->copy_binary, +- &mycs->primary_binary[0]); ++ &mycs->copy_binary, ++ &mycs->primary_binary[0]); + if (err) { + IA_CSS_LEAVE_ERR_PRIVATE(err); + return err; +@@ -6229,7 +6227,7 @@ static int load_advanced_binaries( + + assert(pipe); + assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE || +- pipe->mode == IA_CSS_PIPE_ID_COPY); ++ pipe->mode == IA_CSS_PIPE_ID_COPY); + if (pipe->pipe_settings.capture.pre_isp_binary.info) + return 0; + pipe_out_info = &pipe->output_info[0]; +@@ -6242,17 +6240,18 @@ static int load_advanced_binaries( + need_pp = need_capture_pp(pipe); + + ia_css_frame_info_set_format(&vf_info, +- IA_CSS_FRAME_FORMAT_YUV_LINE); ++ IA_CSS_FRAME_FORMAT_YUV_LINE); + + /* we build up the pipeline starting at the end */ + /* Capture post-processing */ + if (need_pp) { + struct ia_css_binary_descr capture_pp_descr; + +- ia_css_pipe_get_capturepp_binarydesc(pipe, +- &capture_pp_descr, &post_out_info, pipe_out_info, &vf_info); ++ ia_css_pipe_get_capturepp_binarydesc(pipe, &capture_pp_descr, ++ &post_out_info, ++ pipe_out_info, &vf_info); + err = ia_css_binary_find(&capture_pp_descr, +- &pipe->pipe_settings.capture.capture_pp_binary); ++ &pipe->pipe_settings.capture.capture_pp_binary); + if (err) + return err; + } else { +@@ -6263,10 +6262,11 @@ static int load_advanced_binaries( + { + struct ia_css_binary_descr post_gdc_descr; + +- ia_css_pipe_get_post_gdc_binarydesc(pipe, +- &post_gdc_descr, &post_in_info, &post_out_info, &vf_info); ++ ia_css_pipe_get_post_gdc_binarydesc(pipe, &post_gdc_descr, ++ &post_in_info, ++ &post_out_info, &vf_info); + err = ia_css_binary_find(&post_gdc_descr, +- &pipe->pipe_settings.capture.post_isp_binary); ++ &pipe->pipe_settings.capture.post_isp_binary); + if (err) + return err; + } +@@ -6276,9 +6276,9 @@ static int load_advanced_binaries( + struct ia_css_binary_descr gdc_descr; + + ia_css_pipe_get_gdc_binarydesc(pipe, &gdc_descr, &gdc_in_info, +- &pipe->pipe_settings.capture.post_isp_binary.in_frame_info); ++ &pipe->pipe_settings.capture.post_isp_binary.in_frame_info); + err = ia_css_binary_find(&gdc_descr, +- &pipe->pipe_settings.capture.anr_gdc_binary); ++ &pipe->pipe_settings.capture.anr_gdc_binary); + if (err) + return err; + } +@@ -6290,9 +6290,9 @@ static int load_advanced_binaries( + struct ia_css_binary_descr pre_gdc_descr; + + ia_css_pipe_get_pre_gdc_binarydesc(pipe, &pre_gdc_descr, &pre_in_info, +- &pipe->pipe_settings.capture.anr_gdc_binary.in_frame_info); ++ &pipe->pipe_settings.capture.anr_gdc_binary.in_frame_info); + err = ia_css_binary_find(&pre_gdc_descr, +- &pipe->pipe_settings.capture.pre_isp_binary); ++ &pipe->pipe_settings.capture.pre_isp_binary); + if (err) + return err; + } +@@ -6314,7 +6314,7 @@ static int load_advanced_binaries( + ia_css_pipe_get_vfpp_binarydesc(pipe, + &vf_pp_descr, vf_pp_in_info, pipe_vf_out_info); + err = ia_css_binary_find(&vf_pp_descr, +- &pipe->pipe_settings.capture.vf_pp_binary); ++ &pipe->pipe_settings.capture.vf_pp_binary); + if (err) + return err; + } +@@ -6326,8 +6326,8 @@ static int load_advanced_binaries( + #endif + if (need_isp_copy) + load_copy_binary(pipe, +- &pipe->pipe_settings.capture.copy_binary, +- &pipe->pipe_settings.capture.pre_isp_binary); ++ &pipe->pipe_settings.capture.copy_binary, ++ &pipe->pipe_settings.capture.pre_isp_binary); + + return err; + } +@@ -6342,7 +6342,7 @@ static int load_bayer_isp_binaries( + IA_CSS_ENTER_PRIVATE(""); + assert(pipe); + assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE || +- pipe->mode == IA_CSS_PIPE_ID_COPY); ++ pipe->mode == IA_CSS_PIPE_ID_COPY); + pipe_out_info = &pipe->output_info[0]; + + if (pipe->pipe_settings.capture.pre_isp_binary.info) +@@ -6353,11 +6353,11 @@ static int load_bayer_isp_binaries( + return err; + + ia_css_pipe_get_pre_de_binarydesc(pipe, &pre_de_descr, +- &pre_isp_in_info, +- pipe_out_info); ++ &pre_isp_in_info, ++ pipe_out_info); + + err = ia_css_binary_find(&pre_de_descr, +- &pipe->pipe_settings.capture.pre_isp_binary); ++ &pipe->pipe_settings.capture.pre_isp_binary); + + return err; + } +@@ -6376,7 +6376,7 @@ static int load_low_light_binaries( + IA_CSS_ENTER_PRIVATE(""); + assert(pipe); + assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE || +- pipe->mode == IA_CSS_PIPE_ID_COPY); ++ pipe->mode == IA_CSS_PIPE_ID_COPY); + + if (pipe->pipe_settings.capture.pre_isp_binary.info) + return 0; +@@ -6391,17 +6391,18 @@ static int load_low_light_binaries( + need_pp = need_capture_pp(pipe); + + ia_css_frame_info_set_format(&vf_info, +- IA_CSS_FRAME_FORMAT_YUV_LINE); ++ IA_CSS_FRAME_FORMAT_YUV_LINE); + + /* we build up the pipeline starting at the end */ + /* Capture post-processing */ + if (need_pp) { + struct ia_css_binary_descr capture_pp_descr; + +- ia_css_pipe_get_capturepp_binarydesc(pipe, +- &capture_pp_descr, &post_out_info, pipe_out_info, &vf_info); ++ ia_css_pipe_get_capturepp_binarydesc(pipe, &capture_pp_descr, ++ &post_out_info, ++ pipe_out_info, &vf_info); + err = ia_css_binary_find(&capture_pp_descr, +- &pipe->pipe_settings.capture.capture_pp_binary); ++ &pipe->pipe_settings.capture.capture_pp_binary); + if (err) + return err; + } else { +@@ -6415,7 +6416,7 @@ static int load_low_light_binaries( + ia_css_pipe_get_post_anr_binarydesc(pipe, + &post_anr_descr, &post_in_info, &post_out_info, &vf_info); + err = ia_css_binary_find(&post_anr_descr, +- &pipe->pipe_settings.capture.post_isp_binary); ++ &pipe->pipe_settings.capture.post_isp_binary); + if (err) + return err; + } +@@ -6425,9 +6426,9 @@ static int load_low_light_binaries( + struct ia_css_binary_descr anr_descr; + + ia_css_pipe_get_anr_binarydesc(pipe, &anr_descr, &anr_in_info, +- &pipe->pipe_settings.capture.post_isp_binary.in_frame_info); ++ &pipe->pipe_settings.capture.post_isp_binary.in_frame_info); + err = ia_css_binary_find(&anr_descr, +- &pipe->pipe_settings.capture.anr_gdc_binary); ++ &pipe->pipe_settings.capture.anr_gdc_binary); + if (err) + return err; + } +@@ -6439,9 +6440,9 @@ static int load_low_light_binaries( + struct ia_css_binary_descr pre_anr_descr; + + ia_css_pipe_get_pre_anr_binarydesc(pipe, &pre_anr_descr, &pre_in_info, +- &pipe->pipe_settings.capture.anr_gdc_binary.in_frame_info); ++ &pipe->pipe_settings.capture.anr_gdc_binary.in_frame_info); + err = ia_css_binary_find(&pre_anr_descr, +- &pipe->pipe_settings.capture.pre_isp_binary); ++ &pipe->pipe_settings.capture.pre_isp_binary); + if (err) + return err; + } +@@ -6460,10 +6461,10 @@ static int load_low_light_binaries( + { + struct ia_css_binary_descr vf_pp_descr; + +- ia_css_pipe_get_vfpp_binarydesc(pipe, +- &vf_pp_descr, vf_pp_in_info, pipe_vf_out_info); ++ ia_css_pipe_get_vfpp_binarydesc(pipe, &vf_pp_descr, ++ vf_pp_in_info, pipe_vf_out_info); + err = ia_css_binary_find(&vf_pp_descr, +- &pipe->pipe_settings.capture.vf_pp_binary); ++ &pipe->pipe_settings.capture.vf_pp_binary); + if (err) + return err; + } +@@ -6475,8 +6476,8 @@ static int load_low_light_binaries( + #endif + if (need_isp_copy) + err = load_copy_binary(pipe, +- &pipe->pipe_settings.capture.copy_binary, +- &pipe->pipe_settings.capture.pre_isp_binary); ++ &pipe->pipe_settings.capture.copy_binary, ++ &pipe->pipe_settings.capture.pre_isp_binary); + + return err; + } +@@ -6510,7 +6511,7 @@ static int load_capture_binaries( + IA_CSS_ENTER_PRIVATE(""); + assert(pipe); + assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE || +- pipe->mode == IA_CSS_PIPE_ID_COPY); ++ pipe->mode == IA_CSS_PIPE_ID_COPY); + + if (pipe->pipe_settings.capture.primary_binary[0].info) { + IA_CSS_LEAVE_ERR_PRIVATE(0); +@@ -6605,7 +6606,7 @@ unload_capture_binaries(struct ia_css_pi + + static bool + need_downscaling(const struct ia_css_resolution in_res, +- const struct ia_css_resolution out_res) ++ const struct ia_css_resolution out_res) + { + if (in_res.width > out_res.width || in_res.height > out_res.height) + return true; +@@ -6676,9 +6677,9 @@ static int ia_css_pipe_create_cas_scaler + descr->num_output_stage = 1; + + hor_ds_factor = CEIL_DIV(cas_scaler_in_info->res.width, +- cas_scaler_out_info->res.width); ++ cas_scaler_out_info->res.width); + ver_ds_factor = CEIL_DIV(cas_scaler_in_info->res.height, +- cas_scaler_out_info->res.height); ++ cas_scaler_out_info->res.height); + /* use the same horizontal and vertical downscaling factor for simplicity */ + assert(hor_ds_factor == ver_ds_factor); + +@@ -6688,31 +6689,36 @@ static int ia_css_pipe_create_cas_scaler + i *= max_scale_factor_per_stage; + } + +- descr->in_info = kmalloc(descr->num_stage * sizeof(struct ia_css_frame_info), +- GFP_KERNEL); ++ descr->in_info = kmalloc(descr->num_stage * ++ sizeof(struct ia_css_frame_info), ++ GFP_KERNEL); + if (!descr->in_info) { + err = -ENOMEM; + goto ERR; + } +- descr->internal_out_info = kmalloc(descr->num_stage * sizeof( +- struct ia_css_frame_info), GFP_KERNEL); ++ descr->internal_out_info = kmalloc(descr->num_stage * ++ sizeof(struct ia_css_frame_info), ++ GFP_KERNEL); + if (!descr->internal_out_info) { + err = -ENOMEM; + goto ERR; + } +- descr->out_info = kmalloc(descr->num_stage * sizeof(struct ia_css_frame_info), +- GFP_KERNEL); ++ descr->out_info = kmalloc(descr->num_stage * ++ sizeof(struct ia_css_frame_info), ++ GFP_KERNEL); + if (!descr->out_info) { + err = -ENOMEM; + goto ERR; + } +- descr->vf_info = kmalloc(descr->num_stage * sizeof(struct ia_css_frame_info), +- GFP_KERNEL); ++ descr->vf_info = kmalloc(descr->num_stage * ++ sizeof(struct ia_css_frame_info), ++ GFP_KERNEL); + if (!descr->vf_info) { + err = -ENOMEM; + goto ERR; + } +- descr->is_output_stage = kmalloc(descr->num_stage * sizeof(bool), GFP_KERNEL); ++ descr->is_output_stage = kmalloc(descr->num_stage * sizeof(bool), ++ GFP_KERNEL); + if (!descr->is_output_stage) { + err = -ENOMEM; + goto ERR; +@@ -6756,9 +6762,9 @@ static int ia_css_pipe_create_cas_scaler + max_scale_factor_per_stage; + descr->internal_out_info[i].format = IA_CSS_FRAME_FORMAT_YUV420; + ia_css_frame_info_init(&descr->internal_out_info[i], +- tmp_in_info.res.width / max_scale_factor_per_stage, +- tmp_in_info.res.height / max_scale_factor_per_stage, +- IA_CSS_FRAME_FORMAT_YUV420, 0); ++ tmp_in_info.res.width / max_scale_factor_per_stage, ++ tmp_in_info.res.height / max_scale_factor_per_stage, ++ IA_CSS_FRAME_FORMAT_YUV420, 0); + descr->out_info[i].res.width = 0; + descr->out_info[i].res.height = 0; + descr->vf_info[i].res.width = 0; +@@ -6834,30 +6840,35 @@ static int ia_css_pipe_create_cas_scaler + descr->num_stage = num_stages; + + descr->in_info = kmalloc_array(descr->num_stage, +- sizeof(struct ia_css_frame_info), GFP_KERNEL); ++ sizeof(struct ia_css_frame_info), ++ GFP_KERNEL); + if (!descr->in_info) { + err = -ENOMEM; + goto ERR; + } +- descr->internal_out_info = kmalloc(descr->num_stage * sizeof( +- struct ia_css_frame_info), GFP_KERNEL); ++ descr->internal_out_info = kmalloc(descr->num_stage * ++ sizeof(struct ia_css_frame_info), ++ GFP_KERNEL); + if (!descr->internal_out_info) { + err = -ENOMEM; + goto ERR; + } +- descr->out_info = kmalloc(descr->num_stage * sizeof(struct ia_css_frame_info), +- GFP_KERNEL); ++ descr->out_info = kmalloc(descr->num_stage * ++ sizeof(struct ia_css_frame_info), ++ GFP_KERNEL); + if (!descr->out_info) { + err = -ENOMEM; + goto ERR; + } +- descr->vf_info = kmalloc(descr->num_stage * sizeof(struct ia_css_frame_info), +- GFP_KERNEL); ++ descr->vf_info = kmalloc(descr->num_stage * ++ sizeof(struct ia_css_frame_info), ++ GFP_KERNEL); + if (!descr->vf_info) { + err = -ENOMEM; + goto ERR; + } +- descr->is_output_stage = kmalloc(descr->num_stage * sizeof(bool), GFP_KERNEL); ++ descr->is_output_stage = kmalloc(descr->num_stage * sizeof(bool), ++ GFP_KERNEL); + if (!descr->is_output_stage) { + err = -ENOMEM; + goto ERR; +@@ -6867,7 +6878,7 @@ static int ia_css_pipe_create_cas_scaler + if (out_info[i]) { + if (i > 0) { + assert((out_info[i - 1]->res.width >= out_info[i]->res.width) && +- (out_info[i - 1]->res.height >= out_info[i]->res.height)); ++ (out_info[i - 1]->res.height >= out_info[i]->res.height)); + } + } + } +@@ -6915,9 +6926,9 @@ static int ia_css_pipe_create_cas_scaler + max_scale_factor_per_stage; + descr->internal_out_info[i].format = IA_CSS_FRAME_FORMAT_YUV420; + ia_css_frame_info_init(&descr->internal_out_info[i], +- tmp_in_info.res.width / max_scale_factor_per_stage, +- tmp_in_info.res.height / max_scale_factor_per_stage, +- IA_CSS_FRAME_FORMAT_YUV420, 0); ++ tmp_in_info.res.width / max_scale_factor_per_stage, ++ tmp_in_info.res.height / max_scale_factor_per_stage, ++ IA_CSS_FRAME_FORMAT_YUV420, 0); + descr->out_info[i].res.width = 0; + descr->out_info[i].res.height = 0; + descr->vf_info[i].res.width = 0; +@@ -6996,13 +7007,14 @@ load_yuvpp_binaries(struct ia_css_pipe * + struct ia_css_binary_descr yuv_scaler_descr; + + err = ia_css_pipe_create_cas_scaler_desc(pipe, +- &cas_scaler_descr); ++ &cas_scaler_descr); + if (err) + goto ERR; + mycs->num_output = cas_scaler_descr.num_output_stage; + mycs->num_yuv_scaler = cas_scaler_descr.num_stage; + mycs->yuv_scaler_binary = kzalloc(cas_scaler_descr.num_stage * +- sizeof(struct ia_css_binary), GFP_KERNEL); ++ sizeof(struct ia_css_binary), ++ GFP_KERNEL); + if (!mycs->yuv_scaler_binary) { + err = -ENOMEM; + goto ERR; +@@ -7016,12 +7028,13 @@ load_yuvpp_binaries(struct ia_css_pipe * + for (i = 0; i < cas_scaler_descr.num_stage; i++) { + mycs->is_output_stage[i] = cas_scaler_descr.is_output_stage[i]; + ia_css_pipe_get_yuvscaler_binarydesc(pipe, +- &yuv_scaler_descr, &cas_scaler_descr.in_info[i], +- &cas_scaler_descr.out_info[i], +- &cas_scaler_descr.internal_out_info[i], +- &cas_scaler_descr.vf_info[i]); ++ &yuv_scaler_descr, ++ &cas_scaler_descr.in_info[i], ++ &cas_scaler_descr.out_info[i], ++ &cas_scaler_descr.internal_out_info[i], ++ &cas_scaler_descr.vf_info[i]); + err = ia_css_binary_find(&yuv_scaler_descr, +- &mycs->yuv_scaler_binary[i]); ++ &mycs->yuv_scaler_binary[i]); + if (err) + goto ERR; + } +@@ -7061,8 +7074,8 @@ load_yuvpp_binaries(struct ia_css_pipe * + + if (need_isp_copy_binary) { + err = load_copy_binary(pipe, +- &mycs->copy_binary, +- next_binary); ++ &mycs->copy_binary, ++ next_binary); + + if (err) + goto ERR; +@@ -7107,8 +7120,9 @@ load_yuvpp_binaries(struct ia_css_pipe * + + mycs->num_vf_pp = 1; + } +- mycs->vf_pp_binary = kzalloc(mycs->num_vf_pp * sizeof(struct ia_css_binary), +- GFP_KERNEL); ++ mycs->vf_pp_binary = kzalloc(mycs->num_vf_pp * ++ sizeof(struct ia_css_binary), ++ GFP_KERNEL); + if (!mycs->vf_pp_binary) { + err = -ENOMEM; + goto ERR; +@@ -7437,18 +7451,26 @@ create_host_yuvpp_pipeline(struct ia_css + #endif + + if (need_scaler) { +- ia_css_pipe_util_set_output_frames(bin_out_frame, 0, NULL); +- ia_css_pipe_get_generic_stage_desc(&stage_desc, copy_binary, +- bin_out_frame, in_frame_local, NULL); ++ ia_css_pipe_util_set_output_frames(bin_out_frame, ++ 0, NULL); ++ ia_css_pipe_get_generic_stage_desc(&stage_desc, ++ copy_binary, ++ bin_out_frame, ++ in_frame_local, ++ NULL); + } else { +- ia_css_pipe_util_set_output_frames(bin_out_frame, 0, out_frame[0]); +- ia_css_pipe_get_generic_stage_desc(&stage_desc, copy_binary, +- bin_out_frame, in_frame_local, NULL); ++ ia_css_pipe_util_set_output_frames(bin_out_frame, ++ 0, out_frame[0]); ++ ia_css_pipe_get_generic_stage_desc(&stage_desc, ++ copy_binary, ++ bin_out_frame, ++ in_frame_local, ++ NULL); + } + + err = ia_css_pipeline_create_and_add_stage(me, +- &stage_desc, +- ©_stage); ++ &stage_desc, ++ ©_stage); + + if (err) { + IA_CSS_LEAVE_ERR_PRIVATE(err); +@@ -7480,10 +7502,11 @@ create_host_yuvpp_pipeline(struct ia_css + tmp_vf_frame = NULL; + } + +- err = add_yuv_scaler_stage(pipe, me, tmp_in_frame, tmp_out_frame, +- NULL, +- &yuv_scaler_binary[i], +- &yuv_scaler_stage); ++ err = add_yuv_scaler_stage(pipe, me, tmp_in_frame, ++ tmp_out_frame, ++ NULL, ++ &yuv_scaler_binary[i], ++ &yuv_scaler_stage); + + if (err) { + IA_CSS_LEAVE_ERR_PRIVATE(err); +@@ -7494,8 +7517,10 @@ create_host_yuvpp_pipeline(struct ia_css + if (pipe->pipe_settings.yuvpp.is_output_stage[i]) { + if (tmp_vf_frame && (tmp_vf_frame->info.res.width != 0)) { + in_frame = yuv_scaler_stage->args.out_vf_frame; +- err = add_vf_pp_stage(pipe, in_frame, tmp_vf_frame, &vf_pp_binary[j], +- &vf_pp_stage); ++ err = add_vf_pp_stage(pipe, in_frame, ++ tmp_vf_frame, ++ &vf_pp_binary[j], ++ &vf_pp_stage); + + if (err) { + IA_CSS_LEAVE_ERR_PRIVATE(err); +@@ -7508,8 +7533,8 @@ create_host_yuvpp_pipeline(struct ia_css + } else if (copy_stage) { + if (vf_frame[0] && vf_frame[0]->info.res.width != 0) { + in_frame = copy_stage->args.out_vf_frame; +- err = add_vf_pp_stage(pipe, in_frame, vf_frame[0], &vf_pp_binary[0], +- &vf_pp_stage); ++ err = add_vf_pp_stage(pipe, in_frame, vf_frame[0], ++ &vf_pp_binary[0], &vf_pp_stage); + } + if (err) { + IA_CSS_LEAVE_ERR_PRIVATE(err); +@@ -7517,7 +7542,8 @@ create_host_yuvpp_pipeline(struct ia_css + } + } + +- ia_css_pipeline_finalize_stages(&pipe->pipeline, pipe->stream->config.continuous); ++ ia_css_pipeline_finalize_stages(&pipe->pipeline, ++ pipe->stream->config.continuous); + + IA_CSS_LEAVE_ERR_PRIVATE(0); + +@@ -7526,8 +7552,8 @@ create_host_yuvpp_pipeline(struct ia_css + + static int + create_host_copy_pipeline(struct ia_css_pipe *pipe, +- unsigned int max_input_width, +- struct ia_css_frame *out_frame) ++ unsigned int max_input_width, ++ struct ia_css_frame *out_frame) + { + struct ia_css_pipeline *me; + int err = 0; +@@ -7546,12 +7572,8 @@ create_host_copy_pipeline(struct ia_css_ + + if (copy_on_sp(pipe) && + pipe->stream->config.input_config.format == ATOMISP_INPUT_FORMAT_BINARY_8) { +- ia_css_frame_info_init( +- &out_frame->info, +- JPEG_BYTES, +- 1, +- IA_CSS_FRAME_FORMAT_BINARY_8, +- 0); ++ ia_css_frame_info_init(&out_frame->info, JPEG_BYTES, 1, ++ IA_CSS_FRAME_FORMAT_BINARY_8, 0); + } else if (out_frame->info.format == IA_CSS_FRAME_FORMAT_RAW) { + out_frame->info.raw_bit_depth = + ia_css_pipe_util_pipe_input_format_bpp(pipe); +@@ -7562,12 +7584,12 @@ create_host_copy_pipeline(struct ia_css_ + pipe->mode = IA_CSS_PIPE_ID_COPY; + + ia_css_pipe_get_sp_func_stage_desc(&stage_desc, out_frame, +- IA_CSS_PIPELINE_RAW_COPY, max_input_width); +- err = ia_css_pipeline_create_and_add_stage(me, +- &stage_desc, +- NULL); ++ IA_CSS_PIPELINE_RAW_COPY, ++ max_input_width); ++ err = ia_css_pipeline_create_and_add_stage(me, &stage_desc, NULL); + +- ia_css_pipeline_finalize_stages(&pipe->pipeline, pipe->stream->config.continuous); ++ ia_css_pipeline_finalize_stages(&pipe->pipeline, ++ pipe->stream->config.continuous); + + ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, + "create_host_copy_pipeline() leave:\n"); +@@ -7606,9 +7628,10 @@ create_host_isyscopy_capture_pipeline(st + me->pipe_id = IA_CSS_PIPE_ID_CAPTURE; + pipe->mode = IA_CSS_PIPE_ID_CAPTURE; + ia_css_pipe_get_sp_func_stage_desc(&stage_desc, out_frame, +- IA_CSS_PIPELINE_ISYS_COPY, max_input_width); ++ IA_CSS_PIPELINE_ISYS_COPY, ++ max_input_width); + err = ia_css_pipeline_create_and_add_stage(me, +- &stage_desc, &out_stage); ++ &stage_desc, &out_stage); + if (err) + return err; + +@@ -7660,7 +7683,8 @@ create_host_regular_capture_pipeline(str + IA_CSS_ENTER_PRIVATE(""); + assert(pipe); + assert(pipe->stream); +- assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE || pipe->mode == IA_CSS_PIPE_ID_COPY); ++ assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE || ++ pipe->mode == IA_CSS_PIPE_ID_COPY); + + me = &pipe->pipeline; + mode = pipe->config.default_capture_config.mode; +@@ -7750,26 +7774,37 @@ create_host_regular_capture_pipeline(str + ia_css_pipe_util_set_output_frames(out_frames, 0, out_frame); + #if defined(ISP2401) + if (!continuous) { +- ia_css_pipe_get_generic_stage_desc(&stage_desc, copy_binary, +- out_frames, in_frame, NULL); ++ ia_css_pipe_get_generic_stage_desc(&stage_desc, ++ copy_binary, ++ out_frames, ++ in_frame, ++ NULL); + } else { + in_frame = pipe->stream->last_pipe->continuous_frames[0]; +- ia_css_pipe_get_generic_stage_desc(&stage_desc, copy_binary, +- out_frames, in_frame, NULL); ++ ia_css_pipe_get_generic_stage_desc(&stage_desc, ++ copy_binary, ++ out_frames, ++ in_frame, ++ NULL); + } + #else +- ia_css_pipe_get_generic_stage_desc(&stage_desc, copy_binary, +- out_frames, NULL, NULL); ++ ia_css_pipe_get_generic_stage_desc(&stage_desc, ++ copy_binary, ++ out_frames, ++ NULL, NULL); + #endif + } else { +- ia_css_pipe_util_set_output_frames(out_frames, 0, in_frame); +- ia_css_pipe_get_generic_stage_desc(&stage_desc, copy_binary, +- out_frames, NULL, NULL); ++ ia_css_pipe_util_set_output_frames(out_frames, 0, ++ in_frame); ++ ia_css_pipe_get_generic_stage_desc(&stage_desc, ++ copy_binary, ++ out_frames, ++ NULL, NULL); + } + + err = ia_css_pipeline_create_and_add_stage(me, +- &stage_desc, +- ¤t_stage); ++ &stage_desc, ++ ¤t_stage); + if (err) { + IA_CSS_LEAVE_ERR_PRIVATE(err); + return err; +@@ -7806,11 +7841,14 @@ create_host_regular_capture_pipeline(str + * Proper investigation should be done to come up with the clean + * solution. + * */ +- ia_css_pipe_get_generic_stage_desc(&stage_desc, primary_binary[i], +- out_frames, local_in_frame, NULL); ++ ia_css_pipe_get_generic_stage_desc(&stage_desc, ++ primary_binary[i], ++ out_frames, ++ local_in_frame, ++ NULL); + err = ia_css_pipeline_create_and_add_stage(me, +- &stage_desc, +- ¤t_stage); ++ &stage_desc, ++ ¤t_stage); + if (err) { + IA_CSS_LEAVE_ERR_PRIVATE(err); + return err; +@@ -7826,18 +7864,18 @@ create_host_regular_capture_pipeline(str + mode == IA_CSS_CAPTURE_MODE_LOW_LIGHT) { + ia_css_pipe_util_set_output_frames(out_frames, 0, NULL); + ia_css_pipe_get_generic_stage_desc(&stage_desc, pre_isp_binary, +- out_frames, in_frame, NULL); +- err = ia_css_pipeline_create_and_add_stage(me, +- &stage_desc, NULL); ++ out_frames, in_frame, NULL); ++ err = ia_css_pipeline_create_and_add_stage(me, &stage_desc, ++ NULL); + if (err) { + IA_CSS_LEAVE_ERR_PRIVATE(err); + return err; + } + ia_css_pipe_util_set_output_frames(out_frames, 0, NULL); + ia_css_pipe_get_generic_stage_desc(&stage_desc, anr_gdc_binary, +- out_frames, NULL, NULL); +- err = ia_css_pipeline_create_and_add_stage(me, +- &stage_desc, NULL); ++ out_frames, NULL, NULL); ++ err = ia_css_pipeline_create_and_add_stage(me, &stage_desc, ++ NULL); + if (err) { + IA_CSS_LEAVE_ERR_PRIVATE(err); + return err; +@@ -7845,16 +7883,21 @@ create_host_regular_capture_pipeline(str + + if (need_pp) { + ia_css_pipe_util_set_output_frames(out_frames, 0, NULL); +- ia_css_pipe_get_generic_stage_desc(&stage_desc, post_isp_binary, +- out_frames, NULL, NULL); ++ ia_css_pipe_get_generic_stage_desc(&stage_desc, ++ post_isp_binary, ++ out_frames, ++ NULL, NULL); + } else { +- ia_css_pipe_util_set_output_frames(out_frames, 0, out_frame); +- ia_css_pipe_get_generic_stage_desc(&stage_desc, post_isp_binary, +- out_frames, NULL, NULL); ++ ia_css_pipe_util_set_output_frames(out_frames, 0, ++ out_frame); ++ ia_css_pipe_get_generic_stage_desc(&stage_desc, ++ post_isp_binary, ++ out_frames, ++ NULL, NULL); + } + +- err = ia_css_pipeline_create_and_add_stage(me, +- &stage_desc, ¤t_stage); ++ err = ia_css_pipeline_create_and_add_stage(me, &stage_desc, ++ ¤t_stage); + if (err) { + IA_CSS_LEAVE_ERR_PRIVATE(err); + return err; +@@ -7862,10 +7905,9 @@ create_host_regular_capture_pipeline(str + } else if (mode == IA_CSS_CAPTURE_MODE_BAYER) { + ia_css_pipe_util_set_output_frames(out_frames, 0, out_frame); + ia_css_pipe_get_generic_stage_desc(&stage_desc, pre_isp_binary, +- out_frames, in_frame, NULL); +- err = ia_css_pipeline_create_and_add_stage(me, +- &stage_desc, +- NULL); ++ out_frames, in_frame, NULL); ++ err = ia_css_pipeline_create_and_add_stage(me, &stage_desc, ++ NULL); + if (err) { + IA_CSS_LEAVE_ERR_PRIVATE(err); + return err; +@@ -7880,31 +7922,34 @@ create_host_regular_capture_pipeline(str + + if (need_ldc) { + ia_css_pipe_util_set_output_frames(out_frames, 0, NULL); +- ia_css_pipe_get_generic_stage_desc(&stage_desc, capture_ldc_binary, +- out_frames, local_in_frame, NULL); ++ ia_css_pipe_get_generic_stage_desc(&stage_desc, ++ capture_ldc_binary, ++ out_frames, ++ local_in_frame, ++ NULL); + err = ia_css_pipeline_create_and_add_stage(me, +- &stage_desc, +- ¤t_stage); ++ &stage_desc, ++ ¤t_stage); + local_in_frame = current_stage->args.out_frame[0]; + } + err = add_capture_pp_stage(pipe, me, local_in_frame, +- need_yuv_pp ? NULL : out_frame, ++ need_yuv_pp ? NULL : out_frame, + #else + /* ldc and capture_pp not supported in same pipeline */ + if (need_ldc && current_stage) { + in_frame = current_stage->args.out_frame[0]; + ia_css_pipe_util_set_output_frames(out_frames, 0, out_frame); + ia_css_pipe_get_generic_stage_desc(&stage_desc, capture_ldc_binary, +- out_frames, in_frame, NULL); +- err = ia_css_pipeline_create_and_add_stage(me, +- &stage_desc, +- NULL); ++ out_frames, in_frame, NULL); ++ err = ia_css_pipeline_create_and_add_stage(me, &stage_desc, ++ NULL); + } else if (need_pp && current_stage) { + in_frame = current_stage->args.out_frame[0]; +- err = add_capture_pp_stage(pipe, me, in_frame, need_yuv_pp ? NULL : out_frame, ++ err = add_capture_pp_stage(pipe, me, in_frame, ++ need_yuv_pp ? NULL : out_frame, + #endif +- capture_pp_binary, +- ¤t_stage); ++ capture_pp_binary, ++ ¤t_stage); + if (err) { + IA_CSS_LEAVE_ERR_PRIVATE(err); + return err; +@@ -7921,10 +7966,10 @@ create_host_regular_capture_pipeline(str + else + tmp_out_frame = NULL; + +- err = add_yuv_scaler_stage(pipe, me, tmp_in_frame, tmp_out_frame, +- NULL, +- &yuv_scaler_binary[i], +- &yuv_scaler_stage); ++ err = add_yuv_scaler_stage(pipe, me, tmp_in_frame, ++ tmp_out_frame, NULL, ++ &yuv_scaler_binary[i], ++ &yuv_scaler_stage); + if (err) { + IA_CSS_LEAVE_ERR_PRIVATE(err); + return err; +@@ -7946,7 +7991,7 @@ create_host_regular_capture_pipeline(str + if (mode != IA_CSS_CAPTURE_MODE_RAW && mode != IA_CSS_CAPTURE_MODE_BAYER && current_stage && vf_frame) { + in_frame = current_stage->args.out_vf_frame; + err = add_vf_pp_stage(pipe, in_frame, vf_frame, vf_pp_binary, +- ¤t_stage); ++ ¤t_stage); + if (err) { + IA_CSS_LEAVE_ERR_PRIVATE(err); + return err; +@@ -7998,7 +8043,7 @@ static int capture_start( + me = &pipe->pipeline; + + if ((pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_RAW || +- pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_BAYER) && ++ pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_BAYER) && + (pipe->config.mode != IA_CSS_PIPE_MODE_COPY)) { + if (copy_on_sp(pipe)) { + err = start_copy_on_sp(pipe, &me->out_frame[0]); +@@ -8042,7 +8087,7 @@ static int capture_start( + if (pipe->config.mode == IA_CSS_PIPE_MODE_COPY && + pipe->stream->reconfigure_css_rx) { + ia_css_isys_rx_configure(&pipe->stream->csi_rx_config, +- pipe->stream->config.mode); ++ pipe->stream->config.mode); + pipe->stream->reconfigure_css_rx = false; + } + #endif +@@ -8053,8 +8098,8 @@ static int capture_start( + + static int + sh_css_pipe_get_output_frame_info(struct ia_css_pipe *pipe, +- struct ia_css_frame_info *info, +- unsigned int idx) ++ struct ia_css_frame_info *info, ++ unsigned int idx) + { + assert(pipe); + assert(info); +@@ -8072,7 +8117,7 @@ sh_css_pipe_get_output_frame_info(struct + IA_CSS_FRAME_FORMAT_BINARY_8, + 0); + } else if (info->format == IA_CSS_FRAME_FORMAT_RAW || +- info->format == IA_CSS_FRAME_FORMAT_RAW_PACKED) { ++ info->format == IA_CSS_FRAME_FORMAT_RAW_PACKED) { + info->raw_bit_depth = + ia_css_pipe_util_pipe_input_format_bpp(pipe); + } +@@ -8084,9 +8129,9 @@ sh_css_pipe_get_output_frame_info(struct + + void + ia_css_stream_send_input_frame(const struct ia_css_stream *stream, +- const unsigned short *data, +- unsigned int width, +- unsigned int height) ++ const unsigned short *data, ++ unsigned int width, ++ unsigned int height) + { + assert(stream); + +@@ -8110,22 +8155,22 @@ ia_css_stream_start_input_frame(const st + + void + ia_css_stream_send_input_line(const struct ia_css_stream *stream, +- const unsigned short *data, +- unsigned int width, +- const unsigned short *data2, +- unsigned int width2) ++ const unsigned short *data, ++ unsigned int width, ++ const unsigned short *data2, ++ unsigned int width2) + { + assert(stream); + + ia_css_inputfifo_send_line(stream->config.channel_id, +- data, width, data2, width2); ++ data, width, data2, width2); + } + + void + ia_css_stream_send_input_embedded_line(const struct ia_css_stream *stream, +- enum atomisp_input_format format, +- const unsigned short *data, +- unsigned int width) ++ enum atomisp_input_format format, ++ const unsigned short *data, ++ unsigned int width) + { + assert(stream); + if (!data || width == 0) +@@ -8246,7 +8291,7 @@ acc_unload_extension(struct ia_css_fw_in + /* Load firmware for extension */ + static int + ia_css_pipe_load_extension(struct ia_css_pipe *pipe, +- struct ia_css_fw_info *firmware) ++ struct ia_css_fw_info *firmware) + { + int err = 0; + +@@ -8270,7 +8315,7 @@ ia_css_pipe_load_extension(struct ia_css + /* Unload firmware for extension */ + static void + ia_css_pipe_unload_extension(struct ia_css_pipe *pipe, +- struct ia_css_fw_info *firmware) ++ struct ia_css_fw_info *firmware) + { + IA_CSS_ENTER_PRIVATE("fw = %p pipe = %p", firmware, pipe); + +@@ -8312,7 +8357,7 @@ ia_css_pipeline_uses_params(struct ia_cs + + static int + sh_css_pipeline_add_acc_stage(struct ia_css_pipeline *pipeline, +- const void *acc_fw) ++ const void *acc_fw) + { + struct ia_css_fw_info *fw = (struct ia_css_fw_info *)acc_fw; + /* In QoS case, load_extension already called, so skipping */ +@@ -8330,8 +8375,8 @@ sh_css_pipeline_add_acc_stage(struct ia_ + + ia_css_pipe_get_acc_stage_desc(&stage_desc, NULL, fw); + err = ia_css_pipeline_create_and_add_stage(pipeline, +- &stage_desc, +- NULL); ++ &stage_desc, ++ NULL); + } + + ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, +@@ -8344,7 +8389,7 @@ sh_css_pipeline_add_acc_stage(struct ia_ + * Refer to "sh_css_internal.h" for details. + */ + int ia_css_stream_capture_frame(struct ia_css_stream *stream, +- unsigned int exp_id) ++ unsigned int exp_id) + { + struct sh_css_tag_descr tag_descr; + u32 encoded_tag_descr; +@@ -8503,22 +8548,22 @@ sh_css_init_host_sp_control_vars(void) + (void)HIVE_ADDR_host_sp_com; + + sp_dmem_store_uint32(SP0_ID, +- (unsigned int)sp_address_of(ia_css_ispctrl_sp_isp_started), +- (uint32_t)(0)); ++ (unsigned int)sp_address_of(ia_css_ispctrl_sp_isp_started), ++ (uint32_t)(0)); + + sp_dmem_store_uint32(SP0_ID, +- (unsigned int)sp_address_of(host_sp_queues_initialized), +- (uint32_t)(0)); ++ (unsigned int)sp_address_of(host_sp_queues_initialized), ++ (uint32_t)(0)); + sp_dmem_store_uint32(SP0_ID, +- (unsigned int)sp_address_of(sp_sleep_mode), +- (uint32_t)(0)); ++ (unsigned int)sp_address_of(sp_sleep_mode), ++ (uint32_t)(0)); + sp_dmem_store_uint32(SP0_ID, +- (unsigned int)sp_address_of(ia_css_dmaproxy_sp_invalidate_tlb), +- (uint32_t)(false)); ++ (unsigned int)sp_address_of(ia_css_dmaproxy_sp_invalidate_tlb), ++ (uint32_t)(false)); + #ifndef ISP2401 + sp_dmem_store_uint32(SP0_ID, +- (unsigned int)sp_address_of(sp_stop_copy_preview), +- my_css.stop_copy_preview ? (uint32_t)(1) : (uint32_t)(0)); ++ (unsigned int)sp_address_of(sp_stop_copy_preview), ++ my_css.stop_copy_preview ? (uint32_t)(1) : (uint32_t)(0)); + #endif + store_sp_array_uint(host_sp_com, o, host2sp_cmd_ready); + +@@ -8545,8 +8590,7 @@ void ia_css_pipe_config_defaults(struct + } + + void +-ia_css_pipe_extra_config_defaults(struct ia_css_pipe_extra_config +- *extra_config) ++ia_css_pipe_extra_config_defaults(struct ia_css_pipe_extra_config *extra_config) + { + if (!extra_config) { + IA_CSS_ERROR("NULL input parameter"); +@@ -8620,8 +8664,8 @@ int ia_css_pipe_create(const struct ia_c + + int + ia_css_pipe_create_extra(const struct ia_css_pipe_config *config, +- const struct ia_css_pipe_extra_config *extra_config, +- struct ia_css_pipe **pipe) ++ const struct ia_css_pipe_extra_config *extra_config, ++ struct ia_css_pipe **pipe) + { + int err = -EINVAL; + struct ia_css_pipe *internal_pipe = NULL; +@@ -8689,7 +8733,7 @@ ia_css_pipe_create_extra(const struct ia + + /* YUV downscaling */ + if ((internal_pipe->config.vf_pp_in_res.width || +- internal_pipe->config.capt_pp_in_res.width)) { ++ internal_pipe->config.capt_pp_in_res.width)) { + enum ia_css_frame_format format; + + if (internal_pipe->config.vf_pp_in_res.width) { +@@ -8765,7 +8809,7 @@ ia_css_pipe_create_extra(const struct ia + } + if (internal_pipe->config.acc_extension) { + err = ia_css_pipe_load_extension(internal_pipe, +- internal_pipe->config.acc_extension); ++ internal_pipe->config.acc_extension); + if (err) { + IA_CSS_LEAVE_ERR_PRIVATE(err); + kvfree(internal_pipe); +@@ -8783,7 +8827,7 @@ ia_css_pipe_create_extra(const struct ia + + int + ia_css_pipe_get_info(const struct ia_css_pipe *pipe, +- struct ia_css_pipe_info *pipe_info) ++ struct ia_css_pipe_info *pipe_info) + { + ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, + "ia_css_pipe_get_info()\n"); +@@ -8821,8 +8865,8 @@ bool ia_css_pipe_has_dvs_stats(struct ia + + int + ia_css_pipe_override_frame_format(struct ia_css_pipe *pipe, +- int pin_index, +- enum ia_css_frame_format new_format) ++ int pin_index, ++ enum ia_css_frame_format new_format) + { + int err = 0; + +@@ -8902,10 +8946,8 @@ ia_css_stream_configure_rx(struct ia_css + #endif + + static struct ia_css_pipe * +-find_pipe(struct ia_css_pipe *pipes[], +- unsigned int num_pipes, +- enum ia_css_pipe_mode mode, +- bool copy_pipe) ++find_pipe(struct ia_css_pipe *pipes[], unsigned int num_pipes, ++ enum ia_css_pipe_mode mode, bool copy_pipe) + { + unsigned int i; + +@@ -8976,7 +9018,7 @@ ia_css_acc_stream_create(struct ia_css_s + + static int + metadata_info_init(const struct ia_css_metadata_config *mdc, +- struct ia_css_metadata_info *md) ++ struct ia_css_metadata_info *md) + { + /* Either both width and height should be set or neither */ + if ((mdc->resolution.height > 0) ^ (mdc->resolution.width > 0)) +@@ -9004,7 +9046,7 @@ static int check_pipe_resolutions(const + } + + if (ia_css_util_check_res(pipe->config.input_effective_res.width, +- pipe->config.input_effective_res.height) != 0) { ++ pipe->config.input_effective_res.height) != 0) { + IA_CSS_ERROR("effective resolution not supported"); + err = -EINVAL; + goto EXIT; +@@ -9012,7 +9054,7 @@ static int check_pipe_resolutions(const + if (!ia_css_util_resolution_is_zero( + pipe->stream->config.input_config.input_res)) { + if (!ia_css_util_res_leq(pipe->config.input_effective_res, +- pipe->stream->config.input_config.input_res)) { ++ pipe->stream->config.input_config.input_res)) { + IA_CSS_ERROR("effective resolution is larger than input resolution"); + err = -EINVAL; + goto EXIT; +@@ -9035,9 +9077,9 @@ EXIT: + + int + ia_css_stream_create(const struct ia_css_stream_config *stream_config, +- int num_pipes, +- struct ia_css_pipe *pipes[], +- struct ia_css_stream **stream) ++ int num_pipes, ++ struct ia_css_pipe *pipes[], ++ struct ia_css_stream **stream) + { + struct ia_css_pipe *curr_pipe; + struct ia_css_stream *curr_stream = NULL; +@@ -9198,11 +9240,11 @@ ia_css_stream_create(const struct ia_css + case IA_CSS_INPUT_MODE_TPG: + #if !defined(ISP2401) + IA_CSS_LOG("tpg_configuration: x_mask=%d, y_mask=%d, x_delta=%d, y_delta=%d, xy_mask=%d", +- curr_stream->config.source.tpg.x_mask, +- curr_stream->config.source.tpg.y_mask, +- curr_stream->config.source.tpg.x_delta, +- curr_stream->config.source.tpg.y_delta, +- curr_stream->config.source.tpg.xy_mask); ++ curr_stream->config.source.tpg.x_mask, ++ curr_stream->config.source.tpg.y_mask, ++ curr_stream->config.source.tpg.x_delta, ++ curr_stream->config.source.tpg.y_delta, ++ curr_stream->config.source.tpg.xy_mask); + + sh_css_sp_configure_tpg( + curr_stream->config.source.tpg.x_mask, +@@ -9227,9 +9269,8 @@ ia_css_stream_create(const struct ia_css + } + + #ifdef ISP2401 +- err = aspect_ratio_crop_init(curr_stream, +- pipes, +- &aspect_ratio_crop_enabled); ++ err = aspect_ratio_crop_init(curr_stream, pipes, ++ &aspect_ratio_crop_enabled); + if (err) { + IA_CSS_LEAVE_ERR(err); + goto ERR; +@@ -9266,8 +9307,8 @@ ia_css_stream_create(const struct ia_css + curr_pipe->config.input_effective_res = effective_res; + } + IA_CSS_LOG("effective_res=%dx%d", +- effective_res.width, +- effective_res.height); ++ effective_res.width, ++ effective_res.height); + } + + if (IS_ISP2401) { +@@ -9295,13 +9336,13 @@ ia_css_stream_create(const struct ia_css + if (!spcopyonly) { + sensor_binning_changed = + sh_css_params_set_binning_factor(curr_stream, +- curr_stream->config.sensor_binning_factor); ++ curr_stream->config.sensor_binning_factor); + } else { + sensor_binning_changed = false; + } + + IA_CSS_LOG("sensor_binning=%d, changed=%d", +- curr_stream->config.sensor_binning_factor, sensor_binning_changed); ++ curr_stream->config.sensor_binning_factor, sensor_binning_changed); + /* loop over pipes */ + IA_CSS_LOG("num_pipes=%d", num_pipes); + curr_stream->cont_capt = false; +@@ -9325,17 +9366,18 @@ ia_css_stream_create(const struct ia_css + + /* Create copy pipe here, since it may not be exposed to the driver */ + preview_pipe = find_pipe(pipes, num_pipes, +- IA_CSS_PIPE_MODE_PREVIEW, false); ++ IA_CSS_PIPE_MODE_PREVIEW, false); + video_pipe = find_pipe(pipes, num_pipes, +- IA_CSS_PIPE_MODE_VIDEO, false); +- acc_pipe = find_pipe(pipes, num_pipes, +- IA_CSS_PIPE_MODE_ACC, false); ++ IA_CSS_PIPE_MODE_VIDEO, false); ++ acc_pipe = find_pipe(pipes, num_pipes, IA_CSS_PIPE_MODE_ACC, ++ false); + if (acc_pipe && num_pipes == 2 && curr_stream->cont_capt) + curr_stream->cont_capt = + false; /* preview + QoS case will not need cont_capt switch */ + if (curr_stream->cont_capt) { + capture_pipe = find_pipe(pipes, num_pipes, +- IA_CSS_PIPE_MODE_CAPTURE, false); ++ IA_CSS_PIPE_MODE_CAPTURE, ++ false); + if (!capture_pipe) { + err = -EINVAL; + goto ERR; +@@ -9417,10 +9459,12 @@ ia_css_stream_create(const struct ia_css + if (!spcopyonly) { + if (!IS_ISP2401) + err = sh_css_pipe_get_shading_info(curr_pipe, +- &pipe_info->shading_info, NULL); ++ &pipe_info->shading_info, ++ NULL); + else + err = sh_css_pipe_get_shading_info(curr_pipe, +- &pipe_info->shading_info, &curr_pipe->config); ++ &pipe_info->shading_info, ++ &curr_pipe->config); + + if (err) + goto ERR; +@@ -9430,7 +9474,8 @@ ia_css_stream_create(const struct ia_css + goto ERR; + for (j = 0; j < IA_CSS_PIPE_MAX_OUTPUT_STAGE; j++) { + sh_css_pipe_get_viewfinder_frame_info(curr_pipe, +- &pipe_info->vf_output_info[j], j); ++ &pipe_info->vf_output_info[j], ++ j); + if (err) + goto ERR; + } +@@ -9615,7 +9660,7 @@ ia_css_stream_destroy(struct ia_css_stre + + int + ia_css_stream_get_info(const struct ia_css_stream *stream, +- struct ia_css_stream_info *stream_info) ++ struct ia_css_stream_info *stream_info) + { + ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_get_info: enter/exit\n"); + assert(stream); +@@ -9903,7 +9948,7 @@ ia_css_stream_get_3a_binary(const struct + + int + ia_css_stream_set_output_padded_width(struct ia_css_stream *stream, +- unsigned int output_padded_width) ++ unsigned int output_padded_width) + { + struct ia_css_pipe *pipe; + +@@ -10380,7 +10425,7 @@ ia_css_unlock_raw_frame(struct ia_css_st + */ + int + ia_css_pipe_set_qos_ext_state(struct ia_css_pipe *pipe, uint32_t fw_handle, +- bool enable) ++ bool enable) + { + unsigned int thread_id; + struct ia_css_pipeline_stage *stage; +@@ -10426,7 +10471,7 @@ ia_css_pipe_set_qos_ext_state(struct ia_ + */ + int + ia_css_pipe_get_qos_ext_state(struct ia_css_pipe *pipe, uint32_t fw_handle, +- bool *enable) ++ bool *enable) + { + struct ia_css_pipeline_stage *stage; + unsigned int thread_id; +@@ -10462,9 +10507,9 @@ ia_css_pipe_get_qos_ext_state(struct ia_ + /* ISP2401 */ + int + ia_css_pipe_update_qos_ext_mapped_arg(struct ia_css_pipe *pipe, +- u32 fw_handle, +- struct ia_css_isp_param_css_segments *css_seg, +- struct ia_css_isp_param_isp_segments *isp_seg) ++ u32 fw_handle, ++ struct ia_css_isp_param_css_segments *css_seg, ++ struct ia_css_isp_param_isp_segments *isp_seg) + { + unsigned int HIVE_ADDR_sp_group; + static struct sh_css_sp_group sp_group; +@@ -10499,7 +10544,7 @@ ia_css_pipe_update_qos_ext_mapped_arg(st + if (!err) { + /* Get the Extension State */ + enabled = (SH_CSS_QOS_STAGE_IS_ENABLED(&sh_css_sp_group.pipe[thread_id], +- stage->stage_num)) ? true : false; ++ stage->stage_num)) ? true : false; + /* Update mapped arg only when extension stage is not enabled */ + if (enabled) { + IA_CSS_ERROR("Leaving: cannot update when stage is enabled."); +@@ -10509,13 +10554,14 @@ ia_css_pipe_update_qos_ext_mapped_arg(st + + HIVE_ADDR_sp_group = fw->info.sp.group; + sp_dmem_load(SP0_ID, +- (unsigned int)sp_address_of(sp_group), +- &sp_group, sizeof(struct sh_css_sp_group)); ++ (unsigned int)sp_address_of(sp_group), ++ &sp_group, ++ sizeof(struct sh_css_sp_group)); + hmm_load(sp_group.pipe[thread_id].sp_stage_addr[stage_num], +- &sp_stage, sizeof(struct sh_css_sp_stage)); ++ &sp_stage, sizeof(struct sh_css_sp_stage)); + + hmm_load(sp_stage.isp_stage_addr, +- &isp_stage, sizeof(struct sh_css_isp_stage)); ++ &isp_stage, sizeof(struct sh_css_isp_stage)); + + for (mem = 0; mem < N_IA_CSS_ISP_MEMORIES; mem++) { + isp_stage.mem_initializers.params[IA_CSS_PARAM_CLASS_PARAM][mem].address = +@@ -10531,7 +10577,8 @@ ia_css_pipe_update_qos_ext_mapped_arg(st + } + + hmm_store(sp_stage.isp_stage_addr, +- &isp_stage, sizeof(struct sh_css_isp_stage)); ++ &isp_stage, ++ sizeof(struct sh_css_isp_stage)); + } + } + } +@@ -10542,8 +10589,8 @@ ia_css_pipe_update_qos_ext_mapped_arg(st + #ifdef ISP2401 + static int + aspect_ratio_crop_init(struct ia_css_stream *curr_stream, +- struct ia_css_pipe *pipes[], +- bool *do_crop_status) ++ struct ia_css_pipe *pipes[], ++ bool *do_crop_status) + { + int err = 0; + int i; +@@ -10589,7 +10636,7 @@ aspect_ratio_crop_check(bool enabled, st + + static int + aspect_ratio_crop(struct ia_css_pipe *curr_pipe, +- struct ia_css_resolution *effective_res) ++ struct ia_css_resolution *effective_res) + { + int err = 0; + struct ia_css_resolution crop_res; +@@ -10649,7 +10696,7 @@ aspect_ratio_crop(struct ia_css_pipe *cu + case IA_CSS_PIPE_MODE_YUVPP: + default: + IA_CSS_ERROR("aspect ratio cropping invalid args: mode[%d]\n", +- curr_pipe->config.mode); ++ curr_pipe->config.mode); + assert(0); + break; + } +@@ -10713,7 +10760,7 @@ static struct sh_css_hmm_buffer_record + + assert(h_vbuf); + assert((type > IA_CSS_BUFFER_TYPE_INVALID) && +- (type < IA_CSS_NUM_DYNAMIC_BUFFER_TYPE)); ++ (type < IA_CSS_NUM_DYNAMIC_BUFFER_TYPE)); + assert(kernel_ptr != 0); + + buffer_record = &hmm_buffer_record[0]; diff --git a/queue-5.10/media-staging-media-atomisp-fix-sh_css.c-brace-coding-style-issues.patch b/queue-5.10/media-staging-media-atomisp-fix-sh_css.c-brace-coding-style-issues.patch new file mode 100644 index 0000000000..8e3268a27b --- /dev/null +++ b/queue-5.10/media-staging-media-atomisp-fix-sh_css.c-brace-coding-style-issues.patch @@ -0,0 +1,655 @@ +From stable+bounces-274530-greg=kroah.com@vger.kernel.org Tue Jul 14 22:02:29 2026 +From: Sasha Levin +Date: Tue, 14 Jul 2026 16:01:54 -0400 +Subject: media: staging: media: atomisp: Fix sh_css.c brace coding style issues +To: stable@vger.kernel.org +Cc: Martiros Shakhzadyan , Hans Verkuil , Mauro Carvalho Chehab , Sasha Levin +Message-ID: <20260714200158.3152137-2-sashal@kernel.org> + +From: Martiros Shakhzadyan + +[ Upstream commit 6ceb557604e85c55bce0585216623c21c7a00453 ] + +Fix brace coding style issues. + +Signed-off-by: Martiros Shakhzadyan +Signed-off-by: Hans Verkuil +Signed-off-by: Mauro Carvalho Chehab +Stable-dep-of: f4d51e55dd47 ("staging: media: atomisp: reduce load_primary_binaries() stack usage") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/staging/media/atomisp/pci/sh_css.c | 224 +++++++++++------------------ + 1 file changed, 90 insertions(+), 134 deletions(-) + +--- a/drivers/staging/media/atomisp/pci/sh_css.c ++++ b/drivers/staging/media/atomisp/pci/sh_css.c +@@ -456,15 +456,15 @@ static enum ia_css_frame_format yuv422_c + * by the copy binary given the stream format. + * */ + static int +-verify_copy_out_frame_format(struct ia_css_pipe *pipe) { ++verify_copy_out_frame_format(struct ia_css_pipe *pipe) ++{ + enum ia_css_frame_format out_fmt = pipe->output_info[0].format; + unsigned int i, found = 0; + + assert(pipe); + assert(pipe->stream); + +- switch (pipe->stream->config.input_config.format) +- { ++ switch (pipe->stream->config.input_config.format) { + case ATOMISP_INPUT_FORMAT_YUV420_8_LEGACY: + case ATOMISP_INPUT_FORMAT_YUV420_8: + for (i = 0; i < ARRAY_SIZE(yuv420_copy_formats) && !found; i++) +@@ -532,7 +532,8 @@ ia_css_stream_input_format_bits_per_pixe + + #if !defined(ISP2401) + static int +-sh_css_config_input_network(struct ia_css_stream *stream) { ++sh_css_config_input_network(struct ia_css_stream *stream) ++{ + unsigned int fmt_type; + struct ia_css_pipe *pipe = stream->last_pipe; + struct ia_css_binary *binary = NULL; +@@ -558,8 +559,7 @@ sh_css_config_input_network(struct ia_cs + stream->config.mode); + + if ((binary && (binary->online || stream->config.continuous)) || +- pipe->config.mode == IA_CSS_PIPE_MODE_COPY) +- { ++ pipe->config.mode == IA_CSS_PIPE_MODE_COPY) { + err = ia_css_ifmtr_configure(&stream->config, + binary); + if (err) +@@ -567,8 +567,7 @@ sh_css_config_input_network(struct ia_cs + } + + if (stream->config.mode == IA_CSS_INPUT_MODE_TPG || +- stream->config.mode == IA_CSS_INPUT_MODE_PRBS) +- { ++ stream->config.mode == IA_CSS_INPUT_MODE_PRBS) { + unsigned int hblank_cycles = 100, + vblank_lines = 6, + width, +@@ -723,35 +722,32 @@ static bool sh_css_translate_stream_cfg_ + switch (stream_cfg->mode) { + case IA_CSS_INPUT_MODE_TPG: + +- if (stream_cfg->source.tpg.id == IA_CSS_TPG_ID0) { ++ if (stream_cfg->source.tpg.id == IA_CSS_TPG_ID0) + isys_stream_descr->input_port_id = INPUT_SYSTEM_PIXELGEN_PORT0_ID; +- } else if (stream_cfg->source.tpg.id == IA_CSS_TPG_ID1) { ++ else if (stream_cfg->source.tpg.id == IA_CSS_TPG_ID1) + isys_stream_descr->input_port_id = INPUT_SYSTEM_PIXELGEN_PORT1_ID; +- } else if (stream_cfg->source.tpg.id == IA_CSS_TPG_ID2) { ++ else if (stream_cfg->source.tpg.id == IA_CSS_TPG_ID2) + isys_stream_descr->input_port_id = INPUT_SYSTEM_PIXELGEN_PORT2_ID; +- } + + break; + case IA_CSS_INPUT_MODE_PRBS: + +- if (stream_cfg->source.prbs.id == IA_CSS_PRBS_ID0) { ++ if (stream_cfg->source.prbs.id == IA_CSS_PRBS_ID0) + isys_stream_descr->input_port_id = INPUT_SYSTEM_PIXELGEN_PORT0_ID; +- } else if (stream_cfg->source.prbs.id == IA_CSS_PRBS_ID1) { ++ else if (stream_cfg->source.prbs.id == IA_CSS_PRBS_ID1) + isys_stream_descr->input_port_id = INPUT_SYSTEM_PIXELGEN_PORT1_ID; +- } else if (stream_cfg->source.prbs.id == IA_CSS_PRBS_ID2) { ++ else if (stream_cfg->source.prbs.id == IA_CSS_PRBS_ID2) + isys_stream_descr->input_port_id = INPUT_SYSTEM_PIXELGEN_PORT2_ID; +- } + + break; + case IA_CSS_INPUT_MODE_BUFFERED_SENSOR: + +- if (stream_cfg->source.port.port == MIPI_PORT0_ID) { ++ if (stream_cfg->source.port.port == MIPI_PORT0_ID) + isys_stream_descr->input_port_id = INPUT_SYSTEM_CSI_PORT0_ID; +- } else if (stream_cfg->source.port.port == MIPI_PORT1_ID) { ++ else if (stream_cfg->source.port.port == MIPI_PORT1_ID) + isys_stream_descr->input_port_id = INPUT_SYSTEM_CSI_PORT1_ID; +- } else if (stream_cfg->source.port.port == MIPI_PORT2_ID) { ++ else if (stream_cfg->source.port.port == MIPI_PORT2_ID) + isys_stream_descr->input_port_id = INPUT_SYSTEM_CSI_PORT2_ID; +- } + + break; + default: +@@ -804,15 +800,14 @@ static bool sh_css_translate_stream_cfg_ + rc = true; + switch (stream_cfg->mode) { + case IA_CSS_INPUT_MODE_TPG: +- if (stream_cfg->source.tpg.mode == IA_CSS_TPG_MODE_RAMP) { ++ if (stream_cfg->source.tpg.mode == IA_CSS_TPG_MODE_RAMP) + isys_stream_descr->tpg_port_attr.mode = PIXELGEN_TPG_MODE_RAMP; +- } else if (stream_cfg->source.tpg.mode == IA_CSS_TPG_MODE_CHECKERBOARD) { ++ else if (stream_cfg->source.tpg.mode == IA_CSS_TPG_MODE_CHECKERBOARD) + isys_stream_descr->tpg_port_attr.mode = PIXELGEN_TPG_MODE_CHBO; +- } else if (stream_cfg->source.tpg.mode == IA_CSS_TPG_MODE_MONO) { ++ else if (stream_cfg->source.tpg.mode == IA_CSS_TPG_MODE_MONO) + isys_stream_descr->tpg_port_attr.mode = PIXELGEN_TPG_MODE_MONO; +- } else { ++ else + rc = false; +- } + + /* + * TODO +@@ -951,12 +946,12 @@ static bool sh_css_translate_stream_cfg_ + stream_cfg->mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR) && + stream_cfg->source.port.compression.type != IA_CSS_CSI2_COMPRESSION_TYPE_NONE) { + if (stream_cfg->source.port.compression.uncompressed_bits_per_pixel == +- UNCOMPRESSED_BITS_PER_PIXEL_10) { ++ UNCOMPRESSED_BITS_PER_PIXEL_10) + fmt_type = ATOMISP_INPUT_FORMAT_RAW_10; +- } else if (stream_cfg->source.port.compression.uncompressed_bits_per_pixel == +- UNCOMPRESSED_BITS_PER_PIXEL_12) { ++ else if (stream_cfg->source.port.compression.uncompressed_bits_per_pixel == ++ UNCOMPRESSED_BITS_PER_PIXEL_12) + fmt_type = ATOMISP_INPUT_FORMAT_RAW_12; +- } else ++ else + return false; + } + +@@ -1043,7 +1038,8 @@ static bool sh_css_translate_binary_info + } + + static int +-sh_css_config_input_network(struct ia_css_stream *stream) { ++sh_css_config_input_network(struct ia_css_stream *stream) ++{ + bool rc; + ia_css_isys_descr_t isys_stream_descr; + unsigned int sp_thread_id; +@@ -1058,19 +1054,16 @@ sh_css_config_input_network(struct ia_cs + ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, + "sh_css_config_input_network() enter 0x%p:\n", stream); + +- if (stream->config.continuous) +- { +- if (stream->last_pipe->config.mode == IA_CSS_PIPE_MODE_CAPTURE) { ++ if (stream->config.continuous) { ++ if (stream->last_pipe->config.mode == IA_CSS_PIPE_MODE_CAPTURE) + pipe = stream->last_pipe; +- } else if (stream->last_pipe->config.mode == IA_CSS_PIPE_MODE_YUVPP) { ++ else if (stream->last_pipe->config.mode == IA_CSS_PIPE_MODE_YUVPP) + pipe = stream->last_pipe; +- } else if (stream->last_pipe->config.mode == IA_CSS_PIPE_MODE_PREVIEW) { ++ else if (stream->last_pipe->config.mode == IA_CSS_PIPE_MODE_PREVIEW) + pipe = stream->last_pipe->pipe_settings.preview.copy_pipe; +- } else if (stream->last_pipe->config.mode == IA_CSS_PIPE_MODE_VIDEO) { ++ else if (stream->last_pipe->config.mode == IA_CSS_PIPE_MODE_VIDEO) + pipe = stream->last_pipe->pipe_settings.video.copy_pipe; +- } +- } else +- { ++ } else { + pipe = stream->last_pipe; + if (stream->last_pipe->config.mode == IA_CSS_PIPE_MODE_CAPTURE) { + /* +@@ -1093,8 +1086,7 @@ sh_css_config_input_network(struct ia_cs + if (pipe->pipeline.stages->binary) + binary = pipe->pipeline.stages->binary; + +- if (binary) +- { ++ if (binary) { + /* this was being done in ifmtr in 2400. + * online and cont bypass the init_in_frameinfo_memory_defaults + * so need to do it here +@@ -1208,11 +1200,10 @@ static inline struct ia_css_pipe *stream + struct ia_css_pipe *target_pipe; + + /* get the pipe that consumes the stream */ +- if (stream->config.continuous) { ++ if (stream->config.continuous) + target_pipe = stream_get_copy_pipe(stream); +- } else { ++ else + target_pipe = stream_get_last_pipe(stream); +- } + + return target_pipe; + } +@@ -1386,7 +1377,8 @@ start_binary(struct ia_css_pipe *pipe, + /* start the copy function on the SP */ + static int + start_copy_on_sp(struct ia_css_pipe *pipe, +- struct ia_css_frame *out_frame) { ++ struct ia_css_frame *out_frame) ++{ + (void)out_frame; + assert(pipe); + assert(pipe->stream); +@@ -1404,8 +1396,7 @@ start_copy_on_sp(struct ia_css_pipe *pip + sh_css_sp_start_binary_copy(ia_css_pipe_get_pipe_num(pipe), out_frame, pipe->stream->config.pixels_per_clock == 2); + + #if !defined(ISP2401) +- if (pipe->stream->reconfigure_css_rx) +- { ++ if (pipe->stream->reconfigure_css_rx) { + ia_css_isys_rx_configure(&pipe->stream->csi_rx_config, + pipe->stream->config.mode); + pipe->stream->reconfigure_css_rx = false; +@@ -1594,7 +1585,8 @@ ia_css_reset_defaults(struct sh_css *css + + int + ia_css_load_firmware(struct device *dev, const struct ia_css_env *env, +- const struct ia_css_fw *fw) { ++ const struct ia_css_fw *fw) ++{ + int err; + + if (!env) +@@ -1605,16 +1597,14 @@ ia_css_load_firmware(struct device *dev, + ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_load_firmware() enter\n"); + + /* make sure we initialize my_css */ +- if (my_css.flush != env->cpu_mem_env.flush) +- { ++ if (my_css.flush != env->cpu_mem_env.flush) { + ia_css_reset_defaults(&my_css); + my_css.flush = env->cpu_mem_env.flush; + } + + ia_css_unload_firmware(); /* in case we are called twice */ + err = sh_css_load_firmware(dev, fw->data, fw->bytes); +- if (!err) +- { ++ if (!err) { + err = ia_css_binary_init_infos(); + if (!err) + fw_explicitly_loaded = true; +@@ -1628,7 +1618,8 @@ int + ia_css_init(struct device *dev, const struct ia_css_env *env, + const struct ia_css_fw *fw, + u32 mmu_l1_base, +- enum ia_css_irq_type irq_type) { ++ enum ia_css_irq_type irq_type) ++{ + int err; + ia_css_spctrl_cfg spctrl_cfg; + +@@ -1702,16 +1693,14 @@ ia_css_init(struct device *dev, const st + my_css.flush = flush_func; + + err = ia_css_rmgr_init(); +- if (err) +- { ++ if (err) { + IA_CSS_LEAVE_ERR(err); + return err; + } + + IA_CSS_LOG("init: %d", my_css_save_initialized); + +- if (!my_css_save_initialized) +- { ++ if (!my_css_save_initialized) { + my_css_save_initialized = true; + my_css_save.mode = sh_css_mode_working; + memset(my_css_save.stream_seeds, 0, +@@ -1739,19 +1728,16 @@ ia_css_init(struct device *dev, const st + gpio_reg_store(GPIO0_ID, _gpio_block_reg_do_0, 0); + + err = ia_css_refcount_init(REFCOUNT_SIZE); +- if (err) +- { ++ if (err) { + IA_CSS_LEAVE_ERR(err); + return err; + } + err = sh_css_params_init(); +- if (err) +- { ++ if (err) { + IA_CSS_LEAVE_ERR(err); + return err; + } +- if (fw) +- { ++ if (fw) { + ia_css_unload_firmware(); /* in case we already had firmware loaded */ + err = sh_css_load_firmware(dev, fw->data, fw->bytes); + if (err) { +@@ -1772,23 +1758,20 @@ ia_css_init(struct device *dev, const st + return -EINVAL; + + err = ia_css_spctrl_load_fw(SP0_ID, &spctrl_cfg); +- if (err) +- { ++ if (err) { + IA_CSS_LEAVE_ERR(err); + return err; + } + + #if WITH_PC_MONITORING +- if (!thread_alive) +- { ++ if (!thread_alive) { + thread_alive++; + sh_css_print("PC_MONITORING: %s() -- create thread DISABLED\n", + __func__); + spying_thread_create(); + } + #endif +- if (!sh_css_hrt_system_is_idle()) +- { ++ if (!sh_css_hrt_system_is_idle()) { + IA_CSS_LEAVE_ERR(-EBUSY); + return -EBUSY; + } +@@ -1821,7 +1804,8 @@ ia_css_init(struct device *dev, const st + } + + int +-ia_css_enable_isys_event_queue(bool enable) { ++ia_css_enable_isys_event_queue(bool enable) ++{ + if (sh_css_sp_is_running()) + return -EBUSY; + sh_css_sp_enable_isys_event_queue(enable); +@@ -1842,7 +1826,8 @@ sh_css_flush(struct ia_css_acc_fw *fw) + * doing it from stream_create since we could run out of sp threads due to + * allocation on inactive pipelines. */ + static int +-map_sp_threads(struct ia_css_stream *stream, bool map) { ++map_sp_threads(struct ia_css_stream *stream, bool map) ++{ + struct ia_css_pipe *main_pipe = NULL; + struct ia_css_pipe *copy_pipe = NULL; + struct ia_css_pipe *capture_pipe = NULL; +@@ -1854,8 +1839,7 @@ map_sp_threads(struct ia_css_stream *str + IA_CSS_ENTER_PRIVATE("stream = %p, map = %s", + stream, map ? "true" : "false"); + +- if (!stream) +- { ++ if (!stream) { + IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL); + return -EINVAL; + } +@@ -1865,8 +1849,7 @@ map_sp_threads(struct ia_css_stream *str + + ia_css_pipeline_map(main_pipe->pipe_num, map); + +- switch (pipe_id) +- { ++ switch (pipe_id) { + case IA_CSS_PIPE_ID_PREVIEW: + copy_pipe = main_pipe->pipe_settings.preview.copy_pipe; + capture_pipe = main_pipe->pipe_settings.preview.capture_pipe; +@@ -1885,23 +1868,17 @@ map_sp_threads(struct ia_css_stream *str + } + + if (acc_pipe) +- { + ia_css_pipeline_map(acc_pipe->pipe_num, map); +- } + + if (capture_pipe) +- { + ia_css_pipeline_map(capture_pipe->pipe_num, map); +- } + + /* Firmware expects copy pipe to be the last pipe mapped. (if needed) */ + if (copy_pipe) +- { + ia_css_pipeline_map(copy_pipe->pipe_num, map); +- } ++ + /* DH regular multi pipe - not continuous mode: map the next pipes too */ +- if (!stream->config.continuous) +- { ++ if (!stream->config.continuous) { + int i; + + for (i = 1; i < stream->num_pipes; i++) +@@ -1915,7 +1892,8 @@ map_sp_threads(struct ia_css_stream *str + /* creates a host pipeline skeleton for all pipes in a stream. Called during + * stream_create. */ + static int +-create_host_pipeline_structure(struct ia_css_stream *stream) { ++create_host_pipeline_structure(struct ia_css_stream *stream) ++{ + struct ia_css_pipe *copy_pipe = NULL, *capture_pipe = NULL; + struct ia_css_pipe *acc_pipe = NULL; + enum ia_css_pipe_id pipe_id; +@@ -1927,24 +1905,21 @@ create_host_pipeline_structure(struct ia + assert(stream); + IA_CSS_ENTER_PRIVATE("stream = %p", stream); + +- if (!stream) +- { ++ if (!stream) { + IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL); + return -EINVAL; + } + + main_pipe = stream->last_pipe; + assert(main_pipe); +- if (!main_pipe) +- { ++ if (!main_pipe) { + IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL); + return -EINVAL; + } + + pipe_id = main_pipe->mode; + +- switch (pipe_id) +- { ++ switch (pipe_id) { + case IA_CSS_PIPE_ID_PREVIEW: + copy_pipe = main_pipe->pipe_settings.preview.copy_pipe; + copy_pipe_delay = main_pipe->dvs_frame_delay; +@@ -1984,30 +1959,23 @@ create_host_pipeline_structure(struct ia + } + + if (!(err) && copy_pipe) +- { + err = ia_css_pipeline_create(©_pipe->pipeline, + copy_pipe->mode, + copy_pipe->pipe_num, + copy_pipe_delay); +- } + + if (!(err) && capture_pipe) +- { + err = ia_css_pipeline_create(&capture_pipe->pipeline, + capture_pipe->mode, + capture_pipe->pipe_num, + capture_pipe_delay); +- } + + if (!(err) && acc_pipe) +- { + err = ia_css_pipeline_create(&acc_pipe->pipeline, acc_pipe->mode, + acc_pipe->pipe_num, main_pipe->dvs_frame_delay); +- } + + /* DH regular multi pipe - not continuous mode: create the next pipelines too */ +- if (!stream->config.continuous) +- { ++ if (!stream->config.continuous) { + int i; + + for (i = 1; i < stream->num_pipes && 0 == err; i++) { +@@ -2026,7 +1994,8 @@ create_host_pipeline_structure(struct ia + /* creates a host pipeline for all pipes in a stream. Called during + * stream_start. */ + static int +-create_host_pipeline(struct ia_css_stream *stream) { ++create_host_pipeline(struct ia_css_stream *stream) ++{ + struct ia_css_pipe *copy_pipe = NULL, *capture_pipe = NULL; + struct ia_css_pipe *acc_pipe = NULL; + enum ia_css_pipe_id pipe_id; +@@ -2035,8 +2004,7 @@ create_host_pipeline(struct ia_css_strea + unsigned int max_input_width = 0; + + IA_CSS_ENTER_PRIVATE("stream = %p", stream); +- if (!stream) +- { ++ if (!stream) { + IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL); + return -EINVAL; + } +@@ -2047,8 +2015,7 @@ create_host_pipeline(struct ia_css_strea + /* No continuous frame allocation for capture pipe. It uses the + * "main" pipe's frames. */ + if ((pipe_id == IA_CSS_PIPE_ID_PREVIEW) || +- (pipe_id == IA_CSS_PIPE_ID_VIDEO)) +- { ++ (pipe_id == IA_CSS_PIPE_ID_VIDEO)) { + /* About pipe_id == IA_CSS_PIPE_ID_PREVIEW && stream->config.mode != IA_CSS_INPUT_MODE_MEMORY: + * The original condition pipe_id == IA_CSS_PIPE_ID_PREVIEW is too strong. E.g. in SkyCam (with memory + * based input frames) there is no continuous mode and thus no need for allocated continuous frames +@@ -2066,24 +2033,21 @@ create_host_pipeline(struct ia_css_strea + + #if !defined(ISP2401) + /* old isys: need to allocate_mipi_frames() even in IA_CSS_PIPE_MODE_COPY */ +- if (pipe_id != IA_CSS_PIPE_ID_ACC) +- { ++ if (pipe_id != IA_CSS_PIPE_ID_ACC) { + err = allocate_mipi_frames(main_pipe, &stream->info); + if (err) + goto ERR; + } + #elif defined(ISP2401) + if ((pipe_id != IA_CSS_PIPE_ID_ACC) && +- (main_pipe->config.mode != IA_CSS_PIPE_MODE_COPY)) +- { ++ (main_pipe->config.mode != IA_CSS_PIPE_MODE_COPY)) { + err = allocate_mipi_frames(main_pipe, &stream->info); + if (err) + goto ERR; + } + #endif + +- switch (pipe_id) +- { ++ switch (pipe_id) { + case IA_CSS_PIPE_ID_PREVIEW: + copy_pipe = main_pipe->pipe_settings.preview.copy_pipe; + capture_pipe = main_pipe->pipe_settings.preview.capture_pipe; +@@ -2133,31 +2097,27 @@ create_host_pipeline(struct ia_css_strea + if (err) + goto ERR; + +- if (copy_pipe) +- { ++ if (copy_pipe) { + err = create_host_copy_pipeline(copy_pipe, max_input_width, + main_pipe->continuous_frames[0]); + if (err) + goto ERR; + } + +- if (capture_pipe) +- { ++ if (capture_pipe) { + err = create_host_capture_pipeline(capture_pipe); + if (err) + goto ERR; + } + +- if (acc_pipe) +- { ++ if (acc_pipe) { + err = create_host_acc_pipeline(acc_pipe); + if (err) + goto ERR; + } + + /* DH regular multi pipe - not continuous mode: create the next pipelines too */ +- if (!stream->config.continuous) +- { ++ if (!stream->config.continuous) { + int i; + + for (i = 1; i < stream->num_pipes && 0 == err; i++) { +@@ -2199,10 +2159,10 @@ static const struct ia_css_yuvpp_setting + static int + init_pipe_defaults(enum ia_css_pipe_mode mode, + struct ia_css_pipe *pipe, +- bool copy_pipe) { ++ bool copy_pipe) ++{ + +- if (!pipe) +- { ++ if (!pipe) { + IA_CSS_ERROR("NULL pipe parameter"); + return -EINVAL; + } +@@ -2211,18 +2171,17 @@ init_pipe_defaults(enum ia_css_pipe_mode + memcpy(pipe, &default_pipe, sizeof(default_pipe)); + + /* TODO: JB should not be needed, but temporary backward reference */ +- switch (mode) +- { ++ switch (mode) { + case IA_CSS_PIPE_MODE_PREVIEW: + pipe->mode = IA_CSS_PIPE_ID_PREVIEW; + memcpy(&pipe->pipe_settings.preview, &preview, sizeof(preview)); + break; + case IA_CSS_PIPE_MODE_CAPTURE: +- if (copy_pipe) { ++ if (copy_pipe) + pipe->mode = IA_CSS_PIPE_ID_COPY; +- } else { ++ else + pipe->mode = IA_CSS_PIPE_ID_CAPTURE; +- } ++ + memcpy(&pipe->pipe_settings.capture, &capture, sizeof(capture)); + break; + case IA_CSS_PIPE_MODE_VIDEO: +@@ -2252,27 +2211,25 @@ pipe_global_init(void) + u8 i; + + my_css.pipe_counter = 0; +- for (i = 0; i < IA_CSS_PIPELINE_NUM_MAX; i++) { ++ for (i = 0; i < IA_CSS_PIPELINE_NUM_MAX; i++) + my_css.all_pipes[i] = NULL; +- } + } + + static int + pipe_generate_pipe_num(const struct ia_css_pipe *pipe, +- unsigned int *pipe_number) { ++ unsigned int *pipe_number) ++{ + const u8 INVALID_PIPE_NUM = (uint8_t)~(0); + u8 pipe_num = INVALID_PIPE_NUM; + u8 i; + +- if (!pipe) +- { ++ if (!pipe) { + IA_CSS_ERROR("NULL pipe parameter"); + return -EINVAL; + } + + /* Assign a new pipe_num .... search for empty place */ +- for (i = 0; i < IA_CSS_PIPELINE_NUM_MAX; i++) +- { ++ for (i = 0; i < IA_CSS_PIPELINE_NUM_MAX; i++) { + if (!my_css.all_pipes[i]) { + /*position is reserved */ + my_css.all_pipes[i] = (struct ia_css_pipe *)pipe; +@@ -2280,8 +2237,7 @@ pipe_generate_pipe_num(const struct ia_c + break; + } + } +- if (pipe_num == INVALID_PIPE_NUM) +- { ++ if (pipe_num == INVALID_PIPE_NUM) { + /* Max number of pipes already allocated */ + IA_CSS_ERROR("Max number of pipes already created"); + return -ENOSPC; diff --git a/queue-5.10/media-staging-media-atomisp-fix-the-rest-of-sh_css.c-brace-issues.patch b/queue-5.10/media-staging-media-atomisp-fix-the-rest-of-sh_css.c-brace-issues.patch new file mode 100644 index 0000000000..98c2aabd00 --- /dev/null +++ b/queue-5.10/media-staging-media-atomisp-fix-the-rest-of-sh_css.c-brace-issues.patch @@ -0,0 +1,3438 @@ +From stable+bounces-274532-greg=kroah.com@vger.kernel.org Tue Jul 14 22:02:41 2026 +From: Sasha Levin +Date: Tue, 14 Jul 2026 16:01:55 -0400 +Subject: media: staging: media: atomisp: Fix the rest of sh_css.c brace issues +To: stable@vger.kernel.org +Cc: Martiros Shakhzadyan , Hans Verkuil , Mauro Carvalho Chehab , Sasha Levin +Message-ID: <20260714200158.3152137-3-sashal@kernel.org> + +From: Martiros Shakhzadyan + +[ Upstream commit 7394bf6d3c1e8316484fcf3a9d71daaab489f211 ] + +Fix the remainder of brace coding style issues. + +Signed-off-by: Martiros Shakhzadyan +Signed-off-by: Hans Verkuil +Signed-off-by: Mauro Carvalho Chehab +Stable-dep-of: f4d51e55dd47 ("staging: media: atomisp: reduce load_primary_binaries() stack usage") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/staging/media/atomisp/pci/sh_css.c | 1134 ++++++++++++----------------- + 1 file changed, 498 insertions(+), 636 deletions(-) + +--- a/drivers/staging/media/atomisp/pci/sh_css.c ++++ b/drivers/staging/media/atomisp/pci/sh_css.c +@@ -1101,8 +1101,7 @@ sh_css_config_input_network(struct ia_cs + /* get the target input terminal */ + sp_pipeline_input_terminal = &sh_css_sp_group.pipe_io[sp_thread_id].input; + +- for (i = 0; i < IA_CSS_STREAM_MAX_ISYS_STREAM_PER_CH; i++) +- { ++ for (i = 0; i < IA_CSS_STREAM_MAX_ISYS_STREAM_PER_CH; i++) { + /* initialization */ + memset((void *)(&isys_stream_descr), 0, sizeof(ia_css_isys_descr_t)); + sp_pipeline_input_terminal->context.virtual_input_system_stream[i].valid = 0; +@@ -2161,7 +2160,6 @@ init_pipe_defaults(enum ia_css_pipe_mode + struct ia_css_pipe *pipe, + bool copy_pipe) + { +- + if (!pipe) { + IA_CSS_ERROR("NULL pipe parameter"); + return -EINVAL; +@@ -2263,12 +2261,12 @@ pipe_release_pipe_num(unsigned int pipe_ + static int + create_pipe(enum ia_css_pipe_mode mode, + struct ia_css_pipe **pipe, +- bool copy_pipe) { ++ bool copy_pipe) ++{ + int err = 0; + struct ia_css_pipe *me; + +- if (!pipe) +- { ++ if (!pipe) { + IA_CSS_ERROR("NULL pipe parameter"); + return -EINVAL; + } +@@ -2278,15 +2276,13 @@ create_pipe(enum ia_css_pipe_mode mode, + return -ENOMEM; + + err = init_pipe_defaults(mode, me, copy_pipe); +- if (err) +- { ++ if (err) { + kfree(me); + return err; + } + + err = pipe_generate_pipe_num(me, &me->pipe_num); +- if (err) +- { ++ if (err) { + kfree(me); + return err; + } +@@ -2332,26 +2328,24 @@ static void sh_css_pipe_free_acc_binarie + } + + int +-ia_css_pipe_destroy(struct ia_css_pipe *pipe) { ++ia_css_pipe_destroy(struct ia_css_pipe *pipe) ++{ + int err = 0; + + IA_CSS_ENTER("pipe = %p", pipe); + +- if (!pipe) +- { ++ if (!pipe) { + IA_CSS_LEAVE_ERR(-EINVAL); + return -EINVAL; + } + +- if (pipe->stream) +- { ++ if (pipe->stream) { + IA_CSS_LOG("ia_css_stream_destroy not called!"); + IA_CSS_LEAVE_ERR(-EINVAL); + return -EINVAL; + } + +- switch (pipe->config.mode) +- { ++ switch (pipe->config.mode) { + case IA_CSS_PIPE_MODE_PREVIEW: + /* need to take into account that this function is also called + on the internal copy pipe */ +@@ -2415,9 +2409,8 @@ ia_css_pipe_destroy(struct ia_css_pipe * + + /* Temporarily, not every sh_css_pipe has an acc_extension. */ + if (pipe->config.acc_extension) +- { + ia_css_pipe_unload_extension(pipe, pipe->config.acc_extension); +- } ++ + kfree(pipe); + IA_CSS_LEAVE("err = %d", err); + return err; +@@ -2447,9 +2440,9 @@ ia_css_uninit(void) + ifmtr_set_if_blocking_mode_reset = true; + #endif + +- if (!fw_explicitly_loaded) { ++ if (!fw_explicitly_loaded) + ia_css_unload_firmware(); +- } ++ + ia_css_spctrl_unload_fw(SP0_ID); + sh_css_sp_set_sp_running(false); + /* check and free any remaining mipi frames */ +@@ -2636,7 +2629,8 @@ static int load_copy_binary( + + static int + alloc_continuous_frames( +- struct ia_css_pipe *pipe, bool init_time) { ++ struct ia_css_pipe *pipe, bool init_time) ++{ + int err = 0; + struct ia_css_frame_info ref_info; + enum ia_css_pipe_id pipe_id; +@@ -2646,8 +2640,7 @@ alloc_continuous_frames( + + IA_CSS_ENTER_PRIVATE("pipe = %p, init_time = %d", pipe, init_time); + +- if ((!pipe) || (!pipe->stream)) +- { ++ if ((!pipe) || (!pipe->stream)) { + IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL); + return -EINVAL; + } +@@ -2655,26 +2648,22 @@ alloc_continuous_frames( + pipe_id = pipe->mode; + continuous = pipe->stream->config.continuous; + +- if (continuous) +- { ++ if (continuous) { + if (init_time) { + num_frames = pipe->stream->config.init_num_cont_raw_buf; + pipe->stream->continuous_pipe = pipe; +- } else ++ } else { + num_frames = pipe->stream->config.target_num_cont_raw_buf; +- } else +- { ++ } ++ } else { + num_frames = NUM_ONLINE_INIT_CONTINUOUS_FRAMES; + } + +- if (pipe_id == IA_CSS_PIPE_ID_PREVIEW) +- { ++ if (pipe_id == IA_CSS_PIPE_ID_PREVIEW) { + ref_info = pipe->pipe_settings.preview.preview_binary.in_frame_info; +- } else if (pipe_id == IA_CSS_PIPE_ID_VIDEO) +- { ++ } else if (pipe_id == IA_CSS_PIPE_ID_VIDEO) { + ref_info = pipe->pipe_settings.video.video_binary.in_frame_info; +- } else +- { ++ } else { + /* should not happen */ + IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL); + return -EINVAL; +@@ -2690,8 +2679,7 @@ alloc_continuous_frames( + #endif + + #if !defined(HAS_NO_PACKED_RAW_PIXELS) +- if (pipe->stream->config.pack_raw_pixels) +- { ++ if (pipe->stream->config.pack_raw_pixels) { + ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, + "alloc_continuous_frames() IA_CSS_FRAME_FORMAT_RAW_PACKED\n"); + ref_info.format = IA_CSS_FRAME_FORMAT_RAW_PACKED; +@@ -2720,8 +2708,7 @@ alloc_continuous_frames( + else + idx = pipe->stream->config.init_num_cont_raw_buf; + +- for (i = idx; i < NUM_CONTINUOUS_FRAMES; i++) +- { ++ for (i = idx; i < NUM_CONTINUOUS_FRAMES; i++) { + /* free previous frame */ + if (pipe->continuous_frames[i]) { + ia_css_frame_free(pipe->continuous_frames[i]); +@@ -2751,14 +2738,16 @@ alloc_continuous_frames( + } + + int +-ia_css_alloc_continuous_frame_remain(struct ia_css_stream *stream) { ++ia_css_alloc_continuous_frame_remain(struct ia_css_stream *stream) ++{ + if (!stream) + return -EINVAL; + return alloc_continuous_frames(stream->continuous_pipe, false); + } + + static int +-load_preview_binaries(struct ia_css_pipe *pipe) { ++load_preview_binaries(struct ia_css_pipe *pipe) ++{ + struct ia_css_frame_info prev_in_info, + prev_bds_out_info, + prev_out_info, +@@ -2866,8 +2855,7 @@ load_preview_binaries(struct ia_css_pipe + * then the preview binary selection is done again. + */ + if (need_vf_pp && +- (mycs->preview_binary.out_frame_info[0].format != IA_CSS_FRAME_FORMAT_YUV_LINE)) +- { ++ (mycs->preview_binary.out_frame_info[0].format != IA_CSS_FRAME_FORMAT_YUV_LINE)) { + /* Preview step 2 */ + if (pipe->vf_yuv_ds_input_info.res.width) + prev_vf_info = pipe->vf_yuv_ds_input_info; +@@ -2892,8 +2880,7 @@ load_preview_binaries(struct ia_css_pipe + return err; + } + +- if (need_vf_pp) +- { ++ if (need_vf_pp) { + struct ia_css_binary_descr vf_pp_descr; + + /* Viewfinder post-processing */ +@@ -2924,8 +2911,7 @@ load_preview_binaries(struct ia_css_pipe + #endif + + /* Copy */ +- if (need_isp_copy_binary) +- { ++ if (need_isp_copy_binary) { + err = load_copy_binary(pipe, + &mycs->copy_binary, + &mycs->preview_binary); +@@ -2933,8 +2919,7 @@ load_preview_binaries(struct ia_css_pipe + return err; + } + +- if (pipe->shading_table) +- { ++ if (pipe->shading_table) { + ia_css_shading_table_free(pipe->shading_table); + pipe->shading_table = NULL; + } +@@ -2949,11 +2934,11 @@ ia_css_binary_unload(struct ia_css_binar + } + + static int +-unload_preview_binaries(struct ia_css_pipe *pipe) { ++unload_preview_binaries(struct ia_css_pipe *pipe) ++{ + IA_CSS_ENTER_PRIVATE("pipe = %p", pipe); + +- if ((!pipe) || (pipe->mode != IA_CSS_PIPE_ID_PREVIEW)) +- { ++ if ((!pipe) || (pipe->mode != IA_CSS_PIPE_ID_PREVIEW)) { + IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL); + return -EINVAL; + } +@@ -3006,15 +2991,15 @@ static int add_firmwares( + struct ia_css_frame *in = NULL; + struct ia_css_frame *vf = NULL; + +- if ((fw == last_fw) && (fw->info.isp.sp.enable.out_frame != 0)) { ++ if ((fw == last_fw) && (fw->info.isp.sp.enable.out_frame != 0)) + out[0] = out_frame; +- } +- if (fw->info.isp.sp.enable.in_frame != 0) { ++ ++ if (fw->info.isp.sp.enable.in_frame != 0) + in = in_frame; +- } +- if (fw->info.isp.sp.enable.out_frame != 0) { ++ ++ if (fw->info.isp.sp.enable.out_frame != 0) + vf = vf_frame; +- } ++ + ia_css_pipe_get_firmwares_stage_desc(&stage_desc, binary, + out, in, vf, fw, binary_mode); + err = ia_css_pipeline_create_and_add_stage(me, +@@ -3228,7 +3213,8 @@ static void sh_css_setup_queues(void) + + static int + init_vf_frameinfo_defaults(struct ia_css_pipe *pipe, +- struct ia_css_frame *vf_frame, unsigned int idx) { ++ struct ia_css_frame *vf_frame, unsigned int idx) ++{ + int err = 0; + unsigned int thread_id; + enum sh_css_queue_id queue_id; +@@ -3393,7 +3379,8 @@ ia_css_get_crop_offsets( + + static int + init_in_frameinfo_memory_defaults(struct ia_css_pipe *pipe, +- struct ia_css_frame *frame, enum ia_css_frame_format format) { ++ struct ia_css_frame *frame, enum ia_css_frame_format format) ++{ + struct ia_css_frame *in_frame; + int err = 0; + unsigned int thread_id; +@@ -3434,7 +3421,8 @@ init_in_frameinfo_memory_defaults(struct + + static int + init_out_frameinfo_defaults(struct ia_css_pipe *pipe, +- struct ia_css_frame *out_frame, unsigned int idx) { ++ struct ia_css_frame *out_frame, unsigned int idx) ++{ + int err = 0; + unsigned int thread_id; + enum sh_css_queue_id queue_id; +@@ -3665,14 +3653,14 @@ ERR: + } + + static int +-create_host_acc_pipeline(struct ia_css_pipe *pipe) { ++create_host_acc_pipeline(struct ia_css_pipe *pipe) ++{ + int err = 0; + const struct ia_css_fw_info *fw; + unsigned int i; + + IA_CSS_ENTER_PRIVATE("pipe = %p", pipe); +- if ((!pipe) || (!pipe->stream)) +- { ++ if ((!pipe) || (!pipe->stream)) { + IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL); + return -EINVAL; + } +@@ -3683,15 +3671,13 @@ create_host_acc_pipeline(struct ia_css_p + pipe->pipeline.pipe_qos_config = 0; + + fw = pipe->vf_stage; +- for (i = 0; fw; fw = fw->next) +- { ++ for (i = 0; fw; fw = fw->next) { + err = sh_css_pipeline_add_acc_stage(&pipe->pipeline, fw); + if (err) + goto ERR; + } + +- for (i = 0; i < pipe->config.num_acc_stages; i++) +- { ++ for (i = 0; i < pipe->config.num_acc_stages; i++) { + struct ia_css_fw_info *fw = pipe->config.acc_stages[i]; + + err = sh_css_pipeline_add_acc_stage(&pipe->pipeline, fw); +@@ -3708,7 +3694,8 @@ ERR: + + /* Create stages for preview */ + static int +-create_host_preview_pipeline(struct ia_css_pipe *pipe) { ++create_host_preview_pipeline(struct ia_css_pipe *pipe) ++{ + struct ia_css_pipeline_stage *copy_stage = NULL; + struct ia_css_pipeline_stage *preview_stage = NULL; + struct ia_css_pipeline_stage *vf_pp_stage = NULL; +@@ -3728,8 +3715,7 @@ create_host_preview_pipeline(struct ia_c + #endif + + IA_CSS_ENTER_PRIVATE("pipe = %p", pipe); +- if ((!pipe) || (!pipe->stream) || (pipe->mode != IA_CSS_PIPE_ID_PREVIEW)) +- { ++ if ((!pipe) || (!pipe->stream) || (pipe->mode != IA_CSS_PIPE_ID_PREVIEW)) { + IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL); + return -EINVAL; + } +@@ -3757,16 +3743,14 @@ create_host_preview_pipeline(struct ia_c + /* Construct in_frame info (only in case we have dynamic input */ + need_in_frameinfo_memory = pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY; + #endif +- if (need_in_frameinfo_memory) +- { ++ if (need_in_frameinfo_memory) { + err = init_in_frameinfo_memory_defaults(pipe, &me->in_frame, + IA_CSS_FRAME_FORMAT_RAW); + if (err) + goto ERR; + + in_frame = &me->in_frame; +- } else +- { ++ } else { + in_frame = NULL; + } + +@@ -3780,8 +3764,7 @@ create_host_preview_pipeline(struct ia_c + if (pipe->pipe_settings.preview.vf_pp_binary.info) + vf_pp_binary = &pipe->pipe_settings.preview.vf_pp_binary; + +- if (pipe->pipe_settings.preview.copy_binary.info) +- { ++ if (pipe->pipe_settings.preview.copy_binary.info) { + ia_css_pipe_util_set_output_frames(out_frames, 0, NULL); + ia_css_pipe_get_generic_stage_desc(&stage_desc, copy_binary, + out_frames, NULL, NULL); +@@ -3796,21 +3779,19 @@ create_host_preview_pipeline(struct ia_c + /* When continuous is enabled, configure in_frame with the + * last pipe, which is the copy pipe. + */ +- if (continuous || !online) { ++ if (continuous || !online) + in_frame = pipe->stream->last_pipe->continuous_frames[0]; +- } ++ + #else + in_frame = pipe->continuous_frames[0]; + #endif + } + +- if (vf_pp_binary) +- { ++ if (vf_pp_binary) { + ia_css_pipe_util_set_output_frames(out_frames, 0, NULL); + ia_css_pipe_get_generic_stage_desc(&stage_desc, preview_binary, + out_frames, in_frame, NULL); +- } else +- { ++ } else { + ia_css_pipe_util_set_output_frames(out_frames, 0, out_frame); + ia_css_pipe_get_generic_stage_desc(&stage_desc, preview_binary, + out_frames, in_frame, NULL); +@@ -3824,14 +3805,12 @@ create_host_preview_pipeline(struct ia_c + preview_stage->args.copy_vf = + preview_binary->info->sp.pipeline.mode == IA_CSS_BINARY_MODE_COPY; + preview_stage->args.copy_output = !preview_stage->args.copy_vf; +- if (preview_stage->args.copy_vf && !preview_stage->args.out_vf_frame) +- { ++ if (preview_stage->args.copy_vf && !preview_stage->args.out_vf_frame) { + /* in case of copy, use the vf frame as output frame */ + preview_stage->args.out_vf_frame = + preview_stage->args.out_frame[0]; + } +- if (vf_pp_binary) +- { ++ if (vf_pp_binary) { + if (preview_binary->info->sp.pipeline.mode == IA_CSS_BINARY_MODE_COPY) + in_frame = preview_stage->args.out_vf_frame; + else +@@ -3871,7 +3850,8 @@ static void send_raw_frames(struct ia_cs + } + + static int +-preview_start(struct ia_css_pipe *pipe) { ++preview_start(struct ia_css_pipe *pipe) ++{ + int err = 0; + struct ia_css_pipe *copy_pipe, *capture_pipe; + struct ia_css_pipe *acc_pipe; +@@ -3881,8 +3861,7 @@ preview_start(struct ia_css_pipe *pipe) + const struct ia_css_isp_parameters *params = NULL; + + IA_CSS_ENTER_PRIVATE("pipe = %p", pipe); +- if ((!pipe) || (!pipe->stream) || (pipe->mode != IA_CSS_PIPE_ID_PREVIEW)) +- { ++ if ((!pipe) || (!pipe->stream) || (pipe->mode != IA_CSS_PIPE_ID_PREVIEW)) { + IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL); + return -EINVAL; + } +@@ -3909,8 +3888,7 @@ preview_start(struct ia_css_pipe *pipe) + ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id); + copy_ovrd = 1 << thread_id; + +- if (pipe->stream->cont_capt) +- { ++ if (pipe->stream->cont_capt) { + ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(capture_pipe), + &thread_id); + copy_ovrd |= 1 << thread_id; +@@ -3923,8 +3901,7 @@ preview_start(struct ia_css_pipe *pipe) + } + + /* Construct and load the copy pipe */ +- if (pipe->stream->config.continuous) +- { ++ if (pipe->stream->config.continuous) { + sh_css_sp_init_pipeline(©_pipe->pipeline, + IA_CSS_PIPE_ID_COPY, + (uint8_t)ia_css_pipe_get_pipe_num(copy_pipe), +@@ -3945,8 +3922,7 @@ preview_start(struct ia_css_pipe *pipe) + } + + /* Construct and load the capture pipe */ +- if (pipe->stream->cont_capt) +- { ++ if (pipe->stream->cont_capt) { + sh_css_sp_init_pipeline(&capture_pipe->pipeline, + IA_CSS_PIPE_ID_CAPTURE, + (uint8_t)ia_css_pipe_get_pipe_num(capture_pipe), +@@ -3964,8 +3940,7 @@ preview_start(struct ia_css_pipe *pipe) + params); + } + +- if (acc_pipe) +- { ++ if (acc_pipe) { + sh_css_sp_init_pipeline(&acc_pipe->pipeline, + IA_CSS_PIPE_ID_ACC, + (uint8_t)ia_css_pipe_get_pipe_num(acc_pipe), +@@ -3991,7 +3966,8 @@ preview_start(struct ia_css_pipe *pipe) + + int + ia_css_pipe_enqueue_buffer(struct ia_css_pipe *pipe, +- const struct ia_css_buffer *buffer) { ++ const struct ia_css_buffer *buffer) ++{ + int return_err = 0; + unsigned int thread_id; + enum sh_css_queue_id queue_id; +@@ -4006,8 +3982,7 @@ ia_css_pipe_enqueue_buffer(struct ia_css + + IA_CSS_ENTER("pipe=%p, buffer=%p", pipe, buffer); + +- if ((!pipe) || (!buffer)) +- { ++ if ((!pipe) || (!buffer)) { + IA_CSS_LEAVE_ERR(-EINVAL); + return -EINVAL; + } +@@ -4016,8 +3991,7 @@ ia_css_pipe_enqueue_buffer(struct ia_css + /* following code will be enabled when IA_CSS_BUFFER_TYPE_SEC_OUTPUT_FRAME + is removed */ + #if 0 +- if (buf_type == IA_CSS_BUFFER_TYPE_OUTPUT_FRAME) +- { ++ if (buf_type == IA_CSS_BUFFER_TYPE_OUTPUT_FRAME) { + bool found_pipe = false; + + for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) { +@@ -4031,8 +4005,7 @@ ia_css_pipe_enqueue_buffer(struct ia_css + if (!found_pipe) + return -EINVAL; + } +- if (buf_type == IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME) +- { ++ if (buf_type == IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME) { + bool found_pipe = false; + + for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) { +@@ -4055,34 +4028,29 @@ ia_css_pipe_enqueue_buffer(struct ia_css + assert(buf_type < IA_CSS_NUM_DYNAMIC_BUFFER_TYPE); + if ((buf_type == IA_CSS_BUFFER_TYPE_INVALID) || + (buf_type >= IA_CSS_NUM_DYNAMIC_BUFFER_TYPE) || +- (pipe_id >= IA_CSS_PIPE_ID_NUM)) +- { ++ (pipe_id >= IA_CSS_PIPE_ID_NUM)) { + IA_CSS_LEAVE_ERR(-EINVAL); + return -EINVAL; + } + + ret_err = ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id); +- if (!ret_err) +- { ++ if (!ret_err) { + IA_CSS_LEAVE_ERR(-EINVAL); + return -EINVAL; + } + + ret_err = ia_css_query_internal_queue_id(buf_type, thread_id, &queue_id); +- if (!ret_err) +- { ++ if (!ret_err) { + IA_CSS_LEAVE_ERR(-EINVAL); + return -EINVAL; + } + +- if ((queue_id <= SH_CSS_INVALID_QUEUE_ID) || (queue_id >= SH_CSS_MAX_NUM_QUEUES)) +- { ++ if ((queue_id <= SH_CSS_INVALID_QUEUE_ID) || (queue_id >= SH_CSS_MAX_NUM_QUEUES)) { + IA_CSS_LEAVE_ERR(-EINVAL); + return -EINVAL; + } + +- if (!sh_css_sp_is_running()) +- { ++ if (!sh_css_sp_is_running()) { + IA_CSS_LOG("SP is not running!"); + IA_CSS_LEAVE_ERR(-EBUSY); + /* SP is not running. The queues are not valid */ +@@ -4100,24 +4068,21 @@ ia_css_pipe_enqueue_buffer(struct ia_css + ddr_buffer.cookie_ptr = buffer->driver_cookie; + ddr_buffer.timing_data = buffer->timing_data; + +- if (buf_type == IA_CSS_BUFFER_TYPE_3A_STATISTICS) +- { ++ if (buf_type == IA_CSS_BUFFER_TYPE_3A_STATISTICS) { + if (!buffer->data.stats_3a) { + IA_CSS_LEAVE_ERR(-EINVAL); + return -EINVAL; + } + ddr_buffer.kernel_ptr = HOST_ADDRESS(buffer->data.stats_3a); + ddr_buffer.payload.s3a = *buffer->data.stats_3a; +- } else if (buf_type == IA_CSS_BUFFER_TYPE_DIS_STATISTICS) +- { ++ } else if (buf_type == IA_CSS_BUFFER_TYPE_DIS_STATISTICS) { + if (!buffer->data.stats_dvs) { + IA_CSS_LEAVE_ERR(-EINVAL); + return -EINVAL; + } + ddr_buffer.kernel_ptr = HOST_ADDRESS(buffer->data.stats_dvs); + ddr_buffer.payload.dis = *buffer->data.stats_dvs; +- } else if (buf_type == IA_CSS_BUFFER_TYPE_METADATA) +- { ++ } else if (buf_type == IA_CSS_BUFFER_TYPE_METADATA) { + if (!buffer->data.metadata) { + IA_CSS_LEAVE_ERR(-EINVAL); + return -EINVAL; +@@ -4128,8 +4093,7 @@ ia_css_pipe_enqueue_buffer(struct ia_css + || (buf_type == IA_CSS_BUFFER_TYPE_OUTPUT_FRAME) + || (buf_type == IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME) + || (buf_type == IA_CSS_BUFFER_TYPE_SEC_OUTPUT_FRAME) +- || (buf_type == IA_CSS_BUFFER_TYPE_SEC_VF_OUTPUT_FRAME)) +- { ++ || (buf_type == IA_CSS_BUFFER_TYPE_SEC_VF_OUTPUT_FRAME)) { + if (!buffer->data.frame) { + IA_CSS_LEAVE_ERR(-EINVAL); + return -EINVAL; +@@ -4164,8 +4128,7 @@ ia_css_pipe_enqueue_buffer(struct ia_css + assert(h_vbuf); + assert(h_vbuf->vptr != 0x0); + +- if ((!h_vbuf) || (h_vbuf->vptr == 0x0)) +- { ++ if ((!h_vbuf) || (h_vbuf->vptr == 0x0)) { + IA_CSS_LEAVE_ERR(-EINVAL); + return -EINVAL; + } +@@ -4175,8 +4138,7 @@ ia_css_pipe_enqueue_buffer(struct ia_css + sizeof(struct sh_css_hmm_buffer)); + if ((buf_type == IA_CSS_BUFFER_TYPE_3A_STATISTICS) + || (buf_type == IA_CSS_BUFFER_TYPE_DIS_STATISTICS) +- || (buf_type == IA_CSS_BUFFER_TYPE_LACE_STATISTICS)) +- { ++ || (buf_type == IA_CSS_BUFFER_TYPE_LACE_STATISTICS)) { + if (!pipeline) { + ia_css_rmgr_rel_vbuf(hmm_buffer_pool, &h_vbuf); + IA_CSS_LOG("pipeline is empty!"); +@@ -4199,8 +4161,7 @@ ia_css_pipe_enqueue_buffer(struct ia_css + || (buf_type == IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME) + || (buf_type == IA_CSS_BUFFER_TYPE_SEC_OUTPUT_FRAME) + || (buf_type == IA_CSS_BUFFER_TYPE_SEC_VF_OUTPUT_FRAME) +- || (buf_type == IA_CSS_BUFFER_TYPE_METADATA)) +- { ++ || (buf_type == IA_CSS_BUFFER_TYPE_METADATA)) { + return_err = ia_css_bufq_enqueue_buffer(thread_id, + queue_id, + (uint32_t)h_vbuf->vptr); +@@ -4214,8 +4175,7 @@ ia_css_pipe_enqueue_buffer(struct ia_css + #endif + } + +- if (!return_err) +- { ++ if (!return_err) { + if (sh_css_hmm_buffer_record_acquire( + h_vbuf, buf_type, + HOST_ADDRESS(ddr_buffer.kernel_ptr))) { +@@ -4230,8 +4190,7 @@ ia_css_pipe_enqueue_buffer(struct ia_css + * Tell the SP which queues are not empty, + * by sending the software event. + */ +- if (!return_err) +- { ++ if (!return_err) { + if (!sh_css_sp_is_running()) { + /* SP is not running. The queues are not valid */ + IA_CSS_LOG("SP is not running!"); +@@ -4243,8 +4202,7 @@ ia_css_pipe_enqueue_buffer(struct ia_css + (uint8_t)thread_id, + queue_id, + 0); +- } else +- { ++ } else { + ia_css_rmgr_rel_vbuf(hmm_buffer_pool, &h_vbuf); + IA_CSS_ERROR("buffer not enqueued"); + } +@@ -4259,7 +4217,8 @@ ia_css_pipe_enqueue_buffer(struct ia_css + */ + int + ia_css_pipe_dequeue_buffer(struct ia_css_pipe *pipe, +- struct ia_css_buffer *buffer) { ++ struct ia_css_buffer *buffer) ++{ + int return_err; + enum sh_css_queue_id queue_id; + ia_css_ptr ddr_buffer_addr = (ia_css_ptr)0; +@@ -4272,8 +4231,7 @@ ia_css_pipe_dequeue_buffer(struct ia_css + + IA_CSS_ENTER("pipe=%p, buffer=%p", pipe, buffer); + +- if ((!pipe) || (!buffer)) +- { ++ if ((!pipe) || (!buffer)) { + IA_CSS_LEAVE_ERR(-EINVAL); + return -EINVAL; + } +@@ -4287,27 +4245,23 @@ ia_css_pipe_dequeue_buffer(struct ia_css + ddr_buffer.kernel_ptr = 0; + + ret_err = ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id); +- if (!ret_err) +- { ++ if (!ret_err) { + IA_CSS_LEAVE_ERR(-EINVAL); + return -EINVAL; + } + + ret_err = ia_css_query_internal_queue_id(buf_type, thread_id, &queue_id); +- if (!ret_err) +- { ++ if (!ret_err) { + IA_CSS_LEAVE_ERR(-EINVAL); + return -EINVAL; + } + +- if ((queue_id <= SH_CSS_INVALID_QUEUE_ID) || (queue_id >= SH_CSS_MAX_NUM_QUEUES)) +- { ++ if ((queue_id <= SH_CSS_INVALID_QUEUE_ID) || (queue_id >= SH_CSS_MAX_NUM_QUEUES)) { + IA_CSS_LEAVE_ERR(-EINVAL); + return -EINVAL; + } + +- if (!sh_css_sp_is_running()) +- { ++ if (!sh_css_sp_is_running()) { + IA_CSS_LOG("SP is not running!"); + IA_CSS_LEAVE_ERR(-EBUSY); + /* SP is not running. The queues are not valid */ +@@ -4317,8 +4271,7 @@ ia_css_pipe_dequeue_buffer(struct ia_css + return_err = ia_css_bufq_dequeue_buffer(queue_id, + (uint32_t *)&ddr_buffer_addr); + +- if (!return_err) +- { ++ if (!return_err) { + struct ia_css_frame *frame; + struct sh_css_hmm_buffer_record *hmm_buffer_record = NULL; + +@@ -4460,8 +4413,7 @@ ia_css_pipe_dequeue_buffer(struct ia_css + * Tell the SP which queues are not full, + * by sending the software event. + */ +- if (!return_err) +- { ++ if (!return_err) { + if (!sh_css_sp_is_running()) { + IA_CSS_LOG("SP is not running!"); + IA_CSS_LEAVE_ERR(-EBUSY); +@@ -4510,12 +4462,14 @@ static enum ia_css_event_type convert_ev + }; + + int +-ia_css_dequeue_event(struct ia_css_event *event) { ++ia_css_dequeue_event(struct ia_css_event *event) ++{ + return ia_css_dequeue_psys_event(event); + } + + int +-ia_css_dequeue_psys_event(struct ia_css_event *event) { ++ia_css_dequeue_psys_event(struct ia_css_event *event) ++{ + enum ia_css_pipe_id pipe_id = 0; + u8 payload[4] = {0, 0, 0, 0}; + int ret_err; +@@ -4530,11 +4484,9 @@ ia_css_dequeue_psys_event(struct ia_css_ + if (!event) + return -EINVAL; + ++ /* SP is not running. The queues are not valid */ + if (!sh_css_sp_is_running()) +- { +- /* SP is not running. The queues are not valid */ + return -EBUSY; +- } + + /* dequeue the event (if any) from the psys event queue */ + ret_err = ia_css_bufq_dequeue_psys_event(payload); +@@ -4561,8 +4513,7 @@ ia_css_dequeue_psys_event(struct ia_css_ + event->timer_code = 0; + event->timer_subcode = 0; + +- if (event->type == IA_CSS_EVENT_TYPE_TIMER) +- { ++ if (event->type == IA_CSS_EVENT_TYPE_TIMER) { + /* timer event ??? get the 2nd event and decode the data into the event struct */ + u32 tmp_data; + /* 1st event: LSB 16-bit timer data and code */ +@@ -4586,37 +4537,32 @@ ia_css_dequeue_psys_event(struct ia_css_ + tmp_data = ((payload[1] & 0xFF) | ((payload[3] & 0xFF) << 8)); + event->timer_data |= (tmp_data << 16); + event->timer_subcode = payload[2]; +- } ++ } else { + /* It's a non timer event. So clear first half of the timer event data. + * If the second part of the TIMER event is not received, we discard + * the first half of the timer data and process the non timer event without + * affecting the flow. So the non timer event falls through + * the code. */ +- else { + event->timer_data = 0; + event->timer_code = 0; + event->timer_subcode = 0; + IA_CSS_ERROR("Missing 2nd timer event. Timer event discarded"); + } + } +- if (event->type == IA_CSS_EVENT_TYPE_PORT_EOF) +- { ++ if (event->type == IA_CSS_EVENT_TYPE_PORT_EOF) { + event->port = (enum mipi_port_id)payload[1]; + event->exp_id = payload[3]; +- } else if (event->type == IA_CSS_EVENT_TYPE_FW_WARNING) +- { ++ } else if (event->type == IA_CSS_EVENT_TYPE_FW_WARNING) { + event->fw_warning = (enum ia_css_fw_warning)payload[1]; + /* exp_id is only available in these warning types */ + if (event->fw_warning == IA_CSS_FW_WARNING_EXP_ID_LOCKED || + event->fw_warning == IA_CSS_FW_WARNING_TAG_EXP_ID_FAILED) + event->exp_id = payload[3]; +- } else if (event->type == IA_CSS_EVENT_TYPE_FW_ASSERT) +- { ++ } else if (event->type == IA_CSS_EVENT_TYPE_FW_ASSERT) { + event->fw_assert_module_id = payload[1]; /* module */ + event->fw_assert_line_no = (payload[2] << 8) + payload[3]; + /* payload[2] is line_no>>8, payload[3] is line_no&0xff */ +- } else if (event->type != IA_CSS_EVENT_TYPE_TIMER) +- { ++ } else if (event->type != IA_CSS_EVENT_TYPE_TIMER) { + /* pipe related events. + * payload[1] contains the pipe_num, + * payload[2] contains the pipe_id. These are different. */ +@@ -4666,7 +4612,8 @@ ia_css_dequeue_psys_event(struct ia_css_ + } + + int +-ia_css_dequeue_isys_event(struct ia_css_event *event) { ++ia_css_dequeue_isys_event(struct ia_css_event *event) ++{ + u8 payload[4] = {0, 0, 0, 0}; + int err = 0; + +@@ -4676,11 +4623,9 @@ ia_css_dequeue_isys_event(struct ia_css_ + if (!event) + return -EINVAL; + ++ /* SP is not running. The queues are not valid */ + if (!sh_css_sp_is_running()) +- { +- /* SP is not running. The queues are not valid */ + return -EBUSY; +- } + + err = ia_css_bufq_dequeue_isys_event(payload); + if (err) +@@ -4713,7 +4658,8 @@ acc_start(struct ia_css_pipe *pipe) + } + + static int +-sh_css_pipe_start(struct ia_css_stream *stream) { ++sh_css_pipe_start(struct ia_css_stream *stream) ++{ + int err = 0; + + struct ia_css_pipe *pipe; +@@ -4722,22 +4668,19 @@ sh_css_pipe_start(struct ia_css_stream * + + IA_CSS_ENTER_PRIVATE("stream = %p", stream); + +- if (!stream) +- { ++ if (!stream) { + IA_CSS_LEAVE_ERR(-EINVAL); + return -EINVAL; + } + pipe = stream->last_pipe; +- if (!pipe) +- { ++ if (!pipe) { + IA_CSS_LEAVE_ERR(-EINVAL); + return -EINVAL; + } + + pipe_id = pipe->mode; + +- if (stream->started) +- { ++ if (stream->started) { + IA_CSS_WARNING("Cannot start stream that is already started"); + IA_CSS_LEAVE_ERR(err); + return err; +@@ -4745,8 +4688,7 @@ sh_css_pipe_start(struct ia_css_stream * + + pipe->stop_requested = false; + +- switch (pipe_id) +- { ++ switch (pipe_id) { + case IA_CSS_PIPE_ID_PREVIEW: + err = preview_start(pipe); + break; +@@ -4766,8 +4708,7 @@ sh_css_pipe_start(struct ia_css_stream * + err = -EINVAL; + } + /* DH regular multi pipe - not continuous mode: start the next pipes too */ +- if (!stream->config.continuous) +- { ++ if (!stream->config.continuous) { + int i; + + for (i = 1; i < stream->num_pipes && 0 == err ; i++) { +@@ -4797,8 +4738,7 @@ sh_css_pipe_start(struct ia_css_stream * + } + } + } +- if (err) +- { ++ if (err) { + IA_CSS_LEAVE_ERR_PRIVATE(err); + return err; + } +@@ -4808,8 +4748,7 @@ sh_css_pipe_start(struct ia_css_stream * + * don't use ISP parameters anyway. So this should be okay. + * The SP binary (jpeg) copy does not use any parameters. + */ +- if (!copy_on_sp(pipe)) +- { ++ if (!copy_on_sp(pipe)) { + sh_css_invalidate_params(stream); + err = sh_css_param_update_isp_params(pipe, + stream->isp_params_configs, true, NULL); +@@ -4823,8 +4762,7 @@ sh_css_pipe_start(struct ia_css_stream * + + ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id); + +- if (!sh_css_sp_is_running()) +- { ++ if (!sh_css_sp_is_running()) { + IA_CSS_LEAVE_ERR_PRIVATE(-EBUSY); + /* SP is not running. The queues are not valid */ + return -EBUSY; +@@ -4833,8 +4771,7 @@ sh_css_pipe_start(struct ia_css_stream * + (uint8_t)thread_id, 0, 0); + + /* DH regular multi pipe - not continuous mode: enqueue event to the next pipes too */ +- if (!stream->config.continuous) +- { ++ if (!stream->config.continuous) { + int i; + + for (i = 1; i < stream->num_pipes; i++) { +@@ -4848,8 +4785,7 @@ sh_css_pipe_start(struct ia_css_stream * + } + + /* in case of continuous capture mode, we also start capture thread and copy thread*/ +- if (pipe->stream->config.continuous) +- { ++ if (pipe->stream->config.continuous) { + struct ia_css_pipe *copy_pipe = NULL; + + if (pipe_id == IA_CSS_PIPE_ID_PREVIEW) +@@ -4868,8 +4804,7 @@ sh_css_pipe_start(struct ia_css_stream * + IA_CSS_PSYS_SW_EVENT_START_STREAM, + (uint8_t)thread_id, 0, 0); + } +- if (pipe->stream->cont_capt) +- { ++ if (pipe->stream->cont_capt) { + struct ia_css_pipe *capture_pipe = NULL; + + if (pipe_id == IA_CSS_PIPE_ID_PREVIEW) +@@ -4890,8 +4825,7 @@ sh_css_pipe_start(struct ia_css_stream * + } + + /* in case of PREVIEW mode, check whether QOS acc_pipe is available, then start the qos pipe */ +- if (pipe_id == IA_CSS_PIPE_ID_PREVIEW) +- { ++ if (pipe_id == IA_CSS_PIPE_ID_PREVIEW) { + struct ia_css_pipe *acc_pipe = NULL; + + acc_pipe = pipe->pipe_settings.preview.acc_pipe; +@@ -4942,7 +4876,8 @@ sh_css_continuous_is_enabled(uint8_t pip + /* ISP2400 */ + int + ia_css_stream_get_max_buffer_depth(struct ia_css_stream *stream, +- int *buffer_depth) { ++ int *buffer_depth) ++{ + if (!buffer_depth) + return -EINVAL; + ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_get_max_buffer_depth() enter: void\n"); +@@ -4952,7 +4887,8 @@ ia_css_stream_get_max_buffer_depth(struc + } + + int +-ia_css_stream_set_buffer_depth(struct ia_css_stream *stream, int buffer_depth) { ++ia_css_stream_set_buffer_depth(struct ia_css_stream *stream, int buffer_depth) ++{ + ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_set_buffer_depth() enter: num_frames=%d\n", buffer_depth); + (void)stream; + if (buffer_depth > NUM_CONTINUOUS_FRAMES || buffer_depth < 1) +@@ -4966,7 +4902,8 @@ ia_css_stream_set_buffer_depth(struct ia + /* ISP2401 */ + int + ia_css_stream_get_buffer_depth(struct ia_css_stream *stream, +- int *buffer_depth) { ++ int *buffer_depth) ++{ + if (!buffer_depth) + return -EINVAL; + ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_get_buffer_depth() enter: void\n"); +@@ -4991,8 +4928,7 @@ sh_css_pipes_stop(struct ia_css_stream * + int i; + + assert(stream); +- if (!stream) +- { ++ if (!stream) { + IA_CSS_LOG("stream does NOT exist!"); + err = -EINVAL; + goto ERR; +@@ -5000,8 +4936,7 @@ sh_css_pipes_stop(struct ia_css_stream * + + main_pipe = stream->last_pipe; + assert(main_pipe); +- if (!main_pipe) +- { ++ if (!main_pipe) { + IA_CSS_LOG("main_pipe does NOT exist!"); + err = -EINVAL; + goto ERR; +@@ -5014,8 +4949,7 @@ sh_css_pipes_stop(struct ia_css_stream * + * Stop all "ia_css_pipe" instances in this target + * "ia_css_stream" instance. + */ +- for (i = 0; i < stream->num_pipes; i++) +- { ++ for (i = 0; i < stream->num_pipes; i++) { + /* send the "stop" request to the "ia_css_pipe" instance */ + IA_CSS_LOG("Send the stop-request to the pipe: pipe_id=%d", + stream->pipes[i]->pipeline.pipe_id); +@@ -5049,8 +4983,7 @@ sh_css_pipes_stop(struct ia_css_stream * + * + * We need to stop this "Copy Pipe", as well. + */ +- if (main_pipe->stream->config.continuous) +- { ++ if (main_pipe->stream->config.continuous) { + struct ia_css_pipe *copy_pipe = NULL; + + /* get the reference to "Copy Pipe" */ +@@ -5226,8 +5159,7 @@ sh_css_pipe_get_shading_info(struct ia_c + + binary = ia_css_pipe_get_shading_correction_binary(pipe); + +- if (binary) +- { ++ if (binary) { + err = ia_css_binary_get_shading_info(binary, + IA_CSS_SHADING_CORRECTION_TYPE_1, + pipe->required_bds_factor, +@@ -5237,8 +5169,7 @@ sh_css_pipe_get_shading_info(struct ia_c + /* Other function calls can be added here when other shading correction types will be added + * in the future. + */ +- } else +- { ++ } else { + /* When the pipe does not have a binary which has the shading + * correction, this function does not need to fill the shading + * information. It is not a error case, and then +@@ -5251,7 +5182,8 @@ sh_css_pipe_get_shading_info(struct ia_c + + static int + sh_css_pipe_get_grid_info(struct ia_css_pipe *pipe, +- struct ia_css_grid_info *info) { ++ struct ia_css_grid_info *info) ++{ + int err = 0; + struct ia_css_binary *binary = NULL; + +@@ -5262,30 +5194,27 @@ sh_css_pipe_get_grid_info(struct ia_css_ + + binary = ia_css_pipe_get_s3a_binary(pipe); + +- if (binary) +- { ++ if (binary) { + err = ia_css_binary_3a_grid_info(binary, info, pipe); + if (err) + goto ERR; +- } else ++ } else { + memset(&info->s3a_grid, 0, sizeof(info->s3a_grid)); ++ } + + binary = ia_css_pipe_get_sdis_binary(pipe); + +- if (binary) +- { ++ if (binary) { + ia_css_binary_dvs_grid_info(binary, info, pipe); + ia_css_binary_dvs_stat_grid_info(binary, info, pipe); +- } else +- { ++ } else { + memset(&info->dvs_grid.dvs_grid_info, 0, + sizeof(info->dvs_grid.dvs_grid_info)); + memset(&info->dvs_grid.dvs_stat_grid_info, 0, + sizeof(info->dvs_grid.dvs_stat_grid_info)); + } + +- if (binary) +- { ++ if (binary) { + /* copy pipe does not have ISP binary*/ + info->isp_in_width = binary->internal_frame_info.res.width; + info->isp_in_height = binary->internal_frame_info.res.height; +@@ -5305,7 +5234,8 @@ ERR : + */ + static int + ia_css_pipe_check_format(struct ia_css_pipe *pipe, +- enum ia_css_frame_format format) { ++ enum ia_css_frame_format format) ++{ + const enum ia_css_frame_format *supported_formats; + int number_of_formats; + int found = 0; +@@ -5313,8 +5243,7 @@ ia_css_pipe_check_format(struct ia_css_p + + IA_CSS_ENTER_PRIVATE(""); + +- if (NULL == pipe || NULL == pipe->pipe_settings.video.video_binary.info) +- { ++ if (NULL == pipe || NULL == pipe->pipe_settings.video.video_binary.info) { + IA_CSS_ERROR("Pipe or binary info is not set"); + IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL); + return -EINVAL; +@@ -5323,15 +5252,13 @@ ia_css_pipe_check_format(struct ia_css_p + supported_formats = pipe->pipe_settings.video.video_binary.info->output_formats; + number_of_formats = sizeof(pipe->pipe_settings.video.video_binary.info->output_formats) / sizeof(enum ia_css_frame_format); + +- for (i = 0; i < number_of_formats && !found; i++) +- { ++ for (i = 0; i < number_of_formats && !found; i++) { + if (supported_formats[i] == format) { + found = 1; + break; + } + } +- if (!found) +- { ++ if (!found) { + IA_CSS_ERROR("Requested format is not supported by binary"); + IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL); + return -EINVAL; +@@ -5483,10 +5410,10 @@ static int load_video_binaries(struct ia + &mycs->video_binary); + + if (err) { +- if (video_vf_info) { +- /* This will do another video binary lookup later for YUV_LINE format*/ ++ /* This will do another video binary lookup later for YUV_LINE format*/ ++ if (video_vf_info) + need_vf_pp = true; +- } else ++ else + return err; + } else if (video_vf_info) { + /* The first video binary lookup is successful, but we may +@@ -5649,13 +5576,13 @@ static int load_video_binaries(struct ia + } + + static int +-unload_video_binaries(struct ia_css_pipe *pipe) { ++unload_video_binaries(struct ia_css_pipe *pipe) ++{ + unsigned int i; + + IA_CSS_ENTER_PRIVATE("pipe = %p", pipe); + +- if ((!pipe) || (pipe->mode != IA_CSS_PIPE_ID_VIDEO)) +- { ++ if ((!pipe) || (pipe->mode != IA_CSS_PIPE_ID_VIDEO)) { + IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL); + return -EINVAL; + } +@@ -5805,31 +5732,29 @@ static int + sh_css_pipe_configure_viewfinder(struct ia_css_pipe *pipe, unsigned int width, + unsigned int height, unsigned int min_width, + enum ia_css_frame_format format, +- unsigned int idx) { ++ unsigned int idx) ++{ + int err = 0; + + IA_CSS_ENTER_PRIVATE("pipe = %p, width = %d, height = %d, min_width = %d, format = %d, idx = %d\n", + pipe, width, height, min_width, format, idx); + +- if (!pipe) +- { ++ if (!pipe) { + IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL); + return -EINVAL; + } + + err = ia_css_util_check_res(width, height); +- if (err) +- { ++ if (err) { + IA_CSS_LEAVE_ERR_PRIVATE(err); + return err; + } + if (pipe->vf_output_info[idx].res.width != width || + pipe->vf_output_info[idx].res.height != height || + pipe->vf_output_info[idx].format != format) +- { + ia_css_frame_info_init(&pipe->vf_output_info[idx], width, height, + format, min_width); +- } ++ + IA_CSS_LEAVE_ERR_PRIVATE(0); + return 0; + } +@@ -6209,7 +6134,8 @@ static int load_primary_binaries( + } + + static int +-allocate_delay_frames(struct ia_css_pipe *pipe) { ++allocate_delay_frames(struct ia_css_pipe *pipe) ++{ + unsigned int num_delay_frames = 0, i = 0; + unsigned int dvs_frame_delay = 0; + struct ia_css_frame_info ref_info; +@@ -6219,8 +6145,7 @@ allocate_delay_frames(struct ia_css_pipe + + IA_CSS_ENTER_PRIVATE(""); + +- if (!pipe) +- { ++ if (!pipe) { + IA_CSS_ERROR("Invalid args - pipe %p", pipe); + return -EINVAL; + } +@@ -6231,8 +6156,7 @@ allocate_delay_frames(struct ia_css_pipe + if (dvs_frame_delay > 0) + num_delay_frames = dvs_frame_delay + 1; + +- switch (mode) +- { ++ switch (mode) { + case IA_CSS_PIPE_ID_CAPTURE: { + struct ia_css_capture_settings *mycs_capture = &pipe->pipe_settings.capture; + (void)mycs_capture; +@@ -6284,8 +6208,7 @@ allocate_delay_frames(struct ia_css_pipe + ref_info.raw_bit_depth = SH_CSS_REF_BIT_DEPTH; + + assert(num_delay_frames <= MAX_NUM_VIDEO_DELAY_FRAMES); +- for (i = 0; i < num_delay_frames; i++) +- { ++ for (i = 0; i < num_delay_frames; i++) { + err = ia_css_frame_allocate_from_info(&delay_frames[i], &ref_info); + if (err) + return err; +@@ -6295,7 +6218,8 @@ allocate_delay_frames(struct ia_css_pipe + } + + static int load_advanced_binaries( +- struct ia_css_pipe *pipe) { ++ struct ia_css_pipe *pipe) ++{ + struct ia_css_frame_info pre_in_info, gdc_in_info, + post_in_info, post_out_info, + vf_info, *vf_pp_in_info, *pipe_out_info, +@@ -6412,7 +6336,8 @@ static int load_advanced_binaries( + } + + static int load_bayer_isp_binaries( +- struct ia_css_pipe *pipe) { ++ struct ia_css_pipe *pipe) ++{ + struct ia_css_frame_info pre_isp_in_info, *pipe_out_info; + int err = 0; + struct ia_css_binary_descr pre_de_descr; +@@ -6441,7 +6366,8 @@ static int load_bayer_isp_binaries( + } + + static int load_low_light_binaries( +- struct ia_css_pipe *pipe) { ++ struct ia_css_pipe *pipe) ++{ + struct ia_css_frame_info pre_in_info, anr_in_info, + post_in_info, post_out_info, + vf_info, *pipe_vf_out_info, *pipe_out_info, +@@ -6579,7 +6505,8 @@ static bool copy_on_sp(struct ia_css_pip + } + + static int load_capture_binaries( +- struct ia_css_pipe *pipe) { ++ struct ia_css_pipe *pipe) ++{ + int err = 0; + bool must_be_raw; + +@@ -6647,13 +6574,13 @@ static int load_capture_binaries( + } + + static int +-unload_capture_binaries(struct ia_css_pipe *pipe) { ++unload_capture_binaries(struct ia_css_pipe *pipe) ++{ + unsigned int i; + + IA_CSS_ENTER_PRIVATE("pipe = %p", pipe); + +- if ((!pipe) || ((pipe->mode != IA_CSS_PIPE_ID_CAPTURE) && (pipe->mode != IA_CSS_PIPE_ID_COPY))) +- { ++ if ((!pipe) || ((pipe->mode != IA_CSS_PIPE_ID_CAPTURE) && (pipe->mode != IA_CSS_PIPE_ID_COPY))) { + IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL); + return -EINVAL; + } +@@ -6681,7 +6608,8 @@ unload_capture_binaries(struct ia_css_pi + + static bool + need_downscaling(const struct ia_css_resolution in_res, +- const struct ia_css_resolution out_res) { ++ const struct ia_css_resolution out_res) ++{ + if (in_res.width > out_res.width || in_res.height > out_res.height) + return true; + +@@ -6689,7 +6617,8 @@ need_downscaling(const struct ia_css_res + } + + static bool +-need_yuv_scaler_stage(const struct ia_css_pipe *pipe) { ++need_yuv_scaler_stage(const struct ia_css_pipe *pipe) ++{ + unsigned int i; + struct ia_css_resolution in_res, out_res; + +@@ -6731,7 +6660,8 @@ static int ia_css_pipe_create_cas_scaler + struct ia_css_frame_info *cas_scaler_in_info, + struct ia_css_frame_info *cas_scaler_out_info, + struct ia_css_frame_info *cas_scaler_vf_info, +- struct ia_css_cas_binary_descr *descr) { ++ struct ia_css_cas_binary_descr *descr) ++{ + unsigned int i; + unsigned int hor_ds_factor = 0, ver_ds_factor = 0; + int err = 0; +@@ -6849,7 +6779,8 @@ ERR: + /* FIXME: merge most of this and single output version */ + static int ia_css_pipe_create_cas_scaler_desc( + struct ia_css_pipe *pipe, +- struct ia_css_cas_binary_descr *descr) { ++ struct ia_css_cas_binary_descr *descr) ++{ + struct ia_css_frame_info in_info = IA_CSS_BINARY_DEFAULT_FRAME_INFO; + struct ia_css_frame_info *out_info[IA_CSS_PIPE_MAX_OUTPUT_STAGE]; + struct ia_css_frame_info *vf_out_info[IA_CSS_PIPE_MAX_OUTPUT_STAGE]; +@@ -7005,7 +6936,8 @@ ERR: + } + + static void ia_css_pipe_destroy_cas_scaler_desc(struct ia_css_cas_binary_descr +- *descr) { ++ *descr) ++{ + ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, + "ia_css_pipe_destroy_cas_scaler_desc() enter:\n"); + kfree(descr->in_info); +@@ -7023,7 +6955,8 @@ static void ia_css_pipe_destroy_cas_scal + } + + static int +-load_yuvpp_binaries(struct ia_css_pipe *pipe) { ++load_yuvpp_binaries(struct ia_css_pipe *pipe) ++{ + int err = 0; + bool need_scaler = false; + struct ia_css_frame_info *vf_pp_in_info[IA_CSS_PIPE_MAX_OUTPUT_STAGE]; +@@ -7048,8 +6981,7 @@ load_yuvpp_binaries(struct ia_css_pipe * + + mycs = &pipe->pipe_settings.yuvpp; + +- for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) +- { ++ for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) { + if (pipe->vf_output_info[i].res.width != 0) { + err = ia_css_util_check_vf_out_info(&pipe->output_info[i], + &pipe->vf_output_info[i]); +@@ -7063,8 +6995,7 @@ load_yuvpp_binaries(struct ia_css_pipe * + + /* we build up the pipeline starting at the end */ + /* Capture post-processing */ +- if (need_scaler) +- { ++ if (need_scaler) { + struct ia_css_binary_descr yuv_scaler_descr; + + err = ia_css_pipe_create_cas_scaler_desc(pipe, +@@ -7098,18 +7029,14 @@ load_yuvpp_binaries(struct ia_css_pipe * + goto ERR; + } + ia_css_pipe_destroy_cas_scaler_desc(&cas_scaler_descr); +- } else +- { ++ } else { + mycs->num_output = 1; + } + + if (need_scaler) +- { + next_binary = &mycs->yuv_scaler_binary[0]; +- } else +- { ++ else + next_binary = NULL; +- } + + #if defined(ISP2401) + /* +@@ -7135,8 +7062,7 @@ load_yuvpp_binaries(struct ia_css_pipe * + need_isp_copy_binary = true; + #endif /* ISP2401 */ + +- if (need_isp_copy_binary) +- { ++ if (need_isp_copy_binary) { + err = load_copy_binary(pipe, + &mycs->copy_binary, + next_binary); +@@ -7166,8 +7092,7 @@ load_yuvpp_binaries(struct ia_css_pipe * + } + + /* Viewfinder post-processing */ +- if (need_scaler) +- { ++ if (need_scaler) { + for (i = 0, j = 0; i < mycs->num_yuv_scaler; i++) { + if (mycs->is_output_stage[i]) { + assert(j < 2); +@@ -7177,19 +7102,17 @@ load_yuvpp_binaries(struct ia_css_pipe * + } + } + mycs->num_vf_pp = j; +- } else +- { ++ } else { + vf_pp_in_info[0] = + &mycs->copy_binary.vf_frame_info; +- for (i = 1; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) { ++ for (i = 1; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) + vf_pp_in_info[i] = NULL; +- } ++ + mycs->num_vf_pp = 1; + } + mycs->vf_pp_binary = kzalloc(mycs->num_vf_pp * sizeof(struct ia_css_binary), + GFP_KERNEL); +- if (!mycs->vf_pp_binary) +- { ++ if (!mycs->vf_pp_binary) { + err = -ENOMEM; + goto ERR; + } +@@ -7197,8 +7120,7 @@ load_yuvpp_binaries(struct ia_css_pipe * + { + struct ia_css_binary_descr vf_pp_descr; + +- for (i = 0; i < mycs->num_vf_pp; i++) +- { ++ for (i = 0; i < mycs->num_vf_pp; i++) { + if (pipe->vf_output_info[i].res.width != 0) { + ia_css_pipe_get_vfpp_binarydesc(pipe, + &vf_pp_descr, vf_pp_in_info[i], &pipe->vf_output_info[i]); +@@ -7214,34 +7136,31 @@ load_yuvpp_binaries(struct ia_css_pipe * + + ERR: + if (need_scaler) +- { + ia_css_pipe_destroy_cas_scaler_desc(&cas_scaler_descr); +- } ++ + ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "load_yuvpp_binaries() leave, err=%d\n", + err); + return err; + } + + static int +-unload_yuvpp_binaries(struct ia_css_pipe *pipe) { ++unload_yuvpp_binaries(struct ia_css_pipe *pipe) ++{ + unsigned int i; + + IA_CSS_ENTER_PRIVATE("pipe = %p", pipe); + +- if ((!pipe) || (pipe->mode != IA_CSS_PIPE_ID_YUVPP)) +- { ++ if ((!pipe) || (pipe->mode != IA_CSS_PIPE_ID_YUVPP)) { + IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL); + return -EINVAL; + } + ia_css_binary_unload(&pipe->pipe_settings.yuvpp.copy_binary); + for (i = 0; i < pipe->pipe_settings.yuvpp.num_yuv_scaler; i++) +- { + ia_css_binary_unload(&pipe->pipe_settings.yuvpp.yuv_scaler_binary[i]); +- } ++ + for (i = 0; i < pipe->pipe_settings.yuvpp.num_vf_pp; i++) +- { + ia_css_binary_unload(&pipe->pipe_settings.yuvpp.vf_pp_binary[i]); +- } ++ + kfree(pipe->pipe_settings.yuvpp.is_output_stage); + pipe->pipe_settings.yuvpp.is_output_stage = NULL; + kfree(pipe->pipe_settings.yuvpp.yuv_scaler_binary); +@@ -7291,25 +7210,23 @@ static int yuvpp_start(struct ia_css_pip + } + + static int +-sh_css_pipe_unload_binaries(struct ia_css_pipe *pipe) { ++sh_css_pipe_unload_binaries(struct ia_css_pipe *pipe) ++{ + int err = 0; + + IA_CSS_ENTER_PRIVATE("pipe = %p", pipe); + +- if (!pipe) +- { ++ if (!pipe) { + IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL); + return -EINVAL; + } + /* PIPE_MODE_COPY has no binaries, but has output frames to outside*/ +- if (pipe->config.mode == IA_CSS_PIPE_MODE_COPY) +- { ++ if (pipe->config.mode == IA_CSS_PIPE_MODE_COPY) { + IA_CSS_LEAVE_ERR_PRIVATE(0); + return 0; + } + +- switch (pipe->mode) +- { ++ switch (pipe->mode) { + case IA_CSS_PIPE_ID_PREVIEW: + err = unload_preview_binaries(pipe); + break; +@@ -7330,7 +7247,8 @@ sh_css_pipe_unload_binaries(struct ia_cs + } + + static int +-sh_css_pipe_load_binaries(struct ia_css_pipe *pipe) { ++sh_css_pipe_load_binaries(struct ia_css_pipe *pipe) ++{ + int err = 0; + + assert(pipe); +@@ -7340,8 +7258,7 @@ sh_css_pipe_load_binaries(struct ia_css_ + if (pipe->config.mode == IA_CSS_PIPE_MODE_COPY) + return err; + +- switch (pipe->mode) +- { ++ switch (pipe->mode) { + case IA_CSS_PIPE_ID_PREVIEW: + err = load_preview_binaries(pipe); + break; +@@ -7360,8 +7277,7 @@ sh_css_pipe_load_binaries(struct ia_css_ + err = -EINVAL; + break; + } +- if (err) +- { ++ if (err) { + if (sh_css_pipe_unload_binaries(pipe)) { + /* currently css does not support multiple error returns in a single function, + * using -EINVAL in this case */ +@@ -7372,7 +7288,8 @@ sh_css_pipe_load_binaries(struct ia_css_ + } + + static int +-create_host_yuvpp_pipeline(struct ia_css_pipe *pipe) { ++create_host_yuvpp_pipeline(struct ia_css_pipe *pipe) ++{ + struct ia_css_pipeline *me; + int err = 0; + struct ia_css_pipeline_stage *vf_pp_stage = NULL, +@@ -7399,15 +7316,13 @@ create_host_yuvpp_pipeline(struct ia_css + #endif + + IA_CSS_ENTER_PRIVATE("pipe = %p", pipe); +- if ((!pipe) || (!pipe->stream) || (pipe->mode != IA_CSS_PIPE_ID_YUVPP)) +- { ++ if ((!pipe) || (!pipe->stream) || (pipe->mode != IA_CSS_PIPE_ID_YUVPP)) { + IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL); + return -EINVAL; + } + me = &pipe->pipeline; + ia_css_pipeline_clean(me); +- for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) +- { ++ for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) { + out_frame[i] = NULL; + vf_frame[i] = NULL; + } +@@ -7435,8 +7350,7 @@ create_host_yuvpp_pipeline(struct ia_css + /* the input frame can come from: + * a) memory: connect yuvscaler to me->in_frame + * b) sensor, via copy binary: connect yuvscaler to copy binary later on */ +- if (need_in_frameinfo_memory) +- { ++ if (need_in_frameinfo_memory) { + /* TODO: improve for different input formats. */ + + /* +@@ -7485,13 +7399,11 @@ create_host_yuvpp_pipeline(struct ia_css + } + + in_frame = &me->in_frame; +- } else +- { ++ } else { + in_frame = NULL; + } + +- for (i = 0; i < num_output_stage; i++) +- { ++ for (i = 0; i < num_output_stage; i++) { + assert(i < IA_CSS_PIPE_MAX_OUTPUT_STAGE); + if (pipe->output_info[i].res.width != 0) { + err = init_out_frameinfo_defaults(pipe, &me->out_frame[i], i); +@@ -7518,8 +7430,7 @@ create_host_yuvpp_pipeline(struct ia_css + yuv_scaler_binary = pipe->pipe_settings.yuvpp.yuv_scaler_binary; + need_scaler = need_yuv_scaler_stage(pipe); + +- if (pipe->pipe_settings.yuvpp.copy_binary.info) +- { ++ if (pipe->pipe_settings.yuvpp.copy_binary.info) { + struct ia_css_frame *in_frame_local = NULL; + + #ifdef ISP2401 +@@ -7557,8 +7468,7 @@ create_host_yuvpp_pipeline(struct ia_css + } + } + +- if (need_scaler) +- { ++ if (need_scaler) { + struct ia_css_frame *tmp_out_frame = NULL; + struct ia_css_frame *tmp_vf_frame = NULL; + struct ia_css_frame *tmp_in_frame = in_frame; +@@ -7598,8 +7508,7 @@ create_host_yuvpp_pipeline(struct ia_css + j++; + } + } +- } else if (copy_stage) +- { ++ } else if (copy_stage) { + if (vf_frame[0] && vf_frame[0]->info.res.width != 0) { + in_frame = copy_stage->args.out_vf_frame; + err = add_vf_pp_stage(pipe, in_frame, vf_frame[0], &vf_pp_binary[0], +@@ -7621,7 +7530,8 @@ create_host_yuvpp_pipeline(struct ia_css + static int + create_host_copy_pipeline(struct ia_css_pipe *pipe, + unsigned int max_input_width, +- struct ia_css_frame *out_frame) { ++ struct ia_css_frame *out_frame) ++{ + struct ia_css_pipeline *me; + int err = 0; + struct ia_css_pipeline_stage_desc stage_desc; +@@ -7638,16 +7548,14 @@ create_host_copy_pipeline(struct ia_css_ + out_frame->flash_state = IA_CSS_FRAME_FLASH_STATE_NONE; + + if (copy_on_sp(pipe) && +- pipe->stream->config.input_config.format == ATOMISP_INPUT_FORMAT_BINARY_8) +- { ++ pipe->stream->config.input_config.format == ATOMISP_INPUT_FORMAT_BINARY_8) { + ia_css_frame_info_init( + &out_frame->info, + JPEG_BYTES, + 1, + IA_CSS_FRAME_FORMAT_BINARY_8, + 0); +- } else if (out_frame->info.format == IA_CSS_FRAME_FORMAT_RAW) +- { ++ } else if (out_frame->info.format == IA_CSS_FRAME_FORMAT_RAW) { + out_frame->info.raw_bit_depth = + ia_css_pipe_util_pipe_input_format_bpp(pipe); + } +@@ -7671,7 +7579,8 @@ create_host_copy_pipeline(struct ia_css_ + } + + static int +-create_host_isyscopy_capture_pipeline(struct ia_css_pipe *pipe) { ++create_host_isyscopy_capture_pipeline(struct ia_css_pipe *pipe) ++{ + struct ia_css_pipeline *me = &pipe->pipeline; + int err = 0; + struct ia_css_pipeline_stage_desc stage_desc; +@@ -7715,7 +7624,8 @@ create_host_isyscopy_capture_pipeline(st + } + + static int +-create_host_regular_capture_pipeline(struct ia_css_pipe *pipe) { ++create_host_regular_capture_pipeline(struct ia_css_pipe *pipe) ++{ + struct ia_css_pipeline *me; + int err = 0; + enum ia_css_capture_mode mode; +@@ -7779,8 +7689,7 @@ create_host_regular_capture_pipeline(str + /* Construct in_frame info (only in case we have dynamic input */ + need_in_frameinfo_memory = pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY; + #endif +- if (need_in_frameinfo_memory) +- { ++ if (need_in_frameinfo_memory) { + err = init_in_frameinfo_memory_defaults(pipe, &me->in_frame, + IA_CSS_FRAME_FORMAT_RAW); + if (err) { +@@ -7789,22 +7698,19 @@ create_host_regular_capture_pipeline(str + } + + in_frame = &me->in_frame; +- } else +- { ++ } else { + in_frame = NULL; + } + + err = init_out_frameinfo_defaults(pipe, &me->out_frame[0], 0); +- if (err) +- { ++ if (err) { + IA_CSS_LEAVE_ERR_PRIVATE(err); + return err; + } + out_frame = &me->out_frame[0]; + + /* Construct vf_frame info (only in case we have VF) */ +- if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0]) +- { ++ if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0]) { + if (mode == IA_CSS_CAPTURE_MODE_RAW || mode == IA_CSS_CAPTURE_MODE_BAYER) { + /* These modes don't support viewfinder output */ + vf_frame = NULL; +@@ -7812,22 +7718,20 @@ create_host_regular_capture_pipeline(str + init_vf_frameinfo_defaults(pipe, &me->vf_frame[0], 0); + vf_frame = &me->vf_frame[0]; + } +- } else +- { ++ } else { + vf_frame = NULL; + } + + copy_binary = &pipe->pipe_settings.capture.copy_binary; + num_primary_stage = pipe->pipe_settings.capture.num_primary_stage; +- if ((num_primary_stage == 0) && (mode == IA_CSS_CAPTURE_MODE_PRIMARY)) +- { ++ if ((num_primary_stage == 0) && (mode == IA_CSS_CAPTURE_MODE_PRIMARY)) { + IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL); + return -EINVAL; + } ++ + for (i = 0; i < num_primary_stage; i++) +- { + primary_binary[i] = &pipe->pipe_settings.capture.primary_binary[i]; +- } ++ + vf_pp_binary = &pipe->pipe_settings.capture.vf_pp_binary; + pre_isp_binary = &pipe->pipe_settings.capture.pre_isp_binary; + anr_gdc_binary = &pipe->pipe_settings.capture.anr_gdc_binary; +@@ -7844,8 +7748,7 @@ create_host_regular_capture_pipeline(str + need_yuv_pp = (yuv_scaler_binary && yuv_scaler_binary->info); + need_ldc = (capture_ldc_binary && capture_ldc_binary->info); + +- if (pipe->pipe_settings.capture.copy_binary.info) +- { ++ if (pipe->pipe_settings.capture.copy_binary.info) { + if (raw) { + ia_css_pipe_util_set_output_frames(out_frames, 0, out_frame); + #if defined(ISP2401) +@@ -7874,13 +7777,11 @@ create_host_regular_capture_pipeline(str + IA_CSS_LEAVE_ERR_PRIVATE(err); + return err; + } +- } else if (pipe->stream->config.continuous) +- { ++ } else if (pipe->stream->config.continuous) { + in_frame = pipe->stream->last_pipe->continuous_frames[0]; + } + +- if (mode == IA_CSS_CAPTURE_MODE_PRIMARY) +- { ++ if (mode == IA_CSS_CAPTURE_MODE_PRIMARY) { + struct ia_css_frame *local_in_frame = NULL; + struct ia_css_frame *local_out_frame = NULL; + +@@ -7925,8 +7826,7 @@ create_host_regular_capture_pipeline(str + IA_CSS_BINARY_MODE_COPY; + current_stage->args.copy_output = current_stage->args.copy_vf; + } else if (mode == IA_CSS_CAPTURE_MODE_ADVANCED || +- mode == IA_CSS_CAPTURE_MODE_LOW_LIGHT) +- { ++ mode == IA_CSS_CAPTURE_MODE_LOW_LIGHT) { + ia_css_pipe_util_set_output_frames(out_frames, 0, NULL); + ia_css_pipe_get_generic_stage_desc(&stage_desc, pre_isp_binary, + out_frames, in_frame, NULL); +@@ -7962,8 +7862,7 @@ create_host_regular_capture_pipeline(str + IA_CSS_LEAVE_ERR_PRIVATE(err); + return err; + } +- } else if (mode == IA_CSS_CAPTURE_MODE_BAYER) +- { ++ } else if (mode == IA_CSS_CAPTURE_MODE_BAYER) { + ia_css_pipe_util_set_output_frames(out_frames, 0, out_frame); + ia_css_pipe_get_generic_stage_desc(&stage_desc, pre_isp_binary, + out_frames, in_frame, NULL); +@@ -7977,8 +7876,7 @@ create_host_regular_capture_pipeline(str + } + + #ifndef ISP2401 +- if (need_pp && current_stage) +- { ++ if (need_pp && current_stage) { + struct ia_css_frame *local_in_frame = NULL; + + local_in_frame = current_stage->args.out_frame[0]; +@@ -7996,8 +7894,7 @@ create_host_regular_capture_pipeline(str + need_yuv_pp ? NULL : out_frame, + #else + /* ldc and capture_pp not supported in same pipeline */ +- if (need_ldc && current_stage) +- { ++ if (need_ldc && current_stage) { + in_frame = current_stage->args.out_frame[0]; + ia_css_pipe_util_set_output_frames(out_frames, 0, out_frame); + ia_css_pipe_get_generic_stage_desc(&stage_desc, capture_ldc_binary, +@@ -8005,8 +7902,7 @@ create_host_regular_capture_pipeline(str + err = ia_css_pipeline_create_and_add_stage(me, + &stage_desc, + NULL); +- } else if (need_pp && current_stage) +- { ++ } else if (need_pp && current_stage) { + in_frame = current_stage->args.out_frame[0]; + err = add_capture_pp_stage(pipe, me, in_frame, need_yuv_pp ? NULL : out_frame, + #endif +@@ -8018,8 +7914,7 @@ create_host_regular_capture_pipeline(str + } + } + +- if (need_yuv_pp && current_stage) +- { ++ if (need_yuv_pp && current_stage) { + struct ia_css_frame *tmp_in_frame = current_stage->args.out_frame[0]; + struct ia_css_frame *tmp_out_frame = NULL; + +@@ -8051,8 +7946,7 @@ create_host_regular_capture_pipeline(str + * should not be considered as a clean solution. Proper + * investigation should be done to come up with the clean solution. + * */ +- if (mode != IA_CSS_CAPTURE_MODE_RAW && mode != IA_CSS_CAPTURE_MODE_BAYER && current_stage && vf_frame) +- { ++ if (mode != IA_CSS_CAPTURE_MODE_RAW && mode != IA_CSS_CAPTURE_MODE_BAYER && current_stage && vf_frame) { + in_frame = current_stage->args.out_vf_frame; + err = add_vf_pp_stage(pipe, in_frame, vf_frame, vf_pp_binary, + ¤t_stage); +@@ -8070,7 +7964,8 @@ create_host_regular_capture_pipeline(str + } + + static int +-create_host_capture_pipeline(struct ia_css_pipe *pipe) { ++create_host_capture_pipeline(struct ia_css_pipe *pipe) ++{ + int err = 0; + + IA_CSS_ENTER_PRIVATE("pipe = %p", pipe); +@@ -8079,8 +7974,7 @@ create_host_capture_pipeline(struct ia_c + err = create_host_isyscopy_capture_pipeline(pipe); + else + err = create_host_regular_capture_pipeline(pipe); +- if (err) +- { ++ if (err) { + IA_CSS_LEAVE_ERR_PRIVATE(err); + return err; + } +@@ -8091,7 +7985,8 @@ create_host_capture_pipeline(struct ia_c + } + + static int capture_start( +- struct ia_css_pipe *pipe) { ++ struct ia_css_pipe *pipe) ++{ + struct ia_css_pipeline *me; + + int err = 0; +@@ -8162,7 +8057,8 @@ static int capture_start( + static int + sh_css_pipe_get_output_frame_info(struct ia_css_pipe *pipe, + struct ia_css_frame_info *info, +- unsigned int idx) { ++ unsigned int idx) ++{ + assert(pipe); + assert(info); + +@@ -8171,8 +8067,7 @@ sh_css_pipe_get_output_frame_info(struct + + *info = pipe->output_info[idx]; + if (copy_on_sp(pipe) && +- pipe->stream->config.input_config.format == ATOMISP_INPUT_FORMAT_BINARY_8) +- { ++ pipe->stream->config.input_config.format == ATOMISP_INPUT_FORMAT_BINARY_8) { + ia_css_frame_info_init( + info, + JPEG_BYTES, +@@ -8180,8 +8075,7 @@ sh_css_pipe_get_output_frame_info(struct + IA_CSS_FRAME_FORMAT_BINARY_8, + 0); + } else if (info->format == IA_CSS_FRAME_FORMAT_RAW || +- info->format == IA_CSS_FRAME_FORMAT_RAW_PACKED) +- { ++ info->format == IA_CSS_FRAME_FORMAT_RAW_PACKED) { + info->raw_bit_depth = + ia_css_pipe_util_pipe_input_format_bpp(pipe); + } +@@ -8195,7 +8089,8 @@ void + ia_css_stream_send_input_frame(const struct ia_css_stream *stream, + const unsigned short *data, + unsigned int width, +- unsigned int height) { ++ unsigned int height) ++{ + assert(stream); + + ia_css_inputfifo_send_input_frame( +@@ -8206,7 +8101,8 @@ ia_css_stream_send_input_frame(const str + } + + void +-ia_css_stream_start_input_frame(const struct ia_css_stream *stream) { ++ia_css_stream_start_input_frame(const struct ia_css_stream *stream) ++{ + assert(stream); + + ia_css_inputfifo_start_frame( +@@ -8220,7 +8116,8 @@ ia_css_stream_send_input_line(const stru + const unsigned short *data, + unsigned int width, + const unsigned short *data2, +- unsigned int width2) { ++ unsigned int width2) ++{ + assert(stream); + + ia_css_inputfifo_send_line(stream->config.channel_id, +@@ -8231,7 +8128,8 @@ void + ia_css_stream_send_input_embedded_line(const struct ia_css_stream *stream, + enum atomisp_input_format format, + const unsigned short *data, +- unsigned int width) { ++ unsigned int width) ++{ + assert(stream); + if (!data || width == 0) + return; +@@ -8240,14 +8138,16 @@ ia_css_stream_send_input_embedded_line(c + } + + void +-ia_css_stream_end_input_frame(const struct ia_css_stream *stream) { ++ia_css_stream_end_input_frame(const struct ia_css_stream *stream) ++{ + assert(stream); + + ia_css_inputfifo_end_frame(stream->config.channel_id); + } + + static void +-append_firmware(struct ia_css_fw_info **l, struct ia_css_fw_info *firmware) { ++append_firmware(struct ia_css_fw_info **l, struct ia_css_fw_info *firmware) ++{ + IA_CSS_ENTER_PRIVATE("l = %p, firmware = %p", l, firmware); + if (!l) { + IA_CSS_ERROR("NULL fw_info"); +@@ -8262,7 +8162,8 @@ append_firmware(struct ia_css_fw_info ** + } + + static void +-remove_firmware(struct ia_css_fw_info **l, struct ia_css_fw_info *firmware) { ++remove_firmware(struct ia_css_fw_info **l, struct ia_css_fw_info *firmware) ++{ + assert(*l); + assert(firmware); + (void)l; +@@ -8304,12 +8205,12 @@ static int upload_isp_code(struct ia_css + } + + static int +-acc_load_extension(struct ia_css_fw_info *firmware) { ++acc_load_extension(struct ia_css_fw_info *firmware) ++{ + int err; + struct ia_css_fw_info *hd = firmware; + +- while (hd) +- { ++ while (hd) { + err = upload_isp_code(hd); + if (err) + return err; +@@ -8323,7 +8224,8 @@ acc_load_extension(struct ia_css_fw_info + } + + static void +-acc_unload_extension(struct ia_css_fw_info *firmware) { ++acc_unload_extension(struct ia_css_fw_info *firmware) ++{ + struct ia_css_fw_info *hd = firmware; + struct ia_css_fw_info *hdn = NULL; + +@@ -8347,13 +8249,13 @@ acc_unload_extension(struct ia_css_fw_in + /* Load firmware for extension */ + static int + ia_css_pipe_load_extension(struct ia_css_pipe *pipe, +- struct ia_css_fw_info *firmware) { ++ struct ia_css_fw_info *firmware) ++{ + int err = 0; + + IA_CSS_ENTER_PRIVATE("fw = %p pipe = %p", firmware, pipe); + +- if ((!firmware) || (!pipe)) +- { ++ if ((!firmware) || (!pipe)) { + IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL); + return -EINVAL; + } +@@ -8371,7 +8273,8 @@ ia_css_pipe_load_extension(struct ia_css + /* Unload firmware for extension */ + static void + ia_css_pipe_unload_extension(struct ia_css_pipe *pipe, +- struct ia_css_fw_info *firmware) { ++ struct ia_css_fw_info *firmware) ++{ + IA_CSS_ENTER_PRIVATE("fw = %p pipe = %p", firmware, pipe); + + if ((!firmware) || (!pipe)) { +@@ -8390,7 +8293,8 @@ ia_css_pipe_unload_extension(struct ia_c + } + + bool +-ia_css_pipeline_uses_params(struct ia_css_pipeline *me) { ++ia_css_pipeline_uses_params(struct ia_css_pipeline *me) ++{ + struct ia_css_pipeline_stage *stage; + + assert(me); +@@ -8411,7 +8315,8 @@ ia_css_pipeline_uses_params(struct ia_cs + + static int + sh_css_pipeline_add_acc_stage(struct ia_css_pipeline *pipeline, +- const void *acc_fw) { ++ const void *acc_fw) ++{ + struct ia_css_fw_info *fw = (struct ia_css_fw_info *)acc_fw; + /* In QoS case, load_extension already called, so skipping */ + int err = 0; +@@ -8423,8 +8328,7 @@ sh_css_pipeline_add_acc_stage(struct ia_ + "sh_css_pipeline_add_acc_stage() enter: pipeline=%p, acc_fw=%p\n", + pipeline, acc_fw); + +- if (!err) +- { ++ if (!err) { + struct ia_css_pipeline_stage_desc stage_desc; + + ia_css_pipe_get_acc_stage_desc(&stage_desc, NULL, fw); +@@ -8443,7 +8347,8 @@ sh_css_pipeline_add_acc_stage(struct ia_ + * Refer to "sh_css_internal.h" for details. + */ + int ia_css_stream_capture_frame(struct ia_css_stream *stream, +- unsigned int exp_id) { ++ unsigned int exp_id) ++{ + struct sh_css_tag_descr tag_descr; + u32 encoded_tag_descr; + int err; +@@ -8485,7 +8390,8 @@ int ia_css_stream_capture( + struct ia_css_stream *stream, + int num_captures, + unsigned int skip, +- int offset) { ++ int offset) ++{ + struct sh_css_tag_descr tag_descr; + unsigned int encoded_tag_descr; + int return_err; +@@ -8548,8 +8454,9 @@ void ia_css_stream_request_flash(struct + ia_css_debug_dump_sp_sw_debug_info(); + ia_css_debug_dump_debug_info(NULL); + } +- } else ++ } else { + IA_CSS_LOG("SP is not running!"); ++ } + + #endif + ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, +@@ -8557,7 +8464,8 @@ void ia_css_stream_request_flash(struct + } + + static void +-sh_css_init_host_sp_control_vars(void) { ++sh_css_init_host_sp_control_vars(void) ++{ + const struct ia_css_fw_info *fw; + unsigned int HIVE_ADDR_ia_css_ispctrl_sp_isp_started; + +@@ -8641,7 +8549,8 @@ void ia_css_pipe_config_defaults(struct + + void + ia_css_pipe_extra_config_defaults(struct ia_css_pipe_extra_config +- *extra_config) { ++ *extra_config) ++{ + if (!extra_config) { + IA_CSS_ERROR("NULL input parameter"); + return; +@@ -8671,11 +8580,11 @@ void ia_css_stream_config_defaults(struc + } + + static int +-ia_css_acc_pipe_create(struct ia_css_pipe *pipe) { ++ia_css_acc_pipe_create(struct ia_css_pipe *pipe) ++{ + int err = 0; + +- if (!pipe) +- { ++ if (!pipe) { + IA_CSS_ERROR("NULL input parameter"); + return -EINVAL; + } +@@ -8685,9 +8594,7 @@ ia_css_acc_pipe_create(struct ia_css_pip + pipe->config.acc_num_execs = 1; + + if (pipe->config.acc_extension) +- { + err = ia_css_pipe_load_extension(pipe, pipe->config.acc_extension); +- } + + return err; + } +@@ -8706,9 +8613,8 @@ int ia_css_pipe_create(const struct ia_c + + err = ia_css_pipe_create_extra(config, NULL, pipe); + +- if (err == 0) { ++ if (err == 0) + IA_CSS_LOG("pipe created successfully = %p", *pipe); +- } + + IA_CSS_LEAVE_ERR_PRIVATE(err); + +@@ -8718,7 +8624,8 @@ int ia_css_pipe_create(const struct ia_c + int + ia_css_pipe_create_extra(const struct ia_css_pipe_config *config, + const struct ia_css_pipe_extra_config *extra_config, +- struct ia_css_pipe **pipe) { ++ struct ia_css_pipe **pipe) ++{ + int err = -EINVAL; + struct ia_css_pipe *internal_pipe = NULL; + unsigned int i; +@@ -8726,14 +8633,12 @@ ia_css_pipe_create_extra(const struct ia + IA_CSS_ENTER_PRIVATE("config = %p, extra_config = %p and pipe = %p", config, extra_config, pipe); + + /* do not allow to create more than the maximum limit */ +- if (my_css.pipe_counter >= IA_CSS_PIPELINE_NUM_MAX) +- { ++ if (my_css.pipe_counter >= IA_CSS_PIPELINE_NUM_MAX) { + IA_CSS_LEAVE_ERR_PRIVATE(-ENOSPC); + return -EINVAL; + } + +- if ((!pipe) || (!config)) +- { ++ if ((!pipe) || (!config)) { + IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL); + return -EINVAL; + } +@@ -8742,8 +8647,7 @@ ia_css_pipe_create_extra(const struct ia + ia_css_debug_dump_pipe_extra_config(extra_config); + + err = create_pipe(config->mode, &internal_pipe, false); +- if (err) +- { ++ if (err) { + IA_CSS_LEAVE_ERR_PRIVATE(err); + return err; + } +@@ -8755,8 +8659,7 @@ ia_css_pipe_create_extra(const struct ia + else + ia_css_pipe_extra_config_defaults(&internal_pipe->extra_config); + +- if (config->mode == IA_CSS_PIPE_MODE_ACC) +- { ++ if (config->mode == IA_CSS_PIPE_MODE_ACC) { + /* Temporary hack to migrate acceleration to CSS 2.0. + * In the future the code for all pipe types should be + * unified. */ +@@ -8783,15 +8686,13 @@ ia_css_pipe_create_extra(const struct ia + set bayer_ds_out_res equal to IF output resolution(IF may do cropping on + sensor output) or use default decimation factor 1. */ + if (internal_pipe->extra_config.enable_raw_binning && +- internal_pipe->config.bayer_ds_out_res.width) +- { ++ internal_pipe->config.bayer_ds_out_res.width) { + /* fill some code here, if no code is needed, please remove it during integration */ + } + + /* YUV downscaling */ + if ((internal_pipe->config.vf_pp_in_res.width || +- internal_pipe->config.capt_pp_in_res.width)) +- { ++ internal_pipe->config.capt_pp_in_res.width)) { + enum ia_css_frame_format format; + + if (internal_pipe->config.vf_pp_in_res.width) { +@@ -8812,8 +8713,7 @@ ia_css_pipe_create_extra(const struct ia + } + } + if (internal_pipe->config.vf_pp_in_res.width && +- internal_pipe->config.mode == IA_CSS_PIPE_MODE_PREVIEW) +- { ++ internal_pipe->config.mode == IA_CSS_PIPE_MODE_PREVIEW) { + ia_css_frame_info_init( + &internal_pipe->vf_yuv_ds_input_info, + internal_pipe->config.vf_pp_in_res.width, +@@ -8821,8 +8721,7 @@ ia_css_pipe_create_extra(const struct ia + IA_CSS_FRAME_FORMAT_YUV_LINE, 0); + } + /* handle bayer downscaling output info */ +- if (internal_pipe->config.bayer_ds_out_res.width) +- { ++ if (internal_pipe->config.bayer_ds_out_res.width) { + ia_css_frame_info_init( + &internal_pipe->bds_output_info, + internal_pipe->config.bayer_ds_out_res.width, +@@ -8831,8 +8730,7 @@ ia_css_pipe_create_extra(const struct ia + } + + /* handle output info, assume always needed */ +- for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) +- { ++ for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) { + if (internal_pipe->config.output_info[i].res.width) { + err = sh_css_pipe_configure_output( + internal_pipe, +@@ -8868,8 +8766,7 @@ ia_css_pipe_create_extra(const struct ia + } + } + } +- if (internal_pipe->config.acc_extension) +- { ++ if (internal_pipe->config.acc_extension) { + err = ia_css_pipe_load_extension(internal_pipe, + internal_pipe->config.acc_extension); + if (err) { +@@ -8889,18 +8786,18 @@ ia_css_pipe_create_extra(const struct ia + + int + ia_css_pipe_get_info(const struct ia_css_pipe *pipe, +- struct ia_css_pipe_info *pipe_info) { ++ struct ia_css_pipe_info *pipe_info) ++{ + ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, + "ia_css_pipe_get_info()\n"); ++ + assert(pipe_info); +- if (!pipe_info) +- { ++ if (!pipe_info) { + ia_css_debug_dtrace(IA_CSS_DEBUG_ERROR, + "ia_css_pipe_get_info: pipe_info cannot be NULL\n"); + return -EINVAL; + } +- if (!pipe || !pipe->stream) +- { ++ if (!pipe || !pipe->stream) { + ia_css_debug_dtrace(IA_CSS_DEBUG_ERROR, + "ia_css_pipe_get_info: ia_css_stream_create needs to be called before ia_css_[stream/pipe]_get_info\n"); + return -EINVAL; +@@ -8928,40 +8825,36 @@ bool ia_css_pipe_has_dvs_stats(struct ia + int + ia_css_pipe_override_frame_format(struct ia_css_pipe *pipe, + int pin_index, +- enum ia_css_frame_format new_format) { ++ enum ia_css_frame_format new_format) ++{ + int err = 0; + + IA_CSS_ENTER_PRIVATE("pipe = %p, pin_index = %d, new_formats = %d", pipe, pin_index, new_format); + +- if (!pipe) +- { ++ if (!pipe) { + IA_CSS_ERROR("pipe is not set"); + err = -EINVAL; + IA_CSS_LEAVE_ERR_PRIVATE(err); + return err; + } +- if (0 != pin_index && 1 != pin_index) +- { ++ if (0 != pin_index && 1 != pin_index) { + IA_CSS_ERROR("pin index is not valid"); + err = -EINVAL; + IA_CSS_LEAVE_ERR_PRIVATE(err); + return err; + } +- if (new_format != IA_CSS_FRAME_FORMAT_NV12_TILEY) +- { ++ if (new_format != IA_CSS_FRAME_FORMAT_NV12_TILEY) { + IA_CSS_ERROR("new format is not valid"); + err = -EINVAL; + IA_CSS_LEAVE_ERR_PRIVATE(err); + return err; +- } else +- { ++ } else { + err = ia_css_pipe_check_format(pipe, new_format); + if (!err) { +- if (pin_index == 0) { ++ if (pin_index == 0) + pipe->output_info[0].format = new_format; +- } else { ++ else + pipe->vf_output_info[0].format = new_format; +- } + } + } + IA_CSS_LEAVE_ERR_PRIVATE(err); +@@ -8971,7 +8864,8 @@ ia_css_pipe_override_frame_format(struct + #if !defined(ISP2401) + /* Configuration of INPUT_SYSTEM_VERSION_2401 is done on SP */ + static int +-ia_css_stream_configure_rx(struct ia_css_stream *stream) { ++ia_css_stream_configure_rx(struct ia_css_stream *stream) ++{ + struct ia_css_input_port *config; + + assert(stream); +@@ -9000,11 +8894,10 @@ ia_css_stream_configure_rx(struct ia_css + if (config->compression.type == IA_CSS_CSI2_COMPRESSION_TYPE_NONE) + stream->csi_rx_config.comp = MIPI_PREDICTOR_NONE; + else +- { + /* not implemented yet, requires extension of the rx_cfg_t + * struct */ + return -EINVAL; +- } ++ + stream->csi_rx_config.is_two_ppc = (stream->config.pixels_per_clock == 2); + stream->reconfigure_css_rx = true; + return 0; +@@ -9015,7 +8908,8 @@ static struct ia_css_pipe * + find_pipe(struct ia_css_pipe *pipes[], + unsigned int num_pipes, + enum ia_css_pipe_mode mode, +- bool copy_pipe) { ++ bool copy_pipe) ++{ + unsigned int i; + + assert(pipes); +@@ -9031,21 +8925,20 @@ find_pipe(struct ia_css_pipe *pipes[], + } + + static int +-ia_css_acc_stream_create(struct ia_css_stream *stream) { ++ia_css_acc_stream_create(struct ia_css_stream *stream) ++{ + int i; + int err = 0; + + assert(stream); + IA_CSS_ENTER_PRIVATE("stream = %p", stream); + +- if (!stream) +- { ++ if (!stream) { + IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL); + return -EINVAL; + } + +- for (i = 0; i < stream->num_pipes; i++) +- { ++ for (i = 0; i < stream->num_pipes; i++) { + struct ia_css_pipe *pipe = stream->pipes[i]; + + assert(pipe); +@@ -9059,14 +8952,12 @@ ia_css_acc_stream_create(struct ia_css_s + + /* Map SP threads before doing anything. */ + err = map_sp_threads(stream, true); +- if (err) +- { ++ if (err) { + IA_CSS_LEAVE_ERR_PRIVATE(err); + return err; + } + +- for (i = 0; i < stream->num_pipes; i++) +- { ++ for (i = 0; i < stream->num_pipes; i++) { + struct ia_css_pipe *pipe = stream->pipes[i]; + + assert(pipe); +@@ -9074,8 +8965,7 @@ ia_css_acc_stream_create(struct ia_css_s + } + + err = create_host_pipeline_structure(stream); +- if (err) +- { ++ if (err) { + IA_CSS_LEAVE_ERR_PRIVATE(err); + return err; + } +@@ -9089,7 +8979,8 @@ ia_css_acc_stream_create(struct ia_css_s + + static int + metadata_info_init(const struct ia_css_metadata_config *mdc, +- struct ia_css_metadata_info *md) { ++ struct ia_css_metadata_info *md) ++{ + /* Either both width and height should be set or neither */ + if ((mdc->resolution.height > 0) ^ (mdc->resolution.width > 0)) + return -EINVAL; +@@ -9149,7 +9040,8 @@ int + ia_css_stream_create(const struct ia_css_stream_config *stream_config, + int num_pipes, + struct ia_css_pipe *pipes[], +- struct ia_css_stream **stream) { ++ struct ia_css_stream **stream) ++{ + struct ia_css_pipe *curr_pipe; + struct ia_css_stream *curr_stream = NULL; + bool spcopyonly; +@@ -9168,8 +9060,7 @@ ia_css_stream_create(const struct ia_css + /* some checks */ + if (num_pipes == 0 || + !stream || +- !pipes) +- { ++ !pipes) { + err = -EINVAL; + IA_CSS_LEAVE_ERR(err); + return err; +@@ -9178,8 +9069,7 @@ ia_css_stream_create(const struct ia_css + #if !defined(ISP2401) + /* We don't support metadata for JPEG stream, since they both use str2mem */ + if (stream_config->input_config.format == ATOMISP_INPUT_FORMAT_BINARY_8 && +- stream_config->metadata_config.resolution.height > 0) +- { ++ stream_config->metadata_config.resolution.height > 0) { + err = -EINVAL; + IA_CSS_LEAVE_ERR(err); + return err; +@@ -9187,8 +9077,7 @@ ia_css_stream_create(const struct ia_css + #endif + + #ifdef ISP2401 +- if (stream_config->online && stream_config->pack_raw_pixels) +- { ++ if (stream_config->online && stream_config->pack_raw_pixels) { + IA_CSS_LOG("online and pack raw is invalid on input system 2401"); + err = -EINVAL; + IA_CSS_LEAVE_ERR(err); +@@ -9243,16 +9132,14 @@ ia_css_stream_create(const struct ia_css + + /* Currently we only supported metadata up to a certain size. */ + err = metadata_info_init(&stream_config->metadata_config, &md_info); +- if (err) +- { ++ if (err) { + IA_CSS_LEAVE_ERR(err); + return err; + } + + /* allocate the stream instance */ + curr_stream = kzalloc(sizeof(struct ia_css_stream), GFP_KERNEL); +- if (!curr_stream) +- { ++ if (!curr_stream) { + err = -ENOMEM; + IA_CSS_LEAVE_ERR(err); + return err; +@@ -9263,8 +9150,7 @@ ia_css_stream_create(const struct ia_css + /* allocate pipes */ + curr_stream->num_pipes = num_pipes; + curr_stream->pipes = kcalloc(num_pipes, sizeof(struct ia_css_pipe *), GFP_KERNEL); +- if (!curr_stream->pipes) +- { ++ if (!curr_stream->pipes) { + curr_stream->num_pipes = 0; + kfree(curr_stream); + curr_stream = NULL; +@@ -9287,8 +9173,7 @@ ia_css_stream_create(const struct ia_css + #endif + + #ifdef ISP2401 +- if (curr_stream->config.online) +- { ++ if (curr_stream->config.online) { + curr_stream->config.source.port.num_lanes = + stream_config->source.port.num_lanes; + curr_stream->config.mode = IA_CSS_INPUT_MODE_BUFFERED_SENSOR; +@@ -9306,8 +9191,7 @@ ia_css_stream_create(const struct ia_css + curr_stream->config.lock_all); + + /* copy mode specific stuff */ +- switch (curr_stream->config.mode) +- { ++ switch (curr_stream->config.mode) { + case IA_CSS_INPUT_MODE_SENSOR: + case IA_CSS_INPUT_MODE_BUFFERED_SENSOR: + #if !defined(ISP2401) +@@ -9349,14 +9233,12 @@ ia_css_stream_create(const struct ia_css + err = aspect_ratio_crop_init(curr_stream, + pipes, + &aspect_ratio_crop_enabled); +- if (err) +- { ++ if (err) { + IA_CSS_LEAVE_ERR(err); + goto ERR; + } + #endif +- for (i = 0; i < num_pipes; i++) +- { ++ for (i = 0; i < num_pipes; i++) { + struct ia_css_resolution effective_res; + + curr_pipe = pipes[i]; +@@ -9396,9 +9278,8 @@ ia_css_stream_create(const struct ia_css + if (pipes[i]->config.mode != IA_CSS_PIPE_MODE_ACC && + pipes[i]->config.mode != IA_CSS_PIPE_MODE_COPY) { + err = check_pipe_resolutions(pipes[i]); +- if (err) { ++ if (err) + goto ERR; +- } + } + } + } +@@ -9408,20 +9289,17 @@ ia_css_stream_create(const struct ia_css + goto ERR; + IA_CSS_LOG("isp_params_configs: %p", curr_stream->isp_params_configs); + +- if (num_pipes == 1 && pipes[0]->config.mode == IA_CSS_PIPE_MODE_ACC) +- { ++ if (num_pipes == 1 && pipes[0]->config.mode == IA_CSS_PIPE_MODE_ACC) { + *stream = curr_stream; + err = ia_css_acc_stream_create(curr_stream); + goto ERR; + } + /* sensor binning */ +- if (!spcopyonly) +- { ++ if (!spcopyonly) { + sensor_binning_changed = + sh_css_params_set_binning_factor(curr_stream, + curr_stream->config.sensor_binning_factor); +- } else +- { ++ } else { + sensor_binning_changed = false; + } + +@@ -9432,8 +9310,7 @@ ia_css_stream_create(const struct ia_css + curr_stream->cont_capt = false; + /* Temporary hack: we give the preview pipe a reference to the capture + * pipe in continuous capture mode. */ +- if (curr_stream->config.continuous) +- { ++ if (curr_stream->config.continuous) { + /* Search for the preview pipe and create the copy pipe */ + struct ia_css_pipe *preview_pipe; + struct ia_css_pipe *video_pipe; +@@ -9481,9 +9358,9 @@ ia_css_stream_create(const struct ia_css + preview_pipe->pipe_settings.preview.copy_pipe = copy_pipe; + copy_pipe->stream = curr_stream; + } +- if (preview_pipe && curr_stream->cont_capt) { ++ if (preview_pipe && curr_stream->cont_capt) + preview_pipe->pipe_settings.preview.capture_pipe = capture_pipe; +- } ++ + if (video_pipe && !video_pipe->pipe_settings.video.copy_pipe) { + err = create_pipe(IA_CSS_PIPE_MODE_CAPTURE, ©_pipe, true); + if (err) +@@ -9492,15 +9369,13 @@ ia_css_stream_create(const struct ia_css + video_pipe->pipe_settings.video.copy_pipe = copy_pipe; + copy_pipe->stream = curr_stream; + } +- if (video_pipe && curr_stream->cont_capt) { ++ if (video_pipe && curr_stream->cont_capt) + video_pipe->pipe_settings.video.capture_pipe = capture_pipe; +- } +- if (preview_pipe && acc_pipe) { ++ ++ if (preview_pipe && acc_pipe) + preview_pipe->pipe_settings.preview.acc_pipe = acc_pipe; +- } + } +- for (i = 0; i < num_pipes; i++) +- { ++ for (i = 0; i < num_pipes; i++) { + curr_pipe = pipes[i]; + /* set current stream */ + curr_pipe->stream = curr_stream; +@@ -9521,8 +9396,7 @@ ia_css_stream_create(const struct ia_css + } + + /* now pipes have been configured, info should be available */ +- for (i = 0; i < num_pipes; i++) +- { ++ for (i = 0; i < num_pipes; i++) { + struct ia_css_pipe_info *pipe_info = NULL; + + curr_pipe = pipes[i]; +@@ -9572,22 +9446,19 @@ ia_css_stream_create(const struct ia_css + + /* Map SP threads before doing anything. */ + err = map_sp_threads(curr_stream, true); +- if (err) +- { ++ if (err) { + IA_CSS_LOG("map_sp_threads: return_err=%d", err); + goto ERR; + } + +- for (i = 0; i < num_pipes; i++) +- { ++ for (i = 0; i < num_pipes; i++) { + curr_pipe = pipes[i]; + ia_css_pipe_map_queue(curr_pipe, true); + } + + /* Create host side pipeline objects without stages */ + err = create_host_pipeline_structure(curr_stream); +- if (err) +- { ++ if (err) { + IA_CSS_LOG("create_host_pipeline_structure: return_err=%d", err); + goto ERR; + } +@@ -9625,13 +9496,13 @@ ERR: + } + + int +-ia_css_stream_destroy(struct ia_css_stream *stream) { ++ia_css_stream_destroy(struct ia_css_stream *stream) ++{ + int i; + int err = 0; + + IA_CSS_ENTER_PRIVATE("stream = %p", stream); +- if (!stream) +- { ++ if (!stream) { + err = -EINVAL; + IA_CSS_LEAVE_ERR_PRIVATE(err); + return err; +@@ -9640,8 +9511,7 @@ ia_css_stream_destroy(struct ia_css_stre + ia_css_stream_isp_parameters_uninit(stream); + + if ((stream->last_pipe) && +- ia_css_pipeline_is_mapped(stream->last_pipe->pipe_num)) +- { ++ ia_css_pipeline_is_mapped(stream->last_pipe->pipe_num)) { + #if defined(ISP2401) + bool free_mpi; + +@@ -9703,8 +9573,7 @@ ia_css_stream_destroy(struct ia_css_stre + } + + /* remove references from pipes to stream */ +- for (i = 0; i < stream->num_pipes; i++) +- { ++ for (i = 0; i < stream->num_pipes; i++) { + struct ia_css_pipe *entry = stream->pipes[i]; + + assert(entry); +@@ -9733,8 +9602,7 @@ ia_css_stream_destroy(struct ia_css_stre + /* working mode: take out of the seed list */ + if (my_css_save.mode == sh_css_mode_working) { + for (i = 0; i < MAX_ACTIVE_STREAMS; i++) { +- if (my_css_save.stream_seeds[i].stream == stream) +- { ++ if (my_css_save.stream_seeds[i].stream == stream) { + IA_CSS_LOG("took out stream %d", i); + my_css_save.stream_seeds[i].stream = NULL; + break; +@@ -9750,7 +9618,8 @@ ia_css_stream_destroy(struct ia_css_stre + + int + ia_css_stream_get_info(const struct ia_css_stream *stream, +- struct ia_css_stream_info *stream_info) { ++ struct ia_css_stream_info *stream_info) ++{ + ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_get_info: enter/exit\n"); + assert(stream); + assert(stream_info); +@@ -9766,15 +9635,15 @@ ia_css_stream_get_info(const struct ia_c + * The stream handle is used to identify the correct entry in the css_save struct + */ + int +-ia_css_stream_load(struct ia_css_stream *stream) { ++ia_css_stream_load(struct ia_css_stream *stream) ++{ + if (!IS_ISP2401) { + int i; + int err; + + assert(stream); + ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_load() enter,\n"); +- for (i = 0; i < MAX_ACTIVE_STREAMS; i++) +- { ++ for (i = 0; i < MAX_ACTIVE_STREAMS; i++) { + if (my_css_save.stream_seeds[i].stream == stream) { + int j; + +@@ -9813,12 +9682,12 @@ ia_css_stream_load(struct ia_css_stream + } + + int +-ia_css_stream_start(struct ia_css_stream *stream) { ++ia_css_stream_start(struct ia_css_stream *stream) ++{ + int err = 0; + + IA_CSS_ENTER("stream = %p", stream); +- if ((!stream) || (!stream->last_pipe)) +- { ++ if ((!stream) || (!stream->last_pipe)) { + IA_CSS_LEAVE_ERR(-EINVAL); + return -EINVAL; + } +@@ -9828,8 +9697,7 @@ ia_css_stream_start(struct ia_css_stream + + /* Create host side pipeline. */ + err = create_host_pipeline(stream); +- if (err) +- { ++ if (err) { + IA_CSS_LEAVE_ERR(err); + return err; + } +@@ -9842,8 +9710,7 @@ ia_css_stream_start(struct ia_css_stream + + #if !defined(ISP2401) + /* Initialize mipi size checks */ +- if (stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR) +- { ++ if (stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR) { + unsigned int idx; + unsigned int port = (unsigned int)(stream->config.source.port.port); + +@@ -9854,8 +9721,7 @@ ia_css_stream_start(struct ia_css_stream + } + #endif + +- if (stream->config.mode != IA_CSS_INPUT_MODE_MEMORY) +- { ++ if (stream->config.mode != IA_CSS_INPUT_MODE_MEMORY) { + err = sh_css_config_input_network(stream); + if (err) + return err; +@@ -9867,7 +9733,8 @@ ia_css_stream_start(struct ia_css_stream + } + + int +-ia_css_stream_stop(struct ia_css_stream *stream) { ++ia_css_stream_stop(struct ia_css_stream *stream) ++{ + int err = 0; + + ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_stop() enter/exit\n"); +@@ -9878,22 +9745,19 @@ ia_css_stream_stop(struct ia_css_stream + + #if !defined(ISP2401) + /* De-initialize mipi size checks */ +- if (stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR) +- { ++ if (stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR) { + unsigned int idx; + unsigned int port = (unsigned int)(stream->config.source.port.port); + +- for (idx = 0; idx < IA_CSS_MIPI_SIZE_CHECK_MAX_NOF_ENTRIES_PER_PORT; idx++) { ++ for (idx = 0; idx < IA_CSS_MIPI_SIZE_CHECK_MAX_NOF_ENTRIES_PER_PORT; idx++) + sh_css_sp_group.config.mipi_sizes_for_check[port][idx] = 0; +- } + } + #endif + +- if (!IS_ISP2401) { ++ if (!IS_ISP2401) + err = ia_css_pipeline_request_stop(&stream->last_pipe->pipeline); +- } else { ++ else + err = sh_css_pipes_stop(stream); +- } + + if (err) + return err; +@@ -9906,16 +9770,16 @@ ia_css_stream_stop(struct ia_css_stream + } + + bool +-ia_css_stream_has_stopped(struct ia_css_stream *stream) { ++ia_css_stream_has_stopped(struct ia_css_stream *stream) ++{ + bool stopped; + + assert(stream); + +- if (!IS_ISP2401) { ++ if (!IS_ISP2401) + stopped = ia_css_pipeline_has_stopped(&stream->last_pipe->pipeline); +- } else { ++ else + stopped = sh_css_pipes_have_stopped(stream); +- } + + return stopped; + } +@@ -9926,7 +9790,8 @@ ia_css_stream_has_stopped(struct ia_css_ + * The stream handle is used to identify the correct entry in the css_save struct + */ + int +-ia_css_stream_unload(struct ia_css_stream *stream) { ++ia_css_stream_unload(struct ia_css_stream *stream) ++{ + int i; + + assert(stream); +@@ -9934,8 +9799,7 @@ ia_css_stream_unload(struct ia_css_strea + /* some checks */ + assert(stream); + for (i = 0; i < MAX_ACTIVE_STREAMS; i++) +- if (my_css_save.stream_seeds[i].stream == stream) +- { ++ if (my_css_save.stream_seeds[i].stream == stream) { + int j; + + ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, +@@ -9955,7 +9819,8 @@ ia_css_stream_unload(struct ia_css_strea + + int + ia_css_temp_pipe_to_pipe_id(const struct ia_css_pipe *pipe, +- enum ia_css_pipe_id *pipe_id) { ++ enum ia_css_pipe_id *pipe_id) ++{ + ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_temp_pipe_to_pipe_id() enter/exit\n"); + if (pipe) + *pipe_id = pipe->mode; +@@ -9966,18 +9831,21 @@ ia_css_temp_pipe_to_pipe_id(const struct + } + + enum atomisp_input_format +-ia_css_stream_get_format(const struct ia_css_stream *stream) { ++ia_css_stream_get_format(const struct ia_css_stream *stream) ++{ + return stream->config.input_config.format; + } + + bool +-ia_css_stream_get_two_pixels_per_clock(const struct ia_css_stream *stream) { ++ia_css_stream_get_two_pixels_per_clock(const struct ia_css_stream *stream) ++{ + return (stream->config.pixels_per_clock == 2); + } + + struct ia_css_binary * + ia_css_stream_get_shading_correction_binary(const struct ia_css_stream +- *stream) { ++ *stream) ++{ + struct ia_css_pipe *pipe; + + assert(stream); +@@ -9995,7 +9863,8 @@ ia_css_stream_get_shading_correction_bin + } + + struct ia_css_binary * +-ia_css_stream_get_dvs_binary(const struct ia_css_stream *stream) { ++ia_css_stream_get_dvs_binary(const struct ia_css_stream *stream) ++{ + int i; + struct ia_css_pipe *video_pipe = NULL; + +@@ -10014,7 +9883,8 @@ ia_css_stream_get_dvs_binary(const struc + } + + struct ia_css_binary * +-ia_css_stream_get_3a_binary(const struct ia_css_stream *stream) { ++ia_css_stream_get_3a_binary(const struct ia_css_stream *stream) ++{ + struct ia_css_pipe *pipe; + struct ia_css_binary *s3a_binary = NULL; + +@@ -10036,7 +9906,8 @@ ia_css_stream_get_3a_binary(const struct + + int + ia_css_stream_set_output_padded_width(struct ia_css_stream *stream, +- unsigned int output_padded_width) { ++ unsigned int output_padded_width) ++{ + struct ia_css_pipe *pipe; + + assert(stream); +@@ -10053,7 +9924,8 @@ ia_css_stream_set_output_padded_width(st + } + + static struct ia_css_binary * +-ia_css_pipe_get_shading_correction_binary(const struct ia_css_pipe *pipe) { ++ia_css_pipe_get_shading_correction_binary(const struct ia_css_pipe *pipe) ++{ + struct ia_css_binary *binary = NULL; + + assert(pipe); +@@ -10098,7 +9970,8 @@ ia_css_pipe_get_shading_correction_binar + } + + static struct ia_css_binary * +-ia_css_pipe_get_s3a_binary(const struct ia_css_pipe *pipe) { ++ia_css_pipe_get_s3a_binary(const struct ia_css_pipe *pipe) ++{ + struct ia_css_binary *binary = NULL; + + assert(pipe); +@@ -10121,9 +9994,9 @@ ia_css_pipe_get_s3a_binary(const struct + } + } + } else if (pipe->config.default_capture_config.mode == +- IA_CSS_CAPTURE_MODE_BAYER) ++ IA_CSS_CAPTURE_MODE_BAYER) { + binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.pre_isp_binary; +- else if (pipe->config.default_capture_config.mode == ++ } else if (pipe->config.default_capture_config.mode == + IA_CSS_CAPTURE_MODE_ADVANCED || + pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_LOW_LIGHT) { + if (pipe->config.isp_pipe_version == IA_CSS_PIPE_VERSION_1) +@@ -10145,7 +10018,8 @@ ia_css_pipe_get_s3a_binary(const struct + } + + static struct ia_css_binary * +-ia_css_pipe_get_sdis_binary(const struct ia_css_pipe *pipe) { ++ia_css_pipe_get_sdis_binary(const struct ia_css_pipe *pipe) ++{ + struct ia_css_binary *binary = NULL; + + assert(pipe); +@@ -10165,14 +10039,16 @@ ia_css_pipe_get_sdis_binary(const struct + } + + struct ia_css_pipeline * +-ia_css_pipe_get_pipeline(const struct ia_css_pipe *pipe) { ++ia_css_pipe_get_pipeline(const struct ia_css_pipe *pipe) ++{ + assert(pipe); + + return (struct ia_css_pipeline *)&pipe->pipeline; + } + + unsigned int +-ia_css_pipe_get_pipe_num(const struct ia_css_pipe *pipe) { ++ia_css_pipe_get_pipe_num(const struct ia_css_pipe *pipe) ++{ + assert(pipe); + + /* KW was not sure this function was not returning a value +@@ -10189,7 +10065,8 @@ ia_css_pipe_get_pipe_num(const struct ia + } + + unsigned int +-ia_css_pipe_get_isp_pipe_version(const struct ia_css_pipe *pipe) { ++ia_css_pipe_get_isp_pipe_version(const struct ia_css_pipe *pipe) ++{ + assert(pipe); + + return (unsigned int)pipe->config.isp_pipe_version; +@@ -10198,7 +10075,8 @@ ia_css_pipe_get_isp_pipe_version(const s + #define SP_START_TIMEOUT_US 30000000 + + int +-ia_css_start_sp(void) { ++ia_css_start_sp(void) ++{ + unsigned long timeout; + int err = 0; + +@@ -10207,13 +10085,11 @@ ia_css_start_sp(void) { + + /* waiting for the SP is completely started */ + timeout = SP_START_TIMEOUT_US; +- while ((ia_css_spctrl_get_state(SP0_ID) != IA_CSS_SP_SW_INITIALIZED) && timeout) +- { ++ while ((ia_css_spctrl_get_state(SP0_ID) != IA_CSS_SP_SW_INITIALIZED) && timeout) { + timeout--; + udelay(1); + } +- if (timeout == 0) +- { ++ if (timeout == 0) { + IA_CSS_ERROR("timeout during SP initialization"); + return -EINVAL; + } +@@ -10241,14 +10117,14 @@ ia_css_start_sp(void) { + #define SP_SHUTDOWN_TIMEOUT_US 200000 + + int +-ia_css_stop_sp(void) { ++ia_css_stop_sp(void) ++{ + unsigned long timeout; + int err = 0; + + IA_CSS_ENTER("void"); + +- if (!sh_css_sp_is_running()) +- { ++ if (!sh_css_sp_is_running()) { + err = -EINVAL; + IA_CSS_LEAVE("SP already stopped : return_err=%d", err); + +@@ -10260,8 +10136,7 @@ ia_css_stop_sp(void) { + if (!IS_ISP2401) { + sh_css_write_host2sp_command(host2sp_cmd_terminate); + } else { +- if (!sh_css_write_host2sp_command(host2sp_cmd_terminate)) +- { ++ if (!sh_css_write_host2sp_command(host2sp_cmd_terminate)) { + IA_CSS_ERROR("Call to 'sh-css_write_host2sp_command()' failed"); + ia_css_debug_dump_sp_sw_debug_info(); + ia_css_debug_dump_debug_info(NULL); +@@ -10271,27 +10146,23 @@ ia_css_stop_sp(void) { + sh_css_sp_set_sp_running(false); + + timeout = SP_SHUTDOWN_TIMEOUT_US; +- while (!ia_css_spctrl_is_idle(SP0_ID) && timeout) +- { ++ while (!ia_css_spctrl_is_idle(SP0_ID) && timeout) { + timeout--; + udelay(1); + } + if ((ia_css_spctrl_get_state(SP0_ID) != IA_CSS_SP_SW_TERMINATED)) + IA_CSS_WARNING("SP has not terminated (SW)"); + +- if (timeout == 0) +- { ++ if (timeout == 0) { + IA_CSS_WARNING("SP is not idle"); + ia_css_debug_dump_sp_sw_debug_info(); + } + timeout = SP_SHUTDOWN_TIMEOUT_US; +- while (!isp_ctrl_getbit(ISP0_ID, ISP_SC_REG, ISP_IDLE_BIT) && timeout) +- { ++ while (!isp_ctrl_getbit(ISP0_ID, ISP_SC_REG, ISP_IDLE_BIT) && timeout) { + timeout--; + udelay(1); + } +- if (timeout == 0) +- { ++ if (timeout == 0) { + IA_CSS_WARNING("ISP is not idle"); + ia_css_debug_dump_sp_sw_debug_info(); + } +@@ -10306,7 +10177,8 @@ ia_css_stop_sp(void) { + } + + int +-ia_css_update_continuous_frames(struct ia_css_stream *stream) { ++ia_css_update_continuous_frames(struct ia_css_stream *stream) ++{ + struct ia_css_pipe *pipe; + unsigned int i; + +@@ -10314,8 +10186,7 @@ ia_css_update_continuous_frames(struct i + IA_CSS_DEBUG_TRACE, + "sh_css_update_continuous_frames() enter:\n"); + +- if (!stream) +- { ++ if (!stream) { + ia_css_debug_dtrace( + IA_CSS_DEBUG_TRACE, + "sh_css_update_continuous_frames() leave: invalid stream, return_void\n"); +@@ -10326,10 +10197,9 @@ ia_css_update_continuous_frames(struct i + + for (i = stream->config.init_num_cont_raw_buf; + i < stream->config.target_num_cont_raw_buf; i++) +- { + sh_css_update_host2sp_offline_frame(i, + pipe->continuous_frames[i], pipe->cont_md_buffers[i]); +- } ++ + sh_css_update_host2sp_cont_num_raw_frames + (stream->config.target_num_cont_raw_buf, true); + ia_css_debug_dtrace( +@@ -10455,7 +10325,8 @@ void ia_css_pipe_map_queue(struct ia_css + + #if CONFIG_ON_FRAME_ENQUEUE() + static int set_config_on_frame_enqueue(struct ia_css_frame_info +- *info, struct frame_data_wrapper *frame) { ++ *info, struct frame_data_wrapper *frame) ++{ + frame->config_on_frame_enqueue.padded_width = 0; + + /* currently we support configuration on frame enqueue only on YUV formats */ +@@ -10463,11 +10334,11 @@ static int set_config_on_frame_enqueue(s + switch (info->format) { + case IA_CSS_FRAME_FORMAT_YUV420: + case IA_CSS_FRAME_FORMAT_NV12: +- if (info->padded_width > info->res.width) { ++ if (info->padded_width > info->res.width) + frame->config_on_frame_enqueue.padded_width = info->padded_width; +- } else if ((info->padded_width < info->res.width) && (info->padded_width > 0)) { ++ else if ((info->padded_width < info->res.width) && (info->padded_width > 0)) + return -EINVAL; +- } ++ + /* nothing to do if width == padded width or padded width is zeroed (the same) */ + break; + default: +@@ -10479,22 +10350,21 @@ static int set_config_on_frame_enqueue(s + #endif + + int +-ia_css_unlock_raw_frame(struct ia_css_stream *stream, uint32_t exp_id) { ++ia_css_unlock_raw_frame(struct ia_css_stream *stream, uint32_t exp_id) ++{ + int ret; + + IA_CSS_ENTER(""); + + /* Only continuous streams have a tagger to which we can send the + * unlock message. */ +- if (!stream || !stream->config.continuous) +- { ++ if (!stream || !stream->config.continuous) { + IA_CSS_ERROR("invalid stream pointer"); + return -EINVAL; + } + + if (exp_id > IA_CSS_ISYS_MAX_EXPOSURE_ID || +- exp_id < IA_CSS_ISYS_MIN_EXPOSURE_ID) +- { ++ exp_id < IA_CSS_ISYS_MIN_EXPOSURE_ID) { + IA_CSS_ERROR("invalid exposure ID: %d\n", exp_id); + return -EINVAL; + } +@@ -10513,7 +10383,8 @@ ia_css_unlock_raw_frame(struct ia_css_st + */ + int + ia_css_pipe_set_qos_ext_state(struct ia_css_pipe *pipe, uint32_t fw_handle, +- bool enable) { ++ bool enable) ++{ + unsigned int thread_id; + struct ia_css_pipeline_stage *stage; + int err = 0; +@@ -10521,20 +10392,16 @@ ia_css_pipe_set_qos_ext_state(struct ia_ + IA_CSS_ENTER(""); + + /* Parameter Check */ +- if (!pipe || !pipe->stream) +- { ++ if (!pipe || !pipe->stream) { + IA_CSS_ERROR("Invalid Pipe."); + err = -EINVAL; +- } else if (!(pipe->config.acc_extension)) +- { ++ } else if (!(pipe->config.acc_extension)) { + IA_CSS_ERROR("Invalid Pipe(No Extension Firmware)"); + err = -EINVAL; +- } else if (!sh_css_sp_is_running()) +- { ++ } else if (!sh_css_sp_is_running()) { + IA_CSS_ERROR("Leaving: queue unavailable."); + err = -EBUSY; +- } else +- { ++ } else { + /* Query the threadid and stage_num for the Extension firmware*/ + ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id); + err = ia_css_pipeline_get_stage_from_fw(&pipe->pipeline, fw_handle, &stage); +@@ -10562,7 +10429,8 @@ ia_css_pipe_set_qos_ext_state(struct ia_ + */ + int + ia_css_pipe_get_qos_ext_state(struct ia_css_pipe *pipe, uint32_t fw_handle, +- bool *enable) { ++ bool *enable) ++{ + struct ia_css_pipeline_stage *stage; + unsigned int thread_id; + int err = 0; +@@ -10570,20 +10438,16 @@ ia_css_pipe_get_qos_ext_state(struct ia_ + IA_CSS_ENTER(""); + + /* Parameter Check */ +- if (!pipe || !pipe->stream) +- { ++ if (!pipe || !pipe->stream) { + IA_CSS_ERROR("Invalid Pipe."); + err = -EINVAL; +- } else if (!(pipe->config.acc_extension)) +- { ++ } else if (!(pipe->config.acc_extension)) { + IA_CSS_ERROR("Invalid Pipe (No Extension Firmware)."); + err = -EINVAL; +- } else if (!sh_css_sp_is_running()) +- { ++ } else if (!sh_css_sp_is_running()) { + IA_CSS_ERROR("Leaving: queue unavailable."); + err = -EBUSY; +- } else +- { ++ } else { + /* Query the threadid and stage_num corresponding to the Extension firmware*/ + ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id); + err = ia_css_pipeline_get_stage_from_fw(&pipe->pipeline, fw_handle, &stage); +@@ -10603,7 +10467,8 @@ int + ia_css_pipe_update_qos_ext_mapped_arg(struct ia_css_pipe *pipe, + u32 fw_handle, + struct ia_css_isp_param_css_segments *css_seg, +- struct ia_css_isp_param_isp_segments *isp_seg) { ++ struct ia_css_isp_param_isp_segments *isp_seg) ++{ + unsigned int HIVE_ADDR_sp_group; + static struct sh_css_sp_group sp_group; + static struct sh_css_sp_stage sp_stage; +@@ -10621,20 +10486,16 @@ ia_css_pipe_update_qos_ext_mapped_arg(st + fw = &sh_css_sp_fw; + + /* Parameter Check */ +- if (!pipe || !pipe->stream) +- { ++ if (!pipe || !pipe->stream) { + IA_CSS_ERROR("Invalid Pipe."); + err = -EINVAL; +- } else if (!(pipe->config.acc_extension)) +- { ++ } else if (!(pipe->config.acc_extension)) { + IA_CSS_ERROR("Invalid Pipe (No Extension Firmware)."); + err = -EINVAL; +- } else if (!sh_css_sp_is_running()) +- { ++ } else if (!sh_css_sp_is_running()) { + IA_CSS_ERROR("Leaving: queue unavailable."); + err = -EBUSY; +- } else +- { ++ } else { + /* Query the thread_id and stage_num corresponding to the Extension firmware */ + ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id); + err = ia_css_pipeline_get_stage_from_fw(&pipe->pipeline, fw_handle, &stage); +@@ -10685,7 +10546,8 @@ ia_css_pipe_update_qos_ext_mapped_arg(st + static int + aspect_ratio_crop_init(struct ia_css_stream *curr_stream, + struct ia_css_pipe *pipes[], +- bool *do_crop_status) { ++ bool *do_crop_status) ++{ + int err = 0; + int i; + struct ia_css_pipe *curr_pipe; +@@ -10694,15 +10556,13 @@ aspect_ratio_crop_init(struct ia_css_str + if ((!curr_stream) || + (curr_stream->num_pipes == 0) || + (!pipes) || +- (!do_crop_status)) +- { ++ (!do_crop_status)) { + err = -EINVAL; + IA_CSS_LEAVE_ERR(err); + return err; + } + +- for (i = 0; i < curr_stream->num_pipes; i++) +- { ++ for (i = 0; i < curr_stream->num_pipes; i++) { + curr_pipe = pipes[i]; + pipe_mask |= (1 << curr_pipe->config.mode); + } +@@ -10716,7 +10576,8 @@ aspect_ratio_crop_init(struct ia_css_str + } + + static bool +-aspect_ratio_crop_check(bool enabled, struct ia_css_pipe *curr_pipe) { ++aspect_ratio_crop_check(bool enabled, struct ia_css_pipe *curr_pipe) ++{ + bool status = false; + + if ((curr_pipe) && enabled) { +@@ -10731,7 +10592,8 @@ aspect_ratio_crop_check(bool enabled, st + + static int + aspect_ratio_crop(struct ia_css_pipe *curr_pipe, +- struct ia_css_resolution *effective_res) { ++ struct ia_css_resolution *effective_res) ++{ + int err = 0; + struct ia_css_resolution crop_res; + struct ia_css_resolution *in_res = NULL; +@@ -10741,8 +10603,7 @@ aspect_ratio_crop(struct ia_css_pipe *cu + bool use_capt_pp_in_res = false; + + if ((!curr_pipe) || +- (!effective_res)) +- { ++ (!effective_res)) { + err = -EINVAL; + IA_CSS_LEAVE_ERR(err); + return err; +@@ -10750,8 +10611,7 @@ aspect_ratio_crop(struct ia_css_pipe *cu + + if ((curr_pipe->config.mode != IA_CSS_PIPE_MODE_PREVIEW) && + (curr_pipe->config.mode != IA_CSS_PIPE_MODE_VIDEO) && +- (curr_pipe->config.mode != IA_CSS_PIPE_MODE_CAPTURE)) +- { ++ (curr_pipe->config.mode != IA_CSS_PIPE_MODE_CAPTURE)) { + err = -EINVAL; + IA_CSS_LEAVE_ERR(err); + return err; +@@ -10772,8 +10632,7 @@ aspect_ratio_crop(struct ia_css_pipe *cu + in_res = &curr_pipe->stream->config.input_config.effective_res; + out_res = &curr_pipe->output_info[0].res; + +- switch (curr_pipe->config.mode) +- { ++ switch (curr_pipe->config.mode) { + case IA_CSS_PIPE_MODE_PREVIEW: + if (use_bds_output_info) + out_res = &curr_pipe->bds_output_info.res; +@@ -10800,20 +10659,19 @@ aspect_ratio_crop(struct ia_css_pipe *cu + + err = ia_css_frame_find_crop_resolution(in_res, out_res, &crop_res); + if (!err) +- { + *effective_res = crop_res; +- } else +- { ++ else + /* in case of error fallback to default + * effective resolution from driver. */ + IA_CSS_LOG("ia_css_frame_find_crop_resolution() failed with err(%d)", err); +- } ++ + return err; + } + #endif + + static void +-sh_css_hmm_buffer_record_init(void) { ++sh_css_hmm_buffer_record_init(void) ++{ + int i; + + for (i = 0; i < MAX_HMM_BUFFER_NUM; i++) +@@ -10821,7 +10679,8 @@ sh_css_hmm_buffer_record_init(void) { + } + + static void +-sh_css_hmm_buffer_record_uninit(void) { ++sh_css_hmm_buffer_record_uninit(void) ++{ + int i; + struct sh_css_hmm_buffer_record *buffer_record = NULL; + +@@ -10837,7 +10696,8 @@ sh_css_hmm_buffer_record_uninit(void) { + } + + static void +-sh_css_hmm_buffer_record_reset(struct sh_css_hmm_buffer_record *buffer_record) { ++sh_css_hmm_buffer_record_reset(struct sh_css_hmm_buffer_record *buffer_record) ++{ + assert(buffer_record); + buffer_record->in_use = false; + buffer_record->type = IA_CSS_BUFFER_TYPE_INVALID; +@@ -10848,7 +10708,8 @@ sh_css_hmm_buffer_record_reset(struct sh + static struct sh_css_hmm_buffer_record + *sh_css_hmm_buffer_record_acquire(struct ia_css_rmgr_vbuf_handle *h_vbuf, + enum ia_css_buffer_type type, +- hrt_address kernel_ptr) { ++ hrt_address kernel_ptr) ++{ + int i; + struct sh_css_hmm_buffer_record *buffer_record = NULL; + struct sh_css_hmm_buffer_record *out_buffer_record = NULL; +@@ -10876,7 +10737,8 @@ static struct sh_css_hmm_buffer_record + + static struct sh_css_hmm_buffer_record + *sh_css_hmm_buffer_record_validate(ia_css_ptr ddr_buffer_addr, +- enum ia_css_buffer_type type) { ++ enum ia_css_buffer_type type) ++{ + int i; + struct sh_css_hmm_buffer_record *buffer_record = NULL; + bool found_record = false; diff --git a/queue-5.10/media-staging-media-atomisp-replace-if-else-clause-with-a-ternary.patch b/queue-5.10/media-staging-media-atomisp-replace-if-else-clause-with-a-ternary.patch new file mode 100644 index 0000000000..1e61c08a8b --- /dev/null +++ b/queue-5.10/media-staging-media-atomisp-replace-if-else-clause-with-a-ternary.patch @@ -0,0 +1,41 @@ +From stable+bounces-274528-greg=kroah.com@vger.kernel.org Tue Jul 14 22:02:18 2026 +From: Sasha Levin +Date: Tue, 14 Jul 2026 16:01:56 -0400 +Subject: media: staging: media: atomisp: Replace if else clause with a ternary +To: stable@vger.kernel.org +Cc: Martiros Shakhzadyan , Hans Verkuil , Mauro Carvalho Chehab , Sasha Levin +Message-ID: <20260714200158.3152137-4-sashal@kernel.org> + +From: Martiros Shakhzadyan + +[ Upstream commit d4bc34d18201120b247506b4a6ed17af694dfcf7 ] + +Use the ternary operator for conditional variable assignment in +create_host_video_pipeline(). + +Signed-off-by: Martiros Shakhzadyan +Signed-off-by: Hans Verkuil +Signed-off-by: Mauro Carvalho Chehab +Stable-dep-of: f4d51e55dd47 ("staging: media: atomisp: reduce load_primary_binaries() stack usage") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/staging/media/atomisp/pci/sh_css.c | 7 ++----- + 1 file changed, 2 insertions(+), 5 deletions(-) + +--- a/drivers/staging/media/atomisp/pci/sh_css.c ++++ b/drivers/staging/media/atomisp/pci/sh_css.c +@@ -3623,11 +3623,8 @@ static int create_host_video_pipeline(st + struct ia_css_frame *tmp_out_frame = NULL; + + for (i = 0; i < num_yuv_scaler; i++) { +- if (is_output_stage[i]) { +- tmp_out_frame = out_frame; +- } else { +- tmp_out_frame = NULL; +- } ++ tmp_out_frame = is_output_stage[i] ? out_frame : NULL; ++ + err = add_yuv_scaler_stage(pipe, me, tmp_in_frame, tmp_out_frame, + NULL, + &yuv_scaler_binary[i], diff --git a/queue-5.10/netfilter-ebtables-use-vmalloc_array-to-improve-code.patch b/queue-5.10/netfilter-ebtables-use-vmalloc_array-to-improve-code.patch new file mode 100644 index 0000000000..fad98f0fbb --- /dev/null +++ b/queue-5.10/netfilter-ebtables-use-vmalloc_array-to-improve-code.patch @@ -0,0 +1,77 @@ +From stable+bounces-275063-greg=kroah.com@vger.kernel.org Wed Jul 15 23:32:06 2026 +From: Sasha Levin +Date: Wed, 15 Jul 2026 17:31:45 -0400 +Subject: netfilter: ebtables: Use vmalloc_array() to improve code +To: stable@vger.kernel.org +Cc: Qianfeng Rong , Florian Westphal , Sasha Levin +Message-ID: <20260715213146.296837-1-sashal@kernel.org> + +From: Qianfeng Rong + +[ Upstream commit 46015e6b3ea75297b28d4806564f3f692cf11861 ] + +Remove array_size() calls and replace vmalloc() with vmalloc_array() to +simplify the code. vmalloc_array() is also optimized better, uses fewer +instructions, and handles overflow more concisely[1]. + +[1]: https://lore.kernel.org/lkml/abc66ec5-85a4-47e1-9759-2f60ab111971@vivo.com/ +Signed-off-by: Qianfeng Rong +Signed-off-by: Florian Westphal +Stable-dep-of: cbfe53599eeb ("netfilter: ebtables: zero chainstack array") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + net/bridge/netfilter/ebtables.c | 14 +++++++------- + 1 file changed, 7 insertions(+), 7 deletions(-) + +--- a/net/bridge/netfilter/ebtables.c ++++ b/net/bridge/netfilter/ebtables.c +@@ -884,8 +884,8 @@ static int translate_table(struct net *n + * if an error occurs + */ + newinfo->chainstack = +- vmalloc(array_size(nr_cpu_ids, +- sizeof(*(newinfo->chainstack)))); ++ vmalloc_array(nr_cpu_ids, ++ sizeof(*(newinfo->chainstack))); + if (!newinfo->chainstack) + return -ENOMEM; + for_each_possible_cpu(i) { +@@ -900,7 +900,7 @@ static int translate_table(struct net *n + } + } + +- cl_s = vmalloc(array_size(udc_cnt, sizeof(*cl_s))); ++ cl_s = vmalloc_array(udc_cnt, sizeof(*cl_s)); + if (!cl_s) + return -ENOMEM; + i = 0; /* the i'th udc */ +@@ -980,8 +980,8 @@ static int do_replace_finish(struct net + * the check on the size is done later, when we have the lock + */ + if (repl->num_counters) { +- unsigned long size = repl->num_counters * sizeof(*counterstmp); +- counterstmp = vmalloc(size); ++ counterstmp = vmalloc_array(repl->num_counters, ++ sizeof(*counterstmp)); + if (!counterstmp) + return -ENOMEM; + } +@@ -1276,7 +1276,7 @@ static int do_update_counters(struct net + if (num_counters == 0) + return -EINVAL; + +- tmp = vmalloc(array_size(num_counters, sizeof(*tmp))); ++ tmp = vmalloc_array(num_counters, sizeof(*tmp)); + if (!tmp) + return -ENOMEM; + +@@ -1417,7 +1417,7 @@ static int copy_counters_to_user(struct + if (num_counters != nentries) + return -EINVAL; + +- counterstmp = vmalloc(array_size(nentries, sizeof(*counterstmp))); ++ counterstmp = vmalloc_array(nentries, sizeof(*counterstmp)); + if (!counterstmp) + return -ENOMEM; + diff --git a/queue-5.10/netfilter-ebtables-zero-chainstack-array.patch b/queue-5.10/netfilter-ebtables-zero-chainstack-array.patch new file mode 100644 index 0000000000..0b105fc36a --- /dev/null +++ b/queue-5.10/netfilter-ebtables-zero-chainstack-array.patch @@ -0,0 +1,46 @@ +From stable+bounces-275064-greg=kroah.com@vger.kernel.org Wed Jul 15 23:32:11 2026 +From: Sasha Levin +Date: Wed, 15 Jul 2026 17:31:46 -0400 +Subject: netfilter: ebtables: zero chainstack array +To: stable@vger.kernel.org +Cc: Florian Westphal , Sasha Levin +Message-ID: <20260715213146.296837-2-sashal@kernel.org> + +From: Florian Westphal + +[ Upstream commit cbfe53599eebffd188938ab6774cc41794f6f9d5 ] + +sashiko reports: + looking at ebtables table + translation, could a sparse cpu_possible_mask lead to an uninitialized pointer + free? + + If cpu_possible_mask is sparse (for example, CPU 0 and CPU 2 are possible, + but CPU 1 is not), the allocation loop skips CPU 1. If vmalloc_node() fails at + CPU 2, the cleanup loop will blindly decrement and call vfree() on + newinfo->chainstack[1]. + +Not a real-world bug, such allocation isn't expected to fail +in the first place. + +Cc: stable@vger.kernel.org +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Florian Westphal +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + net/bridge/netfilter/ebtables.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +--- a/net/bridge/netfilter/ebtables.c ++++ b/net/bridge/netfilter/ebtables.c +@@ -884,8 +884,7 @@ static int translate_table(struct net *n + * if an error occurs + */ + newinfo->chainstack = +- vmalloc_array(nr_cpu_ids, +- sizeof(*(newinfo->chainstack))); ++ vcalloc(nr_cpu_ids, sizeof(*(newinfo->chainstack))); + if (!newinfo->chainstack) + return -ENOMEM; + for_each_possible_cpu(i) { diff --git a/queue-5.10/pci-add-kerneldoc-for-pci_resize_resource.patch b/queue-5.10/pci-add-kerneldoc-for-pci_resize_resource.patch new file mode 100644 index 0000000000..3ddcee7b75 --- /dev/null +++ b/queue-5.10/pci-add-kerneldoc-for-pci_resize_resource.patch @@ -0,0 +1,55 @@ +From stable+bounces-274990-greg=kroah.com@vger.kernel.org Wed Jul 15 18:37:12 2026 +From: Sasha Levin +Date: Wed, 15 Jul 2026 12:32:21 -0400 +Subject: PCI: Add kerneldoc for pci_resize_resource() +To: stable@vger.kernel.org +Cc: "Ilpo Järvinen" , "Bjorn Helgaas" , "Alex Bennée" , "Sasha Levin" +Message-ID: <20260715163223.952417-4-sashal@kernel.org> + +From: Ilpo Järvinen + +[ Upstream commit d787018e2dfdc4c1331538e7a8717690d1b7c9b3 ] + +As pci_resize_resource() is meant to be used also outside of PCI core, +document the interface with kerneldoc. + +Signed-off-by: Ilpo Järvinen +Signed-off-by: Bjorn Helgaas +Tested-by: Alex Bennée # AVA, AMD GPU +Link: https://patch.msgid.link/20251113162628.5946-8-ilpo.jarvinen@linux.intel.com +Stable-dep-of: ee7471fe968d ("PCI: Skip Resizable BAR restore on read error") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/pci/setup-res.c | 20 ++++++++++++++++++++ + 1 file changed, 20 insertions(+) + +--- a/drivers/pci/setup-res.c ++++ b/drivers/pci/setup-res.c +@@ -422,6 +422,26 @@ void pci_release_resource(struct pci_dev + } + EXPORT_SYMBOL(pci_release_resource); + ++/** ++ * pci_resize_resource - reconfigure a Resizable BAR and resources ++ * @dev: the PCI device ++ * @resno: index of the BAR to be resized ++ * @size: new size as defined in the spec (0=1MB, 31=128TB) ++ * @exclude_bars: a mask of BARs that should not be released ++ * ++ * Reconfigure @resno to @size and re-run resource assignment algorithm ++ * with the new size. ++ * ++ * Prior to resize, release @dev resources that share a bridge window with ++ * @resno. This unpins the bridge window resource to allow changing it. ++ * ++ * The caller may prevent releasing a particular BAR by providing ++ * @exclude_bars mask, but this may result in the resize operation failing ++ * due to insufficient space. ++ * ++ * Return: 0 on success, or negative on error. In case of an error, the ++ * resources are restored to their original places. ++ */ + int pci_resize_resource(struct pci_dev *dev, int resno, int size, + int exclude_bars) + { diff --git a/queue-5.10/pci-altera-fix-resource-leaks-on-probe-failure.patch b/queue-5.10/pci-altera-fix-resource-leaks-on-probe-failure.patch new file mode 100644 index 0000000000..6e9163f089 --- /dev/null +++ b/queue-5.10/pci-altera-fix-resource-leaks-on-probe-failure.patch @@ -0,0 +1,99 @@ +From stable+bounces-274492-greg=kroah.com@vger.kernel.org Tue Jul 14 19:50:57 2026 +From: Sasha Levin +Date: Tue, 14 Jul 2026 13:49:16 -0400 +Subject: PCI: altera: Fix resource leaks on probe failure +To: stable@vger.kernel.org +Cc: Mahesh Vaidya , Manivannan Sadhasivam , "Subhransu S. Prusty" , Sasha Levin +Message-ID: <20260714174916.3041625-1-sashal@kernel.org> + +From: Mahesh Vaidya + +[ Upstream commit 7a94138caeb27f3c49c1dbd93bf422098925bb28 ] + +The chained IRQ handler is set during probe, but is only removed during the +driver remove(). If pci_host_probe() fails, the handler and INTx IRQ +domain remain set even though the devm-managed host bridge storage +containing struct altera_pcie will be released, leaving the handler with +a stale data pointer. + +Interrupts are also enabled before pci_host_probe() is called. If probe +fails after that point, the controller interrupt source should be disabled +before the chained handler and INTx domain are removed. + +So set the chained handler only after the INTx domain has been created. +Disable controller interrupts during IRQ teardown, and tear the IRQ setup +down if pci_host_probe() fails. + +Fixes: c63aed7334c2 ("PCI: altera: Use pci_host_probe() to register host") +Signed-off-by: Mahesh Vaidya +[mani: commit log] +Signed-off-by: Manivannan Sadhasivam +Reviewed-by: Subhransu S. Prusty +Cc: stable@vger.kernel.org +Link: https://patch.msgid.link/20260430204330.3121003-3-mahesh.vaidya@altera.com +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/pci/controller/pcie-altera.c | 28 ++++++++++++++++++++++++++-- + 1 file changed, 26 insertions(+), 2 deletions(-) + +--- a/drivers/pci/controller/pcie-altera.c ++++ b/drivers/pci/controller/pcie-altera.c +@@ -685,8 +685,18 @@ static int altera_pcie_init_irq_domain(s + return 0; + } + ++static void altera_pcie_disable_irq(struct altera_pcie *pcie) ++{ ++ if (pcie->pcie_data->version == ALTERA_PCIE_V1 || ++ pcie->pcie_data->version == ALTERA_PCIE_V2) { ++ /* Disable all P2A interrupts */ ++ cra_writel(pcie, 0, P2A_INT_ENABLE); ++ } ++} ++ + static void altera_pcie_irq_teardown(struct altera_pcie *pcie) + { ++ altera_pcie_disable_irq(pcie); + irq_set_chained_handler_and_data(pcie->irq, NULL, NULL); + irq_domain_remove(pcie->irq_domain); + } +@@ -711,7 +721,6 @@ static int altera_pcie_parse_dt(struct a + if (pcie->irq < 0) + return pcie->irq; + +- irq_set_chained_handler_and_data(pcie->irq, altera_pcie_isr, pcie); + return 0; + } + +@@ -796,6 +805,12 @@ static int altera_pcie_probe(struct plat + return ret; + } + ++ /* ++ * The chained handler uses pcie->irq_domain, so set it only after the ++ * INTx domain has been created. ++ */ ++ irq_set_chained_handler_and_data(pcie->irq, altera_pcie_isr, pcie); ++ + /* clear all interrupts */ + cra_writel(pcie, P2A_INT_STS_ALL, P2A_INT_STATUS); + /* enable all interrupts */ +@@ -806,7 +821,16 @@ static int altera_pcie_probe(struct plat + bridge->busnr = pcie->root_bus_nr; + bridge->ops = &altera_pcie_ops; + +- return pci_host_probe(bridge); ++ ret = pci_host_probe(bridge); ++ if (ret) ++ goto err_teardown_irq; ++ ++ return 0; ++ ++err_teardown_irq: ++ altera_pcie_irq_teardown(pcie); ++ ++ return ret; + } + + static int altera_pcie_remove(struct platform_device *pdev) diff --git a/queue-5.10/pci-controller-use-dev_fwnode-instead-of-of_fwnode_handle.patch b/queue-5.10/pci-controller-use-dev_fwnode-instead-of-of_fwnode_handle.patch new file mode 100644 index 0000000000..b1a84b00da --- /dev/null +++ b/queue-5.10/pci-controller-use-dev_fwnode-instead-of-of_fwnode_handle.patch @@ -0,0 +1,130 @@ +From stable+bounces-274659-greg=kroah.com@vger.kernel.org Wed Jul 15 03:23:01 2026 +From: Sasha Levin +Date: Tue, 14 Jul 2026 21:22:53 -0400 +Subject: PCI: controller: Use dev_fwnode() instead of of_fwnode_handle() +To: stable@vger.kernel.org +Cc: "Jiri Slaby (SUSE)" , Arnd Bergmann , Bjorn Helgaas , Sasha Levin +Message-ID: <20260715012255.4073217-1-sashal@kernel.org> + +From: "Jiri Slaby (SUSE)" + +[ Upstream commit a103d2dede5683dabbac2c3374bc24b6a9434478 ] + +All irq_domain functions now accept fwnode instead of of_node. But many +PCI controllers still extract dev to of_node and then of_node to fwnode. + +Instead, clean this up and simply use the dev_fwnode() helper to extract +fwnode directly from dev. Internally, it still does dev => of_node => +fwnode steps, but it's now hidden from the users. + +In the case of altera, this also removes an unused 'node' variable that is +only used when CONFIG_OF is enabled: + + drivers/pci/controller/pcie-altera.c: In function 'altera_pcie_init_irq_domain': + drivers/pci/controller/pcie-altera.c:855:29: error: unused variable 'node' [-Werror=unused-variable] + 855 | struct device_node *node = dev->of_node; + +Signed-off-by: Jiri Slaby (SUSE) +Signed-off-by: Arnd Bergmann # altera +[bhelgaas: squash together, rebase to precede msi-parent] +Signed-off-by: Bjorn Helgaas +Link: https://patch.msgid.link/20250521163329.2137973-1-arnd@kernel.org +Link: https://patch.msgid.link/20250611104348.192092-16-jirislaby@kernel.org +Link: https://patch.msgid.link/20250723065907.1841758-1-jirislaby@kernel.org +Stable-dep-of: f865a57896bd ("PCI: mediatek: Fix IRQ domain leak when port fails to enable") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/pci/controller/dwc/pcie-designware-host.c | 2 +- + drivers/pci/controller/mobiveil/pcie-mobiveil-host.c | 8 +++----- + drivers/pci/controller/pcie-altera-msi.c | 2 +- + drivers/pci/controller/pcie-altera.c | 3 +-- + drivers/pci/controller/pcie-mediatek.c | 2 +- + drivers/pci/controller/pcie-xilinx-nwl.c | 2 +- + 6 files changed, 8 insertions(+), 11 deletions(-) + +--- a/drivers/pci/controller/dwc/pcie-designware-host.c ++++ b/drivers/pci/controller/dwc/pcie-designware-host.c +@@ -233,7 +233,7 @@ static const struct irq_domain_ops dw_pc + int dw_pcie_allocate_domains(struct pcie_port *pp) + { + struct dw_pcie *pci = to_dw_pcie_from_pp(pp); +- struct fwnode_handle *fwnode = of_node_to_fwnode(pci->dev->of_node); ++ struct fwnode_handle *fwnode = dev_fwnode(pci->dev); + + pp->irq_domain = irq_domain_create_linear(fwnode, pp->num_vectors, + &dw_pcie_msi_domain_ops, pp); +--- a/drivers/pci/controller/mobiveil/pcie-mobiveil-host.c ++++ b/drivers/pci/controller/mobiveil/pcie-mobiveil-host.c +@@ -452,7 +452,7 @@ static const struct irq_domain_ops msi_d + static int mobiveil_allocate_msi_domains(struct mobiveil_pcie *pcie) + { + struct device *dev = &pcie->pdev->dev; +- struct fwnode_handle *fwnode = of_node_to_fwnode(dev->of_node); ++ struct fwnode_handle *fwnode = dev_fwnode(dev); + struct mobiveil_msi *msi = &pcie->rp.msi; + + mutex_init(&msi->lock); +@@ -478,13 +478,11 @@ static int mobiveil_allocate_msi_domains + static int mobiveil_pcie_init_irq_domain(struct mobiveil_pcie *pcie) + { + struct device *dev = &pcie->pdev->dev; +- struct device_node *node = dev->of_node; + struct mobiveil_root_port *rp = &pcie->rp; + + /* setup INTx */ +- rp->intx_domain = irq_domain_add_linear(node, PCI_NUM_INTX, +- &intx_domain_ops, pcie); +- ++ rp->intx_domain = irq_domain_create_linear(dev_fwnode(dev), PCI_NUM_INTX, &intx_domain_ops, ++ pcie); + if (!rp->intx_domain) { + dev_err(dev, "Failed to get a INTx IRQ domain\n"); + return -ENOMEM; +--- a/drivers/pci/controller/pcie-altera-msi.c ++++ b/drivers/pci/controller/pcie-altera-msi.c +@@ -173,7 +173,7 @@ static const struct irq_domain_ops msi_d + + static int altera_allocate_domains(struct altera_msi *msi) + { +- struct fwnode_handle *fwnode = of_node_to_fwnode(msi->pdev->dev.of_node); ++ struct fwnode_handle *fwnode = dev_fwnode(&msi->pdev->dev); + + msi->inner_domain = irq_domain_add_linear(NULL, msi->num_of_vectors, + &msi_domain_ops, msi); +--- a/drivers/pci/controller/pcie-altera.c ++++ b/drivers/pci/controller/pcie-altera.c +@@ -672,10 +672,9 @@ static void altera_pcie_isr(struct irq_d + static int altera_pcie_init_irq_domain(struct altera_pcie *pcie) + { + struct device *dev = &pcie->pdev->dev; +- struct device_node *node = dev->of_node; + + /* Setup INTx */ +- pcie->irq_domain = irq_domain_add_linear(node, PCI_NUM_INTX, ++ pcie->irq_domain = irq_domain_create_linear(dev_fwnode(dev), PCI_NUM_INTX, + &intx_domain_ops, pcie); + if (!pcie->irq_domain) { + dev_err(dev, "Failed to get a INTx IRQ domain\n"); +--- a/drivers/pci/controller/pcie-mediatek.c ++++ b/drivers/pci/controller/pcie-mediatek.c +@@ -497,7 +497,7 @@ static struct msi_domain_info mtk_msi_do + + static int mtk_pcie_allocate_msi_domains(struct mtk_pcie_port *port) + { +- struct fwnode_handle *fwnode = of_node_to_fwnode(port->pcie->dev->of_node); ++ struct fwnode_handle *fwnode = dev_fwnode(port->pcie->dev); + + mutex_init(&port->lock); + +--- a/drivers/pci/controller/pcie-xilinx-nwl.c ++++ b/drivers/pci/controller/pcie-xilinx-nwl.c +@@ -515,7 +515,7 @@ static int nwl_pcie_init_msi_irq_domain( + { + #ifdef CONFIG_PCI_MSI + struct device *dev = pcie->dev; +- struct fwnode_handle *fwnode = of_node_to_fwnode(dev->of_node); ++ struct fwnode_handle *fwnode = dev_fwnode(dev); + struct nwl_msi *msi = &pcie->msi; + + msi->dev_domain = irq_domain_add_linear(NULL, INT_PCI_MSI_NR, diff --git a/queue-5.10/pci-fix-restoring-bars-on-bar-resize-rollback-path.patch b/queue-5.10/pci-fix-restoring-bars-on-bar-resize-rollback-path.patch new file mode 100644 index 0000000000..daeae6f65d --- /dev/null +++ b/queue-5.10/pci-fix-restoring-bars-on-bar-resize-rollback-path.patch @@ -0,0 +1,335 @@ +From stable+bounces-274989-greg=kroah.com@vger.kernel.org Wed Jul 15 18:37:09 2026 +From: Sasha Levin +Date: Wed, 15 Jul 2026 12:32:20 -0400 +Subject: PCI: Fix restoring BARs on BAR resize rollback path +To: stable@vger.kernel.org +Cc: "Ilpo Järvinen" , "Simon Richter" , "Alex Bennée" , "Bjorn Helgaas" , "Christian König" , "Sasha Levin" +Message-ID: <20260715163223.952417-3-sashal@kernel.org> + +From: Ilpo Järvinen + +[ Upstream commit 337b1b566db087347194e4543ddfdfa5645275cc ] + +BAR resize operation is implemented in the pci_resize_resource() and +pbus_reassign_bridge_resources() functions. pci_resize_resource() can be +called either from __resource_resize_store() from sysfs or directly by the +driver for the Endpoint Device. + +The pci_resize_resource() requires that caller has released the device +resources that share the bridge window with the BAR to be resized as +otherwise the bridge window is pinned in place and cannot be changed. + +pbus_reassign_bridge_resources() rolls back resources if the resize +operation fails, but rollback is performed only for the bridge windows. +Because releasing the device resources are done by the caller of the BAR +resize interface, these functions performing the BAR resize do not have +access to the device resources as they were before the resize. + +pbus_reassign_bridge_resources() could try __pci_bridge_assign_resources() +after rolling back the bridge windows as they were, however, it will not +guarantee the resource are assigned due to differences in how FW and the +kernel assign the resources (alignment of the start address and tail). + +To perform rollback robustly, the BAR resize interface has to be altered to +also release the device resources that share the bridge window with the BAR +to be resized. + +Also, remove restoring from the entries failed list as saved list should +now contain both the bridge windows and device resources so the extra +restore is duplicated work. + +Some drivers (currently only amdgpu) want to prevent releasing some +resources. Add exclude_bars param to pci_resize_resource() and make amdgpu +pass its register BAR (BAR 2 or 5), which should never be released during +resize operation. Normally 64-bit prefetchable resources do not share a +bridge window with the 32-bit only register BAR, but there are various +fallbacks in the resource assignment logic which may make the resources +share the bridge window in rare cases. + +This change (together with the driver side changes) is to counter the +resource releases that had to be done to prevent resource tree corruption +in the ("PCI: Release assigned resource before restoring them") change. As +such, it likely restores functionality in cases where device resources were +released to avoid resource tree conflicts which appeared to be "working" +when such conflicts were not correctly detected by the kernel. + +Reported-by: Simon Richter +Link: https://lore.kernel.org/linux-pci/f9a8c975-f5d3-4dd2-988e-4371a1433a60@hogyros.de/ +Reported-by: Alex Bennée +Link: https://lore.kernel.org/linux-pci/874irqop6b.fsf@draig.linaro.org/ +Signed-off-by: Ilpo Järvinen +[bhelgaas: squash amdgpu BAR selection from +https: //lore.kernel.org/r/20251114103053.13778-1-ilpo.jarvinen@linux.intel.com] +Signed-off-by: Bjorn Helgaas +Tested-by: Alex Bennée # AVA, AMD GPU +Reviewed-by: Christian König +Link: https://patch.msgid.link/20251113162628.5946-7-ilpo.jarvinen@linux.intel.com +Stable-dep-of: ee7471fe968d ("PCI: Skip Resizable BAR restore on read error") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 4 - + drivers/pci/pci.h | 3 + drivers/pci/setup-bus.c | 97 +++++++++++++++++++---------- + drivers/pci/setup-res.c | 19 +---- + include/linux/pci.h | 4 - + 5 files changed, 79 insertions(+), 48 deletions(-) + +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +@@ -1141,7 +1141,9 @@ int amdgpu_device_resize_fb_bar(struct a + + pci_release_resource(adev->pdev, 0); + +- r = pci_resize_resource(adev->pdev, 0, rbar_size); ++ r = pci_resize_resource(adev->pdev, 0, rbar_size, ++ (adev->asic_type >= CHIP_BONAIRE) ? 1 << 5 ++ : 1 << 2); + if (r == -ENOSPC) + DRM_INFO("Not enough PCI address space for a large BAR."); + else if (r && r != -ENOTSUPP) +--- a/drivers/pci/pci.h ++++ b/drivers/pci/pci.h +@@ -284,6 +284,9 @@ enum pci_bar_type { + struct device *pci_get_host_bridge_device(struct pci_dev *dev); + void pci_put_host_bridge_device(struct device *dev); + ++int pci_do_resource_release_and_resize(struct pci_dev *dev, int resno, int size, ++ int exclude_bars); ++ + int pci_configure_extended_tags(struct pci_dev *dev, void *ign); + bool pci_bus_read_dev_vendor_id(struct pci_bus *bus, int devfn, u32 *pl, + int crs_timeout); +--- a/drivers/pci/setup-bus.c ++++ b/drivers/pci/setup-bus.c +@@ -2166,18 +2166,16 @@ enable_all: + } + EXPORT_SYMBOL_GPL(pci_assign_unassigned_bridge_resources); + +-int pci_reassign_bridge_resources(struct pci_dev *bridge, unsigned long type) ++static int pci_reassign_bridge_resources(struct pci_dev *bridge, unsigned long type, ++ struct list_head *saved) + { + struct pci_dev_resource *dev_res; + struct pci_dev *next; +- LIST_HEAD(saved); + LIST_HEAD(added); + LIST_HEAD(failed); + unsigned int i; + int ret; + +- down_read(&pci_bus_sem); +- + /* Walk to the root hub, releasing bridge BARs when possible */ + next = bridge; + do { +@@ -2193,9 +2191,9 @@ int pci_reassign_bridge_resources(struct + if (res->child) + continue; + +- ret = add_to_list(&saved, bridge, res, 0, 0); ++ ret = add_to_list(saved, bridge, res, 0, 0); + if (ret) +- goto cleanup; ++ return ret; + + pci_info(bridge, "BAR %d: releasing %pR\n", + i, res); +@@ -2212,67 +2210,104 @@ int pci_reassign_bridge_resources(struct + next = bridge->bus ? bridge->bus->self : NULL; + } while (next); + +- if (list_empty(&saved)) { +- up_read(&pci_bus_sem); ++ if (list_empty(saved)) + return -ENOENT; +- } + + __pci_bus_size_bridges(bridge->subordinate, &added); + __pci_bridge_assign_resources(bridge, &added, &failed); + BUG_ON(!list_empty(&added)); + + if (!list_empty(&failed)) { +- ret = -ENOSPC; +- goto cleanup; ++ free_list(&failed); ++ return -ENOSPC; + } + +- list_for_each_entry(dev_res, &saved, list) { ++ list_for_each_entry(dev_res, saved, list) { + /* Skip the bridge we just assigned resources for */ + if (bridge == dev_res->dev) + continue; + ++ if (!dev_res->dev->subordinate) ++ continue; ++ + bridge = dev_res->dev; + pci_setup_bridge(bridge->subordinate); + } + +- free_list(&saved); +- up_read(&pci_bus_sem); + return 0; ++} + +-cleanup: +- /* Restore size and flags */ +- list_for_each_entry(dev_res, &failed, list) { +- struct resource *res = dev_res->res; ++int pci_do_resource_release_and_resize(struct pci_dev *pdev, int resno, int size, ++ int exclude_bars) ++{ ++ struct resource *res = pdev->resource + resno; ++ unsigned long flags = res->flags; ++ struct pci_dev_resource *dev_res; ++ struct pci_bus *bus = pdev->bus; ++ LIST_HEAD(saved); ++ unsigned int i; ++ int ret = 0; + +- res->start = dev_res->start; +- res->end = dev_res->end; +- res->flags = dev_res->flags; ++ down_read(&pci_bus_sem); ++ ++ for (i = 0; i < PCI_BRIDGE_RESOURCES; i++) { ++ struct resource *r = &pdev->resource[i]; ++ ++ if (exclude_bars & BIT(i)) ++ continue; ++ ++ if (!pci_resource_len(pdev, i) || r->flags != flags) ++ continue; ++ ++ ret = add_to_list(&saved, pdev, r, 0, 0); ++ if (ret) ++ goto restore; ++ pci_release_resource(pdev, i); + } +- free_list(&failed); + ++ res->end = res->start + pci_rebar_size_to_bytes(size) - 1; ++ ++ if (!bus->self) ++ goto out; ++ ++ ret = pci_reassign_bridge_resources(bus->self, res->flags, &saved); ++ if (ret) ++ goto restore; ++ ++out: ++ up_read(&pci_bus_sem); ++ free_list(&saved); ++ return ret; ++ ++restore: + /* Revert to the old configuration */ + list_for_each_entry(dev_res, &saved, list) { + struct resource *res = dev_res->res; ++ struct pci_dev *dev = dev_res->dev; + +- bridge = dev_res->dev; +- i = res - bridge->resource; ++ i = res - dev->resource; + + if (res->parent) { + release_child_resources(res); +- pci_release_resource(bridge, i); ++ pci_release_resource(dev, i); + } + + res->start = dev_res->start; + res->end = dev_res->end; + res->flags = dev_res->flags; + +- pci_claim_resource(bridge, i); +- pci_setup_bridge(bridge->subordinate); +- } +- up_read(&pci_bus_sem); +- free_list(&saved); ++ if (pci_claim_resource(dev, i)) ++ continue; + +- return ret; ++ if (i < PCI_BRIDGE_RESOURCES) { ++ pci_update_resource(dev, i); ++ pci_info(dev, "BAR %d: old value restored %pR\n", ++ i, res); ++ } ++ if (dev->subordinate) ++ pci_setup_bridge(dev->subordinate); ++ } ++ goto out; + } + + void pci_assign_unassigned_bus_resources(struct pci_bus *bus) +--- a/drivers/pci/setup-res.c ++++ b/drivers/pci/setup-res.c +@@ -422,9 +422,9 @@ void pci_release_resource(struct pci_dev + } + EXPORT_SYMBOL(pci_release_resource); + +-int pci_resize_resource(struct pci_dev *dev, int resno, int size) ++int pci_resize_resource(struct pci_dev *dev, int resno, int size, ++ int exclude_bars) + { +- struct resource *res = dev->resource + resno; + struct pci_host_bridge *host; + int old, ret; + u32 sizes; +@@ -435,10 +435,6 @@ int pci_resize_resource(struct pci_dev * + if (host->preserve_config) + return -ENOTSUPP; + +- /* Make sure the resource isn't assigned before resizing it. */ +- if (!(res->flags & IORESOURCE_UNSET)) +- return -EBUSY; +- + pci_read_config_word(dev, PCI_COMMAND, &cmd); + if (cmd & PCI_COMMAND_MEMORY) + return -EBUSY; +@@ -458,19 +454,14 @@ int pci_resize_resource(struct pci_dev * + if (ret) + return ret; + +- res->end = res->start + pci_rebar_size_to_bytes(size) - 1; ++ ret = pci_do_resource_release_and_resize(dev, resno, size, exclude_bars); ++ if (ret) ++ goto error_resize; + +- /* Check if the new config works by trying to assign everything. */ +- if (dev->bus->self) { +- ret = pci_reassign_bridge_resources(dev->bus->self, res->flags); +- if (ret) +- goto error_resize; +- } + return 0; + + error_resize: + pci_rebar_set_size(dev, resno, old); +- res->end = res->start + pci_rebar_size_to_bytes(old) - 1; + return ret; + } + EXPORT_SYMBOL(pci_resize_resource); +--- a/include/linux/pci.h ++++ b/include/linux/pci.h +@@ -1257,7 +1257,8 @@ void pci_update_resource(struct pci_dev + int __must_check pci_assign_resource(struct pci_dev *dev, int i); + int __must_check pci_reassign_resource(struct pci_dev *dev, int i, resource_size_t add_size, resource_size_t align); + void pci_release_resource(struct pci_dev *dev, int resno); +-int __must_check pci_resize_resource(struct pci_dev *dev, int i, int size); ++int __must_check pci_resize_resource(struct pci_dev *dev, int i, int size, ++ int exclude_bars); + int pci_select_bars(struct pci_dev *dev, unsigned long flags); + bool pci_device_is_present(struct pci_dev *pdev); + void pci_ignore_hotplug(struct pci_dev *dev); +@@ -1332,7 +1333,6 @@ void pci_assign_unassigned_resources(voi + void pci_assign_unassigned_bridge_resources(struct pci_dev *bridge); + void pci_assign_unassigned_bus_resources(struct pci_bus *bus); + void pci_assign_unassigned_root_bus_resources(struct pci_bus *bus); +-int pci_reassign_bridge_resources(struct pci_dev *bridge, unsigned long type); + void pdev_enable_device(struct pci_dev *); + int pci_enable_resources(struct pci_dev *, int mask); + void pci_assign_irq(struct pci_dev *dev); diff --git a/queue-5.10/pci-free-saved-list-without-holding-pci_bus_sem.patch b/queue-5.10/pci-free-saved-list-without-holding-pci_bus_sem.patch new file mode 100644 index 0000000000..a0ae8ee07c --- /dev/null +++ b/queue-5.10/pci-free-saved-list-without-holding-pci_bus_sem.patch @@ -0,0 +1,38 @@ +From stable+bounces-274988-greg=kroah.com@vger.kernel.org Wed Jul 15 18:32:33 2026 +From: Sasha Levin +Date: Wed, 15 Jul 2026 12:32:19 -0400 +Subject: PCI: Free saved list without holding pci_bus_sem +To: stable@vger.kernel.org +Cc: "Ilpo Järvinen" , "Bjorn Helgaas" , "Alex Bennée" , "Sasha Levin" +Message-ID: <20260715163223.952417-2-sashal@kernel.org> + +From: Ilpo Järvinen + +[ Upstream commit 1d8a0506f69895b7cfd9d5c4546761c508231a8a ] + +Freeing the saved list does not require holding pci_bus_sem, so the +critical section can be made shorter. + +Signed-off-by: Ilpo Järvinen +Signed-off-by: Bjorn Helgaas +Tested-by: Alex Bennée # AVA, AMD GPU +Link: https://patch.msgid.link/20251113162628.5946-6-ilpo.jarvinen@linux.intel.com +Stable-dep-of: ee7471fe968d ("PCI: Skip Resizable BAR restore on read error") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/pci/setup-bus.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/pci/setup-bus.c ++++ b/drivers/pci/setup-bus.c +@@ -2269,8 +2269,8 @@ cleanup: + pci_claim_resource(bridge, i); + pci_setup_bridge(bridge->subordinate); + } +- free_list(&saved); + up_read(&pci_bus_sem); ++ free_list(&saved); + + return ret; + } diff --git a/queue-5.10/pci-imx6-fix-imx6sx_gpr12_pcie_test_powerdown-handling.patch b/queue-5.10/pci-imx6-fix-imx6sx_gpr12_pcie_test_powerdown-handling.patch new file mode 100644 index 0000000000..658fe133b8 --- /dev/null +++ b/queue-5.10/pci-imx6-fix-imx6sx_gpr12_pcie_test_powerdown-handling.patch @@ -0,0 +1,55 @@ +From stable+bounces-274572-greg=kroah.com@vger.kernel.org Wed Jul 15 00:04:21 2026 +From: Sasha Levin +Date: Tue, 14 Jul 2026 18:04:08 -0400 +Subject: PCI: imx6: Fix IMX6SX_GPR12_PCIE_TEST_POWERDOWN handling +To: stable@vger.kernel.org +Cc: Richard Zhu , Manivannan Sadhasivam , Bjorn Helgaas , Frank Li , Sasha Levin +Message-ID: <20260714220408.3333635-1-sashal@kernel.org> + +From: Richard Zhu + +[ Upstream commit aad953fb4eed0df5486cd54ccad80ac197678e01 ] + +The IMX6SX_GPR12_PCIE_TEST_POWERDOWN bit does not control the PCIe +reference clock on i.MX6SX. Instead, it is part of i.MX6SX PCIe core +reset sequence. + +Move the IMX6SX_GPR12_PCIE_TEST_POWERDOWN assertion/deassertion into +the core reset functions to properly reflect its purpose. Remove the +.enable_ref_clk() callback for i.MX6SX since it was incorrectly +manipulating this bit. + +Fixes: e3c06cd063d6 ("PCI: imx6: Add initial imx6sx support") +Signed-off-by: Richard Zhu +Signed-off-by: Manivannan Sadhasivam +Signed-off-by: Bjorn Helgaas +Reviewed-by: Frank Li +Cc: stable@vger.kernel.org +Link: https://patch.msgid.link/20260319090844.444987-1-hongxing.zhu@nxp.com +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/pci/controller/dwc/pci-imx6.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +--- a/drivers/pci/controller/dwc/pci-imx6.c ++++ b/drivers/pci/controller/dwc/pci-imx6.c +@@ -428,9 +428,6 @@ static int imx6_pcie_enable_ref_clk(stru + dev_err(dev, "unable to enable pcie_axi clock\n"); + break; + } +- +- regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12, +- IMX6SX_GPR12_PCIE_TEST_POWERDOWN, 0); + break; + case IMX6QP: + case IMX6Q: +@@ -557,6 +554,8 @@ static void imx6_pcie_deassert_core_rese + imx7d_pcie_wait_for_phy_pll_lock(imx6_pcie); + break; + case IMX6SX: ++ regmap_clear_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12, ++ IMX6SX_GPR12_PCIE_TEST_POWERDOWN); + regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR5, + IMX6SX_GPR5_PCIE_BTNRST_RESET, 0); + break; diff --git a/queue-5.10/pci-mediatek-convert-bool-to-single-quirks-entry-and-bitmap.patch b/queue-5.10/pci-mediatek-convert-bool-to-single-quirks-entry-and-bitmap.patch new file mode 100644 index 0000000000..8268d37b47 --- /dev/null +++ b/queue-5.10/pci-mediatek-convert-bool-to-single-quirks-entry-and-bitmap.patch @@ -0,0 +1,103 @@ +From stable+bounces-274660-greg=kroah.com@vger.kernel.org Wed Jul 15 03:23:31 2026 +From: Sasha Levin +Date: Tue, 14 Jul 2026 21:22:54 -0400 +Subject: PCI: mediatek: Convert bool to single quirks entry and bitmap +To: stable@vger.kernel.org +Cc: Christian Marangi , Manivannan Sadhasivam , AngeloGioacchino Del Regno , Sasha Levin +Message-ID: <20260715012255.4073217-2-sashal@kernel.org> + +From: Christian Marangi + +[ Upstream commit 04305367fab7ec9c98eeba315ad09c8b20abce93 ] + +To clean Mediatek SoC PCIe struct, convert all the bool to a bitmap and +use a single quirks to reference all the values. This permits cleaner +addition of new quirk without having to define a new bool in the struct. + +Signed-off-by: Christian Marangi +Signed-off-by: Manivannan Sadhasivam +Reviewed-by: AngeloGioacchino Del Regno +Link: https://patch.msgid.link/20251020111121.31779-4-ansuelsmth@gmail.com +Stable-dep-of: f865a57896bd ("PCI: mediatek: Fix IRQ domain leak when port fails to enable") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/pci/controller/pcie-mediatek.c | 25 ++++++++++++++++--------- + 1 file changed, 16 insertions(+), 9 deletions(-) + +--- a/drivers/pci/controller/pcie-mediatek.c ++++ b/drivers/pci/controller/pcie-mediatek.c +@@ -141,21 +141,29 @@ + struct mtk_pcie_port; + + /** ++ * enum mtk_pcie_quirks - MTK PCIe quirks ++ * @MTK_PCIE_FIX_CLASS_ID: host's class ID needed to be fixed ++ * @MTK_PCIE_FIX_DEVICE_ID: host's device ID needed to be fixed ++ */ ++enum mtk_pcie_quirks { ++ MTK_PCIE_FIX_CLASS_ID = BIT(0), ++ MTK_PCIE_FIX_DEVICE_ID = BIT(1), ++}; ++ ++/** + * struct mtk_pcie_soc - differentiate between host generations +- * @need_fix_class_id: whether this host's class ID needed to be fixed or not +- * @need_fix_device_id: whether this host's device ID needed to be fixed or not + * @device_id: device ID which this host need to be fixed + * @ops: pointer to configuration access functions + * @startup: pointer to controller setting functions + * @setup_irq: pointer to initialize IRQ functions ++ * @quirks: PCIe device quirks. + */ + struct mtk_pcie_soc { +- bool need_fix_class_id; +- bool need_fix_device_id; + unsigned int device_id; + struct pci_ops *ops; + int (*startup)(struct mtk_pcie_port *port); + int (*setup_irq)(struct mtk_pcie_port *port, struct device_node *node); ++ enum mtk_pcie_quirks quirks; + }; + + /** +@@ -710,7 +718,7 @@ static int mtk_pcie_startup_port_v2(stru + writel(val, port->base + PCIE_RST_CTRL); + + /* Set up vendor ID and class code */ +- if (soc->need_fix_class_id) { ++ if (soc->quirks & MTK_PCIE_FIX_CLASS_ID) { + val = PCI_VENDOR_ID_MEDIATEK; + writew(val, port->base + PCIE_CONF_VEND_ID); + +@@ -718,7 +726,7 @@ static int mtk_pcie_startup_port_v2(stru + writew(val, port->base + PCIE_CONF_CLASS_ID); + } + +- if (soc->need_fix_device_id) ++ if (soc->quirks & MTK_PCIE_FIX_DEVICE_ID) + writew(soc->device_id, port->base + PCIE_CONF_DEVICE_ID); + + /* 100ms timeout value should be enough for Gen1/2 training */ +@@ -1206,19 +1214,18 @@ static const struct mtk_pcie_soc mtk_pci + }; + + static const struct mtk_pcie_soc mtk_pcie_soc_mt7622 = { +- .need_fix_class_id = true, + .ops = &mtk_pcie_ops_v2, + .startup = mtk_pcie_startup_port_v2, + .setup_irq = mtk_pcie_setup_irq, ++ .quirks = MTK_PCIE_FIX_CLASS_ID, + }; + + static const struct mtk_pcie_soc mtk_pcie_soc_mt7629 = { +- .need_fix_class_id = true, +- .need_fix_device_id = true, + .device_id = PCI_DEVICE_ID_MEDIATEK_7629, + .ops = &mtk_pcie_ops_v2, + .startup = mtk_pcie_startup_port_v2, + .setup_irq = mtk_pcie_setup_irq, ++ .quirks = MTK_PCIE_FIX_CLASS_ID | MTK_PCIE_FIX_DEVICE_ID, + }; + + static const struct of_device_id mtk_pcie_ids[] = { diff --git a/queue-5.10/pci-mediatek-fix-irq-domain-leak-when-port-fails-to-enable.patch b/queue-5.10/pci-mediatek-fix-irq-domain-leak-when-port-fails-to-enable.patch new file mode 100644 index 0000000000..efd9848839 --- /dev/null +++ b/queue-5.10/pci-mediatek-fix-irq-domain-leak-when-port-fails-to-enable.patch @@ -0,0 +1,170 @@ +From stable+bounces-274661-greg=kroah.com@vger.kernel.org Wed Jul 15 03:23:35 2026 +From: Sasha Levin +Date: Tue, 14 Jul 2026 21:22:55 -0400 +Subject: PCI: mediatek: Fix IRQ domain leak when port fails to enable +To: stable@vger.kernel.org +Cc: Manivannan Sadhasivam , Manivannan Sadhasivam , Caleb James DeLisle , Sasha Levin +Message-ID: <20260715012255.4073217-3-sashal@kernel.org> + +From: Manivannan Sadhasivam + +[ Upstream commit f865a57896bd92d7662eb2818d8f48872e2cbbc7 ] + +When mtk_pcie_enable_port() fails, mtk_pcie_port_free() removes the port +from pcie->ports and frees the port structure. However, the IRQ domains set +up earlier by mtk_pcie_init_irq_domain() are never freed. + +Fix this by refactoring mtk_pcie_irq_teardown() into a per-port helper, +mtk_pcie_irq_teardown_port(), and calling it from mtk_pcie_setup() when +mtk_pcie_enable_port() fails. Since the IRQ teardown must only happen in +the probe error path (during resume, child devices may have active MSI +mappings and the NOIRQ context prohibits sleeping locks), +mtk_pcie_enable_port() is changed to return an error code so callers can +distinguish the two paths and act accordingly. + +This issue was reported by Sashiko while reviewing the EcoNet EN7528 SoC +support series. + +Fixes: b099631df160 ("PCI: mediatek: Add controller support for MT2712 and MT7622") +Signed-off-by: Manivannan Sadhasivam +Signed-off-by: Manivannan Sadhasivam +Cc: stable@vger.kernel.org # 5.10 +Cc: Caleb James DeLisle +Link: https://patch.msgid.link/20260521174617.17692-1-mani@kernel.org +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/pci/controller/pcie-mediatek.c | 67 ++++++++++++++++++++------------- + 1 file changed, 42 insertions(+), 25 deletions(-) + +--- a/drivers/pci/controller/pcie-mediatek.c ++++ b/drivers/pci/controller/pcie-mediatek.c +@@ -541,25 +541,29 @@ static void mtk_pcie_enable_msi(struct m + writel(val, port->base + PCIE_INT_MASK); + } + +-static void mtk_pcie_irq_teardown(struct mtk_pcie *pcie) ++static void mtk_pcie_irq_teardown_port(struct mtk_pcie_port *port) + { +- struct mtk_pcie_port *port, *tmp; ++ irq_set_chained_handler_and_data(port->irq, NULL, NULL); + +- list_for_each_entry_safe(port, tmp, &pcie->ports, list) { +- irq_set_chained_handler_and_data(port->irq, NULL, NULL); ++ if (port->irq_domain) ++ irq_domain_remove(port->irq_domain); + +- if (port->irq_domain) +- irq_domain_remove(port->irq_domain); ++ if (IS_ENABLED(CONFIG_PCI_MSI)) { ++ if (port->msi_domain) ++ irq_domain_remove(port->msi_domain); ++ if (port->inner_domain) ++ irq_domain_remove(port->inner_domain); ++ } + +- if (IS_ENABLED(CONFIG_PCI_MSI)) { +- if (port->msi_domain) +- irq_domain_remove(port->msi_domain); +- if (port->inner_domain) +- irq_domain_remove(port->inner_domain); +- } ++ irq_dispose_mapping(port->irq); ++} + +- irq_dispose_mapping(port->irq); +- } ++static void mtk_pcie_irq_teardown(struct mtk_pcie *pcie) ++{ ++ struct mtk_pcie_port *port, *tmp; ++ ++ list_for_each_entry_safe(port, tmp, &pcie->ports, list) ++ mtk_pcie_irq_teardown_port(port); + } + + static int mtk_pcie_intx_map(struct irq_domain *domain, unsigned int irq, +@@ -836,7 +840,7 @@ static int mtk_pcie_startup_port(struct + return 0; + } + +-static void mtk_pcie_enable_port(struct mtk_pcie_port *port) ++static int mtk_pcie_enable_port(struct mtk_pcie_port *port) + { + struct mtk_pcie *pcie = port->pcie; + struct device *dev = pcie->dev; +@@ -845,7 +849,7 @@ static void mtk_pcie_enable_port(struct + err = clk_prepare_enable(port->sys_ck); + if (err) { + dev_err(dev, "failed to enable sys_ck%d clock\n", port->slot); +- goto err_sys_clk; ++ return err; + } + + err = clk_prepare_enable(port->ahb_ck); +@@ -893,11 +897,15 @@ static void mtk_pcie_enable_port(struct + goto err_phy_on; + } + +- if (!pcie->soc->startup(port)) +- return; ++ err = pcie->soc->startup(port); ++ if (err) { ++ dev_info(dev, "Port%d link down\n", port->slot); ++ goto err_soc_startup; ++ } + +- dev_info(dev, "Port%d link down\n", port->slot); ++ return 0; + ++err_soc_startup: + phy_power_off(port->phy); + err_phy_on: + phy_exit(port->phy); +@@ -913,8 +921,8 @@ err_aux_clk: + clk_disable_unprepare(port->ahb_ck); + err_ahb_clk: + clk_disable_unprepare(port->sys_ck); +-err_sys_clk: +- mtk_pcie_port_free(port); ++ ++ return err; + } + + static int mtk_pcie_parse_port(struct mtk_pcie *pcie, +@@ -1077,8 +1085,13 @@ static int mtk_pcie_setup(struct mtk_pci + return err; + + /* enable each port, and then check link status */ +- list_for_each_entry_safe(port, tmp, &pcie->ports, list) +- mtk_pcie_enable_port(port); ++ list_for_each_entry_safe(port, tmp, &pcie->ports, list) { ++ err = mtk_pcie_enable_port(port); ++ if (err) { ++ mtk_pcie_irq_teardown_port(port); ++ mtk_pcie_port_free(port); ++ } ++ } + + /* power down PCIe subsys if slots are all empty (link down) */ + if (list_empty(&pcie->ports)) +@@ -1181,14 +1194,18 @@ static int __maybe_unused mtk_pcie_resum + { + struct mtk_pcie *pcie = dev_get_drvdata(dev); + struct mtk_pcie_port *port, *tmp; ++ int err; + + if (list_empty(&pcie->ports)) + return 0; + + clk_prepare_enable(pcie->free_ck); + +- list_for_each_entry_safe(port, tmp, &pcie->ports, list) +- mtk_pcie_enable_port(port); ++ list_for_each_entry_safe(port, tmp, &pcie->ports, list) { ++ err = mtk_pcie_enable_port(port); ++ if (err) ++ mtk_pcie_port_free(port); ++ } + + /* In case of EP was removed while system suspend. */ + if (list_empty(&pcie->ports)) diff --git a/queue-5.10/pci-move-resizable-bar-code-to-rebar.c.patch b/queue-5.10/pci-move-resizable-bar-code-to-rebar.c.patch new file mode 100644 index 0000000000..c68152d462 --- /dev/null +++ b/queue-5.10/pci-move-resizable-bar-code-to-rebar.c.patch @@ -0,0 +1,508 @@ +From stable+bounces-274991-greg=kroah.com@vger.kernel.org Wed Jul 15 18:37:16 2026 +From: Sasha Levin +Date: Wed, 15 Jul 2026 12:32:22 -0400 +Subject: PCI: Move Resizable BAR code to rebar.c +To: stable@vger.kernel.org +Cc: "Ilpo Järvinen" , "Bjorn Helgaas" , "Christian König" , "Sasha Levin" +Message-ID: <20260715163223.952417-5-sashal@kernel.org> + +From: Ilpo Järvinen + +[ Upstream commit 9f71938cd77f32a448f40a288e409eca60e55486 ] + +For lack of a better place to put it, Resizable BAR code has been placed +inside pci.c and setup-res.c that do not use it for anything. Upcoming +changes are going to add more Resizable BAR related functions, increasing +the code size. + +As pci.c is huge as is, move the Resizable BAR related code and the BAR +resize code from setup-res.c to rebar.c. + +Signed-off-by: Ilpo Järvinen +Signed-off-by: Bjorn Helgaas +Reviewed-by: Christian König +Link: https://patch.msgid.link/20251113180053.27944-2-ilpo.jarvinen@linux.intel.com +Stable-dep-of: ee7471fe968d ("PCI: Skip Resizable BAR restore on read error") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + Documentation/driver-api/pci/pci.rst | 3 + drivers/pci/Makefile | 2 + drivers/pci/pci.c | 135 ---------------------- + drivers/pci/pci.h | 1 + drivers/pci/rebar.c | 211 +++++++++++++++++++++++++++++++++++ + drivers/pci/setup-res.c | 64 ---------- + 6 files changed, 216 insertions(+), 200 deletions(-) + create mode 100644 drivers/pci/rebar.c + +--- a/Documentation/driver-api/pci/pci.rst ++++ b/Documentation/driver-api/pci/pci.rst +@@ -31,6 +31,9 @@ PCI Support Library + .. kernel-doc:: drivers/pci/slot.c + :export: + ++.. kernel-doc:: drivers/pci/rebar.c ++ :export: ++ + .. kernel-doc:: drivers/pci/rom.c + :export: + +--- a/drivers/pci/Makefile ++++ b/drivers/pci/Makefile +@@ -4,7 +4,7 @@ + + obj-$(CONFIG_PCI) += access.o bus.o probe.o host-bridge.o \ + remove.o pci.o pci-driver.o search.o \ +- pci-sysfs.o rom.o setup-res.o irq.o vpd.o \ ++ pci-sysfs.o rebar.o rom.o setup-res.o irq.o vpd.o \ + setup-bus.o vc.o mmap.o setup-irq.o + + obj-$(CONFIG_PCI) += pcie/ +--- a/drivers/pci/pci.c ++++ b/drivers/pci/pci.c +@@ -1626,33 +1626,6 @@ static void pci_restore_config_space(str + } + } + +-static void pci_restore_rebar_state(struct pci_dev *pdev) +-{ +- unsigned int pos, nbars, i; +- u32 ctrl; +- +- pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_REBAR); +- if (!pos) +- return; +- +- pci_read_config_dword(pdev, pos + PCI_REBAR_CTRL, &ctrl); +- nbars = (ctrl & PCI_REBAR_CTRL_NBAR_MASK) >> +- PCI_REBAR_CTRL_NBAR_SHIFT; +- +- for (i = 0; i < nbars; i++, pos += 8) { +- struct resource *res; +- int bar_idx, size; +- +- pci_read_config_dword(pdev, pos + PCI_REBAR_CTRL, &ctrl); +- bar_idx = ctrl & PCI_REBAR_CTRL_BAR_IDX; +- res = pdev->resource + bar_idx; +- size = ilog2(resource_size(res)) - 20; +- ctrl &= ~PCI_REBAR_CTRL_BAR_SIZE; +- ctrl |= size << PCI_REBAR_CTRL_BAR_SHIFT; +- pci_write_config_dword(pdev, pos + PCI_REBAR_CTRL, ctrl); +- } +-} +- + /** + * pci_restore_state - Restore the saved state of a PCI device + * @dev: PCI device that we're dealing with +@@ -3558,114 +3531,6 @@ void pci_acs_init(struct pci_dev *dev) + } + + /** +- * pci_rebar_find_pos - find position of resize ctrl reg for BAR +- * @pdev: PCI device +- * @bar: BAR to find +- * +- * Helper to find the position of the ctrl register for a BAR. +- * Returns -ENOTSUPP if resizable BARs are not supported at all. +- * Returns -ENOENT if no ctrl register for the BAR could be found. +- */ +-static int pci_rebar_find_pos(struct pci_dev *pdev, int bar) +-{ +- unsigned int pos, nbars, i; +- u32 ctrl; +- +- pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_REBAR); +- if (!pos) +- return -ENOTSUPP; +- +- pci_read_config_dword(pdev, pos + PCI_REBAR_CTRL, &ctrl); +- nbars = (ctrl & PCI_REBAR_CTRL_NBAR_MASK) >> +- PCI_REBAR_CTRL_NBAR_SHIFT; +- +- for (i = 0; i < nbars; i++, pos += 8) { +- int bar_idx; +- +- pci_read_config_dword(pdev, pos + PCI_REBAR_CTRL, &ctrl); +- bar_idx = ctrl & PCI_REBAR_CTRL_BAR_IDX; +- if (bar_idx == bar) +- return pos; +- } +- +- return -ENOENT; +-} +- +-/** +- * pci_rebar_get_possible_sizes - get possible sizes for BAR +- * @pdev: PCI device +- * @bar: BAR to query +- * +- * Get the possible sizes of a resizable BAR as bitmask defined in the spec +- * (bit 0=1MB, bit 19=512GB). Returns 0 if BAR isn't resizable. +- */ +-u32 pci_rebar_get_possible_sizes(struct pci_dev *pdev, int bar) +-{ +- int pos; +- u32 cap; +- +- pos = pci_rebar_find_pos(pdev, bar); +- if (pos < 0) +- return 0; +- +- pci_read_config_dword(pdev, pos + PCI_REBAR_CAP, &cap); +- cap &= PCI_REBAR_CAP_SIZES; +- +- /* Sapphire RX 5600 XT Pulse has an invalid cap dword for BAR 0 */ +- if (pdev->vendor == PCI_VENDOR_ID_ATI && pdev->device == 0x731f && +- bar == 0 && cap == 0x7000) +- cap = 0x3f000; +- +- return cap >> 4; +-} +- +-/** +- * pci_rebar_get_current_size - get the current size of a BAR +- * @pdev: PCI device +- * @bar: BAR to set size to +- * +- * Read the size of a BAR from the resizable BAR config. +- * Returns size if found or negative error code. +- */ +-int pci_rebar_get_current_size(struct pci_dev *pdev, int bar) +-{ +- int pos; +- u32 ctrl; +- +- pos = pci_rebar_find_pos(pdev, bar); +- if (pos < 0) +- return pos; +- +- pci_read_config_dword(pdev, pos + PCI_REBAR_CTRL, &ctrl); +- return (ctrl & PCI_REBAR_CTRL_BAR_SIZE) >> PCI_REBAR_CTRL_BAR_SHIFT; +-} +- +-/** +- * pci_rebar_set_size - set a new size for a BAR +- * @pdev: PCI device +- * @bar: BAR to set size to +- * @size: new size as defined in the spec (0=1MB, 19=512GB) +- * +- * Set the new size of a BAR as defined in the spec. +- * Returns zero if resizing was successful, error code otherwise. +- */ +-int pci_rebar_set_size(struct pci_dev *pdev, int bar, int size) +-{ +- int pos; +- u32 ctrl; +- +- pos = pci_rebar_find_pos(pdev, bar); +- if (pos < 0) +- return pos; +- +- pci_read_config_dword(pdev, pos + PCI_REBAR_CTRL, &ctrl); +- ctrl &= ~PCI_REBAR_CTRL_BAR_SIZE; +- ctrl |= size << PCI_REBAR_CTRL_BAR_SHIFT; +- pci_write_config_dword(pdev, pos + PCI_REBAR_CTRL, ctrl); +- return 0; +-} +- +-/** + * pci_enable_atomic_ops_to_root - enable AtomicOp requests to root port + * @dev: the PCI device + * @cap_mask: mask of desired AtomicOp sizes, including one or more of: +--- a/drivers/pci/pci.h ++++ b/drivers/pci/pci.h +@@ -629,6 +629,7 @@ static inline int acpi_get_rc_resources( + #endif + + u32 pci_rebar_get_possible_sizes(struct pci_dev *pdev, int bar); ++void pci_restore_rebar_state(struct pci_dev *pdev); + int pci_rebar_get_current_size(struct pci_dev *pdev, int bar); + int pci_rebar_set_size(struct pci_dev *pdev, int bar, int size); + static inline u64 pci_rebar_size_to_bytes(int size) +--- /dev/null ++++ b/drivers/pci/rebar.c +@@ -0,0 +1,211 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * PCI Resizable BAR Extended Capability handling. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "pci.h" ++ ++/** ++ * pci_rebar_find_pos - find position of resize ctrl reg for BAR ++ * @pdev: PCI device ++ * @bar: BAR to find ++ * ++ * Helper to find the position of the ctrl register for a BAR. ++ * Returns -ENOTSUPP if resizable BARs are not supported at all. ++ * Returns -ENOENT if no ctrl register for the BAR could be found. ++ */ ++static int pci_rebar_find_pos(struct pci_dev *pdev, int bar) ++{ ++ unsigned int pos, nbars, i; ++ u32 ctrl; ++ ++ pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_REBAR); ++ if (!pos) ++ return -ENOTSUPP; ++ ++ pci_read_config_dword(pdev, pos + PCI_REBAR_CTRL, &ctrl); ++ nbars = (ctrl & PCI_REBAR_CTRL_NBAR_MASK) >> ++ PCI_REBAR_CTRL_NBAR_SHIFT; ++ ++ for (i = 0; i < nbars; i++, pos += 8) { ++ int bar_idx; ++ ++ pci_read_config_dword(pdev, pos + PCI_REBAR_CTRL, &ctrl); ++ bar_idx = ctrl & PCI_REBAR_CTRL_BAR_IDX; ++ if (bar_idx == bar) ++ return pos; ++ } ++ ++ return -ENOENT; ++} ++ ++/** ++ * pci_rebar_get_possible_sizes - get possible sizes for BAR ++ * @pdev: PCI device ++ * @bar: BAR to query ++ * ++ * Get the possible sizes of a resizable BAR as bitmask defined in the spec ++ * (bit 0=1MB, bit 19=512GB). Returns 0 if BAR isn't resizable. ++ */ ++u32 pci_rebar_get_possible_sizes(struct pci_dev *pdev, int bar) ++{ ++ int pos; ++ u32 cap; ++ ++ pos = pci_rebar_find_pos(pdev, bar); ++ if (pos < 0) ++ return 0; ++ ++ pci_read_config_dword(pdev, pos + PCI_REBAR_CAP, &cap); ++ cap &= PCI_REBAR_CAP_SIZES; ++ ++ /* Sapphire RX 5600 XT Pulse has an invalid cap dword for BAR 0 */ ++ if (pdev->vendor == PCI_VENDOR_ID_ATI && pdev->device == 0x731f && ++ bar == 0 && cap == 0x7000) ++ cap = 0x3f000; ++ ++ return cap >> 4; ++} ++ ++/** ++ * pci_rebar_get_current_size - get the current size of a BAR ++ * @pdev: PCI device ++ * @bar: BAR to set size to ++ * ++ * Read the size of a BAR from the resizable BAR config. ++ * Returns size if found or negative error code. ++ */ ++int pci_rebar_get_current_size(struct pci_dev *pdev, int bar) ++{ ++ int pos; ++ u32 ctrl; ++ ++ pos = pci_rebar_find_pos(pdev, bar); ++ if (pos < 0) ++ return pos; ++ ++ pci_read_config_dword(pdev, pos + PCI_REBAR_CTRL, &ctrl); ++ return (ctrl & PCI_REBAR_CTRL_BAR_SIZE) >> PCI_REBAR_CTRL_BAR_SHIFT; ++} ++ ++/** ++ * pci_rebar_set_size - set a new size for a BAR ++ * @pdev: PCI device ++ * @bar: BAR to set size to ++ * @size: new size as defined in the spec (0=1MB, 19=512GB) ++ * ++ * Set the new size of a BAR as defined in the spec. ++ * Returns zero if resizing was successful, error code otherwise. ++ */ ++int pci_rebar_set_size(struct pci_dev *pdev, int bar, int size) ++{ ++ int pos; ++ u32 ctrl; ++ ++ pos = pci_rebar_find_pos(pdev, bar); ++ if (pos < 0) ++ return pos; ++ ++ pci_read_config_dword(pdev, pos + PCI_REBAR_CTRL, &ctrl); ++ ctrl &= ~PCI_REBAR_CTRL_BAR_SIZE; ++ ctrl |= size << PCI_REBAR_CTRL_BAR_SHIFT; ++ pci_write_config_dword(pdev, pos + PCI_REBAR_CTRL, ctrl); ++ return 0; ++} ++ ++void pci_restore_rebar_state(struct pci_dev *pdev) ++{ ++ unsigned int pos, nbars, i; ++ u32 ctrl; ++ ++ pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_REBAR); ++ if (!pos) ++ return; ++ ++ pci_read_config_dword(pdev, pos + PCI_REBAR_CTRL, &ctrl); ++ nbars = FIELD_GET(PCI_REBAR_CTRL_NBAR_MASK, ctrl); ++ ++ for (i = 0; i < nbars; i++, pos += 8) { ++ struct resource *res; ++ int bar_idx, size; ++ ++ pci_read_config_dword(pdev, pos + PCI_REBAR_CTRL, &ctrl); ++ bar_idx = ctrl & PCI_REBAR_CTRL_BAR_IDX; ++ res = pdev->resource + bar_idx; ++ size = ilog2(resource_size(res)) - 20; ++ ctrl &= ~PCI_REBAR_CTRL_BAR_SIZE; ++ ctrl |= size << PCI_REBAR_CTRL_BAR_SHIFT; ++ pci_write_config_dword(pdev, pos + PCI_REBAR_CTRL, ctrl); ++ } ++} ++ ++/** ++ * pci_resize_resource - reconfigure a Resizable BAR and resources ++ * @dev: the PCI device ++ * @resno: index of the BAR to be resized ++ * @size: new size as defined in the spec (0=1MB, 31=128TB) ++ * @exclude_bars: a mask of BARs that should not be released ++ * ++ * Reconfigure @resno to @size and re-run resource assignment algorithm ++ * with the new size. ++ * ++ * Prior to resize, release @dev resources that share a bridge window with ++ * @resno. This unpins the bridge window resource to allow changing it. ++ * ++ * The caller may prevent releasing a particular BAR by providing ++ * @exclude_bars mask, but this may result in the resize operation failing ++ * due to insufficient space. ++ * ++ * Return: 0 on success, or negative on error. In case of an error, the ++ * resources are restored to their original places. ++ */ ++int pci_resize_resource(struct pci_dev *dev, int resno, int size, ++ int exclude_bars) ++{ ++ struct pci_host_bridge *host; ++ int old, ret; ++ u32 sizes; ++ u16 cmd; ++ ++ /* Check if we must preserve the firmware's resource assignment */ ++ host = pci_find_host_bridge(dev->bus); ++ if (host->preserve_config) ++ return -ENOTSUPP; ++ ++ pci_read_config_word(dev, PCI_COMMAND, &cmd); ++ if (cmd & PCI_COMMAND_MEMORY) ++ return -EBUSY; ++ ++ sizes = pci_rebar_get_possible_sizes(dev, resno); ++ if (!sizes) ++ return -ENOTSUPP; ++ ++ if (!(sizes & BIT(size))) ++ return -EINVAL; ++ ++ old = pci_rebar_get_current_size(dev, resno); ++ if (old < 0) ++ return old; ++ ++ ret = pci_rebar_set_size(dev, resno, size); ++ if (ret) ++ return ret; ++ ++ ret = pci_do_resource_release_and_resize(dev, resno, size, exclude_bars); ++ if (ret) ++ goto error_resize; ++ ++ return 0; ++ ++error_resize: ++ pci_rebar_set_size(dev, resno, old); ++ return ret; ++} ++EXPORT_SYMBOL(pci_resize_resource); +--- a/drivers/pci/setup-res.c ++++ b/drivers/pci/setup-res.c +@@ -422,70 +422,6 @@ void pci_release_resource(struct pci_dev + } + EXPORT_SYMBOL(pci_release_resource); + +-/** +- * pci_resize_resource - reconfigure a Resizable BAR and resources +- * @dev: the PCI device +- * @resno: index of the BAR to be resized +- * @size: new size as defined in the spec (0=1MB, 31=128TB) +- * @exclude_bars: a mask of BARs that should not be released +- * +- * Reconfigure @resno to @size and re-run resource assignment algorithm +- * with the new size. +- * +- * Prior to resize, release @dev resources that share a bridge window with +- * @resno. This unpins the bridge window resource to allow changing it. +- * +- * The caller may prevent releasing a particular BAR by providing +- * @exclude_bars mask, but this may result in the resize operation failing +- * due to insufficient space. +- * +- * Return: 0 on success, or negative on error. In case of an error, the +- * resources are restored to their original places. +- */ +-int pci_resize_resource(struct pci_dev *dev, int resno, int size, +- int exclude_bars) +-{ +- struct pci_host_bridge *host; +- int old, ret; +- u32 sizes; +- u16 cmd; +- +- /* Check if we must preserve the firmware's resource assignment */ +- host = pci_find_host_bridge(dev->bus); +- if (host->preserve_config) +- return -ENOTSUPP; +- +- pci_read_config_word(dev, PCI_COMMAND, &cmd); +- if (cmd & PCI_COMMAND_MEMORY) +- return -EBUSY; +- +- sizes = pci_rebar_get_possible_sizes(dev, resno); +- if (!sizes) +- return -ENOTSUPP; +- +- if (!(sizes & BIT(size))) +- return -EINVAL; +- +- old = pci_rebar_get_current_size(dev, resno); +- if (old < 0) +- return old; +- +- ret = pci_rebar_set_size(dev, resno, size); +- if (ret) +- return ret; +- +- ret = pci_do_resource_release_and_resize(dev, resno, size, exclude_bars); +- if (ret) +- goto error_resize; +- +- return 0; +- +-error_resize: +- pci_rebar_set_size(dev, resno, old); +- return ret; +-} +-EXPORT_SYMBOL(pci_resize_resource); +- + int pci_enable_resources(struct pci_dev *dev, int mask) + { + u16 cmd, old_cmd; diff --git a/queue-5.10/pci-prevent-resource-tree-corruption-when-bar-resize-fails.patch b/queue-5.10/pci-prevent-resource-tree-corruption-when-bar-resize-fails.patch new file mode 100644 index 0000000000..2bb5196e8b --- /dev/null +++ b/queue-5.10/pci-prevent-resource-tree-corruption-when-bar-resize-fails.patch @@ -0,0 +1,71 @@ +From stable+bounces-274987-greg=kroah.com@vger.kernel.org Wed Jul 15 18:32:33 2026 +From: Sasha Levin +Date: Wed, 15 Jul 2026 12:32:18 -0400 +Subject: PCI: Prevent resource tree corruption when BAR resize fails +To: stable@vger.kernel.org +Cc: "Ilpo Järvinen" , "Simon Richter" , "Alex Bennée" , "Bjorn Helgaas" , "Sasha Levin" +Message-ID: <20260715163223.952417-1-sashal@kernel.org> + +From: Ilpo Järvinen + +[ Upstream commit 91c4c89db41499eea1b29c56655f79c3bae66e93 ] + +pbus_reassign_bridge_resources() saves bridge windows into the saved +list before attempting to adjust resource assignments to perform a BAR +resize operation. If resource adjustments cannot be completed fully, +rollback is attempted by restoring the resource from the saved list. + +The rollback, however, does not check whether the resources it restores were +assigned by the partial resize attempt. If restore changes addresses of the +resource, it can result in corrupting the resource tree. + +An example of a corrupted resource tree with overlapping addresses: + + 6200000000000-6203fbfffffff : pciex@620c3c0000000 + 6200000000000-6203fbff0ffff : PCI Bus 0030:01 + 6200020000000-62000207fffff : 0030:01:00.0 + 6200000000000-6203fbff0ffff : PCI Bus 0030:02 + +A resource that are assigned into the resource tree must remain +unchanged. Thus, release such a resource before attempting to restore +and claim it back. + +For simplicity, always do the release and claim back for the resource +even in the cases where it is restored to the same address range. + +Note: this fix may "break" some cases where devices "worked" because +the resource tree corruption allowed address space double counting to +fit more resource than what can now be assigned without double +counting. The upcoming changes to BAR resizing should address those +scenarios (to the extent possible). + +Fixes: 8bb705e3e79d ("PCI: Add pci_resize_resource() for resizing BARs") +Reported-by: Simon Richter +Link: https://lore.kernel.org/linux-pci/67840a16-99b4-4d8c-9b5c-4721ab0970a2@hogyros.de/ +Reported-by: Alex Bennée +Link: https://lore.kernel.org/linux-pci/874irqop6b.fsf@draig.linaro.org/ +Signed-off-by: Ilpo Järvinen +Signed-off-by: Bjorn Helgaas +Tested-by: Alex Bennée # AVA, AMD GPU +Link: https://patch.msgid.link/20251113162628.5946-2-ilpo.jarvinen@linux.intel.com +Stable-dep-of: ee7471fe968d ("PCI: Skip Resizable BAR restore on read error") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/pci/setup-bus.c | 5 +++++ + 1 file changed, 5 insertions(+) + +--- a/drivers/pci/setup-bus.c ++++ b/drivers/pci/setup-bus.c +@@ -2257,6 +2257,11 @@ cleanup: + bridge = dev_res->dev; + i = res - bridge->resource; + ++ if (res->parent) { ++ release_child_resources(res); ++ pci_release_resource(bridge, i); ++ } ++ + res->start = dev_res->start; + res->end = dev_res->end; + res->flags = dev_res->flags; diff --git a/queue-5.10/pci-skip-resizable-bar-restore-on-read-error.patch b/queue-5.10/pci-skip-resizable-bar-restore-on-read-error.patch new file mode 100644 index 0000000000..f0d1d34b2e --- /dev/null +++ b/queue-5.10/pci-skip-resizable-bar-restore-on-read-error.patch @@ -0,0 +1,61 @@ +From stable+bounces-274992-greg=kroah.com@vger.kernel.org Wed Jul 15 18:37:21 2026 +From: Sasha Levin +Date: Wed, 15 Jul 2026 12:32:23 -0400 +Subject: PCI: Skip Resizable BAR restore on read error +To: stable@vger.kernel.org +Cc: Marco Nenciarini , Bjorn Helgaas , Sasha Levin +Message-ID: <20260715163223.952417-6-sashal@kernel.org> + +From: Marco Nenciarini + +[ Upstream commit ee7471fe968d210939be9046089a924cd23c8c3b ] + +pci_restore_rebar_state() uses the Resizable BAR Control register to decide +how many BARs to restore (nbars) and which BAR each iteration addresses +(bar_idx). + +When a device does not respond, config reads typically return +PCI_ERROR_RESPONSE (~0). Both fields are 3 bits wide, so nbars and bar_idx +both evaluate to 7, past the spec's valid ranges for both fields. +pci_resource_n() then returns an unrelated resource slot, whose size is +used to derive a nonsensical value written back to the Resizable BAR +Control register. + +Bail out if any Resizable BAR Control read returns PCI_ERROR_RESPONSE. No +further BARs are touched, which is safe because a config read that returns +PCI_ERROR_RESPONSE indicates the device is unreachable and restoration is +pointless. + +Fixes: d3252ace0bc6 ("PCI: Restore resized BAR state on resume") +Signed-off-by: Marco Nenciarini +Signed-off-by: Bjorn Helgaas +Cc: stable@vger.kernel.org +Link: https://patch.msgid.link/666cac19b5daa0ab0e0ab64454e76b4d24465dbd.1776429882.git.mnencia@kcore.it +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/pci/rebar.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +--- a/drivers/pci/rebar.c ++++ b/drivers/pci/rebar.c +@@ -130,6 +130,9 @@ void pci_restore_rebar_state(struct pci_ + return; + + pci_read_config_dword(pdev, pos + PCI_REBAR_CTRL, &ctrl); ++ if (PCI_POSSIBLE_ERROR(ctrl)) ++ return; ++ + nbars = FIELD_GET(PCI_REBAR_CTRL_NBAR_MASK, ctrl); + + for (i = 0; i < nbars; i++, pos += 8) { +@@ -137,6 +140,9 @@ void pci_restore_rebar_state(struct pci_ + int bar_idx, size; + + pci_read_config_dword(pdev, pos + PCI_REBAR_CTRL, &ctrl); ++ if (PCI_POSSIBLE_ERROR(ctrl)) ++ return; ++ + bar_idx = ctrl & PCI_REBAR_CTRL_BAR_IDX; + res = pdev->resource + bar_idx; + size = ilog2(resource_size(res)) - 20; diff --git a/queue-5.10/proc-protect-ptrace_may_access-with-exec_update_lock-fd-links.patch b/queue-5.10/proc-protect-ptrace_may_access-with-exec_update_lock-fd-links.patch new file mode 100644 index 0000000000..71beacf371 --- /dev/null +++ b/queue-5.10/proc-protect-ptrace_may_access-with-exec_update_lock-fd-links.patch @@ -0,0 +1,274 @@ +From stable+bounces-277135-greg=kroah.com@vger.kernel.org Fri Jul 17 18:38:31 2026 +From: Sasha Levin +Date: Fri, 17 Jul 2026 12:38:21 -0400 +Subject: proc: protect ptrace_may_access() with exec_update_lock (FD links) +To: stable@vger.kernel.org +Cc: Jann Horn , "Christian Brauner (Amutable)" , Sasha Levin +Message-ID: <20260717163821.2035203-3-sashal@kernel.org> + +From: Jann Horn + +[ Upstream commit 6255da28d4bb5349fe18e84cb043ccd394eba75d ] + +proc_pid_get_link() and proc_pid_readlink() currently look up the task from +the pid once, then do the ptrace access check on that task, then look up +the task from the pid a second time to do the actual access. +That's racy in several ways. + +To fix it, pass the task to the ->proc_get_link() handler, and instead of +proc_fd_access_allowed(), introduce a new helper call_proc_get_link() that +looks up and locks the task, does the access check, and calls +->proc_get_link(). + +Fixes: 778c1144771f ("[PATCH] proc: Use sane permission checks on the /proc//fd/ symlinks") +Cc: stable@vger.kernel.org +Signed-off-by: Jann Horn +Link: https://patch.msgid.link/20260518-procfs-lockfix-part1-v1-2-5c3d20e0ac33@google.com +Signed-off-by: Christian Brauner (Amutable) +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + fs/proc/base.c | 119 ++++++++++++++++++++--------------------------------- + fs/proc/fd.c | 25 ++++------- + fs/proc/internal.h | 2 + 3 files changed, 58 insertions(+), 88 deletions(-) + +--- a/fs/proc/base.c ++++ b/fs/proc/base.c +@@ -217,33 +217,24 @@ static int get_task_root(struct task_str + return result; + } + +-static int proc_cwd_link(struct dentry *dentry, struct path *path) ++static int proc_cwd_link(struct dentry *dentry, struct path *path, ++ struct task_struct *task) + { +- struct task_struct *task = get_proc_task(d_inode(dentry)); + int result = -ENOENT; + +- if (task) { +- task_lock(task); +- if (task->fs) { +- get_fs_pwd(task->fs, path); +- result = 0; +- } +- task_unlock(task); +- put_task_struct(task); ++ task_lock(task); ++ if (task->fs) { ++ get_fs_pwd(task->fs, path); ++ result = 0; + } ++ task_unlock(task); + return result; + } + +-static int proc_root_link(struct dentry *dentry, struct path *path) ++static int proc_root_link(struct dentry *dentry, struct path *path, ++ struct task_struct *task) + { +- struct task_struct *task = get_proc_task(d_inode(dentry)); +- int result = -ENOENT; +- +- if (task) { +- result = get_task_root(task, path); +- put_task_struct(task); +- } +- return result; ++ return get_task_root(task, path); + } + + /* +@@ -703,23 +694,6 @@ static int proc_pid_syscall(struct seq_f + /* Here the fs part begins */ + /************************************************************************/ + +-/* permission checks */ +-static int proc_fd_access_allowed(struct inode *inode) +-{ +- struct task_struct *task; +- int allowed = 0; +- /* Allow access to a task's file descriptors if it is us or we +- * may use ptrace attach to the process and find out that +- * information. +- */ +- task = get_proc_task(inode); +- if (task) { +- allowed = ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS); +- put_task_struct(task); +- } +- return allowed; +-} +- + int proc_nochmod_setattr(struct dentry *dentry, struct iattr *attr) + { + int error; +@@ -1774,16 +1748,12 @@ static const struct file_operations proc + .release = single_release, + }; + +-static int proc_exe_link(struct dentry *dentry, struct path *exe_path) ++static int proc_exe_link(struct dentry *dentry, struct path *exe_path, ++ struct task_struct *task) + { +- struct task_struct *task; + struct file *exe_file; + +- task = get_proc_task(d_inode(dentry)); +- if (!task) +- return -ENOENT; + exe_file = get_task_exe_file(task); +- put_task_struct(task); + if (exe_file) { + *exe_path = exe_file->f_path; + path_get(&exe_file->f_path); +@@ -1793,26 +1763,42 @@ static int proc_exe_link(struct dentry * + return -ENOENT; + } + ++static int call_proc_get_link(struct dentry *dentry, struct inode *inode, struct path *path_out) ++{ ++ struct task_struct *task; ++ int ret; ++ ++ task = get_proc_task(inode); ++ if (!task) ++ return -ENOENT; ++ ret = down_read_killable(&task->signal->exec_update_lock); ++ if (ret) ++ goto out_put_task; ++ if (!ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS)) { ++ ret = -EACCES; ++ goto out; ++ } ++ ret = PROC_I(inode)->op.proc_get_link(dentry, path_out, task); ++ ++out: ++ up_read(&task->signal->exec_update_lock); ++out_put_task: ++ put_task_struct(task); ++ return ret; ++} ++ + static const char *proc_pid_get_link(struct dentry *dentry, + struct inode *inode, + struct delayed_call *done) + { + struct path path; +- int error = -EACCES; ++ int error; + + if (!dentry) + return ERR_PTR(-ECHILD); +- +- /* Are we allowed to snoop on the tasks file descriptors? */ +- if (!proc_fd_access_allowed(inode)) +- goto out; +- +- error = PROC_I(inode)->op.proc_get_link(dentry, &path); +- if (error) +- goto out; +- +- error = nd_jump_link(&path); +-out: ++ error = call_proc_get_link(dentry, inode, &path); ++ if (!error) ++ error = nd_jump_link(&path); + return ERR_PTR(error); + } + +@@ -1846,17 +1832,11 @@ static int proc_pid_readlink(struct dent + struct inode *inode = d_inode(dentry); + struct path path; + +- /* Are we allowed to snoop on the tasks file descriptors? */ +- if (!proc_fd_access_allowed(inode)) +- goto out; +- +- error = PROC_I(inode)->op.proc_get_link(dentry, &path); +- if (error) +- goto out; +- +- error = do_proc_readlink(&path, buffer, buflen); +- path_put(&path); +-out: ++ error = call_proc_get_link(dentry, inode, &path); ++ if (!error) { ++ error = do_proc_readlink(&path, buffer, buflen); ++ path_put(&path); ++ } + return error; + } + +@@ -2242,21 +2222,16 @@ static const struct dentry_operations ti + .d_delete = pid_delete_dentry, + }; + +-static int map_files_get_link(struct dentry *dentry, struct path *path) ++static int map_files_get_link(struct dentry *dentry, struct path *path, ++ struct task_struct *task) + { + unsigned long vm_start, vm_end; + struct vm_area_struct *vma; +- struct task_struct *task; + struct mm_struct *mm; + int rc; + + rc = -ENOENT; +- task = get_proc_task(d_inode(dentry)); +- if (!task) +- goto out; +- + mm = get_task_mm(task); +- put_task_struct(task); + if (!mm) + goto out; + +--- a/fs/proc/fd.c ++++ b/fs/proc/fd.c +@@ -140,24 +140,19 @@ static const struct dentry_operations ti + .d_delete = pid_delete_dentry, + }; + +-static int proc_fd_link(struct dentry *dentry, struct path *path) ++static int proc_fd_link(struct dentry *dentry, struct path *path, ++ struct task_struct *task) + { +- struct task_struct *task; + int ret = -ENOENT; ++ unsigned int fd = proc_fd(d_inode(dentry)); ++ struct file *fd_file; + +- task = get_proc_task(d_inode(dentry)); +- if (task) { +- unsigned int fd = proc_fd(d_inode(dentry)); +- struct file *fd_file; +- +- fd_file = fget_task(task, fd); +- if (fd_file) { +- *path = fd_file->f_path; +- path_get(&fd_file->f_path); +- ret = 0; +- fput(fd_file); +- } +- put_task_struct(task); ++ fd_file = fget_task(task, fd); ++ if (fd_file) { ++ *path = fd_file->f_path; ++ path_get(&fd_file->f_path); ++ ret = 0; ++ fput(fd_file); + } + + return ret; +--- a/fs/proc/internal.h ++++ b/fs/proc/internal.h +@@ -97,7 +97,7 @@ extern struct kmem_cache *proc_dir_entry + void pde_free(struct proc_dir_entry *pde); + + union proc_op { +- int (*proc_get_link)(struct dentry *, struct path *); ++ int (*proc_get_link)(struct dentry *, struct path *, struct task_struct *); + int (*proc_show)(struct seq_file *m, + struct pid_namespace *ns, struct pid *pid, + struct task_struct *task); diff --git a/queue-5.10/proc-protect-ptrace_may_access-with-exec_update_lock-part-1.patch b/queue-5.10/proc-protect-ptrace_may_access-with-exec_update_lock-part-1.patch new file mode 100644 index 0000000000..e7b907075b --- /dev/null +++ b/queue-5.10/proc-protect-ptrace_may_access-with-exec_update_lock-part-1.patch @@ -0,0 +1,210 @@ +From stable+bounces-277189-greg=kroah.com@vger.kernel.org Fri Jul 17 21:24:09 2026 +From: Sasha Levin +Date: Fri, 17 Jul 2026 15:23:58 -0400 +Subject: proc: protect ptrace_may_access() with exec_update_lock (part 1) +To: stable@vger.kernel.org +Cc: Jann Horn , "Christian Brauner (Amutable)" , Sasha Levin +Message-ID: <20260717192358.2131761-1-sashal@kernel.org> + +From: Jann Horn + +[ Upstream commit 6650527444dadc63d84aa939d14ecba4fadb2f69 ] + +Fix the easy cases where procfs currently calls ptrace_may_access() without +exec_update_lock protection, where the fix is to simply add the extra lock +or use mm_access(): + + - do_task_stat(): grab exec_update_lock + - proc_pid_wchan(): grab exec_update_lock + - proc_map_files_lookup(): use mm_access() instead of get_task_mm() + - proc_map_files_readdir(): use mm_access() instead of get_task_mm() + - proc_ns_get_link(): grab exec_update_lock + - proc_ns_readlink(): grab exec_update_lock + +Fixes: f83ce3e6b02d ("proc: avoid information leaks to non-privileged processes") +Cc: stable@vger.kernel.org +Signed-off-by: Jann Horn +Link: https://patch.msgid.link/20260518-procfs-lockfix-part1-v1-1-5c3d20e0ac33@google.com +Signed-off-by: Christian Brauner (Amutable) +[ converted NULL return from mm_access() to ERR_PTR(-ESRCH) at call sites since 5.15's mm_access() returns NULL when the task has no mm ] +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + fs/proc/array.c | 6 ++++++ + fs/proc/base.c | 41 ++++++++++++++++++++++++----------------- + fs/proc/namespaces.c | 12 ++++++++++++ + 3 files changed, 42 insertions(+), 17 deletions(-) + +--- a/fs/proc/array.c ++++ b/fs/proc/array.c +@@ -449,6 +449,11 @@ static int do_task_stat(struct seq_file + unsigned long flags; + struct signal_struct *sig = task->signal; + unsigned int seq = 1; ++ int ret; ++ ++ ret = down_read_killable(&task->signal->exec_update_lock); ++ if (ret) ++ return ret; + + state = *get_task_state(task); + vsize = eip = esp = 0; +@@ -626,6 +631,7 @@ static int do_task_stat(struct seq_file + seq_puts(m, " 0"); + + seq_putc(m, '\n'); ++ up_read(&task->signal->exec_update_lock); + if (mm) + mmput(mm); + return 0; +--- a/fs/proc/base.c ++++ b/fs/proc/base.c +@@ -413,18 +413,24 @@ static int proc_pid_wchan(struct seq_fil + { + unsigned long wchan; + char symname[KSYM_NAME_LEN]; ++ int err; + ++ err = down_read_killable(&task->signal->exec_update_lock); ++ if (err) ++ return err; + if (!ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS)) + goto print0; + + wchan = get_wchan(task); + if (wchan && !lookup_symbol_name(wchan, symname)) { + seq_puts(m, symname); ++ up_read(&task->signal->exec_update_lock); + return 0; + } + + print0: + seq_putc(m, '0'); ++ up_read(&task->signal->exec_update_lock); + return 0; + } + #endif /* CONFIG_KALLSYMS */ +@@ -2327,17 +2333,17 @@ static struct dentry *proc_map_files_loo + if (!task) + goto out; + +- result = ERR_PTR(-EACCES); +- if (!ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS)) +- goto out_put_task; +- + result = ERR_PTR(-ENOENT); + if (dname_to_vma_addr(dentry, &vm_start, &vm_end)) + goto out_put_task; + +- mm = get_task_mm(task); ++ mm = mm_access(task, PTRACE_MODE_READ_FSCREDS); + if (!mm) ++ mm = ERR_PTR(-ESRCH); ++ if (IS_ERR(mm)) { ++ result = ERR_CAST(mm); + goto out_put_task; ++ } + + result = ERR_PTR(-EINTR); + if (mmap_read_lock_killable(mm)) +@@ -2386,23 +2392,24 @@ proc_map_files_readdir(struct file *file + if (!task) + goto out; + +- ret = -EACCES; +- if (!ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS)) +- goto out_put_task; +- + ret = 0; + if (!dir_emit_dots(file, ctx)) + goto out_put_task; + +- mm = get_task_mm(task); ++ mm = mm_access(task, PTRACE_MODE_READ_FSCREDS); + if (!mm) ++ mm = ERR_PTR(-ESRCH); ++ if (IS_ERR(mm)) { ++ ret = PTR_ERR(mm); ++ /* if the task has no mm, the directory should just be empty */ ++ if (ret == -ESRCH) ++ ret = 0; + goto out_put_task; ++ } + + ret = mmap_read_lock_killable(mm); +- if (ret) { +- mmput(mm); +- goto out_put_task; +- } ++ if (ret) ++ goto out_put_mm; + + nr_files = 0; + +@@ -2426,8 +2433,7 @@ proc_map_files_readdir(struct file *file + if (!p) { + ret = -ENOMEM; + mmap_read_unlock(mm); +- mmput(mm); +- goto out_put_task; ++ goto out_put_mm; + } + + p->start = vma->vm_start; +@@ -2435,7 +2441,6 @@ proc_map_files_readdir(struct file *file + p->mode = vma->vm_file->f_mode; + } + mmap_read_unlock(mm); +- mmput(mm); + + for (i = 0; i < nr_files; i++) { + char buf[4 * sizeof(long) + 2]; /* max: %lx-%lx\0 */ +@@ -2452,6 +2457,8 @@ proc_map_files_readdir(struct file *file + ctx->pos++; + } + ++out_put_mm: ++ mmput(mm); + out_put_task: + put_task_struct(task); + out: +--- a/fs/proc/namespaces.c ++++ b/fs/proc/namespaces.c +@@ -55,6 +55,10 @@ static const char *proc_ns_get_link(stru + if (!task) + return ERR_PTR(-EACCES); + ++ error = down_read_killable(&task->signal->exec_update_lock); ++ if (error) ++ goto out_put_task; ++ + if (!ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS)) + goto out; + +@@ -64,6 +68,8 @@ static const char *proc_ns_get_link(stru + + error = nd_jump_link(&ns_path); + out: ++ up_read(&task->signal->exec_update_lock); ++out_put_task: + put_task_struct(task); + return ERR_PTR(error); + } +@@ -80,11 +86,17 @@ static int proc_ns_readlink(struct dentr + if (!task) + return res; + ++ res = down_read_killable(&task->signal->exec_update_lock); ++ if (res) ++ goto out_put_task; ++ + if (ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS)) { + res = ns_get_name(name, sizeof(name), task, ns_ops); + if (res >= 0) + res = readlink_copy(buffer, buflen, name); + } ++ up_read(&task->signal->exec_update_lock); ++out_put_task: + put_task_struct(task); + return res; + } diff --git a/queue-5.10/proc-rename-proc_setattr-to-proc_nochmod_setattr.patch b/queue-5.10/proc-rename-proc_setattr-to-proc_nochmod_setattr.patch new file mode 100644 index 0000000000..e75f859a31 --- /dev/null +++ b/queue-5.10/proc-rename-proc_setattr-to-proc_nochmod_setattr.patch @@ -0,0 +1,193 @@ +From stable+bounces-277134-greg=kroah.com@vger.kernel.org Fri Jul 17 18:38:30 2026 +From: Sasha Levin +Date: Fri, 17 Jul 2026 12:38:20 -0400 +Subject: proc: rename proc_setattr to proc_nochmod_setattr +To: stable@vger.kernel.org +Cc: Christoph Hellwig , Jan Kara , Christian Brauner , Sasha Levin +Message-ID: <20260717163821.2035203-2-sashal@kernel.org> + +From: Christoph Hellwig + +[ Upstream commit 690005b0b1e6b567c88b7790e6d90d4d6c9e09cc ] + +What is currently proc_setattr is a special version added after the more +general procfs ->seattr in commit 6d76fa58b050 ("Don't allow chmod() on +the /proc// files"). Give it a name that reflects that to free the +proc_setattr name and better describe what is doing. + +Signed-off-by: Christoph Hellwig +Link: https://patch.msgid.link/20260325063711.3298685-5-hch@lst.de +Reviewed-by: Jan Kara +Signed-off-by: Christian Brauner +Stable-dep-of: 6255da28d4bb ("proc: protect ptrace_may_access() with exec_update_lock (FD links)") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + fs/proc/base.c | 22 +++++++++++----------- + fs/proc/fd.c | 4 ++-- + fs/proc/internal.h | 2 +- + fs/proc/namespaces.c | 4 ++-- + fs/proc/proc_net.c | 2 +- + 5 files changed, 17 insertions(+), 17 deletions(-) + +--- a/fs/proc/base.c ++++ b/fs/proc/base.c +@@ -720,7 +720,7 @@ static int proc_fd_access_allowed(struct + return allowed; + } + +-int proc_setattr(struct dentry *dentry, struct iattr *attr) ++int proc_nochmod_setattr(struct dentry *dentry, struct iattr *attr) + { + int error; + struct inode *inode = d_inode(dentry); +@@ -792,7 +792,7 @@ static int proc_pid_permission(struct in + + + static const struct inode_operations proc_def_inode_operations = { +- .setattr = proc_setattr, ++ .setattr = proc_nochmod_setattr, + }; + + static int proc_single_show(struct seq_file *m, void *v) +@@ -1863,7 +1863,7 @@ out: + const struct inode_operations proc_pid_link_inode_operations = { + .readlink = proc_pid_readlink, + .get_link = proc_pid_get_link, +- .setattr = proc_setattr, ++ .setattr = proc_nochmod_setattr, + }; + + +@@ -2311,7 +2311,7 @@ proc_map_files_get_link(struct dentry *d + static const struct inode_operations proc_map_files_link_inode_operations = { + .readlink = proc_pid_readlink, + .get_link = proc_map_files_get_link, +- .setattr = proc_setattr, ++ .setattr = proc_nochmod_setattr, + }; + + static struct dentry * +@@ -2390,7 +2390,7 @@ out: + static const struct inode_operations proc_map_files_inode_operations = { + .lookup = proc_map_files_lookup, + .permission = proc_fd_permission, +- .setattr = proc_setattr, ++ .setattr = proc_nochmod_setattr, + }; + + static int +@@ -2882,7 +2882,7 @@ static struct dentry *proc_##LSM##_attr_ + static const struct inode_operations proc_##LSM##_attr_dir_inode_ops = { \ + .lookup = proc_##LSM##_attr_dir_lookup, \ + .getattr = pid_getattr, \ +- .setattr = proc_setattr, \ ++ .setattr = proc_nochmod_setattr, \ + } + + #ifdef CONFIG_SECURITY_SMACK +@@ -2941,7 +2941,7 @@ static struct dentry *proc_attr_dir_look + static const struct inode_operations proc_attr_dir_inode_operations = { + .lookup = proc_attr_dir_lookup, + .getattr = pid_getattr, +- .setattr = proc_setattr, ++ .setattr = proc_nochmod_setattr, + }; + + #endif +@@ -3395,7 +3395,7 @@ static struct dentry *proc_tgid_base_loo + static const struct inode_operations proc_tgid_base_inode_operations = { + .lookup = proc_tgid_base_lookup, + .getattr = pid_getattr, +- .setattr = proc_setattr, ++ .setattr = proc_nochmod_setattr, + .permission = proc_pid_permission, + }; + +@@ -3594,7 +3594,7 @@ static int proc_tid_comm_permission(stru + } + + static const struct inode_operations proc_tid_comm_inode_operations = { +- .setattr = proc_setattr, ++ .setattr = proc_nochmod_setattr, + .permission = proc_tid_comm_permission, + }; + +@@ -3718,7 +3718,7 @@ static const struct file_operations proc + static const struct inode_operations proc_tid_base_inode_operations = { + .lookup = proc_tid_base_lookup, + .getattr = pid_getattr, +- .setattr = proc_setattr, ++ .setattr = proc_nochmod_setattr, + }; + + static struct dentry *proc_task_instantiate(struct dentry *dentry, +@@ -3913,7 +3913,7 @@ static int proc_task_getattr(const struc + static const struct inode_operations proc_task_inode_operations = { + .lookup = proc_task_lookup, + .getattr = proc_task_getattr, +- .setattr = proc_setattr, ++ .setattr = proc_nochmod_setattr, + .permission = proc_pid_permission, + }; + +--- a/fs/proc/fd.c ++++ b/fs/proc/fd.c +@@ -297,7 +297,7 @@ int proc_fd_permission(struct inode *ino + const struct inode_operations proc_fd_inode_operations = { + .lookup = proc_lookupfd, + .permission = proc_fd_permission, +- .setattr = proc_setattr, ++ .setattr = proc_nochmod_setattr, + }; + + static struct dentry *proc_fdinfo_instantiate(struct dentry *dentry, +@@ -335,7 +335,7 @@ static int proc_readfdinfo(struct file * + + const struct inode_operations proc_fdinfo_inode_operations = { + .lookup = proc_lookupfdinfo, +- .setattr = proc_setattr, ++ .setattr = proc_nochmod_setattr, + }; + + const struct file_operations proc_fdinfo_operations = { +--- a/fs/proc/internal.h ++++ b/fs/proc/internal.h +@@ -177,7 +177,7 @@ extern int proc_pid_statm(struct seq_fil + */ + extern const struct dentry_operations pid_dentry_operations; + extern int pid_getattr(const struct path *, struct kstat *, u32, unsigned int); +-extern int proc_setattr(struct dentry *, struct iattr *); ++int proc_nochmod_setattr(struct dentry *dentry, struct iattr *attr); + extern void proc_pid_evict_inode(struct proc_inode *); + extern struct inode *proc_pid_make_inode(struct super_block *, struct task_struct *, umode_t); + extern void pid_update_inode(struct task_struct *, struct inode *); +--- a/fs/proc/namespaces.c ++++ b/fs/proc/namespaces.c +@@ -92,7 +92,7 @@ static int proc_ns_readlink(struct dentr + static const struct inode_operations proc_ns_link_inode_operations = { + .readlink = proc_ns_readlink, + .get_link = proc_ns_get_link, +- .setattr = proc_setattr, ++ .setattr = proc_nochmod_setattr, + }; + + static struct dentry *proc_ns_instantiate(struct dentry *dentry, +@@ -179,5 +179,5 @@ out_no_task: + const struct inode_operations proc_ns_dir_inode_operations = { + .lookup = proc_ns_dir_lookup, + .getattr = pid_getattr, +- .setattr = proc_setattr, ++ .setattr = proc_nochmod_setattr, + }; +--- a/fs/proc/proc_net.c ++++ b/fs/proc/proc_net.c +@@ -310,7 +310,7 @@ static int proc_tgid_net_getattr(const s + const struct inode_operations proc_net_inode_operations = { + .lookup = proc_tgid_net_lookup, + .getattr = proc_tgid_net_getattr, +- .setattr = proc_setattr, ++ .setattr = proc_nochmod_setattr, + }; + + static int proc_tgid_net_readdir(struct file *file, struct dir_context *ctx) diff --git a/queue-5.10/proc-use-generic-setattr-for-proc-pid-net.patch b/queue-5.10/proc-use-generic-setattr-for-proc-pid-net.patch new file mode 100644 index 0000000000..5c6c41d786 --- /dev/null +++ b/queue-5.10/proc-use-generic-setattr-for-proc-pid-net.patch @@ -0,0 +1,46 @@ +From stable+bounces-277133-greg=kroah.com@vger.kernel.org Fri Jul 17 18:38:28 2026 +From: Sasha Levin +Date: Fri, 17 Jul 2026 12:38:19 -0400 +Subject: proc: use generic setattr() for /proc/$PID/net +To: stable@vger.kernel.org +Cc: "Thomas Weißschuh" , "Zhangjin Wu" , "Willy Tarreau" , "Christian Brauner" , "Sasha Levin" +Message-ID: <20260717163821.2035203-1-sashal@kernel.org> + +From: Thomas Weißschuh + +[ Upstream commit 18e66ae67673f2c8df6f02428798b1355691f2a9 ] + +All other files in /proc/$PID/ use proc_setattr(). + +Not using it allows the usage of chmod() on /proc/$PID/net, even on +other processes owned by the same user. +The same would probably also be true for other attributes to be changed. + +As this technically represents an ABI change it is not marked for +stable so any unlikely regressions are caught during a full release cycle. + +Fixes: e9720acd728a ("[NET]: Make /proc/net a symlink on /proc/self/net (v3)") +Signed-off-by: Thomas Weißschuh +Link: https://lore.kernel.org/lkml/d0d111ef-edae-4760-83fb-36db84278da1@t-8ch.de/ +Fixes: b4844fa0bdb4 ("selftests/nolibc: implement a few tests for various syscalls") +Tested-by: Zhangjin Wu +Signed-off-by: Willy Tarreau +Message-Id: <20230624-proc-net-setattr-v1-2-73176812adee@weissschuh.net> +Signed-off-by: Christian Brauner +Stable-dep-of: 6255da28d4bb ("proc: protect ptrace_may_access() with exec_update_lock (FD links)") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + fs/proc/proc_net.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/fs/proc/proc_net.c ++++ b/fs/proc/proc_net.c +@@ -310,6 +310,7 @@ static int proc_tgid_net_getattr(const s + const struct inode_operations proc_net_inode_operations = { + .lookup = proc_tgid_net_lookup, + .getattr = proc_tgid_net_getattr, ++ .setattr = proc_setattr, + }; + + static int proc_tgid_net_readdir(struct file *file, struct dir_context *ctx) diff --git a/queue-5.10/serial-8250_mid-disable-dma-for-selected-platforms.patch b/queue-5.10/serial-8250_mid-disable-dma-for-selected-platforms.patch new file mode 100644 index 0000000000..4caeccf273 --- /dev/null +++ b/queue-5.10/serial-8250_mid-disable-dma-for-selected-platforms.patch @@ -0,0 +1,64 @@ +From stable+bounces-277239-greg=kroah.com@vger.kernel.org Sat Jul 18 03:33:53 2026 +From: Sasha Levin +Date: Fri, 17 Jul 2026 21:33:38 -0400 +Subject: serial: 8250_mid: Disable DMA for selected platforms +To: stable@vger.kernel.org +Cc: Andy Shevchenko , micas-opensource , stable , Greg Kroah-Hartman , Sasha Levin +Message-ID: <20260718013338.2621443-2-sashal@kernel.org> + +From: Andy Shevchenko + +[ Upstream commit b1b4efea05a56c0995e4702a86d6624b4fdff32f ] + +In accordance with Errata (specification updates) +HSUART May Stop Functioning when DMA is Active. + +- Denverton document #572409, rev 3.4, DNV60 +- Ice Lake Xeon D document #714070, ICXD65 +- Snowridge document #731931, SNR44 + +For a quick fix just disable the respective callbacks during the device probe. +Depending on the future development we might remove them completely. + +Reported-by: micas-opensource +Closes: https://lore.kernel.org/linux-serial/20250625031409.2404219-1-opensource@ruijie.com.cn/ +Fixes: 6ede6dcd87aa ("serial: 8250_mid: add support for DMA engine handling from UART MMIO") +Cc: stable +Signed-off-by: Andy Shevchenko +Link: https://patch.msgid.link/20260626094937.561776-1-andriy.shevchenko@linux.intel.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/tty/serial/8250/8250_mid.c | 13 +++++++++++-- + 1 file changed, 11 insertions(+), 2 deletions(-) + +--- a/drivers/tty/serial/8250/8250_mid.c ++++ b/drivers/tty/serial/8250/8250_mid.c +@@ -10,6 +10,7 @@ + #include + #include + #include ++#include + + #include + +@@ -371,8 +372,16 @@ static const struct mid8250_board dnv_bo + .freq = 133333333, + .base_baud = 115200, + .bar = 1, +- .setup = dnv_setup, +- .exit = dnv_exit, ++ /* ++ * Errata: ++ * HSUART May Stop Functioning when DMA is Active. ++ * ++ * - Denverton document #572409, rev 3.4, DNV60 ++ * - Ice Lake Xeon D document #714070, ICXD65 ++ * - Snowridge document #731931, SNR44 ++ */ ++ .setup = PTR_IF(false, dnv_setup), ++ .exit = PTR_IF(false, dnv_exit), + }; + + #define MID_DEVICE(id, board) { PCI_VDEVICE(INTEL, id), (kernel_ulong_t)&board } diff --git a/queue-5.10/serial-8250_mid-remove-8250_pci-usage.patch b/queue-5.10/serial-8250_mid-remove-8250_pci-usage.patch new file mode 100644 index 0000000000..1625fe5816 --- /dev/null +++ b/queue-5.10/serial-8250_mid-remove-8250_pci-usage.patch @@ -0,0 +1,120 @@ +From stable+bounces-277238-greg=kroah.com@vger.kernel.org Sat Jul 18 03:33:50 2026 +From: Sasha Levin +Date: Fri, 17 Jul 2026 21:33:37 -0400 +Subject: serial: 8250_mid: Remove 8250_pci usage +To: stable@vger.kernel.org +Cc: "Ilpo Järvinen" , "Greg Kroah-Hartman" , "Sasha Levin" +Message-ID: <20260718013338.2621443-1-sashal@kernel.org> + +From: Ilpo Järvinen + +[ Upstream commit a136abd7e7abe0f1247f8ffde6cc7c8ab09f985b ] + +8250_mid uses FL_*BASE* from linux/8250_pci.h and nothing else. The +code can be simplified by directly defining BARs within the driver +instead. + +Signed-off-by: Ilpo Järvinen +Link: https://lore.kernel.org/r/20230915094336.13278-1-ilpo.jarvinen@linux.intel.com +Signed-off-by: Greg Kroah-Hartman +Stable-dep-of: b1b4efea05a5 ("serial: 8250_mid: Disable DMA for selected platforms") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/tty/serial/8250/8250_mid.c | 18 +++++++----------- + 1 file changed, 7 insertions(+), 11 deletions(-) + +--- a/drivers/tty/serial/8250/8250_mid.c ++++ b/drivers/tty/serial/8250/8250_mid.c +@@ -12,7 +12,6 @@ + #include + + #include +-#include + + #include "8250.h" + +@@ -32,9 +31,9 @@ + struct mid8250; + + struct mid8250_board { +- unsigned int flags; + unsigned long freq; + unsigned int base_baud; ++ unsigned int bar; + int (*setup)(struct mid8250 *, struct uart_port *p); + void (*exit)(struct mid8250 *); + }; +@@ -169,7 +168,6 @@ static int dnv_setup(struct mid8250 *mid + { + struct hsu_dma_chip *chip = &mid->dma_chip; + struct pci_dev *pdev = to_pci_dev(p->dev); +- unsigned int bar = FL_GET_BASE(mid->board->flags); + int ret; + + pci_set_master(pdev); +@@ -183,7 +181,7 @@ static int dnv_setup(struct mid8250 *mid + chip->dev = &pdev->dev; + chip->irq = pci_irq_vector(pdev, 0); + chip->regs = p->membase; +- chip->length = pci_resource_len(pdev, bar); ++ chip->length = pci_resource_len(pdev, mid->board->bar); + chip->offset = DNV_DMA_CHAN_OFFSET; + + /* Falling back to PIO mode if DMA probing fails */ +@@ -292,7 +290,6 @@ static int mid8250_probe(struct pci_dev + { + struct uart_8250_port uart; + struct mid8250 *mid; +- unsigned int bar; + int ret; + + ret = pcim_enable_device(pdev); +@@ -304,7 +301,6 @@ static int mid8250_probe(struct pci_dev + return -ENOMEM; + + mid->board = (struct mid8250_board *)id->driver_data; +- bar = FL_GET_BASE(mid->board->flags); + + memset(&uart, 0, sizeof(struct uart_8250_port)); + +@@ -317,8 +313,8 @@ static int mid8250_probe(struct pci_dev + uart.port.flags = UPF_SHARE_IRQ | UPF_FIXED_PORT | UPF_FIXED_TYPE; + uart.port.set_termios = mid8250_set_termios; + +- uart.port.mapbase = pci_resource_start(pdev, bar); +- uart.port.membase = pcim_iomap(pdev, bar, 0); ++ uart.port.mapbase = pci_resource_start(pdev, mid->board->bar); ++ uart.port.membase = pcim_iomap(pdev, mid->board->bar, 0); + if (!uart.port.membase) + return -ENOMEM; + +@@ -356,25 +352,25 @@ static void mid8250_remove(struct pci_de + } + + static const struct mid8250_board pnw_board = { +- .flags = FL_BASE0, + .freq = 50000000, + .base_baud = 115200, ++ .bar = 0, + .setup = pnw_setup, + .exit = pnw_exit, + }; + + static const struct mid8250_board tng_board = { +- .flags = FL_BASE0, + .freq = 38400000, + .base_baud = 1843200, ++ .bar = 0, + .setup = tng_setup, + .exit = tng_exit, + }; + + static const struct mid8250_board dnv_board = { +- .flags = FL_BASE1, + .freq = 133333333, + .base_baud = 115200, ++ .bar = 1, + .setup = dnv_setup, + .exit = dnv_exit, + }; diff --git a/queue-5.10/series b/queue-5.10/series index 3c4d092511..47b26c7a6c 100644 --- a/queue-5.10/series +++ b/queue-5.10/series @@ -578,3 +578,107 @@ crypto-amcc-fix-incorrect-kernel-doc-comment-syntax-in-files.patch crypto-crypto4xx-remove-ahash-related-code.patch crypto-crypto4xx-remove-insecure-and-unused-rng_alg.patch batman-adv-clean-untagged-vlan-on-netdev-registration-failure.patch +acpi-nfit-core-fix-acpi_nfit_init-error-cleanup.patch +iio-imu-adis-add-irqf_no_thread-to-non-fifo-trigger-irq.patch +iio-hid-sensor-rotation-fix-stale-or-zero-output-when-reading-raw-values.patch +iio-imu-inv_icm42600-make-timestamp-module-chip-independent.patch +iio-move-inv_icm42600-timestamp-module-in-common.patch +iio-make-invensense-timestamp-module-generic.patch +iio-imu-inv_mpu6050-use-the-common-inv_sensors-timestamp-module.patch +iio-invensense-remove-redundant-initialization-of-variable-period.patch +iio-invensense-fix-timestamp-glitches-when-switching-frequency.patch +iio-imu-inv_icm42600-stabilized-timestamp-in-interrupt.patch +iio-imu-inv_icm42600-fix-timestamping-by-limiting-fifo-reading.patch +bitops-make-bytes_to_bits-treewide-available.patch +iio-common-st_sensors-honour-channel-endianness-in-read_axis_data.patch +alsa-aoa-check-snd_ctl_new1-return-value.patch +bluetooth-btintel-fix-offset-calculation-boot-address-parameter.patch +bluetooth-btintel-check-firmware-version-before-download.patch +bluetooth-btusb-fix-use-after-free-on-marvell-probe-failure.patch +bluetooth-btusb-fix-wakeup-source-leak-on-probe-failure.patch +vfio-pci-release-the-vga-arbiter-client-on-register_device-failure.patch +binder-fix-uaf-in-binder_free_transaction.patch +pci-altera-fix-resource-leaks-on-probe-failure.patch +media-atomisp-replace-boolean-comparison-of-values-with-bool-variables.patch +media-staging-media-atomisp-fix-sh_css.c-brace-coding-style-issues.patch +media-staging-media-atomisp-fix-the-rest-of-sh_css.c-brace-issues.patch +media-staging-media-atomisp-replace-if-else-clause-with-a-ternary.patch +media-staging-media-atomisp-fix-alignment-and-line-length-issues.patch +staging-media-atomisp-reduce-load_primary_binaries-stack-usage.patch +cifs-create-a-new-shared-file-holding-smb2-pdu-definitions.patch +cifs-remove-check-of-list-iterator-against-head-past-the-loop-body.patch +smb2-small-refactor-in-smb2_check_message.patch +cifs-remove-unused-server-parameter-from-calc_smb_size.patch +smb-client-restrict-implied-bcc-exemption-to-responses-without-data-area.patch +pci-imx6-fix-imx6sx_gpr12_pcie_test_powerdown-handling.patch +staging-rtl8723bs-split-too-long-line.patch +staging-rtl8723bs-remove-commented-out-rt_assert-occurrences.patch +staging-rtl8723bs-remove-all-5ghz-network-types.patch +staging-rtl8723bs-remove-5ghz-code-related-to-channel-plan-definition.patch +staging-rtl8723bs-remove-5ghz-code-blocks.patch +staging-rtl8723bs-remove-commented-out-condition.patch +staging-rtl8723bs-clean-up-comparsions-to-null.patch +staging-rtl8723bs-fix-wep-length-underflow-and-oob-read-in-onauth.patch +staging-rtl8723bs-fix-space-issues.patch +staging-rtl8723bs-fix-heap-buffer-overflow-in-rtw_cfg80211_set_wpa_ie.patch +staging-rtl8723bs-fix-oob-reads-in-ie-loops-in-issue_assocreq-and-join_cmd_hdl.patch +pci-controller-use-dev_fwnode-instead-of-of_fwnode_handle.patch +pci-mediatek-convert-bool-to-single-quirks-entry-and-bitmap.patch +pci-mediatek-fix-irq-domain-leak-when-port-fails-to-enable.patch +staging-rtl8723bs-remove-dbg_871x-log-argument.patch +crypto-qat-fix-vf2pf-work-teardown-race-in-adf_disable_sriov.patch +pci-prevent-resource-tree-corruption-when-bar-resize-fails.patch +pci-free-saved-list-without-holding-pci_bus_sem.patch +pci-fix-restoring-bars-on-bar-resize-rollback-path.patch +pci-add-kerneldoc-for-pci_resize_resource.patch +pci-move-resizable-bar-code-to-rebar.c.patch +pci-skip-resizable-bar-restore-on-read-error.patch +coresight-etb10-restore-atomic_t-for-shared-reading-state.patch +netfilter-ebtables-use-vmalloc_array-to-improve-code.patch +netfilter-ebtables-zero-chainstack-array.patch +bluetooth-l2cap-fix-not-tracking-outstanding-tx-ident.patch +bluetooth-l2cap-fix-deadlock-in-l2cap_conn_del.patch +bluetooth-l2cap-cancel-pending_rx_work-before-taking-conn-lock.patch +smb-client-fix-next-buffer-leak-in-receive_encrypted_standard.patch +smb-client-mask-server-provided-mode-to-07777-in-modefromsid.patch +smb-client-use-unaligned-reads-in-parse_posix_ctxt.patch +smb-client-harden-posix-sid-length-parsing.patch +writeback-fix-race-between-cgroup_writeback_umount-and-inode_switch_wbs.patch +x.509-fix-validation-of-asn.1-certificate-header.patch +proc-use-generic-setattr-for-proc-pid-net.patch +proc-rename-proc_setattr-to-proc_nochmod_setattr.patch +proc-protect-ptrace_may_access-with-exec_update_lock-fd-links.patch +hid-add-haptics-page-defines.patch +hid-multitouch-fix-out-of-bounds-bit-access-on-mt_io_flags.patch +cpufreq-intel_pstate-sync-policy-cur-during-cpu-offline.patch +proc-protect-ptrace_may_access-with-exec_update_lock-part-1.patch +hid-appleir-fix-uaf-on-pending-key_up_timer-in-remove.patch +serial-8250_mid-remove-8250_pci-usage.patch +serial-8250_mid-disable-dma-for-selected-platforms.patch +xfs-reflect-sb-features-in-xfs_mount.patch +xfs-fix-unreachable-bigtime-check-in-dquot-flush-validation.patch +xfs-use-null-daddr-for-unset-first-bad-log-block.patch +hfs-hfsplus-prevent-getting-negative-values-of-offset-length.patch +hfs-hfsplus-fix-u32-overflow-in-check_and_correct_requested_length.patch +usb-gadget-function-simplify-diagnostic-messaging-in-printer.patch +usb-gadget-f_printer-take-kref-only-for-successful-open.patch +usb-free-iso-schedules-on-failed-submit.patch +usb-iowarrior-remove-inherent-race-with-minor-number.patch +usb-serial-digi_acceleport-fix-write-buffer-corruption.patch +drm-i2c-sil164-drop-no-op-remove-function.patch +leds-lm3697-remove-duplicated-error-reporting-in-.remove.patch +leds-lm3601x-improve-error-reporting-for-problems-during-.remove.patch +gpio-pca953x-make-platform-teardown-callback-return-void.patch +usb-typec-ucsi-ccg-fix-use-after-free-of-ucsi-on-remove.patch +usb-atm-ueagle-atm-wait-for-pre-firmware-load-in-.disconnect.patch +usb-typec-tcpm-fix-vdm-type-for-enter-mode-commands.patch +usb-gadget-f_fs-initialize-reset_work-at-allocation-time.patch +crypto-atmel-sha204a-mark-of-related-data-as-maybe-unused.patch +crypto-atmel-drop-explicit-initialization-of-struct-i2c_device_id-driver_data-to-0.patch +crypto-atmel-sha204a-drop-hwrng-quality-reduction-for-atsha204a.patch +usb-gadget-f_fs-tie-read_buffer-lifetime-to-ffs_epfile.patch +btrfs-do-not-trim-a-device-which-is-not-writeable.patch +crypto-qat-fix-restarting-state-leak-on-allocation-failure.patch +crypto-qat-validate-rsa-crt-component-lengths.patch +audit-add-audit_log_nf_skb-helper-function.patch +audit-fix-potential-integer-overflow-in-audit_log_n_hex.patch diff --git a/queue-5.10/smb-client-fix-next-buffer-leak-in-receive_encrypted_standard.patch b/queue-5.10/smb-client-fix-next-buffer-leak-in-receive_encrypted_standard.patch new file mode 100644 index 0000000000..3a808ce427 --- /dev/null +++ b/queue-5.10/smb-client-fix-next-buffer-leak-in-receive_encrypted_standard.patch @@ -0,0 +1,56 @@ +From stable+bounces-276753-greg=kroah.com@vger.kernel.org Thu Jul 16 18:51:29 2026 +From: Sasha Levin +Date: Thu, 16 Jul 2026 11:36:57 -0400 +Subject: smb: client: Fix next buffer leak in receive_encrypted_standard() +To: stable@vger.kernel.org +Cc: Haoxiang Li , Steve French , Sasha Levin +Message-ID: <20260716153657.582978-2-sashal@kernel.org> + +From: Haoxiang Li + +[ Upstream commit 1c6267a1d5cf4c73b656f8181b310cbbb3e4767b ] + +receive_encrypted_standard() allocates next_buffer before checking +whether the number of compound PDUs already reached MAX_COMPOUND. If +the limit check fails, the function returns immediately and the newly +allocated next_buffer is not assigned to server->smallbuf/server->bigbuf, +making it leaked. + +Move the MAX_COMPOUND check before allocating next_buffer. + +Fixes: b24df3e30cbf ("cifs: update receive_encrypted_standard to handle compounded responses") +Cc: stable@vger.kernel.org +Signed-off-by: Haoxiang Li +Signed-off-by: Steve French +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + fs/cifs/smb2ops.c | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +--- a/fs/cifs/smb2ops.c ++++ b/fs/cifs/smb2ops.c +@@ -4961,6 +4961,12 @@ receive_encrypted_standard(struct TCP_Se + one_more: + shdr = (struct smb2_hdr *)buf; + next_cmd = le32_to_cpu(shdr->NextCommand); ++ ++ if (*num_mids >= MAX_COMPOUND) { ++ cifs_server_dbg(VFS, "too many PDUs in compound\n"); ++ return -1; ++ } ++ + if (next_cmd) { + if (WARN_ON_ONCE(next_cmd > pdu_length)) + return -1; +@@ -4984,10 +4990,6 @@ one_more: + mid_entry->resp_buf_size = server->pdu_size; + } + +- if (*num_mids >= MAX_COMPOUND) { +- cifs_server_dbg(VFS, "too many PDUs in compound\n"); +- return -1; +- } + bufs[*num_mids] = buf; + mids[(*num_mids)++] = mid_entry; + diff --git a/queue-5.10/smb-client-harden-posix-sid-length-parsing.patch b/queue-5.10/smb-client-harden-posix-sid-length-parsing.patch new file mode 100644 index 0000000000..0fccdda34f --- /dev/null +++ b/queue-5.10/smb-client-harden-posix-sid-length-parsing.patch @@ -0,0 +1,44 @@ +From stable+bounces-276773-greg=kroah.com@vger.kernel.org Thu Jul 16 18:32:41 2026 +From: Sasha Levin +Date: Thu, 16 Jul 2026 12:28:12 -0400 +Subject: smb: client: harden POSIX SID length parsing +To: stable@vger.kernel.org +Cc: Zihan Xi , Yuan Tan , Yifan Wu , Juefei Pu , Xin Liu , Ren Wei , Steve French , Sasha Levin +Message-ID: <20260716162812.635414-1-sashal@kernel.org> + +From: Zihan Xi + +[ Upstream commit 7ad2bcf2441430bb2e918fb3ef9a90d775a6e422 ] + +posix_info_sid_size() reads sid[1] to obtain the subauthority count, +but its existing boundary check still accepts buffers with only one +remaining byte. Require two bytes before reading sid[1] so all client +paths that reuse the helper reject truncated POSIX SIDs safely. + +Fixes: 349e13ad30b4 ("cifs: add smb2 POSIX info level") +Cc: stable@vger.kernel.org +Reported-by: Yuan Tan +Reported-by: Yifan Wu +Reported-by: Juefei Pu +Reported-by: Xin Liu +Assisted-by: Codex:gpt-5.4 +Signed-off-by: Zihan Xi +Signed-off-by: Ren Wei +Signed-off-by: Steve French +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + fs/cifs/smb2pdu.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/fs/cifs/smb2pdu.c ++++ b/fs/cifs/smb2pdu.c +@@ -4518,7 +4518,7 @@ int posix_info_sid_size(const void *beg, + size_t subauth; + int total; + +- if (beg + 1 > end) ++ if (beg + 2 > end) + return -1; + + subauth = *(u8 *)(beg+1); diff --git a/queue-5.10/smb-client-mask-server-provided-mode-to-07777-in-modefromsid.patch b/queue-5.10/smb-client-mask-server-provided-mode-to-07777-in-modefromsid.patch new file mode 100644 index 0000000000..4bc27f51ac --- /dev/null +++ b/queue-5.10/smb-client-mask-server-provided-mode-to-07777-in-modefromsid.patch @@ -0,0 +1,38 @@ +From stable+bounces-276771-greg=kroah.com@vger.kernel.org Thu Jul 16 19:13:20 2026 +From: Sasha Levin +Date: Thu, 16 Jul 2026 12:28:08 -0400 +Subject: smb: client: mask server-provided mode to 07777 in modefromsid +To: stable@vger.kernel.org +Cc: Norbert Manthey , Steve French , Sasha Levin +Message-ID: <20260716162808.635328-1-sashal@kernel.org> + +From: Norbert Manthey + +[ Upstream commit e3d9c7160d483fc8f9e225aafad8ecbbc43f3151 ] + +When modefromsid is active, parse_dacl() applies the server-provided +sub_auth[2] value from the NFS mode SID to cf_mode without masking to +07777. Apply the correct masking, same as in the read path. + +Fixes: e2f8fbfb8d09c ("cifs: get mode bits from special sid on stat") +Signed-off-by: Norbert Manthey +Assisted-by: Kiro:claude-opus-4.6 +Cc: stable@vger.kernel.org +Signed-off-by: Steve French +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + fs/cifs/cifsacl.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/fs/cifs/cifsacl.c ++++ b/fs/cifs/cifsacl.c +@@ -767,7 +767,7 @@ static void parse_dacl(struct cifs_acl * + */ + fattr->cf_mode &= ~07777; + fattr->cf_mode |= +- le32_to_cpu(ppace[i]->sid.sub_auth[2]); ++ le32_to_cpu(ppace[i]->sid.sub_auth[2]) & 07777; + break; + } else if (compare_sids(&(ppace[i]->sid), pownersid) == 0) + access_flags_to_mode(ppace[i]->access_req, diff --git a/queue-5.10/smb-client-restrict-implied-bcc-exemption-to-responses-without-data-area.patch b/queue-5.10/smb-client-restrict-implied-bcc-exemption-to-responses-without-data-area.patch new file mode 100644 index 0000000000..02c68ac191 --- /dev/null +++ b/queue-5.10/smb-client-restrict-implied-bcc-exemption-to-responses-without-data-area.patch @@ -0,0 +1,206 @@ +From stable+bounces-274573-greg=kroah.com@vger.kernel.org Wed Jul 15 00:04:23 2026 +From: Sasha Levin +Date: Tue, 14 Jul 2026 18:04:05 -0400 +Subject: smb: client: restrict implied bcc[0] exemption to responses without data area +To: stable@vger.kernel.org +Cc: Shoichiro Miyamoto , Steve French , Sasha Levin +Message-ID: <20260714220405.3333589-5-sashal@kernel.org> + +From: Shoichiro Miyamoto + +[ Upstream commit 53b7c271f06be4dd5cfc8c6ef552a8355c891a7f ] + +smb2_check_message() has a long-standing quirk that accepts a response +whose calculated length is one byte larger than the bytes actually +received ("server can return one byte more due to implied bcc[0]"). +This was introduced to accommodate servers that omit the trailing bcc[0] +overlap byte when no data area is present. + +However, the exemption is applied unconditionally, regardless of whether +the command actually carries a data area (has_smb2_data_area[]). When a +response with a data area is subject to the +1 exemption, the reported +data can extend one byte beyond the bytes actually received, yet +smb2_check_message() still accepts it. The subsequent decoder then reads +past the end of the receive buffer. This is reachable during NEGOTIATE +and SESSION_SETUP, before the session is established. + +The resulting out-of-bounds reads are visible under KASAN when mounting +against a non-conforming server; both the SPNEGO/negTokenInit and the +NTLMSSP challenge decoders are affected: + + BUG: KASAN: slab-out-of-bounds in asn1_ber_decoder+0x16a7/0x1b00 + Read of size 1 at addr ffff8880084d67c0 by task mount.cifs/81 + CPU: 1 UID: 0 PID: 81 Comm: mount.cifs Not tainted 7.1.0-rc6 #1 + Call Trace: + + dump_stack_lvl+0x4e/0x70 + print_report+0x157/0x4c9 + kasan_report+0xce/0x100 + asn1_ber_decoder+0x16a7/0x1b00 + decode_negTokenInit+0x19/0x30 + SMB2_negotiate+0x31d9/0x4c90 + cifs_negotiate_protocol+0x1f2/0x3f0 + cifs_get_smb_ses+0x93f/0x17e0 + cifs_mount_get_session+0x7f/0x3a0 + cifs_mount+0xb4/0xcf0 + cifs_smb3_do_mount+0x23a/0x1500 + smb3_get_tree+0x3b0/0x630 + vfs_get_tree+0x82/0x2d0 + fc_mount+0x10/0x1b0 + path_mount+0x50d/0x1de0 + __x64_sys_mount+0x20b/0x270 + do_syscall_64+0xee/0x590 + entry_SYSCALL_64_after_hwframe+0x77/0x7f + + Allocated by task 85: + kmem_cache_alloc_noprof+0x106/0x380 + mempool_alloc_noprof+0x116/0x1e0 + cifs_small_buf_get+0x31/0x80 + allocate_buffers+0x10d/0x2b0 + cifs_demultiplex_thread+0x1d5/0x1d50 + kthread+0x2c6/0x390 + ret_from_fork+0x36e/0x5a0 + ret_from_fork_asm+0x1a/0x30 + The buggy address is located 0 bytes to the right of + allocated 448-byte region [ffff8880084d6600, ffff8880084d67c0) + which belongs to the cache cifs_small_rq of size 448 + + BUG: KASAN: slab-out-of-bounds in kmemdup_noprof+0x36/0x50 + Read of size 329 at addr ffff88800726c678 by task mount.cifs/89 + CPU: 0 UID: 0 PID: 89 Comm: mount.cifs Tainted: G B 7.1.0-rc6 #1 + Call Trace: + + dump_stack_lvl+0x4e/0x70 + print_report+0x157/0x4c9 + kasan_report+0xce/0x100 + kasan_check_range+0x10f/0x1e0 + __asan_memcpy+0x23/0x60 + kmemdup_noprof+0x36/0x50 + decode_ntlmssp_challenge+0x457/0x680 + SMB2_sess_auth_rawntlmssp_negotiate+0x6f0/0xcb0 + SMB2_sess_setup+0x219/0x4f0 + cifs_setup_session+0x248/0xaf0 + cifs_get_smb_ses+0xf79/0x17e0 + cifs_mount_get_session+0x7f/0x3a0 + cifs_mount+0xb4/0xcf0 + cifs_smb3_do_mount+0x23a/0x1500 + smb3_get_tree+0x3b0/0x630 + vfs_get_tree+0x82/0x2d0 + fc_mount+0x10/0x1b0 + path_mount+0x50d/0x1de0 + __x64_sys_mount+0x20b/0x270 + do_syscall_64+0xee/0x590 + entry_SYSCALL_64_after_hwframe+0x77/0x7f + + Allocated by task 93: + kmem_cache_alloc_noprof+0x106/0x380 + mempool_alloc_noprof+0x116/0x1e0 + cifs_small_buf_get+0x31/0x80 + allocate_buffers+0x10d/0x2b0 + cifs_demultiplex_thread+0x1d5/0x1d50 + kthread+0x2c6/0x390 + ret_from_fork+0x36e/0x5a0 + ret_from_fork_asm+0x1a/0x30 + The buggy address is located 120 bytes inside of + allocated 448-byte region [ffff88800726c600, ffff88800726c7c0) + which belongs to the cache cifs_small_rq of size 448 + +Restrict the +1 exemption to responses that have no data area, so that +it still covers the bcc[0] omission it was meant for. When a data area +is present, the +1 discrepancy instead means the reported data length +overruns the received buffer, so the response must be rejected. + +Fixes: 093b2bdad322 ("CIFS: Make demultiplex_thread work with SMB2 code") +Cc: stable@vger.kernel.org +Signed-off-by: Shoichiro Miyamoto +Signed-off-by: Steve French +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + fs/cifs/smb2misc.c | 32 ++++++++++++++++++++++++++------ + 1 file changed, 26 insertions(+), 6 deletions(-) + +--- a/fs/cifs/smb2misc.c ++++ b/fs/cifs/smb2misc.c +@@ -30,6 +30,8 @@ + #include "smb2glob.h" + #include "nterr.h" + ++static unsigned int __smb2_calc_size(void *buf, bool *have_data); ++ + static int + check_smb2_hdr(struct smb2_hdr *shdr, __u64 mid) + { +@@ -145,6 +147,7 @@ smb2_check_message(char *buf, unsigned i + int command; + __u32 calc_len; /* calculated length */ + __u64 mid; ++ bool have_data; + + /* + * Add function to do table lookup of StructureSize by command +@@ -225,7 +228,8 @@ smb2_check_message(char *buf, unsigned i + } + } + +- calc_len = smb2_calc_size(buf); ++ have_data = false; ++ calc_len = __smb2_calc_size(buf, &have_data); + + /* For SMB2_IOCTL, OutputOffset and OutputLength are optional, so might + * be 0, and not a real miscalculation */ +@@ -243,8 +247,13 @@ smb2_check_message(char *buf, unsigned i + /* Windows 7 server returns 24 bytes more */ + if (calc_len + 24 == len && command == SMB2_OPLOCK_BREAK_HE) + return 0; +- /* server can return one byte more due to implied bcc[0] */ +- if (calc_len == len + 1) ++ /* ++ * Server can return one byte more due to implied bcc[0]. ++ * Allow it only when there is no data area; if data_length > 0 ++ * the +1 gap indicates an overreported data length rather than ++ * the bcc[0] omission. ++ */ ++ if (calc_len == len + 1 && !have_data) + return 0; + + /* +@@ -405,14 +414,17 @@ smb2_get_data_area_len(int *off, int *le + /* + * Calculate the size of the SMB message based on the fixed header + * portion, the number of word parameters and the data portion of the message. ++ * If have_data is non-NULL, it is set to true when a non-empty data area was ++ * found (data_length > 0), allowing callers to distinguish the implied bcc[0] ++ * case (no data area) from an overreported data length. + */ +-unsigned int +-smb2_calc_size(void *buf) ++static unsigned int ++__smb2_calc_size(void *buf, bool *have_data) + { + struct smb2_pdu *pdu = (struct smb2_pdu *)buf; + struct smb2_hdr *shdr = &pdu->hdr; + int offset; /* the offset from the beginning of SMB to data area */ +- int data_length; /* the length of the variable length data area */ ++ int data_length = 0; /* the length of the variable length data area */ + /* Structure Size has already been checked to make sure it is 64 */ + int len = le16_to_cpu(shdr->StructureSize); + +@@ -445,9 +457,17 @@ smb2_calc_size(void *buf) + } + calc_size_exit: + cifs_dbg(FYI, "SMB2 len %d\n", len); ++ if (have_data) ++ *have_data = (data_length > 0); + return len; + } + ++unsigned int ++smb2_calc_size(void *buf) ++{ ++ return __smb2_calc_size(buf, NULL); ++} ++ + /* Note: caller must free return buffer */ + __le16 * + cifs_convert_path_to_utf16(const char *from, struct cifs_sb_info *cifs_sb) diff --git a/queue-5.10/smb-client-use-unaligned-reads-in-parse_posix_ctxt.patch b/queue-5.10/smb-client-use-unaligned-reads-in-parse_posix_ctxt.patch new file mode 100644 index 0000000000..806d1300c6 --- /dev/null +++ b/queue-5.10/smb-client-use-unaligned-reads-in-parse_posix_ctxt.patch @@ -0,0 +1,42 @@ +From stable+bounces-276772-greg=kroah.com@vger.kernel.org Thu Jul 16 18:33:52 2026 +From: Sasha Levin +Date: Thu, 16 Jul 2026 12:28:10 -0400 +Subject: smb: client: use unaligned reads in parse_posix_ctxt() +To: stable@vger.kernel.org +Cc: Zihan Xi , Ren Wei , Steve French , Sasha Levin +Message-ID: <20260716162810.635369-1-sashal@kernel.org> + +From: Zihan Xi + +[ Upstream commit b86467cd2691192ad4809a5a6e922fc24b8e9839 ] + +The server controls create-context DataOffset, so the POSIX context data +pointer may be misaligned on strict-alignment architectures. Use +get_unaligned_le32() when reading nlink, reparse_tag, and mode. + +Fixes: 69dda3059e7a ("cifs: add SMB2_open() arg to return POSIX data") +Cc: stable@vger.kernel.org +Signed-off-by: Zihan Xi +Signed-off-by: Ren Wei +Signed-off-by: Steve French +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + fs/cifs/smb2pdu.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/fs/cifs/smb2pdu.c ++++ b/fs/cifs/smb2pdu.c +@@ -1973,9 +1973,9 @@ parse_posix_ctxt(struct create_context * + + memset(posix, 0, sizeof(*posix)); + +- posix->nlink = le32_to_cpu(*(__le32 *)(beg + 0)); +- posix->reparse_tag = le32_to_cpu(*(__le32 *)(beg + 4)); +- posix->mode = le32_to_cpu(*(__le32 *)(beg + 8)); ++ posix->nlink = get_unaligned_le32(beg); ++ posix->reparse_tag = get_unaligned_le32(beg + 4); ++ posix->mode = get_unaligned_le32(beg + 8); + + sid = beg + 12; + sid_len = posix_info_sid_size(sid, end); diff --git a/queue-5.10/smb2-small-refactor-in-smb2_check_message.patch b/queue-5.10/smb2-small-refactor-in-smb2_check_message.patch new file mode 100644 index 0000000000..06ffdb3b8d --- /dev/null +++ b/queue-5.10/smb2-small-refactor-in-smb2_check_message.patch @@ -0,0 +1,168 @@ +From stable+bounces-274569-greg=kroah.com@vger.kernel.org Wed Jul 15 00:04:16 2026 +From: Sasha Levin +Date: Tue, 14 Jul 2026 18:04:03 -0400 +Subject: smb2: small refactor in smb2_check_message() +To: stable@vger.kernel.org +Cc: Enzo Matsumiya , Steve French , Sasha Levin +Message-ID: <20260714220405.3333589-3-sashal@kernel.org> + +From: Enzo Matsumiya + +[ Upstream commit da3847894fddc27ca95d5ac0012f444a77a5e0c3 ] + +If the command is SMB2_IOCTL, OutputLength and OutputContext are +optional and can be zero, so return early and skip calculated length +check. + +Move the mismatched length message to the end of the check, to avoid +unnecessary logs when the check was not a real miscalculation. + +Also change the pr_warn_once() to a pr_warn() so we're sure to get a +log for the real mismatches. + +Signed-off-by: Enzo Matsumiya +Signed-off-by: Steve French +Stable-dep-of: 53b7c271f06b ("smb: client: restrict implied bcc[0] exemption to responses without data area") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + fs/cifs/connect.c | 13 ++++++------- + fs/cifs/smb2misc.c | 47 ++++++++++++++++++++++++++++------------------- + 2 files changed, 34 insertions(+), 26 deletions(-) + +--- a/fs/cifs/connect.c ++++ b/fs/cifs/connect.c +@@ -1012,19 +1012,18 @@ int + cifs_handle_standard(struct TCP_Server_Info *server, struct mid_q_entry *mid) + { + char *buf = server->large_buf ? server->bigbuf : server->smallbuf; +- int length; ++ int rc; + + /* + * We know that we received enough to get to the MID as we + * checked the pdu_length earlier. Now check to see +- * if the rest of the header is OK. We borrow the length +- * var for the rest of the loop to avoid a new stack var. ++ * if the rest of the header is OK. + * + * 48 bytes is enough to display the header and a little bit + * into the payload for debugging purposes. + */ +- length = server->ops->check_message(buf, server->total_read, server); +- if (length != 0) ++ rc = server->ops->check_message(buf, server->total_read, server); ++ if (rc) + cifs_dump_mem("Bad SMB: ", buf, + min_t(unsigned int, server->total_read, 48)); + +@@ -1039,9 +1038,9 @@ cifs_handle_standard(struct TCP_Server_I + return -1; + + if (!mid) +- return length; ++ return rc; + +- handle_mid(mid, server, buf, length); ++ handle_mid(mid, server, buf, rc); + return 0; + } + +--- a/fs/cifs/smb2misc.c ++++ b/fs/cifs/smb2misc.c +@@ -136,15 +136,15 @@ static __u32 get_neg_ctxt_len(struct smb + } + + int +-smb2_check_message(char *buf, unsigned int len, struct TCP_Server_Info *srvr) ++smb2_check_message(char *buf, unsigned int len, struct TCP_Server_Info *server) + { + struct smb2_hdr *shdr = (struct smb2_hdr *)buf; + struct smb2_pdu *pdu = (struct smb2_pdu *)shdr; +- __u64 mid; +- __u32 clc_len; /* calculated length */ +- int command; +- int pdu_size = sizeof(struct smb2_pdu); + int hdr_size = sizeof(struct smb2_hdr); ++ int pdu_size = sizeof(struct smb2_pdu); ++ int command; ++ __u32 calc_len; /* calculated length */ ++ __u64 mid; + + /* + * Add function to do table lookup of StructureSize by command +@@ -158,7 +158,7 @@ smb2_check_message(char *buf, unsigned i + + /* decrypt frame now that it is completely read in */ + spin_lock(&cifs_tcp_ses_lock); +- list_for_each_entry(iter, &srvr->smb_ses_list, smb_ses_list) { ++ list_for_each_entry(iter, &server->smb_ses_list, smb_ses_list) { + if (iter->Suid == le64_to_cpu(thdr->SessionId)) { + ses = iter; + break; +@@ -225,30 +225,33 @@ smb2_check_message(char *buf, unsigned i + } + } + +- clc_len = smb2_calc_size(buf, srvr); ++ calc_len = smb2_calc_size(buf, server); ++ ++ /* For SMB2_IOCTL, OutputOffset and OutputLength are optional, so might ++ * be 0, and not a real miscalculation */ ++ if (command == SMB2_IOCTL_HE && calc_len == 0) ++ return 0; + +- if (shdr->Command == SMB2_NEGOTIATE) +- clc_len += get_neg_ctxt_len(shdr, len, clc_len); ++ if (command == SMB2_NEGOTIATE_HE) ++ calc_len += get_neg_ctxt_len(shdr, len, calc_len); + +- if (len != clc_len) { +- cifs_dbg(FYI, "Calculated size %u length %u mismatch mid %llu\n", +- clc_len, len, mid); ++ if (len != calc_len) { + /* create failed on symlink */ + if (command == SMB2_CREATE_HE && + shdr->Status == STATUS_STOPPED_ON_SYMLINK) + return 0; + /* Windows 7 server returns 24 bytes more */ +- if (clc_len + 24 == len && command == SMB2_OPLOCK_BREAK_HE) ++ if (calc_len + 24 == len && command == SMB2_OPLOCK_BREAK_HE) + return 0; + /* server can return one byte more due to implied bcc[0] */ +- if (clc_len == len + 1) ++ if (calc_len == len + 1) + return 0; + + /* + * Some windows servers (win2016) will pad also the final + * PDU in a compound to 8 bytes. + */ +- if (((clc_len + 7) & ~7) == len) ++ if (((calc_len + 7) & ~7) == len) + return 0; + + /* +@@ -257,12 +260,18 @@ smb2_check_message(char *buf, unsigned i + * SMB2/SMB3 frame length (header + smb2 response specific data) + * Some windows servers also pad up to 8 bytes when compounding. + */ +- if (clc_len < len) ++ if (calc_len < len) + return 0; + +- pr_warn_once( +- "srv rsp too short, len %d not %d. cmd:%d mid:%llu\n", +- len, clc_len, command, mid); ++ /* Only log a message if len was really miscalculated */ ++ if (unlikely(cifsFYI)) ++ cifs_dbg(FYI, "Server response too short: calculated " ++ "length %u doesn't match read length %u (cmd=%d, mid=%llu)\n", ++ calc_len, len, command, mid); ++ else ++ pr_warn("Server response too short: calculated length " ++ "%u doesn't match read length %u (cmd=%d, mid=%llu)\n", ++ calc_len, len, command, mid); + + return 1; + } diff --git a/queue-5.10/staging-media-atomisp-reduce-load_primary_binaries-stack-usage.patch b/queue-5.10/staging-media-atomisp-reduce-load_primary_binaries-stack-usage.patch new file mode 100644 index 0000000000..b5c5a99a34 --- /dev/null +++ b/queue-5.10/staging-media-atomisp-reduce-load_primary_binaries-stack-usage.patch @@ -0,0 +1,64 @@ +From stable+bounces-274529-greg=kroah.com@vger.kernel.org Tue Jul 14 22:02:23 2026 +From: Sasha Levin +Date: Tue, 14 Jul 2026 16:01:58 -0400 +Subject: staging: media: atomisp: reduce load_primary_binaries() stack usage +To: stable@vger.kernel.org +Cc: Arnd Bergmann , Andy Shevchenko , Sakari Ailus , Sasha Levin +Message-ID: <20260714200158.3152137-6-sashal@kernel.org> + +From: Arnd Bergmann + +[ Upstream commit f4d51e55dd47ef467fbe37d8575e20eee41b092d ] + +The load_primary_binaries() function is overly complex and has som large +variables on the stack, which can cause warnings depending on CONFIG_FRAME_WARN +setting: + +drivers/staging/media/atomisp/pci/sh_css.c: In function 'load_primary_binaries': +drivers/staging/media/atomisp/pci/sh_css.c:5260:1: error: the frame size of 1560 bytes is larger than 1536 bytes [-Werror=frame-larger-than=] + +Half of the stack usage is for the prim_descr[] array, but only one +member of the array is used at any given time. + +Reduce the stack usage by turning the array into a single structure. + +Fixes: a49d25364dfb ("staging/atomisp: Add support for the Intel IPU v2") +Cc: stable@vger.kernel.org +Signed-off-by: Arnd Bergmann +Reviewed-by: Andy Shevchenko +Signed-off-by: Sakari Ailus +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/staging/media/atomisp/pci/sh_css.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/drivers/staging/media/atomisp/pci/sh_css.c ++++ b/drivers/staging/media/atomisp/pci/sh_css.c +@@ -5870,7 +5870,6 @@ static int load_primary_binaries( + struct ia_css_capture_settings *mycs; + unsigned int i; + bool need_extra_yuv_scaler = false; +- struct ia_css_binary_descr prim_descr[MAX_NUM_PRIMARY_STAGES]; + + IA_CSS_ENTER_PRIVATE(""); + assert(pipe); +@@ -6058,15 +6057,16 @@ static int load_primary_binaries( + + /* Primary */ + for (i = 0; i < mycs->num_primary_stage; i++) { ++ struct ia_css_binary_descr prim_descr; + struct ia_css_frame_info *local_vf_info = NULL; + + if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0] && + (i == mycs->num_primary_stage - 1)) + local_vf_info = &vf_info; +- ia_css_pipe_get_primary_binarydesc(pipe, &prim_descr[i], ++ ia_css_pipe_get_primary_binarydesc(pipe, &prim_descr, + &prim_in_info, &prim_out_info, + local_vf_info, i); +- err = ia_css_binary_find(&prim_descr[i], &mycs->primary_binary[i]); ++ err = ia_css_binary_find(&prim_descr, &mycs->primary_binary[i]); + if (err) { + IA_CSS_LEAVE_ERR_PRIVATE(err); + return err; diff --git a/queue-5.10/staging-rtl8723bs-clean-up-comparsions-to-null.patch b/queue-5.10/staging-rtl8723bs-clean-up-comparsions-to-null.patch new file mode 100644 index 0000000000..2a9f11a4ce --- /dev/null +++ b/queue-5.10/staging-rtl8723bs-clean-up-comparsions-to-null.patch @@ -0,0 +1,1042 @@ +From stable+bounces-274606-greg=kroah.com@vger.kernel.org Wed Jul 15 01:34:46 2026 +From: Sasha Levin +Date: Tue, 14 Jul 2026 19:34:06 -0400 +Subject: staging: rtl8723bs: clean up comparsions to NULL +To: stable@vger.kernel.org +Cc: Michael Straube , Greg Kroah-Hartman , Sasha Levin +Message-ID: <20260714233407.3591885-7-sashal@kernel.org> + +From: Michael Straube + +[ Upstream commit cd1f1450092216b3e39516f8db58869b6fc20575 ] + +Clean up comparsions to NULL reported by checkpatch. + +x == NULL -> !x +x != NULL -> x + +Signed-off-by: Michael Straube +Link: https://lore.kernel.org/r/20210829154533.11054-1-straube.linux@gmail.com +Signed-off-by: Greg Kroah-Hartman +Stable-dep-of: a1fc19d61f66 ("staging: rtl8723bs: fix WEP length underflow and OOB read in OnAuth()") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/staging/rtl8723bs/core/rtw_ap.c | 20 ++-- + drivers/staging/rtl8723bs/core/rtw_cmd.c | 96 +++++++++++----------- + drivers/staging/rtl8723bs/core/rtw_ioctl_set.c | 4 + drivers/staging/rtl8723bs/core/rtw_mlme.c | 6 - + drivers/staging/rtl8723bs/core/rtw_mlme_ext.c | 56 ++++++------ + drivers/staging/rtl8723bs/core/rtw_security.c | 6 - + drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c | 24 ++--- + drivers/staging/rtl8723bs/os_dep/ioctl_linux.c | 18 ++-- + drivers/staging/rtl8723bs/os_dep/os_intfs.c | 4 + 9 files changed, 117 insertions(+), 117 deletions(-) + +--- a/drivers/staging/rtl8723bs/core/rtw_ap.c ++++ b/drivers/staging/rtl8723bs/core/rtw_ap.c +@@ -1033,7 +1033,7 @@ int rtw_check_beacon_data(struct adapter + &ie_len, + (pbss_network->IELength - _BEACON_IE_OFFSET_) + ); +- if (p != NULL) { ++ if (p) { + memcpy(supportRate, p + 2, ie_len); + supportRateNum = ie_len; + } +@@ -1045,7 +1045,7 @@ int rtw_check_beacon_data(struct adapter + &ie_len, + pbss_network->IELength - _BEACON_IE_OFFSET_ + ); +- if (p != NULL) { ++ if (p) { + memcpy(supportRate + supportRateNum, p + 2, ie_len); + supportRateNum += ie_len; + } +@@ -1133,7 +1133,7 @@ int rtw_check_beacon_data(struct adapter + break; + } + +- if ((p == NULL) || (ie_len == 0)) ++ if (!p || ie_len == 0) + break; + } + +@@ -1162,7 +1162,7 @@ int rtw_check_beacon_data(struct adapter + break; + } + +- if ((p == NULL) || (ie_len == 0)) ++ if (!p || ie_len == 0) + break; + } + } +@@ -1290,7 +1290,7 @@ int rtw_check_beacon_data(struct adapter + psta = rtw_get_stainfo(&padapter->stapriv, pbss_network->MacAddress); + if (!psta) { + psta = rtw_alloc_stainfo(&padapter->stapriv, pbss_network->MacAddress); +- if (psta == NULL) ++ if (!psta) + return _FAIL; + } + +@@ -1447,7 +1447,7 @@ u8 rtw_ap_set_pairwise_key(struct adapte + } + + psetstakey_para = rtw_zmalloc(sizeof(struct set_stakey_parm)); +- if (psetstakey_para == NULL) { ++ if (!psetstakey_para) { + kfree(ph2c); + res = _FAIL; + goto exit; +@@ -1485,12 +1485,12 @@ static int rtw_ap_set_key( + /* DBG_871X("%s\n", __func__); */ + + pcmd = rtw_zmalloc(sizeof(struct cmd_obj)); +- if (pcmd == NULL) { ++ if (!pcmd) { + res = _FAIL; + goto exit; + } + psetkeyparm = rtw_zmalloc(sizeof(struct setkey_parm)); +- if (psetkeyparm == NULL) { ++ if (!psetkeyparm) { + kfree(pcmd); + res = _FAIL; + goto exit; +@@ -1662,11 +1662,11 @@ static void update_bcn_wps_ie(struct ada + &wps_ielen + ); + +- if (pwps_ie == NULL || wps_ielen == 0) ++ if (!pwps_ie || wps_ielen == 0) + return; + + pwps_ie_src = pmlmepriv->wps_beacon_ie; +- if (pwps_ie_src == NULL) ++ if (!pwps_ie_src) + return; + + wps_offset = (uint)(pwps_ie - ie); +--- a/drivers/staging/rtl8723bs/core/rtw_cmd.c ++++ b/drivers/staging/rtl8723bs/core/rtw_cmd.c +@@ -259,7 +259,7 @@ int _rtw_enqueue_cmd(struct __queue *que + { + _irqL irqL; + +- if (obj == NULL) ++ if (!obj) + goto exit; + + /* spin_lock_bh(&queue->lock); */ +@@ -335,7 +335,7 @@ int rtw_enqueue_cmd(struct cmd_priv *pcm + int res = _FAIL; + struct adapter *padapter = pcmdpriv->padapter; + +- if (cmd_obj == NULL) { ++ if (!cmd_obj) { + goto exit; + } + +@@ -509,7 +509,7 @@ post_process: + /* call callback function for post-processed */ + if (pcmd->cmdcode < ARRAY_SIZE(rtw_cmd_callback)) { + pcmd_callback = rtw_cmd_callback[pcmd->cmdcode].callback; +- if (pcmd_callback == NULL) { ++ if (!pcmd_callback) { + RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, ("mlme_cmd_hdl(): pcmd_callback = 0x%p, cmdcode = 0x%x\n", pcmd_callback, pcmd->cmdcode)); + rtw_free_cmd_obj(pcmd); + } else { +@@ -530,7 +530,7 @@ post_process: + /* free all cmd_obj resources */ + do { + pcmd = rtw_dequeue_cmd(pcmdpriv); +- if (pcmd == NULL) { ++ if (!pcmd) { + rtw_unregister_cmd_alive(padapter); + break; + } +@@ -572,11 +572,11 @@ u8 rtw_sitesurvey_cmd(struct adapter *p + } + + ph2c = rtw_zmalloc(sizeof(struct cmd_obj)); +- if (ph2c == NULL) ++ if (!ph2c) + return _FAIL; + + psurveyPara = rtw_zmalloc(sizeof(struct sitesurvey_parm)); +- if (psurveyPara == NULL) { ++ if (!psurveyPara) { + kfree(ph2c); + return _FAIL; + } +@@ -640,13 +640,13 @@ u8 rtw_setdatarate_cmd(struct adapter *p + u8 res = _SUCCESS; + + ph2c = rtw_zmalloc(sizeof(struct cmd_obj)); +- if (ph2c == NULL) { ++ if (!ph2c) { + res = _FAIL; + goto exit; + } + + pbsetdataratepara = rtw_zmalloc(sizeof(struct setdatarate_parm)); +- if (pbsetdataratepara == NULL) { ++ if (!pbsetdataratepara) { + kfree(ph2c); + res = _FAIL; + goto exit; +@@ -683,7 +683,7 @@ u8 rtw_createbss_cmd(struct adapter *pa + } + + pcmd = rtw_zmalloc(sizeof(struct cmd_obj)); +- if (pcmd == NULL) { ++ if (!pcmd) { + res = _FAIL; + goto exit; + } +@@ -716,7 +716,7 @@ int rtw_startbss_cmd(struct adapter *pa + } else { + /* need enqueue, prepare cmd_obj and enqueue */ + pcmd = rtw_zmalloc(sizeof(struct cmd_obj)); +- if (pcmd == NULL) { ++ if (!pcmd) { + res = _FAIL; + goto exit; + } +@@ -774,7 +774,7 @@ u8 rtw_joinbss_cmd(struct adapter *pada + } + + pcmd = rtw_zmalloc(sizeof(struct cmd_obj)); +- if (pcmd == NULL) { ++ if (!pcmd) { + res = _FAIL; + RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("rtw_joinbss_cmd: memory allocate for cmd_obj fail!!!\n")); + goto exit; +@@ -891,7 +891,7 @@ u8 rtw_disassoc_cmd(struct adapter *pada + + /* prepare cmd parameter */ + param = rtw_zmalloc(sizeof(*param)); +- if (param == NULL) { ++ if (!param) { + res = _FAIL; + goto exit; + } +@@ -900,7 +900,7 @@ u8 rtw_disassoc_cmd(struct adapter *pada + if (enqueue) { + /* need enqueue, prepare cmd_obj and enqueue */ + cmdobj = rtw_zmalloc(sizeof(*cmdobj)); +- if (cmdobj == NULL) { ++ if (!cmdobj) { + res = _FAIL; + kfree(param); + goto exit; +@@ -928,7 +928,7 @@ u8 rtw_setopmode_cmd(struct adapter *pa + + psetop = rtw_zmalloc(sizeof(struct setopmode_parm)); + +- if (psetop == NULL) { ++ if (!psetop) { + res = _FAIL; + goto exit; + } +@@ -936,7 +936,7 @@ u8 rtw_setopmode_cmd(struct adapter *pa + + if (enqueue) { + ph2c = rtw_zmalloc(sizeof(struct cmd_obj)); +- if (ph2c == NULL) { ++ if (!ph2c) { + kfree(psetop); + res = _FAIL; + goto exit; +@@ -964,7 +964,7 @@ u8 rtw_setstakey_cmd(struct adapter *pad + u8 res = _SUCCESS; + + psetstakey_para = rtw_zmalloc(sizeof(struct set_stakey_parm)); +- if (psetstakey_para == NULL) { ++ if (!psetstakey_para) { + res = _FAIL; + goto exit; + } +@@ -988,14 +988,14 @@ u8 rtw_setstakey_cmd(struct adapter *pad + + if (enqueue) { + ph2c = rtw_zmalloc(sizeof(struct cmd_obj)); +- if (ph2c == NULL) { ++ if (!ph2c) { + kfree(psetstakey_para); + res = _FAIL; + goto exit; + } + + psetstakey_rsp = rtw_zmalloc(sizeof(struct set_stakey_rsp)); +- if (psetstakey_rsp == NULL) { ++ if (!psetstakey_rsp) { + kfree(ph2c); + kfree(psetstakey_para); + res = _FAIL; +@@ -1031,20 +1031,20 @@ u8 rtw_clearstakey_cmd(struct adapter *p + } + } else { + ph2c = rtw_zmalloc(sizeof(struct cmd_obj)); +- if (ph2c == NULL) { ++ if (!ph2c) { + res = _FAIL; + goto exit; + } + + psetstakey_para = rtw_zmalloc(sizeof(struct set_stakey_parm)); +- if (psetstakey_para == NULL) { ++ if (!psetstakey_para) { + kfree(ph2c); + res = _FAIL; + goto exit; + } + + psetstakey_rsp = rtw_zmalloc(sizeof(struct set_stakey_rsp)); +- if (psetstakey_rsp == NULL) { ++ if (!psetstakey_rsp) { + kfree(ph2c); + kfree(psetstakey_para); + res = _FAIL; +@@ -1076,13 +1076,13 @@ u8 rtw_addbareq_cmd(struct adapter *pada + u8 res = _SUCCESS; + + ph2c = rtw_zmalloc(sizeof(struct cmd_obj)); +- if (ph2c == NULL) { ++ if (!ph2c) { + res = _FAIL; + goto exit; + } + + paddbareq_parm = rtw_zmalloc(sizeof(struct addBaReq_parm)); +- if (paddbareq_parm == NULL) { ++ if (!paddbareq_parm) { + kfree(ph2c); + res = _FAIL; + goto exit; +@@ -1110,13 +1110,13 @@ u8 rtw_reset_securitypriv_cmd(struct ada + u8 res = _SUCCESS; + + ph2c = rtw_zmalloc(sizeof(struct cmd_obj)); +- if (ph2c == NULL) { ++ if (!ph2c) { + res = _FAIL; + goto exit; + } + + pdrvextra_cmd_parm = rtw_zmalloc(sizeof(struct drvextra_cmd_parm)); +- if (pdrvextra_cmd_parm == NULL) { ++ if (!pdrvextra_cmd_parm) { + kfree(ph2c); + res = _FAIL; + goto exit; +@@ -1145,13 +1145,13 @@ u8 rtw_free_assoc_resources_cmd(struct a + u8 res = _SUCCESS; + + ph2c = rtw_zmalloc(sizeof(struct cmd_obj)); +- if (ph2c == NULL) { ++ if (!ph2c) { + res = _FAIL; + goto exit; + } + + pdrvextra_cmd_parm = rtw_zmalloc(sizeof(struct drvextra_cmd_parm)); +- if (pdrvextra_cmd_parm == NULL) { ++ if (!pdrvextra_cmd_parm) { + kfree(ph2c); + res = _FAIL; + goto exit; +@@ -1181,13 +1181,13 @@ u8 rtw_dynamic_chk_wk_cmd(struct adapter + + /* only primary padapter does this cmd */ + ph2c = rtw_zmalloc(sizeof(struct cmd_obj)); +- if (ph2c == NULL) { ++ if (!ph2c) { + res = _FAIL; + goto exit; + } + + pdrvextra_cmd_parm = rtw_zmalloc(sizeof(struct drvextra_cmd_parm)); +- if (pdrvextra_cmd_parm == NULL) { ++ if (!pdrvextra_cmd_parm) { + kfree(ph2c); + res = _FAIL; + goto exit; +@@ -1231,7 +1231,7 @@ u8 rtw_set_chplan_cmd(struct adapter *pa + + /* prepare cmd parameter */ + setChannelPlan_param = rtw_zmalloc(sizeof(struct SetChannelPlan_param)); +- if (setChannelPlan_param == NULL) { ++ if (!setChannelPlan_param) { + res = _FAIL; + goto exit; + } +@@ -1240,7 +1240,7 @@ u8 rtw_set_chplan_cmd(struct adapter *pa + if (enqueue) { + /* need enqueue, prepare cmd_obj and enqueue */ + pcmdobj = rtw_zmalloc(sizeof(struct cmd_obj)); +- if (pcmdobj == NULL) { ++ if (!pcmdobj) { + kfree(setChannelPlan_param); + res = _FAIL; + goto exit; +@@ -1501,13 +1501,13 @@ u8 rtw_lps_ctrl_wk_cmd(struct adapter *p + + if (enqueue) { + ph2c = rtw_zmalloc(sizeof(struct cmd_obj)); +- if (ph2c == NULL) { ++ if (!ph2c) { + res = _FAIL; + goto exit; + } + + pdrvextra_cmd_parm = rtw_zmalloc(sizeof(struct drvextra_cmd_parm)); +- if (pdrvextra_cmd_parm == NULL) { ++ if (!pdrvextra_cmd_parm) { + kfree(ph2c); + res = _FAIL; + goto exit; +@@ -1543,13 +1543,13 @@ u8 rtw_dm_in_lps_wk_cmd(struct adapter * + + + ph2c = rtw_zmalloc(sizeof(struct cmd_obj)); +- if (ph2c == NULL) { ++ if (!ph2c) { + res = _FAIL; + goto exit; + } + + pdrvextra_cmd_parm = rtw_zmalloc(sizeof(struct drvextra_cmd_parm)); +- if (pdrvextra_cmd_parm == NULL) { ++ if (!pdrvextra_cmd_parm) { + kfree(ph2c); + res = _FAIL; + goto exit; +@@ -1616,13 +1616,13 @@ u8 rtw_dm_ra_mask_wk_cmd(struct adapter + + + ph2c = rtw_zmalloc(sizeof(struct cmd_obj)); +- if (ph2c == NULL) { ++ if (!ph2c) { + res = _FAIL; + goto exit; + } + + pdrvextra_cmd_parm = rtw_zmalloc(sizeof(struct drvextra_cmd_parm)); +- if (pdrvextra_cmd_parm == NULL) { ++ if (!pdrvextra_cmd_parm) { + kfree(ph2c); + res = _FAIL; + goto exit; +@@ -1651,13 +1651,13 @@ u8 rtw_ps_cmd(struct adapter *padapter) + u8 res = _SUCCESS; + + ppscmd = rtw_zmalloc(sizeof(struct cmd_obj)); +- if (ppscmd == NULL) { ++ if (!ppscmd) { + res = _FAIL; + goto exit; + } + + pdrvextra_cmd_parm = rtw_zmalloc(sizeof(struct drvextra_cmd_parm)); +- if (pdrvextra_cmd_parm == NULL) { ++ if (!pdrvextra_cmd_parm) { + kfree(ppscmd); + res = _FAIL; + goto exit; +@@ -1723,13 +1723,13 @@ u8 rtw_chk_hi_queue_cmd(struct adapter * + u8 res = _SUCCESS; + + ph2c = rtw_zmalloc(sizeof(struct cmd_obj)); +- if (ph2c == NULL) { ++ if (!ph2c) { + res = _FAIL; + goto exit; + } + + pdrvextra_cmd_parm = rtw_zmalloc(sizeof(struct drvextra_cmd_parm)); +- if (pdrvextra_cmd_parm == NULL) { ++ if (!pdrvextra_cmd_parm) { + kfree(ph2c); + res = _FAIL; + goto exit; +@@ -1817,13 +1817,13 @@ u8 rtw_c2h_packet_wk_cmd(struct adapter + u8 res = _SUCCESS; + + ph2c = rtw_zmalloc(sizeof(struct cmd_obj)); +- if (ph2c == NULL) { ++ if (!ph2c) { + res = _FAIL; + goto exit; + } + + pdrvextra_cmd_parm = rtw_zmalloc(sizeof(struct drvextra_cmd_parm)); +- if (pdrvextra_cmd_parm == NULL) { ++ if (!pdrvextra_cmd_parm) { + kfree(ph2c); + res = _FAIL; + goto exit; +@@ -1852,13 +1852,13 @@ u8 rtw_c2h_wk_cmd(struct adapter *padapt + u8 res = _SUCCESS; + + ph2c = rtw_zmalloc(sizeof(struct cmd_obj)); +- if (ph2c == NULL) { ++ if (!ph2c) { + res = _FAIL; + goto exit; + } + + pdrvextra_cmd_parm = rtw_zmalloc(sizeof(struct drvextra_cmd_parm)); +- if (pdrvextra_cmd_parm == NULL) { ++ if (!pdrvextra_cmd_parm) { + kfree(ph2c); + res = _FAIL; + goto exit; +@@ -2036,7 +2036,7 @@ void rtw_createbss_cmd_callback(struct a + struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)pcmd->parmbuf; + struct wlan_network *tgt_network = &(pmlmepriv->cur_network); + +- if (pcmd->parmbuf == NULL) ++ if (!pcmd->parmbuf) + goto exit; + + if ((pcmd->res != H2C_SUCCESS)) { +@@ -2063,9 +2063,9 @@ void rtw_createbss_cmd_callback(struct a + } else { + pwlan = rtw_alloc_network(pmlmepriv); + spin_lock_bh(&(pmlmepriv->scanned_queue.lock)); +- if (pwlan == NULL) { ++ if (!pwlan) { + pwlan = rtw_get_oldest_wlan_network(&pmlmepriv->scanned_queue); +- if (pwlan == NULL) { ++ if (!pwlan) { + RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\n Error: can't get pwlan in rtw_joinbss_event_callback\n")); + spin_unlock_bh(&(pmlmepriv->scanned_queue.lock)); + goto createbss_cmd_fail; +--- a/drivers/staging/rtl8723bs/core/rtw_ioctl_set.c ++++ b/drivers/staging/rtl8723bs/core/rtw_ioctl_set.c +@@ -508,7 +508,7 @@ u8 rtw_set_802_11_bssid_list_scan(struct + + RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("+rtw_set_802_11_bssid_list_scan(), fw_state =%x\n", get_fwstate(pmlmepriv))); + +- if (padapter == NULL) { ++ if (!padapter) { + res = false; + goto exit; + } +@@ -649,7 +649,7 @@ u16 rtw_get_cur_max_rate(struct adapter + return 0; + + psta = rtw_get_stainfo(&adapter->stapriv, get_bssid(pmlmepriv)); +- if (psta == NULL) ++ if (!psta) + return 0; + + short_GI = query_ra_short_GI(psta); +--- a/drivers/staging/rtl8723bs/core/rtw_mlme.c ++++ b/drivers/staging/rtl8723bs/core/rtw_mlme.c +@@ -472,7 +472,7 @@ struct wlan_network *rtw_get_oldest_wlan + pwlan = LIST_CONTAINOR(plist, struct wlan_network, list); + + if (!pwlan->fixed) { +- if (oldest == NULL || time_after(oldest->last_scanned, pwlan->last_scanned)) ++ if (!oldest || time_after(oldest->last_scanned, pwlan->last_scanned)) + oldest = pwlan; + } + +@@ -603,7 +603,7 @@ void rtw_update_scanned_network(struct a + /* TODO: don't select netowrk in the same ess as oldest if it's new enough*/ + } + +- if (oldest == NULL || time_after(oldest->last_scanned, pnetwork->last_scanned)) ++ if (!oldest || time_after(oldest->last_scanned, pnetwork->last_scanned)) + oldest = pnetwork; + + plist = get_next(plist); +@@ -2023,7 +2023,7 @@ static int rtw_check_join_candidate(stru + goto exit; + } + +- if (*candidate == NULL || (*candidate)->network.Rssi < competitor->network.Rssi) { ++ if (!*candidate || (*candidate)->network.Rssi < competitor->network.Rssi) { + *candidate = competitor; + updated = true; + } +--- a/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c ++++ b/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c +@@ -934,12 +934,12 @@ unsigned int OnAuth(struct adapter *pada + } + + pstat = rtw_get_stainfo(pstapriv, sa); +- if (pstat == NULL) { ++ if (!pstat) { + + /* allocate a new one */ + DBG_871X("going to alloc stainfo for sa ="MAC_FMT"\n", MAC_ARG(sa)); + pstat = rtw_alloc_stainfo(pstapriv, sa); +- if (pstat == NULL) { ++ if (!pstat) { + DBG_871X(" Exceed the upper limit of supported clients...\n"); + status = _STATS_UNABLE_HANDLE_STA_; + goto auth_fail; +@@ -1014,7 +1014,7 @@ unsigned int OnAuth(struct adapter *pada + p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + 4 + _AUTH_IE_OFFSET_, _CHLGETXT_IE_, (int *)&ie_len, + len - WLAN_HDR_A3_LEN - _AUTH_IE_OFFSET_ - 4); + +- if ((p == NULL) || (ie_len <= 0)) { ++ if (!p || ie_len <= 0) { + DBG_871X("auth rejected because challenge failure!(1)\n"); + status = _STATS_CHALLENGE_FAIL_; + goto auth_fail; +@@ -1255,7 +1255,7 @@ unsigned int OnAssocReq(struct adapter * + + /* check if the supported rate is ok */ + p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + ie_offset, _SUPPORTEDRATES_IE_, &ie_len, pkt_len - WLAN_HDR_A3_LEN - ie_offset); +- if (p == NULL) { ++ if (!p) { + DBG_871X("Rx a sta assoc-req which supported rate is empty!\n"); + /* use our own rate set as statoin used */ + /* memcpy(supportRate, AP_BSSRATE, AP_BSSRATE_LEN); */ +@@ -1272,7 +1272,7 @@ unsigned int OnAssocReq(struct adapter * + + p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + ie_offset, _EXT_SUPPORTEDRATES_IE_, &ie_len, + pkt_len - WLAN_HDR_A3_LEN - ie_offset); +- if (p != NULL) { ++ if (p) { + + if (supportRateNum + ie_len <= sizeof(supportRate)) { + memcpy(supportRate+supportRateNum, p+2, ie_len); +@@ -1538,7 +1538,7 @@ unsigned int OnAssocReq(struct adapter * + DBG_871X(" old AID %d\n", pstat->aid); + } else { + for (pstat->aid = 1; pstat->aid <= NUM_STA; pstat->aid++) +- if (pstapriv->sta_aid[pstat->aid - 1] == NULL) ++ if (!pstapriv->sta_aid[pstat->aid - 1]) + break; + + /* if (pstat->aid > NUM_STA) { */ +@@ -2226,7 +2226,7 @@ static struct xmit_frame *_alloc_mgtxmit + } + + pxmitbuf = rtw_alloc_xmitbuf_ext(pxmitpriv); +- if (pxmitbuf == NULL) { ++ if (!pxmitbuf) { + DBG_871X(FUNC_ADPT_FMT" alloc xmitbuf fail\n", FUNC_ADPT_ARG(pxmitpriv->adapter)); + rtw_free_xmitframe(pxmitpriv, pmgntframe); + pmgntframe = NULL; +@@ -2596,7 +2596,7 @@ void issue_probersp(struct adapter *pada + + /* DBG_871X("%s\n", __func__); */ + +- if (da == NULL) ++ if (!da) + return; + + pmgntframe = alloc_mgtxmitframe(pxmitpriv); +@@ -2961,7 +2961,7 @@ void issue_auth(struct adapter *padapter + __le16 le_tmp; + + pmgntframe = alloc_mgtxmitframe(pxmitpriv); +- if (pmgntframe == NULL) ++ if (!pmgntframe) + return; + + /* update attribute */ +@@ -3097,7 +3097,7 @@ void issue_asocrsp(struct adapter *padap + DBG_871X("%s\n", __func__); + + pmgntframe = alloc_mgtxmitframe(pxmitpriv); +- if (pmgntframe == NULL) ++ if (!pmgntframe) + return; + + /* update attribute */ +@@ -3185,7 +3185,7 @@ void issue_asocrsp(struct adapter *padap + break; + } + +- if ((pbuf == NULL) || (ie_len == 0)) { ++ if (!pbuf || ie_len == 0) { + break; + } + } +@@ -3229,7 +3229,7 @@ void issue_assocreq(struct adapter *pada + u8 vs_ie_length = 0; + + pmgntframe = alloc_mgtxmitframe(pxmitpriv); +- if (pmgntframe == NULL) ++ if (!pmgntframe) + goto exit; + + /* update attribute */ +@@ -3420,7 +3420,7 @@ static int _issue_nulldata(struct adapte + pmlmeinfo = &(pmlmeext->mlmext_info); + + pmgntframe = alloc_mgtxmitframe(pxmitpriv); +- if (pmgntframe == NULL) ++ if (!pmgntframe) + goto exit; + + /* update attribute */ +@@ -3573,7 +3573,7 @@ static int _issue_qos_nulldata(struct ad + DBG_871X("%s\n", __func__); + + pmgntframe = alloc_mgtxmitframe(pxmitpriv); +- if (pmgntframe == NULL) ++ if (!pmgntframe) + goto exit; + + /* update attribute */ +@@ -3698,7 +3698,7 @@ static int _issue_deauth(struct adapter + /* DBG_871X("%s to "MAC_FMT"\n", __func__, MAC_ARG(da)); */ + + pmgntframe = alloc_mgtxmitframe(pxmitpriv); +- if (pmgntframe == NULL) { ++ if (!pmgntframe) { + goto exit; + } + +@@ -4047,7 +4047,7 @@ static void issue_action_BSSCoexistPacke + action = ACT_PUBLIC_BSSCOEXIST; + + pmgntframe = alloc_mgtxmitframe(pxmitpriv); +- if (pmgntframe == NULL) { ++ if (!pmgntframe) { + return; + } + +@@ -4114,7 +4114,7 @@ static void issue_action_BSSCoexistPacke + pbss_network = (struct wlan_bssid_ex *)&pnetwork->network; + + p = rtw_get_ie(pbss_network->IEs + _FIXED_IE_LENGTH_, _HT_CAPABILITY_IE_, &len, pbss_network->IELength - _FIXED_IE_LENGTH_); +- if ((p == NULL) || (len == 0)) {/* non-HT */ ++ if (!p || len == 0) {/* non-HT */ + + if (pbss_network->Configuration.DSConfig <= 0) + continue; +@@ -4177,7 +4177,7 @@ unsigned int send_delba(struct adapter * + return _SUCCESS; + + psta = rtw_get_stainfo(pstapriv, addr); +- if (psta == NULL) ++ if (!psta) + return _SUCCESS; + + /* DBG_871X("%s:%s\n", __func__, (initiator == 0)?"RX_DIR":"TX_DIR"); */ +@@ -5153,13 +5153,13 @@ void report_del_sta_event(struct adapter + struct cmd_priv *pcmdpriv = &padapter->cmdpriv; + + pcmd_obj = rtw_zmalloc(sizeof(struct cmd_obj)); +- if (pcmd_obj == NULL) { ++ if (!pcmd_obj) { + return; + } + + cmdsz = (sizeof(struct stadel_event) + sizeof(struct C2HEvent_Header)); + pevtcmd = rtw_zmalloc(cmdsz); +- if (pevtcmd == NULL) { ++ if (!pevtcmd) { + kfree(pcmd_obj); + return; + } +@@ -5207,12 +5207,12 @@ void report_add_sta_event(struct adapter + struct cmd_priv *pcmdpriv = &padapter->cmdpriv; + + pcmd_obj = rtw_zmalloc(sizeof(struct cmd_obj)); +- if (pcmd_obj == NULL) ++ if (!pcmd_obj) + return; + + cmdsz = (sizeof(struct stassoc_event) + sizeof(struct C2HEvent_Header)); + pevtcmd = rtw_zmalloc(cmdsz); +- if (pevtcmd == NULL) { ++ if (!pevtcmd) { + kfree(pcmd_obj); + return; + } +@@ -5732,12 +5732,12 @@ void survey_timer_hdl(struct timer_list + } + + ph2c = rtw_zmalloc(sizeof(struct cmd_obj)); +- if (ph2c == NULL) { ++ if (!ph2c) { + goto exit_survey_timer_hdl; + } + + psurveyPara = rtw_zmalloc(sizeof(struct sitesurvey_parm)); +- if (psurveyPara == NULL) { ++ if (!psurveyPara) { + kfree(ph2c); + goto exit_survey_timer_hdl; + } +@@ -6467,7 +6467,7 @@ u8 chk_bmc_sleepq_cmd(struct adapter *pa + u8 res = _SUCCESS; + + ph2c = rtw_zmalloc(sizeof(struct cmd_obj)); +- if (ph2c == NULL) { ++ if (!ph2c) { + res = _FAIL; + goto exit; + } +@@ -6491,13 +6491,13 @@ u8 set_tx_beacon_cmd(struct adapter *pad + int len_diff = 0; + + ph2c = rtw_zmalloc(sizeof(struct cmd_obj)); +- if (ph2c == NULL) { ++ if (!ph2c) { + res = _FAIL; + goto exit; + } + + ptxBeacon_parm = rtw_zmalloc(sizeof(struct Tx_Beacon_param)); +- if (ptxBeacon_parm == NULL) { ++ if (!ptxBeacon_parm) { + kfree(ph2c); + res = _FAIL; + goto exit; +@@ -6529,7 +6529,7 @@ u8 mlme_evt_hdl(struct adapter *padapter + void (*event_callback)(struct adapter *dev, u8 *pbuf); + struct evt_priv *pevt_priv = &(padapter->evtpriv); + +- if (pbuf == NULL) ++ if (!pbuf) + goto _abort_event_; + + peventbuf = (uint *)pbuf; +--- a/drivers/staging/rtl8723bs/core/rtw_security.c ++++ b/drivers/staging/rtl8723bs/core/rtw_security.c +@@ -226,7 +226,7 @@ void rtw_wep_encrypt(struct adapter *pad + struct security_priv *psecuritypriv = &padapter->securitypriv; + struct xmit_priv *pxmitpriv = &padapter->xmitpriv; + +- if (((struct xmit_frame *)pxmitframe)->buf_addr == NULL) ++ if (!((struct xmit_frame *)pxmitframe)->buf_addr) + return; + + hw_hdr_offset = TXDESC_OFFSET; +@@ -669,7 +669,7 @@ u32 rtw_tkip_encrypt(struct adapter *pad + struct xmit_priv *pxmitpriv = &padapter->xmitpriv; + u32 res = _SUCCESS; + +- if (((struct xmit_frame *)pxmitframe)->buf_addr == NULL) ++ if (!((struct xmit_frame *)pxmitframe)->buf_addr) + return _FAIL; + + hw_hdr_offset = TXDESC_OFFSET; +@@ -1489,7 +1489,7 @@ u32 rtw_aes_encrypt(struct adapter *pada + + u32 res = _SUCCESS; + +- if (((struct xmit_frame *)pxmitframe)->buf_addr == NULL) ++ if (!((struct xmit_frame *)pxmitframe)->buf_addr) + return _FAIL; + + hw_hdr_offset = TXDESC_OFFSET; +--- a/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c ++++ b/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c +@@ -418,7 +418,7 @@ void rtw_cfg80211_ibss_indicate_connect( + } + else + { +- if (scanned == NULL) { ++ if (!scanned) { + rtw_warn_on(1); + return; + } +@@ -466,7 +466,7 @@ void rtw_cfg80211_indicate_connect(struc + + /* DBG_871X(FUNC_ADPT_FMT" BSS not found\n", FUNC_ADPT_ARG(padapter)); */ + +- if (scanned == NULL) { ++ if (!scanned) { + rtw_warn_on(1); + goto check_bss; + } +@@ -597,7 +597,7 @@ static int rtw_cfg80211_ap_set_encryptio + } + } + +- if (strcmp(param->u.crypt.alg, "none") == 0 && (psta == NULL)) ++ if (strcmp(param->u.crypt.alg, "none") == 0 && !psta) + { + /* todo:clear default encryption keys */ + +@@ -607,7 +607,7 @@ static int rtw_cfg80211_ap_set_encryptio + } + + +- if (strcmp(param->u.crypt.alg, "WEP") == 0 && (psta == NULL)) ++ if (strcmp(param->u.crypt.alg, "WEP") == 0 && !psta) + { + DBG_8192C("r871x_set_encryption, crypt.alg = WEP\n"); + +@@ -1001,7 +1001,7 @@ static int rtw_cfg80211_set_encryption(s + } + + pbcmc_sta = rtw_get_bcmc_stainfo(padapter); +- if (pbcmc_sta == NULL) ++ if (!pbcmc_sta) + { + /* DEBUG_ERR(("Set OID_802_11_ADD_KEY: bcmc stainfo is null\n")); */ + } +@@ -1050,7 +1050,7 @@ static int cfg80211_rtw_add_key(struct w + + param_len = sizeof(struct ieee_param) + params->key_len; + param = rtw_malloc(param_len); +- if (param == NULL) ++ if (!param) + return -1; + + memset(param, 0, param_len); +@@ -1214,7 +1214,7 @@ static int cfg80211_rtw_get_station(stru + } + + psta = rtw_get_stainfo(pstapriv, (u8 *)mac); +- if (psta == NULL) { ++ if (!psta) { + DBG_8192C("%s, sta_info is null\n", __func__); + ret = -ENOENT; + goto exit; +@@ -1495,7 +1495,7 @@ static int cfg80211_rtw_scan(struct wiph + struct rtw_wdev_priv *pwdev_priv; + struct mlme_priv *pmlmepriv; + +- if (ndev == NULL) { ++ if (!ndev) { + ret = -EINVAL; + goto exit; + } +@@ -1783,7 +1783,7 @@ static int rtw_cfg80211_set_wpa_ie(struc + u8 *pwpa, *pwpa2; + u8 null_addr[] = {0, 0, 0, 0, 0, 0}; + +- if (pie == NULL || !ielen) { ++ if (!pie || !ielen) { + /* Treat this as normal case, but need to clear WIFI_UNDER_WPS */ + _clr_fwstate_(&padapter->mlmepriv, WIFI_UNDER_WPS); + goto exit; +@@ -1795,7 +1795,7 @@ static int rtw_cfg80211_set_wpa_ie(struc + } + + buf = rtw_zmalloc(ielen); +- if (buf == NULL) { ++ if (!buf) { + ret = -ENOMEM; + goto exit; + } +@@ -2138,7 +2138,7 @@ static int cfg80211_rtw_connect(struct w + wep_key_len = wep_key_len <= 5 ? 5 : 13; + wep_total_len = wep_key_len + FIELD_OFFSET(struct ndis_802_11_wep, KeyMaterial); + pwep = rtw_malloc(wep_total_len); +- if (pwep == NULL) { ++ if (!pwep) { + DBG_871X(" wpa_set_encryption: pwep allocate fail !!!\n"); + ret = -ENOMEM; + goto exit; +@@ -3073,7 +3073,7 @@ static int cfg80211_rtw_mgmt_tx(struct w + struct adapter *padapter; + struct rtw_wdev_priv *pwdev_priv; + +- if (ndev == NULL) { ++ if (!ndev) { + ret = -EINVAL; + goto exit; + } +--- a/drivers/staging/rtl8723bs/os_dep/ioctl_linux.c ++++ b/drivers/staging/rtl8723bs/os_dep/ioctl_linux.c +@@ -519,7 +519,7 @@ static int wpa_set_encryption(struct net + + if (check_fwstate(pmlmepriv, WIFI_STATION_STATE | WIFI_MP_STATE) == true) { /* sta mode */ + psta = rtw_get_stainfo(pstapriv, get_bssid(pmlmepriv)); +- if (psta == NULL) { ++ if (!psta) { + /* DEBUG_ERR(("Set wpa_set_encryption: Obtain Sta_info fail\n")); */ + } else { + /* Jeff: don't disable ieee8021x_blocked while clearing key */ +@@ -578,7 +578,7 @@ static int wpa_set_encryption(struct net + } + + pbcmc_sta = rtw_get_bcmc_stainfo(padapter); +- if (pbcmc_sta == NULL) { ++ if (!pbcmc_sta) { + /* DEBUG_ERR(("Set OID_802_11_ADD_KEY: bcmc stainfo is null\n")); */ + } else { + /* Jeff: don't disable ieee8021x_blocked while clearing key */ +@@ -608,9 +608,9 @@ static int rtw_set_wpa_ie(struct adapter + int ret = 0; + u8 null_addr[] = {0, 0, 0, 0, 0, 0}; + +- if ((ielen > MAX_WPA_IE_LEN) || (pie == NULL)) { ++ if (ielen > MAX_WPA_IE_LEN || !pie) { + _clr_fwstate_(&padapter->mlmepriv, WIFI_UNDER_WPS); +- if (pie == NULL) ++ if (!pie) + return ret; + else + return -EINVAL; +@@ -618,7 +618,7 @@ static int rtw_set_wpa_ie(struct adapter + + if (ielen) { + buf = rtw_zmalloc(ielen); +- if (buf == NULL) { ++ if (!buf) { + ret = -ENOMEM; + goto exit; + } +@@ -3366,7 +3366,7 @@ static int wpa_supplicant_ioctl(struct n + return -EINVAL; + + param = rtw_malloc(p->length); +- if (param == NULL) ++ if (!param) + return -ENOMEM; + + if (copy_from_user(param, p->pointer, p->length)) { +@@ -3448,7 +3448,7 @@ static int rtw_set_encryption(struct net + } + } + +- if (strcmp(param->u.crypt.alg, "none") == 0 && (psta == NULL)) { ++ if (strcmp(param->u.crypt.alg, "none") == 0 && !psta) { + /* todo:clear default encryption keys */ + + psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Open; +@@ -3462,7 +3462,7 @@ static int rtw_set_encryption(struct net + } + + +- if (strcmp(param->u.crypt.alg, "WEP") == 0 && (psta == NULL)) { ++ if (strcmp(param->u.crypt.alg, "WEP") == 0 && !psta) { + DBG_871X("r871x_set_encryption, crypt.alg = WEP\n"); + + wep_key_idx = param->u.crypt.idx; +@@ -4187,7 +4187,7 @@ static int rtw_hostapd_ioctl(struct net_ + return -EINVAL; + + param = rtw_malloc(p->length); +- if (param == NULL) ++ if (!param) + return -ENOMEM; + + if (copy_from_user(param, p->pointer, p->length)) { +--- a/drivers/staging/rtl8723bs/os_dep/os_intfs.c ++++ b/drivers/staging/rtl8723bs/os_dep/os_intfs.c +@@ -525,7 +525,7 @@ void rtw_unregister_netdevs(struct dvobj + + padapter = dvobj->padapters; + +- if (padapter == NULL) ++ if (!padapter) + return; + + pnetdev = padapter->pnetdev; +@@ -638,7 +638,7 @@ struct dvobj_priv *devobj_init(void) + struct dvobj_priv *pdvobj = NULL; + + pdvobj = rtw_zmalloc(sizeof(*pdvobj)); +- if (pdvobj == NULL) ++ if (!pdvobj) + return NULL; + + mutex_init(&pdvobj->hw_init_mutex); diff --git a/queue-5.10/staging-rtl8723bs-fix-heap-buffer-overflow-in-rtw_cfg80211_set_wpa_ie.patch b/queue-5.10/staging-rtl8723bs-fix-heap-buffer-overflow-in-rtw_cfg80211_set_wpa_ie.patch new file mode 100644 index 0000000000..216d1ba441 --- /dev/null +++ b/queue-5.10/staging-rtl8723bs-fix-heap-buffer-overflow-in-rtw_cfg80211_set_wpa_ie.patch @@ -0,0 +1,66 @@ +From stable+bounces-274607-greg=kroah.com@vger.kernel.org Wed Jul 15 01:34:19 2026 +From: Sasha Levin +Date: Tue, 14 Jul 2026 19:34:11 -0400 +Subject: staging: rtl8723bs: fix heap buffer overflow in rtw_cfg80211_set_wpa_ie() +To: stable@vger.kernel.org +Cc: Alexandru Hossu , stable , Luka Gejak , Greg Kroah-Hartman , Sasha Levin +Message-ID: <20260714233411.3592079-2-sashal@kernel.org> + +From: Alexandru Hossu + +[ Upstream commit 5a752a616e756844388a1a45404db9fc29fec655 ] + +supplicant_ie is a 256-byte array in struct security_priv. The WPA and +WPA2 IE copy paths use: + + memcpy(padapter->securitypriv.supplicant_ie, &pwpa[0], wpa_ielen + 2); + +where wpa_ielen is the raw IE length field (u8, 0-255). When a local user +supplies a connect request via nl80211 with a crafted WPA IE of length 255, +wpa_ielen + 2 equals 257, overflowing the 256-byte buffer by one byte into +the adjacent last_mic_err_time field. + +rtw_parse_wpa_ie() does not prevent this: its length consistency check +compares *(wpa_ie+1) against (u8)(wpa_ie_len-2), which is (u8)(255) == 255 +when wpa_ie_len = 257, so the check passes silently. + +Add explicit bounds checks for both the WPA and WPA2 paths before the +memcpy, rejecting any IE whose total size (wpa_ielen + 2) exceeds the +supplicant_ie buffer. + +Fixes: 554c0a3abf21 ("staging: Add rtl8723bs sdio wifi driver") +Cc: stable +Reviewed-by: Luka Gejak +Signed-off-by: Alexandru Hossu +Link: https://patch.msgid.link/20260522004531.1038924-4-hossu.alexandru@gmail.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +--- a/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c ++++ b/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c +@@ -1818,6 +1818,10 @@ static int rtw_cfg80211_set_wpa_ie(struc + + pwpa = rtw_get_wpa_ie(buf, &wpa_ielen, ielen); + if (pwpa && wpa_ielen > 0) { ++ if (wpa_ielen + 2 > sizeof(padapter->securitypriv.supplicant_ie)) { ++ ret = -EINVAL; ++ goto exit; ++ } + if (rtw_parse_wpa_ie(pwpa, wpa_ielen + 2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) { + padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_8021X; + padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeWPAPSK; +@@ -1829,6 +1833,10 @@ static int rtw_cfg80211_set_wpa_ie(struc + + pwpa2 = rtw_get_wpa2_ie(buf, &wpa2_ielen, ielen); + if (pwpa2 && wpa2_ielen > 0) { ++ if (wpa2_ielen + 2 > sizeof(padapter->securitypriv.supplicant_ie)) { ++ ret = -EINVAL; ++ goto exit; ++ } + if (rtw_parse_wpa2_ie(pwpa2, wpa2_ielen + 2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) { + padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_8021X; + padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeWPA2PSK; diff --git a/queue-5.10/staging-rtl8723bs-fix-oob-reads-in-ie-loops-in-issue_assocreq-and-join_cmd_hdl.patch b/queue-5.10/staging-rtl8723bs-fix-oob-reads-in-ie-loops-in-issue_assocreq-and-join_cmd_hdl.patch new file mode 100644 index 0000000000..c70c04bfbf --- /dev/null +++ b/queue-5.10/staging-rtl8723bs-fix-oob-reads-in-ie-loops-in-issue_assocreq-and-join_cmd_hdl.patch @@ -0,0 +1,69 @@ +From stable+bounces-274633-greg=kroah.com@vger.kernel.org Wed Jul 15 02:18:15 2026 +From: Sasha Levin +Date: Tue, 14 Jul 2026 20:17:26 -0400 +Subject: staging: rtl8723bs: fix OOB reads in IE loops in issue_assocreq() and join_cmd_hdl() +To: stable@vger.kernel.org +Cc: Alexandru Hossu , stable , Luka Gejak , Greg Kroah-Hartman , Sasha Levin +Message-ID: <20260715001726.3782263-1-sashal@kernel.org> + +From: Alexandru Hossu + +[ Upstream commit ef61d628dfad38fead1fd2e08979ae9126d011d5 ] + +Two IE parsing loops are missing the header bounds checks before they +dereference pIE->length: + + - issue_assocreq() walks pmlmeinfo->network.ies to build the + association request. If the stored IE data ends with only an + element_id byte and no length byte, pIE->length is read one byte + past the end of the buffer. + + - join_cmd_hdl() walks pnetwork->ies during station join and has + the same problem under the same conditions. + +Both buffers are filled from AP beacon and probe-response frames, so a +malicious AP that sends a truncated final IE can trigger the issue. + +Apply the two-guard pattern established in update_beacon_info(): + 1. Break if fewer than sizeof(*pIE) bytes remain. + 2. Break if the IE's declared data extends past the buffer end. + +Fixes: 554c0a3abf21 ("staging: Add rtl8723bs sdio wifi driver") +Cc: stable +Reviewed-by: Luka Gejak +Signed-off-by: Alexandru Hossu +Link: https://patch.msgid.link/20260522004531.1038924-3-hossu.alexandru@gmail.com +Signed-off-by: Greg Kroah-Hartman +[ replaced sizeof(*pIE) with literal 2 (5.10's ndis_80211_var_ie still has data[1]) and used pre-rename field names IELength/IEs/ElementID/Length ] +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/staging/rtl8723bs/core/rtw_mlme_ext.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +--- a/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c ++++ b/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c +@@ -3341,7 +3341,11 @@ void issue_assocreq(struct adapter *pada + + /* vendor specific IE, such as WPA, WMM, WPS */ + for (i = sizeof(struct ndis_802_11_fix_ie); i < pmlmeinfo->network.IELength;) { ++ if (i + 2 > pmlmeinfo->network.IELength) ++ break; + pIE = (struct ndis_80211_var_ie *)(pmlmeinfo->network.IEs + i); ++ if (i + 2 + pIE->Length > pmlmeinfo->network.IELength) ++ break; + + switch (pIE->ElementID) { + case _VENDOR_SPECIFIC_IE_: +@@ -6105,7 +6109,11 @@ u8 join_cmd_hdl(struct adapter *padapter + + /* sizeof(struct ndis_802_11_fix_ie) */ + for (i = _FIXED_IE_LENGTH_; i < pnetwork->IELength;) { ++ if (i + 2 > pnetwork->IELength) ++ break; + pIE = (struct ndis_80211_var_ie *)(pnetwork->IEs + i); ++ if (i + 2 + pIE->Length > pnetwork->IELength) ++ break; + + switch (pIE->ElementID) { + case _VENDOR_SPECIFIC_IE_:/* Get WMM IE. */ diff --git a/queue-5.10/staging-rtl8723bs-fix-space-issues.patch b/queue-5.10/staging-rtl8723bs-fix-space-issues.patch new file mode 100644 index 0000000000..cd180f2cbe --- /dev/null +++ b/queue-5.10/staging-rtl8723bs-fix-space-issues.patch @@ -0,0 +1,266 @@ +From stable+bounces-274604-greg=kroah.com@vger.kernel.org Wed Jul 15 01:34:37 2026 +From: Sasha Levin +Date: Tue, 14 Jul 2026 19:34:10 -0400 +Subject: staging: rtl8723bs: Fix space issues +To: stable@vger.kernel.org +Cc: Franziska Naepelt , Greg Kroah-Hartman , Sasha Levin +Message-ID: <20260714233411.3592079-1-sashal@kernel.org> + +From: Franziska Naepelt + +[ Upstream commit c4b811b9361b0d7ea167a79587f5ec0a13fd8863 ] + +Fix the following checkpatch space issues: +- CHECK: spaces preferred around that '*' (ctx:VxV) +- CHECK: spaces preferred around that '+' (ctx:VxV) +- CHECK: spaces preferred around that '-' (ctx:VxV) +- CHECK: spaces preferred around that '|' (ctx:VxV) +- CHECK: No space is necessary after a cast +- WARNING: please, no spaces at the start of a line + +Signed-off-by: Franziska Naepelt +Link: https://lore.kernel.org/r/20230701102538.5359-1-franziska.naepelt@googlemail.com +Signed-off-by: Greg Kroah-Hartman +Stable-dep-of: 5a752a616e75 ("staging: rtl8723bs: fix heap buffer overflow in rtw_cfg80211_set_wpa_ie()") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c | 84 ++++++++++------------ + 1 file changed, 40 insertions(+), 44 deletions(-) + +--- a/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c ++++ b/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c +@@ -98,14 +98,14 @@ static struct ieee80211_channel rtw_2ghz + static void rtw_2g_channels_init(struct ieee80211_channel *channels) + { + memcpy((void *)channels, (void *)rtw_2ghz_channels, +- sizeof(struct ieee80211_channel)*RTW_2G_CHANNELS_NUM ++ sizeof(struct ieee80211_channel) * RTW_2G_CHANNELS_NUM + ); + } + + static void rtw_2g_rates_init(struct ieee80211_rate *rates) + { + memcpy(rates, rtw_g_rates, +- sizeof(struct ieee80211_rate)*RTW_G_RATES_NUM ++ sizeof(struct ieee80211_rate) * RTW_G_RATES_NUM + ); + } + +@@ -132,8 +132,8 @@ static struct ieee80211_supported_band * + if (!spt_band) + goto exit; + +- spt_band->channels = (struct ieee80211_channel *)(((u8 *)spt_band)+sizeof(struct ieee80211_supported_band)); +- spt_band->bitrates = (struct ieee80211_rate *)(((u8 *)spt_band->channels)+sizeof(struct ieee80211_channel)*n_channels); ++ spt_band->channels = (struct ieee80211_channel *)(((u8 *)spt_band) + sizeof(struct ieee80211_supported_band)); ++ spt_band->bitrates = (struct ieee80211_rate *)(((u8 *)spt_band->channels) + sizeof(struct ieee80211_channel) * n_channels); + spt_band->band = band; + spt_band->n_channels = n_channels; + spt_band->n_bitrates = n_bitrates; +@@ -267,10 +267,10 @@ struct cfg80211_bss *rtw_cfg80211_inform + u32 wpsielen = 0; + u8 *wpsie = NULL; + +- wpsie = rtw_get_wps_ie(pnetwork->network.IEs+_FIXED_IE_LENGTH_, pnetwork->network.IELength-_FIXED_IE_LENGTH_, NULL, &wpsielen); ++ wpsie = rtw_get_wps_ie(pnetwork->network.IEs + _FIXED_IE_LENGTH_, pnetwork->network.IELength - _FIXED_IE_LENGTH_, NULL, &wpsielen); + + if (wpsie && wpsielen > 0) +- psr = rtw_get_wps_attr_content(wpsie, wpsielen, WPS_ATTR_SELECTED_REGISTRAR, (u8 *)(&sr), NULL); ++ psr = rtw_get_wps_attr_content(wpsie, wpsielen, WPS_ATTR_SELECTED_REGISTRAR, (u8 *)(&sr), NULL); + + if (sr != 0) + { +@@ -306,9 +306,9 @@ struct cfg80211_bss *rtw_cfg80211_inform + /* We've set wiphy's signal_type as CFG80211_SIGNAL_TYPE_MBM: signal strength in mBm (100*dBm) */ + if (check_fwstate(pmlmepriv, _FW_LINKED) == true && + is_same_network(&pmlmepriv->cur_network.network, &pnetwork->network, 0)) { +- notify_signal = 100*translate_percentage_to_dbm(padapter->recvpriv.signal_strength);/* dbm */ ++ notify_signal = 100 * translate_percentage_to_dbm(padapter->recvpriv.signal_strength);/* dbm */ + } else { +- notify_signal = 100*translate_percentage_to_dbm(pnetwork->network.PhyInfo.SignalStrength);/* dbm */ ++ notify_signal = 100 * translate_percentage_to_dbm(pnetwork->network.PhyInfo.SignalStrength);/* dbm */ + } + + buf = kzalloc(MAX_BSSINFO_LEN, GFP_ATOMIC); +@@ -507,22 +507,22 @@ check_bss: + roam_info.channel = notify_channel; + roam_info.bssid = cur_network->network.MacAddress; + roam_info.req_ie = +- pmlmepriv->assoc_req+sizeof(struct ieee80211_hdr_3addr)+2; ++ pmlmepriv->assoc_req + sizeof(struct ieee80211_hdr_3addr) + 2; + roam_info.req_ie_len = +- pmlmepriv->assoc_req_len-sizeof(struct ieee80211_hdr_3addr)-2; ++ pmlmepriv->assoc_req_len - sizeof(struct ieee80211_hdr_3addr) - 2; + roam_info.resp_ie = +- pmlmepriv->assoc_rsp+sizeof(struct ieee80211_hdr_3addr)+6; ++ pmlmepriv->assoc_rsp + sizeof(struct ieee80211_hdr_3addr) + 6; + roam_info.resp_ie_len = +- pmlmepriv->assoc_rsp_len-sizeof(struct ieee80211_hdr_3addr)-6; ++ pmlmepriv->assoc_rsp_len - sizeof(struct ieee80211_hdr_3addr) - 6; + cfg80211_roamed(padapter->pnetdev, &roam_info, GFP_ATOMIC); + } + else + { + cfg80211_connect_result(padapter->pnetdev, cur_network->network.MacAddress +- , pmlmepriv->assoc_req+sizeof(struct ieee80211_hdr_3addr)+2 +- , pmlmepriv->assoc_req_len-sizeof(struct ieee80211_hdr_3addr)-2 +- , pmlmepriv->assoc_rsp+sizeof(struct ieee80211_hdr_3addr)+6 +- , pmlmepriv->assoc_rsp_len-sizeof(struct ieee80211_hdr_3addr)-6 ++ , pmlmepriv->assoc_req + sizeof(struct ieee80211_hdr_3addr) + 2 ++ , pmlmepriv->assoc_req_len - sizeof(struct ieee80211_hdr_3addr) - 2 ++ , pmlmepriv->assoc_rsp + sizeof(struct ieee80211_hdr_3addr) + 6 ++ , pmlmepriv->assoc_rsp_len - sizeof(struct ieee80211_hdr_3addr) - 6 + , WLAN_STATUS_SUCCESS, GFP_ATOMIC); + } + } +@@ -855,7 +855,7 @@ static int rtw_cfg80211_set_encryption(s + param->u.crypt.err = 0; + param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0'; + +- if (param_len < (u32) ((u8 *) param->u.crypt.key - (u8 *) param) + param->u.crypt.key_len) ++ if (param_len < (u32)((u8 *)param->u.crypt.key - (u8 *)param) + param->u.crypt.key_len) + { + ret = -EINVAL; + goto exit; +@@ -1252,10 +1252,10 @@ static int cfg80211_rtw_get_station(stru + } + + /* for Ad-Hoc/AP mode */ +- if ((check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) +- || check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) +- || check_fwstate(pmlmepriv, WIFI_AP_STATE)) +- && check_fwstate(pmlmepriv, _FW_LINKED) ++ if ((check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) || ++ check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) || ++ check_fwstate(pmlmepriv, WIFI_AP_STATE)) && ++ check_fwstate(pmlmepriv, _FW_LINKED) + ) + { + /* TODO: should acquire station info... */ +@@ -1518,7 +1518,7 @@ static int cfg80211_rtw_scan(struct wiph + DBG_871X("%s under WIFI_AP_STATE\n", __func__); + #endif + +- if (check_fwstate(pmlmepriv, WIFI_UNDER_WPS|_FW_UNDER_SURVEY|_FW_UNDER_LINKING) == true) ++ if (check_fwstate(pmlmepriv, WIFI_UNDER_WPS | _FW_UNDER_SURVEY | _FW_UNDER_LINKING) == true) + { + DBG_8192C("%s, fwstate = 0x%x\n", __func__, pmlmepriv->fw_state); + +@@ -1591,7 +1591,7 @@ static int cfg80211_rtw_scan(struct wiph + } + + /* parsing channels, n_channels */ +- memset(ch, 0, sizeof(struct rtw_ieee80211_channel)*RTW_CHANNEL_SCAN_AMOUNT); ++ memset(ch, 0, sizeof(struct rtw_ieee80211_channel) * RTW_CHANNEL_SCAN_AMOUNT); + for (i = 0; i < request->n_channels && i < RTW_CHANNEL_SCAN_AMOUNT; i++) { + #ifdef DEBUG_CFG80211 + DBG_871X(FUNC_ADPT_FMT CHAN_FMT"\n", FUNC_ADPT_ARG(padapter), CHAN_ARG(request->channels[i])); +@@ -1609,7 +1609,7 @@ static int cfg80211_rtw_scan(struct wiph + for (j = request->n_channels - 1; j >= 0; j--) + for (i = 0; i < survey_times; i++) + { +- memcpy(&ch[j*survey_times+i], &ch[j], sizeof(struct rtw_ieee80211_channel)); ++ memcpy(&ch[j * survey_times + i], &ch[j], sizeof(struct rtw_ieee80211_channel)); + } + _status = rtw_sitesurvey_cmd(padapter, ssid, RTW_SSID_SCAN_AMOUNT, ch, survey_times * request->n_channels); + } else { +@@ -1789,7 +1789,7 @@ static int rtw_cfg80211_set_wpa_ie(struc + goto exit; + } + +- if (ielen > MAX_WPA_IE_LEN+MAX_WPS_IE_LEN+MAX_P2P_IE_LEN) { ++ if (ielen > MAX_WPA_IE_LEN + MAX_WPS_IE_LEN + MAX_P2P_IE_LEN) { + ret = -EINVAL; + goto exit; + } +@@ -1817,26 +1817,22 @@ static int rtw_cfg80211_set_wpa_ie(struc + } + + pwpa = rtw_get_wpa_ie(buf, &wpa_ielen, ielen); +- if (pwpa && wpa_ielen > 0) +- { +- if (rtw_parse_wpa_ie(pwpa, wpa_ielen+2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) +- { ++ if (pwpa && wpa_ielen > 0) { ++ if (rtw_parse_wpa_ie(pwpa, wpa_ielen + 2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) { + padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_8021X; + padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeWPAPSK; +- memcpy(padapter->securitypriv.supplicant_ie, &pwpa[0], wpa_ielen+2); ++ memcpy(padapter->securitypriv.supplicant_ie, &pwpa[0], wpa_ielen + 2); + + DBG_8192C("got wpa_ie, wpa_ielen:%u\n", wpa_ielen); + } + } + + pwpa2 = rtw_get_wpa2_ie(buf, &wpa2_ielen, ielen); +- if (pwpa2 && wpa2_ielen > 0) +- { +- if (rtw_parse_wpa2_ie(pwpa2, wpa2_ielen+2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) +- { ++ if (pwpa2 && wpa2_ielen > 0) { ++ if (rtw_parse_wpa2_ie(pwpa2, wpa2_ielen + 2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) { + padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_8021X; + padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeWPA2PSK; +- memcpy(padapter->securitypriv.supplicant_ie, &pwpa2[0], wpa2_ielen+2); ++ memcpy(padapter->securitypriv.supplicant_ie, &pwpa2[0], wpa2_ielen + 2); + + DBG_8192C("got wpa2_ie, wpa2_ielen:%u\n", wpa2_ielen); + } +@@ -2303,7 +2299,7 @@ static int cfg80211_rtw_set_pmksa(struct + + memcpy(psecuritypriv->PMKIDList[index].PMKID, (u8 *)pmksa->pmkid, WLAN_PMKID_LEN); + psecuritypriv->PMKIDList[index].bUsed = true; +- psecuritypriv->PMKIDIndex = index+1; ++ psecuritypriv->PMKIDIndex = index + 1; + blInserted = true; + break; + } +@@ -2477,8 +2473,8 @@ static netdev_tx_t rtw_cfg80211_monitor_ + return _rtw_xmit_entry(skb, padapter->pnetdev); + + } +- else if ((frame_control & (IEEE80211_FCTL_FTYPE|IEEE80211_FCTL_STYPE)) +- == (IEEE80211_FTYPE_MGMT|IEEE80211_STYPE_ACTION) ++ else if ((frame_control & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) ++ == (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ACTION) + ) + { + /* only for action frames */ +@@ -2616,7 +2612,7 @@ static int rtw_cfg80211_add_monitor_if(s + } + + *ndev = pwdev_priv->pmon_ndev = mon_ndev; +- memcpy(pwdev_priv->ifname_mon, name, IFNAMSIZ+1); ++ memcpy(pwdev_priv->ifname_mon, name, IFNAMSIZ + 1); + + out: + if (ret && mon_wdev) { +@@ -2719,14 +2715,14 @@ static int rtw_add_beacon(struct adapter + if (head_len < 24) + return -EINVAL; + +- pbuf = rtw_zmalloc(head_len+tail_len); ++ pbuf = rtw_zmalloc(head_len + tail_len); + if (!pbuf) + return -ENOMEM; + +- memcpy(pbuf, (void *)head+24, head_len-24);/* 24 =beacon header len. */ +- memcpy(pbuf+head_len-24, (void *)tail, tail_len); ++ memcpy(pbuf, (void *)head + 24, head_len - 24);/* 24 =beacon header len. */ ++ memcpy(pbuf + head_len - 24, (void *)tail, tail_len); + +- len = head_len+tail_len-24; ++ len = head_len + tail_len - 24; + + /* check wps ie if inclued */ + if (rtw_get_wps_ie(pbuf+_FIXED_IE_LENGTH_, len-_FIXED_IE_LENGTH_, NULL, &wps_ielen)) +@@ -3082,7 +3078,7 @@ static int cfg80211_rtw_mgmt_tx(struct w + pwdev_priv = adapter_wdev_data(padapter); + + /* cookie generation */ +- *cookie = (unsigned long) buf; ++ *cookie = (unsigned long)buf; + + #ifdef DEBUG_CFG80211 + DBG_871X(FUNC_ADPT_FMT" len =%zu, ch =%d" diff --git a/queue-5.10/staging-rtl8723bs-fix-wep-length-underflow-and-oob-read-in-onauth.patch b/queue-5.10/staging-rtl8723bs-fix-wep-length-underflow-and-oob-read-in-onauth.patch new file mode 100644 index 0000000000..2ef14e993f --- /dev/null +++ b/queue-5.10/staging-rtl8723bs-fix-wep-length-underflow-and-oob-read-in-onauth.patch @@ -0,0 +1,74 @@ +From stable+bounces-274605-greg=kroah.com@vger.kernel.org Wed Jul 15 01:34:41 2026 +From: Sasha Levin +Date: Tue, 14 Jul 2026 19:34:07 -0400 +Subject: staging: rtl8723bs: fix WEP length underflow and OOB read in OnAuth() +To: stable@vger.kernel.org +Cc: Alexandru Hossu , stable , Greg Kroah-Hartman , Sasha Levin +Message-ID: <20260714233407.3591885-8-sashal@kernel.org> + +From: Alexandru Hossu + +[ Upstream commit a1fc19d61f661d47204f095b593de507884849f7 ] + +OnAuth() has two bugs in the shared-key authentication path. + +When the Privacy bit is set, rtw_wep_decrypt() is called without +verifying that the frame is long enough to contain a valid WEP IV and +ICV. Inside rtw_wep_decrypt(), length is computed as: + + length = len - WLAN_HDR_A3_LEN - iv_len + +and then passed as (length - 4) to crc32_le(). If len is less than +WLAN_HDR_A3_LEN + iv_len + icv_len (32 bytes), length - 4 is negative +and, after the implicit cast to size_t, causes crc32_le() to read far +beyond the frame buffer. Add a minimum length check before accessing +the IV field and calling the decryption path. + +When processing a seq=3 response, rtw_get_ie() stores the Challenge +Text IE length in ie_len, but the subsequent memcmp() always reads 128 +bytes regardless of ie_len. IEEE 802.11 mandates a challenge text of +exactly 128 bytes; reject any IE whose length field differs, matching +the check already applied to OnAuthClient(). + +Fixes: 554c0a3abf21 ("staging: Add rtl8723bs sdio wifi driver") +Cc: stable +Signed-off-by: Alexandru Hossu +Link: https://patch.msgid.link/20260522004605.1039209-1-hossu.alexandru@gmail.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/staging/rtl8723bs/core/rtw_mlme_ext.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +--- a/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c ++++ b/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c +@@ -886,6 +886,9 @@ unsigned int OnAuth(struct adapter *pada + + DBG_871X("+OnAuth\n"); + ++ if (len < WLAN_HDR_A3_LEN) ++ return _FAIL; ++ + sa = GetAddr2Ptr(pframe); + + auth_mode = psecuritypriv->dot11AuthAlgrthm; +@@ -897,6 +900,9 @@ unsigned int OnAuth(struct adapter *pada + prxattrib->hdrlen = WLAN_HDR_A3_LEN; + prxattrib->encrypt = _WEP40_; + ++ if (len < WLAN_HDR_A3_LEN + 8) ++ return _FAIL; ++ + iv = pframe+prxattrib->hdrlen; + prxattrib->key_index = ((iv[3]>>6)&0x3); + +@@ -1014,7 +1020,7 @@ unsigned int OnAuth(struct adapter *pada + p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + 4 + _AUTH_IE_OFFSET_, _CHLGETXT_IE_, (int *)&ie_len, + len - WLAN_HDR_A3_LEN - _AUTH_IE_OFFSET_ - 4); + +- if (!p || ie_len <= 0) { ++ if (!p || ie_len != 128) { + DBG_871X("auth rejected because challenge failure!(1)\n"); + status = _STATS_CHALLENGE_FAIL_; + goto auth_fail; diff --git a/queue-5.10/staging-rtl8723bs-remove-5ghz-code-blocks.patch b/queue-5.10/staging-rtl8723bs-remove-5ghz-code-blocks.patch new file mode 100644 index 0000000000..f882cd74c3 --- /dev/null +++ b/queue-5.10/staging-rtl8723bs-remove-5ghz-code-blocks.patch @@ -0,0 +1,92 @@ +From stable+bounces-274601-greg=kroah.com@vger.kernel.org Wed Jul 15 01:34:18 2026 +From: Sasha Levin +Date: Tue, 14 Jul 2026 19:34:04 -0400 +Subject: staging: rtl8723bs: remove 5Ghz code blocks +To: stable@vger.kernel.org +Cc: Fabio Aiuto , Greg Kroah-Hartman , Sasha Levin +Message-ID: <20260714233407.3591885-5-sashal@kernel.org> + +From: Fabio Aiuto + +[ Upstream commit ddd7c8b0033ba01a0ee605697f12a33fd31e6fca ] + +remove 5 Ghz code blocks, related to networks +working over channel numbers above 14. + +Signed-off-by: Fabio Aiuto +Link: https://lore.kernel.org/r/c64443b92ce1a60f568db153842a62e3244a8c3a.1626874164.git.fabioaiuto83@gmail.com +Signed-off-by: Greg Kroah-Hartman +Stable-dep-of: a1fc19d61f66 ("staging: rtl8723bs: fix WEP length underflow and OOB read in OnAuth()") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/staging/rtl8723bs/core/rtw_mlme_ext.c | 7 ++----- + drivers/staging/rtl8723bs/os_dep/ioctl_linux.c | 20 +++----------------- + 2 files changed, 5 insertions(+), 22 deletions(-) + +--- a/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c ++++ b/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c +@@ -4116,7 +4116,7 @@ static void issue_action_BSSCoexistPacke + p = rtw_get_ie(pbss_network->IEs + _FIXED_IE_LENGTH_, _HT_CAPABILITY_IE_, &len, pbss_network->IELength - _FIXED_IE_LENGTH_); + if ((p == NULL) || (len == 0)) {/* non-HT */ + +- if ((pbss_network->Configuration.DSConfig <= 0) || (pbss_network->Configuration.DSConfig > 14)) ++ if (pbss_network->Configuration.DSConfig <= 0) + continue; + + ICS[0][pbss_network->Configuration.DSConfig] = 1; +@@ -6118,10 +6118,7 @@ u8 join_cmd_hdl(struct adapter *padapter + { + struct HT_info_element *pht_info = (struct HT_info_element *)(pIE->data); + +- if (pnetwork->Configuration.DSConfig > 14) { +- if ((pregpriv->bw_mode >> 4) > CHANNEL_WIDTH_20) +- cbw40_enable = 1; +- } else { ++ if (pnetwork->Configuration.DSConfig <= 14) { + if ((pregpriv->bw_mode & 0x0f) > CHANNEL_WIDTH_20) + cbw40_enable = 1; + } +--- a/drivers/staging/rtl8723bs/os_dep/ioctl_linux.c ++++ b/drivers/staging/rtl8723bs/os_dep/ioctl_linux.c +@@ -135,14 +135,7 @@ static char *translate_scan(struct adapt + else + snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bg"); + } else { +- if (pnetwork->network.Configuration.DSConfig > 14) { +- if (vht_cap) +- snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11AC"); +- else if (ht_cap) +- snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11an"); +- else +- snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11a"); +- } else { ++ if (pnetwork->network.Configuration.DSConfig <= 14) { + if (ht_cap) + snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11gn"); + else +@@ -762,7 +755,7 @@ static int rtw_wx_get_name(struct net_de + struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); + u32 ht_ielen = 0; + char *p; +- u8 ht_cap = false, vht_cap = false; ++ u8 ht_cap = false; + struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); + struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network; + NDIS_802_11_RATES_EX* prates = NULL; +@@ -788,14 +781,7 @@ static int rtw_wx_get_name(struct net_de + else + snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11bg"); + } else { +- if (pcur_bss->Configuration.DSConfig > 14) { +- if (vht_cap) +- snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11AC"); +- else if (ht_cap) +- snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11an"); +- else +- snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11a"); +- } else { ++ if (pcur_bss->Configuration.DSConfig <= 14) { + if (ht_cap) + snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11gn"); + else diff --git a/queue-5.10/staging-rtl8723bs-remove-5ghz-code-related-to-channel-plan-definition.patch b/queue-5.10/staging-rtl8723bs-remove-5ghz-code-related-to-channel-plan-definition.patch new file mode 100644 index 0000000000..a473eeb44d --- /dev/null +++ b/queue-5.10/staging-rtl8723bs-remove-5ghz-code-related-to-channel-plan-definition.patch @@ -0,0 +1,494 @@ +From stable+bounces-274602-greg=kroah.com@vger.kernel.org Wed Jul 15 01:34:29 2026 +From: Sasha Levin +Date: Tue, 14 Jul 2026 19:34:03 -0400 +Subject: staging: rtl8723bs: remove 5Ghz code related to channel plan definition +To: stable@vger.kernel.org +Cc: Fabio Aiuto , Hans de Goede , Greg Kroah-Hartman , Sasha Levin +Message-ID: <20260714233407.3591885-4-sashal@kernel.org> + +From: Fabio Aiuto + +[ Upstream commit ec84d0ae54a6774091b3b7d1e9da32589f48b2f9 ] + +remove 5Ghz code related to channel plan definition. + +Acked-by: Hans de Goede +Signed-off-by: Fabio Aiuto +Link: https://lore.kernel.org/r/17a707952cec951893748d2cb59d02a294cdd1be.1624367071.git.fabioaiuto83@gmail.com +Signed-off-by: Greg Kroah-Hartman +Stable-dep-of: a1fc19d61f66 ("staging: rtl8723bs: fix WEP length underflow and OOB read in OnAuth()") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/staging/rtl8723bs/core/rtw_mlme_ext.c | 210 +++++++++------------- + drivers/staging/rtl8723bs/hal/hal_com_phycfg.c | 34 --- + drivers/staging/rtl8723bs/include/rtw_mlme_ext.h | 6 + drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c | 2 + drivers/staging/rtl8723bs/os_dep/ioctl_linux.c | 1 + 5 files changed, 94 insertions(+), 159 deletions(-) + +--- a/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c ++++ b/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c +@@ -123,93 +123,93 @@ static RT_CHANNEL_PLAN_5G RTW_ChannelPla + + static RT_CHANNEL_PLAN_MAP RTW_ChannelPlanMap[RT_CHANNEL_DOMAIN_MAX] = { + /* 0x00 ~ 0x1F , Old Define ===== */ +- {0x02, 0x20}, /* 0x00, RT_CHANNEL_DOMAIN_FCC */ +- {0x02, 0x0A}, /* 0x01, RT_CHANNEL_DOMAIN_IC */ +- {0x01, 0x01}, /* 0x02, RT_CHANNEL_DOMAIN_ETSI */ +- {0x01, 0x00}, /* 0x03, RT_CHANNEL_DOMAIN_SPAIN */ +- {0x01, 0x00}, /* 0x04, RT_CHANNEL_DOMAIN_FRANCE */ +- {0x03, 0x00}, /* 0x05, RT_CHANNEL_DOMAIN_MKK */ +- {0x03, 0x00}, /* 0x06, RT_CHANNEL_DOMAIN_MKK1 */ +- {0x01, 0x09}, /* 0x07, RT_CHANNEL_DOMAIN_ISRAEL */ +- {0x03, 0x09}, /* 0x08, RT_CHANNEL_DOMAIN_TELEC */ +- {0x03, 0x00}, /* 0x09, RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN */ +- {0x00, 0x00}, /* 0x0A, RT_CHANNEL_DOMAIN_WORLD_WIDE_13 */ +- {0x02, 0x0F}, /* 0x0B, RT_CHANNEL_DOMAIN_TAIWAN */ +- {0x01, 0x08}, /* 0x0C, RT_CHANNEL_DOMAIN_CHINA */ +- {0x02, 0x06}, /* 0x0D, RT_CHANNEL_DOMAIN_SINGAPORE_INDIA_MEXICO */ +- {0x02, 0x0B}, /* 0x0E, RT_CHANNEL_DOMAIN_KOREA */ +- {0x02, 0x09}, /* 0x0F, RT_CHANNEL_DOMAIN_TURKEY */ +- {0x01, 0x01}, /* 0x10, RT_CHANNEL_DOMAIN_JAPAN */ +- {0x02, 0x05}, /* 0x11, RT_CHANNEL_DOMAIN_FCC_NO_DFS */ +- {0x01, 0x21}, /* 0x12, RT_CHANNEL_DOMAIN_JAPAN_NO_DFS */ +- {0x00, 0x04}, /* 0x13, RT_CHANNEL_DOMAIN_WORLD_WIDE_5G */ +- {0x02, 0x10}, /* 0x14, RT_CHANNEL_DOMAIN_TAIWAN_NO_DFS */ +- {0x00, 0x21}, /* 0x15, RT_CHANNEL_DOMAIN_ETSI_NO_DFS */ +- {0x00, 0x22}, /* 0x16, RT_CHANNEL_DOMAIN_KOREA_NO_DFS */ +- {0x03, 0x21}, /* 0x17, RT_CHANNEL_DOMAIN_JAPAN_NO_DFS */ +- {0x06, 0x08}, /* 0x18, RT_CHANNEL_DOMAIN_PAKISTAN_NO_DFS */ +- {0x02, 0x08}, /* 0x19, RT_CHANNEL_DOMAIN_TAIWAN2_NO_DFS */ +- {0x00, 0x00}, /* 0x1A, */ +- {0x00, 0x00}, /* 0x1B, */ +- {0x00, 0x00}, /* 0x1C, */ +- {0x00, 0x00}, /* 0x1D, */ +- {0x00, 0x00}, /* 0x1E, */ +- {0x06, 0x04}, /* 0x1F, RT_CHANNEL_DOMAIN_WORLD_WIDE_ONLY_5G */ ++ {0x02}, /* 0x00, RT_CHANNEL_DOMAIN_FCC */ ++ {0x02}, /* 0x01, RT_CHANNEL_DOMAIN_IC */ ++ {0x01}, /* 0x02, RT_CHANNEL_DOMAIN_ETSI */ ++ {0x01}, /* 0x03, RT_CHANNEL_DOMAIN_SPAIN */ ++ {0x01}, /* 0x04, RT_CHANNEL_DOMAIN_FRANCE */ ++ {0x03}, /* 0x05, RT_CHANNEL_DOMAIN_MKK */ ++ {0x03}, /* 0x06, RT_CHANNEL_DOMAIN_MKK1 */ ++ {0x01}, /* 0x07, RT_CHANNEL_DOMAIN_ISRAEL */ ++ {0x03}, /* 0x08, RT_CHANNEL_DOMAIN_TELEC */ ++ {0x03}, /* 0x09, RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN */ ++ {0x00}, /* 0x0A, RT_CHANNEL_DOMAIN_WORLD_WIDE_13 */ ++ {0x02}, /* 0x0B, RT_CHANNEL_DOMAIN_TAIWAN */ ++ {0x01}, /* 0x0C, RT_CHANNEL_DOMAIN_CHINA */ ++ {0x02}, /* 0x0D, RT_CHANNEL_DOMAIN_SINGAPORE_INDIA_MEXICO */ ++ {0x02}, /* 0x0E, RT_CHANNEL_DOMAIN_KOREA */ ++ {0x02}, /* 0x0F, RT_CHANNEL_DOMAIN_TURKEY */ ++ {0x01}, /* 0x10, RT_CHANNEL_DOMAIN_JAPAN */ ++ {0x02}, /* 0x11, RT_CHANNEL_DOMAIN_FCC_NO_DFS */ ++ {0x01}, /* 0x12, RT_CHANNEL_DOMAIN_JAPAN_NO_DFS */ ++ {0x00}, /* 0x13, RT_CHANNEL_DOMAIN_WORLD_WIDE_5G */ ++ {0x02}, /* 0x14, RT_CHANNEL_DOMAIN_TAIWAN_NO_DFS */ ++ {0x00}, /* 0x15, RT_CHANNEL_DOMAIN_ETSI_NO_DFS */ ++ {0x00}, /* 0x16, RT_CHANNEL_DOMAIN_KOREA_NO_DFS */ ++ {0x03}, /* 0x17, RT_CHANNEL_DOMAIN_JAPAN_NO_DFS */ ++ {0x06}, /* 0x18, RT_CHANNEL_DOMAIN_PAKISTAN_NO_DFS */ ++ {0x02}, /* 0x19, RT_CHANNEL_DOMAIN_TAIWAN2_NO_DFS */ ++ {0x00}, /* 0x1A, */ ++ {0x00}, /* 0x1B, */ ++ {0x00}, /* 0x1C, */ ++ {0x00}, /* 0x1D, */ ++ {0x00}, /* 0x1E, */ ++ {0x06}, /* 0x1F, RT_CHANNEL_DOMAIN_WORLD_WIDE_ONLY_5G */ + /* 0x20 ~ 0x7F , New Define ===== */ +- {0x00, 0x00}, /* 0x20, RT_CHANNEL_DOMAIN_WORLD_NULL */ +- {0x01, 0x00}, /* 0x21, RT_CHANNEL_DOMAIN_ETSI1_NULL */ +- {0x02, 0x00}, /* 0x22, RT_CHANNEL_DOMAIN_FCC1_NULL */ +- {0x03, 0x00}, /* 0x23, RT_CHANNEL_DOMAIN_MKK1_NULL */ +- {0x04, 0x00}, /* 0x24, RT_CHANNEL_DOMAIN_ETSI2_NULL */ +- {0x02, 0x04}, /* 0x25, RT_CHANNEL_DOMAIN_FCC1_FCC1 */ +- {0x00, 0x01}, /* 0x26, RT_CHANNEL_DOMAIN_WORLD_ETSI1 */ +- {0x03, 0x0C}, /* 0x27, RT_CHANNEL_DOMAIN_MKK1_MKK1 */ +- {0x00, 0x0B}, /* 0x28, RT_CHANNEL_DOMAIN_WORLD_KCC1 */ +- {0x00, 0x05}, /* 0x29, RT_CHANNEL_DOMAIN_WORLD_FCC2 */ +- {0x00, 0x00}, /* 0x2A, */ +- {0x00, 0x00}, /* 0x2B, */ +- {0x00, 0x00}, /* 0x2C, */ +- {0x00, 0x00}, /* 0x2D, */ +- {0x00, 0x00}, /* 0x2E, */ +- {0x00, 0x00}, /* 0x2F, */ +- {0x00, 0x06}, /* 0x30, RT_CHANNEL_DOMAIN_WORLD_FCC3 */ +- {0x00, 0x07}, /* 0x31, RT_CHANNEL_DOMAIN_WORLD_FCC4 */ +- {0x00, 0x08}, /* 0x32, RT_CHANNEL_DOMAIN_WORLD_FCC5 */ +- {0x00, 0x09}, /* 0x33, RT_CHANNEL_DOMAIN_WORLD_FCC6 */ +- {0x02, 0x0A}, /* 0x34, RT_CHANNEL_DOMAIN_FCC1_FCC7 */ +- {0x00, 0x02}, /* 0x35, RT_CHANNEL_DOMAIN_WORLD_ETSI2 */ +- {0x00, 0x03}, /* 0x36, RT_CHANNEL_DOMAIN_WORLD_ETSI3 */ +- {0x03, 0x0D}, /* 0x37, RT_CHANNEL_DOMAIN_MKK1_MKK2 */ +- {0x03, 0x0E}, /* 0x38, RT_CHANNEL_DOMAIN_MKK1_MKK3 */ +- {0x02, 0x0F}, /* 0x39, RT_CHANNEL_DOMAIN_FCC1_NCC1 */ +- {0x00, 0x00}, /* 0x3A, */ +- {0x00, 0x00}, /* 0x3B, */ +- {0x00, 0x00}, /* 0x3C, */ +- {0x00, 0x00}, /* 0x3D, */ +- {0x00, 0x00}, /* 0x3E, */ +- {0x00, 0x00}, /* 0x3F, */ +- {0x02, 0x10}, /* 0x40, RT_CHANNEL_DOMAIN_FCC1_NCC2 */ +- {0x05, 0x00}, /* 0x41, RT_CHANNEL_DOMAIN_GLOBAL_NULL */ +- {0x01, 0x12}, /* 0x42, RT_CHANNEL_DOMAIN_ETSI1_ETSI4 */ +- {0x02, 0x05}, /* 0x43, RT_CHANNEL_DOMAIN_FCC1_FCC2 */ +- {0x02, 0x11}, /* 0x44, RT_CHANNEL_DOMAIN_FCC1_NCC3 */ +- {0x00, 0x13}, /* 0x45, RT_CHANNEL_DOMAIN_WORLD_ETSI5 */ +- {0x02, 0x14}, /* 0x46, RT_CHANNEL_DOMAIN_FCC1_FCC8 */ +- {0x00, 0x15}, /* 0x47, RT_CHANNEL_DOMAIN_WORLD_ETSI6 */ +- {0x00, 0x16}, /* 0x48, RT_CHANNEL_DOMAIN_WORLD_ETSI7 */ +- {0x00, 0x17}, /* 0x49, RT_CHANNEL_DOMAIN_WORLD_ETSI8 */ +- {0x00, 0x18}, /* 0x50, RT_CHANNEL_DOMAIN_WORLD_ETSI9 */ +- {0x00, 0x19}, /* 0x51, RT_CHANNEL_DOMAIN_WORLD_ETSI10 */ +- {0x00, 0x1A}, /* 0x52, RT_CHANNEL_DOMAIN_WORLD_ETSI11 */ +- {0x02, 0x1B}, /* 0x53, RT_CHANNEL_DOMAIN_FCC1_NCC4 */ +- {0x00, 0x1C}, /* 0x54, RT_CHANNEL_DOMAIN_WORLD_ETSI12 */ +- {0x02, 0x1D}, /* 0x55, RT_CHANNEL_DOMAIN_FCC1_FCC9 */ +- {0x00, 0x1E}, /* 0x56, RT_CHANNEL_DOMAIN_WORLD_ETSI13 */ +- {0x02, 0x1F}, /* 0x57, RT_CHANNEL_DOMAIN_FCC1_FCC10 */ ++ {0x00}, /* 0x20, RT_CHANNEL_DOMAIN_WORLD_NULL */ ++ {0x01}, /* 0x21, RT_CHANNEL_DOMAIN_ETSI1_NULL */ ++ {0x02}, /* 0x22, RT_CHANNEL_DOMAIN_FCC1_NULL */ ++ {0x03}, /* 0x23, RT_CHANNEL_DOMAIN_MKK1_NULL */ ++ {0x04}, /* 0x24, RT_CHANNEL_DOMAIN_ETSI2_NULL */ ++ {0x02}, /* 0x25, RT_CHANNEL_DOMAIN_FCC1_FCC1 */ ++ {0x00}, /* 0x26, RT_CHANNEL_DOMAIN_WORLD_ETSI1 */ ++ {0x03}, /* 0x27, RT_CHANNEL_DOMAIN_MKK1_MKK1 */ ++ {0x00}, /* 0x28, RT_CHANNEL_DOMAIN_WORLD_KCC1 */ ++ {0x00}, /* 0x29, RT_CHANNEL_DOMAIN_WORLD_FCC2 */ ++ {0x00}, /* 0x2A, */ ++ {0x00}, /* 0x2B, */ ++ {0x00}, /* 0x2C, */ ++ {0x00}, /* 0x2D, */ ++ {0x00}, /* 0x2E, */ ++ {0x00}, /* 0x2F, */ ++ {0x00}, /* 0x30, RT_CHANNEL_DOMAIN_WORLD_FCC3 */ ++ {0x00}, /* 0x31, RT_CHANNEL_DOMAIN_WORLD_FCC4 */ ++ {0x00}, /* 0x32, RT_CHANNEL_DOMAIN_WORLD_FCC5 */ ++ {0x00}, /* 0x33, RT_CHANNEL_DOMAIN_WORLD_FCC6 */ ++ {0x02}, /* 0x34, RT_CHANNEL_DOMAIN_FCC1_FCC7 */ ++ {0x00}, /* 0x35, RT_CHANNEL_DOMAIN_WORLD_ETSI2 */ ++ {0x00}, /* 0x36, RT_CHANNEL_DOMAIN_WORLD_ETSI3 */ ++ {0x03}, /* 0x37, RT_CHANNEL_DOMAIN_MKK1_MKK2 */ ++ {0x03}, /* 0x38, RT_CHANNEL_DOMAIN_MKK1_MKK3 */ ++ {0x02}, /* 0x39, RT_CHANNEL_DOMAIN_FCC1_NCC1 */ ++ {0x00}, /* 0x3A, */ ++ {0x00}, /* 0x3B, */ ++ {0x00}, /* 0x3C, */ ++ {0x00}, /* 0x3D, */ ++ {0x00}, /* 0x3E, */ ++ {0x00}, /* 0x3F, */ ++ {0x02}, /* 0x40, RT_CHANNEL_DOMAIN_FCC1_NCC2 */ ++ {0x05}, /* 0x41, RT_CHANNEL_DOMAIN_GLOBAL_NULL */ ++ {0x01}, /* 0x42, RT_CHANNEL_DOMAIN_ETSI1_ETSI4 */ ++ {0x02}, /* 0x43, RT_CHANNEL_DOMAIN_FCC1_FCC2 */ ++ {0x02}, /* 0x44, RT_CHANNEL_DOMAIN_FCC1_NCC3 */ ++ {0x00}, /* 0x45, RT_CHANNEL_DOMAIN_WORLD_ETSI5 */ ++ {0x02}, /* 0x46, RT_CHANNEL_DOMAIN_FCC1_FCC8 */ ++ {0x00}, /* 0x47, RT_CHANNEL_DOMAIN_WORLD_ETSI6 */ ++ {0x00}, /* 0x48, RT_CHANNEL_DOMAIN_WORLD_ETSI7 */ ++ {0x00}, /* 0x49, RT_CHANNEL_DOMAIN_WORLD_ETSI8 */ ++ {0x00}, /* 0x50, RT_CHANNEL_DOMAIN_WORLD_ETSI9 */ ++ {0x00}, /* 0x51, RT_CHANNEL_DOMAIN_WORLD_ETSI10 */ ++ {0x00}, /* 0x52, RT_CHANNEL_DOMAIN_WORLD_ETSI11 */ ++ {0x02}, /* 0x53, RT_CHANNEL_DOMAIN_FCC1_NCC4 */ ++ {0x00}, /* 0x54, RT_CHANNEL_DOMAIN_WORLD_ETSI12 */ ++ {0x02}, /* 0x55, RT_CHANNEL_DOMAIN_FCC1_FCC9 */ ++ {0x00}, /* 0x56, RT_CHANNEL_DOMAIN_WORLD_ETSI13 */ ++ {0x02}, /* 0x57, RT_CHANNEL_DOMAIN_FCC1_FCC10 */ + }; + + /* use the combination for max channel numbers */ +-static RT_CHANNEL_PLAN_MAP RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE = {0x03, 0x02}; ++static RT_CHANNEL_PLAN_MAP RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE = {0x03}; + + /* Search the @param ch in given @param ch_set + * @ch_set: the given channel set +@@ -231,23 +231,6 @@ int rtw_ch_set_search_ch(RT_CHANNEL_INFO + return i; + } + +-/* Check the @param ch is fit with setband setting of @param adapter +- * @adapter: the given adapter +- * @ch: the given channel number +- * +- * return true when check valid, false not valid +- */ +-bool rtw_mlme_band_check(struct adapter *adapter, const u32 ch) +-{ +- if (adapter->setband == GHZ24_50 /* 2.4G and 5G */ +- || (adapter->setband == GHZ_24 && ch < 35) /* 2.4G only */ +- || (adapter->setband == GHZ_50 && ch > 35) /* 5G only */ +- ) { +- return true; +- } +- return false; +-} +- + /**************************************************************************** + + Following are the initialization functions for WiFi MLME +@@ -424,7 +407,6 @@ static u8 init_channel_set(struct adapte + else if ((channel_set[chanset_size].ChannelNum >= 12 && channel_set[chanset_size].ChannelNum <= 14)) + channel_set[chanset_size].ScanType = SCAN_PASSIVE; + } else if (RT_CHANNEL_DOMAIN_WORLD_WIDE_13 == ChannelPlan || +- RT_CHANNEL_DOMAIN_WORLD_WIDE_5G == ChannelPlan || + RT_CHANNEL_DOMAIN_2G_WORLD == Index2G) { /* channel 12~13, passive scan */ + if (channel_set[chanset_size].ChannelNum <= 11) + channel_set[chanset_size].ScanType = SCAN_ACTIVE; +@@ -4938,10 +4920,6 @@ static void process_80211d(struct adapte + while ((i < MAX_CHANNEL_NUM) && (chplan_new[i].ChannelNum != 0)) { + if (chplan_new[i].ChannelNum == channel) { + if (chplan_new[i].ScanType == SCAN_PASSIVE) { +- /* 5G Bnad 2, 3 (DFS) doesn't change to active scan */ +- if (channel >= 52 && channel <= 144) +- break; +- + chplan_new[i].ScanType = SCAN_ACTIVE; + RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_, + ("%s: change channel %d scan type from passive to active\n", +@@ -6250,7 +6228,6 @@ static int rtw_scan_ch_decision(struct a + set_idx = rtw_ch_set_search_ch(pmlmeext->channel_set, in[i].hw_value); + if (in[i].hw_value && !(in[i].flags & RTW_IEEE80211_CHAN_DISABLED) + && set_idx >= 0 +- && rtw_mlme_band_check(padapter, in[i].hw_value) + ) { + if (j >= out_num) { + DBG_871X_LEVEL(_drv_always_, FUNC_ADPT_FMT" out_num:%u not enough\n", +@@ -6275,21 +6252,18 @@ static int rtw_scan_ch_decision(struct a + + DBG_871X(FUNC_ADPT_FMT" ch:%u\n", FUNC_ADPT_ARG(padapter), pmlmeext->channel_set[i].ChannelNum); + +- if (rtw_mlme_band_check(padapter, pmlmeext->channel_set[i].ChannelNum)) { +- +- if (j >= out_num) { +- DBG_871X_LEVEL(_drv_always_, FUNC_ADPT_FMT" out_num:%u not enough\n", +- FUNC_ADPT_ARG(padapter), out_num); +- break; +- } ++ if (j >= out_num) { ++ DBG_871X_LEVEL(_drv_always_, FUNC_ADPT_FMT" out_num:%u not enough\n", ++ FUNC_ADPT_ARG(padapter), out_num); ++ break; ++ } + +- out[j].hw_value = pmlmeext->channel_set[i].ChannelNum; ++ out[j].hw_value = pmlmeext->channel_set[i].ChannelNum; + +- if (pmlmeext->channel_set[i].ScanType == SCAN_PASSIVE) +- out[j].flags |= RTW_IEEE80211_CHAN_PASSIVE_SCAN; ++ if (pmlmeext->channel_set[i].ScanType == SCAN_PASSIVE) ++ out[j].flags |= RTW_IEEE80211_CHAN_PASSIVE_SCAN; + +- j++; +- } ++ j++; + } + } + +--- a/drivers/staging/rtl8723bs/hal/hal_com_phycfg.c ++++ b/drivers/staging/rtl8723bs/hal/hal_com_phycfg.c +@@ -2062,139 +2062,105 @@ void Hal_ChannelPlanToRegulation(struct + break; + case RT_CHANNEL_DOMAIN_FCC1_FCC1: + pHalData->Regulation2_4G = TXPWR_LMT_FCC; +- pHalData->Regulation5G = TXPWR_LMT_FCC; + break; + case RT_CHANNEL_DOMAIN_WORLD_ETSI1: + pHalData->Regulation2_4G = TXPWR_LMT_FCC; +- pHalData->Regulation5G = TXPWR_LMT_ETSI; + break; + case RT_CHANNEL_DOMAIN_MKK1_MKK1: + pHalData->Regulation2_4G = TXPWR_LMT_MKK; +- pHalData->Regulation5G = TXPWR_LMT_MKK; + break; + case RT_CHANNEL_DOMAIN_WORLD_KCC1: + pHalData->Regulation2_4G = TXPWR_LMT_FCC; +- pHalData->Regulation5G = TXPWR_LMT_MKK; + break; + case RT_CHANNEL_DOMAIN_WORLD_FCC2: + pHalData->Regulation2_4G = TXPWR_LMT_FCC; +- pHalData->Regulation5G = TXPWR_LMT_FCC; + break; + case RT_CHANNEL_DOMAIN_WORLD_FCC3: + pHalData->Regulation2_4G = TXPWR_LMT_FCC; +- pHalData->Regulation5G = TXPWR_LMT_FCC; + break; + case RT_CHANNEL_DOMAIN_WORLD_FCC4: + pHalData->Regulation2_4G = TXPWR_LMT_FCC; +- pHalData->Regulation5G = TXPWR_LMT_FCC; + break; + case RT_CHANNEL_DOMAIN_WORLD_FCC5: + pHalData->Regulation2_4G = TXPWR_LMT_FCC; +- pHalData->Regulation5G = TXPWR_LMT_FCC; + break; + case RT_CHANNEL_DOMAIN_WORLD_FCC6: + pHalData->Regulation2_4G = TXPWR_LMT_FCC; +- pHalData->Regulation5G = TXPWR_LMT_FCC; + break; + case RT_CHANNEL_DOMAIN_FCC1_FCC7: + pHalData->Regulation2_4G = TXPWR_LMT_FCC; +- pHalData->Regulation5G = TXPWR_LMT_FCC; + break; + case RT_CHANNEL_DOMAIN_WORLD_ETSI2: + pHalData->Regulation2_4G = TXPWR_LMT_FCC; +- pHalData->Regulation5G = TXPWR_LMT_FCC; + break; + case RT_CHANNEL_DOMAIN_WORLD_ETSI3: + pHalData->Regulation2_4G = TXPWR_LMT_FCC; +- pHalData->Regulation5G = TXPWR_LMT_FCC; + break; + case RT_CHANNEL_DOMAIN_MKK1_MKK2: + pHalData->Regulation2_4G = TXPWR_LMT_MKK; +- pHalData->Regulation5G = TXPWR_LMT_FCC; + break; + case RT_CHANNEL_DOMAIN_MKK1_MKK3: + pHalData->Regulation2_4G = TXPWR_LMT_MKK; +- pHalData->Regulation5G = TXPWR_LMT_FCC; + break; + case RT_CHANNEL_DOMAIN_FCC1_NCC1: + pHalData->Regulation2_4G = TXPWR_LMT_FCC; +- pHalData->Regulation5G = TXPWR_LMT_FCC; + break; + case RT_CHANNEL_DOMAIN_FCC1_NCC2: + pHalData->Regulation2_4G = TXPWR_LMT_FCC; +- pHalData->Regulation5G = TXPWR_LMT_FCC; + break; + case RT_CHANNEL_DOMAIN_GLOBAL_NULL: + pHalData->Regulation2_4G = TXPWR_LMT_WW; +- pHalData->Regulation5G = TXPWR_LMT_WW; + break; + case RT_CHANNEL_DOMAIN_ETSI1_ETSI4: + pHalData->Regulation2_4G = TXPWR_LMT_ETSI; +- pHalData->Regulation5G = TXPWR_LMT_ETSI; + break; + case RT_CHANNEL_DOMAIN_FCC1_FCC2: + pHalData->Regulation2_4G = TXPWR_LMT_FCC; +- pHalData->Regulation5G = TXPWR_LMT_FCC; + break; + case RT_CHANNEL_DOMAIN_FCC1_NCC3: + pHalData->Regulation2_4G = TXPWR_LMT_FCC; +- pHalData->Regulation5G = TXPWR_LMT_FCC; + break; + case RT_CHANNEL_DOMAIN_WORLD_ETSI5: + pHalData->Regulation2_4G = TXPWR_LMT_ETSI; +- pHalData->Regulation5G = TXPWR_LMT_ETSI; + break; + case RT_CHANNEL_DOMAIN_FCC1_FCC8: + pHalData->Regulation2_4G = TXPWR_LMT_FCC; +- pHalData->Regulation5G = TXPWR_LMT_FCC; + break; + case RT_CHANNEL_DOMAIN_WORLD_ETSI6: + pHalData->Regulation2_4G = TXPWR_LMT_ETSI; +- pHalData->Regulation5G = TXPWR_LMT_ETSI; + break; + case RT_CHANNEL_DOMAIN_WORLD_ETSI7: + pHalData->Regulation2_4G = TXPWR_LMT_ETSI; +- pHalData->Regulation5G = TXPWR_LMT_ETSI; + break; + case RT_CHANNEL_DOMAIN_WORLD_ETSI8: + pHalData->Regulation2_4G = TXPWR_LMT_ETSI; +- pHalData->Regulation5G = TXPWR_LMT_ETSI; + break; + case RT_CHANNEL_DOMAIN_WORLD_ETSI9: + pHalData->Regulation2_4G = TXPWR_LMT_ETSI; +- pHalData->Regulation5G = TXPWR_LMT_ETSI; + break; + case RT_CHANNEL_DOMAIN_WORLD_ETSI10: + pHalData->Regulation2_4G = TXPWR_LMT_ETSI; +- pHalData->Regulation5G = TXPWR_LMT_ETSI; + break; + case RT_CHANNEL_DOMAIN_WORLD_ETSI11: + pHalData->Regulation2_4G = TXPWR_LMT_ETSI; +- pHalData->Regulation5G = TXPWR_LMT_ETSI; + break; + case RT_CHANNEL_DOMAIN_FCC1_NCC4: + pHalData->Regulation2_4G = TXPWR_LMT_FCC; +- pHalData->Regulation5G = TXPWR_LMT_FCC; + break; + case RT_CHANNEL_DOMAIN_WORLD_ETSI12: + pHalData->Regulation2_4G = TXPWR_LMT_ETSI; +- pHalData->Regulation5G = TXPWR_LMT_ETSI; + break; + case RT_CHANNEL_DOMAIN_FCC1_FCC9: + pHalData->Regulation2_4G = TXPWR_LMT_FCC; +- pHalData->Regulation5G = TXPWR_LMT_FCC; + break; + case RT_CHANNEL_DOMAIN_WORLD_ETSI13: + pHalData->Regulation2_4G = TXPWR_LMT_ETSI; +- pHalData->Regulation5G = TXPWR_LMT_ETSI; + break; + case RT_CHANNEL_DOMAIN_FCC1_FCC10: + pHalData->Regulation2_4G = TXPWR_LMT_FCC; +- pHalData->Regulation5G = TXPWR_LMT_FCC; + break; + case RT_CHANNEL_DOMAIN_REALTEK_DEFINE: /* Realtek Reserve */ + pHalData->Regulation2_4G = TXPWR_LMT_WW; +- pHalData->Regulation5G = TXPWR_LMT_WW; + break; + default: + break; +--- a/drivers/staging/rtl8723bs/include/rtw_mlme_ext.h ++++ b/drivers/staging/rtl8723bs/include/rtw_mlme_ext.h +@@ -255,7 +255,6 @@ typedef struct _RT_CHANNEL_PLAN_5G { + + typedef struct _RT_CHANNEL_PLAN_MAP { + unsigned char Index2G; +- unsigned char Index5G; + } RT_CHANNEL_PLAN_MAP, *PRT_CHANNEL_PLAN_MAP; + + enum Associated_AP { +@@ -360,13 +359,13 @@ struct FW_Sta_Info { + * When the driver scanned RTW_SCAN_NUM_OF_CH channels, it would switch back to AP's operating channel for + * RTW_STAY_AP_CH_MILLISECOND * SURVEY_TO milliseconds. + * Example: +- * For chip supports 2.4G + 5GHz and AP mode is operating in channel 1, ++ * For chip supports 2.4G and AP mode is operating in channel 1, + * RTW_SCAN_NUM_OF_CH is 8, RTW_STAY_AP_CH_MILLISECOND is 3 and SURVEY_TO is 100. + * When it's STA mode gets set_scan command, + * it would + * 1. Doing the scan on channel 1.2.3.4.5.6.7.8 + * 2. Back to channel 1 for 300 milliseconds +- * 3. Go through doing site survey on channel 9.10.11.36.40.44.48.52 ++ * 3. Go through doing site survey on channel 9.10.11 + * 4. Back to channel 1 for 300 milliseconds + * 5. ... and so on, till survey done. + */ +@@ -423,7 +422,6 @@ typedef struct _RT_CHANNEL_INFO { + } RT_CHANNEL_INFO, *PRT_CHANNEL_INFO; + + int rtw_ch_set_search_ch(RT_CHANNEL_INFO *ch_set, const u32 ch); +-bool rtw_mlme_band_check(struct adapter *adapter, const u32 ch); + + /* P2P_MAX_REG_CLASSES - Maximum number of regulatory classes */ + #define P2P_MAX_REG_CLASSES 10 +--- a/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c ++++ b/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c +@@ -77,7 +77,6 @@ static struct ieee80211_rate rtw_rates[] + #define RTW_G_RATES_NUM 12 + + #define RTW_2G_CHANNELS_NUM 14 +-#define RTW_5G_CHANNELS_NUM 37 + + static struct ieee80211_channel rtw_2ghz_channels[] = { + CHAN2G(1, 2412, 0), +@@ -1422,7 +1421,6 @@ void rtw_cfg80211_surveydone_event_callb + + /* report network only if the current channel set contains the channel to which this network belongs */ + if (rtw_ch_set_search_ch(padapter->mlmeextpriv.channel_set, pnetwork->network.Configuration.DSConfig) >= 0 +- && rtw_mlme_band_check(padapter, pnetwork->network.Configuration.DSConfig) == true + && true == rtw_validate_ssid(&(pnetwork->network.Ssid)) + ) + { +--- a/drivers/staging/rtl8723bs/os_dep/ioctl_linux.c ++++ b/drivers/staging/rtl8723bs/os_dep/ioctl_linux.c +@@ -1462,7 +1462,6 @@ static int rtw_wx_get_scan(struct net_de + + /* report network only if the current channel set contains the channel to which this network belongs */ + if (rtw_ch_set_search_ch(padapter->mlmeextpriv.channel_set, pnetwork->network.Configuration.DSConfig) >= 0 +- && rtw_mlme_band_check(padapter, pnetwork->network.Configuration.DSConfig) == true + && true == rtw_validate_ssid(&(pnetwork->network.Ssid))) { + + ev = translate_scan(padapter, a, pnetwork, ev, stop); diff --git a/queue-5.10/staging-rtl8723bs-remove-all-5ghz-network-types.patch b/queue-5.10/staging-rtl8723bs-remove-all-5ghz-network-types.patch new file mode 100644 index 0000000000..a88957e7b9 --- /dev/null +++ b/queue-5.10/staging-rtl8723bs-remove-all-5ghz-network-types.patch @@ -0,0 +1,460 @@ +From stable+bounces-274600-greg=kroah.com@vger.kernel.org Wed Jul 15 01:34:21 2026 +From: Sasha Levin +Date: Tue, 14 Jul 2026 19:34:02 -0400 +Subject: staging: rtl8723bs: remove all 5Ghz network types +To: stable@vger.kernel.org +Cc: Fabio Aiuto , Hans de Goede , Greg Kroah-Hartman , Sasha Levin +Message-ID: <20260714233407.3591885-3-sashal@kernel.org> + +From: Fabio Aiuto + +[ Upstream commit 708180a92cd8bff18b3d2ac05172815bcc0b6b9a ] + +remove all 5Ghz network types. rtl8723bs works on +802.11bgn standards and on 2.4Ghz band. + +So remove all code related to 802.11a and 802.11ac +standards, which the device doesn't support. + +Acked-by: Hans de Goede +Signed-off-by: Fabio Aiuto +Link: https://lore.kernel.org/r/7e4644a71d0ba2819370171b3dc78bfc755f6313.1624367071.git.fabioaiuto83@gmail.com +Signed-off-by: Greg Kroah-Hartman +Stable-dep-of: a1fc19d61f66 ("staging: rtl8723bs: fix WEP length underflow and OOB read in OnAuth()") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/staging/rtl8723bs/core/rtw_ap.c | 11 ---- + drivers/staging/rtl8723bs/core/rtw_ieee80211.c | 22 +------- + drivers/staging/rtl8723bs/core/rtw_mlme.c | 10 --- + drivers/staging/rtl8723bs/core/rtw_mlme_ext.c | 55 --------------------- + drivers/staging/rtl8723bs/core/rtw_wlan_util.c | 14 +---- + drivers/staging/rtl8723bs/hal/odm.c | 30 ----------- + drivers/staging/rtl8723bs/hal/odm.h | 3 - + drivers/staging/rtl8723bs/hal/odm_EdcaTurboCheck.c | 4 - + drivers/staging/rtl8723bs/hal/sdio_halinit.c | 5 - + drivers/staging/rtl8723bs/include/hal_phy.h | 3 - + drivers/staging/rtl8723bs/include/ieee80211.h | 22 +------- + drivers/staging/rtl8723bs/include/wifi.h | 1 + drivers/staging/rtl8723bs/os_dep/os_intfs.c | 2 + 13 files changed, 14 insertions(+), 168 deletions(-) + +--- a/drivers/staging/rtl8723bs/core/rtw_ap.c ++++ b/drivers/staging/rtl8723bs/core/rtw_ap.c +@@ -427,11 +427,7 @@ void add_RATid(struct adapter *padapter, + shortGIrate = query_ra_short_GI(psta); + + if (pcur_network->Configuration.DSConfig > 14) { +- if (tx_ra_bitmap & 0xffff000) +- sta_band |= WIRELESS_11_5N; +- +- if (tx_ra_bitmap & 0xff0) +- sta_band |= WIRELESS_11A; ++ sta_band |= WIRELESS_INVALID; + } else { + if (tx_ra_bitmap & 0xffff000) + sta_band |= WIRELESS_11_24N; +@@ -503,7 +499,7 @@ void update_bmc_sta(struct adapter *pada + } else if (network_type == WIRELESS_INVALID) { /* error handling */ + + if (pcur_network->Configuration.DSConfig > 14) +- network_type = WIRELESS_11A; ++ network_type = WIRELESS_INVALID; + else + network_type = WIRELESS_11B; + } +@@ -1254,9 +1250,6 @@ int rtw_check_beacon_data(struct adapter + case WIRELESS_11BG_24N: + pbss_network->NetworkTypeInUse = Ndis802_11OFDM24; + break; +- case WIRELESS_11A: +- pbss_network->NetworkTypeInUse = Ndis802_11OFDM5; +- break; + default: + pbss_network->NetworkTypeInUse = Ndis802_11OFDM24; + break; +--- a/drivers/staging/rtl8723bs/core/rtw_ieee80211.c ++++ b/drivers/staging/rtl8723bs/core/rtw_ieee80211.c +@@ -96,10 +96,7 @@ bool rtw_is_cckratesonly_included(u8 *ra + int rtw_check_network_type(unsigned char *rate, int ratelen, int channel) + { + if (channel > 14) { +- if (rtw_is_cckrates_included(rate)) +- return WIRELESS_INVALID; +- else +- return WIRELESS_11A; ++ return WIRELESS_INVALID; + } else { /* could be pure B, pure G, or B/G */ + if (rtw_is_cckratesonly_included(rate)) + return WIRELESS_11B; +@@ -275,10 +272,6 @@ void rtw_set_supported_rate(u8 *Supporte + break; + + case WIRELESS_11G: +- case WIRELESS_11A: +- case WIRELESS_11_5N: +- case WIRELESS_11A_5N:/* Todo: no basic rate for ofdm ? */ +- case WIRELESS_11_5AC: + memcpy(SupportedRates, WIFI_OFDMRATES, IEEE80211_NUM_OFDM_RATESLEN); + break; + +@@ -336,14 +329,7 @@ int rtw_generate_ie(struct registry_priv + ie = rtw_set_ie(ie, _SSID_IE_, pdev_network->Ssid.SsidLength, pdev_network->Ssid.Ssid, &sz); + + /* supported rates */ +- if (pregistrypriv->wireless_mode == WIRELESS_11ABGN) { +- if (pdev_network->Configuration.DSConfig > 14) +- wireless_mode = WIRELESS_11A_5N; +- else +- wireless_mode = WIRELESS_11BG_24N; +- } else { +- wireless_mode = pregistrypriv->wireless_mode; +- } ++ wireless_mode = pregistrypriv->wireless_mode; + + rtw_set_supported_rate(pdev_network->SupportedRates, wireless_mode); + +@@ -368,8 +354,8 @@ int rtw_generate_ie(struct registry_priv + } + + /* HT Cap. */ +- if (((pregistrypriv->wireless_mode&WIRELESS_11_5N) || (pregistrypriv->wireless_mode&WIRELESS_11_24N)) +- && (pregistrypriv->ht_enable == true)) { ++ if ((pregistrypriv->wireless_mode & WIRELESS_11_24N) && ++ (pregistrypriv->ht_enable == true)) { + /* todo: */ + } + +--- a/drivers/staging/rtl8723bs/core/rtw_mlme.c ++++ b/drivers/staging/rtl8723bs/core/rtw_mlme.c +@@ -2438,16 +2438,6 @@ void rtw_update_registrypriv_dev_network + case WIRELESS_11BG_24N: + pdev_network->NetworkTypeInUse = (Ndis802_11OFDM24); + break; +- case WIRELESS_11A: +- case WIRELESS_11A_5N: +- pdev_network->NetworkTypeInUse = (Ndis802_11OFDM5); +- break; +- case WIRELESS_11ABGN: +- if (pregistrypriv->channel > 14) +- pdev_network->NetworkTypeInUse = (Ndis802_11OFDM5); +- else +- pdev_network->NetworkTypeInUse = (Ndis802_11OFDM24); +- break; + default: + /* TODO */ + break; +--- a/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c ++++ b/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c +@@ -4918,61 +4918,6 @@ static void process_80211d(struct adapte + } + } + +- if (pregistrypriv->wireless_mode & WIRELESS_11A) { +- do { +- if ((i == MAX_CHANNEL_NUM) || +- (chplan_sta[i].ChannelNum == 0)) +- break; +- +- if ((j == chplan_ap.Len) || (chplan_ap.Channel[j] == 0)) +- break; +- +- if (chplan_sta[i].ChannelNum == chplan_ap.Channel[j]) { +- chplan_new[k].ChannelNum = chplan_ap.Channel[j]; +- chplan_new[k].ScanType = SCAN_ACTIVE; +- i++; +- j++; +- k++; +- } else if (chplan_sta[i].ChannelNum < chplan_ap.Channel[j]) { +- chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum; +-/* chplan_new[k].ScanType = chplan_sta[i].ScanType; */ +- chplan_new[k].ScanType = SCAN_PASSIVE; +- i++; +- k++; +- } else if (chplan_sta[i].ChannelNum > chplan_ap.Channel[j]) { +- chplan_new[k].ChannelNum = chplan_ap.Channel[j]; +- chplan_new[k].ScanType = SCAN_ACTIVE; +- j++; +- k++; +- } +- } while (1); +- +- /* change AP not support channel to Passive scan */ +- while ((i < MAX_CHANNEL_NUM) && (chplan_sta[i].ChannelNum != 0)) { +- chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum; +-/* chplan_new[k].ScanType = chplan_sta[i].ScanType; */ +- chplan_new[k].ScanType = SCAN_PASSIVE; +- i++; +- k++; +- } +- +- /* add channel AP supported */ +- while ((j < chplan_ap.Len) && (chplan_ap.Channel[j] != 0)) { +- chplan_new[k].ChannelNum = chplan_ap.Channel[j]; +- chplan_new[k].ScanType = SCAN_ACTIVE; +- j++; +- k++; +- } +- } else { +- /* keep original STA 5G channel plan */ +- while ((i < MAX_CHANNEL_NUM) && (chplan_sta[i].ChannelNum != 0)) { +- chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum; +- chplan_new[k].ScanType = chplan_sta[i].ScanType; +- i++; +- k++; +- } +- } +- + pmlmeext->update_channel_plan_by_ap_done = 1; + + #ifdef DEBUG_RTL871X +--- a/drivers/staging/rtl8723bs/core/rtw_wlan_util.c ++++ b/drivers/staging/rtl8723bs/core/rtw_wlan_util.c +@@ -62,9 +62,6 @@ u8 networktype_to_raid_ex(struct adapter + + if (cur_rf_type == RF_1T1R) { + rf_type = RF_1T1R; +- } else if (IsSupportedVHT(psta->wireless_mode)) { +- if (psta->ra_mask & 0xffc00000) +- rf_type = RF_2T2R; + } else if (IsSupportedHT(psta->wireless_mode)) { + if (psta->ra_mask & 0xfff00000) + rf_type = RF_2T2R; +@@ -74,7 +71,6 @@ u8 networktype_to_raid_ex(struct adapter + case WIRELESS_11B: + raid = RATEID_IDX_B; + break; +- case WIRELESS_11A: + case WIRELESS_11G: + raid = RATEID_IDX_G; + break; +@@ -82,8 +78,6 @@ u8 networktype_to_raid_ex(struct adapter + raid = RATEID_IDX_BG; + break; + case WIRELESS_11_24N: +- case WIRELESS_11_5N: +- case WIRELESS_11A_5N: + case WIRELESS_11G_24N: + if (rf_type == RF_2T2R) + raid = RATEID_IDX_GN_N2SS; +@@ -810,7 +804,7 @@ void WMMOnAssocRsp(struct adapter *padap + + AIFS = aSifsTime + (2 * pmlmeinfo->slotTime); + +- if (pmlmeext->cur_wireless_mode & (WIRELESS_11G | WIRELESS_11A)) { ++ if (pmlmeext->cur_wireless_mode & WIRELESS_11G) { + ECWMin = 4; + ECWMax = 10; + } else if (pmlmeext->cur_wireless_mode & WIRELESS_11B) { +@@ -1695,7 +1689,7 @@ void update_capinfo(struct adapter *Adap + pmlmeinfo->slotTime = NON_SHORT_SLOT_TIME; + else { + /* Filen: See 802.11-2007 p.90 */ +- if (pmlmeext->cur_wireless_mode & (WIRELESS_11_24N | WIRELESS_11A | WIRELESS_11_5N | WIRELESS_11AC)) ++ if (pmlmeext->cur_wireless_mode & (WIRELESS_11_24N)) + pmlmeinfo->slotTime = SHORT_SLOT_TIME; + else if (pmlmeext->cur_wireless_mode & (WIRELESS_11G)) { + if ((updateCap & cShortSlotTime) /* && (!(pMgntInfo->pHTInfo->RT2RT_HT_Mode & RT_HT_CAP_USE_LONG_PREAMBLE)) */) +@@ -1724,9 +1718,7 @@ void update_wireless_mode(struct adapter + if ((pmlmeinfo->HT_info_enable) && (pmlmeinfo->HT_caps_enable)) + pmlmeinfo->HT_enable = 1; + +- if (pmlmeinfo->VHT_enable) +- network_type = WIRELESS_11AC; +- else if (pmlmeinfo->HT_enable) ++ if (pmlmeinfo->HT_enable) + network_type = WIRELESS_11_24N; + + if (rtw_is_cckratesonly_included(rate)) +--- a/drivers/staging/rtl8723bs/hal/odm.c ++++ b/drivers/staging/rtl8723bs/hal/odm.c +@@ -975,7 +975,6 @@ u32 ODM_Get_Rate_Bitmap( + break; + + case (ODM_WM_G): +- case (ODM_WM_A): + if (rssi_level == DM_RATR_STA_HIGH) + rate_bitmap = 0x00000f00; + else +@@ -994,7 +993,6 @@ u32 ODM_Get_Rate_Bitmap( + case (ODM_WM_B|ODM_WM_G|ODM_WM_N24G): + case (ODM_WM_B|ODM_WM_N24G): + case (ODM_WM_G|ODM_WM_N24G): +- case (ODM_WM_A|ODM_WM_N5G): + if (pDM_Odm->RFType == ODM_1T2R || pDM_Odm->RFType == ODM_1T1R) { + if (rssi_level == DM_RATR_STA_HIGH) + rate_bitmap = 0x000f0000; +@@ -1020,34 +1018,6 @@ u32 ODM_Get_Rate_Bitmap( + } + break; + +- case (ODM_WM_AC|ODM_WM_G): +- if (rssi_level == 1) +- rate_bitmap = 0xfc3f0000; +- else if (rssi_level == 2) +- rate_bitmap = 0xfffff000; +- else +- rate_bitmap = 0xffffffff; +- break; +- +- case (ODM_WM_AC|ODM_WM_A): +- +- if (pDM_Odm->RFType == RF_1T1R) { +- if (rssi_level == 1) /* add by Gary for ac-series */ +- rate_bitmap = 0x003f8000; +- else if (rssi_level == 2) +- rate_bitmap = 0x003ff000; +- else +- rate_bitmap = 0x003ff010; +- } else { +- if (rssi_level == 1) /* add by Gary for ac-series */ +- rate_bitmap = 0xfe3f8000; /* VHT 2SS MCS3~9 */ +- else if (rssi_level == 2) +- rate_bitmap = 0xfffff000; /* VHT 2SS MCS0~9 */ +- else +- rate_bitmap = 0xfffff010; /* All */ +- } +- break; +- + default: + if (pDM_Odm->RFType == RF_1T2R) + rate_bitmap = 0x000fffff; +--- a/drivers/staging/rtl8723bs/hal/odm.h ++++ b/drivers/staging/rtl8723bs/hal/odm.h +@@ -541,11 +541,8 @@ typedef enum tag_Wireless_Mode_Definitio + ODM_WM_UNKNOWN = 0x0, + ODM_WM_B = BIT0, + ODM_WM_G = BIT1, +- ODM_WM_A = BIT2, + ODM_WM_N24G = BIT3, +- ODM_WM_N5G = BIT4, + ODM_WM_AUTO = BIT5, +- ODM_WM_AC = BIT6, + } ODM_WIRELESS_MODE_E; + + /* ODM_CMNINFO_BAND */ +--- a/drivers/staging/rtl8723bs/hal/odm_EdcaTurboCheck.c ++++ b/drivers/staging/rtl8723bs/hal/odm_EdcaTurboCheck.c +@@ -142,12 +142,10 @@ void odm_EdcaTurboCheckCE(void *pDM_VOID + } else if ((iot_peer == HT_IOT_PEER_CISCO) && + ((wirelessmode == ODM_WM_G) || + (wirelessmode == (ODM_WM_B | ODM_WM_G)) || +- (wirelessmode == ODM_WM_A) || + (wirelessmode == ODM_WM_B))) { + EDCA_BE_DL = edca_setting_DL_GMode[iot_peer]; + } else if ((iot_peer == HT_IOT_PEER_AIRGO) && +- ((wirelessmode == ODM_WM_G) || +- (wirelessmode == ODM_WM_A))) { ++ (wirelessmode == ODM_WM_G)) { + EDCA_BE_DL = 0xa630; + } else if (iot_peer == HT_IOT_PEER_MARVELL) { + EDCA_BE_DL = edca_setting_DL[iot_peer]; +--- a/drivers/staging/rtl8723bs/hal/sdio_halinit.c ++++ b/drivers/staging/rtl8723bs/hal/sdio_halinit.c +@@ -599,8 +599,6 @@ static void _InitOperationMode(struct ad + case WIRELESS_MODE_B: + regBwOpMode = BW_OPMODE_20MHZ; + break; +- case WIRELESS_MODE_A: +- break; + case WIRELESS_MODE_G: + regBwOpMode = BW_OPMODE_20MHZ; + break; +@@ -612,9 +610,6 @@ static void _InitOperationMode(struct ad + /* CCK rate will be filtered out only when associated AP does not support it. */ + regBwOpMode = BW_OPMODE_20MHZ; + break; +- case WIRELESS_MODE_N_5G: +- regBwOpMode = BW_OPMODE_5G; +- break; + + default: /* for MacOSX compiler warning. */ + break; +--- a/drivers/staging/rtl8723bs/include/hal_phy.h ++++ b/drivers/staging/rtl8723bs/include/hal_phy.h +@@ -118,13 +118,10 @@ enum HW_BLOCK { + + enum WIRELESS_MODE { + WIRELESS_MODE_UNKNOWN = 0x00, +- WIRELESS_MODE_A = 0x01, + WIRELESS_MODE_B = 0x02, + WIRELESS_MODE_G = 0x04, + WIRELESS_MODE_AUTO = 0x08, + WIRELESS_MODE_N_24G = 0x10, +- WIRELESS_MODE_N_5G = 0x20, +- WIRELESS_MODE_AC_5G = 0x40, + WIRELESS_MODE_AC_24G = 0x80, + WIRELESS_MODE_AC_ONLY = 0x100, + }; +--- a/drivers/staging/rtl8723bs/include/ieee80211.h ++++ b/drivers/staging/rtl8723bs/include/ieee80211.h +@@ -157,33 +157,20 @@ enum NETWORK_TYPE { + /* Sub-Element */ + WIRELESS_11B = BIT(0), /* tx: cck only , rx: cck only, hw: cck */ + WIRELESS_11G = BIT(1), /* tx: ofdm only, rx: ofdm & cck, hw: cck & ofdm */ +- WIRELESS_11A = BIT(2), /* tx: ofdm only, rx: ofdm only, hw: ofdm only */ + WIRELESS_11_24N = BIT(3), /* tx: MCS only, rx: MCS & cck, hw: MCS & cck */ +- WIRELESS_11_5N = BIT(4), /* tx: MCS only, rx: MCS & ofdm, hw: ofdm only */ + WIRELESS_AUTO = BIT(5), +- WIRELESS_11AC = BIT(6), + + /* Combination */ + /* Type for current wireless mode */ + WIRELESS_11BG = (WIRELESS_11B|WIRELESS_11G), /* tx: cck & ofdm, rx: cck & ofdm & MCS, hw: cck & ofdm */ + WIRELESS_11G_24N = (WIRELESS_11G|WIRELESS_11_24N), /* tx: ofdm & MCS, rx: ofdm & cck & MCS, hw: cck & ofdm */ +- WIRELESS_11A_5N = (WIRELESS_11A|WIRELESS_11_5N), /* tx: ofdm & MCS, rx: ofdm & MCS, hw: ofdm only */ + WIRELESS_11B_24N = (WIRELESS_11B|WIRELESS_11_24N), /* tx: ofdm & cck & MCS, rx: ofdm & cck & MCS, hw: ofdm & cck */ + WIRELESS_11BG_24N = (WIRELESS_11B|WIRELESS_11G|WIRELESS_11_24N), /* tx: ofdm & cck & MCS, rx: ofdm & cck & MCS, hw: ofdm & cck */ +- WIRELESS_11_24AC = (WIRELESS_11G|WIRELESS_11AC), +- WIRELESS_11_5AC = (WIRELESS_11A|WIRELESS_11AC), +- +- +- /* Type for registry default wireless mode */ +- WIRELESS_11AGN = (WIRELESS_11A|WIRELESS_11G|WIRELESS_11_24N|WIRELESS_11_5N), /* tx: ofdm & MCS, rx: ofdm & MCS, hw: ofdm only */ +- WIRELESS_11ABGN = (WIRELESS_11A|WIRELESS_11B|WIRELESS_11G|WIRELESS_11_24N|WIRELESS_11_5N), +- WIRELESS_MODE_24G = (WIRELESS_11B|WIRELESS_11G|WIRELESS_11_24N|WIRELESS_11AC), +- WIRELESS_MODE_MAX = (WIRELESS_11A|WIRELESS_11B|WIRELESS_11G|WIRELESS_11_24N|WIRELESS_11_5N|WIRELESS_11AC), + }; + + #define SUPPORTED_24G_NETTYPE_MSK (WIRELESS_11B | WIRELESS_11G | WIRELESS_11_24N) + +-#define IsLegacyOnly(NetType) ((NetType) == ((NetType) & (WIRELESS_11BG|WIRELESS_11A))) ++#define IsLegacyOnly(NetType) ((NetType) == ((NetType) & (WIRELESS_11BG))) + + #define IsSupported24G(NetType) ((NetType) & SUPPORTED_24G_NETTYPE_MSK ? true : false) + +@@ -195,11 +182,8 @@ enum NETWORK_TYPE { + #define IsSupportedRxHT(NetType) IsEnableHWOFDM(NetType) + + #define IsSupportedTxCCK(NetType) (((NetType) & (WIRELESS_11B)) ? true : false) +-#define IsSupportedTxOFDM(NetType) (((NetType) & (WIRELESS_11G|WIRELESS_11A)) ? true : false) +-#define IsSupportedHT(NetType) (((NetType) & (WIRELESS_11_24N|WIRELESS_11_5N)) ? true : false) +- +-#define IsSupportedVHT(NetType) (((NetType) & (WIRELESS_11AC)) ? true : false) +- ++#define IsSupportedTxOFDM(NetType) (((NetType) & (WIRELESS_11G) ? true : false) ++#define IsSupportedHT(NetType) (((NetType) & (WIRELESS_11_24N)) ? true : false) + + struct ieee_param { + u32 cmd; +--- a/drivers/staging/rtl8723bs/include/wifi.h ++++ b/drivers/staging/rtl8723bs/include/wifi.h +@@ -457,7 +457,6 @@ static inline int IsFrameTypeCtrl(unsign + #define _PRE_ALLOCICVHDR_ 5 + #define _PRE_ALLOCMICHDR_ 6 + +-#define _SIFSTIME_ ((priv->pmib->dot11BssType.net_work_type&WIRELESS_11A)?16:10) + #define _ACKCTSLNG_ 14 /* 14 bytes long, including crclng */ + #define _CRCLNG_ 4 + +--- a/drivers/staging/rtl8723bs/os_dep/os_intfs.c ++++ b/drivers/staging/rtl8723bs/os_dep/os_intfs.c +@@ -24,7 +24,7 @@ static int rtw_lbkmode;/* RTL8712_AIR_TR + static int rtw_network_mode = Ndis802_11IBSS;/* Ndis802_11Infrastructure;infra, ad-hoc, auto */ + /* struct ndis_802_11_ssid ssid; */ + static int rtw_channel = 1;/* ad-hoc support requirement */ +-static int rtw_wireless_mode = WIRELESS_MODE_MAX; ++static int rtw_wireless_mode = WIRELESS_11BG_24N; + static int rtw_vrtl_carrier_sense = AUTO_VCS; + static int rtw_vcs_type = RTS_CTS;/* */ + static int rtw_rts_thresh = 2347;/* */ diff --git a/queue-5.10/staging-rtl8723bs-remove-commented-out-condition.patch b/queue-5.10/staging-rtl8723bs-remove-commented-out-condition.patch new file mode 100644 index 0000000000..9e3ac6d979 --- /dev/null +++ b/queue-5.10/staging-rtl8723bs-remove-commented-out-condition.patch @@ -0,0 +1,35 @@ +From stable+bounces-274603-greg=kroah.com@vger.kernel.org Wed Jul 15 01:34:18 2026 +From: Sasha Levin +Date: Tue, 14 Jul 2026 19:34:05 -0400 +Subject: staging: rtl8723bs: remove commented out condition +To: stable@vger.kernel.org +Cc: Fabio Aiuto , Greg Kroah-Hartman , Sasha Levin +Message-ID: <20260714233407.3591885-6-sashal@kernel.org> + +From: Fabio Aiuto + +[ Upstream commit 2a62ff13132a22a754d042b2230117bbea0af477 ] + +remove commented out condition checking channel > 14. + +Signed-off-by: Fabio Aiuto +Link: https://lore.kernel.org/r/83762719c0c13ac8b78612a32db26e691eef17d1.1626874164.git.fabioaiuto83@gmail.com +Signed-off-by: Greg Kroah-Hartman +Stable-dep-of: a1fc19d61f66 ("staging: rtl8723bs: fix WEP length underflow and OOB read in OnAuth()") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/staging/rtl8723bs/os_dep/ioctl_linux.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/staging/rtl8723bs/os_dep/ioctl_linux.c ++++ b/drivers/staging/rtl8723bs/os_dep/ioctl_linux.c +@@ -165,7 +165,7 @@ static char *translate_scan(struct adapt + start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_UINT_LEN); + } + +- if (pnetwork->network.Configuration.DSConfig < 1 /*|| pnetwork->network.Configuration.DSConfig > 14*/) ++ if (pnetwork->network.Configuration.DSConfig < 1) + pnetwork->network.Configuration.DSConfig = 1; + + /* Add frequency/channel */ diff --git a/queue-5.10/staging-rtl8723bs-remove-commented-out-rt_assert-occurrences.patch b/queue-5.10/staging-rtl8723bs-remove-commented-out-rt_assert-occurrences.patch new file mode 100644 index 0000000000..8e989b7d33 --- /dev/null +++ b/queue-5.10/staging-rtl8723bs-remove-commented-out-rt_assert-occurrences.patch @@ -0,0 +1,90 @@ +From stable+bounces-274599-greg=kroah.com@vger.kernel.org Wed Jul 15 01:34:17 2026 +From: Sasha Levin +Date: Tue, 14 Jul 2026 19:34:01 -0400 +Subject: staging: rtl8723bs: remove commented out RT_ASSERT occurrences +To: stable@vger.kernel.org +Cc: Fabio Aiuto , Dan Carpenter , Greg Kroah-Hartman , Sasha Levin +Message-ID: <20260714233407.3591885-2-sashal@kernel.org> + +From: Fabio Aiuto + +[ Upstream commit 2172a6576388e63958f47923e435c46af8d006ba ] + +remove commented out obsoete RT_ASSERT macro occurences. + +Reviewed-by: Dan Carpenter +Signed-off-by: Fabio Aiuto +Link: https://lore.kernel.org/r/3ee98d7bf1685af627e625f413de355fce58d52d.1619794331.git.fabioaiuto83@gmail.com +Signed-off-by: Greg Kroah-Hartman +Stable-dep-of: a1fc19d61f66 ("staging: rtl8723bs: fix WEP length underflow and OOB read in OnAuth()") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/staging/rtl8723bs/core/rtw_recv.c | 2 -- + drivers/staging/rtl8723bs/hal/rtl8723b_hal_init.c | 1 - + drivers/staging/rtl8723bs/hal/sdio_halinit.c | 5 ----- + 3 files changed, 8 deletions(-) + +--- a/drivers/staging/rtl8723bs/core/rtw_recv.c ++++ b/drivers/staging/rtl8723bs/core/rtw_recv.c +@@ -2165,8 +2165,6 @@ int recv_indicatepkts_in_order(struct ad + /* pTS->RxIndicateState = RXTS_INDICATE_PROCESSING; */ + + /* Indicate packets */ +- /* RT_ASSERT((index<=REORDER_WIN_SIZE), ("RxReorderIndicatePacket(): Rx Reorder buffer full!!\n")); */ +- + + /* indicate this recv_frame */ + /* DbgPrint("recv_indicatepkts_in_order, indicate_seq =%d, seq_num =%d\n", precvpriv->indicate_seq, pattrib->seq_num); */ +--- a/drivers/staging/rtl8723bs/hal/rtl8723b_hal_init.c ++++ b/drivers/staging/rtl8723bs/hal/rtl8723b_hal_init.c +@@ -158,7 +158,6 @@ static int _WriteFW(struct adapter *pada + u8 *bufferPtr = buffer; + + pageNums = size / MAX_DLFW_PAGE_SIZE; +- /* RT_ASSERT((pageNums <= 4), ("Page numbers should not greater then 4\n")); */ + remainSize = size % MAX_DLFW_PAGE_SIZE; + + for (page = 0; page < pageNums; page++) { +--- a/drivers/staging/rtl8723bs/hal/sdio_halinit.c ++++ b/drivers/staging/rtl8723bs/hal/sdio_halinit.c +@@ -313,7 +313,6 @@ static void _InitNormalChipOneOutEpPrior + value = QUEUE_NORMAL; + break; + default: +- /* RT_ASSERT(false, ("Shall not reach here!\n")); */ + break; + } + +@@ -347,7 +346,6 @@ static void _InitNormalChipTwoOutEpPrior + valueLow = QUEUE_NORMAL; + break; + default: +- /* RT_ASSERT(false, ("Shall not reach here!\n")); */ + break; + } + +@@ -412,7 +410,6 @@ static void _InitQueuePriority(struct ad + _InitNormalChipThreeOutEpPriority(Adapter); + break; + default: +- /* RT_ASSERT(false, ("Shall not reach here!\n")); */ + break; + } + +@@ -603,7 +600,6 @@ static void _InitOperationMode(struct ad + regBwOpMode = BW_OPMODE_20MHZ; + break; + case WIRELESS_MODE_A: +-/* RT_ASSERT(false, ("Error wireless a mode\n")); */ + break; + case WIRELESS_MODE_G: + regBwOpMode = BW_OPMODE_20MHZ; +@@ -617,7 +613,6 @@ static void _InitOperationMode(struct ad + regBwOpMode = BW_OPMODE_20MHZ; + break; + case WIRELESS_MODE_N_5G: +-/* RT_ASSERT(false, ("Error wireless mode")); */ + regBwOpMode = BW_OPMODE_5G; + break; + diff --git a/queue-5.10/staging-rtl8723bs-remove-dbg_871x-log-argument.patch b/queue-5.10/staging-rtl8723bs-remove-dbg_871x-log-argument.patch new file mode 100644 index 0000000000..9ccf2caaec --- /dev/null +++ b/queue-5.10/staging-rtl8723bs-remove-dbg_871x-log-argument.patch @@ -0,0 +1,52 @@ +From stable+bounces-274677-greg=kroah.com@vger.kernel.org Wed Jul 15 04:45:49 2026 +From: Sasha Levin +Date: Tue, 14 Jul 2026 22:45:34 -0400 +Subject: staging: rtl8723bs: remove DBG_871X log argument +To: stable@vger.kernel.org +Cc: Fabio Aiuto , Greg Kroah-Hartman , Sasha Levin +Message-ID: <20260715024543.105642-1-sashal@kernel.org> + +From: Fabio Aiuto + +[ Upstream commit 42c3243ff23d119331a8ace011e0c18b222a1138 ] + +This patch prepares the application of the semantic +patch aimed to remove all DBG_871X logs. + +One occurrence of the DBG_871X macro has one +repeated argument, that's not even comma separated +value with the previous one nor a format string +parameter associated. + +In normal conditions this worked, for the macro +is usually not expanded (the do nothing behaviour), +but if I try to apply the sempantic patch to remove +all macro occurrences, all macros call after that +abnormal declaration are left untouched (not removed). + +Remove all of the DBG_871X logs as they currently +do nothing as they require the code to be modified by +hand in order to be turned on. This obviously has not happened +since the code was merged, so just remove them as they are unused. + +Signed-off-by: Fabio Aiuto +Link: https://lore.kernel.org/r/3473925ae9ee5a3bcd0ab86613dbce80b6d3f33f.1617802415.git.fabioaiuto83@gmail.com +Signed-off-by: Greg Kroah-Hartman +Stable-dep-of: ed51de4a86e1 ("staging: rtl8723bs: fix OOB read in update_beacon_info() IE loop") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/staging/rtl8723bs/core/rtw_recv.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/staging/rtl8723bs/core/rtw_recv.c ++++ b/drivers/staging/rtl8723bs/core/rtw_recv.c +@@ -923,7 +923,7 @@ sint ap2sta_data_frame( + #ifdef DBG_RX_DROP_FRAME + DBG_871X("DBG_RX_DROP_FRAME %s BSSID ="MAC_FMT", mybssid ="MAC_FMT"\n", + __func__, MAC_ARG(pattrib->bssid), MAC_ARG(mybssid)); +- DBG_871X("this adapter = %d, buddy adapter = %d\n", adapter->adapter_type, adapter->pbuddystruct adapter->adapter_type); ++ DBG_871X("this adapter = %d, buddy adapter = %d\n", adapter->adapter_type, adapter->pbuddystruct); + #endif + + if (!bmcast) { diff --git a/queue-5.10/staging-rtl8723bs-split-too-long-line.patch b/queue-5.10/staging-rtl8723bs-split-too-long-line.patch new file mode 100644 index 0000000000..1ac0f05bd5 --- /dev/null +++ b/queue-5.10/staging-rtl8723bs-split-too-long-line.patch @@ -0,0 +1,41 @@ +From stable+bounces-274598-greg=kroah.com@vger.kernel.org Wed Jul 15 01:34:18 2026 +From: Sasha Levin +Date: Tue, 14 Jul 2026 19:34:00 -0400 +Subject: staging: rtl8723bs: split too long line +To: stable@vger.kernel.org +Cc: Fabio Aiuto , Greg Kroah-Hartman , Sasha Levin +Message-ID: <20260714233407.3591885-1-sashal@kernel.org> + +From: Fabio Aiuto + +[ Upstream commit 98dc120895a9a669e35155ee03b98452723aba95 ] + +fix the following post-commit hook checkpatch issue. + +WARNING: line length of 103 exceeds 100 columns +30: FILE: drivers/staging/rtl8723bs/core/rtw_mlme_ext.c:711: ++ +receive_disconnect(padapter, pmlmeinfo->network.MacAddress, 0); + +Signed-off-by: Fabio Aiuto +Link: https://lore.kernel.org/r/4e87fb741205b9f314aec739921405a7ebef908a.1618480688.git.fabioaiuto83@gmail.com +Signed-off-by: Greg Kroah-Hartman +Stable-dep-of: a1fc19d61f66 ("staging: rtl8723bs: fix WEP length underflow and OOB read in OnAuth()") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/staging/rtl8723bs/core/rtw_mlme_ext.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c ++++ b/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c +@@ -835,7 +835,8 @@ unsigned int OnBeacon(struct adapter *pa + ret = rtw_check_bcn_info(padapter, pframe, len); + if (!ret) { + DBG_871X_LEVEL(_drv_always_, "ap has changed, disconnect now\n "); +- receive_disconnect(padapter, pmlmeinfo->network.MacAddress, 0); ++ receive_disconnect(padapter, ++ pmlmeinfo->network.MacAddress, 0); + return _SUCCESS; + } + /* update WMM, ERP in the beacon */ diff --git a/queue-5.10/usb-atm-ueagle-atm-wait-for-pre-firmware-load-in-.disconnect.patch b/queue-5.10/usb-atm-ueagle-atm-wait-for-pre-firmware-load-in-.disconnect.patch new file mode 100644 index 0000000000..d57b594dfc --- /dev/null +++ b/queue-5.10/usb-atm-ueagle-atm-wait-for-pre-firmware-load-in-.disconnect.patch @@ -0,0 +1,175 @@ +From stable+bounces-277539-greg=kroah.com@vger.kernel.org Mon Jul 20 04:35:55 2026 +From: Sasha Levin +Date: Sun, 19 Jul 2026 22:35:43 -0400 +Subject: usb: atm: ueagle-atm: wait for pre-firmware load in .disconnect() +To: stable@vger.kernel.org +Cc: Mauricio Faria de Oliveira , stable , syzbot+ce1e5a1b4e086b43e56d@syzkaller.appspotmail.com, syzbot+306212936b13e520679d@syzkaller.appspotmail.com, syzbot+457452d30bcdda75ead2@syzkaller.appspotmail.com, Andrey Tsygunka , Stanislaw Gruszka , Greg Kroah-Hartman , Sasha Levin +Message-ID: <20260720023543.2969189-1-sashal@kernel.org> + +From: Mauricio Faria de Oliveira + +[ Upstream commit e2674dfbed8a30d57e2bc872c4bfa6c3eec918bf ] + +ueagle-atm uses the asynchronous request_firmware_nowait() in .probe(), +but does not wait for its completion, not even in .disconnect(); so, if the +device is unplugged meanwhile, its teardown runs concurrently with that. + +Even though this inconsistency is worth addressing on its own, it has also +triggered several bug reports in syzbot over the years (some auto-closed) +where the firmware sysfs fallback mechanism (CONFIG_FW_LOADER_USER_HELPER) +creates a firmware subdirectory in the device directory during its removal, +which might hit unexpected conditions in kernfs, apparently, depending at +which point the add and remove operations raced. (See links.) + +The pattern is: + +usb ?-?: Direct firmware load for ueagle-atm/eagle?.fw failed with error -2 +usb ?-?: Falling back to sysfs fallback for: ueagle-atm/eagle?.fw + +Call trace: + ... + kernfs_create_dir_ns + sysfs_create_dir_ns + create_dir + kobject_add_internal + kobject_add_varg + kobject_add + class_dir_create_and_add + get_device_parent + device_add + fw_load_sysfs_fallback + fw_load_from_user_helper + firmware_fallback_sysfs + _request_firmware + request_firmware_work_func + ... + +(Some variations are observed, after fw_load_sysfs_fallback(), e.g., [1].) + +While the kernfs side is being looked at, the ueagle-atm side can be fixed +by waiting for the pre-firmware load in the .disconnect() handler. + +This change has a similar approach to previous work by Andrey Tsygunka [2] +(wait_for_completion() in .disconnect()), but it is relatively different in +design/implementation; using the Originally-by tag for credit assignment. + +This has been tested with: +- synthetic reproducer to check the error path; +- USB gadget (virtual device) to check the firmware upload path; +- QEMU device emulator to check the device ID re-enumeration path; +(The latter two were written by Claude; no other code/text in this commit.) + +Links (year first reported): + 2025 https://syzbot.org/bug?extid=ce1e5a1b4e086b43e56d + 2025 https://syzbot.org/bug?extid=9af8471255ac36e34fd4 + 2024 https://syzbot.org/bug?extid=306212936b13e520679d + 2023 https://syzkaller.appspot.com/bug?extid=457452d30bcdda75ead2 + 2022 https://syzbot.org/bug?extid=782984d6f1701b526edb + 2021 https://syzbot.org/bug?id=f3f221579f4ef7e9691281f3c6f56c05f83e8490 + 2021 https://syzbot.org/bug?id=84d86f0d71394829df6fc53daf6642c045983881 + 2021 https://syzbot.org/bug?id=3302dc1c0e2b9c94f2e8edb404eabc9267bc6f90 + +[1] https://syzkaller.appspot.com/bug?extid=457452d30bcdda75ead2 +[2] https://lore.kernel.org/lkml/20250410093146.3776801-2-aitsygunka@yandex.ru/ + +Cc: stable +Reported-by: syzbot+ce1e5a1b4e086b43e56d@syzkaller.appspotmail.com +Closes: https://syzbot.org/bug?extid=ce1e5a1b4e086b43e56d +Reported-by: syzbot+306212936b13e520679d@syzkaller.appspotmail.com +Closes: https://syzbot.org/bug?extid=306212936b13e520679d +Reported-by: syzbot+457452d30bcdda75ead2@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=457452d30bcdda75ead2 +Originally-by: Andrey Tsygunka +Fixes: b72458a80c75 ("[PATCH] USB: Eagle and ADI 930 usb adsl modem driver") +Assisted-by: Claude:claude-opus-4.7 # usb gadget & qemu device for testing +Signed-off-by: Mauricio Faria de Oliveira +Acked-by: Stanislaw Gruszka +Link: https://patch.msgid.link/20260526-ueagle-atm_req-fw-sync-v3-1-93c01961daaf@igalia.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/atm/ueagle-atm.c | 36 +++++++++++++++++++++++++++++++----- + 1 file changed, 31 insertions(+), 5 deletions(-) + +--- a/drivers/usb/atm/ueagle-atm.c ++++ b/drivers/usb/atm/ueagle-atm.c +@@ -599,7 +599,9 @@ static int uea_send_modem_cmd(struct usb + static void uea_upload_pre_firmware(const struct firmware *fw_entry, + void *context) + { +- struct usb_device *usb = context; ++ struct usb_interface *intf = context; ++ struct usb_device *usb = interface_to_usbdev(intf); ++ struct completion *fw_done = usb_get_intfdata(intf); + const u8 *pfw; + u8 value; + u32 crc = 0; +@@ -670,15 +672,17 @@ err_fw_corrupted: + err: + release_firmware(fw_entry); + uea_leaves(usb); ++ complete(fw_done); + } + + /* + * uea_load_firmware - Load usb firmware for pre-firmware devices. + */ +-static int uea_load_firmware(struct usb_device *usb, unsigned int ver) ++static int uea_load_firmware(struct usb_interface *intf, unsigned int ver) + { + int ret; + char *fw_name = EAGLE_FIRMWARE; ++ struct usb_device *usb = interface_to_usbdev(intf); + + uea_enters(usb); + uea_info(usb, "pre-firmware device, uploading firmware\n"); +@@ -702,7 +706,7 @@ static int uea_load_firmware(struct usb_ + } + + ret = request_firmware_nowait(THIS_MODULE, 1, fw_name, &usb->dev, +- GFP_KERNEL, usb, ++ GFP_KERNEL, intf, + uea_upload_pre_firmware); + if (ret) + uea_err(usb, "firmware %s is not available\n", fw_name); +@@ -2598,8 +2602,23 @@ static int uea_probe(struct usb_interfac + + usb_reset_device(usb); + +- if (UEA_IS_PREFIRM(id)) +- return uea_load_firmware(usb, UEA_CHIP_VERSION(id)); ++ if (UEA_IS_PREFIRM(id)) { ++ struct completion *fw_done; ++ ++ /* Wait for the firmware load to be done, in .disconnect() */ ++ fw_done = kzalloc(sizeof(*fw_done), GFP_KERNEL); ++ if (!fw_done) ++ return -ENOMEM; ++ ++ init_completion(fw_done); ++ usb_set_intfdata(intf, fw_done); ++ ++ ret = uea_load_firmware(intf, UEA_CHIP_VERSION(id)); ++ if (ret) ++ kfree(fw_done); ++ ++ return ret; ++ } + + ret = usbatm_usb_probe(intf, id, &uea_usbatm_driver); + if (ret == 0) { +@@ -2630,6 +2649,13 @@ static void uea_disconnect(struct usb_in + usbatm_usb_disconnect(intf); + mutex_unlock(&uea_mutex); + uea_info(usb, "ADSL device removed\n"); ++ } else if (usb->config->desc.bNumInterfaces == 1) { ++ struct completion *fw_done = usb_get_intfdata(intf); ++ ++ uea_dbg(usb, "pre-firmware device, waiting firmware upload\n"); ++ wait_for_completion(fw_done); ++ uea_dbg(usb, "pre-firmware device, finished waiting\n"); ++ kfree(fw_done); + } + + uea_leaves(usb); diff --git a/queue-5.10/usb-free-iso-schedules-on-failed-submit.patch b/queue-5.10/usb-free-iso-schedules-on-failed-submit.patch new file mode 100644 index 0000000000..478aece069 --- /dev/null +++ b/queue-5.10/usb-free-iso-schedules-on-failed-submit.patch @@ -0,0 +1,110 @@ +From stable+bounces-277457-greg=kroah.com@vger.kernel.org Sun Jul 19 16:53:53 2026 +From: Sasha Levin +Date: Sun, 19 Jul 2026 10:53:46 -0400 +Subject: usb: free iso schedules on failed submit +To: stable@vger.kernel.org +Cc: Dawei Feng , stable , Alan Stern , Greg Kroah-Hartman , Sasha Levin +Message-ID: <20260719145346.5460-1-sashal@kernel.org> + +From: Dawei Feng + +[ Upstream commit b9399d25fbb34a05bbe76eeedd730f62ff2670e9 ] + +EHCI and FOTG210 isochronous submits build an ehci_iso_sched before +linking the URB to the endpoint queue, and keep the staged schedule in +urb->hcpriv until iso_stream_schedule() and the link helpers consume it. +If the controller is no longer accessible, or usb_hcd_link_urb_to_ep() +fails, submit jumps to done_not_linked before that handoff happens and +leaks the staged schedule still attached to urb->hcpriv. + +Free the staged schedule from done_not_linked when submit fails before +the URB is linked and clear urb->hcpriv after the free. + +The bug was first flagged by an experimental analysis tool we are +developing for kernel memory-management bugs while analyzing +v6.13-rc1. The tool is still under development and is not yet publicly +available. Manual inspection confirms that the bug is still +present in v7.1.1. + +An x86_64 allyesconfig build showed no new warnings. As we do not have an +EHCI host controller with a USB isochronous device to test with, no +runtime testing was able to be performed. + +Fixes: 8de98402652c ("[PATCH] USB: Fix USB suspend/resume crasher (#2)") +Fixes: e9df41c5c589 ("USB: make HCDs responsible for managing endpoint queues") +Fixes: 7d50195f6c50 ("usb: host: Faraday fotg210-hcd driver") +Cc: stable +Signed-off-by: Dawei Feng +Reviewed-by: Alan Stern +Link: https://patch.msgid.link/20260630071419.349161-1-dawei.feng@seu.edu.cn +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/host/ehci-sched.c | 11 +++++++++-- + drivers/usb/host/fotg210-hcd.c | 6 ++++-- + 2 files changed, 13 insertions(+), 4 deletions(-) + +--- a/drivers/usb/host/ehci-sched.c ++++ b/drivers/usb/host/ehci-sched.c +@@ -1613,6 +1613,7 @@ iso_stream_schedule( + status = 1; /* and give it back immediately */ + iso_sched_free(stream, sched); + sched = NULL; ++ urb->hcpriv = NULL; + } + } + urb->error_count = skip / period; +@@ -1643,8 +1644,6 @@ iso_stream_schedule( + return status; + + fail: +- iso_sched_free(stream, sched); +- urb->hcpriv = NULL; + return status; + } + +@@ -1956,6 +1955,10 @@ static int itd_submit(struct ehci_hcd *e + usb_hcd_unlink_urb_from_ep(ehci_to_hcd(ehci), urb); + } + done_not_linked: ++ if (status < 0) { ++ iso_sched_free(stream, urb->hcpriv); ++ urb->hcpriv = NULL; ++ } + spin_unlock_irqrestore(&ehci->lock, flags); + done: + return status; +@@ -2333,6 +2336,10 @@ static int sitd_submit(struct ehci_hcd * + usb_hcd_unlink_urb_from_ep(ehci_to_hcd(ehci), urb); + } + done_not_linked: ++ if (status < 0) { ++ iso_sched_free(stream, urb->hcpriv); ++ urb->hcpriv = NULL; ++ } + spin_unlock_irqrestore(&ehci->lock, flags); + done: + return status; +--- a/drivers/usb/host/fotg210-hcd.c ++++ b/drivers/usb/host/fotg210-hcd.c +@@ -4271,8 +4271,6 @@ static int iso_stream_schedule(struct fo + return 0; + + fail: +- iso_sched_free(stream, sched); +- urb->hcpriv = NULL; + return status; + } + +@@ -4566,6 +4564,10 @@ static int itd_submit(struct fotg210_hcd + else + usb_hcd_unlink_urb_from_ep(fotg210_to_hcd(fotg210), urb); + done_not_linked: ++ if (status < 0) { ++ iso_sched_free(stream, urb->hcpriv); ++ urb->hcpriv = NULL; ++ } + spin_unlock_irqrestore(&fotg210->lock, flags); + done: + return status; diff --git a/queue-5.10/usb-gadget-f_fs-initialize-reset_work-at-allocation-time.patch b/queue-5.10/usb-gadget-f_fs-initialize-reset_work-at-allocation-time.patch new file mode 100644 index 0000000000..0b0305fb8d --- /dev/null +++ b/queue-5.10/usb-gadget-f_fs-initialize-reset_work-at-allocation-time.patch @@ -0,0 +1,94 @@ +From sashal@kernel.org Mon Jul 20 15:59:24 2026 +From: Sasha Levin +Date: Mon, 20 Jul 2026 09:59:20 -0400 +Subject: usb: gadget: f_fs: initialize reset_work at allocation time +To: stable@vger.kernel.org +Cc: "Tyler Baker" , stable , "Loic Poulain" , "Dmitry Baryshkov" , "Srinivas Kandagatla" , "Peter Chen" , "Michał Nazarewicz" , "Greg Kroah-Hartman" , "Sasha Levin" +Message-ID: <20260720135920.1408367-1-sashal@kernel.org> + +From: Tyler Baker + +[ Upstream commit 3137b243c93982fe3460335e12f9247739766e10 ] + +ffs_fs_kill_sb() unconditionally calls cancel_work_sync() on +ffs->reset_work when a functionfs instance is unmounted: + + ffs_data_reset(ffs); + cancel_work_sync(&ffs->reset_work); + +However ffs->reset_work is only ever initialized via INIT_WORK() in +ffs_func_set_alt() and ffs_func_disable(), and only on the +FFS_DEACTIVATED path. That state is reached solely by ffs_data_closed() +when the instance is mounted with the "no_disconnect" option, so for the +common case (no "no_disconnect", or mounted and unmounted without ever +being deactivated) reset_work is never initialized. + +ffs_data_new() allocates the ffs_data with kzalloc_obj() and does not +initialize reset_work, and ffs_data_reset()/ffs_data_clear() do not touch +it either, so reset_work.func is left NULL. cancel_work_sync() on such a +work then trips the WARN_ON(!work->func) guard in __flush_work(): + + WARNING: kernel/workqueue.c:4301 at __flush_work+0x330/0x360, CPU#3: umount + Call trace: + __flush_work + cancel_work_sync + ffs_fs_kill_sb [usb_f_fs] + deactivate_locked_super + deactivate_super + cleanup_mnt + __cleanup_mnt + task_work_run + exit_to_user_mode_loop + el0_svc + +On older kernels cancel_work_sync() on a zero-initialized work struct was +a silent no-op, which hid the missing initialization. + +Initialize reset_work once in ffs_data_new() so it is always valid for +the lifetime of the ffs_data, and drop the now-redundant INIT_WORK() +calls from the two deactivation paths. + +Fixes: 18d6b32fca38 ("usb: gadget: f_fs: add "no_disconnect" mode") +Cc: stable +Signed-off-by: Tyler Baker +Cc: Loic Poulain +Cc: Dmitry Baryshkov +Cc: Srinivas Kandagatla +Tested-by: Loic Poulain +Reviewed-by: Peter Chen +Acked-by: Michał Nazarewicz +Link: https://patch.msgid.link/20260609193635.2284430-1-tyler.baker@oss.qualcomm.com +Signed-off-by: Greg Kroah-Hartman +[ dropped the ffs_func_disable hunk since 6.6 predates the disable-body split and routes disable through ffs_func_set_alt, so removing the single lazy INIT_WORK there covers both paths ] +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/gadget/function/f_fs.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/usb/gadget/function/f_fs.c ++++ b/drivers/usb/gadget/function/f_fs.c +@@ -254,6 +254,7 @@ static int ffs_acquire_dev(const char *d + static void ffs_release_dev(struct ffs_dev *ffs_dev); + static int ffs_ready(struct ffs_data *ffs); + static void ffs_closed(struct ffs_data *ffs); ++static void ffs_reset_work(struct work_struct *work); + + /* Misc helper functions ****************************************************/ + +@@ -1774,6 +1775,7 @@ static struct ffs_data *ffs_data_new(con + init_waitqueue_head(&ffs->ev.waitq); + init_waitqueue_head(&ffs->wait); + init_completion(&ffs->ep0req_completion); ++ INIT_WORK(&ffs->reset_work, ffs_reset_work); + + /* XXX REVISIT need to update it in some places, or do we? */ + ffs->ev.can_stall = 1; +@@ -3330,7 +3332,6 @@ static int ffs_func_set_alt(struct usb_f + + if (ffs->state == FFS_DEACTIVATED) { + ffs->state = FFS_CLOSING; +- INIT_WORK(&ffs->reset_work, ffs_reset_work); + schedule_work(&ffs->reset_work); + return -ENODEV; + } diff --git a/queue-5.10/usb-gadget-f_fs-tie-read_buffer-lifetime-to-ffs_epfile.patch b/queue-5.10/usb-gadget-f_fs-tie-read_buffer-lifetime-to-ffs_epfile.patch new file mode 100644 index 0000000000..ae32794945 --- /dev/null +++ b/queue-5.10/usb-gadget-f_fs-tie-read_buffer-lifetime-to-ffs_epfile.patch @@ -0,0 +1,55 @@ +From sashal@kernel.org Mon Jul 20 17:56:43 2026 +From: Sasha Levin +Date: Mon, 20 Jul 2026 11:56:40 -0400 +Subject: usb: gadget: f_fs: Tie read_buffer lifetime to ffs_epfile +To: stable@vger.kernel.org +Cc: Neill Kapron , stable , Greg Kroah-Hartman , Sasha Levin +Message-ID: <20260720155640.2425938-1-sashal@kernel.org> + +From: Neill Kapron + +[ Upstream commit 8bdcf96eb135aebacac319667f87db034fb38406 ] + +Currently, ffs_epfile_release unconditionally frees the endpoint's +read_buffer when a file descriptor is closed. If userspace explicitly +opens the endpoint multiple times and closes one, the read_buffer is +destroyed. This can lead to silent data loss if other file descriptors +are still actively reading from the endpoint. + +By tying the lifetime of the read_buffer to the ffs_epfile structure itself +(which is destroyed when the functionfs instance is torn down in +ffs_epfiles_destroy), we eliminate the brittle dependency on open/release +calls while correctly matching the conceptual lifetime of unread data on +the hardware endpoint. + +Fixes: 9353afbbfa7b ("usb: gadget: f_fs: buffer data from ‘oversized’ OUT requests") +Cc: stable +Assisted-by: Antigravity:gemini-3.1-pro +Signed-off-by: Neill Kapron +Link: https://patch.msgid.link/20260619040609.4010746-3-nkapron@google.com +Signed-off-by: Greg Kroah-Hartman +[ adjusted context in ffs_epfiles_destroy() since 6.12 lacks the simple_remove_by_name() rework and still uses dentry-based cleanup ] +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/gadget/function/f_fs.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/usb/gadget/function/f_fs.c ++++ b/drivers/usb/gadget/function/f_fs.c +@@ -1279,7 +1279,6 @@ ffs_epfile_release(struct inode *inode, + + ENTER(); + +- __ffs_epfile_read_buffer_free(epfile); + ffs_data_closed(epfile->ffs); + + return 0; +@@ -1945,6 +1944,7 @@ static void ffs_epfiles_destroy(struct f + + for (; count; --count, ++epfile) { + BUG_ON(mutex_is_locked(&epfile->mutex)); ++ __ffs_epfile_read_buffer_free(epfile); + if (epfile->dentry) { + d_delete(epfile->dentry); + dput(epfile->dentry); diff --git a/queue-5.10/usb-gadget-f_printer-take-kref-only-for-successful-open.patch b/queue-5.10/usb-gadget-f_printer-take-kref-only-for-successful-open.patch new file mode 100644 index 0000000000..560eb826c9 --- /dev/null +++ b/queue-5.10/usb-gadget-f_printer-take-kref-only-for-successful-open.patch @@ -0,0 +1,46 @@ +From stable+bounces-277456-greg=kroah.com@vger.kernel.org Sun Jul 19 16:54:07 2026 +From: Sasha Levin +Date: Sun, 19 Jul 2026 10:53:42 -0400 +Subject: usb: gadget: f_printer: take kref only for successful open +To: stable@vger.kernel.org +Cc: Xu Rao , stable , Greg Kroah-Hartman , Sasha Levin +Message-ID: <20260719145342.5397-2-sashal@kernel.org> + +From: Xu Rao + +[ Upstream commit 30adce93d5c4a5a1ec29d9249e3fdfcc391d406b ] + +printer_open() returns -EBUSY when the character device is already +open, but it increments dev->kref regardless of the return value. VFS +does not call ->release() for a failed open, so every rejected second +open permanently leaks one reference. + +Move kref_get() into the successful-open branch. + +Fixes: e8d5f92b8d30 ("usb: gadget: function: printer: fix use-after-free in __lock_acquire") +Cc: stable +Signed-off-by: Xu Rao +Link: https://patch.msgid.link/80295742B820DA9B+20260626064617.4090626-1-raoxu@uniontech.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/gadget/function/f_printer.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +--- a/drivers/usb/gadget/function/f_printer.c ++++ b/drivers/usb/gadget/function/f_printer.c +@@ -358,12 +358,11 @@ printer_open(struct inode *inode, struct + ret = 0; + /* Change the printer status to show that it's on-line. */ + dev->printer_status |= PRINTER_SELECTED; ++ kref_get(&dev->kref); + } + + spin_unlock_irqrestore(&dev->lock, flags); + +- kref_get(&dev->kref); +- + return ret; + } + diff --git a/queue-5.10/usb-gadget-function-simplify-diagnostic-messaging-in-printer.patch b/queue-5.10/usb-gadget-function-simplify-diagnostic-messaging-in-printer.patch new file mode 100644 index 0000000000..7cba917126 --- /dev/null +++ b/queue-5.10/usb-gadget-function-simplify-diagnostic-messaging-in-printer.patch @@ -0,0 +1,72 @@ +From stable+bounces-277455-greg=kroah.com@vger.kernel.org Sun Jul 19 16:53:50 2026 +From: Sasha Levin +Date: Sun, 19 Jul 2026 10:53:41 -0400 +Subject: usb: gadget: function: Simplify diagnostic messaging in printer +To: stable@vger.kernel.org +Cc: Andrzej Pietrasiewicz , Greg Kroah-Hartman , Sasha Levin +Message-ID: <20260719145342.5397-1-sashal@kernel.org> + +From: Andrzej Pietrasiewicz + +[ Upstream commit 57b7b733b1a7aeab25bc2670afff608214284863 ] + +Don't issue messages which can be easily achieved with ftrace. +In case of printer_open() the return code is propagated to other layers +so the user will know about -EBUSY anyway. + +Signed-off-by: Andrzej Pietrasiewicz +Link: https://lore.kernel.org/r/20221123110746.59611-1-andrzej.p@collabora.com +Signed-off-by: Greg Kroah-Hartman +Stable-dep-of: 30adce93d5c4 ("usb: gadget: f_printer: take kref only for successful open") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/gadget/function/f_printer.c | 9 +-------- + 1 file changed, 1 insertion(+), 8 deletions(-) + +--- a/drivers/usb/gadget/function/f_printer.c ++++ b/drivers/usb/gadget/function/f_printer.c +@@ -363,7 +363,7 @@ printer_open(struct inode *inode, struct + spin_unlock_irqrestore(&dev->lock, flags); + + kref_get(&dev->kref); +- DBG(dev, "printer_open returned %x\n", ret); ++ + return ret; + } + +@@ -381,7 +381,6 @@ printer_close(struct inode *inode, struc + spin_unlock_irqrestore(&dev->lock, flags); + + kref_put(&dev->kref, printer_dev_free); +- DBG(dev, "printer_close\n"); + + return 0; + } +@@ -867,8 +866,6 @@ static void printer_reset_interface(stru + if (dev->interface < 0) + return; + +- DBG(dev, "%s\n", __func__); +- + if (dev->in_ep->desc) + usb_ep_disable(dev->in_ep); + +@@ -906,8 +903,6 @@ static void printer_soft_reset(struct pr + { + struct usb_request *req; + +- INFO(dev, "Received Printer Reset Request\n"); +- + if (usb_ep_disable(dev->in_ep)) + DBG(dev, "Failed to disable USB in_ep\n"); + if (usb_ep_disable(dev->out_ep)) +@@ -1204,8 +1199,6 @@ static void printer_func_disable(struct + { + struct printer_dev *dev = func_to_printer(f); + +- DBG(dev, "%s\n", __func__); +- + printer_reset_interface(dev); + } + diff --git a/queue-5.10/usb-iowarrior-remove-inherent-race-with-minor-number.patch b/queue-5.10/usb-iowarrior-remove-inherent-race-with-minor-number.patch new file mode 100644 index 0000000000..782a92f5d8 --- /dev/null +++ b/queue-5.10/usb-iowarrior-remove-inherent-race-with-minor-number.patch @@ -0,0 +1,109 @@ +From stable+bounces-277503-greg=kroah.com@vger.kernel.org Sun Jul 19 18:39:26 2026 +From: Sasha Levin +Date: Sun, 19 Jul 2026 12:39:18 -0400 +Subject: usb: iowarrior: remove inherent race with minor number +To: stable@vger.kernel.org +Cc: Oliver Neukum , Greg Kroah-Hartman , Sasha Levin +Message-ID: <20260719163919.650822-1-sashal@kernel.org> + +From: Oliver Neukum + +[ Upstream commit 56dd29088c9d9510c48a8ebad2465248fde36551 ] + +The driver saves the minor number it gets upon registration +in its descriptor for debugging purposes. However, there is +inevitably a window between registration and saving the correct +minor in a descriptor. During this window the debugging output +will be wrong. +As wrong debug output is worse than no debug output, just +remove it. + +Signed-off-by: Oliver Neukum +Link: https://patch.msgid.link/20260312094619.1590556-1-oneukum@suse.com +Signed-off-by: Greg Kroah-Hartman +Stable-dep-of: c602254ba4c1 ("USB: iowarrior: fix use-after-free on disconnect race") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/misc/iowarrior.c | 17 +++-------------- + 1 file changed, 3 insertions(+), 14 deletions(-) + +--- a/drivers/usb/misc/iowarrior.c ++++ b/drivers/usb/misc/iowarrior.c +@@ -74,7 +74,6 @@ struct iowarrior { + struct mutex mutex; /* locks this structure */ + struct usb_device *udev; /* save off the usb device pointer */ + struct usb_interface *interface; /* the interface for this device */ +- unsigned char minor; /* the starting minor number for this device */ + struct usb_endpoint_descriptor *int_out_endpoint; /* endpoint for reading (needed for IOW56 only) */ + struct usb_endpoint_descriptor *int_in_endpoint; /* endpoint for reading */ + struct urb *int_in_urb; /* the urb for reading data */ +@@ -246,7 +245,6 @@ static void iowarrior_write_callback(str + */ + static inline void iowarrior_delete(struct iowarrior *dev) + { +- dev_dbg(&dev->interface->dev, "minor %d\n", dev->minor); + kfree(dev->int_in_buffer); + usb_free_urb(dev->int_in_urb); + kfree(dev->read_queue); +@@ -297,9 +295,6 @@ static ssize_t iowarrior_read(struct fil + goto exit; + } + +- dev_dbg(&dev->interface->dev, "minor %d, count = %zd\n", +- dev->minor, count); +- + /* read count must be packet size (+ time stamp) */ + if ((count != dev->report_size) + && (count != (dev->report_size + 1))) { +@@ -379,8 +374,6 @@ static ssize_t iowarrior_write(struct fi + retval = -ENODEV; + goto exit; + } +- dev_dbg(&dev->interface->dev, "minor %d, count = %zd\n", +- dev->minor, count); + /* if count is 0 we're already done */ + if (count == 0) { + retval = 0; +@@ -526,9 +519,6 @@ static long iowarrior_ioctl(struct file + goto error_out; + } + +- dev_dbg(&dev->interface->dev, "minor %d, cmd 0x%.4x, arg %ld\n", +- dev->minor, cmd, arg); +- + retval = 0; + io_res = 0; + switch (cmd) { +@@ -675,8 +665,6 @@ static int iowarrior_release(struct inod + if (!dev) + return -ENODEV; + +- dev_dbg(&dev->interface->dev, "minor %d\n", dev->minor); +- + /* lock our device */ + mutex_lock(&dev->mutex); + +@@ -779,6 +767,7 @@ static int iowarrior_probe(struct usb_in + struct usb_host_interface *iface_desc; + int retval = -ENOMEM; + int res; ++ int minor; + + /* allocate memory for our device state and initialize it */ + dev = kzalloc(sizeof(struct iowarrior), GFP_KERNEL); +@@ -894,12 +883,12 @@ static int iowarrior_probe(struct usb_in + goto error; + } + +- dev->minor = interface->minor; ++ minor = interface->minor; + + /* let the user know what node this device is now attached to */ + dev_info(&interface->dev, "IOWarrior product=0x%x, serial=%s interface=%d " + "now attached to iowarrior%d\n", dev->product_id, dev->chip_serial, +- iface_desc->desc.bInterfaceNumber, dev->minor - IOWARRIOR_MINOR_BASE); ++ iface_desc->desc.bInterfaceNumber, minor - IOWARRIOR_MINOR_BASE); + return retval; + + error: diff --git a/queue-5.10/usb-serial-digi_acceleport-fix-write-buffer-corruption.patch b/queue-5.10/usb-serial-digi_acceleport-fix-write-buffer-corruption.patch new file mode 100644 index 0000000000..216b471ce6 --- /dev/null +++ b/queue-5.10/usb-serial-digi_acceleport-fix-write-buffer-corruption.patch @@ -0,0 +1,79 @@ +From sashal@kernel.org Sun Jul 19 20:01:32 2026 +From: Sasha Levin +Date: Sun, 19 Jul 2026 14:01:28 -0400 +Subject: USB: serial: digi_acceleport: fix write buffer corruption +To: stable@vger.kernel.org +Cc: Johan Hovold , Greg Kroah-Hartman , Sasha Levin +Message-ID: <20260719180128.1055268-1-sashal@kernel.org> + +From: Johan Hovold + +[ Upstream commit 24ca1fea8f2753bf33e1d458ec1ae5d9b7796a65 ] + +The digi_write_inb_command() is supposed to wait for the write urb to +become available or return an error, but instead it updates the transfer +buffer and tries to resubmit the urb on timeout. + +To make things worse, for commands like break control where no timeout +is used, the driver would corrupt the urb immediately due to a broken +jiffies comparison (on 32-bit machines this takes five minutes of uptime +to trigger due to INITIAL_JIFFIES). + +Fix this by adding the missing return on timeout and waiting +indefinitely when no timeout has been specified as intended. + +This issue was (sort of) flagged by Sashiko when reviewing an unrelated +change to the driver. + +Link: https://sashiko.dev/#/patchset/20260610132232.356139-1-johan%40kernel.org?part=11 +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Cc: stable@vger.kernel.org +Reviewed-by: Greg Kroah-Hartman +Signed-off-by: Johan Hovold +[ adjusted context for 5.10's `&port->write_wait` (no `priv->write_wait`) and kept the existing `unsigned long flags = 0;` declaration alongside the new `expire` variable ] +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/serial/digi_acceleport.c | 15 ++++++++++----- + 1 file changed, 10 insertions(+), 5 deletions(-) + +--- a/drivers/usb/serial/digi_acceleport.c ++++ b/drivers/usb/serial/digi_acceleport.c +@@ -431,20 +431,22 @@ static int digi_write_inb_command(struct + int len; + struct digi_port *priv = usb_get_serial_port_data(port); + unsigned char *data = port->write_urb->transfer_buffer; ++ unsigned long expire; + unsigned long flags = 0; + + dev_dbg(&port->dev, "digi_write_inb_command: TOP: port=%d, count=%d\n", + priv->dp_port_num, count); + + if (timeout) +- timeout += jiffies; +- else +- timeout = ULONG_MAX; ++ expire = jiffies + timeout; + + spin_lock_irqsave(&priv->dp_port_lock, flags); + while (count > 0 && ret == 0) { +- while (priv->dp_write_urb_in_use && +- time_before(jiffies, timeout)) { ++ while (priv->dp_write_urb_in_use) { ++ if (timeout && time_after(jiffies, expire)) { ++ ret = -ETIMEDOUT; ++ break; ++ } + cond_wait_interruptible_timeout_irqrestore( + &port->write_wait, DIGI_RETRY_TIMEOUT, + &priv->dp_port_lock, flags); +@@ -453,6 +455,9 @@ static int digi_write_inb_command(struct + spin_lock_irqsave(&priv->dp_port_lock, flags); + } + ++ if (ret) ++ break; ++ + /* len must be a multiple of 4 and small enough to */ + /* guarantee the write will send buffered data first, */ + /* so commands are in order with data and not split */ diff --git a/queue-5.10/usb-typec-tcpm-fix-vdm-type-for-enter-mode-commands.patch b/queue-5.10/usb-typec-tcpm-fix-vdm-type-for-enter-mode-commands.patch new file mode 100644 index 0000000000..235eada98c --- /dev/null +++ b/queue-5.10/usb-typec-tcpm-fix-vdm-type-for-enter-mode-commands.patch @@ -0,0 +1,39 @@ +From sashal@kernel.org Mon Jul 20 12:56:38 2026 +From: Sasha Levin +Date: Mon, 20 Jul 2026 06:54:58 -0400 +Subject: usb: typec: tcpm: Fix VDM type for Enter Mode commands +To: stable@vger.kernel.org +Cc: Andy Yan , stable , Heikki Krogerus , Greg Kroah-Hartman , Sasha Levin +Message-ID: <20260720105458.217218-1-sashal@kernel.org> + +From: Andy Yan + +[ Upstream commit 9cff680e47632b7723cb19f9c5e63669063c3417 ] + +VDO() second parameter is VDM type (bit 15): 1 for SVDM, 0 for UVDM. +Using 'vdo ? 2 : 1' corrupts SVID low bit when vdo is non-NULL +(2 << 15 = BIT(16)). Enter Mode is always SVDM, hardcode to 1. + +Fixes: 8face9aa57c8 ("usb: typec: Add parameter for the VDO to typec_altmode_enter()") +Cc: stable +Signed-off-by: Andy Yan +Reviewed-by: Heikki Krogerus +Link: https://patch.msgid.link/20260604105059.18750-1-andyshrk@163.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/typec/tcpm/tcpm.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/usb/typec/tcpm/tcpm.c ++++ b/drivers/usb/typec/tcpm/tcpm.c +@@ -1671,7 +1671,7 @@ static int tcpm_altmode_enter(struct typ + struct tcpm_port *port = typec_altmode_get_drvdata(altmode); + u32 header; + +- header = VDO(altmode->svid, vdo ? 2 : 1, CMD_ENTER_MODE); ++ header = VDO(altmode->svid, 1, CMD_ENTER_MODE); + header |= VDO_OPOS(altmode->mode); + + tcpm_queue_vdm_unlocked(port, header, vdo, vdo ? 1 : 0); diff --git a/queue-5.10/usb-typec-ucsi-ccg-fix-use-after-free-of-ucsi-on-remove.patch b/queue-5.10/usb-typec-ucsi-ccg-fix-use-after-free-of-ucsi-on-remove.patch new file mode 100644 index 0000000000..b1048057f0 --- /dev/null +++ b/queue-5.10/usb-typec-ucsi-ccg-fix-use-after-free-of-ucsi-on-remove.patch @@ -0,0 +1,56 @@ +From stable+bounces-277540-greg=kroah.com@vger.kernel.org Mon Jul 20 04:36:00 2026 +From: Sasha Levin +Date: Sun, 19 Jul 2026 22:35:39 -0400 +Subject: usb: typec: ucsi: ccg: Fix use-after-free of ucsi on remove +To: stable@vger.kernel.org +Cc: Fan Wu , stable , Heikki Krogerus , Greg Kroah-Hartman , Sasha Levin +Message-ID: <20260720023539.2968115-5-sashal@kernel.org> + +From: Fan Wu + +[ Upstream commit 1f0bdc2884b67de337215079bba166df0cdf4ac5 ] + +The threaded IRQ handler ccg_irq_handler() calls ucsi_notify_common(), +which on a connector-change event calls ucsi_connector_change() and +schedules connector work. In ucsi_ccg_remove(), ucsi_destroy() frees +uc->ucsi (kfree) before free_irq() is called, so a handler invocation +already in flight may access the freed object after ucsi_destroy(). + + CPU 0 (remove) | CPU 1 (threaded IRQ) + ucsi_destroy(uc->ucsi) | ccg_irq_handler() + kfree(ucsi) // FREE | ucsi_notify_common(uc->ucsi) // USE + +Move free_irq() before ucsi_destroy() in the remove path. It is kept +after ucsi_unregister(): ucsi_unregister() cancels connector work whose +handler issues GET_CONNECTOR_STATUS through ucsi_send_command_common(), +which waits for a completion that is signalled from the IRQ handler, so +the IRQ must stay active until that work has been cancelled. + +The probe error path already orders free_irq() before ucsi_destroy(). + +This bug was found by static analysis. + +Fixes: e32fd989ac1c ("usb: typec: ucsi: ccg: Move to the new API") +Cc: stable +Signed-off-by: Fan Wu +Reviewed-by: Heikki Krogerus +Link: https://patch.msgid.link/20260616132011.103279-1-fanwu01@zju.edu.cn +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/typec/ucsi/ucsi_ccg.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/usb/typec/ucsi/ucsi_ccg.c ++++ b/drivers/usb/typec/ucsi/ucsi_ccg.c +@@ -1418,8 +1418,8 @@ static int ucsi_ccg_remove(struct i2c_cl + cancel_work_sync(&uc->work); + pm_runtime_disable(uc->dev); + ucsi_unregister(uc->ucsi); +- ucsi_destroy(uc->ucsi); + free_irq(uc->irq, uc); ++ ucsi_destroy(uc->ucsi); + + return 0; + } diff --git a/queue-5.10/vfio-pci-release-the-vga-arbiter-client-on-register_device-failure.patch b/queue-5.10/vfio-pci-release-the-vga-arbiter-client-on-register_device-failure.patch new file mode 100644 index 0000000000..ff3c60d142 --- /dev/null +++ b/queue-5.10/vfio-pci-release-the-vga-arbiter-client-on-register_device-failure.patch @@ -0,0 +1,46 @@ +From stable+bounces-274251-greg=kroah.com@vger.kernel.org Tue Jul 14 15:44:56 2026 +From: Sasha Levin +Date: Tue, 14 Jul 2026 09:40:09 -0400 +Subject: vfio/pci: Release the VGA arbiter client on register_device() failure +To: stable@vger.kernel.org +Cc: Alex Williamson , Kevin Tian , Alex Williamson , Sasha Levin +Message-ID: <20260714134009.2674596-1-sashal@kernel.org> + +From: Alex Williamson + +[ Upstream commit daedde7f024ecf88bc8e832ed40cf2c795f0796a ] + +The re-order in the Fixes commit below displaced vfio_pci_vga_init() as +the last failure point of what is now vfio_pci_core_register_device() +without introducing an unwind for the VGA arbiter registration. + +In current kernels this is mostly benign because vfio_pci_set_decode() +only uses pci_dev state, but the original failure path could leave a +callback with a freed vdev cookie. The stale registration also becomes +unsafe again once the callback follows drvdata to the vfio device. + +Add the required VGA unwind callout. + +Fixes: 4aeec3984ddc ("vfio/pci: Re-order vfio_pci_probe()") +Cc: stable@vger.kernel.org +Assisted-by: Claude:claude-opus-4-8 +Signed-off-by: Alex Williamson +Reviewed-by: Kevin Tian +Link: https://lore.kernel.org/r/20260615191241.688297-3-alex.williamson@nvidia.com +Signed-off-by: Alex Williamson +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/vfio/pci/vfio_pci.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/vfio/pci/vfio_pci.c ++++ b/drivers/vfio/pci/vfio_pci.c +@@ -2094,6 +2094,7 @@ static int vfio_pci_probe(struct pci_dev + out_power: + if (!disable_idle_d3) + vfio_pci_set_power_state(vdev, PCI_D0); ++ vfio_pci_vga_uninit(vdev); + out_vf: + vfio_pci_vf_uninit(vdev); + out_reflck: diff --git a/queue-5.10/writeback-fix-race-between-cgroup_writeback_umount-and-inode_switch_wbs.patch b/queue-5.10/writeback-fix-race-between-cgroup_writeback_umount-and-inode_switch_wbs.patch new file mode 100644 index 0000000000..9eaba4d6e9 --- /dev/null +++ b/queue-5.10/writeback-fix-race-between-cgroup_writeback_umount-and-inode_switch_wbs.patch @@ -0,0 +1,149 @@ +From stable+bounces-276823-greg=kroah.com@vger.kernel.org Thu Jul 16 21:49:41 2026 +From: Sasha Levin +Date: Thu, 16 Jul 2026 15:49:31 -0400 +Subject: writeback: fix race between cgroup_writeback_umount() and inode_switch_wbs() +To: stable@vger.kernel.org +Cc: Baokun Li , Jan Kara , Tejun Heo , "Christian Brauner (Amutable)" , Sasha Levin +Message-ID: <20260716194931.1111583-1-sashal@kernel.org> + +From: Baokun Li + +[ Upstream commit cba38ec4cbd3a7b8b942a8d52531a05be8a9ff0d ] + +When a container exits, the following BUG_ON() is occasionally triggered: + +================================================================== + VFS: Busy inodes after unmount of sdb (ext4) + ------------[ cut here ]------------ + kernel BUG at fs/super.c:695! + CPU: 3 PID: 6 Comm: containerd-shim Tainted: G OE K 6.6 #1 + pstate: 63400009 (nZCv daif +PAN -UAO +TCO +DIT -SSBS BTYPE=--) + pc : generic_shutdown_super+0xf0/0x100 + lr : generic_shutdown_super+0xf0/0x100 + Call trace: + generic_shutdown_super+0xf0/0x100 + kill_block_super+0x20/0x48 + ext4_kill_sb+0x28/0x60 + deactivate_locked_super+0x54/0x130 + deactivate_super+0x84/0xa0 + cleanup_mnt+0xa4/0x140 + __cleanup_mnt+0x18/0x28 + task_work_run+0x78/0xe0 + do_notify_resume+0x204/0x240 +================================================================== + +The root cause is a race between cgroup_writeback_umount() and +inode_switch_wbs()/cleanup_offline_cgwb(). There is a window between +inode_prepare_wbs_switch() returning true and the subsequent +wb_queue_isw() call. Following is the process that triggers the issue: + + CPU A (umount) | CPU B (writeback) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + inode_switch_wbs/cleanup_offline_cgwb + atomic_inc(&isw_nr_in_flight) + inode_prepare_wbs_switch + -> passes SB_ACTIVE check + __iget(inode) + generic_shutdown_super + sb->s_flags &= ~SB_ACTIVE + cgroup_writeback_umount(sb) + smp_mb() + atomic_read(&isw_nr_in_flight) + rcu_barrier() + -> no pending RCU callbacks + flush_workqueue(isw_wq) + -> nothing queued, returns + evict_inodes(sb) + -> Inode skipped as isw still holds a ref. + sop->put_super(sb) + /* destroys percpu counters */ + -> VFS: Busy inodes after unmount! + wb_queue_isw() + queue_work(isw_wq, ...) + /* later in work function */ + inode_switch_wbs_work_fn + process_inode_switch_wbs + iput() -> evict + percpu_counter_dec() // UAF! + +Fix this by extending the RCU read-side critical section in +inode_switch_wbs() and cleanup_offline_cgwb() to cover from +inode_prepare_wbs_switch() through wb_queue_isw(). Since there is +no sleep in this window, rcu_read_lock() can be used. Then add a +synchronize_rcu() in cgroup_writeback_umount() before the existing +rcu_barrier(), so that all in-flight switchers that have passed the +SB_ACTIVE check have completed queue_work() before flush_workqueue() +is called. + +The existing rcu_barrier() is intentionally retained so this fix can +be backported unchanged to stable kernels (5.10.y, 6.6.y, ...) that +still queue switches via queue_rcu_work(). It is a no-op on current +mainline (since commit e1b849cfa6b6 ("writeback: Avoid contention on +wb->list_lock when switching inodes")) and is removed in a follow-up +patch. + +Fixes: a1a0e23e4903 ("writeback: flush inode cgroup wb switches instead of pinning super_block") +Cc: stable@vger.kernel.org +Suggested-by: Jan Kara +Link: https://lore.kernel.org/all/mxnjq2l6guusfchvauxr3v7c4bwjasybxlleqbbh4efloeqspz@iqylk76ohufz +Reviewed-by: Jan Kara +Signed-off-by: Baokun Li +Link: https://patch.msgid.link/20260521095016.2791354-2-libaokun@linux.alibaba.com +Acked-by: Tejun Heo +Signed-off-by: Christian Brauner (Amutable) +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + fs/fs-writeback.c | 20 ++++++++++++++++++-- + 1 file changed, 18 insertions(+), 2 deletions(-) + +--- a/fs/fs-writeback.c ++++ b/fs/fs-writeback.c +@@ -507,12 +507,18 @@ static void inode_switch_wbs(struct inod + + atomic_inc(&isw_nr_in_flight); + +- /* find and pin the new wb */ ++ /* ++ * Paired with synchronize_rcu() in cgroup_writeback_umount(): ++ * holding rcu_read_lock across the SB_ACTIVE check, the inode ++ * grab and call_rcu() ensures synchronize_rcu() cannot return ++ * until the switch is queued, so the subsequent rcu_barrier() ++ * and flush_workqueue() will wait for the switch. ++ */ + rcu_read_lock(); ++ /* find and pin the new wb */ + memcg_css = css_from_id(new_wb_id, &memory_cgrp_subsys); + if (memcg_css && !css_tryget(memcg_css)) + memcg_css = NULL; +- rcu_read_unlock(); + if (!memcg_css) + goto out_free; + +@@ -542,9 +548,11 @@ static void inode_switch_wbs(struct inod + * Let's continue after I_WB_SWITCH is guaranteed to be visible. + */ + call_rcu(&isw->rcu_head, inode_switch_wbs_rcu_fn); ++ rcu_read_unlock(); + return; + + out_free: ++ rcu_read_unlock(); + atomic_dec(&isw_nr_in_flight); + if (isw->new_wb) + wb_put(isw->new_wb); +@@ -1011,6 +1019,14 @@ void cgroup_writeback_umount(void) + { + if (atomic_read(&isw_nr_in_flight)) { + /* ++ * Paired with rcu_read_lock() in inode_switch_wbs(). ++ * synchronize_rcu() waits for any in-flight switcher that ++ * already passed the SB_ACTIVE check to finish calling ++ * call_rcu(), so the rcu_barrier() and flush_workqueue() ++ * below will then drain it. ++ */ ++ synchronize_rcu(); ++ /* + * Use rcu_barrier() to wait for all pending callbacks to + * ensure that all in-flight wb switches are in the workqueue. + */ diff --git a/queue-5.10/x.509-fix-validation-of-asn.1-certificate-header.patch b/queue-5.10/x.509-fix-validation-of-asn.1-certificate-header.patch new file mode 100644 index 0000000000..a69f8e1300 --- /dev/null +++ b/queue-5.10/x.509-fix-validation-of-asn.1-certificate-header.patch @@ -0,0 +1,44 @@ +From stable+bounces-276826-greg=kroah.com@vger.kernel.org Thu Jul 16 21:54:31 2026 +From: Sasha Levin +Date: Thu, 16 Jul 2026 15:54:23 -0400 +Subject: X.509: Fix validation of ASN.1 certificate header +To: stable@vger.kernel.org +Cc: Lukas Wunner , Sashiko , Ignat Korchagin , Alistair Francis , Herbert Xu , Sasha Levin +Message-ID: <20260716195423.1113794-1-sashal@kernel.org> + +From: Lukas Wunner + +[ Upstream commit 3b626ba431c4501512ad07549310685e07fe4706 ] + +x509_load_certificate_list() seeks to enforce that a certificate starts +with 0x30 0x82 (ASN.1 SEQUENCE tag followed by a length of more than 256 +and less than 65535 bytes). + +But it only enforces that *either* of those two byte values are present, +instead of checking for the *conjunction* of the two values. Fix it. + +Fixes: 631cc66eb9ea ("MODSIGN: Provide module signing public keys to the kernel") +Reported-by: Sashiko +Closes: https://lore.kernel.org/r/20260508033917.B5873C2BCB0@smtp.kernel.org/ +Signed-off-by: Lukas Wunner +Cc: stable@vger.kernel.org # v3.7+ +Reviewed-by: Ignat Korchagin +Reviewed-by: Alistair Francis +Signed-off-by: Herbert Xu +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + certs/common.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/certs/common.c ++++ b/certs/common.c +@@ -20,7 +20,7 @@ int load_certificate_list(const u8 cert_ + */ + if (end - p < 4) + goto dodgy_cert; +- if (p[0] != 0x30 && ++ if (p[0] != 0x30 || + p[1] != 0x82) + goto dodgy_cert; + plen = (p[2] << 8) | p[3]; diff --git a/queue-5.10/xfs-fix-unreachable-bigtime-check-in-dquot-flush-validation.patch b/queue-5.10/xfs-fix-unreachable-bigtime-check-in-dquot-flush-validation.patch new file mode 100644 index 0000000000..39c09877f5 --- /dev/null +++ b/queue-5.10/xfs-fix-unreachable-bigtime-check-in-dquot-flush-validation.patch @@ -0,0 +1,63 @@ +From stable+bounces-277293-greg=kroah.com@vger.kernel.org Sat Jul 18 13:21:00 2026 +From: Sasha Levin +Date: Sat, 18 Jul 2026 07:20:48 -0400 +Subject: xfs: fix unreachable BIGTIME check in dquot flush validation +To: stable@vger.kernel.org +Cc: Alexey Nepomnyashih , "Darrick J. Wong" , Allison Henderson , Carlos Maiolino , Sasha Levin +Message-ID: <20260718112048.2959902-2-sashal@kernel.org> + +From: Alexey Nepomnyashih + +[ Upstream commit 03866d130ed33ab68cc7faaf4bf2c4abef96d42e ] + +The dqp->q_id == 0 check inside the XFS_DQTYPE_BIGTIME block is +unreachable because root dquots return successfully earlier. Reject root +dquots with XFS_DQTYPE_BIGTIME before that early return, preserving the +intended validation and removing the unreachable condition. + +Found by Linux Verification Center (linuxtesting.org) with SVACE. + +Fixes: 4ea1ff3b4968 ("xfs: widen ondisk quota expiration timestamps to handle y2038+") +Cc: stable@vger.kernel.org # v5.10+ +Signed-off-by: Alexey Nepomnyashih +Reviewed-by: "Darrick J. Wong" +Reviewed-by: Allison Henderson +Signed-off-by: Carlos Maiolino +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + fs/xfs/xfs_dquot.c | 16 ++++++++-------- + 1 file changed, 8 insertions(+), 8 deletions(-) + +--- a/fs/xfs/xfs_dquot.c ++++ b/fs/xfs/xfs_dquot.c +@@ -1201,6 +1201,14 @@ xfs_qm_dqflush_check( + type != XFS_DQTYPE_PROJ) + return __this_address; + ++ /* bigtime flag should never be set on root dquots */ ++ if (dqp->q_type & XFS_DQTYPE_BIGTIME) { ++ if (!xfs_has_bigtime(dqp->q_mount)) ++ return __this_address; ++ if (dqp->q_id == 0) ++ return __this_address; ++ } ++ + if (dqp->q_id == 0) + return NULL; + +@@ -1216,14 +1224,6 @@ xfs_qm_dqflush_check( + !dqp->q_rtb.timer) + return __this_address; + +- /* bigtime flag should never be set on root dquots */ +- if (dqp->q_type & XFS_DQTYPE_BIGTIME) { +- if (!xfs_has_bigtime(dqp->q_mount)) +- return __this_address; +- if (dqp->q_id == 0) +- return __this_address; +- } +- + return NULL; + } + diff --git a/queue-5.10/xfs-reflect-sb-features-in-xfs_mount.patch b/queue-5.10/xfs-reflect-sb-features-in-xfs_mount.patch new file mode 100644 index 0000000000..82151bc325 --- /dev/null +++ b/queue-5.10/xfs-reflect-sb-features-in-xfs_mount.patch @@ -0,0 +1,270 @@ +From stable+bounces-277292-greg=kroah.com@vger.kernel.org Sat Jul 18 13:20:58 2026 +From: Sasha Levin +Date: Sat, 18 Jul 2026 07:20:47 -0400 +Subject: xfs: reflect sb features in xfs_mount +To: stable@vger.kernel.org +Cc: Dave Chinner , Christoph Hellwig , "Darrick J. Wong" , Sasha Levin +Message-ID: <20260718112048.2959902-1-sashal@kernel.org> + +From: Dave Chinner + +[ Upstream commit a1d86e8dec8c1325d301c9d5594bb794bc428fc3 ] + +Currently on-disk feature checks require decoding the superblock +fileds and so can be non-trivial. We have almost 400 hundred +individual feature checks in the XFS code, so this is a significant +amount of code. To reduce runtime check overhead, pre-process all +the version flags into a features field in the xfs_mount at mount +time so we can convert all the feature checks to a simple flag +check. + +There is also a need to convert the dynamic feature flags to update +the m_features field. This is required for attr, attr2 and quota +features. New xfs_mount based wrappers are added for this. + +Signed-off-by: Dave Chinner +Reviewed-by: Christoph Hellwig +Reviewed-by: Darrick J. Wong +Signed-off-by: Darrick J. Wong +Stable-dep-of: 03866d130ed3 ("xfs: fix unreachable BIGTIME check in dquot flush validation") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + fs/xfs/libxfs/xfs_format.h | 2 - + fs/xfs/libxfs/xfs_sb.c | 64 ++++++++++++++++++++++++++++++++++++++ + fs/xfs/libxfs/xfs_sb.h | 1 + fs/xfs/xfs_dquot.c | 2 - + fs/xfs/xfs_log_recover.c | 1 + fs/xfs/xfs_mount.c | 1 + fs/xfs/xfs_mount.h | 75 +++++++++++++++++++++++++++++++++++++++++++++ + fs/xfs/xfs_rtalloc.c | 3 + + 8 files changed, 147 insertions(+), 2 deletions(-) + +--- a/fs/xfs/libxfs/xfs_format.h ++++ b/fs/xfs/libxfs/xfs_format.h +@@ -412,7 +412,7 @@ static inline bool xfs_sb_version_haspro + (sbp->sb_features2 & XFS_SB_VERSION2_PROJID32BIT)); + } + +-static inline void xfs_sb_version_addprojid32bit(struct xfs_sb *sbp) ++static inline void xfs_sb_version_addprojid32(struct xfs_sb *sbp) + { + sbp->sb_versionnum |= XFS_SB_VERSION_MOREBITSBIT; + sbp->sb_features2 |= XFS_SB_VERSION2_PROJID32BIT; +--- a/fs/xfs/libxfs/xfs_sb.c ++++ b/fs/xfs/libxfs/xfs_sb.c +@@ -91,6 +91,70 @@ xfs_perag_put( + trace_xfs_perag_put(pag->pag_mount, pag->pag_agno, ref, _RET_IP_); + } + ++uint64_t ++xfs_sb_version_to_features( ++ struct xfs_sb *sbp) ++{ ++ uint64_t features = 0; ++ ++ /* optional V4 features */ ++ if (sbp->sb_rblocks > 0) ++ features |= XFS_FEAT_REALTIME; ++ if (sbp->sb_versionnum & XFS_SB_VERSION_ATTRBIT) ++ features |= XFS_FEAT_ATTR; ++ if (sbp->sb_versionnum & XFS_SB_VERSION_QUOTABIT) ++ features |= XFS_FEAT_QUOTA; ++ if (sbp->sb_versionnum & XFS_SB_VERSION_ALIGNBIT) ++ features |= XFS_FEAT_ALIGN; ++ if (sbp->sb_versionnum & XFS_SB_VERSION_LOGV2BIT) ++ features |= XFS_FEAT_LOGV2; ++ if (sbp->sb_versionnum & XFS_SB_VERSION_DALIGNBIT) ++ features |= XFS_FEAT_DALIGN; ++ if (sbp->sb_versionnum & XFS_SB_VERSION_EXTFLGBIT) ++ features |= XFS_FEAT_EXTFLG; ++ if (sbp->sb_versionnum & XFS_SB_VERSION_SECTORBIT) ++ features |= XFS_FEAT_SECTOR; ++ if (sbp->sb_versionnum & XFS_SB_VERSION_BORGBIT) ++ features |= XFS_FEAT_ASCIICI; ++ if (sbp->sb_versionnum & XFS_SB_VERSION_MOREBITSBIT) { ++ if (sbp->sb_features2 & XFS_SB_VERSION2_LAZYSBCOUNTBIT) ++ features |= XFS_FEAT_LAZYSBCOUNT; ++ if (sbp->sb_features2 & XFS_SB_VERSION2_ATTR2BIT) ++ features |= XFS_FEAT_ATTR2; ++ if (sbp->sb_features2 & XFS_SB_VERSION2_PROJID32BIT) ++ features |= XFS_FEAT_PROJID32; ++ if (sbp->sb_features2 & XFS_SB_VERSION2_FTYPE) ++ features |= XFS_FEAT_FTYPE; ++ } ++ ++ if (XFS_SB_VERSION_NUM(sbp) != XFS_SB_VERSION_5) ++ return features; ++ ++ /* Always on V5 features */ ++ features |= XFS_FEAT_ALIGN | XFS_FEAT_LOGV2 | XFS_FEAT_EXTFLG | ++ XFS_FEAT_LAZYSBCOUNT | XFS_FEAT_ATTR2 | XFS_FEAT_PROJID32 | ++ XFS_FEAT_V3INODES | XFS_FEAT_CRC | XFS_FEAT_PQUOTINO; ++ ++ /* Optional V5 features */ ++ if (sbp->sb_features_ro_compat & XFS_SB_FEAT_RO_COMPAT_FINOBT) ++ features |= XFS_FEAT_FINOBT; ++ if (sbp->sb_features_ro_compat & XFS_SB_FEAT_RO_COMPAT_RMAPBT) ++ features |= XFS_FEAT_RMAPBT; ++ if (sbp->sb_features_ro_compat & XFS_SB_FEAT_RO_COMPAT_REFLINK) ++ features |= XFS_FEAT_REFLINK; ++ if (sbp->sb_features_ro_compat & XFS_SB_FEAT_RO_COMPAT_INOBTCNT) ++ features |= XFS_FEAT_INOBTCNT; ++ if (sbp->sb_features_incompat & XFS_SB_FEAT_INCOMPAT_FTYPE) ++ features |= XFS_FEAT_FTYPE; ++ if (sbp->sb_features_incompat & XFS_SB_FEAT_INCOMPAT_SPINODES) ++ features |= XFS_FEAT_SPINODES; ++ if (sbp->sb_features_incompat & XFS_SB_FEAT_INCOMPAT_META_UUID) ++ features |= XFS_FEAT_META_UUID; ++ if (sbp->sb_features_incompat & XFS_SB_FEAT_INCOMPAT_BIGTIME) ++ features |= XFS_FEAT_BIGTIME; ++ return features; ++} ++ + /* Check all the superblock fields we care about when reading one in. */ + STATIC int + xfs_validate_sb_read( +--- a/fs/xfs/libxfs/xfs_sb.h ++++ b/fs/xfs/libxfs/xfs_sb.h +@@ -29,6 +29,7 @@ extern void xfs_sb_mount_common(struct x + extern void xfs_sb_from_disk(struct xfs_sb *to, struct xfs_dsb *from); + extern void xfs_sb_to_disk(struct xfs_dsb *to, struct xfs_sb *from); + extern void xfs_sb_quota_from_disk(struct xfs_sb *sbp); ++extern uint64_t xfs_sb_version_to_features(struct xfs_sb *sbp); + + extern int xfs_update_secondary_sbs(struct xfs_mount *mp); + +--- a/fs/xfs/xfs_dquot.c ++++ b/fs/xfs/xfs_dquot.c +@@ -1218,7 +1218,7 @@ xfs_qm_dqflush_check( + + /* bigtime flag should never be set on root dquots */ + if (dqp->q_type & XFS_DQTYPE_BIGTIME) { +- if (!xfs_sb_version_hasbigtime(&dqp->q_mount->m_sb)) ++ if (!xfs_has_bigtime(dqp->q_mount)) + return __this_address; + if (dqp->q_id == 0) + return __this_address; +--- a/fs/xfs/xfs_log_recover.c ++++ b/fs/xfs/xfs_log_recover.c +@@ -3325,6 +3325,7 @@ xlog_do_recover( + xfs_buf_relse(bp); + + /* re-initialise in-core superblock and geometry structures */ ++ mp->m_features |= xfs_sb_version_to_features(sbp); + xfs_reinit_percpu_counters(mp); + error = xfs_initialize_perag(mp, sbp->sb_agcount, &mp->m_maxagi); + if (error) { +--- a/fs/xfs/xfs_mount.c ++++ b/fs/xfs/xfs_mount.c +@@ -345,6 +345,7 @@ reread: + goto reread; + } + ++ mp->m_features |= xfs_sb_version_to_features(sbp); + xfs_reinit_percpu_counters(mp); + + /* no need to be quiet anymore, so reset the buf ops */ +--- a/fs/xfs/xfs_mount.h ++++ b/fs/xfs/xfs_mount.h +@@ -131,6 +131,7 @@ typedef struct xfs_mount { + int m_fixedfsid[2]; /* unchanged for life of FS */ + uint m_qflags; /* quota status flags */ + uint64_t m_flags; /* global mount flags */ ++ uint64_t m_features; /* active filesystem features */ + int64_t m_low_space[XFS_LOWSP_MAX]; + struct xfs_ino_geometry m_ino_geo; /* inode geometry */ + struct xfs_trans_resv m_resv; /* precomputed res values */ +@@ -222,6 +223,80 @@ typedef struct xfs_mount { + #define M_IGEO(mp) (&(mp)->m_ino_geo) + + /* ++ * Flags for m_features. ++ * ++ * These are all the active features in the filesystem, regardless of how ++ * they are configured. ++ */ ++#define XFS_FEAT_ATTR (1ULL << 0) /* xattrs present in fs */ ++#define XFS_FEAT_NLINK (1ULL << 1) /* 32 bit link counts */ ++#define XFS_FEAT_QUOTA (1ULL << 2) /* quota active */ ++#define XFS_FEAT_ALIGN (1ULL << 3) /* inode alignment */ ++#define XFS_FEAT_DALIGN (1ULL << 4) /* data alignment */ ++#define XFS_FEAT_LOGV2 (1ULL << 5) /* version 2 logs */ ++#define XFS_FEAT_SECTOR (1ULL << 6) /* sector size > 512 bytes */ ++#define XFS_FEAT_EXTFLG (1ULL << 7) /* unwritten extents */ ++#define XFS_FEAT_ASCIICI (1ULL << 8) /* ASCII only case-insens. */ ++#define XFS_FEAT_LAZYSBCOUNT (1ULL << 9) /* Superblk counters */ ++#define XFS_FEAT_ATTR2 (1ULL << 10) /* dynamic attr fork */ ++#define XFS_FEAT_PARENT (1ULL << 11) /* parent pointers */ ++#define XFS_FEAT_PROJID32 (1ULL << 12) /* 32 bit project id */ ++#define XFS_FEAT_CRC (1ULL << 13) /* metadata CRCs */ ++#define XFS_FEAT_V3INODES (1ULL << 14) /* Version 3 inodes */ ++#define XFS_FEAT_PQUOTINO (1ULL << 15) /* non-shared proj/grp quotas */ ++#define XFS_FEAT_FTYPE (1ULL << 16) /* inode type in dir */ ++#define XFS_FEAT_FINOBT (1ULL << 17) /* free inode btree */ ++#define XFS_FEAT_RMAPBT (1ULL << 18) /* reverse map btree */ ++#define XFS_FEAT_REFLINK (1ULL << 19) /* reflinked files */ ++#define XFS_FEAT_SPINODES (1ULL << 20) /* sparse inode chunks */ ++#define XFS_FEAT_META_UUID (1ULL << 21) /* metadata UUID */ ++#define XFS_FEAT_REALTIME (1ULL << 22) /* realtime device present */ ++#define XFS_FEAT_INOBTCNT (1ULL << 23) /* inobt block counts */ ++#define XFS_FEAT_BIGTIME (1ULL << 24) /* large timestamps */ ++#define XFS_FEAT_NEEDSREPAIR (1ULL << 25) /* needs xfs_repair */ ++ ++#define __XFS_HAS_FEAT(name, NAME) \ ++static inline bool xfs_has_ ## name (struct xfs_mount *mp) \ ++{ \ ++ return mp->m_features & XFS_FEAT_ ## NAME; \ ++} ++ ++/* Some features can be added dynamically so they need a set wrapper, too. */ ++#define __XFS_ADD_FEAT(name, NAME) \ ++ __XFS_HAS_FEAT(name, NAME); \ ++static inline void xfs_add_ ## name (struct xfs_mount *mp) \ ++{ \ ++ mp->m_features |= XFS_FEAT_ ## NAME; \ ++ xfs_sb_version_add ## name(&mp->m_sb); \ ++} ++ ++__XFS_HAS_FEAT(nlink, NLINK) ++__XFS_ADD_FEAT(quota, QUOTA) ++__XFS_HAS_FEAT(align, ALIGN) ++__XFS_HAS_FEAT(dalign, DALIGN) ++__XFS_HAS_FEAT(logv2, LOGV2) ++__XFS_HAS_FEAT(sector, SECTOR) ++__XFS_HAS_FEAT(extflg, EXTFLG) ++__XFS_HAS_FEAT(asciici, ASCIICI) ++__XFS_HAS_FEAT(lazysbcount, LAZYSBCOUNT) ++__XFS_ADD_FEAT(attr2, ATTR2) ++__XFS_HAS_FEAT(parent, PARENT) ++__XFS_ADD_FEAT(projid32, PROJID32) ++__XFS_HAS_FEAT(crc, CRC) ++__XFS_HAS_FEAT(v3inodes, V3INODES) ++__XFS_HAS_FEAT(pquotino, PQUOTINO) ++__XFS_HAS_FEAT(ftype, FTYPE) ++__XFS_HAS_FEAT(finobt, FINOBT) ++__XFS_HAS_FEAT(rmapbt, RMAPBT) ++__XFS_HAS_FEAT(reflink, REFLINK) ++__XFS_HAS_FEAT(sparseinodes, SPINODES) ++__XFS_HAS_FEAT(metauuid, META_UUID) ++__XFS_HAS_FEAT(realtime, REALTIME) ++__XFS_HAS_FEAT(inobtcounts, INOBTCNT) ++__XFS_HAS_FEAT(bigtime, BIGTIME) ++__XFS_HAS_FEAT(needsrepair, NEEDSREPAIR) ++ ++/* + * Flags for m_flags. + */ + #define XFS_MOUNT_WSYNC (1ULL << 0) /* for nfs - all metadata ops +--- a/fs/xfs/xfs_rtalloc.c ++++ b/fs/xfs/xfs_rtalloc.c +@@ -1101,6 +1101,9 @@ error_cancel: + error = xfs_trans_commit(tp); + if (error) + break; ++ ++ /* Ensure the mount RT feature flag is now set. */ ++ mp->m_features |= XFS_FEAT_REALTIME; + } + if (error) + goto out_free; diff --git a/queue-5.10/xfs-use-null-daddr-for-unset-first-bad-log-block.patch b/queue-5.10/xfs-use-null-daddr-for-unset-first-bad-log-block.patch new file mode 100644 index 0000000000..341784193d --- /dev/null +++ b/queue-5.10/xfs-use-null-daddr-for-unset-first-bad-log-block.patch @@ -0,0 +1,55 @@ +From stable+bounces-277294-greg=kroah.com@vger.kernel.org Sat Jul 18 13:21:09 2026 +From: Sasha Levin +Date: Sat, 18 Jul 2026 07:21:01 -0400 +Subject: xfs: use null daddr for unset first bad log block +To: stable@vger.kernel.org +Cc: Yousef Alhouseen , "Darrick J. Wong" , syzbot+b7dfbed0c6c2b5e9fd34@syzkaller.appspotmail.com, Carlos Maiolino , Sasha Levin +Message-ID: <20260718112101.2964955-1-sashal@kernel.org> + +From: Yousef Alhouseen + +[ Upstream commit cc9af5e461ea5f6e37738f3f1e41c45a9b7f45d6 ] + +xlog_do_recovery_pass() may return before setting first_bad. The caller +must distinguish that case from an error at a valid log block, including +block zero after the log wraps. + +Initialize first_bad to XFS_BUF_DADDR_NULL and test it explicitly before +treating the error as a torn write. + +Fixes: 7088c4136fa1 ("xfs: detect and trim torn writes during log recovery") +Suggested-by: Darrick J. Wong +Reported-by: syzbot+b7dfbed0c6c2b5e9fd34@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=b7dfbed0c6c2b5e9fd34 +Cc: stable@vger.kernel.org # v4.5 +Signed-off-by: Yousef Alhouseen +Reviewed-by: "Darrick J. Wong" +Signed-off-by: Carlos Maiolino +[ adjusted hunk offsets for context drift and dropped an inapplicable whitespace-only end-of-file hunk whose context doesn't exist in 5.10 ] +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + fs/xfs/xfs_log_recover.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +--- a/fs/xfs/xfs_log_recover.c ++++ b/fs/xfs/xfs_log_recover.c +@@ -1034,7 +1034,7 @@ xlog_verify_head( + { + struct xlog_rec_header *tmp_rhead; + char *tmp_buffer; +- xfs_daddr_t first_bad; ++ xfs_daddr_t first_bad = XFS_BUF_DADDR_NULL; + xfs_daddr_t tmp_rhead_blk; + int found; + int error; +@@ -1063,7 +1063,8 @@ xlog_verify_head( + */ + error = xlog_do_recovery_pass(log, *head_blk, tmp_rhead_blk, + XLOG_RECOVER_CRCPASS, &first_bad); +- if ((error == -EFSBADCRC || error == -EFSCORRUPTED) && first_bad) { ++ if ((error == -EFSBADCRC || error == -EFSCORRUPTED) && ++ first_bad != XFS_BUF_DADDR_NULL) { + /* + * We've hit a potential torn write. Reset the error and warn + * about it.