From: Greg Kroah-Hartman Date: Mon, 30 Mar 2026 10:05:32 +0000 (+0200) Subject: 6.19-stable patches X-Git-Tag: v6.6.131~35 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=aa320c84f4f4243f47248b1addf70ebbe1982193;p=thirdparty%2Fkernel%2Fstable-queue.git 6.19-stable patches added patches: alarmtimer-fix-argument-order-in-alarm_timer_forward.patch dmaengine-fsl-edma-fix-channel-parameter-config-for-fixed-channel-requests.patch dmaengine-sh-rz-dmac-move-chctrl-updates-under-spinlock.patch dmaengine-sh-rz-dmac-protect-the-driver-specific-lists.patch drm-amd-display-check-if-ext_caps-is-valid-in-bl-setup.patch drm-amd-display-fix-dce-lvds-handling.patch drm-amd-display-fix-drm_edid-leak-in-amdgpu_dm.patch drm-amd-pm-return-eopnotsupp-for-unsupported-od_mclk-on-smu_v13_0_6.patch drm-amdgpu-fix-strsep-corrupting-lockup_timeout-on-multi-gpu-v3.patch drm-amdgpu-prevent-immediate-pasid-reuse-case.patch drm-i915-dp_tunnel-fix-error-handling-when-clearing-stream-bw-in-atomic-state.patch drm-i915-order-op-vs.-timeout-correctly-in-__wait_for.patch drm-i915-unlink-nv12-planes-earlier.patch futex-clear-stale-exiting-pointer-in-futex_lock_pi-retry-path.patch i2c-designware-amdisp-fix-resume-probe-race-condition-issue.patch i2c-imx-ensure-no-clock-is-generated-after-last-read.patch i2c-imx-fix-i2c-issue-when-reading-multiple-messages.patch iomap-fix-invalid-folio-access-when-i_blkbits-differs-from-i-o-granularity.patch irqchip-qcom-mpm-add-missing-mailbox-tx-done-acknowledgment.patch jbd2-gracefully-abort-on-checkpointing-state-corruptions.patch kvm-x86-mmu-drop-zap-existing-present-spte-even-when-creating-an-mmio-spte.patch kvm-x86-mmu-only-warn-in-direct-mmus-when-overwriting-shadow-present-spte.patch loongarch-fix-missing-null-checks-for-kstrdup.patch loongarch-kvm-fix-base-address-calculation-in-kvm_eiointc_regs_access.patch loongarch-kvm-handle-the-case-that-eiointc-s-coremap-is-empty.patch loongarch-kvm-make-kvm_get_vcpu_by_cpuid-more-robust.patch loongarch-vdso-emit-gnu_eh_frame-correctly.patch loongarch-workaround-ls2k-ls7a-gpu-dma-hang-bug.patch mm-damon-sysfs-check-contexts-nr-before-accessing-contexts_arr.patch mm-damon-sysfs-check-contexts-nr-in-repeat_call_fn.patch mm-damon-sysfs-fix-param_ctx-leak-on-damon_sysfs_new_test_ctx-failure.patch mm-huge_memory-fix-folio-isn-t-locked-in-softleaf_to_folio.patch mm-memory-fix-pmd-pud-checks-in-follow_pfnmap_start.patch mm-mseal-update-vma-end-correctly-on-merge.patch mm-pagewalk-fix-race-between-concurrent-split-and-refault.patch net-macb-move-devm_-free-request-_irq-out-of-spin-lock-area.patch net-macb-protect-access-to-net_device-ip_ptr-with-rcu-lock.patch net-macb-use-dev_consume_skb_any-to-free-tx-skbs.patch ovl-fix-wrong-detection-of-32bit-inode-numbers.patch ovl-make-fsync-after-metadata-copy-up-opt-in-mount-option.patch phy-qcom-qmp-ufs-fix-sm8650-pcs-table-for-gear-4.patch scsi-ibmvfc-fix-oob-access-in-ibmvfc_discover_targets_done.patch scsi-ses-handle-positive-scsi-error-from-ses_recv_diag.patch writeback-don-t-block-sync-for-filesystems-with-no-data-integrity-guarantees.patch x86-cpu-enable-fsgsbase-early-in-cpu_init_exception_handling.patch x86-cpu-remove-x86_cr4_fred-from-the-cr4-pinned-bits-mask.patch x86-fred-fix-early-boot-failures-on-sev-es-snp-guests.patch xfs-avoid-dereferencing-log-items-after-push-callbacks.patch xfs-don-t-irele-after-failing-to-iget-in-xfs_attri_recover_work.patch xfs-fix-ri_total-validation-in-xlog_recover_attri_commit_pass2.patch xfs-remove-file_path-tracepoint-data.patch xfs-save-ailp-before-dropping-the-ail-lock-in-push-callbacks.patch xfs-scrub-unlock-dquot-before-early-return-in-quota-scrub.patch xfs-stop-reclaim-before-pushing-ail-during-unmount.patch --- diff --git a/queue-6.19/alarmtimer-fix-argument-order-in-alarm_timer_forward.patch b/queue-6.19/alarmtimer-fix-argument-order-in-alarm_timer_forward.patch new file mode 100644 index 0000000000..17e7892714 --- /dev/null +++ b/queue-6.19/alarmtimer-fix-argument-order-in-alarm_timer_forward.patch @@ -0,0 +1,51 @@ +From 5d16467ae56343b9205caedf85e3a131e0914ad8 Mon Sep 17 00:00:00 2001 +From: Zhan Xusheng +Date: Mon, 23 Mar 2026 14:11:30 +0800 +Subject: alarmtimer: Fix argument order in alarm_timer_forward() + +From: Zhan Xusheng + +commit 5d16467ae56343b9205caedf85e3a131e0914ad8 upstream. + +alarm_timer_forward() passes arguments to alarm_forward() in the wrong +order: + + alarm_forward(alarm, timr->it_interval, now); + +However, alarm_forward() is defined as: + + u64 alarm_forward(struct alarm *alarm, ktime_t now, ktime_t interval); + +and uses the second argument as the current time: + + delta = ktime_sub(now, alarm->node.expires); + +Passing the interval as "now" results in incorrect delta computation, +which can lead to missed expirations or incorrect overrun accounting. + +This issue has been present since the introduction of +alarm_timer_forward(). + +Fix this by swapping the arguments. + +Fixes: e7561f1633ac ("alarmtimer: Implement forward callback") +Signed-off-by: Zhan Xusheng +Signed-off-by: Thomas Gleixner +Cc: stable@vger.kernel.org +Link: https://patch.msgid.link/20260323061130.29991-1-zhanxusheng@xiaomi.com +Signed-off-by: Greg Kroah-Hartman +--- + kernel/time/alarmtimer.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/kernel/time/alarmtimer.c ++++ b/kernel/time/alarmtimer.c +@@ -540,7 +540,7 @@ static s64 alarm_timer_forward(struct k_ + { + struct alarm *alarm = &timr->it.alarm.alarmtimer; + +- return alarm_forward(alarm, timr->it_interval, now); ++ return alarm_forward(alarm, now, timr->it_interval); + } + + /** diff --git a/queue-6.19/dmaengine-fsl-edma-fix-channel-parameter-config-for-fixed-channel-requests.patch b/queue-6.19/dmaengine-fsl-edma-fix-channel-parameter-config-for-fixed-channel-requests.patch new file mode 100644 index 0000000000..dd4eb7ad85 --- /dev/null +++ b/queue-6.19/dmaengine-fsl-edma-fix-channel-parameter-config-for-fixed-channel-requests.patch @@ -0,0 +1,75 @@ +From 2e7b5cf72e51c9cf9c8b75190189c757df31ddd9 Mon Sep 17 00:00:00 2001 +From: Joy Zou +Date: Wed, 17 Sep 2025 17:53:42 +0800 +Subject: dmaengine: fsl-edma: fix channel parameter config for fixed channel requests + +From: Joy Zou + +commit 2e7b5cf72e51c9cf9c8b75190189c757df31ddd9 upstream. + +Configure only the requested channel when a fixed channel is specified +to avoid modifying other channels unintentionally. + +Fix parameter configuration when a fixed DMA channel is requested on +i.MX9 AON domain and i.MX8QM/QXP/DXL platforms. When a client requests +a fixed channel (e.g., channel 6), the driver traverses channels 0-5 +and may unintentionally modify their configuration if they are unused. + +This leads to issues such as setting the `is_multi_fifo` flag unexpectedly, +causing memcpy tests to fail when using the dmatest tool. + +Only affect edma memcpy test when the channel is fixed. + +Fixes: 72f5801a4e2b ("dmaengine: fsl-edma: integrate v3 support") +Signed-off-by: Joy Zou +Cc: stable@vger.kernel.org +Reviewed-by: Frank Li +Link: https://patch.msgid.link/20250917-b4-edma-chanconf-v1-1-886486e02e91@nxp.com +Signed-off-by: Vinod Koul +Signed-off-by: Greg Kroah-Hartman +--- + drivers/dma/fsl-edma-main.c | 26 +++++++++++--------------- + 1 file changed, 11 insertions(+), 15 deletions(-) + +--- a/drivers/dma/fsl-edma-main.c ++++ b/drivers/dma/fsl-edma-main.c +@@ -317,10 +317,8 @@ static struct dma_chan *fsl_edma3_xlate( + return NULL; + i = fsl_chan - fsl_edma->chans; + +- fsl_chan->priority = dma_spec->args[1]; +- fsl_chan->is_rxchan = dma_spec->args[2] & FSL_EDMA_RX; +- fsl_chan->is_remote = dma_spec->args[2] & FSL_EDMA_REMOTE; +- fsl_chan->is_multi_fifo = dma_spec->args[2] & FSL_EDMA_MULTI_FIFO; ++ if (!b_chmux && i != dma_spec->args[0]) ++ continue; + + if ((dma_spec->args[2] & FSL_EDMA_EVEN_CH) && (i & 0x1)) + continue; +@@ -328,17 +326,15 @@ static struct dma_chan *fsl_edma3_xlate( + if ((dma_spec->args[2] & FSL_EDMA_ODD_CH) && !(i & 0x1)) + continue; + +- if (!b_chmux && i == dma_spec->args[0]) { +- chan = dma_get_slave_channel(chan); +- chan->device->privatecnt++; +- return chan; +- } else if (b_chmux && !fsl_chan->srcid) { +- /* if controller support channel mux, choose a free channel */ +- chan = dma_get_slave_channel(chan); +- chan->device->privatecnt++; +- fsl_chan->srcid = dma_spec->args[0]; +- return chan; +- } ++ fsl_chan->srcid = dma_spec->args[0]; ++ fsl_chan->priority = dma_spec->args[1]; ++ fsl_chan->is_rxchan = dma_spec->args[2] & FSL_EDMA_RX; ++ fsl_chan->is_remote = dma_spec->args[2] & FSL_EDMA_REMOTE; ++ fsl_chan->is_multi_fifo = dma_spec->args[2] & FSL_EDMA_MULTI_FIFO; ++ ++ chan = dma_get_slave_channel(chan); ++ chan->device->privatecnt++; ++ return chan; + } + return NULL; + } diff --git a/queue-6.19/dmaengine-sh-rz-dmac-move-chctrl-updates-under-spinlock.patch b/queue-6.19/dmaengine-sh-rz-dmac-move-chctrl-updates-under-spinlock.patch new file mode 100644 index 0000000000..d564fdff83 --- /dev/null +++ b/queue-6.19/dmaengine-sh-rz-dmac-move-chctrl-updates-under-spinlock.patch @@ -0,0 +1,67 @@ +From 89a8567d84bde88cb7cdbbac2ab2299c4f991490 Mon Sep 17 00:00:00 2001 +From: Claudiu Beznea +Date: Mon, 16 Mar 2026 15:32:46 +0200 +Subject: dmaengine: sh: rz-dmac: Move CHCTRL updates under spinlock + +From: Claudiu Beznea + +commit 89a8567d84bde88cb7cdbbac2ab2299c4f991490 upstream. + +Both rz_dmac_disable_hw() and rz_dmac_irq_handle_channel() update the +CHCTRL register. To avoid concurrency issues when configuring +functionalities exposed by this registers, take the virtual channel lock. +All other CHCTRL updates were already protected by the same lock. + +Previously, rz_dmac_disable_hw() disabled and re-enabled local IRQs, before +accessing CHCTRL registers but this does not ensure race-free access. +Remove the local IRQ disable/enable code as well. + +Fixes: 5000d37042a6 ("dmaengine: sh: Add DMAC driver for RZ/G2L SoC") +Cc: stable@vger.kernel.org +Reviewed-by: Biju Das +Reviewed-by: Frank Li +Signed-off-by: Claudiu Beznea +Link: https://patch.msgid.link/20260316133252.240348-3-claudiu.beznea.uj@bp.renesas.com +Signed-off-by: Vinod Koul +Signed-off-by: Greg Kroah-Hartman +--- + drivers/dma/sh/rz-dmac.c | 9 ++++----- + 1 file changed, 4 insertions(+), 5 deletions(-) + +--- a/drivers/dma/sh/rz-dmac.c ++++ b/drivers/dma/sh/rz-dmac.c +@@ -298,13 +298,10 @@ static void rz_dmac_disable_hw(struct rz + { + struct dma_chan *chan = &channel->vc.chan; + struct rz_dmac *dmac = to_rz_dmac(chan->device); +- unsigned long flags; + + dev_dbg(dmac->dev, "%s channel %d\n", __func__, channel->index); + +- local_irq_save(flags); + rz_dmac_ch_writel(channel, CHCTRL_DEFAULT, CHCTRL, 1); +- local_irq_restore(flags); + } + + static void rz_dmac_set_dmars_register(struct rz_dmac *dmac, int nr, u32 dmars) +@@ -569,8 +566,8 @@ static int rz_dmac_terminate_all(struct + unsigned int i; + LIST_HEAD(head); + +- rz_dmac_disable_hw(channel); + spin_lock_irqsave(&channel->vc.lock, flags); ++ rz_dmac_disable_hw(channel); + for (i = 0; i < DMAC_NR_LMDESC; i++) + lmdesc[i].header = 0; + +@@ -707,7 +704,9 @@ static void rz_dmac_irq_handle_channel(s + if (chstat & CHSTAT_ER) { + dev_err(dmac->dev, "DMAC err CHSTAT_%d = %08X\n", + channel->index, chstat); +- rz_dmac_ch_writel(channel, CHCTRL_DEFAULT, CHCTRL, 1); ++ ++ scoped_guard(spinlock_irqsave, &channel->vc.lock) ++ rz_dmac_ch_writel(channel, CHCTRL_DEFAULT, CHCTRL, 1); + goto done; + } + diff --git a/queue-6.19/dmaengine-sh-rz-dmac-protect-the-driver-specific-lists.patch b/queue-6.19/dmaengine-sh-rz-dmac-protect-the-driver-specific-lists.patch new file mode 100644 index 0000000000..5365af94b9 --- /dev/null +++ b/queue-6.19/dmaengine-sh-rz-dmac-protect-the-driver-specific-lists.patch @@ -0,0 +1,126 @@ +From abb863e6213dc41a58ef8bb3289b7e77460dabf3 Mon Sep 17 00:00:00 2001 +From: Claudiu Beznea +Date: Mon, 16 Mar 2026 15:32:45 +0200 +Subject: dmaengine: sh: rz-dmac: Protect the driver specific lists + +From: Claudiu Beznea + +commit abb863e6213dc41a58ef8bb3289b7e77460dabf3 upstream. + +The driver lists (ld_free, ld_queue) are used in +rz_dmac_free_chan_resources(), rz_dmac_terminate_all(), +rz_dmac_issue_pending(), and rz_dmac_irq_handler_thread(), all under +the virtual channel lock. Take the same lock in rz_dmac_prep_slave_sg() +and rz_dmac_prep_dma_memcpy() as well to avoid concurrency issues, since +these functions also check whether the lists are empty and update or +remove list entries. + +Fixes: 5000d37042a6 ("dmaengine: sh: Add DMAC driver for RZ/G2L SoC") +Cc: stable@vger.kernel.org +Reviewed-by: Frank Li +Signed-off-by: Claudiu Beznea +Link: https://patch.msgid.link/20260316133252.240348-2-claudiu.beznea.uj@bp.renesas.com +Signed-off-by: Vinod Koul +Signed-off-by: Greg Kroah-Hartman +--- + drivers/dma/sh/rz-dmac.c | 63 ++++++++++++++++++++++++++--------------------- + 1 file changed, 35 insertions(+), 28 deletions(-) + +--- a/drivers/dma/sh/rz-dmac.c ++++ b/drivers/dma/sh/rz-dmac.c +@@ -10,6 +10,7 @@ + */ + + #include ++#include + #include + #include + #include +@@ -448,6 +449,7 @@ static int rz_dmac_alloc_chan_resources( + if (!desc) + break; + ++ /* No need to lock. This is called only for the 1st client. */ + list_add_tail(&desc->node, &channel->ld_free); + channel->descs_allocated++; + } +@@ -503,18 +505,21 @@ rz_dmac_prep_dma_memcpy(struct dma_chan + dev_dbg(dmac->dev, "%s channel: %d src=0x%pad dst=0x%pad len=%zu\n", + __func__, channel->index, &src, &dest, len); + +- if (list_empty(&channel->ld_free)) +- return NULL; ++ scoped_guard(spinlock_irqsave, &channel->vc.lock) { ++ if (list_empty(&channel->ld_free)) ++ return NULL; ++ ++ desc = list_first_entry(&channel->ld_free, struct rz_dmac_desc, node); ++ ++ desc->type = RZ_DMAC_DESC_MEMCPY; ++ desc->src = src; ++ desc->dest = dest; ++ desc->len = len; ++ desc->direction = DMA_MEM_TO_MEM; + +- desc = list_first_entry(&channel->ld_free, struct rz_dmac_desc, node); +- +- desc->type = RZ_DMAC_DESC_MEMCPY; +- desc->src = src; +- desc->dest = dest; +- desc->len = len; +- desc->direction = DMA_MEM_TO_MEM; ++ list_move_tail(channel->ld_free.next, &channel->ld_queue); ++ } + +- list_move_tail(channel->ld_free.next, &channel->ld_queue); + return vchan_tx_prep(&channel->vc, &desc->vd, flags); + } + +@@ -530,27 +535,29 @@ rz_dmac_prep_slave_sg(struct dma_chan *c + int dma_length = 0; + int i = 0; + +- if (list_empty(&channel->ld_free)) +- return NULL; +- +- desc = list_first_entry(&channel->ld_free, struct rz_dmac_desc, node); ++ scoped_guard(spinlock_irqsave, &channel->vc.lock) { ++ if (list_empty(&channel->ld_free)) ++ return NULL; ++ ++ desc = list_first_entry(&channel->ld_free, struct rz_dmac_desc, node); ++ ++ for_each_sg(sgl, sg, sg_len, i) ++ dma_length += sg_dma_len(sg); ++ ++ desc->type = RZ_DMAC_DESC_SLAVE_SG; ++ desc->sg = sgl; ++ desc->sgcount = sg_len; ++ desc->len = dma_length; ++ desc->direction = direction; ++ ++ if (direction == DMA_DEV_TO_MEM) ++ desc->src = channel->src_per_address; ++ else ++ desc->dest = channel->dst_per_address; + +- for_each_sg(sgl, sg, sg_len, i) { +- dma_length += sg_dma_len(sg); ++ list_move_tail(channel->ld_free.next, &channel->ld_queue); + } + +- desc->type = RZ_DMAC_DESC_SLAVE_SG; +- desc->sg = sgl; +- desc->sgcount = sg_len; +- desc->len = dma_length; +- desc->direction = direction; +- +- if (direction == DMA_DEV_TO_MEM) +- desc->src = channel->src_per_address; +- else +- desc->dest = channel->dst_per_address; +- +- list_move_tail(channel->ld_free.next, &channel->ld_queue); + return vchan_tx_prep(&channel->vc, &desc->vd, flags); + } + diff --git a/queue-6.19/drm-amd-display-check-if-ext_caps-is-valid-in-bl-setup.patch b/queue-6.19/drm-amd-display-check-if-ext_caps-is-valid-in-bl-setup.patch new file mode 100644 index 0000000000..d1b01542e1 --- /dev/null +++ b/queue-6.19/drm-amd-display-check-if-ext_caps-is-valid-in-bl-setup.patch @@ -0,0 +1,35 @@ +From 9da4f9964abcaeb6e19797d5e3b10faad338a786 Mon Sep 17 00:00:00 2001 +From: Alex Deucher +Date: Fri, 20 Mar 2026 12:33:48 -0400 +Subject: drm/amd/display: check if ext_caps is valid in BL setup + +From: Alex Deucher + +commit 9da4f9964abcaeb6e19797d5e3b10faad338a786 upstream. + +LVDS connectors don't have extended backlight caps so check +if the pointer is valid before accessing it. + +Closes: https://gitlab.freedesktop.org/drm/amd/-/issues/5012 +Fixes: 1454642960b0 ("drm/amd: Re-introduce property to control adaptive backlight modulation") +Cc: Mario Limonciello +Reviewed-by: Mario Limonciello (AMD) +Signed-off-by: Alex Deucher +(cherry picked from commit 3f797396d7f4eb9bb6eded184bbc6f033628a6f6) +Cc: stable@vger.kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c ++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +@@ -5406,7 +5406,7 @@ static void setup_backlight_device(struc + caps = &dm->backlight_caps[aconnector->bl_idx]; + + /* Only offer ABM property when non-OLED and user didn't turn off by module parameter */ +- if (!caps->ext_caps->bits.oled && amdgpu_dm_abm_level < 0) ++ if (caps->ext_caps && !caps->ext_caps->bits.oled && amdgpu_dm_abm_level < 0) + drm_object_attach_property(&aconnector->base.base, + dm->adev->mode_info.abm_level_property, + ABM_SYSFS_CONTROL); diff --git a/queue-6.19/drm-amd-display-fix-dce-lvds-handling.patch b/queue-6.19/drm-amd-display-fix-dce-lvds-handling.patch new file mode 100644 index 0000000000..a122a8f189 --- /dev/null +++ b/queue-6.19/drm-amd-display-fix-dce-lvds-handling.patch @@ -0,0 +1,165 @@ +From 90d239cc53723c1a3f89ce08eac17bf3a9e9f2d4 Mon Sep 17 00:00:00 2001 +From: Alex Deucher +Date: Thu, 26 Feb 2026 17:12:08 -0500 +Subject: drm/amd/display: Fix DCE LVDS handling + +From: Alex Deucher + +commit 90d239cc53723c1a3f89ce08eac17bf3a9e9f2d4 upstream. + +LVDS does not use an HPD pin so it may be invalid. Handle +this case correctly in link encoder creation. + +Fixes: 7c8fb3b8e9ba ("drm/amd/display: Add hpd_source index check for DCE60/80/100/110/112/120 link encoders") +Closes: https://gitlab.freedesktop.org/drm/amd/-/issues/5012 +Cc: Srinivasan Shanmugam +Cc: Roman Li +Reviewed-by: Roman Li +Reviewed-by: Srinivasan Shanmugam +Signed-off-by: Alex Deucher +(cherry picked from commit 3b5620f7ee688177fcf65cf61588c5435bce1872) +Cc: stable@vger.kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/amd/display/dc/resource/dce100/dce100_resource.c | 6 +--- + drivers/gpu/drm/amd/display/dc/resource/dce110/dce110_resource.c | 5 ++- + drivers/gpu/drm/amd/display/dc/resource/dce112/dce112_resource.c | 5 ++- + drivers/gpu/drm/amd/display/dc/resource/dce120/dce120_resource.c | 5 ++- + drivers/gpu/drm/amd/display/dc/resource/dce60/dce60_resource.c | 14 ++++------ + drivers/gpu/drm/amd/display/dc/resource/dce80/dce80_resource.c | 6 +--- + 6 files changed, 19 insertions(+), 22 deletions(-) + +--- a/drivers/gpu/drm/amd/display/dc/resource/dce100/dce100_resource.c ++++ b/drivers/gpu/drm/amd/display/dc/resource/dce100/dce100_resource.c +@@ -651,9 +651,6 @@ static struct link_encoder *dce100_link_ + return &enc110->base; + } + +- if (enc_init_data->hpd_source >= ARRAY_SIZE(link_enc_hpd_regs)) +- return NULL; +- + link_regs_id = + map_transmitter_id_to_phy_instance(enc_init_data->transmitter); + +@@ -662,7 +659,8 @@ static struct link_encoder *dce100_link_ + &link_enc_feature, + &link_enc_regs[link_regs_id], + &link_enc_aux_regs[enc_init_data->channel - 1], +- &link_enc_hpd_regs[enc_init_data->hpd_source]); ++ enc_init_data->hpd_source >= ARRAY_SIZE(link_enc_hpd_regs) ? ++ NULL : &link_enc_hpd_regs[enc_init_data->hpd_source]); + return &enc110->base; + } + +--- a/drivers/gpu/drm/amd/display/dc/resource/dce110/dce110_resource.c ++++ b/drivers/gpu/drm/amd/display/dc/resource/dce110/dce110_resource.c +@@ -672,7 +672,7 @@ static struct link_encoder *dce110_link_ + kzalloc(sizeof(struct dce110_link_encoder), GFP_KERNEL); + int link_regs_id; + +- if (!enc110 || enc_init_data->hpd_source >= ARRAY_SIZE(link_enc_hpd_regs)) ++ if (!enc110) + return NULL; + + link_regs_id = +@@ -683,7 +683,8 @@ static struct link_encoder *dce110_link_ + &link_enc_feature, + &link_enc_regs[link_regs_id], + &link_enc_aux_regs[enc_init_data->channel - 1], +- &link_enc_hpd_regs[enc_init_data->hpd_source]); ++ enc_init_data->hpd_source >= ARRAY_SIZE(link_enc_hpd_regs) ? ++ NULL : &link_enc_hpd_regs[enc_init_data->hpd_source]); + return &enc110->base; + } + +--- a/drivers/gpu/drm/amd/display/dc/resource/dce112/dce112_resource.c ++++ b/drivers/gpu/drm/amd/display/dc/resource/dce112/dce112_resource.c +@@ -633,7 +633,7 @@ static struct link_encoder *dce112_link_ + kzalloc(sizeof(struct dce110_link_encoder), GFP_KERNEL); + int link_regs_id; + +- if (!enc110 || enc_init_data->hpd_source >= ARRAY_SIZE(link_enc_hpd_regs)) ++ if (!enc110) + return NULL; + + link_regs_id = +@@ -644,7 +644,8 @@ static struct link_encoder *dce112_link_ + &link_enc_feature, + &link_enc_regs[link_regs_id], + &link_enc_aux_regs[enc_init_data->channel - 1], +- &link_enc_hpd_regs[enc_init_data->hpd_source]); ++ enc_init_data->hpd_source >= ARRAY_SIZE(link_enc_hpd_regs) ? ++ NULL : &link_enc_hpd_regs[enc_init_data->hpd_source]); + return &enc110->base; + } + +--- a/drivers/gpu/drm/amd/display/dc/resource/dce120/dce120_resource.c ++++ b/drivers/gpu/drm/amd/display/dc/resource/dce120/dce120_resource.c +@@ -717,7 +717,7 @@ static struct link_encoder *dce120_link_ + kzalloc(sizeof(struct dce110_link_encoder), GFP_KERNEL); + int link_regs_id; + +- if (!enc110 || enc_init_data->hpd_source >= ARRAY_SIZE(link_enc_hpd_regs)) ++ if (!enc110) + return NULL; + + link_regs_id = +@@ -728,7 +728,8 @@ static struct link_encoder *dce120_link_ + &link_enc_feature, + &link_enc_regs[link_regs_id], + &link_enc_aux_regs[enc_init_data->channel - 1], +- &link_enc_hpd_regs[enc_init_data->hpd_source]); ++ enc_init_data->hpd_source >= ARRAY_SIZE(link_enc_hpd_regs) ? ++ NULL : &link_enc_hpd_regs[enc_init_data->hpd_source]); + + return &enc110->base; + } +--- a/drivers/gpu/drm/amd/display/dc/resource/dce60/dce60_resource.c ++++ b/drivers/gpu/drm/amd/display/dc/resource/dce60/dce60_resource.c +@@ -747,18 +747,16 @@ static struct link_encoder *dce60_link_e + return &enc110->base; + } + +- if (enc_init_data->hpd_source >= ARRAY_SIZE(link_enc_hpd_regs)) +- return NULL; +- + link_regs_id = + map_transmitter_id_to_phy_instance(enc_init_data->transmitter); + + dce60_link_encoder_construct(enc110, +- enc_init_data, +- &link_enc_feature, +- &link_enc_regs[link_regs_id], +- &link_enc_aux_regs[enc_init_data->channel - 1], +- &link_enc_hpd_regs[enc_init_data->hpd_source]); ++ enc_init_data, ++ &link_enc_feature, ++ &link_enc_regs[link_regs_id], ++ &link_enc_aux_regs[enc_init_data->channel - 1], ++ enc_init_data->hpd_source >= ARRAY_SIZE(link_enc_hpd_regs) ? ++ NULL : &link_enc_hpd_regs[enc_init_data->hpd_source]); + return &enc110->base; + } + +--- a/drivers/gpu/drm/amd/display/dc/resource/dce80/dce80_resource.c ++++ b/drivers/gpu/drm/amd/display/dc/resource/dce80/dce80_resource.c +@@ -753,9 +753,6 @@ static struct link_encoder *dce80_link_e + return &enc110->base; + } + +- if (enc_init_data->hpd_source >= ARRAY_SIZE(link_enc_hpd_regs)) +- return NULL; +- + link_regs_id = + map_transmitter_id_to_phy_instance(enc_init_data->transmitter); + +@@ -764,7 +761,8 @@ static struct link_encoder *dce80_link_e + &link_enc_feature, + &link_enc_regs[link_regs_id], + &link_enc_aux_regs[enc_init_data->channel - 1], +- &link_enc_hpd_regs[enc_init_data->hpd_source]); ++ enc_init_data->hpd_source >= ARRAY_SIZE(link_enc_hpd_regs) ? ++ NULL : &link_enc_hpd_regs[enc_init_data->hpd_source]); + return &enc110->base; + } + diff --git a/queue-6.19/drm-amd-display-fix-drm_edid-leak-in-amdgpu_dm.patch b/queue-6.19/drm-amd-display-fix-drm_edid-leak-in-amdgpu_dm.patch new file mode 100644 index 0000000000..7f47cd810f --- /dev/null +++ b/queue-6.19/drm-amd-display-fix-drm_edid-leak-in-amdgpu_dm.patch @@ -0,0 +1,40 @@ +From 37c2caa167b0b8aca4f74c32404c5288b876a2a3 Mon Sep 17 00:00:00 2001 +From: Alex Hung +Date: Mon, 9 Mar 2026 11:16:08 -0600 +Subject: drm/amd/display: Fix drm_edid leak in amdgpu_dm + +From: Alex Hung + +commit 37c2caa167b0b8aca4f74c32404c5288b876a2a3 upstream. + +[WHAT] +When a sink is connected, aconnector->drm_edid was overwritten without +freeing the previous allocation, causing a memory leak on resume. + +[HOW] +Free the previous drm_edid before updating it. + +Reviewed-by: Roman Li +Signed-off-by: Alex Hung +Signed-off-by: Chuanyu Tseng +Signed-off-by: Alex Deucher +(cherry picked from commit 52024a94e7111366141cfc5d888b2ef011f879e5) +Cc: stable@vger.kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c ++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +@@ -3891,8 +3891,9 @@ void amdgpu_dm_update_connector_after_de + + aconnector->dc_sink = sink; + dc_sink_retain(aconnector->dc_sink); ++ drm_edid_free(aconnector->drm_edid); ++ aconnector->drm_edid = NULL; + if (sink->dc_edid.length == 0) { +- aconnector->drm_edid = NULL; + hdmi_cec_unset_edid(aconnector); + if (aconnector->dc_link->aux_mode) { + drm_dp_cec_unset_edid(&aconnector->dm_dp_aux.aux); diff --git a/queue-6.19/drm-amd-pm-return-eopnotsupp-for-unsupported-od_mclk-on-smu_v13_0_6.patch b/queue-6.19/drm-amd-pm-return-eopnotsupp-for-unsupported-od_mclk-on-smu_v13_0_6.patch new file mode 100644 index 0000000000..8093175d19 --- /dev/null +++ b/queue-6.19/drm-amd-pm-return-eopnotsupp-for-unsupported-od_mclk-on-smu_v13_0_6.patch @@ -0,0 +1,35 @@ +From 2f0e491faee43181b6a86e90f34016b256042fe1 Mon Sep 17 00:00:00 2001 +From: Asad Kamal +Date: Wed, 18 Mar 2026 13:52:57 +0800 +Subject: drm/amd/pm: Return -EOPNOTSUPP for unsupported OD_MCLK on smu_v13_0_6 + +From: Asad Kamal + +commit 2f0e491faee43181b6a86e90f34016b256042fe1 upstream. + +When SET_UCLK_MAX capability is absent, return -EOPNOTSUPP from +smu_v13_0_6_emit_clk_levels() for OD_MCLK instead of 0. This makes +unsupported OD_MCLK reporting consistent with other clock types +and allows callers to skip the entry cleanly. + +Signed-off-by: Asad Kamal +Reviewed-by: Lijo Lazar +Signed-off-by: Alex Deucher +(cherry picked from commit d82e0a72d9189e8acd353988e1a57f85ce479e37) +Cc: stable@vger.kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c ++++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c +@@ -1520,7 +1520,7 @@ static int smu_v13_0_6_print_clk_levels( + + case SMU_OD_MCLK: + if (!smu_v13_0_6_cap_supported(smu, SMU_CAP(SET_UCLK_MAX))) +- return 0; ++ return -EOPNOTSUPP; + + size += sysfs_emit_at(buf, size, "%s:\n", "OD_MCLK"); + size += sysfs_emit_at(buf, size, "0: %uMhz\n1: %uMhz\n", diff --git a/queue-6.19/drm-amdgpu-fix-strsep-corrupting-lockup_timeout-on-multi-gpu-v3.patch b/queue-6.19/drm-amdgpu-fix-strsep-corrupting-lockup_timeout-on-multi-gpu-v3.patch new file mode 100644 index 0000000000..e37a97bbe6 --- /dev/null +++ b/queue-6.19/drm-amdgpu-fix-strsep-corrupting-lockup_timeout-on-multi-gpu-v3.patch @@ -0,0 +1,79 @@ +From 2d300ebfc411205fa31ba7741c5821d381912381 Mon Sep 17 00:00:00 2001 +From: Ruijing Dong +Date: Tue, 17 Mar 2026 13:54:11 -0400 +Subject: drm/amdgpu: fix strsep() corrupting lockup_timeout on multi-GPU (v3) +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Ruijing Dong + +commit 2d300ebfc411205fa31ba7741c5821d381912381 upstream. + +amdgpu_device_get_job_timeout_settings() passes a pointer directly +to the global amdgpu_lockup_timeout[] buffer into strsep(). +strsep() destructively replaces delimiter characters with '\0' +in-place. + +On multi-GPU systems, this function is called once per device. +When a multi-value setting like "0,0,0,-1" is used, the first +GPU's call transforms the global buffer into "0\00\00\0-1". The +second GPU then sees only "0" (terminated at the first '\0'), +parses a single value, hits the single-value fallthrough +(index == 1), and applies timeout=0 to all rings — causing +immediate false job timeouts. + +Fix this by copying into a stack-local array before calling +strsep(), so the global module parameter buffer remains intact +across calls. The buffer is AMDGPU_MAX_TIMEOUT_PARAM_LENGTH +(256) bytes, which is safe for the stack. + +v2: wrap commit message to 72 columns, add Assisted-by tag. +v3: use stack array with strscpy() instead of kstrdup()/kfree() + to avoid unnecessary heap allocation (Christian). + +This patch was developed with assistance from Claude (claude-opus-4-6). + +Assisted-by: Claude:claude-opus-4-6 +Reviewed-by: Christian König +Reviewed-by: Alex Deucher +Signed-off-by: Ruijing Dong +Signed-off-by: Alex Deucher +(cherry picked from commit 94d79f51efecb74be1d88dde66bdc8bfcca17935) +Cc: stable@vger.kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 13 +++++++++++-- + 1 file changed, 11 insertions(+), 2 deletions(-) + +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +@@ -4361,7 +4361,8 @@ fail: + + static int amdgpu_device_get_job_timeout_settings(struct amdgpu_device *adev) + { +- char *input = amdgpu_lockup_timeout; ++ char buf[AMDGPU_MAX_TIMEOUT_PARAM_LENGTH]; ++ char *input = buf; + char *timeout_setting = NULL; + int index = 0; + long timeout; +@@ -4371,9 +4372,17 @@ static int amdgpu_device_get_job_timeout + adev->gfx_timeout = adev->compute_timeout = adev->sdma_timeout = + adev->video_timeout = msecs_to_jiffies(2000); + +- if (!strnlen(input, AMDGPU_MAX_TIMEOUT_PARAM_LENGTH)) ++ if (!strnlen(amdgpu_lockup_timeout, AMDGPU_MAX_TIMEOUT_PARAM_LENGTH)) + return 0; + ++ /* ++ * strsep() destructively modifies its input by replacing delimiters ++ * with '\0'. Use a stack copy so the global module parameter buffer ++ * remains intact for multi-GPU systems where this function is called ++ * once per device. ++ */ ++ strscpy(buf, amdgpu_lockup_timeout, sizeof(buf)); ++ + while ((timeout_setting = strsep(&input, ",")) && + strnlen(timeout_setting, AMDGPU_MAX_TIMEOUT_PARAM_LENGTH)) { + ret = kstrtol(timeout_setting, 0, &timeout); diff --git a/queue-6.19/drm-amdgpu-prevent-immediate-pasid-reuse-case.patch b/queue-6.19/drm-amdgpu-prevent-immediate-pasid-reuse-case.patch new file mode 100644 index 0000000000..396c4b24ad --- /dev/null +++ b/queue-6.19/drm-amdgpu-prevent-immediate-pasid-reuse-case.patch @@ -0,0 +1,132 @@ +From 14b81abe7bdc25f8097906fc2f91276ffedb2d26 Mon Sep 17 00:00:00 2001 +From: Eric Huang +Date: Mon, 16 Mar 2026 11:01:30 -0400 +Subject: drm/amdgpu: prevent immediate PASID reuse case +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Eric Huang + +commit 14b81abe7bdc25f8097906fc2f91276ffedb2d26 upstream. + +PASID resue could cause interrupt issue when process +immediately runs into hw state left by previous +process exited with the same PASID, it's possible that +page faults are still pending in the IH ring buffer when +the process exits and frees up its PASID. To prevent the +case, it uses idr cyclic allocator same as kernel pid's. + +Signed-off-by: Eric Huang +Reviewed-by: Christian König +Signed-off-by: Alex Deucher +(cherry picked from commit 8f1de51f49be692de137c8525106e0fce2d1912d) +Cc: stable@vger.kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c | 45 ++++++++++++++++++++++---------- + drivers/gpu/drm/amd/amdgpu/amdgpu_ids.h | 1 + drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 1 + 3 files changed, 34 insertions(+), 13 deletions(-) + +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c +@@ -35,10 +35,13 @@ + * PASIDs are global address space identifiers that can be shared + * between the GPU, an IOMMU and the driver. VMs on different devices + * may use the same PASID if they share the same address +- * space. Therefore PASIDs are allocated using a global IDA. VMs are +- * looked up from the PASID per amdgpu_device. ++ * space. Therefore PASIDs are allocated using IDR cyclic allocator ++ * (similar to kernel PID allocation) which naturally delays reuse. ++ * VMs are looked up from the PASID per amdgpu_device. + */ +-static DEFINE_IDA(amdgpu_pasid_ida); ++ ++static DEFINE_IDR(amdgpu_pasid_idr); ++static DEFINE_SPINLOCK(amdgpu_pasid_idr_lock); + + /* Helper to free pasid from a fence callback */ + struct amdgpu_pasid_cb { +@@ -50,8 +53,8 @@ struct amdgpu_pasid_cb { + * amdgpu_pasid_alloc - Allocate a PASID + * @bits: Maximum width of the PASID in bits, must be at least 1 + * +- * Allocates a PASID of the given width while keeping smaller PASIDs +- * available if possible. ++ * Uses kernel's IDR cyclic allocator (same as PID allocation). ++ * Allocates sequentially with automatic wrap-around. + * + * Returns a positive integer on success. Returns %-EINVAL if bits==0. + * Returns %-ENOSPC if no PASID was available. Returns %-ENOMEM on +@@ -59,14 +62,15 @@ struct amdgpu_pasid_cb { + */ + int amdgpu_pasid_alloc(unsigned int bits) + { +- int pasid = -EINVAL; ++ int pasid; + +- for (bits = min(bits, 31U); bits > 0; bits--) { +- pasid = ida_alloc_range(&amdgpu_pasid_ida, 1U << (bits - 1), +- (1U << bits) - 1, GFP_KERNEL); +- if (pasid != -ENOSPC) +- break; +- } ++ if (bits == 0) ++ return -EINVAL; ++ ++ spin_lock(&amdgpu_pasid_idr_lock); ++ pasid = idr_alloc_cyclic(&amdgpu_pasid_idr, NULL, 1, ++ 1U << bits, GFP_KERNEL); ++ spin_unlock(&amdgpu_pasid_idr_lock); + + if (pasid >= 0) + trace_amdgpu_pasid_allocated(pasid); +@@ -81,7 +85,10 @@ int amdgpu_pasid_alloc(unsigned int bits + void amdgpu_pasid_free(u32 pasid) + { + trace_amdgpu_pasid_freed(pasid); +- ida_free(&amdgpu_pasid_ida, pasid); ++ ++ spin_lock(&amdgpu_pasid_idr_lock); ++ idr_remove(&amdgpu_pasid_idr, pasid); ++ spin_unlock(&amdgpu_pasid_idr_lock); + } + + static void amdgpu_pasid_free_cb(struct dma_fence *fence, +@@ -616,3 +623,15 @@ void amdgpu_vmid_mgr_fini(struct amdgpu_ + } + } + } ++ ++/** ++ * amdgpu_pasid_mgr_cleanup - cleanup PASID manager ++ * ++ * Cleanup the IDR allocator. ++ */ ++void amdgpu_pasid_mgr_cleanup(void) ++{ ++ spin_lock(&amdgpu_pasid_idr_lock); ++ idr_destroy(&amdgpu_pasid_idr); ++ spin_unlock(&amdgpu_pasid_idr_lock); ++} +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.h ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.h +@@ -74,6 +74,7 @@ int amdgpu_pasid_alloc(unsigned int bits + void amdgpu_pasid_free(u32 pasid); + void amdgpu_pasid_free_delayed(struct dma_resv *resv, + u32 pasid); ++void amdgpu_pasid_mgr_cleanup(void); + + bool amdgpu_vmid_had_gpu_reset(struct amdgpu_device *adev, + struct amdgpu_vmid *id); +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +@@ -2898,6 +2898,7 @@ void amdgpu_vm_manager_fini(struct amdgp + xa_destroy(&adev->vm_manager.pasids); + + amdgpu_vmid_mgr_fini(adev); ++ amdgpu_pasid_mgr_cleanup(); + } + + /** diff --git a/queue-6.19/drm-i915-dp_tunnel-fix-error-handling-when-clearing-stream-bw-in-atomic-state.patch b/queue-6.19/drm-i915-dp_tunnel-fix-error-handling-when-clearing-stream-bw-in-atomic-state.patch new file mode 100644 index 0000000000..e4946db4aa --- /dev/null +++ b/queue-6.19/drm-i915-dp_tunnel-fix-error-handling-when-clearing-stream-bw-in-atomic-state.patch @@ -0,0 +1,131 @@ +From 77fcf58df15edcf3f5b5421f24814fb72796def9 Mon Sep 17 00:00:00 2001 +From: Imre Deak +Date: Fri, 20 Mar 2026 11:29:00 +0200 +Subject: drm/i915/dp_tunnel: Fix error handling when clearing stream BW in atomic state +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Imre Deak + +commit 77fcf58df15edcf3f5b5421f24814fb72796def9 upstream. + +Clearing the DP tunnel stream BW in the atomic state involves getting +the tunnel group state, which can fail. Handle the error accordingly. + +This fixes at least one issue where drm_dp_tunnel_atomic_set_stream_bw() +failed to get the tunnel group state returning -EDEADLK, which wasn't +handled. This lead to the ctx->contended warn later in modeset_lock() +while taking a WW mutex for another object in the same atomic state, and +thus within the same already contended WW context. + +Moving intel_crtc_state_alloc() later would avoid freeing saved_state on +the error path; this stable patch leaves that simplification for a +follow-up. + +Cc: Uma Shankar +Cc: Ville Syrjälä +Cc: # v6.9+ +Fixes: a4efae87ecb2 ("drm/i915/dp: Compute DP tunnel BW during encoder state computation") +Closes: https://gitlab.freedesktop.org/drm/xe/kernel/-/issues/7617 +Reviewed-by: Michał Grzelak +Reviewed-by: Uma Shankar +Signed-off-by: Imre Deak +Link: https://patch.msgid.link/20260320092900.13210-1-imre.deak@intel.com +(cherry picked from commit fb69d0076e687421188bc8103ab0e8e5825b1df1) +Signed-off-by: Joonas Lahtinen +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/i915/display/intel_display.c | 8 +++++++- + drivers/gpu/drm/i915/display/intel_dp_tunnel.c | 20 ++++++++++++++------ + drivers/gpu/drm/i915/display/intel_dp_tunnel.h | 11 +++++++---- + 3 files changed, 28 insertions(+), 11 deletions(-) + +--- a/drivers/gpu/drm/i915/display/intel_display.c ++++ b/drivers/gpu/drm/i915/display/intel_display.c +@@ -4578,6 +4578,7 @@ intel_crtc_prepare_cleared_state(struct + struct intel_crtc_state *crtc_state = + intel_atomic_get_new_crtc_state(state, crtc); + struct intel_crtc_state *saved_state; ++ int err; + + saved_state = intel_crtc_state_alloc(crtc); + if (!saved_state) +@@ -4586,7 +4587,12 @@ intel_crtc_prepare_cleared_state(struct + /* free the old crtc_state->hw members */ + intel_crtc_free_hw_state(crtc_state); + +- intel_dp_tunnel_atomic_clear_stream_bw(state, crtc_state); ++ err = intel_dp_tunnel_atomic_clear_stream_bw(state, crtc_state); ++ if (err) { ++ kfree(saved_state); ++ ++ return err; ++ } + + /* FIXME: before the switch to atomic started, a new pipe_config was + * kzalloc'd. Code that depends on any field being zero should be +--- a/drivers/gpu/drm/i915/display/intel_dp_tunnel.c ++++ b/drivers/gpu/drm/i915/display/intel_dp_tunnel.c +@@ -622,19 +622,27 @@ int intel_dp_tunnel_atomic_compute_strea + * + * Clear any DP tunnel stream BW requirement set by + * intel_dp_tunnel_atomic_compute_stream_bw(). ++ * ++ * Returns 0 in case of success, a negative error code otherwise. + */ +-void intel_dp_tunnel_atomic_clear_stream_bw(struct intel_atomic_state *state, +- struct intel_crtc_state *crtc_state) ++int intel_dp_tunnel_atomic_clear_stream_bw(struct intel_atomic_state *state, ++ struct intel_crtc_state *crtc_state) + { + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); ++ int err; + + if (!crtc_state->dp_tunnel_ref.tunnel) +- return; ++ return 0; ++ ++ err = drm_dp_tunnel_atomic_set_stream_bw(&state->base, ++ crtc_state->dp_tunnel_ref.tunnel, ++ crtc->pipe, 0); ++ if (err) ++ return err; + +- drm_dp_tunnel_atomic_set_stream_bw(&state->base, +- crtc_state->dp_tunnel_ref.tunnel, +- crtc->pipe, 0); + drm_dp_tunnel_ref_put(&crtc_state->dp_tunnel_ref); ++ ++ return 0; + } + + /** +--- a/drivers/gpu/drm/i915/display/intel_dp_tunnel.h ++++ b/drivers/gpu/drm/i915/display/intel_dp_tunnel.h +@@ -40,8 +40,8 @@ int intel_dp_tunnel_atomic_compute_strea + struct intel_dp *intel_dp, + const struct intel_connector *connector, + struct intel_crtc_state *crtc_state); +-void intel_dp_tunnel_atomic_clear_stream_bw(struct intel_atomic_state *state, +- struct intel_crtc_state *crtc_state); ++int intel_dp_tunnel_atomic_clear_stream_bw(struct intel_atomic_state *state, ++ struct intel_crtc_state *crtc_state); + + int intel_dp_tunnel_atomic_add_state_for_crtc(struct intel_atomic_state *state, + struct intel_crtc *crtc); +@@ -88,9 +88,12 @@ intel_dp_tunnel_atomic_compute_stream_bw + return 0; + } + +-static inline void ++static inline int + intel_dp_tunnel_atomic_clear_stream_bw(struct intel_atomic_state *state, +- struct intel_crtc_state *crtc_state) {} ++ struct intel_crtc_state *crtc_state) ++{ ++ return 0; ++} + + static inline int + intel_dp_tunnel_atomic_add_state_for_crtc(struct intel_atomic_state *state, diff --git a/queue-6.19/drm-i915-order-op-vs.-timeout-correctly-in-__wait_for.patch b/queue-6.19/drm-i915-order-op-vs.-timeout-correctly-in-__wait_for.patch new file mode 100644 index 0000000000..c17a0139ae --- /dev/null +++ b/queue-6.19/drm-i915-order-op-vs.-timeout-correctly-in-__wait_for.patch @@ -0,0 +1,53 @@ +From 6ad2a661ff0d3d94884947d2a593311ba46d34c2 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= +Date: Fri, 13 Mar 2026 13:07:40 +0200 +Subject: drm/i915: Order OP vs. timeout correctly in __wait_for() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Ville Syrjälä + +commit 6ad2a661ff0d3d94884947d2a593311ba46d34c2 upstream. + +Put the barrier() before the OP so that anything we read out in +OP and check in COND will actually be read out after the timeout +has been evaluated. + +Currently the only place where we use OP is __intel_wait_for_register(), +but the use there is precisely susceptible to this reordering, assuming +the ktime_*() stuff itself doesn't act as a sufficient barrier: + +__intel_wait_for_register(...) +{ + ... + ret = __wait_for(reg_value = intel_uncore_read_notrace(...), + (reg_value & mask) == value, ...); + ... +} + +Cc: stable@vger.kernel.org +Fixes: 1c3c1dc66a96 ("drm/i915: Add compiler barrier to wait_for") +Signed-off-by: Ville Syrjälä +Link: https://patch.msgid.link/20260313110740.24620-1-ville.syrjala@linux.intel.com +Reviewed-by: Jani Nikula +(cherry picked from commit a464bace0482aa9a83e9aa7beefbaf44cd58e6cf) +Signed-off-by: Joonas Lahtinen +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/i915/i915_wait_util.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/gpu/drm/i915/i915_wait_util.h ++++ b/drivers/gpu/drm/i915/i915_wait_util.h +@@ -25,9 +25,9 @@ + might_sleep(); \ + for (;;) { \ + const bool expired__ = ktime_after(ktime_get_raw(), end__); \ +- OP; \ + /* Guarantee COND check prior to timeout */ \ + barrier(); \ ++ OP; \ + if (COND) { \ + ret__ = 0; \ + break; \ diff --git a/queue-6.19/drm-i915-unlink-nv12-planes-earlier.patch b/queue-6.19/drm-i915-unlink-nv12-planes-earlier.patch new file mode 100644 index 0000000000..7050191d41 --- /dev/null +++ b/queue-6.19/drm-i915-unlink-nv12-planes-earlier.patch @@ -0,0 +1,85 @@ +From bfa71b7a9dc6b5b8af157686e03308291141d00c Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= +Date: Mon, 16 Mar 2026 18:39:51 +0200 +Subject: drm/i915: Unlink NV12 planes earlier +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Ville Syrjälä + +commit bfa71b7a9dc6b5b8af157686e03308291141d00c upstream. + +unlink_nv12_plane() will clobber parts of the plane state +potentially already set up by plane_atomic_check(), so we +must make sure not to call the two in the wrong order. +The problem happens when a plane previously selected as +a Y plane is now configured as a normal plane by user space. +plane_atomic_check() will first compute the proper plane +state based on the userspace request, and unlink_nv12_plane() +later clears some of the state. + +This used to work on account of unlink_nv12_plane() skipping +the state clearing based on the plane visibility. But I removed +that check, thinking it was an impossible situation. Now when +that situation happens unlink_nv12_plane() will just WARN +and proceed to clobber the state. + +Rather than reverting to the old way of doing things, I think +it's more clear if we unlink the NV12 planes before we even +compute the new plane state. + +Cc: stable@vger.kernel.org +Reported-by: Khaled Almahallawy +Closes: https://lore.kernel.org/intel-gfx/20260212004852.1920270-1-khaled.almahallawy@intel.com/ +Tested-by: Khaled Almahallawy +Fixes: 6a01df2f1b2a ("drm/i915: Remove pointless visible check in unlink_nv12_plane()") +Signed-off-by: Ville Syrjälä +Link: https://patch.msgid.link/20260316163953.12905-2-ville.syrjala@linux.intel.com +Reviewed-by: Uma Shankar +(cherry picked from commit 017ecd04985573eeeb0745fa2c23896fb22ee0cc) +Signed-off-by: Joonas Lahtinen +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/i915/display/intel_plane.c | 11 +++++++++-- + 1 file changed, 9 insertions(+), 2 deletions(-) + +--- a/drivers/gpu/drm/i915/display/intel_plane.c ++++ b/drivers/gpu/drm/i915/display/intel_plane.c +@@ -433,11 +433,16 @@ void intel_plane_copy_hw_state(struct in + drm_framebuffer_get(plane_state->hw.fb); + } + ++static void unlink_nv12_plane(struct intel_crtc_state *crtc_state, ++ struct intel_plane_state *plane_state); ++ + void intel_plane_set_invisible(struct intel_crtc_state *crtc_state, + struct intel_plane_state *plane_state) + { + struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); + ++ unlink_nv12_plane(crtc_state, plane_state); ++ + crtc_state->active_planes &= ~BIT(plane->id); + crtc_state->scaled_planes &= ~BIT(plane->id); + crtc_state->nv12_planes &= ~BIT(plane->id); +@@ -1511,6 +1516,9 @@ static void unlink_nv12_plane(struct int + struct intel_display *display = to_intel_display(plane_state); + struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); + ++ if (!plane_state->planar_linked_plane) ++ return; ++ + plane_state->planar_linked_plane = NULL; + + if (!plane_state->is_y_plane) +@@ -1548,8 +1556,7 @@ static int icl_check_nv12_planes(struct + if (plane->pipe != crtc->pipe) + continue; + +- if (plane_state->planar_linked_plane) +- unlink_nv12_plane(crtc_state, plane_state); ++ unlink_nv12_plane(crtc_state, plane_state); + } + + if (!crtc_state->nv12_planes) diff --git a/queue-6.19/futex-clear-stale-exiting-pointer-in-futex_lock_pi-retry-path.patch b/queue-6.19/futex-clear-stale-exiting-pointer-in-futex_lock_pi-retry-path.patch new file mode 100644 index 0000000000..ce31817988 --- /dev/null +++ b/queue-6.19/futex-clear-stale-exiting-pointer-in-futex_lock_pi-retry-path.patch @@ -0,0 +1,76 @@ +From 210d36d892de5195e6766c45519dfb1e65f3eb83 Mon Sep 17 00:00:00 2001 +From: Davidlohr Bueso +Date: Wed, 25 Mar 2026 17:17:59 -0700 +Subject: futex: Clear stale exiting pointer in futex_lock_pi() retry path + +From: Davidlohr Bueso + +commit 210d36d892de5195e6766c45519dfb1e65f3eb83 upstream. + +Fuzzying/stressing futexes triggered: + + WARNING: kernel/futex/core.c:825 at wait_for_owner_exiting+0x7a/0x80, CPU#11: futex_lock_pi_s/524 + +When futex_lock_pi_atomic() sees the owner is exiting, it returns -EBUSY +and stores a refcounted task pointer in 'exiting'. + +After wait_for_owner_exiting() consumes that reference, the local pointer +is never reset to nil. Upon a retry, if futex_lock_pi_atomic() returns a +different error, the bogus pointer is passed to wait_for_owner_exiting(). + + CPU0 CPU1 CPU2 + futex_lock_pi(uaddr) + // acquires the PI futex + exit() + futex_cleanup_begin() + futex_state = EXITING; + futex_lock_pi(uaddr) + futex_lock_pi_atomic() + attach_to_pi_owner() + // observes EXITING + *exiting = owner; // takes ref + return -EBUSY + wait_for_owner_exiting(-EBUSY, owner) + put_task_struct(); // drops ref + // exiting still points to owner + goto retry; + futex_lock_pi_atomic() + lock_pi_update_atomic() + cmpxchg(uaddr) + *uaddr ^= WAITERS // whatever + // value changed + return -EAGAIN; + wait_for_owner_exiting(-EAGAIN, exiting) // stale + WARN_ON_ONCE(exiting) + +Fix this by resetting upon retry, essentially aligning it with requeue_pi. + +Fixes: 3ef240eaff36 ("futex: Prevent exit livelock") +Signed-off-by: Davidlohr Bueso +Signed-off-by: Thomas Gleixner +Cc: stable@vger.kernel.org +Link: https://patch.msgid.link/20260326001759.4129680-1-dave@stgolabs.net +Signed-off-by: Greg Kroah-Hartman +--- + kernel/futex/pi.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/kernel/futex/pi.c ++++ b/kernel/futex/pi.c +@@ -918,7 +918,7 @@ int fixup_pi_owner(u32 __user *uaddr, st + int futex_lock_pi(u32 __user *uaddr, unsigned int flags, ktime_t *time, int trylock) + { + struct hrtimer_sleeper timeout, *to; +- struct task_struct *exiting = NULL; ++ struct task_struct *exiting; + struct rt_mutex_waiter rt_waiter; + struct futex_q q = futex_q_init; + DEFINE_WAKE_Q(wake_q); +@@ -933,6 +933,7 @@ int futex_lock_pi(u32 __user *uaddr, uns + to = futex_setup_timer(time, &timeout, flags, 0); + + retry: ++ exiting = NULL; + ret = get_futex_key(uaddr, flags, &q.key, FUTEX_WRITE); + if (unlikely(ret != 0)) + goto out; diff --git a/queue-6.19/i2c-designware-amdisp-fix-resume-probe-race-condition-issue.patch b/queue-6.19/i2c-designware-amdisp-fix-resume-probe-race-condition-issue.patch new file mode 100644 index 0000000000..744292b368 --- /dev/null +++ b/queue-6.19/i2c-designware-amdisp-fix-resume-probe-race-condition-issue.patch @@ -0,0 +1,78 @@ +From e2f1ada8e089dd5a331bcd8b88125ae2af8d188f Mon Sep 17 00:00:00 2001 +From: Pratap Nirujogi +Date: Fri, 20 Mar 2026 16:12:22 -0400 +Subject: i2c: designware: amdisp: Fix resume-probe race condition issue + +From: Pratap Nirujogi + +commit e2f1ada8e089dd5a331bcd8b88125ae2af8d188f upstream. + +Identified resume-probe race condition in kernel v7.0 with the commit +38fa29b01a6a ("i2c: designware: Combine the init functions"),but this +issue existed from the beginning though not detected. + +The amdisp i2c device requires ISP to be in power-on state for probe +to succeed. To meet this requirement, this device is added to genpd +to control ISP power using runtime PM. The pm_runtime_get_sync() called +before i2c_dw_probe() triggers PM resume, which powers on ISP and also +invokes the amdisp i2c runtime resume before the probe completes resulting +in this race condition and a NULL dereferencing issue in v7.0 + +Fix this race condition by using the genpd APIs directly during probe: + - Call dev_pm_genpd_resume() to Power ON ISP before probe + - Call dev_pm_genpd_suspend() to Power OFF ISP after probe + - Set the device to suspended state with pm_runtime_set_suspended() + - Enable runtime PM only after the device is fully initialized + +Fixes: d6263c468a761 ("i2c: amd-isp: Add ISP i2c-designware driver") +Co-developed-by: Bin Du +Signed-off-by: Bin Du +Signed-off-by: Pratap Nirujogi +Cc: # v6.16+ +Acked-by: Mika Westerberg +Reviewed-by: Mario Limonciello (AMD) +Reviewed-by: Andy Shevchenko +Signed-off-by: Andi Shyti +Link: https://lore.kernel.org/r/20260320201302.3490570-1-pratap.nirujogi@amd.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/i2c/busses/i2c-designware-amdisp.c | 11 +++++------ + 1 file changed, 5 insertions(+), 6 deletions(-) + +--- a/drivers/i2c/busses/i2c-designware-amdisp.c ++++ b/drivers/i2c/busses/i2c-designware-amdisp.c +@@ -7,6 +7,7 @@ + + #include + #include ++#include + #include + #include + +@@ -82,22 +83,20 @@ static int amd_isp_dw_i2c_plat_probe(str + if (isp_i2c_dev->shared_with_punit) + pm_runtime_get_noresume(&pdev->dev); + +- pm_runtime_enable(&pdev->dev); +- pm_runtime_get_sync(&pdev->dev); +- ++ dev_pm_genpd_resume(&pdev->dev); + ret = i2c_dw_probe(isp_i2c_dev); + if (ret) { + dev_err_probe(&pdev->dev, ret, "i2c_dw_probe failed\n"); + goto error_release_rpm; + } +- +- pm_runtime_put_sync(&pdev->dev); ++ dev_pm_genpd_suspend(&pdev->dev); ++ pm_runtime_set_suspended(&pdev->dev); ++ pm_runtime_enable(&pdev->dev); + + return 0; + + error_release_rpm: + amd_isp_dw_i2c_plat_pm_cleanup(isp_i2c_dev); +- pm_runtime_put_sync(&pdev->dev); + return ret; + } + diff --git a/queue-6.19/i2c-imx-ensure-no-clock-is-generated-after-last-read.patch b/queue-6.19/i2c-imx-ensure-no-clock-is-generated-after-last-read.patch new file mode 100644 index 0000000000..e4dbf89d77 --- /dev/null +++ b/queue-6.19/i2c-imx-ensure-no-clock-is-generated-after-last-read.patch @@ -0,0 +1,131 @@ +From 13101db735bdb29c5f60e95fb578690bd178b30f Mon Sep 17 00:00:00 2001 +From: Stefan Eichenberger +Date: Wed, 18 Feb 2026 16:08:50 +0100 +Subject: i2c: imx: ensure no clock is generated after last read + +From: Stefan Eichenberger + +commit 13101db735bdb29c5f60e95fb578690bd178b30f upstream. + +When reading from the I2DR register, right after releasing the bus by +clearing MSTA and MTX, the I2C controller might still generate an +additional clock cycle which can cause devices to misbehave. Ensure to +only read from I2DR after the bus is not busy anymore. Because this +requires polling, the read of the last byte is moved outside of the +interrupt handler. + +An example for such a failing transfer is this: +i2ctransfer -y -a 0 w1@0x00 0x02 r1 +Error: Sending messages failed: Connection timed out +It does not happen with every device because not all devices react to +the additional clock cycle. + +Fixes: 5f5c2d4579ca ("i2c: imx: prevent rescheduling in non dma mode") +Cc: stable@vger.kernel.org # v6.13+ +Signed-off-by: Stefan Eichenberger +Signed-off-by: Andi Shyti +Link: https://lore.kernel.org/r/20260218150940.131354-3-eichest@gmail.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/i2c/busses/i2c-imx.c | 51 ++++++++++++++++++++++++++----------------- + 1 file changed, 32 insertions(+), 19 deletions(-) + +--- a/drivers/i2c/busses/i2c-imx.c ++++ b/drivers/i2c/busses/i2c-imx.c +@@ -1018,8 +1018,9 @@ static inline int i2c_imx_isr_read(struc + return 0; + } + +-static inline void i2c_imx_isr_read_continue(struct imx_i2c_struct *i2c_imx) ++static inline enum imx_i2c_state i2c_imx_isr_read_continue(struct imx_i2c_struct *i2c_imx) + { ++ enum imx_i2c_state next_state = IMX_I2C_STATE_READ_CONTINUE; + unsigned int temp; + + if ((i2c_imx->msg->len - 1) == i2c_imx->msg_buf_idx) { +@@ -1033,18 +1034,20 @@ static inline void i2c_imx_isr_read_cont + i2c_imx->stopped = 1; + temp &= ~(I2CR_MSTA | I2CR_MTX); + imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR); +- } else { +- /* +- * For i2c master receiver repeat restart operation like: +- * read -> repeat MSTA -> read/write +- * The controller must set MTX before read the last byte in +- * the first read operation, otherwise the first read cost +- * one extra clock cycle. +- */ +- temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR); +- temp |= I2CR_MTX; +- imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR); ++ ++ return IMX_I2C_STATE_DONE; + } ++ /* ++ * For i2c master receiver repeat restart operation like: ++ * read -> repeat MSTA -> read/write ++ * The controller must set MTX before read the last byte in ++ * the first read operation, otherwise the first read cost ++ * one extra clock cycle. ++ */ ++ temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR); ++ temp |= I2CR_MTX; ++ imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR); ++ next_state = IMX_I2C_STATE_DONE; + } else if (i2c_imx->msg_buf_idx == (i2c_imx->msg->len - 2)) { + temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR); + temp |= I2CR_TXAK; +@@ -1052,6 +1055,7 @@ static inline void i2c_imx_isr_read_cont + } + + i2c_imx->msg->buf[i2c_imx->msg_buf_idx++] = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2DR); ++ return next_state; + } + + static inline void i2c_imx_isr_read_block_data_len(struct imx_i2c_struct *i2c_imx) +@@ -1088,11 +1092,9 @@ static irqreturn_t i2c_imx_master_isr(st + break; + + case IMX_I2C_STATE_READ_CONTINUE: +- i2c_imx_isr_read_continue(i2c_imx); +- if (i2c_imx->msg_buf_idx == i2c_imx->msg->len) { +- i2c_imx->state = IMX_I2C_STATE_DONE; ++ i2c_imx->state = i2c_imx_isr_read_continue(i2c_imx); ++ if (i2c_imx->state == IMX_I2C_STATE_DONE) + wake_up(&i2c_imx->queue); +- } + break; + + case IMX_I2C_STATE_READ_BLOCK_DATA: +@@ -1490,6 +1492,7 @@ static int i2c_imx_read(struct imx_i2c_s + bool is_lastmsg) + { + int block_data = msgs->flags & I2C_M_RECV_LEN; ++ int ret = 0; + + dev_dbg(&i2c_imx->adapter.dev, + "<%s> write slave address: addr=0x%x\n", +@@ -1522,10 +1525,20 @@ static int i2c_imx_read(struct imx_i2c_s + dev_err(&i2c_imx->adapter.dev, "<%s> read timedout\n", __func__); + return -ETIMEDOUT; + } +- if (i2c_imx->is_lastmsg && !i2c_imx->stopped) +- return i2c_imx_bus_busy(i2c_imx, 0, false); ++ if (i2c_imx->is_lastmsg) { ++ if (!i2c_imx->stopped) ++ ret = i2c_imx_bus_busy(i2c_imx, 0, false); ++ /* ++ * Only read the last byte of the last message after the bus is ++ * not busy. Else the controller generates another clock which ++ * might confuse devices. ++ */ ++ if (!ret) ++ i2c_imx->msg->buf[i2c_imx->msg_buf_idx++] = imx_i2c_read_reg(i2c_imx, ++ IMX_I2C_I2DR); ++ } + +- return 0; ++ return ret; + } + + static int i2c_imx_xfer_common(struct i2c_adapter *adapter, diff --git a/queue-6.19/i2c-imx-fix-i2c-issue-when-reading-multiple-messages.patch b/queue-6.19/i2c-imx-fix-i2c-issue-when-reading-multiple-messages.patch new file mode 100644 index 0000000000..54b6d6f485 --- /dev/null +++ b/queue-6.19/i2c-imx-fix-i2c-issue-when-reading-multiple-messages.patch @@ -0,0 +1,39 @@ +From f88e2e748a1fc3cb4b8d163a9be790812f578850 Mon Sep 17 00:00:00 2001 +From: Stefan Eichenberger +Date: Wed, 18 Feb 2026 16:08:49 +0100 +Subject: i2c: imx: fix i2c issue when reading multiple messages + +From: Stefan Eichenberger + +commit f88e2e748a1fc3cb4b8d163a9be790812f578850 upstream. + +When reading multiple messages, meaning a repeated start is required, +polling the bus busy bit must be avoided. This must only be done for +the last message. Otherwise, the driver will timeout. + +Here an example of such a sequence that fails with an error: +i2ctransfer -y -a 0 w1@0x00 0x02 r1 w1@0x00 0x02 r1 +Error: Sending messages failed: Connection timed out + +Fixes: 5f5c2d4579ca ("i2c: imx: prevent rescheduling in non dma mode") +Cc: stable@vger.kernel.org # v6.13+ +Signed-off-by: Stefan Eichenberger +Reviewed-by: Frank Li +Signed-off-by: Andi Shyti +Link: https://lore.kernel.org/r/20260218150940.131354-2-eichest@gmail.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/i2c/busses/i2c-imx.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/i2c/busses/i2c-imx.c ++++ b/drivers/i2c/busses/i2c-imx.c +@@ -1522,7 +1522,7 @@ static int i2c_imx_read(struct imx_i2c_s + dev_err(&i2c_imx->adapter.dev, "<%s> read timedout\n", __func__); + return -ETIMEDOUT; + } +- if (!i2c_imx->stopped) ++ if (i2c_imx->is_lastmsg && !i2c_imx->stopped) + return i2c_imx_bus_busy(i2c_imx, 0, false); + + return 0; diff --git a/queue-6.19/iomap-fix-invalid-folio-access-when-i_blkbits-differs-from-i-o-granularity.patch b/queue-6.19/iomap-fix-invalid-folio-access-when-i_blkbits-differs-from-i-o-granularity.patch new file mode 100644 index 0000000000..802d0f0e4c --- /dev/null +++ b/queue-6.19/iomap-fix-invalid-folio-access-when-i_blkbits-differs-from-i-o-granularity.patch @@ -0,0 +1,81 @@ +From bd71fb3fea9945987053968f028a948997cba8cc Mon Sep 17 00:00:00 2001 +From: Joanne Koong +Date: Tue, 17 Mar 2026 13:39:35 -0700 +Subject: iomap: fix invalid folio access when i_blkbits differs from I/O granularity + +From: Joanne Koong + +commit bd71fb3fea9945987053968f028a948997cba8cc upstream. + +Commit aa35dd5cbc06 ("iomap: fix invalid folio access after +folio_end_read()") partially addressed invalid folio access for folios +without an ifs attached, but it did not handle the case where +1 << inode->i_blkbits matches the folio size but is different from the +granularity used for the IO, which means IO can be submitted for less +than the full folio for the !ifs case. + +In this case, the condition: + + if (*bytes_submitted == folio_len) + ctx->cur_folio = NULL; + +in iomap_read_folio_iter() will not invalidate ctx->cur_folio, and +iomap_read_end() will still be called on the folio even though the IO +helper owns it and will finish the read on it. + +Fix this by unconditionally invalidating ctx->cur_folio for the !ifs +case. + +Reported-by: Johannes Thumshirn +Tested-by: Johannes Thumshirn +Link: https://lore.kernel.org/linux-fsdevel/b3dfe271-4e3d-4922-b618-e73731242bca@wdc.com/ +Fixes: b2f35ac4146d ("iomap: add caller-provided callbacks for read and readahead") +Cc: stable@vger.kernel.org +Signed-off-by: Joanne Koong +Link: https://patch.msgid.link/20260317203935.830549-1-joannelkoong@gmail.com +Reviewed-by: Christoph Hellwig +Signed-off-by: Christian Brauner +Signed-off-by: Greg Kroah-Hartman +--- + fs/iomap/buffered-io.c | 15 ++++++++++----- + 1 file changed, 10 insertions(+), 5 deletions(-) + +--- a/fs/iomap/buffered-io.c ++++ b/fs/iomap/buffered-io.c +@@ -506,6 +506,7 @@ static int iomap_read_folio_iter(struct + loff_t length = iomap_length(iter); + struct folio *folio = ctx->cur_folio; + size_t folio_len = folio_size(folio); ++ struct iomap_folio_state *ifs; + size_t poff, plen; + loff_t pos_diff; + int ret; +@@ -517,7 +518,7 @@ static int iomap_read_folio_iter(struct + return iomap_iter_advance(iter, length); + } + +- ifs_alloc(iter->inode, folio, iter->flags); ++ ifs = ifs_alloc(iter->inode, folio, iter->flags); + + length = min_t(loff_t, length, folio_len - offset_in_folio(folio, pos)); + while (length) { +@@ -548,11 +549,15 @@ static int iomap_read_folio_iter(struct + + *bytes_submitted += plen; + /* +- * If the entire folio has been read in by the IO +- * helper, then the helper owns the folio and will end +- * the read on it. ++ * Hand off folio ownership to the IO helper when: ++ * 1) The entire folio has been submitted for IO, or ++ * 2) There is no ifs attached to the folio ++ * ++ * Case (2) occurs when 1 << i_blkbits matches the folio ++ * size but the underlying filesystem or block device ++ * uses a smaller granularity for IO. + */ +- if (*bytes_submitted == folio_len) ++ if (*bytes_submitted == folio_len || !ifs) + ctx->cur_folio = NULL; + } + diff --git a/queue-6.19/irqchip-qcom-mpm-add-missing-mailbox-tx-done-acknowledgment.patch b/queue-6.19/irqchip-qcom-mpm-add-missing-mailbox-tx-done-acknowledgment.patch new file mode 100644 index 0000000000..e8eccd2622 --- /dev/null +++ b/queue-6.19/irqchip-qcom-mpm-add-missing-mailbox-tx-done-acknowledgment.patch @@ -0,0 +1,46 @@ +From cfe02147e86307a17057ee4e3604f5f5919571d2 Mon Sep 17 00:00:00 2001 +From: Jassi Brar +Date: Sun, 22 Mar 2026 12:15:33 -0500 +Subject: irqchip/qcom-mpm: Add missing mailbox TX done acknowledgment + +From: Jassi Brar + +commit cfe02147e86307a17057ee4e3604f5f5919571d2 upstream. + +The mbox_client for qcom-mpm sends NULL doorbell messages via +mbox_send_message() but never signals TX completion. + +Set knows_txdone=true and call mbox_client_txdone() after a successful +send, matching the pattern used by other Qualcomm mailbox clients (smp2p, +smsm, qcom_aoss etc). + +Fixes: a6199bb514d8a6 "irqchip: Add Qualcomm MPM controller driver" +Signed-off-by: Jassi Brar +Signed-off-by: Thomas Gleixner +Reviewed-by: Douglas Anderson +Cc: stable@vger.kernel.org +Link: https://patch.msgid.link/20260322171533.608436-1-jassisinghbrar@gmail.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/irqchip/irq-qcom-mpm.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/drivers/irqchip/irq-qcom-mpm.c ++++ b/drivers/irqchip/irq-qcom-mpm.c +@@ -306,6 +306,8 @@ static int mpm_pd_power_off(struct gener + if (ret < 0) + return ret; + ++ mbox_client_txdone(priv->mbox_chan, 0); ++ + return 0; + } + +@@ -434,6 +436,7 @@ static int qcom_mpm_probe(struct platfor + } + + priv->mbox_client.dev = dev; ++ priv->mbox_client.knows_txdone = true; + priv->mbox_chan = mbox_request_channel(&priv->mbox_client, 0); + if (IS_ERR(priv->mbox_chan)) { + ret = PTR_ERR(priv->mbox_chan); diff --git a/queue-6.19/jbd2-gracefully-abort-on-checkpointing-state-corruptions.patch b/queue-6.19/jbd2-gracefully-abort-on-checkpointing-state-corruptions.patch new file mode 100644 index 0000000000..536ba1442a --- /dev/null +++ b/queue-6.19/jbd2-gracefully-abort-on-checkpointing-state-corruptions.patch @@ -0,0 +1,66 @@ +From bac3190a8e79beff6ed221975e0c9b1b5f2a21da Mon Sep 17 00:00:00 2001 +From: Milos Nikic +Date: Tue, 10 Mar 2026 21:15:48 -0700 +Subject: jbd2: gracefully abort on checkpointing state corruptions + +From: Milos Nikic + +commit bac3190a8e79beff6ed221975e0c9b1b5f2a21da upstream. + +This patch targets two internal state machine invariants in checkpoint.c +residing inside functions that natively return integer error codes. + +- In jbd2_cleanup_journal_tail(): A blocknr of 0 indicates a severely +corrupted journal superblock. Replaced the J_ASSERT with a WARN_ON_ONCE +and a graceful journal abort, returning -EFSCORRUPTED. + +- In jbd2_log_do_checkpoint(): Replaced the J_ASSERT_BH checking for +an unexpected buffer_jwrite state. If the warning triggers, we +explicitly drop the just-taken get_bh() reference and call __flush_batch() +to safely clean up any previously queued buffers in the j_chkpt_bhs array, +preventing a memory leak before returning -EFSCORRUPTED. + +Signed-off-by: Milos Nikic +Reviewed-by: Andreas Dilger +Reviewed-by: Zhang Yi +Reviewed-by: Baokun Li +Reviewed-by: Jan Kara +Link: https://patch.msgid.link/20260311041548.159424-1-nikic.milos@gmail.com +Signed-off-by: Theodore Ts'o +Cc: stable@kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + fs/jbd2/checkpoint.c | 15 +++++++++++++-- + 1 file changed, 13 insertions(+), 2 deletions(-) + +--- a/fs/jbd2/checkpoint.c ++++ b/fs/jbd2/checkpoint.c +@@ -267,7 +267,15 @@ restart: + */ + BUFFER_TRACE(bh, "queue"); + get_bh(bh); +- J_ASSERT_BH(bh, !buffer_jwrite(bh)); ++ if (WARN_ON_ONCE(buffer_jwrite(bh))) { ++ put_bh(bh); /* drop the ref we just took */ ++ spin_unlock(&journal->j_list_lock); ++ /* Clean up any previously batched buffers */ ++ if (batch_count) ++ __flush_batch(journal, &batch_count); ++ jbd2_journal_abort(journal, -EFSCORRUPTED); ++ return -EFSCORRUPTED; ++ } + journal->j_chkpt_bhs[batch_count++] = bh; + transaction->t_chp_stats.cs_written++; + transaction->t_checkpoint_list = jh->b_cpnext; +@@ -325,7 +333,10 @@ int jbd2_cleanup_journal_tail(journal_t + + if (!jbd2_journal_get_log_tail(journal, &first_tid, &blocknr)) + return 1; +- J_ASSERT(blocknr != 0); ++ if (WARN_ON_ONCE(blocknr == 0)) { ++ jbd2_journal_abort(journal, -EFSCORRUPTED); ++ return -EFSCORRUPTED; ++ } + + /* + * We need to make sure that any blocks that were recently written out diff --git a/queue-6.19/kvm-x86-mmu-drop-zap-existing-present-spte-even-when-creating-an-mmio-spte.patch b/queue-6.19/kvm-x86-mmu-drop-zap-existing-present-spte-even-when-creating-an-mmio-spte.patch new file mode 100644 index 0000000000..5d813f027b --- /dev/null +++ b/queue-6.19/kvm-x86-mmu-drop-zap-existing-present-spte-even-when-creating-an-mmio-spte.patch @@ -0,0 +1,83 @@ +From aad885e774966e97b675dfe928da164214a71605 Mon Sep 17 00:00:00 2001 +From: Sean Christopherson +Date: Thu, 5 Mar 2026 17:28:04 -0800 +Subject: KVM: x86/mmu: Drop/zap existing present SPTE even when creating an MMIO SPTE + +From: Sean Christopherson + +commit aad885e774966e97b675dfe928da164214a71605 upstream. + +When installing an emulated MMIO SPTE, do so *after* dropping/zapping the +existing SPTE (if it's shadow-present). While commit a54aa15c6bda3 was +right about it being impossible to convert a shadow-present SPTE to an +MMIO SPTE due to a _guest_ write, it failed to account for writes to guest +memory that are outside the scope of KVM. + +E.g. if host userspace modifies a shadowed gPTE to switch from a memslot +to emulted MMIO and then the guest hits a relevant page fault, KVM will +install the MMIO SPTE without first zapping the shadow-present SPTE. + + ------------[ cut here ]------------ + is_shadow_present_pte(*sptep) + WARNING: arch/x86/kvm/mmu/mmu.c:484 at mark_mmio_spte+0xb2/0xc0 [kvm], CPU#0: vmx_ept_stale_r/4292 + Modules linked in: kvm_intel kvm irqbypass + CPU: 0 UID: 1000 PID: 4292 Comm: vmx_ept_stale_r Not tainted 7.0.0-rc2-eafebd2d2ab0-sink-vm #319 PREEMPT + Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 0.0.0 02/06/2015 + RIP: 0010:mark_mmio_spte+0xb2/0xc0 [kvm] + Call Trace: + + mmu_set_spte+0x237/0x440 [kvm] + ept_page_fault+0x535/0x7f0 [kvm] + kvm_mmu_do_page_fault+0xee/0x1f0 [kvm] + kvm_mmu_page_fault+0x8d/0x620 [kvm] + vmx_handle_exit+0x18c/0x5a0 [kvm_intel] + kvm_arch_vcpu_ioctl_run+0xc55/0x1c20 [kvm] + kvm_vcpu_ioctl+0x2d5/0x980 [kvm] + __x64_sys_ioctl+0x8a/0xd0 + do_syscall_64+0xb5/0x730 + entry_SYSCALL_64_after_hwframe+0x4b/0x53 + RIP: 0033:0x47fa3f + + ---[ end trace 0000000000000000 ]--- + +Reported-by: Alexander Bulekov +Debugged-by: Alexander Bulekov +Suggested-by: Fred Griffoul +Fixes: a54aa15c6bda3 ("KVM: x86/mmu: Handle MMIO SPTEs directly in mmu_set_spte()") +Cc: stable@vger.kernel.org +Signed-off-by: Sean Christopherson +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/kvm/mmu/mmu.c | 14 ++++++++------ + 1 file changed, 8 insertions(+), 6 deletions(-) + +--- a/arch/x86/kvm/mmu/mmu.c ++++ b/arch/x86/kvm/mmu/mmu.c +@@ -3044,12 +3044,6 @@ static int mmu_set_spte(struct kvm_vcpu + bool prefetch = !fault || fault->prefetch; + bool write_fault = fault && fault->write; + +- if (unlikely(is_noslot_pfn(pfn))) { +- vcpu->stat.pf_mmio_spte_created++; +- mark_mmio_spte(vcpu, sptep, gfn, pte_access); +- return RET_PF_EMULATE; +- } +- + if (is_shadow_present_pte(*sptep)) { + if (prefetch && is_last_spte(*sptep, level) && + pfn == spte_to_pfn(*sptep)) +@@ -3073,6 +3067,14 @@ static int mmu_set_spte(struct kvm_vcpu + was_rmapped = 1; + } + ++ if (unlikely(is_noslot_pfn(pfn))) { ++ vcpu->stat.pf_mmio_spte_created++; ++ mark_mmio_spte(vcpu, sptep, gfn, pte_access); ++ if (flush) ++ kvm_flush_remote_tlbs_gfn(vcpu->kvm, gfn, level); ++ return RET_PF_EMULATE; ++ } ++ + wrprot = make_spte(vcpu, sp, slot, pte_access, gfn, pfn, *sptep, prefetch, + false, host_writable, &spte); + diff --git a/queue-6.19/kvm-x86-mmu-only-warn-in-direct-mmus-when-overwriting-shadow-present-spte.patch b/queue-6.19/kvm-x86-mmu-only-warn-in-direct-mmus-when-overwriting-shadow-present-spte.patch new file mode 100644 index 0000000000..93da6e9d29 --- /dev/null +++ b/queue-6.19/kvm-x86-mmu-only-warn-in-direct-mmus-when-overwriting-shadow-present-spte.patch @@ -0,0 +1,57 @@ +From df83746075778958954aa0460cca55f4b3fc9c02 Mon Sep 17 00:00:00 2001 +From: Sean Christopherson +Date: Thu, 5 Mar 2026 17:42:14 -0800 +Subject: KVM: x86/mmu: Only WARN in direct MMUs when overwriting shadow-present SPTE + +From: Sean Christopherson + +commit df83746075778958954aa0460cca55f4b3fc9c02 upstream. + +Adjust KVM's sanity check against overwriting a shadow-present SPTE with a +another SPTE with a different target PFN to only apply to direct MMUs, +i.e. only to MMUs without shadowed gPTEs. While it's impossible for KVM +to overwrite a shadow-present SPTE in response to a guest write, writes +from outside the scope of KVM, e.g. from host userspace, aren't detected +by KVM's write tracking and so can break KVM's shadow paging rules. + + ------------[ cut here ]------------ + pfn != spte_to_pfn(*sptep) + WARNING: arch/x86/kvm/mmu/mmu.c:3069 at mmu_set_spte+0x1e4/0x440 [kvm], CPU#0: vmx_ept_stale_r/872 + Modules linked in: kvm_intel kvm irqbypass + CPU: 0 UID: 1000 PID: 872 Comm: vmx_ept_stale_r Not tainted 7.0.0-rc2-eafebd2d2ab0-sink-vm #319 PREEMPT + Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 0.0.0 02/06/2015 + RIP: 0010:mmu_set_spte+0x1e4/0x440 [kvm] + Call Trace: + + ept_page_fault+0x535/0x7f0 [kvm] + kvm_mmu_do_page_fault+0xee/0x1f0 [kvm] + kvm_mmu_page_fault+0x8d/0x620 [kvm] + vmx_handle_exit+0x18c/0x5a0 [kvm_intel] + kvm_arch_vcpu_ioctl_run+0xc55/0x1c20 [kvm] + kvm_vcpu_ioctl+0x2d5/0x980 [kvm] + __x64_sys_ioctl+0x8a/0xd0 + do_syscall_64+0xb5/0x730 + entry_SYSCALL_64_after_hwframe+0x4b/0x53 + + ---[ end trace 0000000000000000 ]--- + +Fixes: 11d45175111d ("KVM: x86/mmu: Warn if PFN changes on shadow-present SPTE in shadow MMU") +Cc: stable@vger.kernel.org +Signed-off-by: Sean Christopherson +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/kvm/mmu/mmu.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/arch/x86/kvm/mmu/mmu.c ++++ b/arch/x86/kvm/mmu/mmu.c +@@ -3060,7 +3060,8 @@ static int mmu_set_spte(struct kvm_vcpu + child = spte_to_child_sp(pte); + drop_parent_pte(vcpu->kvm, child, sptep); + flush = true; +- } else if (WARN_ON_ONCE(pfn != spte_to_pfn(*sptep))) { ++ } else if (pfn != spte_to_pfn(*sptep)) { ++ WARN_ON_ONCE(vcpu->arch.mmu->root_role.direct); + drop_spte(vcpu->kvm, sptep); + flush = true; + } else diff --git a/queue-6.19/loongarch-fix-missing-null-checks-for-kstrdup.patch b/queue-6.19/loongarch-fix-missing-null-checks-for-kstrdup.patch new file mode 100644 index 0000000000..6f7601e236 --- /dev/null +++ b/queue-6.19/loongarch-fix-missing-null-checks-for-kstrdup.patch @@ -0,0 +1,45 @@ +From 3a28daa9b7d7c2ddf2c722e9e95d7e0928bf0cd1 Mon Sep 17 00:00:00 2001 +From: Li Jun +Date: Thu, 26 Mar 2026 14:29:08 +0800 +Subject: LoongArch: Fix missing NULL checks for kstrdup() + +From: Li Jun + +commit 3a28daa9b7d7c2ddf2c722e9e95d7e0928bf0cd1 upstream. + +1. Replace "of_find_node_by_path("/")" with "of_root" to avoid multiple +calls to "of_node_put()". + +2. Fix a potential kernel oops during early boot when memory allocation +fails while parsing CPU model from device tree. + +Cc: stable@vger.kernel.org +Signed-off-by: Li Jun +Signed-off-by: Huacai Chen +Signed-off-by: Greg Kroah-Hartman +--- + arch/loongarch/kernel/env.c | 7 +++---- + 1 file changed, 3 insertions(+), 4 deletions(-) + +--- a/arch/loongarch/kernel/env.c ++++ b/arch/loongarch/kernel/env.c +@@ -42,16 +42,15 @@ static int __init init_cpu_fullname(void + int cpu, ret; + char *cpuname; + const char *model; +- struct device_node *root; + + /* Parsing cpuname from DTS model property */ +- root = of_find_node_by_path("/"); +- ret = of_property_read_string(root, "model", &model); ++ ret = of_property_read_string(of_root, "model", &model); + if (ret == 0) { + cpuname = kstrdup(model, GFP_KERNEL); ++ if (!cpuname) ++ return -ENOMEM; + loongson_sysconf.cpuname = strsep(&cpuname, " "); + } +- of_node_put(root); + + if (loongson_sysconf.cpuname && !strncmp(loongson_sysconf.cpuname, "Loongson", 8)) { + for (cpu = 0; cpu < NR_CPUS; cpu++) diff --git a/queue-6.19/loongarch-kvm-fix-base-address-calculation-in-kvm_eiointc_regs_access.patch b/queue-6.19/loongarch-kvm-fix-base-address-calculation-in-kvm_eiointc_regs_access.patch new file mode 100644 index 0000000000..ce25adc3d1 --- /dev/null +++ b/queue-6.19/loongarch-kvm-fix-base-address-calculation-in-kvm_eiointc_regs_access.patch @@ -0,0 +1,70 @@ +From 6bcfb7f46d667b04bd1a1169ccedf5fb699c60df Mon Sep 17 00:00:00 2001 +From: Bibo Mao +Date: Thu, 26 Mar 2026 14:29:09 +0800 +Subject: LoongArch: KVM: Fix base address calculation in kvm_eiointc_regs_access() + +From: Bibo Mao + +commit 6bcfb7f46d667b04bd1a1169ccedf5fb699c60df upstream. + +In function kvm_eiointc_regs_access(), the register base address is +caculated from array base address plus offset, the offset is absolute +value from the base address. The data type of array base address is +u64, it should be converted into the "void *" type and then plus the +offset. + +Cc: +Fixes: d3e43a1f34ac ("LoongArch: KVM: Use 64-bit register definition for EIOINTC"). +Reported-by: Aurelien Jarno +Link: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1131431 +Signed-off-by: Bibo Mao +Signed-off-by: Huacai Chen +Signed-off-by: Greg Kroah-Hartman +--- + arch/loongarch/kvm/intc/eiointc.c | 14 +++++++------- + 1 file changed, 7 insertions(+), 7 deletions(-) + +--- a/arch/loongarch/kvm/intc/eiointc.c ++++ b/arch/loongarch/kvm/intc/eiointc.c +@@ -481,34 +481,34 @@ static int kvm_eiointc_regs_access(struc + switch (addr) { + case EIOINTC_NODETYPE_START ... EIOINTC_NODETYPE_END: + offset = (addr - EIOINTC_NODETYPE_START) / 4; +- p = s->nodetype + offset * 4; ++ p = (void *)s->nodetype + offset * 4; + break; + case EIOINTC_IPMAP_START ... EIOINTC_IPMAP_END: + offset = (addr - EIOINTC_IPMAP_START) / 4; +- p = &s->ipmap + offset * 4; ++ p = (void *)&s->ipmap + offset * 4; + break; + case EIOINTC_ENABLE_START ... EIOINTC_ENABLE_END: + offset = (addr - EIOINTC_ENABLE_START) / 4; +- p = s->enable + offset * 4; ++ p = (void *)s->enable + offset * 4; + break; + case EIOINTC_BOUNCE_START ... EIOINTC_BOUNCE_END: + offset = (addr - EIOINTC_BOUNCE_START) / 4; +- p = s->bounce + offset * 4; ++ p = (void *)s->bounce + offset * 4; + break; + case EIOINTC_ISR_START ... EIOINTC_ISR_END: + offset = (addr - EIOINTC_ISR_START) / 4; +- p = s->isr + offset * 4; ++ p = (void *)s->isr + offset * 4; + break; + case EIOINTC_COREISR_START ... EIOINTC_COREISR_END: + if (cpu >= s->num_cpu) + return -EINVAL; + + offset = (addr - EIOINTC_COREISR_START) / 4; +- p = s->coreisr[cpu] + offset * 4; ++ p = (void *)s->coreisr[cpu] + offset * 4; + break; + case EIOINTC_COREMAP_START ... EIOINTC_COREMAP_END: + offset = (addr - EIOINTC_COREMAP_START) / 4; +- p = s->coremap + offset * 4; ++ p = (void *)s->coremap + offset * 4; + break; + default: + kvm_err("%s: unknown eiointc register, addr = %d\n", __func__, addr); diff --git a/queue-6.19/loongarch-kvm-handle-the-case-that-eiointc-s-coremap-is-empty.patch b/queue-6.19/loongarch-kvm-handle-the-case-that-eiointc-s-coremap-is-empty.patch new file mode 100644 index 0000000000..3070e41523 --- /dev/null +++ b/queue-6.19/loongarch-kvm-handle-the-case-that-eiointc-s-coremap-is-empty.patch @@ -0,0 +1,36 @@ +From b97bd69eb0f67b5f961b304d28e9ba45e202d841 Mon Sep 17 00:00:00 2001 +From: Huacai Chen +Date: Thu, 26 Mar 2026 14:29:09 +0800 +Subject: LoongArch: KVM: Handle the case that EIOINTC's coremap is empty + +From: Huacai Chen + +commit b97bd69eb0f67b5f961b304d28e9ba45e202d841 upstream. + +EIOINTC's coremap in eiointc_update_sw_coremap() can be empty, currently +we get a cpuid with -1 in this case, but we actually need 0 because it's +similar as the case that cpuid >= 4. + +This fix an out-of-bounds access to kvm_arch::phyid_map::phys_map[]. + +Cc: +Fixes: 3956a52bc05bd81 ("LoongArch: KVM: Add EIOINTC read and write functions") +Reported-by: Aurelien Jarno +Link: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1131431 +Signed-off-by: Huacai Chen +Signed-off-by: Greg Kroah-Hartman +--- + arch/loongarch/kvm/intc/eiointc.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/arch/loongarch/kvm/intc/eiointc.c ++++ b/arch/loongarch/kvm/intc/eiointc.c +@@ -83,7 +83,7 @@ static inline void eiointc_update_sw_cor + + if (!(s->status & BIT(EIOINTC_ENABLE_CPU_ENCODE))) { + cpuid = ffs(cpuid) - 1; +- cpuid = (cpuid >= 4) ? 0 : cpuid; ++ cpuid = ((cpuid < 0) || (cpuid >= 4)) ? 0 : cpuid; + } + + vcpu = kvm_get_vcpu_by_cpuid(s->kvm, cpuid); diff --git a/queue-6.19/loongarch-kvm-make-kvm_get_vcpu_by_cpuid-more-robust.patch b/queue-6.19/loongarch-kvm-make-kvm_get_vcpu_by_cpuid-more-robust.patch new file mode 100644 index 0000000000..1a858f100b --- /dev/null +++ b/queue-6.19/loongarch-kvm-make-kvm_get_vcpu_by_cpuid-more-robust.patch @@ -0,0 +1,37 @@ +From 2db06c15d8c7a0ccb6108524e16cd9163753f354 Mon Sep 17 00:00:00 2001 +From: Huacai Chen +Date: Thu, 26 Mar 2026 14:29:09 +0800 +Subject: LoongArch: KVM: Make kvm_get_vcpu_by_cpuid() more robust + +From: Huacai Chen + +commit 2db06c15d8c7a0ccb6108524e16cd9163753f354 upstream. + +kvm_get_vcpu_by_cpuid() takes a cpuid parameter whose type is int, so +cpuid can be negative. Let kvm_get_vcpu_by_cpuid() return NULL for this +case so as to make it more robust. + +This fix an out-of-bounds access to kvm_arch::phyid_map::phys_map[]. + +Cc: +Fixes: 73516e9da512adc ("LoongArch: KVM: Add vcpu mapping from physical cpuid") +Reported-by: Aurelien Jarno +Link: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1131431 +Signed-off-by: Huacai Chen +Signed-off-by: Greg Kroah-Hartman +--- + arch/loongarch/kvm/vcpu.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/arch/loongarch/kvm/vcpu.c ++++ b/arch/loongarch/kvm/vcpu.c +@@ -562,6 +562,9 @@ struct kvm_vcpu *kvm_get_vcpu_by_cpuid(s + { + struct kvm_phyid_map *map; + ++ if (cpuid < 0) ++ return NULL; ++ + if (cpuid >= KVM_MAX_PHYID) + return NULL; + diff --git a/queue-6.19/loongarch-vdso-emit-gnu_eh_frame-correctly.patch b/queue-6.19/loongarch-vdso-emit-gnu_eh_frame-correctly.patch new file mode 100644 index 0000000000..b1930a2067 --- /dev/null +++ b/queue-6.19/loongarch-vdso-emit-gnu_eh_frame-correctly.patch @@ -0,0 +1,208 @@ +From e4878c37f6679fdea91b27a0f4e60a871f0b7bad Mon Sep 17 00:00:00 2001 +From: Xi Ruoyao +Date: Thu, 26 Mar 2026 14:29:09 +0800 +Subject: LoongArch: vDSO: Emit GNU_EH_FRAME correctly + +From: Xi Ruoyao + +commit e4878c37f6679fdea91b27a0f4e60a871f0b7bad upstream. + +With -fno-asynchronous-unwind-tables and --no-eh-frame-hdr (the default +of the linker), the GNU_EH_FRAME segment (specified by vdso.lds.S) is +empty. This is not valid, as the current DWARF specification mandates +the first byte of the EH frame to be the version number 1. It causes +some unwinders to complain, for example the ClickHouse query profiler +spams the log with messages: + + clickhouse-server[365854]: libunwind: unsupported .eh_frame_hdr + version: 127 at 7ffffffb0000 + +Here "127" is just the byte located at the p_vaddr (0, i.e. the +beginning of the vDSO) of the empty GNU_EH_FRAME segment. Cross- +checking with /proc/365854/maps has also proven 7ffffffb0000 is the +start of vDSO in the process VM image. + +In LoongArch the -fno-asynchronous-unwind-tables option seems just a +MIPS legacy, and MIPS only uses this option to satisfy the MIPS-specific +"genvdso" program, per the commit cfd75c2db17e ("MIPS: VDSO: Explicitly +use -fno-asynchronous-unwind-tables"). IIRC it indicates some inherent +limitation of the MIPS ELF ABI and has nothing to do with LoongArch. So +we can simply flip it over to -fasynchronous-unwind-tables and pass +--eh-frame-hdr for linking the vDSO, allowing the profilers to unwind the +stack for statistics even if the sample point is taken when the PC is in +the vDSO. + +However simply adjusting the options above would exploit an issue: when +the libgcc unwinder saw the invalid GNU_EH_FRAME segment, it silently +falled back to a machine-specific routine to match the code pattern of +rt_sigreturn() and extract the registers saved in the sigframe if the +code pattern is matched. As unwinding from signal handlers is vital for +libgcc to support pthread cancellation etc., the fall-back routine had +been silently keeping the LoongArch Linux systems functioning since +Linux 5.19. But when we start to emit GNU_EH_FRAME with the correct +format, fall-back routine will no longer be used and libgcc will fail +to unwind the sigframe, and unwinding from signal handlers will no +longer work, causing dozens of glibc test failures. To make it possible +to unwind from signal handlers again, it's necessary to code the unwind +info in __vdso_rt_sigreturn via .cfi_* directives. + +The offsets in the .cfi_* directives depend on the layout of struct +sigframe, notably the offset of sigcontext in the sigframe. To use the +offset in the assembly file, factor out struct sigframe into a header to +allow asm-offsets.c to output the offset for assembly. + +To work around a long-term issue in the libgcc unwinder (the pc is +unconditionally substracted by 1: doing so is technically incorrect for +a signal frame), a nop instruction is included with the two real +instructions in __vdso_rt_sigreturn in the same FDE PC range. The same +hack has been used on x86 for a long time. + +Cc: stable@vger.kernel.org +Fixes: c6b99bed6b8f ("LoongArch: Add VDSO and VSYSCALL support") +Signed-off-by: Xi Ruoyao +Signed-off-by: Huacai Chen +Signed-off-by: Greg Kroah-Hartman +--- + arch/loongarch/include/asm/linkage.h | 36 ++++++++++++++++++++++++++++++++++ + arch/loongarch/include/asm/sigframe.h | 9 ++++++++ + arch/loongarch/kernel/asm-offsets.c | 2 + + arch/loongarch/kernel/signal.c | 6 ----- + arch/loongarch/vdso/Makefile | 4 +-- + arch/loongarch/vdso/sigreturn.S | 6 ++--- + 6 files changed, 53 insertions(+), 10 deletions(-) + create mode 100644 arch/loongarch/include/asm/sigframe.h + +--- a/arch/loongarch/include/asm/linkage.h ++++ b/arch/loongarch/include/asm/linkage.h +@@ -41,4 +41,40 @@ + .cfi_endproc; \ + SYM_END(name, SYM_T_NONE) + ++/* ++ * This is for the signal handler trampoline, which is used as the return ++ * address of the signal handlers in userspace instead of called normally. ++ * The long standing libgcc bug https://gcc.gnu.org/PR124050 requires a ++ * nop between .cfi_startproc and the actual address of the trampoline, so ++ * we cannot simply use SYM_FUNC_START. ++ * ++ * This wrapper also contains all the .cfi_* directives for recovering ++ * the content of the GPRs and the "return address" (where the rt_sigreturn ++ * syscall will jump to), assuming there is a struct rt_sigframe (where ++ * a struct sigcontext containing those information we need to recover) at ++ * $sp. The "DWARF for the LoongArch(TM) Architecture" manual states ++ * column 0 is for $zero, but it does not make too much sense to ++ * save/restore the hardware zero register. Repurpose this column here ++ * for the return address (here it's not the content of $ra we cannot use ++ * the default column 3). ++ */ ++#define SYM_SIGFUNC_START(name) \ ++ .cfi_startproc; \ ++ .cfi_signal_frame; \ ++ .cfi_def_cfa 3, RT_SIGFRAME_SC; \ ++ .cfi_return_column 0; \ ++ .cfi_offset 0, SC_PC; \ ++ \ ++ .irp num, 1, 2, 3, 4, 5, 6, 7, 8, \ ++ 9, 10, 11, 12, 13, 14, 15, 16, \ ++ 17, 18, 19, 20, 21, 22, 23, 24, \ ++ 25, 26, 27, 28, 29, 30, 31; \ ++ .cfi_offset \num, SC_REGS + \num * SZREG; \ ++ .endr; \ ++ \ ++ nop; \ ++ SYM_START(name, SYM_L_GLOBAL, SYM_A_ALIGN) ++ ++#define SYM_SIGFUNC_END(name) SYM_FUNC_END(name) ++ + #endif +--- /dev/null ++++ b/arch/loongarch/include/asm/sigframe.h +@@ -0,0 +1,9 @@ ++/* SPDX-License-Identifier: GPL-2.0+ */ ++ ++#include ++#include ++ ++struct rt_sigframe { ++ struct siginfo rs_info; ++ struct ucontext rs_uctx; ++}; +--- a/arch/loongarch/kernel/asm-offsets.c ++++ b/arch/loongarch/kernel/asm-offsets.c +@@ -16,6 +16,7 @@ + #include + #include + #include ++#include + #include + + static void __used output_ptreg_defines(void) +@@ -220,6 +221,7 @@ static void __used output_sc_defines(voi + COMMENT("Linux sigcontext offsets."); + OFFSET(SC_REGS, sigcontext, sc_regs); + OFFSET(SC_PC, sigcontext, sc_pc); ++ OFFSET(RT_SIGFRAME_SC, rt_sigframe, rs_uctx.uc_mcontext); + BLANK(); + } + +--- a/arch/loongarch/kernel/signal.c ++++ b/arch/loongarch/kernel/signal.c +@@ -35,6 +35,7 @@ + #include + #include + #include ++#include + #include + #include + +@@ -51,11 +52,6 @@ + #define lock_lbt_owner() ({ preempt_disable(); pagefault_disable(); }) + #define unlock_lbt_owner() ({ pagefault_enable(); preempt_enable(); }) + +-struct rt_sigframe { +- struct siginfo rs_info; +- struct ucontext rs_uctx; +-}; +- + struct _ctx_layout { + struct sctx_info *addr; + unsigned int size; +--- a/arch/loongarch/vdso/Makefile ++++ b/arch/loongarch/vdso/Makefile +@@ -26,7 +26,7 @@ cflags-vdso := $(ccflags-vdso) \ + $(filter -W%,$(filter-out -Wa$(comma)%,$(KBUILD_CFLAGS))) \ + -std=gnu11 -fms-extensions -O2 -g -fno-strict-aliasing -fno-common -fno-builtin \ + -fno-stack-protector -fno-jump-tables -DDISABLE_BRANCH_PROFILING \ +- $(call cc-option, -fno-asynchronous-unwind-tables) \ ++ $(call cc-option, -fasynchronous-unwind-tables) \ + $(call cc-option, -fno-stack-protector) + aflags-vdso := $(ccflags-vdso) \ + -D__ASSEMBLY__ -Wa,-gdwarf-2 +@@ -41,7 +41,7 @@ endif + + # VDSO linker flags. + ldflags-y := -Bsymbolic --no-undefined -soname=linux-vdso.so.1 \ +- $(filter -E%,$(KBUILD_CFLAGS)) -shared --build-id -T ++ $(filter -E%,$(KBUILD_CFLAGS)) -shared --build-id --eh-frame-hdr -T + + # + # Shared build commands. +--- a/arch/loongarch/vdso/sigreturn.S ++++ b/arch/loongarch/vdso/sigreturn.S +@@ -12,13 +12,13 @@ + + #include + #include ++#include + + .section .text +- .cfi_sections .debug_frame + +-SYM_FUNC_START(__vdso_rt_sigreturn) ++SYM_SIGFUNC_START(__vdso_rt_sigreturn) + + li.w a7, __NR_rt_sigreturn + syscall 0 + +-SYM_FUNC_END(__vdso_rt_sigreturn) ++SYM_SIGFUNC_END(__vdso_rt_sigreturn) diff --git a/queue-6.19/loongarch-workaround-ls2k-ls7a-gpu-dma-hang-bug.patch b/queue-6.19/loongarch-workaround-ls2k-ls7a-gpu-dma-hang-bug.patch new file mode 100644 index 0000000000..7c7cc8bff8 --- /dev/null +++ b/queue-6.19/loongarch-workaround-ls2k-ls7a-gpu-dma-hang-bug.patch @@ -0,0 +1,131 @@ +From 95db0c9f526d583634cddb2e5914718570fbac87 Mon Sep 17 00:00:00 2001 +From: Huacai Chen +Date: Thu, 26 Mar 2026 14:29:09 +0800 +Subject: LoongArch: Workaround LS2K/LS7A GPU DMA hang bug + +From: Huacai Chen + +commit 95db0c9f526d583634cddb2e5914718570fbac87 upstream. + +1. Hardware limitation: GPU, DC and VPU are typically PCI device 06.0, +06.1 and 06.2. They share some hardware resources, so when configure the +PCI 06.0 device BAR1, DMA memory access cannot be performed through this +BAR, otherwise it will cause hardware abnormalities. + +2. In typical scenarios of reboot or S3/S4, DC access to memory through +BAR is not prohibited, resulting in GPU DMA hangs. + +3. Workaround method: When configuring the 06.0 device BAR1, turn off +the memory access of DC, GPU and VPU (via DC's CRTC registers). + +Cc: stable@vger.kernel.org +Signed-off-by: Qianhai Wu +Signed-off-by: Huacai Chen +Signed-off-by: Greg Kroah-Hartman +--- + arch/loongarch/pci/pci.c | 80 +++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 80 insertions(+) + +--- a/arch/loongarch/pci/pci.c ++++ b/arch/loongarch/pci/pci.c +@@ -5,9 +5,11 @@ + #include + #include + #include ++#include + #include + #include + #include ++#include + #include + #include + +@@ -15,6 +17,9 @@ + #define PCI_DEVICE_ID_LOONGSON_DC1 0x7a06 + #define PCI_DEVICE_ID_LOONGSON_DC2 0x7a36 + #define PCI_DEVICE_ID_LOONGSON_DC3 0x7a46 ++#define PCI_DEVICE_ID_LOONGSON_GPU1 0x7a15 ++#define PCI_DEVICE_ID_LOONGSON_GPU2 0x7a25 ++#define PCI_DEVICE_ID_LOONGSON_GPU3 0x7a35 + + int raw_pci_read(unsigned int domain, unsigned int bus, unsigned int devfn, + int reg, int len, u32 *val) +@@ -99,3 +104,78 @@ static void pci_fixup_vgadev(struct pci_ + DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_LOONGSON, PCI_DEVICE_ID_LOONGSON_DC1, pci_fixup_vgadev); + DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_LOONGSON, PCI_DEVICE_ID_LOONGSON_DC2, pci_fixup_vgadev); + DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_LOONGSON, PCI_DEVICE_ID_LOONGSON_DC3, pci_fixup_vgadev); ++ ++#define CRTC_NUM_MAX 2 ++#define CRTC_OUTPUT_ENABLE 0x100 ++ ++static void loongson_gpu_fixup_dma_hang(struct pci_dev *pdev, bool on) ++{ ++ u32 i, val, count, crtc_offset, device; ++ void __iomem *crtc_reg, *base, *regbase; ++ static u32 crtc_status[CRTC_NUM_MAX] = { 0 }; ++ ++ base = pdev->bus->ops->map_bus(pdev->bus, pdev->devfn + 1, 0); ++ device = readw(base + PCI_DEVICE_ID); ++ ++ regbase = ioremap(readq(base + PCI_BASE_ADDRESS_0) & ~0xffull, SZ_64K); ++ if (!regbase) { ++ pci_err(pdev, "Failed to ioremap()\n"); ++ return; ++ } ++ ++ switch (device) { ++ case PCI_DEVICE_ID_LOONGSON_DC2: ++ crtc_reg = regbase + 0x1240; ++ crtc_offset = 0x10; ++ break; ++ case PCI_DEVICE_ID_LOONGSON_DC3: ++ crtc_reg = regbase; ++ crtc_offset = 0x400; ++ break; ++ } ++ ++ for (i = 0; i < CRTC_NUM_MAX; i++, crtc_reg += crtc_offset) { ++ val = readl(crtc_reg); ++ ++ if (!on) ++ crtc_status[i] = val; ++ ++ /* No need to fixup if the status is off at startup. */ ++ if (!(crtc_status[i] & CRTC_OUTPUT_ENABLE)) ++ continue; ++ ++ if (on) ++ val |= CRTC_OUTPUT_ENABLE; ++ else ++ val &= ~CRTC_OUTPUT_ENABLE; ++ ++ mb(); ++ writel(val, crtc_reg); ++ ++ for (count = 0; count < 40; count++) { ++ val = readl(crtc_reg) & CRTC_OUTPUT_ENABLE; ++ if ((on && val) || (!on && !val)) ++ break; ++ udelay(1000); ++ } ++ ++ pci_info(pdev, "DMA hang fixup at reg[0x%lx]: 0x%x\n", ++ (unsigned long)crtc_reg & 0xffff, readl(crtc_reg)); ++ } ++ ++ iounmap(regbase); ++} ++ ++static void pci_fixup_dma_hang_early(struct pci_dev *pdev) ++{ ++ loongson_gpu_fixup_dma_hang(pdev, false); ++} ++DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_LOONGSON, PCI_DEVICE_ID_LOONGSON_GPU2, pci_fixup_dma_hang_early); ++DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_LOONGSON, PCI_DEVICE_ID_LOONGSON_GPU3, pci_fixup_dma_hang_early); ++ ++static void pci_fixup_dma_hang_final(struct pci_dev *pdev) ++{ ++ loongson_gpu_fixup_dma_hang(pdev, true); ++} ++DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_LOONGSON, PCI_DEVICE_ID_LOONGSON_GPU2, pci_fixup_dma_hang_final); ++DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_LOONGSON, PCI_DEVICE_ID_LOONGSON_GPU3, pci_fixup_dma_hang_final); diff --git a/queue-6.19/mm-damon-sysfs-check-contexts-nr-before-accessing-contexts_arr.patch b/queue-6.19/mm-damon-sysfs-check-contexts-nr-before-accessing-contexts_arr.patch new file mode 100644 index 0000000000..7a2fa5abd8 --- /dev/null +++ b/queue-6.19/mm-damon-sysfs-check-contexts-nr-before-accessing-contexts_arr.patch @@ -0,0 +1,58 @@ +From 1bfe9fb5ed2667fb075682408b776b5273162615 Mon Sep 17 00:00:00 2001 +From: Josh Law +Date: Sat, 21 Mar 2026 10:54:25 -0700 +Subject: mm/damon/sysfs: check contexts->nr before accessing contexts_arr[0] + +From: Josh Law + +commit 1bfe9fb5ed2667fb075682408b776b5273162615 upstream. + +Multiple sysfs command paths dereference contexts_arr[0] without first +verifying that kdamond->contexts->nr == 1. A user can set nr_contexts to +0 via sysfs while DAMON is running, causing NULL pointer dereferences. + +In more detail, the issue can be triggered by privileged users like +below. + +First, start DAMON and make contexts directory empty +(kdamond->contexts->nr == 0). + + # damo start + # cd /sys/kernel/mm/damon/admin/kdamonds/0 + # echo 0 > contexts/nr_contexts + +Then, each of below commands will cause the NULL pointer dereference. + + # echo update_schemes_stats > state + # echo update_schemes_tried_regions > state + # echo update_schemes_tried_bytes > state + # echo update_schemes_effective_quotas > state + # echo update_tuned_intervals > state + +Guard all commands (except OFF) at the entry point of +damon_sysfs_handle_cmd(). + +Link: https://lkml.kernel.org/r/20260321175427.86000-3-sj@kernel.org +Fixes: 0ac32b8affb5 ("mm/damon/sysfs: support DAMOS stats") +Signed-off-by: Josh Law +Reviewed-by: SeongJae Park +Signed-off-by: SeongJae Park +Cc: [5.18+] +Signed-off-by: Andrew Morton +Signed-off-by: Greg Kroah-Hartman +--- + mm/damon/sysfs.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/mm/damon/sysfs.c ++++ b/mm/damon/sysfs.c +@@ -1752,6 +1752,9 @@ static int damon_sysfs_update_schemes_tr + static int damon_sysfs_handle_cmd(enum damon_sysfs_cmd cmd, + struct damon_sysfs_kdamond *kdamond) + { ++ if (cmd != DAMON_SYSFS_CMD_OFF && kdamond->contexts->nr != 1) ++ return -EINVAL; ++ + switch (cmd) { + case DAMON_SYSFS_CMD_ON: + return damon_sysfs_turn_damon_on(kdamond); diff --git a/queue-6.19/mm-damon-sysfs-check-contexts-nr-in-repeat_call_fn.patch b/queue-6.19/mm-damon-sysfs-check-contexts-nr-in-repeat_call_fn.patch new file mode 100644 index 0000000000..09e458329f --- /dev/null +++ b/queue-6.19/mm-damon-sysfs-check-contexts-nr-in-repeat_call_fn.patch @@ -0,0 +1,52 @@ +From 6557004a8b59c7701e695f02be03c7e20ed1cc15 Mon Sep 17 00:00:00 2001 +From: Josh Law +Date: Sat, 21 Mar 2026 10:54:26 -0700 +Subject: mm/damon/sysfs: check contexts->nr in repeat_call_fn + +From: Josh Law + +commit 6557004a8b59c7701e695f02be03c7e20ed1cc15 upstream. + +damon_sysfs_repeat_call_fn() calls damon_sysfs_upd_tuned_intervals(), +damon_sysfs_upd_schemes_stats(), and +damon_sysfs_upd_schemes_effective_quotas() without checking contexts->nr. +If nr_contexts is set to 0 via sysfs while DAMON is running, these +functions dereference contexts_arr[0] and cause a NULL pointer +dereference. Add the missing check. + +For example, the issue can be reproduced using DAMON sysfs interface and +DAMON user-space tool (damo) [1] like below. + + $ sudo damo start --refresh_interval 1s + $ echo 0 | sudo tee \ + /sys/kernel/mm/damon/admin/kdamonds/0/contexts/nr_contexts + +Link: https://patch.msgid.link/20260320163559.178101-3-objecting@objecting.org +Link: https://lkml.kernel.org/r/20260321175427.86000-4-sj@kernel.org +Link: https://github.com/damonitor/damo [1] +Fixes: d809a7c64ba8 ("mm/damon/sysfs: implement refresh_ms file internal work") +Signed-off-by: Josh Law +Reviewed-by: SeongJae Park +Signed-off-by: SeongJae Park +Cc: [6.17+] +Signed-off-by: Andrew Morton +Signed-off-by: Greg Kroah-Hartman +--- + mm/damon/sysfs.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/mm/damon/sysfs.c ++++ b/mm/damon/sysfs.c +@@ -1622,9 +1622,12 @@ static int damon_sysfs_repeat_call_fn(vo + + if (!mutex_trylock(&damon_sysfs_lock)) + return 0; ++ if (sysfs_kdamond->contexts->nr != 1) ++ goto out; + damon_sysfs_upd_tuned_intervals(sysfs_kdamond); + damon_sysfs_upd_schemes_stats(sysfs_kdamond); + damon_sysfs_upd_schemes_effective_quotas(sysfs_kdamond); ++out: + mutex_unlock(&damon_sysfs_lock); + return 0; + } diff --git a/queue-6.19/mm-damon-sysfs-fix-param_ctx-leak-on-damon_sysfs_new_test_ctx-failure.patch b/queue-6.19/mm-damon-sysfs-fix-param_ctx-leak-on-damon_sysfs_new_test_ctx-failure.patch new file mode 100644 index 0000000000..049f0ddd44 --- /dev/null +++ b/queue-6.19/mm-damon-sysfs-fix-param_ctx-leak-on-damon_sysfs_new_test_ctx-failure.patch @@ -0,0 +1,50 @@ +From 7fe000eb32904758a85e62f6ea9483f89d5dabfc Mon Sep 17 00:00:00 2001 +From: Josh Law +Date: Sat, 21 Mar 2026 10:54:24 -0700 +Subject: mm/damon/sysfs: fix param_ctx leak on damon_sysfs_new_test_ctx() failure + +From: Josh Law + +commit 7fe000eb32904758a85e62f6ea9483f89d5dabfc upstream. + +Patch series "mm/damon/sysfs: fix memory leak and NULL dereference +issues", v4. + +DAMON_SYSFS can leak memory under allocation failure, and do NULL pointer +dereference when a privileged user make wrong sequences of control. Fix +those. + + +This patch (of 3): + +When damon_sysfs_new_test_ctx() fails in damon_sysfs_commit_input(), +param_ctx is leaked because the early return skips the cleanup at the out +label. Destroy param_ctx before returning. + +Link: https://lkml.kernel.org/r/20260321175427.86000-1-sj@kernel.org +Link: https://lkml.kernel.org/r/20260321175427.86000-2-sj@kernel.org +Fixes: f0c5118ebb0e ("mm/damon/sysfs: catch commit test ctx alloc failure") +Signed-off-by: Josh Law +Reviewed-by: SeongJae Park +Signed-off-by: SeongJae Park +Cc: [6.18+] +Signed-off-by: Andrew Morton +Signed-off-by: Greg Kroah-Hartman +--- + mm/damon/sysfs.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/mm/damon/sysfs.c ++++ b/mm/damon/sysfs.c +@@ -1526,8 +1526,10 @@ static int damon_sysfs_commit_input(void + if (IS_ERR(param_ctx)) + return PTR_ERR(param_ctx); + test_ctx = damon_sysfs_new_test_ctx(kdamond->damon_ctx); +- if (!test_ctx) ++ if (!test_ctx) { ++ damon_destroy_ctx(param_ctx); + return -ENOMEM; ++ } + err = damon_commit_ctx(test_ctx, param_ctx); + if (err) + goto out; diff --git a/queue-6.19/mm-huge_memory-fix-folio-isn-t-locked-in-softleaf_to_folio.patch b/queue-6.19/mm-huge_memory-fix-folio-isn-t-locked-in-softleaf_to_folio.patch new file mode 100644 index 0000000000..3cb1be88de --- /dev/null +++ b/queue-6.19/mm-huge_memory-fix-folio-isn-t-locked-in-softleaf_to_folio.patch @@ -0,0 +1,122 @@ +From 4c5e7f0fcd592801c9cc18f29f80fbee84eb8669 Mon Sep 17 00:00:00 2001 +From: Jinjiang Tu +Date: Thu, 19 Mar 2026 09:25:41 +0800 +Subject: mm/huge_memory: fix folio isn't locked in softleaf_to_folio() + +From: Jinjiang Tu + +commit 4c5e7f0fcd592801c9cc18f29f80fbee84eb8669 upstream. + +On arm64 server, we found folio that get from migration entry isn't locked +in softleaf_to_folio(). This issue triggers when mTHP splitting and +zap_nonpresent_ptes() races, and the root cause is lack of memory barrier +in softleaf_to_folio(). The race is as follows: + + CPU0 CPU1 + +deferred_split_scan() zap_nonpresent_ptes() + lock folio + split_folio() + unmap_folio() + change ptes to migration entries + __split_folio_to_order() softleaf_to_folio() + set flags(including PG_locked) for tail pages folio = pfn_folio(softleaf_to_pfn(entry)) + smp_wmb() VM_WARN_ON_ONCE(!folio_test_locked(folio)) + prep_compound_page() for tail pages + +In __split_folio_to_order(), smp_wmb() guarantees page flags of tail pages +are visible before the tail page becomes non-compound. smp_wmb() should +be paired with smp_rmb() in softleaf_to_folio(), which is missed. As a +result, if zap_nonpresent_ptes() accesses migration entry that stores tail +pfn, softleaf_to_folio() may see the updated compound_head of tail page +before page->flags. + +This issue will trigger VM_WARN_ON_ONCE() in pfn_swap_entry_folio() +because of the race between folio split and zap_nonpresent_ptes() +leading to a folio incorrectly undergoing modification without a folio +lock being held. + +This is a BUG_ON() before commit 93976a20345b ("mm: eliminate further +swapops predicates"), which in merged in v6.19-rc1. + +To fix it, add missing smp_rmb() if the softleaf entry is migration entry +in softleaf_to_folio() and softleaf_to_page(). + +[tujinjiang@huawei.com: update function name and comments] + Link: https://lkml.kernel.org/r/20260321075214.3305564-1-tujinjiang@huawei.com +Link: https://lkml.kernel.org/r/20260319012541.4158561-1-tujinjiang@huawei.com +Fixes: e9b61f19858a ("thp: reintroduce split_huge_page()") +Signed-off-by: Jinjiang Tu +Acked-by: David Hildenbrand (Arm) +Reviewed-by: Lorenzo Stoakes (Oracle) +Cc: Barry Song +Cc: Kefeng Wang +Cc: Liam Howlett +Cc: Michal Hocko +Cc: Mike Rapoport +Cc: Nanyong Sun +Cc: Ryan Roberts +Cc: Suren Baghdasaryan +Cc: Vlastimil Babka +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Greg Kroah-Hartman +--- + include/linux/leafops.h | 32 +++++++++++++++++++++----------- + 1 file changed, 21 insertions(+), 11 deletions(-) + +--- a/include/linux/leafops.h ++++ b/include/linux/leafops.h +@@ -363,6 +363,23 @@ static inline unsigned long softleaf_to_ + return swp_offset(entry) & SWP_PFN_MASK; + } + ++static inline void softleaf_migration_sync(softleaf_t entry, ++ struct folio *folio) ++{ ++ /* ++ * Ensure we do not race with split, which might alter tail pages into new ++ * folios and thus result in observing an unlocked folio. ++ * This matches the write barrier in __split_folio_to_order(). ++ */ ++ smp_rmb(); ++ ++ /* ++ * Any use of migration entries may only occur while the ++ * corresponding page is locked ++ */ ++ VM_WARN_ON_ONCE(!folio_test_locked(folio)); ++} ++ + /** + * softleaf_to_page() - Obtains struct page for PFN encoded within leaf entry. + * @entry: Leaf entry, softleaf_has_pfn(@entry) must return true. +@@ -374,11 +391,8 @@ static inline struct page *softleaf_to_p + struct page *page = pfn_to_page(softleaf_to_pfn(entry)); + + VM_WARN_ON_ONCE(!softleaf_has_pfn(entry)); +- /* +- * Any use of migration entries may only occur while the +- * corresponding page is locked +- */ +- VM_WARN_ON_ONCE(softleaf_is_migration(entry) && !PageLocked(page)); ++ if (softleaf_is_migration(entry)) ++ softleaf_migration_sync(entry, page_folio(page)); + + return page; + } +@@ -394,12 +408,8 @@ static inline struct folio *softleaf_to_ + struct folio *folio = pfn_folio(softleaf_to_pfn(entry)); + + VM_WARN_ON_ONCE(!softleaf_has_pfn(entry)); +- /* +- * Any use of migration entries may only occur while the +- * corresponding folio is locked. +- */ +- VM_WARN_ON_ONCE(softleaf_is_migration(entry) && +- !folio_test_locked(folio)); ++ if (softleaf_is_migration(entry)) ++ softleaf_migration_sync(entry, folio); + + return folio; + } diff --git a/queue-6.19/mm-memory-fix-pmd-pud-checks-in-follow_pfnmap_start.patch b/queue-6.19/mm-memory-fix-pmd-pud-checks-in-follow_pfnmap_start.patch new file mode 100644 index 0000000000..f3f8f22b48 --- /dev/null +++ b/queue-6.19/mm-memory-fix-pmd-pud-checks-in-follow_pfnmap_start.patch @@ -0,0 +1,99 @@ +From ffef67b93aa352b34e6aeba3d52c19a63885409a Mon Sep 17 00:00:00 2001 +From: "David Hildenbrand (Arm)" +Date: Mon, 23 Mar 2026 21:20:18 +0100 +Subject: mm/memory: fix PMD/PUD checks in follow_pfnmap_start() + +From: David Hildenbrand (Arm) + +commit ffef67b93aa352b34e6aeba3d52c19a63885409a upstream. + +follow_pfnmap_start() suffers from two problems: + +(1) We are not re-fetching the pmd/pud after taking the PTL + +Therefore, we are not properly stabilizing what the lock actually +protects. If there is concurrent zapping, we would indicate to the +caller that we found an entry, however, that entry might already have +been invalidated, or contain a different PFN after taking the lock. + +Properly use pmdp_get() / pudp_get() after taking the lock. + +(2) pmd_leaf() / pud_leaf() are not well defined on non-present entries + +pmd_leaf()/pud_leaf() could wrongly trigger on non-present entries. + +There is no real guarantee that pmd_leaf()/pud_leaf() returns something +reasonable on non-present entries. Most architectures indeed either +perform a present check or make it work by smart use of flags. + +However, for example loongarch checks the _PAGE_HUGE flag in pmd_leaf(), +and always sets the _PAGE_HUGE flag in __swp_entry_to_pmd(). Whereby +pmd_trans_huge() explicitly checks pmd_present(), pmd_leaf() does not do +that. + +Let's check pmd_present()/pud_present() before assuming "the is a present +PMD leaf" when spotting pmd_leaf()/pud_leaf(), like other page table +handling code that traverses user page tables does. + +Given that non-present PMD entries are likely rare in VM_IO|VM_PFNMAP, (1) +is likely more relevant than (2). It is questionable how often (1) would +actually trigger, but let's CC stable to be sure. + +This was found by code inspection. + +Link: https://lkml.kernel.org/r/20260323-follow_pfnmap_fix-v1-1-5b0ec10872b3@kernel.org +Fixes: 6da8e9634bb7 ("mm: new follow_pfnmap API") +Signed-off-by: David Hildenbrand (Arm) +Acked-by: Mike Rapoport (Microsoft) +Reviewed-by: Lorenzo Stoakes (Oracle) +Cc: Liam Howlett +Cc: Michal Hocko +Cc: Peter Xu +Cc: Suren Baghdasaryan +Cc: Vlastimil Babka +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Greg Kroah-Hartman +--- + mm/memory.c | 18 +++++++++++++++--- + 1 file changed, 15 insertions(+), 3 deletions(-) + +--- a/mm/memory.c ++++ b/mm/memory.c +@@ -6775,11 +6775,16 @@ retry: + + pudp = pud_offset(p4dp, address); + pud = pudp_get(pudp); +- if (pud_none(pud)) ++ if (!pud_present(pud)) + goto out; + if (pud_leaf(pud)) { + lock = pud_lock(mm, pudp); +- if (!unlikely(pud_leaf(pud))) { ++ pud = pudp_get(pudp); ++ ++ if (unlikely(!pud_present(pud))) { ++ spin_unlock(lock); ++ goto out; ++ } else if (unlikely(!pud_leaf(pud))) { + spin_unlock(lock); + goto retry; + } +@@ -6791,9 +6796,16 @@ retry: + + pmdp = pmd_offset(pudp, address); + pmd = pmdp_get_lockless(pmdp); ++ if (!pmd_present(pmd)) ++ goto out; + if (pmd_leaf(pmd)) { + lock = pmd_lock(mm, pmdp); +- if (!unlikely(pmd_leaf(pmd))) { ++ pmd = pmdp_get(pmdp); ++ ++ if (unlikely(!pmd_present(pmd))) { ++ spin_unlock(lock); ++ goto out; ++ } else if (unlikely(!pmd_leaf(pmd))) { + spin_unlock(lock); + goto retry; + } diff --git a/queue-6.19/mm-mseal-update-vma-end-correctly-on-merge.patch b/queue-6.19/mm-mseal-update-vma-end-correctly-on-merge.patch new file mode 100644 index 0000000000..d8f42baa70 --- /dev/null +++ b/queue-6.19/mm-mseal-update-vma-end-correctly-on-merge.patch @@ -0,0 +1,70 @@ +From 2697dd8ae721db4f6a53d4f4cbd438212a80f8dc Mon Sep 17 00:00:00 2001 +From: "Lorenzo Stoakes (Oracle)" +Date: Fri, 27 Mar 2026 17:31:04 +0000 +Subject: mm/mseal: update VMA end correctly on merge + +From: Lorenzo Stoakes (Oracle) + +commit 2697dd8ae721db4f6a53d4f4cbd438212a80f8dc upstream. + +Previously we stored the end of the current VMA in curr_end, and then upon +iterating to the next VMA updated curr_start to curr_end to advance to the +next VMA. + +However, this doesn't take into account the fact that a VMA might be +updated due to a merge by vma_modify_flags(), which can result in curr_end +being stale and thus, upon setting curr_start to curr_end, ending up with +an incorrect curr_start on the next iteration. + +Resolve the issue by setting curr_end to vma->vm_end unconditionally to +ensure this value remains updated should this occur. + +While we're here, eliminate this entire class of bug by simply setting +const curr_[start/end] to be clamped to the input range and VMAs, which +also happens to simplify the logic. + +Link: https://lkml.kernel.org/r/20260327173104.322405-1-ljs@kernel.org +Fixes: 6c2da14ae1e0 ("mm/mseal: rework mseal apply logic") +Signed-off-by: Lorenzo Stoakes (Oracle) +Reported-by: Antonius +Closes: https://lore.kernel.org/linux-mm/CAK8a0jwWGj9-SgFk0yKFh7i8jMkwKm5b0ao9=kmXWjO54veX2g@mail.gmail.com/ +Suggested-by: David Hildenbrand (ARM) +Acked-by: Vlastimil Babka (SUSE) +Reviewed-by: Pedro Falcato +Acked-by: David Hildenbrand (Arm) +Cc: Jann Horn +Cc: Jeff Xu +Cc: Liam Howlett +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Greg Kroah-Hartman +--- + mm/mseal.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +--- a/mm/mseal.c ++++ b/mm/mseal.c +@@ -56,7 +56,6 @@ static int mseal_apply(struct mm_struct + unsigned long start, unsigned long end) + { + struct vm_area_struct *vma, *prev; +- unsigned long curr_start = start; + VMA_ITERATOR(vmi, mm, start); + + /* We know there are no gaps so this will be non-NULL. */ +@@ -66,6 +65,7 @@ static int mseal_apply(struct mm_struct + prev = vma; + + for_each_vma_range(vmi, vma, end) { ++ const unsigned long curr_start = MAX(vma->vm_start, start); + const unsigned long curr_end = MIN(vma->vm_end, end); + + if (!(vma->vm_flags & VM_SEALED)) { +@@ -79,7 +79,6 @@ static int mseal_apply(struct mm_struct + } + + prev = vma; +- curr_start = curr_end; + } + + return 0; diff --git a/queue-6.19/mm-pagewalk-fix-race-between-concurrent-split-and-refault.patch b/queue-6.19/mm-pagewalk-fix-race-between-concurrent-split-and-refault.patch new file mode 100644 index 0000000000..e7f79106eb --- /dev/null +++ b/queue-6.19/mm-pagewalk-fix-race-between-concurrent-split-and-refault.patch @@ -0,0 +1,151 @@ +From 3b89863c3fa482912911cd65a12a3aeef662c250 Mon Sep 17 00:00:00 2001 +From: Max Boone +Date: Wed, 25 Mar 2026 10:59:16 +0100 +Subject: mm/pagewalk: fix race between concurrent split and refault + +From: Max Boone + +commit 3b89863c3fa482912911cd65a12a3aeef662c250 upstream. + +The splitting of a PUD entry in walk_pud_range() can race with a +concurrent thread refaulting the PUD leaf entry causing it to try walking +a PMD range that has disappeared. + +An example and reproduction of this is to try reading numa_maps of a +process while VFIO-PCI is setting up DMA (specifically the +vfio_pin_pages_remote call) on a large BAR for that process. + +This will trigger a kernel BUG: +vfio-pci 0000:03:00.0: enabling device (0000 -> 0002) +BUG: unable to handle page fault for address: ffffa23980000000 +PGD 0 P4D 0 +Oops: Oops: 0000 [#1] SMP NOPTI +... +RIP: 0010:walk_pgd_range+0x3b5/0x7a0 +Code: 8d 43 ff 48 89 44 24 28 4d 89 ce 4d 8d a7 00 00 20 00 48 8b 4c 24 +28 49 81 e4 00 00 e0 ff 49 8d 44 24 ff 48 39 c8 4c 0f 43 e3 <49> f7 06 + 9f ff ff ff 75 3b 48 8b 44 24 20 48 8b 40 28 48 85 c0 74 +RSP: 0018:ffffac23e1ecf808 EFLAGS: 00010287 +RAX: 00007f44c01fffff RBX: 00007f4500000000 RCX: 00007f44ffffffff +RDX: 0000000000000000 RSI: 000ffffffffff000 RDI: ffffffff93378fe0 +RBP: ffffac23e1ecf918 R08: 0000000000000004 R09: ffffa23980000000 +R10: 0000000000000020 R11: 0000000000000004 R12: 00007f44c0200000 +R13: 00007f44c0000000 R14: ffffa23980000000 R15: 00007f44c0000000 +FS: 00007fe884739580(0000) GS:ffff9b7d7a9c0000(0000) +knlGS:0000000000000000 +CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +CR2: ffffa23980000000 CR3: 000000c0650e2005 CR4: 0000000000770ef0 +PKRU: 55555554 +Call Trace: + + __walk_page_range+0x195/0x1b0 + walk_page_vma+0x62/0xc0 + show_numa_map+0x12b/0x3b0 + seq_read_iter+0x297/0x440 + seq_read+0x11d/0x140 + vfs_read+0xc2/0x340 + ksys_read+0x5f/0xe0 + do_syscall_64+0x68/0x130 + ? get_page_from_freelist+0x5c2/0x17e0 + ? mas_store_prealloc+0x17e/0x360 + ? vma_set_page_prot+0x4c/0xa0 + ? __alloc_pages_noprof+0x14e/0x2d0 + ? __mod_memcg_lruvec_state+0x8d/0x140 + ? __lruvec_stat_mod_folio+0x76/0xb0 + ? __folio_mod_stat+0x26/0x80 + ? do_anonymous_page+0x705/0x900 + ? __handle_mm_fault+0xa8d/0x1000 + ? __count_memcg_events+0x53/0xf0 + ? handle_mm_fault+0xa5/0x360 + ? do_user_addr_fault+0x342/0x640 + ? arch_exit_to_user_mode_prepare.constprop.0+0x16/0xa0 + ? irqentry_exit_to_user_mode+0x24/0x100 + entry_SYSCALL_64_after_hwframe+0x76/0x7e +RIP: 0033:0x7fe88464f47e +Code: c0 e9 b6 fe ff ff 50 48 8d 3d be 07 0b 00 e8 69 01 02 00 66 0f 1f +84 00 00 00 00 00 64 8b 04 25 18 00 00 00 85 c0 75 14 0f 05 <48> 3d 00 + f0 ff ff 77 5a c3 66 0f 1f 84 00 00 00 00 00 48 83 ec 28 +RSP: 002b:00007ffe6cd9a9b8 EFLAGS: 00000246 ORIG_RAX: 0000000000000000 +RAX: ffffffffffffffda RBX: 0000000000020000 RCX: 00007fe88464f47e +RDX: 0000000000020000 RSI: 00007fe884543000 RDI: 0000000000000003 +RBP: 00007fe884543000 R08: 00007fe884542010 R09: 0000000000000000 +R10: fffffffffffffbc5 R11: 0000000000000246 R12: 0000000000000000 +R13: 0000000000000003 R14: 0000000000020000 R15: 0000000000020000 + + +Fix this by validating the PUD entry in walk_pmd_range() using a stable +snapshot (pudp_get()). If the PUD is not present or is a leaf, retry the +walk via ACTION_AGAIN instead of descending further. This mirrors the +retry logic in walk_pte_range(), which lets walk_pmd_range() retry if the +PTE is not being got by pte_offset_map_lock(). + +Link: https://lkml.kernel.org/r/20260325-pagewalk-check-pmd-refault-v2-1-707bff33bc60@akamai.com +Fixes: f9e54c3a2f5b ("vfio/pci: implement huge_fault support") +Co-developed-by: David Hildenbrand (Arm) +Signed-off-by: David Hildenbrand (Arm) +Signed-off-by: Max Boone +Acked-by: David Hildenbrand (Arm) +Cc: Liam Howlett +Cc: Lorenzo Stoakes (Oracle) +Cc: Michal Hocko +Cc: Mike Rapoport +Cc: Suren Baghdasaryan +Cc: Vlastimil Babka +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Greg Kroah-Hartman +--- + mm/pagewalk.c | 25 ++++++++++++++++++++++--- + 1 file changed, 22 insertions(+), 3 deletions(-) + +--- a/mm/pagewalk.c ++++ b/mm/pagewalk.c +@@ -97,6 +97,7 @@ static int walk_pte_range(pmd_t *pmd, un + static int walk_pmd_range(pud_t *pud, unsigned long addr, unsigned long end, + struct mm_walk *walk) + { ++ pud_t pudval = pudp_get(pud); + pmd_t *pmd; + unsigned long next; + const struct mm_walk_ops *ops = walk->ops; +@@ -105,6 +106,24 @@ static int walk_pmd_range(pud_t *pud, un + int err = 0; + int depth = real_depth(3); + ++ /* ++ * For PTE handling, pte_offset_map_lock() takes care of checking ++ * whether there actually is a page table. But it also has to be ++ * very careful about concurrent page table reclaim. ++ * ++ * Similarly, we have to be careful here - a PUD entry that points ++ * to a PMD table cannot go away, so we can just walk it. But if ++ * it's something else, we need to ensure we didn't race something, ++ * so need to retry. ++ * ++ * A pertinent example of this is a PUD refault after PUD split - ++ * we will need to split again or risk accessing invalid memory. ++ */ ++ if (!pud_present(pudval) || pud_leaf(pudval)) { ++ walk->action = ACTION_AGAIN; ++ return 0; ++ } ++ + pmd = pmd_offset(pud, addr); + do { + again: +@@ -218,12 +237,12 @@ static int walk_pud_range(p4d_t *p4d, un + else if (pud_leaf(*pud) || !pud_present(*pud)) + continue; /* Nothing to do. */ + +- if (pud_none(*pud)) +- goto again; +- + err = walk_pmd_range(pud, addr, next, walk); + if (err) + break; ++ ++ if (walk->action == ACTION_AGAIN) ++ goto again; + } while (pud++, addr = next, addr != end); + + return err; diff --git a/queue-6.19/net-macb-move-devm_-free-request-_irq-out-of-spin-lock-area.patch b/queue-6.19/net-macb-move-devm_-free-request-_irq-out-of-spin-lock-area.patch new file mode 100644 index 0000000000..5a15376cf7 --- /dev/null +++ b/queue-6.19/net-macb-move-devm_-free-request-_irq-out-of-spin-lock-area.patch @@ -0,0 +1,144 @@ +From 317e49358ebbf6390fa439ef3c142f9239dd25fb Mon Sep 17 00:00:00 2001 +From: Kevin Hao +Date: Wed, 18 Mar 2026 14:36:58 +0800 +Subject: net: macb: Move devm_{free,request}_irq() out of spin lock area +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Kevin Hao + +commit 317e49358ebbf6390fa439ef3c142f9239dd25fb upstream. + +The devm_free_irq() and devm_request_irq() functions should not be +executed in an atomic context. + +During device suspend, all userspace processes and most kernel threads +are frozen. Additionally, we flush all tx/rx status, disable all macb +interrupts, and halt rx operations. Therefore, it is safe to split the +region protected by bp->lock into two independent sections, allowing +devm_free_irq() and devm_request_irq() to run in a non-atomic context. +This modification resolves the following lockdep warning: + BUG: sleeping function called from invalid context at kernel/locking/mutex.c:591 + in_atomic(): 1, irqs_disabled(): 1, non_block: 0, pid: 501, name: rtcwake + preempt_count: 1, expected: 0 + RCU nest depth: 1, expected: 0 + 7 locks held by rtcwake/501: + #0: ffff0008038c3408 (sb_writers#5){.+.+}-{0:0}, at: vfs_write+0xf8/0x368 + #1: ffff0008049a5e88 (&of->mutex#2){+.+.}-{4:4}, at: kernfs_fop_write_iter+0xbc/0x1c8 + #2: ffff00080098d588 (kn->active#70){.+.+}-{0:0}, at: kernfs_fop_write_iter+0xcc/0x1c8 + #3: ffff800081c84888 (system_transition_mutex){+.+.}-{4:4}, at: pm_suspend+0x1ec/0x290 + #4: ffff0008009ba0f8 (&dev->mutex){....}-{4:4}, at: device_suspend+0x118/0x4f0 + #5: ffff800081d00458 (rcu_read_lock){....}-{1:3}, at: rcu_lock_acquire+0x4/0x48 + #6: ffff0008031fb9e0 (&bp->lock){-.-.}-{3:3}, at: macb_suspend+0x144/0x558 + irq event stamp: 8682 + hardirqs last enabled at (8681): [] _raw_spin_unlock_irqrestore+0x44/0x88 + hardirqs last disabled at (8682): [] _raw_spin_lock_irqsave+0x38/0x98 + softirqs last enabled at (7322): [] handle_softirqs+0x52c/0x588 + softirqs last disabled at (7317): [] __do_softirq+0x20/0x2c + CPU: 1 UID: 0 PID: 501 Comm: rtcwake Not tainted 7.0.0-rc3-next-20260310-yocto-standard+ #125 PREEMPT + Hardware name: ZynqMP ZCU102 Rev1.1 (DT) + Call trace: + show_stack+0x24/0x38 (C) + __dump_stack+0x28/0x38 + dump_stack_lvl+0x64/0x88 + dump_stack+0x18/0x24 + __might_resched+0x200/0x218 + __might_sleep+0x38/0x98 + __mutex_lock_common+0x7c/0x1378 + mutex_lock_nested+0x38/0x50 + free_irq+0x68/0x2b0 + devm_irq_release+0x24/0x38 + devres_release+0x40/0x80 + devm_free_irq+0x48/0x88 + macb_suspend+0x298/0x558 + device_suspend+0x218/0x4f0 + dpm_suspend+0x244/0x3a0 + dpm_suspend_start+0x50/0x78 + suspend_devices_and_enter+0xec/0x560 + pm_suspend+0x194/0x290 + state_store+0x110/0x158 + kobj_attr_store+0x1c/0x30 + sysfs_kf_write+0xa8/0xd0 + kernfs_fop_write_iter+0x11c/0x1c8 + vfs_write+0x248/0x368 + ksys_write+0x7c/0xf8 + __arm64_sys_write+0x28/0x40 + invoke_syscall+0x4c/0xe8 + el0_svc_common+0x98/0xf0 + do_el0_svc+0x28/0x40 + el0_svc+0x54/0x1e0 + el0t_64_sync_handler+0x84/0x130 + el0t_64_sync+0x198/0x1a0 + +Fixes: 558e35ccfe95 ("net: macb: WoL support for GEM type of Ethernet controller") +Cc: stable@vger.kernel.org +Reviewed-by: Théo Lebrun +Signed-off-by: Kevin Hao +Link: https://patch.msgid.link/20260318-macb-irq-v2-1-f1179768ab24@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/ethernet/cadence/macb_main.c | 12 +++++++----- + 1 file changed, 7 insertions(+), 5 deletions(-) + +--- a/drivers/net/ethernet/cadence/macb_main.c ++++ b/drivers/net/ethernet/cadence/macb_main.c +@@ -5832,6 +5832,7 @@ static int __maybe_unused macb_suspend(s + /* write IP address into register */ + tmp |= MACB_BFEXT(IP, be32_to_cpu(ifa->ifa_local)); + } ++ spin_unlock_irqrestore(&bp->lock, flags); + + /* Change interrupt handler and + * Enable WoL IRQ on queue 0 +@@ -5844,11 +5845,12 @@ static int __maybe_unused macb_suspend(s + dev_err(dev, + "Unable to request IRQ %d (error %d)\n", + bp->queues[0].irq, err); +- spin_unlock_irqrestore(&bp->lock, flags); + return err; + } ++ spin_lock_irqsave(&bp->lock, flags); + queue_writel(bp->queues, IER, GEM_BIT(WOL)); + gem_writel(bp, WOL, tmp); ++ spin_unlock_irqrestore(&bp->lock, flags); + } else { + err = devm_request_irq(dev, bp->queues[0].irq, macb_wol_interrupt, + IRQF_SHARED, netdev->name, bp->queues); +@@ -5856,13 +5858,13 @@ static int __maybe_unused macb_suspend(s + dev_err(dev, + "Unable to request IRQ %d (error %d)\n", + bp->queues[0].irq, err); +- spin_unlock_irqrestore(&bp->lock, flags); + return err; + } ++ spin_lock_irqsave(&bp->lock, flags); + queue_writel(bp->queues, IER, MACB_BIT(WOL)); + macb_writel(bp, WOL, tmp); ++ spin_unlock_irqrestore(&bp->lock, flags); + } +- spin_unlock_irqrestore(&bp->lock, flags); + + enable_irq_wake(bp->queues[0].irq); + } +@@ -5929,6 +5931,8 @@ static int __maybe_unused macb_resume(st + queue_readl(bp->queues, ISR); + if (bp->caps & MACB_CAPS_ISR_CLEAR_ON_WRITE) + queue_writel(bp->queues, ISR, -1); ++ spin_unlock_irqrestore(&bp->lock, flags); ++ + /* Replace interrupt handler on queue 0 */ + devm_free_irq(dev, bp->queues[0].irq, bp->queues); + err = devm_request_irq(dev, bp->queues[0].irq, macb_interrupt, +@@ -5937,10 +5941,8 @@ static int __maybe_unused macb_resume(st + dev_err(dev, + "Unable to request IRQ %d (error %d)\n", + bp->queues[0].irq, err); +- spin_unlock_irqrestore(&bp->lock, flags); + return err; + } +- spin_unlock_irqrestore(&bp->lock, flags); + + disable_irq_wake(bp->queues[0].irq); + diff --git a/queue-6.19/net-macb-protect-access-to-net_device-ip_ptr-with-rcu-lock.patch b/queue-6.19/net-macb-protect-access-to-net_device-ip_ptr-with-rcu-lock.patch new file mode 100644 index 0000000000..2a74b59f80 --- /dev/null +++ b/queue-6.19/net-macb-protect-access-to-net_device-ip_ptr-with-rcu-lock.patch @@ -0,0 +1,125 @@ +From baa35a698cea26930679a20a7550bbb4c8319725 Mon Sep 17 00:00:00 2001 +From: Kevin Hao +Date: Wed, 18 Mar 2026 14:36:59 +0800 +Subject: net: macb: Protect access to net_device::ip_ptr with RCU lock +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Kevin Hao + +commit baa35a698cea26930679a20a7550bbb4c8319725 upstream. + +Access to net_device::ip_ptr and its associated members must be +protected by an RCU lock. Since we are modifying this piece of code, +let's also move it to execute only when WAKE_ARP is enabled. + +To minimize the duration of the RCU lock, a local variable is used to +temporarily store the IP address. This change resolves the following +RCU check warning: + WARNING: suspicious RCU usage + 7.0.0-rc3-next-20260310-yocto-standard+ #122 Not tainted + ----------------------------- + drivers/net/ethernet/cadence/macb_main.c:5944 suspicious rcu_dereference_check() usage! + + other info that might help us debug this: + + rcu_scheduler_active = 2, debug_locks = 1 + 5 locks held by rtcwake/518: + #0: ffff000803ab1408 (sb_writers#5){.+.+}-{0:0}, at: vfs_write+0xf8/0x368 + #1: ffff0008090bf088 (&of->mutex#2){+.+.}-{4:4}, at: kernfs_fop_write_iter+0xbc/0x1c8 + #2: ffff00080098d588 (kn->active#70){.+.+}-{0:0}, at: kernfs_fop_write_iter+0xcc/0x1c8 + #3: ffff800081c84888 (system_transition_mutex){+.+.}-{4:4}, at: pm_suspend+0x1ec/0x290 + #4: ffff0008009ba0f8 (&dev->mutex){....}-{4:4}, at: device_suspend+0x118/0x4f0 + + stack backtrace: + CPU: 3 UID: 0 PID: 518 Comm: rtcwake Not tainted 7.0.0-rc3-next-20260310-yocto-standard+ #122 PREEMPT + Hardware name: ZynqMP ZCU102 Rev1.1 (DT) + Call trace: + show_stack+0x24/0x38 (C) + __dump_stack+0x28/0x38 + dump_stack_lvl+0x64/0x88 + dump_stack+0x18/0x24 + lockdep_rcu_suspicious+0x134/0x1d8 + macb_suspend+0xd8/0x4c0 + device_suspend+0x218/0x4f0 + dpm_suspend+0x244/0x3a0 + dpm_suspend_start+0x50/0x78 + suspend_devices_and_enter+0xec/0x560 + pm_suspend+0x194/0x290 + state_store+0x110/0x158 + kobj_attr_store+0x1c/0x30 + sysfs_kf_write+0xa8/0xd0 + kernfs_fop_write_iter+0x11c/0x1c8 + vfs_write+0x248/0x368 + ksys_write+0x7c/0xf8 + __arm64_sys_write+0x28/0x40 + invoke_syscall+0x4c/0xe8 + el0_svc_common+0x98/0xf0 + do_el0_svc+0x28/0x40 + el0_svc+0x54/0x1e0 + el0t_64_sync_handler+0x84/0x130 + el0t_64_sync+0x198/0x1a0 + +Fixes: 0cb8de39a776 ("net: macb: Add ARP support to WOL") +Signed-off-by: Kevin Hao +Cc: stable@vger.kernel.org +Reviewed-by: Théo Lebrun +Link: https://patch.msgid.link/20260318-macb-irq-v2-2-f1179768ab24@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/ethernet/cadence/macb_main.c | 25 ++++++++++++++++--------- + 1 file changed, 16 insertions(+), 9 deletions(-) + +--- a/drivers/net/ethernet/cadence/macb_main.c ++++ b/drivers/net/ethernet/cadence/macb_main.c +@@ -5773,9 +5773,9 @@ static int __maybe_unused macb_suspend(s + struct macb_queue *queue; + struct in_device *idev; + unsigned long flags; ++ u32 tmp, ifa_local; + unsigned int q; + int err; +- u32 tmp; + + if (!device_may_wakeup(&bp->dev->dev)) + phy_exit(bp->phy); +@@ -5784,14 +5784,21 @@ static int __maybe_unused macb_suspend(s + return 0; + + if (bp->wol & MACB_WOL_ENABLED) { +- /* Check for IP address in WOL ARP mode */ +- idev = __in_dev_get_rcu(bp->dev); +- if (idev) +- ifa = rcu_dereference(idev->ifa_list); +- if ((bp->wolopts & WAKE_ARP) && !ifa) { +- netdev_err(netdev, "IP address not assigned as required by WoL walk ARP\n"); +- return -EOPNOTSUPP; ++ if (bp->wolopts & WAKE_ARP) { ++ /* Check for IP address in WOL ARP mode */ ++ rcu_read_lock(); ++ idev = __in_dev_get_rcu(bp->dev); ++ if (idev) ++ ifa = rcu_dereference(idev->ifa_list); ++ if (!ifa) { ++ rcu_read_unlock(); ++ netdev_err(netdev, "IP address not assigned as required by WoL walk ARP\n"); ++ return -EOPNOTSUPP; ++ } ++ ifa_local = be32_to_cpu(ifa->ifa_local); ++ rcu_read_unlock(); + } ++ + spin_lock_irqsave(&bp->lock, flags); + + /* Disable Tx and Rx engines before disabling the queues, +@@ -5830,7 +5837,7 @@ static int __maybe_unused macb_suspend(s + if (bp->wolopts & WAKE_ARP) { + tmp |= MACB_BIT(ARP); + /* write IP address into register */ +- tmp |= MACB_BFEXT(IP, be32_to_cpu(ifa->ifa_local)); ++ tmp |= MACB_BFEXT(IP, ifa_local); + } + spin_unlock_irqrestore(&bp->lock, flags); + diff --git a/queue-6.19/net-macb-use-dev_consume_skb_any-to-free-tx-skbs.patch b/queue-6.19/net-macb-use-dev_consume_skb_any-to-free-tx-skbs.patch new file mode 100644 index 0000000000..fe6773c86e --- /dev/null +++ b/queue-6.19/net-macb-use-dev_consume_skb_any-to-free-tx-skbs.patch @@ -0,0 +1,73 @@ +From 647b8a2fe474474704110db6bd07f7a139e621eb Mon Sep 17 00:00:00 2001 +From: Kevin Hao +Date: Sat, 21 Mar 2026 22:04:41 +0800 +Subject: net: macb: Use dev_consume_skb_any() to free TX SKBs + +From: Kevin Hao + +commit 647b8a2fe474474704110db6bd07f7a139e621eb upstream. + +The napi_consume_skb() function is not intended to be called in an IRQ +disabled context. However, after commit 6bc8a5098bf4 ("net: macb: Fix +tx_ptr_lock locking"), the freeing of TX SKBs is performed with IRQs +disabled. To resolve the following call trace, use dev_consume_skb_any() +for freeing TX SKBs: + WARNING: kernel/softirq.c:430 at __local_bh_enable_ip+0x174/0x188, CPU#0: ksoftirqd/0/15 + Modules linked in: + CPU: 0 UID: 0 PID: 15 Comm: ksoftirqd/0 Not tainted 7.0.0-rc4-next-20260319-yocto-standard-dirty #37 PREEMPT + Hardware name: ZynqMP ZCU102 Rev1.1 (DT) + pstate: 200000c5 (nzCv daIF -PAN -UAO -TCO -DIT -SSBS BTYPE=--) + pc : __local_bh_enable_ip+0x174/0x188 + lr : local_bh_enable+0x24/0x38 + sp : ffff800082b3bb10 + x29: ffff800082b3bb10 x28: ffff0008031f3c00 x27: 000000000011ede0 + x26: ffff000800a7ff00 x25: ffff800083937ce8 x24: 0000000000017a80 + x23: ffff000803243a78 x22: 0000000000000040 x21: 0000000000000000 + x20: ffff000800394c80 x19: 0000000000000200 x18: 0000000000000001 + x17: 0000000000000001 x16: ffff000803240000 x15: 0000000000000000 + x14: ffffffffffffffff x13: 0000000000000028 x12: ffff000800395650 + x11: ffff8000821d1528 x10: ffff800081c2bc08 x9 : ffff800081c1e258 + x8 : 0000000100000301 x7 : ffff8000810426ec x6 : 0000000000000000 + x5 : 0000000000000001 x4 : 0000000000000001 x3 : 0000000000000000 + x2 : 0000000000000008 x1 : 0000000000000200 x0 : ffff8000810428dc + Call trace: + __local_bh_enable_ip+0x174/0x188 (P) + local_bh_enable+0x24/0x38 + skb_attempt_defer_free+0x190/0x1d8 + napi_consume_skb+0x58/0x108 + macb_tx_poll+0x1a4/0x558 + __napi_poll+0x50/0x198 + net_rx_action+0x1f4/0x3d8 + handle_softirqs+0x16c/0x560 + run_ksoftirqd+0x44/0x80 + smpboot_thread_fn+0x1d8/0x338 + kthread+0x120/0x150 + ret_from_fork+0x10/0x20 + irq event stamp: 29751 + hardirqs last enabled at (29750): [] _raw_spin_unlock_irqrestore+0x44/0x88 + hardirqs last disabled at (29751): [] _raw_spin_lock_irqsave+0x38/0x98 + softirqs last enabled at (29150): [] handle_softirqs+0x504/0x560 + softirqs last disabled at (29153): [] run_ksoftirqd+0x44/0x80 + +Fixes: 6bc8a5098bf4 ("net: macb: Fix tx_ptr_lock locking") +Signed-off-by: Kevin Hao +Cc: stable@vger.kernel.org +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20260321-macb-tx-v1-1-b383a58dd4e6@gmail.com +Signed-off-by: Paolo Abeni +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/ethernet/cadence/macb_main.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/ethernet/cadence/macb_main.c ++++ b/drivers/net/ethernet/cadence/macb_main.c +@@ -1071,7 +1071,7 @@ static void macb_tx_unmap(struct macb *b + } + + if (tx_skb->skb) { +- napi_consume_skb(tx_skb->skb, budget); ++ dev_consume_skb_any(tx_skb->skb); + tx_skb->skb = NULL; + } + } diff --git a/queue-6.19/ovl-fix-wrong-detection-of-32bit-inode-numbers.patch b/queue-6.19/ovl-fix-wrong-detection-of-32bit-inode-numbers.patch new file mode 100644 index 0000000000..cc2e71c607 --- /dev/null +++ b/queue-6.19/ovl-fix-wrong-detection-of-32bit-inode-numbers.patch @@ -0,0 +1,43 @@ +From 53a7c171e9dd833f0a96b545adcb89bd57387239 Mon Sep 17 00:00:00 2001 +From: Amir Goldstein +Date: Sun, 8 Mar 2026 12:02:21 +0100 +Subject: ovl: fix wrong detection of 32bit inode numbers + +From: Amir Goldstein + +commit 53a7c171e9dd833f0a96b545adcb89bd57387239 upstream. + +The implicit FILEID_INO32_GEN encoder was changed to be explicit, +so we need to fix the detection. + +When mounting overlayfs with upperdir and lowerdir on different ext4 +filesystems, the expected kmsg log is: + + overlayfs: "xino" feature enabled using 32 upper inode bits. + +But instead, since the regressing commit, the kmsg log was: + + overlayfs: "xino" feature enabled using 2 upper inode bits. + +Fixes: e21fc2038c1b9 ("exportfs: make ->encode_fh() a mandatory method for NFS export") +Cc: stable@vger.kernel.org # v6.7+ +Signed-off-by: Amir Goldstein +Signed-off-by: Greg Kroah-Hartman +--- + fs/overlayfs/util.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +--- a/fs/overlayfs/util.c ++++ b/fs/overlayfs/util.c +@@ -85,7 +85,10 @@ int ovl_can_decode_fh(struct super_block + if (!exportfs_can_decode_fh(sb->s_export_op)) + return 0; + +- return sb->s_export_op->encode_fh ? -1 : FILEID_INO32_GEN; ++ if (sb->s_export_op->encode_fh == generic_encode_ino32_fh) ++ return FILEID_INO32_GEN; ++ ++ return -1; + } + + struct dentry *ovl_indexdir(struct super_block *sb) diff --git a/queue-6.19/ovl-make-fsync-after-metadata-copy-up-opt-in-mount-option.patch b/queue-6.19/ovl-make-fsync-after-metadata-copy-up-opt-in-mount-option.patch new file mode 100644 index 0000000000..f5e0c95ab6 --- /dev/null +++ b/queue-6.19/ovl-make-fsync-after-metadata-copy-up-opt-in-mount-option.patch @@ -0,0 +1,285 @@ +From 1f6ee9be92f8df85a8c9a5a78c20fd39c0c21a95 Mon Sep 17 00:00:00 2001 +From: Fei Lv +Date: Mon, 22 Jul 2024 18:14:43 +0800 +Subject: ovl: make fsync after metadata copy-up opt-in mount option + +From: Fei Lv + +commit 1f6ee9be92f8df85a8c9a5a78c20fd39c0c21a95 upstream. + +Commit 7d6899fb69d25 ("ovl: fsync after metadata copy-up") was done to +fix durability of overlayfs copy up on an upper filesystem which does +not enforce ordering on storing of metadata changes (e.g. ubifs). + +In an earlier revision of the regressing commit by Lei Lv, the metadata +fsync behavior was opt-in via a new "fsync=strict" mount option. +We were hoping that the opt-in mount option could be avoided, so the +change was only made to depend on metacopy=off, in the hope of not +hurting performance of metadata heavy workloads, which are more likely +to be using metacopy=on. + +This hope was proven wrong by a performance regression report from Google +COS workload after upgrade to kernel 6.12. + +This is an adaptation of Lei's original "fsync=strict" mount option +to the existing upstream code. + +The new mount option is mutually exclusive with the "volatile" mount +option, so the latter is now an alias to the "fsync=volatile" mount +option. + +Reported-by: Chenglong Tang +Closes: https://lore.kernel.org/linux-unionfs/CAOdxtTadAFH01Vui1FvWfcmQ8jH1O45owTzUcpYbNvBxnLeM7Q@mail.gmail.com/ +Link: https://lore.kernel.org/linux-unionfs/CAOQ4uxgKC1SgjMWre=fUb00v8rxtd6sQi-S+dxR8oDzAuiGu8g@mail.gmail.com/ +Fixes: 7d6899fb69d25 ("ovl: fsync after metadata copy-up") +Depends: 50e638beb67e0 ("ovl: Use str_on_off() helper in ovl_show_options()") +Cc: stable@vger.kernel.org # v6.12+ +Signed-off-by: Fei Lv +Signed-off-by: Amir Goldstein +Signed-off-by: Greg Kroah-Hartman +--- + Documentation/filesystems/overlayfs.rst | 50 ++++++++++++++++++++++++++++++++ + fs/overlayfs/copy_up.c | 6 +-- + fs/overlayfs/overlayfs.h | 21 +++++++++++++ + fs/overlayfs/ovl_entry.h | 7 ---- + fs/overlayfs/params.c | 33 +++++++++++++++++---- + fs/overlayfs/super.c | 2 - + 6 files changed, 104 insertions(+), 15 deletions(-) + +--- a/Documentation/filesystems/overlayfs.rst ++++ b/Documentation/filesystems/overlayfs.rst +@@ -783,6 +783,56 @@ controlled by the "uuid" mount option, w + mounted with "uuid=on". + + ++Durability and copy up ++---------------------- ++ ++The fsync(2) system call ensures that the data and metadata of a file ++are safely written to the backing storage, which is expected to ++guarantee the existence of the information post system crash. ++ ++Without an fsync(2) call, there is no guarantee that the observed ++data after a system crash will be either the old or the new data, but ++in practice, the observed data after crash is often the old or new data ++or a mix of both. ++ ++When an overlayfs file is modified for the first time, copy up will ++create a copy of the lower file and its parent directories in the upper ++layer. Since the Linux filesystem API does not enforce any particular ++ordering on storing changes without explicit fsync(2) calls, in case ++of a system crash, the upper file could end up with no data at all ++(i.e. zeros), which would be an unusual outcome. To avoid this ++experience, overlayfs calls fsync(2) on the upper file before completing ++data copy up with rename(2) or link(2) to make the copy up "atomic". ++ ++By default, overlayfs does not explicitly call fsync(2) on copied up ++directories or on metadata-only copy up, so it provides no guarantee to ++persist the user's modification unless the user calls fsync(2). ++The fsync during copy up only guarantees that if a copy up is observed ++after a crash, the observed data is not zeroes or intermediate values ++from the copy up staging area. ++ ++On traditional local filesystems with a single journal (e.g. ext4, xfs), ++fsync on a file also persists the parent directory changes, because they ++are usually modified in the same transaction, so metadata durability during ++data copy up effectively comes for free. Overlayfs further limits risk by ++disallowing network filesystems as upper layer. ++ ++Overlayfs can be tuned to prefer performance or durability when storing ++to the underlying upper layer. This is controlled by the "fsync" mount ++option, which supports these values: ++ ++- "auto": (default) ++ Call fsync(2) on upper file before completion of data copy up. ++ No explicit fsync(2) on directory or metadata-only copy up. ++- "strict": ++ Call fsync(2) on upper file and directories before completion of any ++ copy up. ++- "volatile": [*] ++ Prefer performance over durability (see `Volatile mount`_) ++ ++[*] The mount option "volatile" is an alias to "fsync=volatile". ++ ++ + Volatile mount + -------------- + +--- a/fs/overlayfs/copy_up.c ++++ b/fs/overlayfs/copy_up.c +@@ -1146,15 +1146,15 @@ static int ovl_copy_up_one(struct dentry + return -EOVERFLOW; + + /* +- * With metacopy disabled, we fsync after final metadata copyup, for ++ * With "fsync=strict", we fsync after final metadata copyup, for + * both regular files and directories to get atomic copyup semantics + * on filesystems that do not use strict metadata ordering (e.g. ubifs). + * +- * With metacopy enabled we want to avoid fsync on all meta copyup ++ * By default, we want to avoid fsync on all meta copyup, because + * that will hurt performance of workloads such as chown -R, so we + * only fsync on data copyup as legacy behavior. + */ +- ctx.metadata_fsync = !OVL_FS(dentry->d_sb)->config.metacopy && ++ ctx.metadata_fsync = ovl_should_sync_metadata(OVL_FS(dentry->d_sb)) && + (S_ISREG(ctx.stat.mode) || S_ISDIR(ctx.stat.mode)); + ctx.metacopy = ovl_need_meta_copy_up(dentry, ctx.stat.mode, flags); + +--- a/fs/overlayfs/overlayfs.h ++++ b/fs/overlayfs/overlayfs.h +@@ -99,6 +99,12 @@ enum { + OVL_VERITY_REQUIRE, + }; + ++enum { ++ OVL_FSYNC_VOLATILE, ++ OVL_FSYNC_AUTO, ++ OVL_FSYNC_STRICT, ++}; ++ + /* + * The tuple (fh,uuid) is a universal unique identifier for a copy up origin, + * where: +@@ -656,6 +662,21 @@ static inline bool ovl_xino_warn(struct + return ofs->config.xino == OVL_XINO_ON; + } + ++static inline bool ovl_should_sync(struct ovl_fs *ofs) ++{ ++ return ofs->config.fsync_mode != OVL_FSYNC_VOLATILE; ++} ++ ++static inline bool ovl_should_sync_metadata(struct ovl_fs *ofs) ++{ ++ return ofs->config.fsync_mode == OVL_FSYNC_STRICT; ++} ++ ++static inline bool ovl_is_volatile(struct ovl_config *config) ++{ ++ return config->fsync_mode == OVL_FSYNC_VOLATILE; ++} ++ + /* + * To avoid regressions in existing setups with overlay lower offline changes, + * we allow lower changes only if none of the new features are used. +--- a/fs/overlayfs/ovl_entry.h ++++ b/fs/overlayfs/ovl_entry.h +@@ -18,7 +18,7 @@ struct ovl_config { + int xino; + bool metacopy; + bool userxattr; +- bool ovl_volatile; ++ int fsync_mode; + }; + + struct ovl_sb { +@@ -120,11 +120,6 @@ static inline struct ovl_fs *OVL_FS(stru + return (struct ovl_fs *)sb->s_fs_info; + } + +-static inline bool ovl_should_sync(struct ovl_fs *ofs) +-{ +- return !ofs->config.ovl_volatile; +-} +- + static inline unsigned int ovl_numlower(struct ovl_entry *oe) + { + return oe ? oe->__numlower : 0; +--- a/fs/overlayfs/params.c ++++ b/fs/overlayfs/params.c +@@ -58,6 +58,7 @@ enum ovl_opt { + Opt_xino, + Opt_metacopy, + Opt_verity, ++ Opt_fsync, + Opt_volatile, + Opt_override_creds, + }; +@@ -140,6 +141,23 @@ static int ovl_verity_mode_def(void) + return OVL_VERITY_OFF; + } + ++static const struct constant_table ovl_parameter_fsync[] = { ++ { "volatile", OVL_FSYNC_VOLATILE }, ++ { "auto", OVL_FSYNC_AUTO }, ++ { "strict", OVL_FSYNC_STRICT }, ++ {} ++}; ++ ++static const char *ovl_fsync_mode(struct ovl_config *config) ++{ ++ return ovl_parameter_fsync[config->fsync_mode].name; ++} ++ ++static int ovl_fsync_mode_def(void) ++{ ++ return OVL_FSYNC_AUTO; ++} ++ + const struct fs_parameter_spec ovl_parameter_spec[] = { + fsparam_string_empty("lowerdir", Opt_lowerdir), + fsparam_file_or_string("lowerdir+", Opt_lowerdir_add), +@@ -155,6 +173,7 @@ const struct fs_parameter_spec ovl_param + fsparam_enum("xino", Opt_xino, ovl_parameter_xino), + fsparam_enum("metacopy", Opt_metacopy, ovl_parameter_bool), + fsparam_enum("verity", Opt_verity, ovl_parameter_verity), ++ fsparam_enum("fsync", Opt_fsync, ovl_parameter_fsync), + fsparam_flag("volatile", Opt_volatile), + fsparam_flag_no("override_creds", Opt_override_creds), + {} +@@ -665,8 +684,11 @@ static int ovl_parse_param(struct fs_con + case Opt_verity: + config->verity_mode = result.uint_32; + break; ++ case Opt_fsync: ++ config->fsync_mode = result.uint_32; ++ break; + case Opt_volatile: +- config->ovl_volatile = true; ++ config->fsync_mode = OVL_FSYNC_VOLATILE; + break; + case Opt_userxattr: + config->userxattr = true; +@@ -800,6 +822,7 @@ int ovl_init_fs_context(struct fs_contex + ofs->config.nfs_export = ovl_nfs_export_def; + ofs->config.xino = ovl_xino_def(); + ofs->config.metacopy = ovl_metacopy_def; ++ ofs->config.fsync_mode = ovl_fsync_mode_def(); + + fc->s_fs_info = ofs; + fc->fs_private = ctx; +@@ -870,9 +893,9 @@ int ovl_fs_params_verify(const struct ov + config->index = false; + } + +- if (!config->upperdir && config->ovl_volatile) { ++ if (!config->upperdir && ovl_is_volatile(config)) { + pr_info("option \"volatile\" is meaningless in a non-upper mount, ignoring it.\n"); +- config->ovl_volatile = false; ++ config->fsync_mode = ovl_fsync_mode_def(); + } + + if (!config->upperdir && config->uuid == OVL_UUID_ON) { +@@ -1070,8 +1093,8 @@ int ovl_show_options(struct seq_file *m, + seq_printf(m, ",xino=%s", ovl_xino_mode(&ofs->config)); + if (ofs->config.metacopy != ovl_metacopy_def) + seq_printf(m, ",metacopy=%s", str_on_off(ofs->config.metacopy)); +- if (ofs->config.ovl_volatile) +- seq_puts(m, ",volatile"); ++ if (ofs->config.fsync_mode != ovl_fsync_mode_def()) ++ seq_printf(m, ",fsync=%s", ovl_fsync_mode(&ofs->config)); + if (ofs->config.userxattr) + seq_puts(m, ",userxattr"); + if (ofs->config.verity_mode != ovl_verity_mode_def()) +--- a/fs/overlayfs/super.c ++++ b/fs/overlayfs/super.c +@@ -776,7 +776,7 @@ static int ovl_make_workdir(struct super + * For volatile mount, create a incompat/volatile/dirty file to keep + * track of it. + */ +- if (ofs->config.ovl_volatile) { ++ if (ovl_is_volatile(&ofs->config)) { + err = ovl_create_volatile_dirty(ofs); + if (err < 0) { + pr_err("Failed to create volatile/dirty file.\n"); diff --git a/queue-6.19/phy-qcom-qmp-ufs-fix-sm8650-pcs-table-for-gear-4.patch b/queue-6.19/phy-qcom-qmp-ufs-fix-sm8650-pcs-table-for-gear-4.patch new file mode 100644 index 0000000000..d2d3cbdaa3 --- /dev/null +++ b/queue-6.19/phy-qcom-qmp-ufs-fix-sm8650-pcs-table-for-gear-4.patch @@ -0,0 +1,59 @@ +From 81af9e40e2e4e1aa95f09fb34811760be6742c58 Mon Sep 17 00:00:00 2001 +From: Abel Vesa +Date: Thu, 19 Feb 2026 13:11:48 +0200 +Subject: phy: qcom: qmp-ufs: Fix SM8650 PCS table for Gear 4 + +From: Abel Vesa + +commit 81af9e40e2e4e1aa95f09fb34811760be6742c58 upstream. + +According to internal documentation, on SM8650, when the PHY is configured +in Gear 4, the QPHY_V6_PCS_UFS_PLL_CNTL register needs to have the same +value as for Gear 5. + +At the moment, there is no board that comes with a UFS 3.x device, so +this issue doesn't show up, but with the new Eliza SoC, which uses the +same init sequence as SM8650, on the MTP board, the link startup fails +with the current Gear 4 PCS table. + +So fix that by moving the entry into the PCS generic table instead, +while keeping the value from Gear 5 configuration. + +Cc: stable@vger.kernel.org # v6.10 +Fixes: b9251e64a96f ("phy: qcom: qmp-ufs: update SM8650 tables for Gear 4 & 5") +Suggested-by: Nitin Rawat +Signed-off-by: Abel Vesa +Reviewed-by: Konrad Dybcio +Reviewed-by: Neil Armstrong +Tested-by: Neil Armstrong # on SM8650-HDK +Link: https://patch.msgid.link/20260219-phy-qcom-qmp-ufs-fix-sm8650-pcs-g4-table-v1-1-f136505b57f6@oss.qualcomm.com +Signed-off-by: Vinod Koul +Signed-off-by: Greg Kroah-Hartman +--- + drivers/phy/qualcomm/phy-qcom-qmp-ufs.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +--- a/drivers/phy/qualcomm/phy-qcom-qmp-ufs.c ++++ b/drivers/phy/qualcomm/phy-qcom-qmp-ufs.c +@@ -928,6 +928,7 @@ static const struct qmp_phy_init_tbl sm8 + QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_MULTI_LANE_CTRL1, 0x02), + QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_TX_MID_TERM_CTRL1, 0x43), + QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_PCS_CTRL1, 0xc1), ++ QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_PLL_CNTL, 0x33), + QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_TX_LARGE_AMP_DRV_LVL, 0x0f), + QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_RX_SIGDET_CTRL2, 0x68), + QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_TX_POST_EMP_LVL_S4, 0x0e), +@@ -937,13 +938,11 @@ static const struct qmp_phy_init_tbl sm8 + }; + + static const struct qmp_phy_init_tbl sm8650_ufsphy_g4_pcs[] = { +- QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_PLL_CNTL, 0x13), + QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_TX_HSGEAR_CAPABILITY, 0x04), + QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_RX_HSGEAR_CAPABILITY, 0x04), + }; + + static const struct qmp_phy_init_tbl sm8650_ufsphy_g5_pcs[] = { +- QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_PLL_CNTL, 0x33), + QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_TX_HSGEAR_CAPABILITY, 0x05), + QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_RX_HSGEAR_CAPABILITY, 0x05), + QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_RX_HS_G5_SYNC_LENGTH_CAPABILITY, 0x4d), diff --git a/queue-6.19/scsi-ibmvfc-fix-oob-access-in-ibmvfc_discover_targets_done.patch b/queue-6.19/scsi-ibmvfc-fix-oob-access-in-ibmvfc_discover_targets_done.patch new file mode 100644 index 0000000000..72dda4fd23 --- /dev/null +++ b/queue-6.19/scsi-ibmvfc-fix-oob-access-in-ibmvfc_discover_targets_done.patch @@ -0,0 +1,45 @@ +From 61d099ac4a7a8fb11ebdb6e2ec8d77f38e77362f Mon Sep 17 00:00:00 2001 +From: Tyllis Xu +Date: Sat, 14 Mar 2026 12:01:50 -0500 +Subject: scsi: ibmvfc: Fix OOB access in ibmvfc_discover_targets_done() + +From: Tyllis Xu + +commit 61d099ac4a7a8fb11ebdb6e2ec8d77f38e77362f upstream. + +A malicious or compromised VIO server can return a num_written value in the +discover targets MAD response that exceeds max_targets. This value is +stored directly in vhost->num_targets without validation, and is then used +as the loop bound in ibmvfc_alloc_targets() to index into disc_buf[], which +is only allocated for max_targets entries. Indices at or beyond max_targets +access kernel memory outside the DMA-coherent allocation. The +out-of-bounds data is subsequently embedded in Implicit Logout and PLOGI +MADs that are sent back to the VIO server, leaking kernel memory. + +Fix by clamping num_written to max_targets before storing it. + +Fixes: 072b91f9c651 ("[SCSI] ibmvfc: IBM Power Virtual Fibre Channel Adapter Client Driver") +Reported-by: Yuhao Jiang +Cc: stable@vger.kernel.org +Signed-off-by: Tyllis Xu +Reviewed-by: Dave Marquardt +Acked-by: Tyrel Datwyler +Link: https://patch.msgid.link/20260314170151.548614-1-LivelyCarpet87@gmail.com +Signed-off-by: Martin K. Petersen +Signed-off-by: Greg Kroah-Hartman +--- + drivers/scsi/ibmvscsi/ibmvfc.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/scsi/ibmvscsi/ibmvfc.c ++++ b/drivers/scsi/ibmvscsi/ibmvfc.c +@@ -4965,7 +4965,8 @@ static void ibmvfc_discover_targets_done + switch (mad_status) { + case IBMVFC_MAD_SUCCESS: + ibmvfc_dbg(vhost, "Discover Targets succeeded\n"); +- vhost->num_targets = be32_to_cpu(rsp->num_written); ++ vhost->num_targets = min_t(u32, be32_to_cpu(rsp->num_written), ++ max_targets); + ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_ALLOC_TGTS); + break; + case IBMVFC_MAD_FAILED: diff --git a/queue-6.19/scsi-ses-handle-positive-scsi-error-from-ses_recv_diag.patch b/queue-6.19/scsi-ses-handle-positive-scsi-error-from-ses_recv_diag.patch new file mode 100644 index 0000000000..9f47cea602 --- /dev/null +++ b/queue-6.19/scsi-ses-handle-positive-scsi-error-from-ses_recv_diag.patch @@ -0,0 +1,36 @@ +From 7a9f448d44127217fabc4065c5ba070d4e0b5d37 Mon Sep 17 00:00:00 2001 +From: Greg Kroah-Hartman +Date: Mon, 23 Feb 2026 16:44:59 +0100 +Subject: scsi: ses: Handle positive SCSI error from ses_recv_diag() + +From: Greg Kroah-Hartman + +commit 7a9f448d44127217fabc4065c5ba070d4e0b5d37 upstream. + +ses_recv_diag() can return a positive value, which also means that an +error happened, so do not only test for negative values. + +Cc: James E.J. Bottomley +Cc: Martin K. Petersen +Cc: stable +Assisted-by: gkh_clanker_2000 +Signed-off-by: Greg Kroah-Hartman +Reviewed-by: Hannes Reinecke +Link: https://patch.msgid.link/2026022301-bony-overstock-a07f@gregkh +Signed-off-by: Martin K. Petersen +Signed-off-by: Greg Kroah-Hartman +--- + drivers/scsi/ses.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/scsi/ses.c ++++ b/drivers/scsi/ses.c +@@ -216,7 +216,7 @@ static unsigned char *ses_get_page2_desc + unsigned char *type_ptr = ses_dev->page1_types; + unsigned char *desc_ptr = ses_dev->page2 + 8; + +- if (ses_recv_diag(sdev, 2, ses_dev->page2, ses_dev->page2_len) < 0) ++ if (ses_recv_diag(sdev, 2, ses_dev->page2, ses_dev->page2_len)) + return NULL; + + for (i = 0; i < ses_dev->page1_num_types; i++, type_ptr += 4) { diff --git a/queue-6.19/series b/queue-6.19/series index bbb1bb7773..0b4ed579c7 100644 --- a/queue-6.19/series +++ b/queue-6.19/series @@ -233,3 +233,57 @@ virt-tdx-guest-fix-handling-of-host-controlled-quote-buffer-length.patch virtio_net-fix-uaf-on-dst_ops-when-iff_xmit_dst_release-is-cleared-and-napi_tx-is-false.patch vfio-pci-fix-double-free-in-dma-buf-feature.patch erofs-add-gfp_noio-in-the-bio-completion-if-needed.patch +alarmtimer-fix-argument-order-in-alarm_timer_forward.patch +mm-huge_memory-fix-folio-isn-t-locked-in-softleaf_to_folio.patch +writeback-don-t-block-sync-for-filesystems-with-no-data-integrity-guarantees.patch +x86-cpu-enable-fsgsbase-early-in-cpu_init_exception_handling.patch +x86-cpu-remove-x86_cr4_fred-from-the-cr4-pinned-bits-mask.patch +x86-fred-fix-early-boot-failures-on-sev-es-snp-guests.patch +phy-qcom-qmp-ufs-fix-sm8650-pcs-table-for-gear-4.patch +ovl-make-fsync-after-metadata-copy-up-opt-in-mount-option.patch +ovl-fix-wrong-detection-of-32bit-inode-numbers.patch +scsi-ibmvfc-fix-oob-access-in-ibmvfc_discover_targets_done.patch +scsi-ses-handle-positive-scsi-error-from-ses_recv_diag.patch +net-macb-move-devm_-free-request-_irq-out-of-spin-lock-area.patch +net-macb-protect-access-to-net_device-ip_ptr-with-rcu-lock.patch +net-macb-use-dev_consume_skb_any-to-free-tx-skbs.patch +kvm-x86-mmu-drop-zap-existing-present-spte-even-when-creating-an-mmio-spte.patch +kvm-x86-mmu-only-warn-in-direct-mmus-when-overwriting-shadow-present-spte.patch +jbd2-gracefully-abort-on-checkpointing-state-corruptions.patch +irqchip-qcom-mpm-add-missing-mailbox-tx-done-acknowledgment.patch +iomap-fix-invalid-folio-access-when-i_blkbits-differs-from-i-o-granularity.patch +i2c-designware-amdisp-fix-resume-probe-race-condition-issue.patch +futex-clear-stale-exiting-pointer-in-futex_lock_pi-retry-path.patch +i2c-imx-fix-i2c-issue-when-reading-multiple-messages.patch +i2c-imx-ensure-no-clock-is-generated-after-last-read.patch +dmaengine-fsl-edma-fix-channel-parameter-config-for-fixed-channel-requests.patch +dmaengine-sh-rz-dmac-protect-the-driver-specific-lists.patch +dmaengine-sh-rz-dmac-move-chctrl-updates-under-spinlock.patch +drm-amdgpu-prevent-immediate-pasid-reuse-case.patch +drm-amdgpu-fix-strsep-corrupting-lockup_timeout-on-multi-gpu-v3.patch +drm-amd-display-fix-dce-lvds-handling.patch +drm-amd-display-fix-drm_edid-leak-in-amdgpu_dm.patch +drm-amd-display-check-if-ext_caps-is-valid-in-bl-setup.patch +drm-i915-dp_tunnel-fix-error-handling-when-clearing-stream-bw-in-atomic-state.patch +drm-i915-order-op-vs.-timeout-correctly-in-__wait_for.patch +drm-i915-unlink-nv12-planes-earlier.patch +loongarch-fix-missing-null-checks-for-kstrdup.patch +loongarch-vdso-emit-gnu_eh_frame-correctly.patch +loongarch-workaround-ls2k-ls7a-gpu-dma-hang-bug.patch +loongarch-kvm-make-kvm_get_vcpu_by_cpuid-more-robust.patch +loongarch-kvm-fix-base-address-calculation-in-kvm_eiointc_regs_access.patch +loongarch-kvm-handle-the-case-that-eiointc-s-coremap-is-empty.patch +drm-amd-pm-return-eopnotsupp-for-unsupported-od_mclk-on-smu_v13_0_6.patch +mm-memory-fix-pmd-pud-checks-in-follow_pfnmap_start.patch +mm-mseal-update-vma-end-correctly-on-merge.patch +mm-damon-sysfs-fix-param_ctx-leak-on-damon_sysfs_new_test_ctx-failure.patch +mm-damon-sysfs-check-contexts-nr-before-accessing-contexts_arr.patch +mm-damon-sysfs-check-contexts-nr-in-repeat_call_fn.patch +mm-pagewalk-fix-race-between-concurrent-split-and-refault.patch +xfs-stop-reclaim-before-pushing-ail-during-unmount.patch +xfs-save-ailp-before-dropping-the-ail-lock-in-push-callbacks.patch +xfs-avoid-dereferencing-log-items-after-push-callbacks.patch +xfs-scrub-unlock-dquot-before-early-return-in-quota-scrub.patch +xfs-fix-ri_total-validation-in-xlog_recover_attri_commit_pass2.patch +xfs-don-t-irele-after-failing-to-iget-in-xfs_attri_recover_work.patch +xfs-remove-file_path-tracepoint-data.patch diff --git a/queue-6.19/writeback-don-t-block-sync-for-filesystems-with-no-data-integrity-guarantees.patch b/queue-6.19/writeback-don-t-block-sync-for-filesystems-with-no-data-integrity-guarantees.patch new file mode 100644 index 0000000000..b8c2de8cbc --- /dev/null +++ b/queue-6.19/writeback-don-t-block-sync-for-filesystems-with-no-data-integrity-guarantees.patch @@ -0,0 +1,173 @@ +From 76f9377cd2ab7a9220c25d33940d9ca20d368172 Mon Sep 17 00:00:00 2001 +From: Joanne Koong +Date: Thu, 19 Mar 2026 17:51:45 -0700 +Subject: writeback: don't block sync for filesystems with no data integrity guarantees + +From: Joanne Koong + +commit 76f9377cd2ab7a9220c25d33940d9ca20d368172 upstream. + +Add a SB_I_NO_DATA_INTEGRITY superblock flag for filesystems that cannot +guarantee data persistence on sync (eg fuse). For superblocks with this +flag set, sync kicks off writeback of dirty inodes but does not wait +for the flusher threads to complete the writeback. + +This replaces the per-inode AS_NO_DATA_INTEGRITY mapping flag added in +commit f9a49aa302a0 ("fs/writeback: skip AS_NO_DATA_INTEGRITY mappings +in wait_sb_inodes()"). The flag belongs at the superblock level because +data integrity is a filesystem-wide property, not a per-inode one. +Having this flag at the superblock level also allows us to skip having +to iterate every dirty inode in wait_sb_inodes() only to skip each inode +individually. + +Prior to this commit, mappings with no data integrity guarantees skipped +waiting on writeback completion but still waited on the flusher threads +to finish initiating the writeback. Waiting on the flusher threads is +unnecessary. This commit kicks off writeback but does not wait on the +flusher threads. This change properly addresses a recent report [1] for +a suspend-to-RAM hang seen on fuse-overlayfs that was caused by waiting +on the flusher threads to finish: + +Workqueue: pm_fs_sync pm_fs_sync_work_fn +Call Trace: + + __schedule+0x457/0x1720 + schedule+0x27/0xd0 + wb_wait_for_completion+0x97/0xe0 + sync_inodes_sb+0xf8/0x2e0 + __iterate_supers+0xdc/0x160 + ksys_sync+0x43/0xb0 + pm_fs_sync_work_fn+0x17/0xa0 + process_one_work+0x193/0x350 + worker_thread+0x1a1/0x310 + kthread+0xfc/0x240 + ret_from_fork+0x243/0x280 + ret_from_fork_asm+0x1a/0x30 + + +On fuse this is problematic because there are paths that may cause the +flusher thread to block (eg if systemd freezes the user session cgroups +first, which freezes the fuse daemon, before invoking the kernel +suspend. The kernel suspend triggers ->write_node() which on fuse issues +a synchronous setattr request, which cannot be processed since the +daemon is frozen. Or if the daemon is buggy and cannot properly complete +writeback, initiating writeback on a dirty folio already under writeback +leads to writeback_get_folio() -> folio_prepare_writeback() -> +unconditional wait on writeback to finish, which will cause a hang). +This commit restores fuse to its prior behavior before tmp folios were +removed, where sync was essentially a no-op. + +[1] https://lore.kernel.org/linux-fsdevel/CAJnrk1a-asuvfrbKXbEwwDSctvemF+6zfhdnuzO65Pt8HsFSRw@mail.gmail.com/T/#m632c4648e9cafc4239299887109ebd880ac6c5c1 + +Fixes: 0c58a97f919c ("fuse: remove tmp folio for writebacks and internal rb tree") +Reported-by: John +Cc: stable@vger.kernel.org +Signed-off-by: Joanne Koong +Link: https://patch.msgid.link/20260320005145.2483161-2-joannelkoong@gmail.com +Reviewed-by: Jan Kara +Reviewed-by: David Hildenbrand (Arm) +Signed-off-by: Christian Brauner +Signed-off-by: Greg Kroah-Hartman +--- + fs/fs-writeback.c | 18 ++++++++++++------ + fs/fuse/file.c | 4 +--- + fs/fuse/inode.c | 1 + + include/linux/fs/super_types.h | 1 + + include/linux/pagemap.h | 11 ----------- + 5 files changed, 15 insertions(+), 20 deletions(-) + +--- a/fs/fs-writeback.c ++++ b/fs/fs-writeback.c +@@ -2759,13 +2759,8 @@ static void wait_sb_inodes(struct super_ + * The mapping can appear untagged while still on-list since we + * do not have the mapping lock. Skip it here, wb completion + * will remove it. +- * +- * If the mapping does not have data integrity semantics, +- * there's no need to wait for the writeout to complete, as the +- * mapping cannot guarantee that data is persistently stored. + */ +- if (!mapping_tagged(mapping, PAGECACHE_TAG_WRITEBACK) || +- mapping_no_data_integrity(mapping)) ++ if (!mapping_tagged(mapping, PAGECACHE_TAG_WRITEBACK)) + continue; + + spin_unlock_irq(&sb->s_inode_wblist_lock); +@@ -2900,6 +2895,17 @@ void sync_inodes_sb(struct super_block * + */ + if (bdi == &noop_backing_dev_info) + return; ++ ++ /* ++ * If the superblock has SB_I_NO_DATA_INTEGRITY set, there's no need to ++ * wait for the writeout to complete, as the filesystem cannot guarantee ++ * data persistence on sync. Just kick off writeback and return. ++ */ ++ if (sb->s_iflags & SB_I_NO_DATA_INTEGRITY) { ++ wakeup_flusher_threads_bdi(bdi, WB_REASON_SYNC); ++ return; ++ } ++ + WARN_ON(!rwsem_is_locked(&sb->s_umount)); + + /* protect against inode wb switch, see inode_switch_wbs_work_fn() */ +--- a/fs/fuse/file.c ++++ b/fs/fuse/file.c +@@ -3200,10 +3200,8 @@ void fuse_init_file_inode(struct inode * + + inode->i_fop = &fuse_file_operations; + inode->i_data.a_ops = &fuse_file_aops; +- if (fc->writeback_cache) { ++ if (fc->writeback_cache) + mapping_set_writeback_may_deadlock_on_reclaim(&inode->i_data); +- mapping_set_no_data_integrity(&inode->i_data); +- } + + INIT_LIST_HEAD(&fi->write_files); + INIT_LIST_HEAD(&fi->queued_writes); +--- a/fs/fuse/inode.c ++++ b/fs/fuse/inode.c +@@ -1709,6 +1709,7 @@ static void fuse_sb_defaults(struct supe + sb->s_export_op = &fuse_export_operations; + sb->s_iflags |= SB_I_IMA_UNVERIFIABLE_SIGNATURE; + sb->s_iflags |= SB_I_NOIDMAP; ++ sb->s_iflags |= SB_I_NO_DATA_INTEGRITY; + if (sb->s_user_ns != &init_user_ns) + sb->s_iflags |= SB_I_UNTRUSTED_MOUNTER; + sb->s_flags &= ~(SB_NOSEC | SB_I_VERSION); +--- a/include/linux/fs/super_types.h ++++ b/include/linux/fs/super_types.h +@@ -332,5 +332,6 @@ struct super_block { + #define SB_I_NOUMASK 0x00001000 /* VFS does not apply umask */ + #define SB_I_NOIDMAP 0x00002000 /* No idmapped mounts on this superblock */ + #define SB_I_ALLOW_HSM 0x00004000 /* Allow HSM events on this superblock */ ++#define SB_I_NO_DATA_INTEGRITY 0x00008000 /* fs cannot guarantee data persistence on sync */ + + #endif /* _LINUX_FS_SUPER_TYPES_H */ +--- a/include/linux/pagemap.h ++++ b/include/linux/pagemap.h +@@ -210,7 +210,6 @@ enum mapping_flags { + AS_WRITEBACK_MAY_DEADLOCK_ON_RECLAIM = 9, + AS_KERNEL_FILE = 10, /* mapping for a fake kernel file that shouldn't + account usage to user cgroups */ +- AS_NO_DATA_INTEGRITY = 11, /* no data integrity guarantees */ + /* Bits 16-25 are used for FOLIO_ORDER */ + AS_FOLIO_ORDER_BITS = 5, + AS_FOLIO_ORDER_MIN = 16, +@@ -346,16 +345,6 @@ static inline bool mapping_writeback_may + return test_bit(AS_WRITEBACK_MAY_DEADLOCK_ON_RECLAIM, &mapping->flags); + } + +-static inline void mapping_set_no_data_integrity(struct address_space *mapping) +-{ +- set_bit(AS_NO_DATA_INTEGRITY, &mapping->flags); +-} +- +-static inline bool mapping_no_data_integrity(const struct address_space *mapping) +-{ +- return test_bit(AS_NO_DATA_INTEGRITY, &mapping->flags); +-} +- + static inline gfp_t mapping_gfp_mask(const struct address_space *mapping) + { + return mapping->gfp_mask; diff --git a/queue-6.19/x86-cpu-enable-fsgsbase-early-in-cpu_init_exception_handling.patch b/queue-6.19/x86-cpu-enable-fsgsbase-early-in-cpu_init_exception_handling.patch new file mode 100644 index 0000000000..314a325a23 --- /dev/null +++ b/queue-6.19/x86-cpu-enable-fsgsbase-early-in-cpu_init_exception_handling.patch @@ -0,0 +1,137 @@ +From 05243d490bb7852a8acca7b5b5658019c7797a52 Mon Sep 17 00:00:00 2001 +From: Nikunj A Dadhania +Date: Wed, 18 Mar 2026 07:56:52 +0000 +Subject: x86/cpu: Enable FSGSBASE early in cpu_init_exception_handling() + +From: Nikunj A Dadhania + +commit 05243d490bb7852a8acca7b5b5658019c7797a52 upstream. + +Move FSGSBASE enablement from identify_cpu() to cpu_init_exception_handling() +to ensure it is enabled before any exceptions can occur on both boot and +secondary CPUs. + +== Background == + +Exception entry code (paranoid_entry()) uses ALTERNATIVE patching based on +X86_FEATURE_FSGSBASE to decide whether to use RDGSBASE/WRGSBASE instructions +or the slower RDMSR/SWAPGS sequence for saving/restoring GSBASE. + +On boot CPU, ALTERNATIVE patching happens after enabling FSGSBASE in CR4. +When the feature is available, the code is permanently patched to use +RDGSBASE/WRGSBASE, which require CR4.FSGSBASE=1 to execute without triggering + +== Boot Sequence == + +Boot CPU (with CR pinning enabled): + trap_init() + cpu_init() <- Uses unpatched code (RDMSR/SWAPGS) + x2apic_setup() + ... + arch_cpu_finalize_init() + identify_boot_cpu() + identify_cpu() + cr4_set_bits(X86_CR4_FSGSBASE) # Enables the feature + # This becomes part of cr4_pinned_bits + ... + alternative_instructions() <- Patches code to use RDGSBASE/WRGSBASE + +Secondary CPUs (with CR pinning enabled): + start_secondary() + cr4_init() <- Code already patched, CR4.FSGSBASE=1 + set implicitly via cr4_pinned_bits + + cpu_init() <- exceptions work because FSGSBASE is + already enabled + +Secondary CPU (with CR pinning disabled): + start_secondary() + cr4_init() <- Code already patched, CR4.FSGSBASE=0 + cpu_init() + x2apic_setup() + rdmsrq(MSR_IA32_APICBASE) <- Triggers #VC in SNP guests + exc_vmm_communication() + paranoid_entry() <- Uses RDGSBASE with CR4.FSGSBASE=0 + (patched code) + ... + ap_starting() + identify_secondary_cpu() + identify_cpu() + cr4_set_bits(X86_CR4_FSGSBASE) <- Enables the feature, which is + too late + +== CR Pinning == + +Currently, for secondary CPUs, CR4.FSGSBASE is set implicitly through +CR-pinning: the boot CPU sets it during identify_cpu(), it becomes part of +cr4_pinned_bits, and cr4_init() applies those pinned bits to secondary CPUs. +This works but creates an undocumented dependency between cr4_init() and the +pinning mechanism. + +== Problem == + +Secondary CPUs boot after alternatives have been applied globally. They +execute already-patched paranoid_entry() code that uses RDGSBASE/WRGSBASE +instructions, which require CR4.FSGSBASE=1. Upcoming changes to CR pinning +behavior will break the implicit dependency, causing secondary CPUs to +generate #UD. + +This issue manifests itself on AMD SEV-SNP guests, where the rdmsrq() in +x2apic_setup() triggers a #VC exception early during cpu_init(). The #VC +handler (exc_vmm_communication()) executes the patched paranoid_entry() path. +Without CR4.FSGSBASE enabled, RDGSBASE instructions trigger #UD. + +== Fix == + +Enable FSGSBASE explicitly in cpu_init_exception_handling() before loading +exception handlers. This makes the dependency explicit and ensures both +boot and secondary CPUs have FSGSBASE enabled before paranoid_entry() +executes. + +Fixes: c82965f9e530 ("x86/entry/64: Handle FSGSBASE enabled paranoid entry/exit") +Reported-by: Borislav Petkov +Suggested-by: Sohil Mehta +Signed-off-by: Nikunj A Dadhania +Signed-off-by: Borislav Petkov (AMD) +Reviewed-by: Sohil Mehta +Cc: +Link: https://patch.msgid.link/20260318075654.1792916-2-nikunj@amd.com +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/kernel/cpu/common.c | 18 ++++++++++++------ + 1 file changed, 12 insertions(+), 6 deletions(-) + +--- a/arch/x86/kernel/cpu/common.c ++++ b/arch/x86/kernel/cpu/common.c +@@ -2042,12 +2042,6 @@ static void identify_cpu(struct cpuinfo_ + setup_umip(c); + setup_lass(c); + +- /* Enable FSGSBASE instructions if available. */ +- if (cpu_has(c, X86_FEATURE_FSGSBASE)) { +- cr4_set_bits(X86_CR4_FSGSBASE); +- elf_hwcap2 |= HWCAP2_FSGSBASE; +- } +- + /* + * The vendor-specific functions might have changed features. + * Now we do "generic changes." +@@ -2408,6 +2402,18 @@ void cpu_init_exception_handling(bool bo + /* GHCB needs to be setup to handle #VC. */ + setup_ghcb(); + ++ /* ++ * On CPUs with FSGSBASE support, paranoid_entry() uses ++ * ALTERNATIVE-patched RDGSBASE/WRGSBASE instructions. Secondary CPUs ++ * boot after alternatives are patched globally, so early exceptions ++ * execute patched code that depends on FSGSBASE. Enable the feature ++ * before any exceptions occur. ++ */ ++ if (cpu_feature_enabled(X86_FEATURE_FSGSBASE)) { ++ cr4_set_bits(X86_CR4_FSGSBASE); ++ elf_hwcap2 |= HWCAP2_FSGSBASE; ++ } ++ + if (cpu_feature_enabled(X86_FEATURE_FRED)) { + /* The boot CPU has enabled FRED during early boot */ + if (!boot_cpu) diff --git a/queue-6.19/x86-cpu-remove-x86_cr4_fred-from-the-cr4-pinned-bits-mask.patch b/queue-6.19/x86-cpu-remove-x86_cr4_fred-from-the-cr4-pinned-bits-mask.patch new file mode 100644 index 0000000000..7ae8376d18 --- /dev/null +++ b/queue-6.19/x86-cpu-remove-x86_cr4_fred-from-the-cr4-pinned-bits-mask.patch @@ -0,0 +1,63 @@ +From 411df123c017169922cc767affce76282b8e6c85 Mon Sep 17 00:00:00 2001 +From: "Borislav Petkov (AMD)" +Date: Thu, 19 Mar 2026 12:07:59 +0100 +Subject: x86/cpu: Remove X86_CR4_FRED from the CR4 pinned bits mask + +From: Borislav Petkov (AMD) + +commit 411df123c017169922cc767affce76282b8e6c85 upstream. + +Commit in Fixes added the FRED CR4 bit to the CR4 pinned bits mask so +that whenever something else modifies CR4, that bit remains set. Which +in itself is a perfectly fine idea. + +However, there's an issue when during boot FRED is initialized: first on +the BSP and later on the APs. Thus, there's a window in time when +exceptions cannot be handled. + +This becomes particularly nasty when running as SEV-{ES,SNP} or TDX +guests which, when they manage to trigger exceptions during that short +window described above, triple fault due to FRED MSRs not being set up +yet. + +See Link tag below for a much more detailed explanation of the +situation. + +So, as a result, the commit in that Link URL tried to address this +shortcoming by temporarily disabling CR4 pinning when an AP is not +online yet. + +However, that is a problem in itself because in this case, an attack on +the kernel needs to only modify the online bit - a single bit in RW +memory - and then disable CR4 pinning and then disable SM*P, leading to +more and worse things to happen to the system. + +So, instead, remove the FRED bit from the CR4 pinning mask, thus +obviating the need to temporarily disable CR4 pinning. + +If someone manages to disable FRED when poking at CR4, then +idt_invalidate() would make sure the system would crash'n'burn on the +first exception triggered, which is a much better outcome security-wise. + +Fixes: ff45746fbf00 ("x86/cpu: Add X86_CR4_FRED macro") +Suggested-by: Dave Hansen +Suggested-by: Peter Zijlstra +Signed-off-by: Borislav Petkov (AMD) +Cc: # 6.12+ +Link: https://lore.kernel.org/r/177385987098.1647592.3381141860481415647.tip-bot2@tip-bot2 +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/kernel/cpu/common.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/arch/x86/kernel/cpu/common.c ++++ b/arch/x86/kernel/cpu/common.c +@@ -433,7 +433,7 @@ static __always_inline void setup_lass(s + + /* These bits should not change their value after CPU init is finished. */ + static const unsigned long cr4_pinned_mask = X86_CR4_SMEP | X86_CR4_SMAP | X86_CR4_UMIP | +- X86_CR4_FSGSBASE | X86_CR4_CET | X86_CR4_FRED; ++ X86_CR4_FSGSBASE | X86_CR4_CET; + static DEFINE_STATIC_KEY_FALSE_RO(cr_pinning); + static unsigned long cr4_pinned_bits __ro_after_init; + diff --git a/queue-6.19/x86-fred-fix-early-boot-failures-on-sev-es-snp-guests.patch b/queue-6.19/x86-fred-fix-early-boot-failures-on-sev-es-snp-guests.patch new file mode 100644 index 0000000000..d28befa6bb --- /dev/null +++ b/queue-6.19/x86-fred-fix-early-boot-failures-on-sev-es-snp-guests.patch @@ -0,0 +1,89 @@ +From 3645eb7e3915990a149460c151a00894cb586253 Mon Sep 17 00:00:00 2001 +From: Nikunj A Dadhania +Date: Wed, 18 Mar 2026 07:56:54 +0000 +Subject: x86/fred: Fix early boot failures on SEV-ES/SNP guests + +From: Nikunj A Dadhania + +commit 3645eb7e3915990a149460c151a00894cb586253 upstream. + +FRED-enabled SEV-(ES,SNP) guests fail to boot due to the following issues +in the early boot sequence: + +* FRED does not have a #VC exception handler in the dispatch logic + +* Early FRED #VC exceptions attempt to use uninitialized per-CPU GHCBs + instead of boot_ghcb + +Add X86_TRAP_VC case to fred_hwexc() with a new exc_vmm_communication() +function that provides the unified entry point FRED requires, dispatching +to existing user/kernel handlers based on privilege level. The function is +already declared via DECLARE_IDTENTRY_VC(). + +Fix early GHCB access by falling back to boot_ghcb in +__sev_{get,put}_ghcb() when per-CPU GHCBs are not yet initialized. + +Fixes: 14619d912b65 ("x86/fred: FRED entry/exit and dispatch code") +Signed-off-by: Nikunj A Dadhania +Signed-off-by: Borislav Petkov (AMD) +Reviewed-by: Tom Lendacky +Cc: # 6.12+ +Link: https://patch.msgid.link/20260318075654.1792916-4-nikunj@amd.com +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/coco/sev/noinstr.c | 6 ++++++ + arch/x86/entry/entry_fred.c | 14 ++++++++++++++ + 2 files changed, 20 insertions(+) + +--- a/arch/x86/coco/sev/noinstr.c ++++ b/arch/x86/coco/sev/noinstr.c +@@ -120,6 +120,9 @@ noinstr struct ghcb *__sev_get_ghcb(stru + + WARN_ON(!irqs_disabled()); + ++ if (!sev_cfg.ghcbs_initialized) ++ return boot_ghcb; ++ + data = this_cpu_read(runtime_data); + ghcb = &data->ghcb_page; + +@@ -163,6 +166,9 @@ noinstr void __sev_put_ghcb(struct ghcb_ + + WARN_ON(!irqs_disabled()); + ++ if (!sev_cfg.ghcbs_initialized) ++ return; ++ + data = this_cpu_read(runtime_data); + ghcb = &data->ghcb_page; + +--- a/arch/x86/entry/entry_fred.c ++++ b/arch/x86/entry/entry_fred.c +@@ -176,6 +176,16 @@ static noinstr void fred_extint(struct p + } + } + ++#ifdef CONFIG_AMD_MEM_ENCRYPT ++noinstr void exc_vmm_communication(struct pt_regs *regs, unsigned long error_code) ++{ ++ if (user_mode(regs)) ++ return user_exc_vmm_communication(regs, error_code); ++ else ++ return kernel_exc_vmm_communication(regs, error_code); ++} ++#endif ++ + static noinstr void fred_hwexc(struct pt_regs *regs, unsigned long error_code) + { + /* Optimize for #PF. That's the only exception which matters performance wise */ +@@ -206,6 +216,10 @@ static noinstr void fred_hwexc(struct pt + #ifdef CONFIG_X86_CET + case X86_TRAP_CP: return exc_control_protection(regs, error_code); + #endif ++#ifdef CONFIG_AMD_MEM_ENCRYPT ++ case X86_TRAP_VC: return exc_vmm_communication(regs, error_code); ++#endif ++ + default: return fred_bad_type(regs, error_code); + } + diff --git a/queue-6.19/xfs-avoid-dereferencing-log-items-after-push-callbacks.patch b/queue-6.19/xfs-avoid-dereferencing-log-items-after-push-callbacks.patch new file mode 100644 index 0000000000..9bc3b002f9 --- /dev/null +++ b/queue-6.19/xfs-avoid-dereferencing-log-items-after-push-callbacks.patch @@ -0,0 +1,165 @@ +From 79ef34ec0554ec04bdbafafbc9836423734e1bd6 Mon Sep 17 00:00:00 2001 +From: Yuto Ohnuki +Date: Tue, 10 Mar 2026 18:38:38 +0000 +Subject: xfs: avoid dereferencing log items after push callbacks + +From: Yuto Ohnuki + +commit 79ef34ec0554ec04bdbafafbc9836423734e1bd6 upstream. + +After xfsaild_push_item() calls iop_push(), the log item may have been +freed if the AIL lock was dropped during the push. Background inode +reclaim or the dquot shrinker can free the log item while the AIL lock +is not held, and the tracepoints in the switch statement dereference +the log item after iop_push() returns. + +Fix this by capturing the log item type, flags, and LSN before calling +xfsaild_push_item(), and introducing a new xfs_ail_push_class trace +event class that takes these pre-captured values and the ailp pointer +instead of the log item pointer. + +Reported-by: syzbot+652af2b3c5569c4ab63c@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=652af2b3c5569c4ab63c +Fixes: 90c60e164012 ("xfs: xfs_iflush() is no longer necessary") +Cc: stable@vger.kernel.org # v5.9 +Signed-off-by: Yuto Ohnuki +Reviewed-by: Darrick J. Wong +Signed-off-by: Carlos Maiolino +Signed-off-by: Greg Kroah-Hartman +--- + fs/xfs/xfs_trace.h | 36 ++++++++++++++++++++++++++++++++---- + fs/xfs/xfs_trans_ail.c | 26 +++++++++++++++++++------- + 2 files changed, 51 insertions(+), 11 deletions(-) + +--- a/fs/xfs/xfs_trace.h ++++ b/fs/xfs/xfs_trace.h +@@ -56,6 +56,7 @@ + #include + + struct xfs_agf; ++struct xfs_ail; + struct xfs_alloc_arg; + struct xfs_attr_list_context; + struct xfs_buf_log_item; +@@ -1647,16 +1648,43 @@ TRACE_EVENT(xfs_log_force, + DEFINE_EVENT(xfs_log_item_class, name, \ + TP_PROTO(struct xfs_log_item *lip), \ + TP_ARGS(lip)) +-DEFINE_LOG_ITEM_EVENT(xfs_ail_push); +-DEFINE_LOG_ITEM_EVENT(xfs_ail_pinned); +-DEFINE_LOG_ITEM_EVENT(xfs_ail_locked); +-DEFINE_LOG_ITEM_EVENT(xfs_ail_flushing); + DEFINE_LOG_ITEM_EVENT(xfs_cil_whiteout_mark); + DEFINE_LOG_ITEM_EVENT(xfs_cil_whiteout_skip); + DEFINE_LOG_ITEM_EVENT(xfs_cil_whiteout_unpin); + DEFINE_LOG_ITEM_EVENT(xlog_ail_insert_abort); + DEFINE_LOG_ITEM_EVENT(xfs_trans_free_abort); + ++DECLARE_EVENT_CLASS(xfs_ail_push_class, ++ TP_PROTO(struct xfs_ail *ailp, uint type, unsigned long flags, xfs_lsn_t lsn), ++ TP_ARGS(ailp, type, flags, lsn), ++ TP_STRUCT__entry( ++ __field(dev_t, dev) ++ __field(uint, type) ++ __field(unsigned long, flags) ++ __field(xfs_lsn_t, lsn) ++ ), ++ TP_fast_assign( ++ __entry->dev = ailp->ail_log->l_mp->m_super->s_dev; ++ __entry->type = type; ++ __entry->flags = flags; ++ __entry->lsn = lsn; ++ ), ++ TP_printk("dev %d:%d lsn %d/%d type %s flags %s", ++ MAJOR(__entry->dev), MINOR(__entry->dev), ++ CYCLE_LSN(__entry->lsn), BLOCK_LSN(__entry->lsn), ++ __print_symbolic(__entry->type, XFS_LI_TYPE_DESC), ++ __print_flags(__entry->flags, "|", XFS_LI_FLAGS)) ++) ++ ++#define DEFINE_AIL_PUSH_EVENT(name) \ ++DEFINE_EVENT(xfs_ail_push_class, name, \ ++ TP_PROTO(struct xfs_ail *ailp, uint type, unsigned long flags, xfs_lsn_t lsn), \ ++ TP_ARGS(ailp, type, flags, lsn)) ++DEFINE_AIL_PUSH_EVENT(xfs_ail_push); ++DEFINE_AIL_PUSH_EVENT(xfs_ail_pinned); ++DEFINE_AIL_PUSH_EVENT(xfs_ail_locked); ++DEFINE_AIL_PUSH_EVENT(xfs_ail_flushing); ++ + DECLARE_EVENT_CLASS(xfs_ail_class, + TP_PROTO(struct xfs_log_item *lip, xfs_lsn_t old_lsn, xfs_lsn_t new_lsn), + TP_ARGS(lip, old_lsn, new_lsn), +--- a/fs/xfs/xfs_trans_ail.c ++++ b/fs/xfs/xfs_trans_ail.c +@@ -365,6 +365,12 @@ xfsaild_resubmit_item( + return XFS_ITEM_SUCCESS; + } + ++/* ++ * Push a single log item from the AIL. ++ * ++ * @lip may have been released and freed by the time this function returns, ++ * so callers must not dereference the log item afterwards. ++ */ + static inline uint + xfsaild_push_item( + struct xfs_ail *ailp, +@@ -505,7 +511,10 @@ xfsaild_push( + + lsn = lip->li_lsn; + while ((XFS_LSN_CMP(lip->li_lsn, ailp->ail_target) <= 0)) { +- int lock_result; ++ int lock_result; ++ uint type = lip->li_type; ++ unsigned long flags = lip->li_flags; ++ xfs_lsn_t item_lsn = lip->li_lsn; + + if (test_bit(XFS_LI_FLUSHING, &lip->li_flags)) + goto next_item; +@@ -514,14 +523,17 @@ xfsaild_push( + * Note that iop_push may unlock and reacquire the AIL lock. We + * rely on the AIL cursor implementation to be able to deal with + * the dropped lock. ++ * ++ * The log item may have been freed by the push, so it must not ++ * be accessed or dereferenced below this line. + */ + lock_result = xfsaild_push_item(ailp, lip); + switch (lock_result) { + case XFS_ITEM_SUCCESS: + XFS_STATS_INC(mp, xs_push_ail_success); +- trace_xfs_ail_push(lip); ++ trace_xfs_ail_push(ailp, type, flags, item_lsn); + +- ailp->ail_last_pushed_lsn = lsn; ++ ailp->ail_last_pushed_lsn = item_lsn; + break; + + case XFS_ITEM_FLUSHING: +@@ -537,22 +549,22 @@ xfsaild_push( + * AIL is being flushed. + */ + XFS_STATS_INC(mp, xs_push_ail_flushing); +- trace_xfs_ail_flushing(lip); ++ trace_xfs_ail_flushing(ailp, type, flags, item_lsn); + + flushing++; +- ailp->ail_last_pushed_lsn = lsn; ++ ailp->ail_last_pushed_lsn = item_lsn; + break; + + case XFS_ITEM_PINNED: + XFS_STATS_INC(mp, xs_push_ail_pinned); +- trace_xfs_ail_pinned(lip); ++ trace_xfs_ail_pinned(ailp, type, flags, item_lsn); + + stuck++; + ailp->ail_log_flush++; + break; + case XFS_ITEM_LOCKED: + XFS_STATS_INC(mp, xs_push_ail_locked); +- trace_xfs_ail_locked(lip); ++ trace_xfs_ail_locked(ailp, type, flags, item_lsn); + + stuck++; + break; diff --git a/queue-6.19/xfs-don-t-irele-after-failing-to-iget-in-xfs_attri_recover_work.patch b/queue-6.19/xfs-don-t-irele-after-failing-to-iget-in-xfs_attri_recover_work.patch new file mode 100644 index 0000000000..15b08b32a7 --- /dev/null +++ b/queue-6.19/xfs-don-t-irele-after-failing-to-iget-in-xfs_attri_recover_work.patch @@ -0,0 +1,34 @@ +From 70685c291ef82269180758130394ecdc4496b52c Mon Sep 17 00:00:00 2001 +From: "Darrick J. Wong" +Date: Mon, 23 Mar 2026 14:01:57 -0700 +Subject: xfs: don't irele after failing to iget in xfs_attri_recover_work + +From: Darrick J. Wong + +commit 70685c291ef82269180758130394ecdc4496b52c upstream. + +xlog_recovery_iget* never set @ip to a valid pointer if they return +an error, so this irele will walk off a dangling pointer. Fix that. + +Cc: stable@vger.kernel.org # v6.10 +Fixes: ae673f534a3097 ("xfs: record inode generation in xattr update log intent items") +Signed-off-by: Darrick J. Wong +Reviewed-by: Long Li +Reviewed-by: Christoph Hellwig +Reviewed-by: Carlos Maiolino +Signed-off-by: Carlos Maiolino +Signed-off-by: Greg Kroah-Hartman +--- + fs/xfs/xfs_attr_item.c | 1 - + 1 file changed, 1 deletion(-) + +--- a/fs/xfs/xfs_attr_item.c ++++ b/fs/xfs/xfs_attr_item.c +@@ -656,7 +656,6 @@ xfs_attri_recover_work( + break; + } + if (error) { +- xfs_irele(ip); + XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, attrp, + sizeof(*attrp)); + return ERR_PTR(-EFSCORRUPTED); diff --git a/queue-6.19/xfs-fix-ri_total-validation-in-xlog_recover_attri_commit_pass2.patch b/queue-6.19/xfs-fix-ri_total-validation-in-xlog_recover_attri_commit_pass2.patch new file mode 100644 index 0000000000..4a7c07465e --- /dev/null +++ b/queue-6.19/xfs-fix-ri_total-validation-in-xlog_recover_attri_commit_pass2.patch @@ -0,0 +1,61 @@ +From d72f2084e30966097c8eae762e31986a33c3c0ae Mon Sep 17 00:00:00 2001 +From: Long Li +Date: Fri, 20 Mar 2026 10:11:29 +0800 +Subject: xfs: fix ri_total validation in xlog_recover_attri_commit_pass2 + +From: Long Li + +commit d72f2084e30966097c8eae762e31986a33c3c0ae upstream. + +The ri_total checks for SET/REPLACE operations are hardcoded to 3, +but xfs_attri_item_size() only emits a value iovec when value_len > 0, +so ri_total is 2 when value_len == 0. + +For PPTR_SET/PPTR_REMOVE/PPTR_REPLACE, value_len is validated by +xfs_attri_validate() to be exactly sizeof(struct xfs_parent_rec) and +is never zero, so their hardcoded checks remain correct. + +This problem may cause log recovery failures. The following script can be +used to reproduce the problem: + + #!/bin/bash + mkfs.xfs -f /dev/sda + mount /dev/sda /mnt/test/ + touch /mnt/test/file + for i in {1..200}; do + attr -s "user.attr_$i" -V "value_$i" /mnt/test/file > /dev/null + done + echo 1 > /sys/fs/xfs/debug/larp + echo 1 > /sys/fs/xfs/sda/errortag/larp + attr -s "user.zero" -V "" /mnt/test/file + echo 0 > /sys/fs/xfs/sda/errortag/larp + umount /mnt/test + mount /dev/sda /mnt/test/ # mount failed + +Fix this by deriving the expected count dynamically as "2 + !!value_len" +for SET/REPLACE operations. + +Cc: stable@vger.kernel.org # v6.9 +Fixes: ad206ae50eca ("xfs: check opcode and iovec count match in xlog_recover_attri_commit_pass2") +Reviewed-by: Darrick J. Wong +Signed-off-by: Long Li +Reviewed-by: Christoph Hellwig +Signed-off-by: Carlos Maiolino +Signed-off-by: Greg Kroah-Hartman +--- + fs/xfs/xfs_attr_item.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/fs/xfs/xfs_attr_item.c ++++ b/fs/xfs/xfs_attr_item.c +@@ -1050,8 +1050,8 @@ xlog_recover_attri_commit_pass2( + break; + case XFS_ATTRI_OP_FLAGS_SET: + case XFS_ATTRI_OP_FLAGS_REPLACE: +- /* Log item, attr name, attr value */ +- if (item->ri_total != 3) { ++ /* Log item, attr name, optional attr value */ ++ if (item->ri_total != 2 + !!attri_formatp->alfi_value_len) { + XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, + attri_formatp, len); + return -EFSCORRUPTED; diff --git a/queue-6.19/xfs-remove-file_path-tracepoint-data.patch b/queue-6.19/xfs-remove-file_path-tracepoint-data.patch new file mode 100644 index 0000000000..82a5653fc5 --- /dev/null +++ b/queue-6.19/xfs-remove-file_path-tracepoint-data.patch @@ -0,0 +1,91 @@ +From e31c53a8060e134111ed095783fee0aa0c43b080 Mon Sep 17 00:00:00 2001 +From: "Darrick J. Wong" +Date: Mon, 23 Mar 2026 14:04:33 -0700 +Subject: xfs: remove file_path tracepoint data + +From: Darrick J. Wong + +commit e31c53a8060e134111ed095783fee0aa0c43b080 upstream. + +The xfile/xmbuf shmem file descriptions are no longer as detailed as +they were when online fsck was first merged, because moving to static +strings in commit 60382993a2e180 ("xfs: get rid of the +xchk_xfile_*_descr calls") removed a memory allocation and hence a +source of failure. + +However this makes encoding the description in the tracepoints sort of a +waste of memory. David Laight also points out that file_path doesn't +zero the whole buffer which causes exposure of stale trace bytes, and +Steven Rostedt wonders why we're not using a dynamic array for the file +path. + +I don't think this is worth fixing, so let's just rip it out. + +Cc: rostedt@goodmis.org +Cc: david.laight.linux@gmail.com +Link: https://lore.kernel.org/linux-xfs/20260323172204.work.979-kees@kernel.org/ +Cc: stable@vger.kernel.org # v6.11 +Fixes: 19ebc8f84ea12e ("xfs: fix file_path handling in tracepoints") +Signed-off-by: Darrick J. Wong +Reviewed-by: Carlos Maiolino +Reviewed-by: Christoph Hellwig +Signed-off-by: Carlos Maiolino +Signed-off-by: Greg Kroah-Hartman +--- + fs/xfs/scrub/trace.h | 12 ++---------- + fs/xfs/xfs_trace.h | 11 ++--------- + 2 files changed, 4 insertions(+), 19 deletions(-) + +--- a/fs/xfs/scrub/trace.h ++++ b/fs/xfs/scrub/trace.h +@@ -972,20 +972,12 @@ TRACE_EVENT(xfile_create, + TP_STRUCT__entry( + __field(dev_t, dev) + __field(unsigned long, ino) +- __array(char, pathname, MAXNAMELEN) + ), + TP_fast_assign( +- char *path; +- + __entry->ino = file_inode(xf->file)->i_ino; +- path = file_path(xf->file, __entry->pathname, MAXNAMELEN); +- if (IS_ERR(path)) +- strncpy(__entry->pathname, "(unknown)", +- sizeof(__entry->pathname)); + ), +- TP_printk("xfino 0x%lx path '%s'", +- __entry->ino, +- __entry->pathname) ++ TP_printk("xfino 0x%lx", ++ __entry->ino) + ); + + TRACE_EVENT(xfile_destroy, +--- a/fs/xfs/xfs_trace.h ++++ b/fs/xfs/xfs_trace.h +@@ -5115,23 +5115,16 @@ TRACE_EVENT(xmbuf_create, + TP_STRUCT__entry( + __field(dev_t, dev) + __field(unsigned long, ino) +- __array(char, pathname, MAXNAMELEN) + ), + TP_fast_assign( +- char *path; + struct file *file = btp->bt_file; + + __entry->dev = btp->bt_mount->m_super->s_dev; + __entry->ino = file_inode(file)->i_ino; +- path = file_path(file, __entry->pathname, MAXNAMELEN); +- if (IS_ERR(path)) +- strncpy(__entry->pathname, "(unknown)", +- sizeof(__entry->pathname)); + ), +- TP_printk("dev %d:%d xmino 0x%lx path '%s'", ++ TP_printk("dev %d:%d xmino 0x%lx", + MAJOR(__entry->dev), MINOR(__entry->dev), +- __entry->ino, +- __entry->pathname) ++ __entry->ino) + ); + + TRACE_EVENT(xmbuf_free, diff --git a/queue-6.19/xfs-save-ailp-before-dropping-the-ail-lock-in-push-callbacks.patch b/queue-6.19/xfs-save-ailp-before-dropping-the-ail-lock-in-push-callbacks.patch new file mode 100644 index 0000000000..35339e296a --- /dev/null +++ b/queue-6.19/xfs-save-ailp-before-dropping-the-ail-lock-in-push-callbacks.patch @@ -0,0 +1,98 @@ +From 394d70b86fae9fe865e7e6d9540b7696f73aa9b6 Mon Sep 17 00:00:00 2001 +From: Yuto Ohnuki +Date: Tue, 10 Mar 2026 18:38:39 +0000 +Subject: xfs: save ailp before dropping the AIL lock in push callbacks + +From: Yuto Ohnuki + +commit 394d70b86fae9fe865e7e6d9540b7696f73aa9b6 upstream. + +In xfs_inode_item_push() and xfs_qm_dquot_logitem_push(), the AIL lock +is dropped to perform buffer IO. Once the cluster buffer no longer +protects the log item from reclaim, the log item may be freed by +background reclaim or the dquot shrinker. The subsequent spin_lock() +call dereferences lip->li_ailp, which is a use-after-free. + +Fix this by saving the ailp pointer in a local variable while the AIL +lock is held and the log item is guaranteed to be valid. + +Reported-by: syzbot+652af2b3c5569c4ab63c@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=652af2b3c5569c4ab63c +Fixes: 90c60e164012 ("xfs: xfs_iflush() is no longer necessary") +Cc: stable@vger.kernel.org # v5.9 +Reviewed-by: Darrick J. Wong +Reviewed-by: Dave Chinner +Signed-off-by: Yuto Ohnuki +Signed-off-by: Carlos Maiolino +Signed-off-by: Greg Kroah-Hartman +--- + fs/xfs/xfs_dquot_item.c | 9 +++++++-- + fs/xfs/xfs_inode_item.c | 9 +++++++-- + 2 files changed, 14 insertions(+), 4 deletions(-) + +--- a/fs/xfs/xfs_dquot_item.c ++++ b/fs/xfs/xfs_dquot_item.c +@@ -126,6 +126,7 @@ xfs_qm_dquot_logitem_push( + struct xfs_dq_logitem *qlip = DQUOT_ITEM(lip); + struct xfs_dquot *dqp = qlip->qli_dquot; + struct xfs_buf *bp; ++ struct xfs_ail *ailp = lip->li_ailp; + uint rval = XFS_ITEM_SUCCESS; + int error; + +@@ -154,7 +155,7 @@ xfs_qm_dquot_logitem_push( + goto out_unlock; + } + +- spin_unlock(&lip->li_ailp->ail_lock); ++ spin_unlock(&ailp->ail_lock); + + error = xfs_dquot_use_attached_buf(dqp, &bp); + if (error == -EAGAIN) { +@@ -173,9 +174,13 @@ xfs_qm_dquot_logitem_push( + rval = XFS_ITEM_FLUSHING; + } + xfs_buf_relse(bp); ++ /* ++ * The buffer no longer protects the log item from reclaim, so ++ * do not reference lip after this point. ++ */ + + out_relock_ail: +- spin_lock(&lip->li_ailp->ail_lock); ++ spin_lock(&ailp->ail_lock); + out_unlock: + mutex_unlock(&dqp->q_qlock); + return rval; +--- a/fs/xfs/xfs_inode_item.c ++++ b/fs/xfs/xfs_inode_item.c +@@ -749,6 +749,7 @@ xfs_inode_item_push( + struct xfs_inode_log_item *iip = INODE_ITEM(lip); + struct xfs_inode *ip = iip->ili_inode; + struct xfs_buf *bp = lip->li_buf; ++ struct xfs_ail *ailp = lip->li_ailp; + uint rval = XFS_ITEM_SUCCESS; + int error; + +@@ -774,7 +775,7 @@ xfs_inode_item_push( + if (!xfs_buf_trylock(bp)) + return XFS_ITEM_LOCKED; + +- spin_unlock(&lip->li_ailp->ail_lock); ++ spin_unlock(&ailp->ail_lock); + + /* + * We need to hold a reference for flushing the cluster buffer as it may +@@ -798,7 +799,11 @@ xfs_inode_item_push( + rval = XFS_ITEM_LOCKED; + } + +- spin_lock(&lip->li_ailp->ail_lock); ++ /* ++ * The buffer no longer protects the log item from reclaim, so ++ * do not reference lip after this point. ++ */ ++ spin_lock(&ailp->ail_lock); + return rval; + } + diff --git a/queue-6.19/xfs-scrub-unlock-dquot-before-early-return-in-quota-scrub.patch b/queue-6.19/xfs-scrub-unlock-dquot-before-early-return-in-quota-scrub.patch new file mode 100644 index 0000000000..8bd83c3351 --- /dev/null +++ b/queue-6.19/xfs-scrub-unlock-dquot-before-early-return-in-quota-scrub.patch @@ -0,0 +1,40 @@ +From 268378b6ad20569af0d1957992de1c8b16c6e900 Mon Sep 17 00:00:00 2001 +From: hongao +Date: Thu, 12 Mar 2026 20:10:26 +0800 +Subject: xfs: scrub: unlock dquot before early return in quota scrub + +From: hongao + +commit 268378b6ad20569af0d1957992de1c8b16c6e900 upstream. + +xchk_quota_item can return early after calling xchk_fblock_process_error. +When that helper returns false, the function returned immediately without +dropping dq->q_qlock, which can leave the dquot lock held and risk lock +leaks or deadlocks in later quota operations. + +Fix this by unlocking dq->q_qlock before the early return. + +Signed-off-by: hongao +Fixes: 7d1f0e167a067e ("xfs: check the ondisk space mapping behind a dquot") +Cc: # v6.8 +Reviewed-by: Darrick J. Wong +Signed-off-by: Carlos Maiolino +Signed-off-by: Greg Kroah-Hartman +--- + fs/xfs/scrub/quota.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/fs/xfs/scrub/quota.c ++++ b/fs/xfs/scrub/quota.c +@@ -171,8 +171,10 @@ xchk_quota_item( + + error = xchk_quota_item_bmap(sc, dq, offset); + xchk_iunlock(sc, XFS_ILOCK_SHARED); +- if (!xchk_fblock_process_error(sc, XFS_DATA_FORK, offset, &error)) ++ if (!xchk_fblock_process_error(sc, XFS_DATA_FORK, offset, &error)) { ++ mutex_unlock(&dq->q_qlock); + return error; ++ } + + /* + * Warn if the hard limits are larger than the fs. diff --git a/queue-6.19/xfs-stop-reclaim-before-pushing-ail-during-unmount.patch b/queue-6.19/xfs-stop-reclaim-before-pushing-ail-during-unmount.patch new file mode 100644 index 0000000000..09a0c4815e --- /dev/null +++ b/queue-6.19/xfs-stop-reclaim-before-pushing-ail-during-unmount.patch @@ -0,0 +1,58 @@ +From 4f24a767e3d64a5f58c595b5c29b6063a201f1e3 Mon Sep 17 00:00:00 2001 +From: Yuto Ohnuki +Date: Tue, 10 Mar 2026 18:38:37 +0000 +Subject: xfs: stop reclaim before pushing AIL during unmount + +From: Yuto Ohnuki + +commit 4f24a767e3d64a5f58c595b5c29b6063a201f1e3 upstream. + +The unmount sequence in xfs_unmount_flush_inodes() pushed the AIL while +background reclaim and inodegc are still running. This is broken +independently of any use-after-free issues - background reclaim and +inodegc should not be running while the AIL is being pushed during +unmount, as inodegc can dirty and insert inodes into the AIL during the +flush, and background reclaim can race to abort and free dirty inodes. + +Reorder xfs_unmount_flush_inodes() to stop inodegc and cancel background +reclaim before pushing the AIL. Stop inodegc before cancelling +m_reclaim_work because the inodegc worker can re-queue m_reclaim_work +via xfs_inodegc_set_reclaimable. + +Reported-by: syzbot+652af2b3c5569c4ab63c@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=652af2b3c5569c4ab63c +Fixes: 90c60e164012 ("xfs: xfs_iflush() is no longer necessary") +Cc: stable@vger.kernel.org # v5.9 +Signed-off-by: Yuto Ohnuki +Reviewed-by: Darrick J. Wong +Signed-off-by: Carlos Maiolino +Signed-off-by: Greg Kroah-Hartman +--- + fs/xfs/xfs_mount.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +--- a/fs/xfs/xfs_mount.c ++++ b/fs/xfs/xfs_mount.c +@@ -607,8 +607,9 @@ xfs_unmount_check( + * have been retrying in the background. This will prevent never-ending + * retries in AIL pushing from hanging the unmount. + * +- * Finally, we can push the AIL to clean all the remaining dirty objects, then +- * reclaim the remaining inodes that are still in memory at this point in time. ++ * Stop inodegc and background reclaim before pushing the AIL so that they ++ * are not running while the AIL is being flushed. Then push the AIL to ++ * clean all the remaining dirty objects and reclaim the remaining inodes. + */ + static void + xfs_unmount_flush_inodes( +@@ -620,9 +621,9 @@ xfs_unmount_flush_inodes( + + xfs_set_unmounting(mp); + +- xfs_ail_push_all_sync(mp->m_ail); + xfs_inodegc_stop(mp); + cancel_delayed_work_sync(&mp->m_reclaim_work); ++ xfs_ail_push_all_sync(mp->m_ail); + xfs_reclaim_inodes(mp); + xfs_health_unmount(mp); + }