From: Sasha Levin Date: Thu, 22 May 2025 20:52:55 +0000 (-0400) Subject: Fixes for 6.14 X-Git-Tag: v6.12.31~99 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=6d129aa607b83c52df065877d709e04012e1d741;p=thirdparty%2Fkernel%2Fstable-queue.git Fixes for 6.14 Signed-off-by: Sasha Levin --- diff --git a/queue-6.14/__legitimize_mnt-check-for-mnt_sync_umount-should-be.patch b/queue-6.14/__legitimize_mnt-check-for-mnt_sync_umount-should-be.patch new file mode 100644 index 0000000000..4c3f9c2a60 --- /dev/null +++ b/queue-6.14/__legitimize_mnt-check-for-mnt_sync_umount-should-be.patch @@ -0,0 +1,48 @@ +From bb47ca1b09f9e86b283d1d407f1d06c06298cf8d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 27 Apr 2025 15:41:51 -0400 +Subject: __legitimize_mnt(): check for MNT_SYNC_UMOUNT should be under + mount_lock + +From: Al Viro + +[ Upstream commit 250cf3693060a5f803c5f1ddc082bb06b16112a9 ] + +... or we risk stealing final mntput from sync umount - raising mnt_count +after umount(2) has verified that victim is not busy, but before it +has set MNT_SYNC_UMOUNT; in that case __legitimize_mnt() doesn't see +that it's safe to quietly undo mnt_count increment and leaves dropping +the reference to caller, where it'll be a full-blown mntput(). + +Check under mount_lock is needed; leaving the current one done before +taking that makes no sense - it's nowhere near common enough to bother +with. + +Reviewed-by: Christian Brauner +Signed-off-by: Al Viro +Signed-off-by: Sasha Levin +--- + fs/namespace.c | 6 +----- + 1 file changed, 1 insertion(+), 5 deletions(-) + +diff --git a/fs/namespace.c b/fs/namespace.c +index 5b84e29613fe4..1d950974d67ee 100644 +--- a/fs/namespace.c ++++ b/fs/namespace.c +@@ -781,12 +781,8 @@ int __legitimize_mnt(struct vfsmount *bastard, unsigned seq) + smp_mb(); // see mntput_no_expire() and do_umount() + if (likely(!read_seqretry(&mount_lock, seq))) + return 0; +- if (bastard->mnt_flags & MNT_SYNC_UMOUNT) { +- mnt_add_count(mnt, -1); +- return 1; +- } + lock_mount_hash(); +- if (unlikely(bastard->mnt_flags & MNT_DOOMED)) { ++ if (unlikely(bastard->mnt_flags & (MNT_SYNC_UMOUNT | MNT_DOOMED))) { + mnt_add_count(mnt, -1); + unlock_mount_hash(); + return 1; +-- +2.39.5 + diff --git a/queue-6.14/accel-amdxdna-check-interrupt-register-before-mailbo.patch b/queue-6.14/accel-amdxdna-check-interrupt-register-before-mailbo.patch new file mode 100644 index 0000000000..d35edf39b5 --- /dev/null +++ b/queue-6.14/accel-amdxdna-check-interrupt-register-before-mailbo.patch @@ -0,0 +1,75 @@ +From ae7c837e427b3d8b084c423693b0ece0575c78fc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 26 Feb 2025 08:18:10 -0800 +Subject: accel/amdxdna: Check interrupt register before mailbox_rx_worker + exits + +From: Lizhi Hou + +[ Upstream commit cd740b873f8f6f5f4558723241ba9c09eb36d0ba ] + +There is a timeout failure been found during stress tests. If the firmware +generates a mailbox response right after driver clears the mailbox channel +interrupt register, the hardware will not generate an interrupt for the +response. This causes the unexpected mailbox command timeout. + +To handle this failure, driver checks the interrupt register before +exiting mailbox_rx_worker(). If there is a new response, driver goes back +to process it. + +Signed-off-by: Lizhi Hou +Reviewed-by: Jacek Lawrynowicz +Signed-off-by: Mario Limonciello +Link: https://patchwork.freedesktop.org/patch/msgid/20250226161810.4188334-1-lizhi.hou@amd.com +Signed-off-by: Sasha Levin +--- + drivers/accel/amdxdna/amdxdna_mailbox.c | 17 +++++++++++++---- + 1 file changed, 13 insertions(+), 4 deletions(-) + +diff --git a/drivers/accel/amdxdna/amdxdna_mailbox.c b/drivers/accel/amdxdna/amdxdna_mailbox.c +index e5301fac13971..2879e4149c937 100644 +--- a/drivers/accel/amdxdna/amdxdna_mailbox.c ++++ b/drivers/accel/amdxdna/amdxdna_mailbox.c +@@ -349,8 +349,6 @@ static irqreturn_t mailbox_irq_handler(int irq, void *p) + trace_mbox_irq_handle(MAILBOX_NAME, irq); + /* Schedule a rx_work to call the callback functions */ + queue_work(mb_chann->work_q, &mb_chann->rx_work); +- /* Clear IOHUB register */ +- mailbox_reg_write(mb_chann, mb_chann->iohub_int_addr, 0); + + return IRQ_HANDLED; + } +@@ -367,6 +365,9 @@ static void mailbox_rx_worker(struct work_struct *rx_work) + return; + } + ++again: ++ mailbox_reg_write(mb_chann, mb_chann->iohub_int_addr, 0); ++ + while (1) { + /* + * If return is 0, keep consuming next message, until there is +@@ -380,10 +381,18 @@ static void mailbox_rx_worker(struct work_struct *rx_work) + if (unlikely(ret)) { + MB_ERR(mb_chann, "Unexpected ret %d, disable irq", ret); + WRITE_ONCE(mb_chann->bad_state, true); +- disable_irq(mb_chann->msix_irq); +- break; ++ return; + } + } ++ ++ /* ++ * The hardware will not generate interrupt if firmware creates a new ++ * response right after driver clears interrupt register. Check ++ * the interrupt register to make sure there is not any new response ++ * before exiting. ++ */ ++ if (mailbox_reg_read(mb_chann, mb_chann->iohub_int_addr)) ++ goto again; + } + + int xdna_mailbox_send_msg(struct mailbox_channel *mb_chann, +-- +2.39.5 + diff --git a/queue-6.14/accel-amdxdna-refactor-hardware-context-destroy-rout.patch b/queue-6.14/accel-amdxdna-refactor-hardware-context-destroy-rout.patch new file mode 100644 index 0000000000..82472bc4c1 --- /dev/null +++ b/queue-6.14/accel-amdxdna-refactor-hardware-context-destroy-rout.patch @@ -0,0 +1,136 @@ +From 0b21199630538e476b7cba82f81a93af065a3677 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 24 Jan 2025 09:35:36 -0800 +Subject: accel/amdxdna: Refactor hardware context destroy routine + +From: Lizhi Hou + +[ Upstream commit 4fd6ca90fc7f509977585d39885f21b2911123f3 ] + +It is required by firmware to wait up to 2 seconds for pending commands +before sending the destroy hardware context command. After 2 seconds +wait, if there are still pending commands, driver needs to cancel them. + +So the context destroy steps need to be: + 1. Stop drm scheduler. (drm_sched_entity_destroy) + 2. Wait up to 2 seconds for pending commands. + 3. Destroy hardware context and cancel the rest pending requests. + 4. Wait all jobs associated with the hwctx are freed. + 5. Free job resources. + +Signed-off-by: Lizhi Hou +Reviewed-by: Jeffrey Hugo +Signed-off-by: Jeffrey Hugo +Link: https://patchwork.freedesktop.org/patch/msgid/20250124173536.148676-1-lizhi.hou@amd.com +Signed-off-by: Sasha Levin +--- + drivers/accel/amdxdna/aie2_ctx.c | 29 ++++++++++++++++------------- + drivers/accel/amdxdna/amdxdna_ctx.c | 2 ++ + drivers/accel/amdxdna/amdxdna_ctx.h | 3 +++ + 3 files changed, 21 insertions(+), 13 deletions(-) + +diff --git a/drivers/accel/amdxdna/aie2_ctx.c b/drivers/accel/amdxdna/aie2_ctx.c +index 5f43db02b2404..92c768b0c9a03 100644 +--- a/drivers/accel/amdxdna/aie2_ctx.c ++++ b/drivers/accel/amdxdna/aie2_ctx.c +@@ -34,6 +34,8 @@ static void aie2_job_release(struct kref *ref) + + job = container_of(ref, struct amdxdna_sched_job, refcnt); + amdxdna_sched_job_cleanup(job); ++ atomic64_inc(&job->hwctx->job_free_cnt); ++ wake_up(&job->hwctx->priv->job_free_wq); + if (job->out_fence) + dma_fence_put(job->out_fence); + kfree(job); +@@ -134,7 +136,8 @@ static void aie2_hwctx_wait_for_idle(struct amdxdna_hwctx *hwctx) + if (!fence) + return; + +- dma_fence_wait(fence, false); ++ /* Wait up to 2 seconds for fw to finish all pending requests */ ++ dma_fence_wait_timeout(fence, false, msecs_to_jiffies(2000)); + dma_fence_put(fence); + } + +@@ -616,6 +619,7 @@ int aie2_hwctx_init(struct amdxdna_hwctx *hwctx) + hwctx->status = HWCTX_STAT_INIT; + ndev = xdna->dev_handle; + ndev->hwctx_num++; ++ init_waitqueue_head(&priv->job_free_wq); + + XDNA_DBG(xdna, "hwctx %s init completed", hwctx->name); + +@@ -652,25 +656,23 @@ void aie2_hwctx_fini(struct amdxdna_hwctx *hwctx) + xdna = hwctx->client->xdna; + ndev = xdna->dev_handle; + ndev->hwctx_num--; +- drm_sched_wqueue_stop(&hwctx->priv->sched); + +- /* Now, scheduler will not send command to device. */ ++ XDNA_DBG(xdna, "%s sequence number %lld", hwctx->name, hwctx->priv->seq); ++ drm_sched_entity_destroy(&hwctx->priv->entity); ++ ++ aie2_hwctx_wait_for_idle(hwctx); ++ ++ /* Request fw to destroy hwctx and cancel the rest pending requests */ + aie2_release_resource(hwctx); + +- /* +- * All submitted commands are aborted. +- * Restart scheduler queues to cleanup jobs. The amdxdna_sched_job_run() +- * will return NODEV if it is called. +- */ +- drm_sched_wqueue_start(&hwctx->priv->sched); ++ /* Wait for all submitted jobs to be completed or canceled */ ++ wait_event(hwctx->priv->job_free_wq, ++ atomic64_read(&hwctx->job_submit_cnt) == ++ atomic64_read(&hwctx->job_free_cnt)); + +- aie2_hwctx_wait_for_idle(hwctx); +- drm_sched_entity_destroy(&hwctx->priv->entity); + drm_sched_fini(&hwctx->priv->sched); + aie2_ctx_syncobj_destroy(hwctx); + +- XDNA_DBG(xdna, "%s sequence number %lld", hwctx->name, hwctx->priv->seq); +- + for (idx = 0; idx < ARRAY_SIZE(hwctx->priv->cmd_buf); idx++) + drm_gem_object_put(to_gobj(hwctx->priv->cmd_buf[idx])); + amdxdna_gem_unpin(hwctx->priv->heap); +@@ -879,6 +881,7 @@ int aie2_cmd_submit(struct amdxdna_hwctx *hwctx, struct amdxdna_sched_job *job, + drm_gem_unlock_reservations(job->bos, job->bo_cnt, &acquire_ctx); + + aie2_job_put(job); ++ atomic64_inc(&hwctx->job_submit_cnt); + + return 0; + +diff --git a/drivers/accel/amdxdna/amdxdna_ctx.c b/drivers/accel/amdxdna/amdxdna_ctx.c +index d11b1c83d9c3b..43442b9e273b3 100644 +--- a/drivers/accel/amdxdna/amdxdna_ctx.c ++++ b/drivers/accel/amdxdna/amdxdna_ctx.c +@@ -220,6 +220,8 @@ int amdxdna_drm_create_hwctx_ioctl(struct drm_device *dev, void *data, struct dr + args->syncobj_handle = hwctx->syncobj_hdl; + mutex_unlock(&xdna->dev_lock); + ++ atomic64_set(&hwctx->job_submit_cnt, 0); ++ atomic64_set(&hwctx->job_free_cnt, 0); + XDNA_DBG(xdna, "PID %d create HW context %d, ret %d", client->pid, args->handle, ret); + drm_dev_exit(idx); + return 0; +diff --git a/drivers/accel/amdxdna/amdxdna_ctx.h b/drivers/accel/amdxdna/amdxdna_ctx.h +index 80b0304193ec3..f0a4a8586d858 100644 +--- a/drivers/accel/amdxdna/amdxdna_ctx.h ++++ b/drivers/accel/amdxdna/amdxdna_ctx.h +@@ -87,6 +87,9 @@ struct amdxdna_hwctx { + struct amdxdna_qos_info qos; + struct amdxdna_hwctx_param_config_cu *cus; + u32 syncobj_hdl; ++ ++ atomic64_t job_submit_cnt; ++ atomic64_t job_free_cnt ____cacheline_aligned_in_smp; + }; + + #define drm_job_to_xdna_job(j) \ +-- +2.39.5 + diff --git a/queue-6.14/accel-qaic-mask-out-sr-iov-pci-resources.patch b/queue-6.14/accel-qaic-mask-out-sr-iov-pci-resources.patch new file mode 100644 index 0000000000..a7bb34215d --- /dev/null +++ b/queue-6.14/accel-qaic-mask-out-sr-iov-pci-resources.patch @@ -0,0 +1,42 @@ +From 1304a765615a2dff12582f48b9a380b46f4b19e7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 17 Jan 2025 10:09:41 -0700 +Subject: accel/qaic: Mask out SR-IOV PCI resources + +From: Youssef Samir + +[ Upstream commit 8685520474bfc0fe4be83c3cbfe3fb3e1ca1514a ] + +During the initialization of the qaic device, pci_select_bars() is +used to fetch a bitmask of the BARs exposed by the device. On devices +that have Virtual Functions capabilities, the bitmask includes SR-IOV +BARs. + +Use a mask to filter out SR-IOV BARs if they exist. + +Signed-off-by: Youssef Samir +Reviewed-by: Jeffrey Hugo +Signed-off-by: Jeffrey Hugo +Reviewed-by: Lizhi Hou +Link: https://patchwork.freedesktop.org/patch/msgid/20250117170943.2643280-6-quic_jhugo@quicinc.com +Signed-off-by: Sasha Levin +--- + drivers/accel/qaic/qaic_drv.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/accel/qaic/qaic_drv.c b/drivers/accel/qaic/qaic_drv.c +index 81819b9ef8d4f..32f0e81d3e304 100644 +--- a/drivers/accel/qaic/qaic_drv.c ++++ b/drivers/accel/qaic/qaic_drv.c +@@ -431,7 +431,7 @@ static int init_pci(struct qaic_device *qdev, struct pci_dev *pdev) + int bars; + int ret; + +- bars = pci_select_bars(pdev, IORESOURCE_MEM); ++ bars = pci_select_bars(pdev, IORESOURCE_MEM) & 0x3f; + + /* make sure the device has the expected BARs */ + if (bars != (BIT(0) | BIT(2) | BIT(4))) { +-- +2.39.5 + diff --git a/queue-6.14/acpi-hed-always-initialize-before-evged.patch b/queue-6.14/acpi-hed-always-initialize-before-evged.patch new file mode 100644 index 0000000000..80a1b2076e --- /dev/null +++ b/queue-6.14/acpi-hed-always-initialize-before-evged.patch @@ -0,0 +1,67 @@ +From b154e21854951532ae9fa74194b0104a4acc8eed Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 12 Feb 2025 14:34:08 +0800 +Subject: ACPI: HED: Always initialize before evged + +From: Xiaofei Tan + +[ Upstream commit cccf6ee090c8c133072d5d5b52ae25f3bc907a16 ] + +When the HED driver is built-in, it initializes after evged because they +both are at the same initcall level, so the initialization ordering +depends on the Makefile order. However, this prevents RAS records +coming in between the evged driver initialization and the HED driver +initialization from being handled. + +If the number of such RAS records is above the APEI HEST error source +number, the HEST resources may be exhausted, and that may affect +subsequent RAS error reporting. + +To fix this issue, change the initcall level of HED to subsys_initcall +and prevent the driver from being built as a module by changing ACPI_HED +in Kconfig from "tristate" to "bool". + +Signed-off-by: Xiaofei Tan +Link: https://patch.msgid.link/20250212063408.927666-1-tanxiaofei@huawei.com +[ rjw: Changelog edits ] +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Sasha Levin +--- + drivers/acpi/Kconfig | 2 +- + drivers/acpi/hed.c | 7 ++++++- + 2 files changed, 7 insertions(+), 2 deletions(-) + +diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig +index d81b55f5068c4..7f10aa38269d2 100644 +--- a/drivers/acpi/Kconfig ++++ b/drivers/acpi/Kconfig +@@ -452,7 +452,7 @@ config ACPI_SBS + the modules will be called sbs and sbshc. + + config ACPI_HED +- tristate "Hardware Error Device" ++ bool "Hardware Error Device" + help + This driver supports the Hardware Error Device (PNP0C33), + which is used to report some hardware errors notified via +diff --git a/drivers/acpi/hed.c b/drivers/acpi/hed.c +index 7652515a6be1e..3499f86c411e3 100644 +--- a/drivers/acpi/hed.c ++++ b/drivers/acpi/hed.c +@@ -80,7 +80,12 @@ static struct acpi_driver acpi_hed_driver = { + .remove = acpi_hed_remove, + }, + }; +-module_acpi_driver(acpi_hed_driver); ++ ++static int __init acpi_hed_driver_init(void) ++{ ++ return acpi_bus_register_driver(&acpi_hed_driver); ++} ++subsys_initcall(acpi_hed_driver_init); + + MODULE_AUTHOR("Huang Ying"); + MODULE_DESCRIPTION("ACPI Hardware Error Device Driver"); +-- +2.39.5 + diff --git a/queue-6.14/acpi-pnp-add-intel-oc-watchdog-ids-to-non-pnp-device.patch b/queue-6.14/acpi-pnp-add-intel-oc-watchdog-ids-to-non-pnp-device.patch new file mode 100644 index 0000000000..b878a5dd65 --- /dev/null +++ b/queue-6.14/acpi-pnp-add-intel-oc-watchdog-ids-to-non-pnp-device.patch @@ -0,0 +1,46 @@ +From fa541dc05f19df98d52c8a54514358948887d8a7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Mar 2025 10:55:07 +0000 +Subject: ACPI: PNP: Add Intel OC Watchdog IDs to non-PNP device list + +From: Diogo Ivo + +[ Upstream commit f06777cf2bbc21dd8c71d6e3906934e56b4e18e4 ] + +Intel Over-Clocking Watchdogs are described in ACPI tables by both the +generic PNP0C02 _CID and their ACPI _HID. The presence of the _CID then +causes the PNP scan handler to attach to the watchdog, preventing the +actual watchdog driver from binding. Address this by adding the ACPI +_HIDs to the list of non-PNP devices, so that the PNP scan handler is +bypassed. + +Note that these watchdogs can be described by multiple _HIDs for what +seems to be identical hardware. This commit is not a complete list of +all the possible watchdog ACPI _HIDs. + +Signed-off-by: Diogo Ivo +Link: https://patch.msgid.link/20250317-ivo-intel_oc_wdt-v3-2-32c396f4eefd@siemens.com +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Sasha Levin +--- + drivers/acpi/acpi_pnp.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/acpi/acpi_pnp.c b/drivers/acpi/acpi_pnp.c +index 01abf26764b00..3f5a1840f5733 100644 +--- a/drivers/acpi/acpi_pnp.c ++++ b/drivers/acpi/acpi_pnp.c +@@ -355,8 +355,10 @@ static bool acpi_pnp_match(const char *idstr, const struct acpi_device_id **matc + * device represented by it. + */ + static const struct acpi_device_id acpi_nonpnp_device_ids[] = { ++ {"INT3F0D"}, + {"INTC1080"}, + {"INTC1081"}, ++ {"INTC1099"}, + {""}, + }; + +-- +2.39.5 + diff --git a/queue-6.14/alsa-hda-realtek-add-quirk-for-hp-spectre-x360-15-df.patch b/queue-6.14/alsa-hda-realtek-add-quirk-for-hp-spectre-x360-15-df.patch new file mode 100644 index 0000000000..c4c467c4b7 --- /dev/null +++ b/queue-6.14/alsa-hda-realtek-add-quirk-for-hp-spectre-x360-15-df.patch @@ -0,0 +1,106 @@ +From 42e496546d7c77c218854fd914f7789a116889c9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 27 Apr 2025 10:10:34 +0200 +Subject: ALSA: hda/realtek: Add quirk for HP Spectre x360 15-df1xxx + +From: Takashi Iwai + +[ Upstream commit be0c40da888840fe91b45474cb70779e6cbaf7ca ] + +HP Spectre x360 15-df1xxx with SSID 13c:863e requires similar +workarounds that were applied to another HP Spectre x360 models; +it has a mute LED only, no micmute LEDs, and needs the speaker GPIO +seup. + +Link: https://bugzilla.kernel.org/show_bug.cgi?id=220054 +Link: https://patch.msgid.link/20250427081035.11567-1-tiwai@suse.de +Signed-off-by: Takashi Iwai +Signed-off-by: Sasha Levin +--- + sound/pci/hda/patch_realtek.c | 42 +++++++++++++++++++++++++++++++++++ + 1 file changed, 42 insertions(+) + +diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c +index 025c80fa68b05..244fb8f9989b4 100644 +--- a/sound/pci/hda/patch_realtek.c ++++ b/sound/pci/hda/patch_realtek.c +@@ -6963,6 +6963,41 @@ static void alc285_fixup_hp_spectre_x360_eb1(struct hda_codec *codec, + } + } + ++/* GPIO1 = amplifier on/off */ ++static void alc285_fixup_hp_spectre_x360_df1(struct hda_codec *codec, ++ const struct hda_fixup *fix, ++ int action) ++{ ++ struct alc_spec *spec = codec->spec; ++ static const hda_nid_t conn[] = { 0x02 }; ++ static const struct hda_pintbl pincfgs[] = { ++ { 0x14, 0x90170110 }, /* front/high speakers */ ++ { 0x17, 0x90170130 }, /* back/bass speakers */ ++ { } ++ }; ++ ++ // enable mute led ++ alc285_fixup_hp_mute_led_coefbit(codec, fix, action); ++ ++ switch (action) { ++ case HDA_FIXUP_ACT_PRE_PROBE: ++ /* needed for amp of back speakers */ ++ spec->gpio_mask |= 0x01; ++ spec->gpio_dir |= 0x01; ++ snd_hda_apply_pincfgs(codec, pincfgs); ++ /* share DAC to have unified volume control */ ++ snd_hda_override_conn_list(codec, 0x14, ARRAY_SIZE(conn), conn); ++ snd_hda_override_conn_list(codec, 0x17, ARRAY_SIZE(conn), conn); ++ break; ++ case HDA_FIXUP_ACT_INIT: ++ /* need to toggle GPIO to enable the amp of back speakers */ ++ alc_update_gpio_data(codec, 0x01, true); ++ msleep(100); ++ alc_update_gpio_data(codec, 0x01, false); ++ break; ++ } ++} ++ + static void alc285_fixup_hp_spectre_x360(struct hda_codec *codec, + const struct hda_fixup *fix, int action) + { +@@ -7743,6 +7778,7 @@ enum { + ALC280_FIXUP_HP_9480M, + ALC245_FIXUP_HP_X360_AMP, + ALC285_FIXUP_HP_SPECTRE_X360_EB1, ++ ALC285_FIXUP_HP_SPECTRE_X360_DF1, + ALC285_FIXUP_HP_ENVY_X360, + ALC288_FIXUP_DELL_HEADSET_MODE, + ALC288_FIXUP_DELL1_MIC_NO_PRESENCE, +@@ -9818,6 +9854,10 @@ static const struct hda_fixup alc269_fixups[] = { + .type = HDA_FIXUP_FUNC, + .v.func = alc285_fixup_hp_spectre_x360_eb1 + }, ++ [ALC285_FIXUP_HP_SPECTRE_X360_DF1] = { ++ .type = HDA_FIXUP_FUNC, ++ .v.func = alc285_fixup_hp_spectre_x360_df1 ++ }, + [ALC285_FIXUP_HP_ENVY_X360] = { + .type = HDA_FIXUP_FUNC, + .v.func = alc285_fixup_hp_envy_x360, +@@ -10541,6 +10581,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = { + SND_PCI_QUIRK(0x103c, 0x86c1, "HP Laptop 15-da3001TU", ALC236_FIXUP_HP_MUTE_LED_COEFBIT2), + SND_PCI_QUIRK(0x103c, 0x86c7, "HP Envy AiO 32", ALC274_FIXUP_HP_ENVY_GPIO), + SND_PCI_QUIRK(0x103c, 0x86e7, "HP Spectre x360 15-eb0xxx", ALC285_FIXUP_HP_SPECTRE_X360_EB1), ++ SND_PCI_QUIRK(0x103c, 0x863e, "HP Spectre x360 15-df1xxx", ALC285_FIXUP_HP_SPECTRE_X360_DF1), + SND_PCI_QUIRK(0x103c, 0x86e8, "HP Spectre x360 15-eb0xxx", ALC285_FIXUP_HP_SPECTRE_X360_EB1), + SND_PCI_QUIRK(0x103c, 0x86f9, "HP Spectre x360 13-aw0xxx", ALC285_FIXUP_HP_SPECTRE_X360_MUTE_LED), + SND_PCI_QUIRK(0x103c, 0x8716, "HP Elite Dragonfly G2 Notebook PC", ALC285_FIXUP_HP_GPIO_AMP_INIT), +@@ -11457,6 +11498,7 @@ static const struct hda_model_fixup alc269_fixup_models[] = { + {.id = ALC295_FIXUP_HP_OMEN, .name = "alc295-hp-omen"}, + {.id = ALC285_FIXUP_HP_SPECTRE_X360, .name = "alc285-hp-spectre-x360"}, + {.id = ALC285_FIXUP_HP_SPECTRE_X360_EB1, .name = "alc285-hp-spectre-x360-eb1"}, ++ {.id = ALC285_FIXUP_HP_SPECTRE_X360_DF1, .name = "alc285-hp-spectre-x360-df1"}, + {.id = ALC285_FIXUP_HP_ENVY_X360, .name = "alc285-hp-envy-x360"}, + {.id = ALC287_FIXUP_IDEAPAD_BASS_SPK_AMP, .name = "alc287-ideapad-bass-spk-amp"}, + {.id = ALC287_FIXUP_YOGA9_14IAP7_BASS_SPK_PIN, .name = "alc287-yoga9-bass-spk-pin"}, +-- +2.39.5 + diff --git a/queue-6.14/alsa-hda-realtek-enable-pc-beep-passthrough-for-hp-e.patch b/queue-6.14/alsa-hda-realtek-enable-pc-beep-passthrough-for-hp-e.patch new file mode 100644 index 0000000000..54c6bd19e0 --- /dev/null +++ b/queue-6.14/alsa-hda-realtek-enable-pc-beep-passthrough-for-hp-e.patch @@ -0,0 +1,177 @@ +From 976f14b1c5d78c5420accbbc025a0cb9c1a37b9e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 16 Feb 2025 22:31:03 +0100 +Subject: ALSA: hda/realtek: Enable PC beep passthrough for HP EliteBook 855 G7 + +From: Maciej S. Szmigiero + +[ Upstream commit aa85822c611aef7cd4dc17d27121d43e21bb82f0 ] + +PC speaker works well on this platform in BIOS and in Linux until sound +card drivers are loaded. Then it stops working. + +There seems to be a beep generator node at 0x1a in this CODEC +(ALC269_TYPE_ALC215) but it seems to be only connected to capture mixers +at nodes 0x22 and 0x23. +If I unmute the mixer input for 0x1a at node 0x23 and start recording +from its "ALC285 Analog" capture device I can clearly hear beeps in that +recording. + +So the beep generator is indeed working properly, however I wasn't able to +figure out any way to connect it to speakers. + +However, the bits in the "Passthrough Control" register (0x36) seems to +work at least partially: by zeroing "B" and "h" and setting "S" I can at +least make the PIT PC speaker output appear either in this laptop speakers +or headphones (depending on whether they are connected or not). + +There are some caveats, however: +* If the CODEC gets runtime-suspended the beeps stop so it needs HDA beep +device for keeping it awake during beeping. + +* If the beep generator node is generating any beep the PC beep passthrough +seems to be temporarily inhibited, so the HDA beep device has to be +prevented from using the actual beep generator node - but the beep device +is still necessary due to the previous point. + +* In contrast with other platforms here beep amplification has to be +disabled otherwise the beeps output are WAY louder than they were on pure +BIOS setup. + +Unless someone (from Realtek probably) knows how to make the beep generator +node output appear in speakers / headphones using PC beep passthrough seems +to be the only way to make PC speaker beeping actually work on this +platform. + +Signed-off-by: Maciej S. Szmigiero +Acked-by: kailang@realtek.com +Link: https://patch.msgid.link/7461f695b4daed80f2fc4b1463ead47f04f9ad05.1739741254.git.mail@maciej.szmigiero.name +Signed-off-by: Takashi Iwai +Signed-off-by: Sasha Levin +--- + include/sound/hda_codec.h | 1 + + sound/pci/hda/hda_beep.c | 15 +++++++++------ + sound/pci/hda/patch_realtek.c | 34 +++++++++++++++++++++++++++++++++- + 3 files changed, 43 insertions(+), 7 deletions(-) + +diff --git a/include/sound/hda_codec.h b/include/sound/hda_codec.h +index 575e55aa08ca9..c1fe6290d04dc 100644 +--- a/include/sound/hda_codec.h ++++ b/include/sound/hda_codec.h +@@ -195,6 +195,7 @@ struct hda_codec { + /* beep device */ + struct hda_beep *beep; + unsigned int beep_mode; ++ bool beep_just_power_on; + + /* widget capabilities cache */ + u32 *wcaps; +diff --git a/sound/pci/hda/hda_beep.c b/sound/pci/hda/hda_beep.c +index e51d475725576..13a7d92e8d8d0 100644 +--- a/sound/pci/hda/hda_beep.c ++++ b/sound/pci/hda/hda_beep.c +@@ -31,8 +31,9 @@ static void generate_tone(struct hda_beep *beep, int tone) + beep->power_hook(beep, true); + beep->playing = 1; + } +- snd_hda_codec_write(codec, beep->nid, 0, +- AC_VERB_SET_BEEP_CONTROL, tone); ++ if (!codec->beep_just_power_on) ++ snd_hda_codec_write(codec, beep->nid, 0, ++ AC_VERB_SET_BEEP_CONTROL, tone); + if (!tone && beep->playing) { + beep->playing = 0; + if (beep->power_hook) +@@ -212,10 +213,12 @@ int snd_hda_attach_beep_device(struct hda_codec *codec, int nid) + struct hda_beep *beep; + int err; + +- if (!snd_hda_get_bool_hint(codec, "beep")) +- return 0; /* disabled explicitly by hints */ +- if (codec->beep_mode == HDA_BEEP_MODE_OFF) +- return 0; /* disabled by module option */ ++ if (!codec->beep_just_power_on) { ++ if (!snd_hda_get_bool_hint(codec, "beep")) ++ return 0; /* disabled explicitly by hints */ ++ if (codec->beep_mode == HDA_BEEP_MODE_OFF) ++ return 0; /* disabled by module option */ ++ } + + beep = kzalloc(sizeof(*beep), GFP_KERNEL); + if (beep == NULL) +diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c +index 2ff02fb6f7e94..025c80fa68b05 100644 +--- a/sound/pci/hda/patch_realtek.c ++++ b/sound/pci/hda/patch_realtek.c +@@ -28,6 +28,7 @@ + #include + #include "hda_local.h" + #include "hda_auto_parser.h" ++#include "hda_beep.h" + #include "hda_jack.h" + #include "hda_generic.h" + #include "hda_component.h" +@@ -7034,6 +7035,30 @@ static void alc285_fixup_hp_envy_x360(struct hda_codec *codec, + } + } + ++static void alc285_fixup_hp_beep(struct hda_codec *codec, ++ const struct hda_fixup *fix, int action) ++{ ++ if (action == HDA_FIXUP_ACT_PRE_PROBE) { ++ codec->beep_just_power_on = true; ++ } else if (action == HDA_FIXUP_ACT_INIT) { ++#ifdef CONFIG_SND_HDA_INPUT_BEEP ++ /* ++ * Just enable loopback to internal speaker and headphone jack. ++ * Disable amplification to get about the same beep volume as ++ * was on pure BIOS setup before loading the driver. ++ */ ++ alc_update_coef_idx(codec, 0x36, 0x7070, BIT(13)); ++ ++ snd_hda_enable_beep_device(codec, 1); ++ ++#if !IS_ENABLED(CONFIG_INPUT_PCSPKR) ++ dev_warn_once(hda_codec_dev(codec), ++ "enable CONFIG_INPUT_PCSPKR to get PC beeps\n"); ++#endif ++#endif ++ } ++} ++ + /* for hda_fixup_thinkpad_acpi() */ + #include "thinkpad_helper.c" + +@@ -7819,6 +7844,7 @@ enum { + ALC285_FIXUP_HP_GPIO_LED, + ALC285_FIXUP_HP_MUTE_LED, + ALC285_FIXUP_HP_SPECTRE_X360_MUTE_LED, ++ ALC285_FIXUP_HP_BEEP_MICMUTE_LED, + ALC236_FIXUP_HP_MUTE_LED_COEFBIT2, + ALC236_FIXUP_HP_GPIO_LED, + ALC236_FIXUP_HP_MUTE_LED, +@@ -9415,6 +9441,12 @@ static const struct hda_fixup alc269_fixups[] = { + .type = HDA_FIXUP_FUNC, + .v.func = alc285_fixup_hp_spectre_x360_mute_led, + }, ++ [ALC285_FIXUP_HP_BEEP_MICMUTE_LED] = { ++ .type = HDA_FIXUP_FUNC, ++ .v.func = alc285_fixup_hp_beep, ++ .chained = true, ++ .chain_id = ALC285_FIXUP_HP_MUTE_LED, ++ }, + [ALC236_FIXUP_HP_MUTE_LED_COEFBIT2] = { + .type = HDA_FIXUP_FUNC, + .v.func = alc236_fixup_hp_mute_led_coefbit2, +@@ -10519,7 +10551,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = { + SND_PCI_QUIRK(0x103c, 0x8730, "HP ProBook 445 G7", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF), + SND_PCI_QUIRK(0x103c, 0x8735, "HP ProBook 435 G7", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF), + SND_PCI_QUIRK(0x103c, 0x8736, "HP", ALC285_FIXUP_HP_GPIO_AMP_INIT), +- SND_PCI_QUIRK(0x103c, 0x8760, "HP", ALC285_FIXUP_HP_MUTE_LED), ++ SND_PCI_QUIRK(0x103c, 0x8760, "HP EliteBook 8{4,5}5 G7", ALC285_FIXUP_HP_BEEP_MICMUTE_LED), + SND_PCI_QUIRK(0x103c, 0x876e, "HP ENVY x360 Convertible 13-ay0xxx", ALC245_FIXUP_HP_X360_MUTE_LEDS), + SND_PCI_QUIRK(0x103c, 0x877a, "HP", ALC285_FIXUP_HP_MUTE_LED), + SND_PCI_QUIRK(0x103c, 0x877d, "HP", ALC236_FIXUP_HP_MUTE_LED), +-- +2.39.5 + diff --git a/queue-6.14/alsa-seq-improve-data-consistency-at-polling.patch b/queue-6.14/alsa-seq-improve-data-consistency-at-polling.patch new file mode 100644 index 0000000000..0d7a09203d --- /dev/null +++ b/queue-6.14/alsa-seq-improve-data-consistency-at-polling.patch @@ -0,0 +1,70 @@ +From f939c5a3711f931faa89dcb4c1326b1221958811 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 7 Mar 2025 09:42:42 +0100 +Subject: ALSA: seq: Improve data consistency at polling + +From: Takashi Iwai + +[ Upstream commit e3cd33ab17c33bd8f1a9df66ec83a15dd8f7afbb ] + +snd_seq_poll() calls snd_seq_write_pool_allocated() that reads out a +field in client->pool object, while it can be updated concurrently via +ioctls, as reported by syzbot. The data race itself is harmless, as +it's merely a poll() call, and the state is volatile. OTOH, the read +out of poll object info from the caller side is fragile, and we can +leave it better in snd_seq_pool_poll_wait() alone. + +A similar pattern is seen in snd_seq_kernel_client_write_poll(), too, +which is called from the OSS sequencer. + +This patch drops the pool checks from the caller side and add the +pool->lock in snd_seq_pool_poll_wait() for better data consistency. + +Reported-by: syzbot+2d373c9936c00d7e120c@syzkaller.appspotmail.com +Closes: https://lore.kernel.org/67c88903.050a0220.15b4b9.0028.GAE@google.com +Link: https://patch.msgid.link/20250307084246.29271-1-tiwai@suse.de +Signed-off-by: Takashi Iwai +Signed-off-by: Sasha Levin +--- + sound/core/seq/seq_clientmgr.c | 5 +---- + sound/core/seq/seq_memory.c | 1 + + 2 files changed, 2 insertions(+), 4 deletions(-) + +diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c +index 0ae01b85bb18c..198683a69a534 100644 +--- a/sound/core/seq/seq_clientmgr.c ++++ b/sound/core/seq/seq_clientmgr.c +@@ -1164,8 +1164,7 @@ static __poll_t snd_seq_poll(struct file *file, poll_table * wait) + if (snd_seq_file_flags(file) & SNDRV_SEQ_LFLG_OUTPUT) { + + /* check if data is available in the pool */ +- if (!snd_seq_write_pool_allocated(client) || +- snd_seq_pool_poll_wait(client->pool, file, wait)) ++ if (snd_seq_pool_poll_wait(client->pool, file, wait)) + mask |= EPOLLOUT | EPOLLWRNORM; + } + +@@ -2600,8 +2599,6 @@ int snd_seq_kernel_client_write_poll(int clientid, struct file *file, poll_table + if (client == NULL) + return -ENXIO; + +- if (! snd_seq_write_pool_allocated(client)) +- return 1; + if (snd_seq_pool_poll_wait(client->pool, file, wait)) + return 1; + return 0; +diff --git a/sound/core/seq/seq_memory.c b/sound/core/seq/seq_memory.c +index 20155e3e87c6a..ccde0ca3d2082 100644 +--- a/sound/core/seq/seq_memory.c ++++ b/sound/core/seq/seq_memory.c +@@ -427,6 +427,7 @@ int snd_seq_pool_poll_wait(struct snd_seq_pool *pool, struct file *file, + poll_table *wait) + { + poll_wait(file, &pool->output_sleep, wait); ++ guard(spinlock_irq)(&pool->lock); + return snd_seq_output_ok(pool); + } + +-- +2.39.5 + diff --git a/queue-6.14/alsa-usb-audio-fix-duplicated-name-in-midi-substream.patch b/queue-6.14/alsa-usb-audio-fix-duplicated-name-in-midi-substream.patch new file mode 100644 index 0000000000..dd1072ba16 --- /dev/null +++ b/queue-6.14/alsa-usb-audio-fix-duplicated-name-in-midi-substream.patch @@ -0,0 +1,78 @@ +From 321bf1f4ca71b4680e91ad29ecf9c42cb95c1a8e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 29 Apr 2025 20:36:15 +0200 +Subject: ALSA: usb-audio: Fix duplicated name in MIDI substream names + +From: Takashi Iwai + +[ Upstream commit 0759e77a6d9bd34a874da73721ce4a7dc6665023 ] + +The MIDI substream name string is constructed from the combination of +the card shortname (which is taken from USB iProduct) and the USB +iJack. The problem is that some devices put the product name to the +iJack field, too. For example, aplaymidi -l output on the Lanchkey MK +49 are like: + + % aplaymidi -l + Port Client name Port name + 44:0 Launchkey MK4 49 Launchkey MK4 49 Launchkey MK4 + 44:1 Launchkey MK4 49 Launchkey MK4 49 Launchkey MK4 + +where the actual iJack name can't be seen because it's truncated due +to the doubly words. + +For resolving those situations, this patch compares the iJack string +with the card shortname, and drops if both start with the same words. +Then the result becomes like: + + % aplaymidi -l + Port Client name Port name + 40:0 Launchkey MK4 49 Launchkey MK4 49 MIDI In + 40:1 Launchkey MK4 49 Launchkey MK4 49 DAW In + +A caveat is that there are some pre-defined names for certain +devices in the driver code, and this workaround shouldn't be applied +to them. Similarly, when the iJack isn't specified, we should skip +this check, too. The patch added those checks in addition to the +string comparison. + +Suggested-by: Paul Davis +Tested-by: Paul Davis +Link: https://lore.kernel.org/CAFa_cKmEDQWcJatbYWi6A58Zg4Ma9_6Nr3k5LhqwyxC-P_kXtw@mail.gmail.com +Link: https://patch.msgid.link/20250429183626.20773-1-tiwai@suse.de +Signed-off-by: Takashi Iwai +Signed-off-by: Sasha Levin +--- + sound/usb/midi.c | 16 ++++++++++++---- + 1 file changed, 12 insertions(+), 4 deletions(-) + +diff --git a/sound/usb/midi.c b/sound/usb/midi.c +index 826ac870f2469..a792ada18863a 100644 +--- a/sound/usb/midi.c ++++ b/sound/usb/midi.c +@@ -1885,10 +1885,18 @@ static void snd_usbmidi_init_substream(struct snd_usb_midi *umidi, + } + + port_info = find_port_info(umidi, number); +- name_format = port_info ? port_info->name : +- (jack_name != default_jack_name ? "%s %s" : "%s %s %d"); +- snprintf(substream->name, sizeof(substream->name), +- name_format, umidi->card->shortname, jack_name, number + 1); ++ if (port_info || jack_name == default_jack_name || ++ strncmp(umidi->card->shortname, jack_name, strlen(umidi->card->shortname)) != 0) { ++ name_format = port_info ? port_info->name : ++ (jack_name != default_jack_name ? "%s %s" : "%s %s %d"); ++ snprintf(substream->name, sizeof(substream->name), ++ name_format, umidi->card->shortname, jack_name, number + 1); ++ } else { ++ /* The manufacturer included the iProduct name in the jack ++ * name, do not use both ++ */ ++ strscpy(substream->name, jack_name); ++ } + + *rsubstream = substream; + } +-- +2.39.5 + diff --git a/queue-6.14/amdgpu-soc15-enable-asic-reset-for-dgpu-in-case-of-s.patch b/queue-6.14/amdgpu-soc15-enable-asic-reset-for-dgpu-in-case-of-s.patch new file mode 100644 index 0000000000..6939cb4cd6 --- /dev/null +++ b/queue-6.14/amdgpu-soc15-enable-asic-reset-for-dgpu-in-case-of-s.patch @@ -0,0 +1,56 @@ +From 55973aa1d3bebc3cb2c5adb8cd8e3aef37f83279 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 13 Jan 2025 11:40:12 +0800 +Subject: amdgpu/soc15: enable asic reset for dGPU in case of suspend abort + +From: Jiang Liu + +[ Upstream commit 38e8ca3e4b6de1c6e49d0140264cfc8d314a5f70 ] + +When GPU suspend is aborted, do the same for dGPU as APU to reset +soc15 asic. Otherwise it may cause following errors: +[ 547.229463] amdgpu 0001:81:00.0: [drm:amdgpu_ring_test_helper [amdgpu]] *ERROR* ring kiq_0.2.1.0 test failed (-110) + +[ 555.126827] amdgpu 0000:0a:00.0: [drm:amdgpu_ring_test_helper [amdgpu]] *ERROR* ring kiq_0.2.1.0 test failed (-110) +[ 555.126901] [drm:amdgpu_gfx_enable_kcq [amdgpu]] *ERROR* KCQ enable failed +[ 555.126957] [drm:amdgpu_device_ip_resume_phase2 [amdgpu]] *ERROR* resume of IP block failed -110 +[ 555.126959] amdgpu 0000:0a:00.0: amdgpu: amdgpu_device_ip_resume failed (-110). +[ 555.126965] PM: dpm_run_callback(): pci_pm_resume+0x0/0xe0 returns -110 +[ 555.126966] PM: Device 0000:0a:00.0 failed to resume async: error -110 + +This fix has been tested on Mi308X. + +Signed-off-by: Jiang Liu +Tested-by: Shuo Liu +Reviewed-by: Mario Limonciello +Link: https://lore.kernel.org/r/2462b4b12eb9d025e82525178d568cbaa4c223ff.1736739303.git.gerry@linux.alibaba.com +Signed-off-by: Mario Limonciello +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/amdgpu/soc15.c | 8 +++----- + 1 file changed, 3 insertions(+), 5 deletions(-) + +diff --git a/drivers/gpu/drm/amd/amdgpu/soc15.c b/drivers/gpu/drm/amd/amdgpu/soc15.c +index e98fb3fa36a88..6e09613de8cd2 100644 +--- a/drivers/gpu/drm/amd/amdgpu/soc15.c ++++ b/drivers/gpu/drm/amd/amdgpu/soc15.c +@@ -604,12 +604,10 @@ soc15_asic_reset_method(struct amdgpu_device *adev) + static bool soc15_need_reset_on_resume(struct amdgpu_device *adev) + { + /* Will reset for the following suspend abort cases. +- * 1) Only reset on APU side, dGPU hasn't checked yet. +- * 2) S3 suspend aborted in the normal S3 suspend or +- * performing pm core test. ++ * 1) S3 suspend aborted in the normal S3 suspend ++ * 2) S3 suspend aborted in performing pm core test. + */ +- if (adev->flags & AMD_IS_APU && adev->in_s3 && +- !pm_resume_via_firmware()) ++ if (adev->in_s3 && !pm_resume_via_firmware()) + return true; + else + return false; +-- +2.39.5 + diff --git a/queue-6.14/arch-powerpc-perf-check-the-instruction-type-before-.patch b/queue-6.14/arch-powerpc-perf-check-the-instruction-type-before-.patch new file mode 100644 index 0000000000..3d1bd66431 --- /dev/null +++ b/queue-6.14/arch-powerpc-perf-check-the-instruction-type-before-.patch @@ -0,0 +1,137 @@ +From bd01cca842f95c4909745299c3358845ad02f5bc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Jan 2025 18:46:20 +0530 +Subject: arch/powerpc/perf: Check the instruction type before creating sample + with perf_mem_data_src + +From: Athira Rajeev + +[ Upstream commit 2ffb26afa64261139e608bf087a0c1fe24d76d4d ] + +perf mem report aborts as below sometimes (during some corner +case) in powerpc: + + # ./perf mem report 1>out + *** stack smashing detected ***: terminated + Aborted (core dumped) + +The backtrace is as below: + __pthread_kill_implementation () + raise () + abort () + __libc_message + __fortify_fail + __stack_chk_fail + hist_entry.lvl_snprintf + __sort__hpp_entry + __hist_entry__snprintf + hists.fprintf + cmd_report + cmd_mem + +Snippet of code which triggers the issue +from tools/perf/util/sort.c + + static int hist_entry__lvl_snprintf(struct hist_entry *he, char *bf, + size_t size, unsigned int width) + { + char out[64]; + + perf_mem__lvl_scnprintf(out, sizeof(out), he->mem_info); + return repsep_snprintf(bf, size, "%-*s", width, out); + } + +The value of "out" is filled from perf_mem_data_src value. +Debugging this further showed that for some corner cases, the +value of "data_src" was pointing to wrong value. This resulted +in bigger size of string and causing stack check fail. + +The perf mem data source values are captured in the sample via +isa207_get_mem_data_src function. The initial check is to fetch +the type of sampled instruction. If the type of instruction is +not valid (not a load/store instruction), the function returns. + +Since 'commit e16fd7f2cb1a ("perf: Use sample_flags for data_src")', +data_src field is not initialized by the perf_sample_data_init() +function. If the PMU driver doesn't set the data_src value to zero if +type is not valid, this will result in uninitailised value for data_src. +The uninitailised value of data_src resulted in stack check fail +followed by abort for "perf mem report". + +When requesting for data source information in the sample, the +instruction type is expected to be load or store instruction. +In ISA v3.0, due to hardware limitation, there are corner cases +where the instruction type other than load or store is observed. +In ISA v3.0 and before values "0" and "7" are considered reserved. +In ISA v3.1, value "7" has been used to indicate "larx/stcx". +Drop the sample if instruction type has reserved values for this +field with a ISA version check. Initialize data_src to zero in +isa207_get_mem_data_src if the instruction type is not load/store. + +Reported-by: Disha Goel +Signed-off-by: Athira Rajeev +Signed-off-by: Madhavan Srinivasan +Link: https://patch.msgid.link/20250121131621.39054-1-atrajeev@linux.vnet.ibm.com +Signed-off-by: Sasha Levin +--- + arch/powerpc/perf/core-book3s.c | 20 ++++++++++++++++++++ + arch/powerpc/perf/isa207-common.c | 4 +++- + 2 files changed, 23 insertions(+), 1 deletion(-) + +diff --git a/arch/powerpc/perf/core-book3s.c b/arch/powerpc/perf/core-book3s.c +index f4e03aaabb4c3..b906d28f74fd4 100644 +--- a/arch/powerpc/perf/core-book3s.c ++++ b/arch/powerpc/perf/core-book3s.c +@@ -2226,6 +2226,10 @@ static struct pmu power_pmu = { + #define PERF_SAMPLE_ADDR_TYPE (PERF_SAMPLE_ADDR | \ + PERF_SAMPLE_PHYS_ADDR | \ + PERF_SAMPLE_DATA_PAGE_SIZE) ++ ++#define SIER_TYPE_SHIFT 15 ++#define SIER_TYPE_MASK (0x7ull << SIER_TYPE_SHIFT) ++ + /* + * A counter has overflowed; update its count and record + * things if requested. Note that interrupts are hard-disabled +@@ -2294,6 +2298,22 @@ static void record_and_restart(struct perf_event *event, unsigned long val, + is_kernel_addr(mfspr(SPRN_SIAR))) + record = 0; + ++ /* ++ * SIER[46-48] presents instruction type of the sampled instruction. ++ * In ISA v3.0 and before values "0" and "7" are considered reserved. ++ * In ISA v3.1, value "7" has been used to indicate "larx/stcx". ++ * Drop the sample if "type" has reserved values for this field with a ++ * ISA version check. ++ */ ++ if (event->attr.sample_type & PERF_SAMPLE_DATA_SRC && ++ ppmu->get_mem_data_src) { ++ val = (regs->dar & SIER_TYPE_MASK) >> SIER_TYPE_SHIFT; ++ if (val == 0 || (val == 7 && !cpu_has_feature(CPU_FTR_ARCH_31))) { ++ record = 0; ++ atomic64_inc(&event->lost_samples); ++ } ++ } ++ + /* + * Finally record data if requested. + */ +diff --git a/arch/powerpc/perf/isa207-common.c b/arch/powerpc/perf/isa207-common.c +index 56301b2bc8ae8..031a2b63c171d 100644 +--- a/arch/powerpc/perf/isa207-common.c ++++ b/arch/powerpc/perf/isa207-common.c +@@ -321,8 +321,10 @@ void isa207_get_mem_data_src(union perf_mem_data_src *dsrc, u32 flags, + + sier = mfspr(SPRN_SIER); + val = (sier & ISA207_SIER_TYPE_MASK) >> ISA207_SIER_TYPE_SHIFT; +- if (val != 1 && val != 2 && !(val == 7 && cpu_has_feature(CPU_FTR_ARCH_31))) ++ if (val != 1 && val != 2 && !(val == 7 && cpu_has_feature(CPU_FTR_ARCH_31))) { ++ dsrc->val = 0; + return; ++ } + + idx = (sier & ISA207_SIER_LDST_MASK) >> ISA207_SIER_LDST_SHIFT; + sub_idx = (sier & ISA207_SIER_DATA_SRC_MASK) >> ISA207_SIER_DATA_SRC_SHIFT; +-- +2.39.5 + diff --git a/queue-6.14/arm-at91-pm-fix-at91_suspend_finish-for-zq-calibrati.patch b/queue-6.14/arm-at91-pm-fix-at91_suspend_finish-for-zq-calibrati.patch new file mode 100644 index 0000000000..06e6e754e1 --- /dev/null +++ b/queue-6.14/arm-at91-pm-fix-at91_suspend_finish-for-zq-calibrati.patch @@ -0,0 +1,90 @@ +From b36a2d12020cd4bac69146bd8ade76bc581556de Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 27 Feb 2025 08:51:56 -0700 +Subject: ARM: at91: pm: fix at91_suspend_finish for ZQ calibration + +From: Li Bin + +[ Upstream commit bc4722c3598d0e2c2dbf9609a3d3198993093e2b ] + +For sama7g5 and sama7d65 backup mode, we encountered a "ZQ calibrate error" +during recalibrating the impedance in BootStrap. +We found that the impedance value saved in at91_suspend_finish() before +the DDR entered self-refresh mode did not match the resistor values. The +ZDATA field in the DDR3PHY_ZQ0CR0 register uses a modified gray code to +select the different impedance setting. +But these gray code are incorrect, a workaournd from design team fixed the +bug in the calibration logic. The ZDATA contains four independent impedance +elements, but the algorithm combined the four elements into one. The elements +were fixed using properly shifted offsets. + +Signed-off-by: Li Bin +[nicolas.ferre@microchip.com: fix indentation and combine 2 patches] +Signed-off-by: Nicolas Ferre +Tested-by: Ryan Wanner +Tested-by: Durai Manickam KR +Tested-by: Andrei Simion +Signed-off-by: Ryan Wanner +Link: https://lore.kernel.org/r/28b33f9bcd0ca60ceba032969fe054d38f2b9577.1740671156.git.Ryan.Wanner@microchip.com +Signed-off-by: Claudiu Beznea +Signed-off-by: Sasha Levin +--- + arch/arm/mach-at91/pm.c | 21 +++++++++++---------- + 1 file changed, 11 insertions(+), 10 deletions(-) + +diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c +index 05a1547642b60..6c3e6aa22606f 100644 +--- a/arch/arm/mach-at91/pm.c ++++ b/arch/arm/mach-at91/pm.c +@@ -545,11 +545,12 @@ extern u32 at91_pm_suspend_in_sram_sz; + + static int at91_suspend_finish(unsigned long val) + { +- unsigned char modified_gray_code[] = { +- 0x00, 0x01, 0x02, 0x03, 0x06, 0x07, 0x04, 0x05, 0x0c, 0x0d, +- 0x0e, 0x0f, 0x0a, 0x0b, 0x08, 0x09, 0x18, 0x19, 0x1a, 0x1b, +- 0x1e, 0x1f, 0x1c, 0x1d, 0x14, 0x15, 0x16, 0x17, 0x12, 0x13, +- 0x10, 0x11, ++ /* SYNOPSYS workaround to fix a bug in the calibration logic */ ++ unsigned char modified_fix_code[] = { ++ 0x00, 0x01, 0x01, 0x06, 0x07, 0x0c, 0x06, 0x07, 0x0b, 0x18, ++ 0x0a, 0x0b, 0x0c, 0x0d, 0x0d, 0x0a, 0x13, 0x13, 0x12, 0x13, ++ 0x14, 0x15, 0x15, 0x12, 0x18, 0x19, 0x19, 0x1e, 0x1f, 0x14, ++ 0x1e, 0x1f, + }; + unsigned int tmp, index; + int i; +@@ -560,25 +561,25 @@ static int at91_suspend_finish(unsigned long val) + * restore the ZQ0SR0 with the value saved here. But the + * calibration is buggy and restoring some values from ZQ0SR0 + * is forbidden and risky thus we need to provide processed +- * values for these (modified gray code values). ++ * values for these. + */ + tmp = readl(soc_pm.data.ramc_phy + DDR3PHY_ZQ0SR0); + + /* Store pull-down output impedance select. */ + index = (tmp >> DDR3PHY_ZQ0SR0_PDO_OFF) & 0x1f; +- soc_pm.bu->ddr_phy_calibration[0] = modified_gray_code[index]; ++ soc_pm.bu->ddr_phy_calibration[0] = modified_fix_code[index] << DDR3PHY_ZQ0SR0_PDO_OFF; + + /* Store pull-up output impedance select. */ + index = (tmp >> DDR3PHY_ZQ0SR0_PUO_OFF) & 0x1f; +- soc_pm.bu->ddr_phy_calibration[0] |= modified_gray_code[index]; ++ soc_pm.bu->ddr_phy_calibration[0] |= modified_fix_code[index] << DDR3PHY_ZQ0SR0_PUO_OFF; + + /* Store pull-down on-die termination impedance select. */ + index = (tmp >> DDR3PHY_ZQ0SR0_PDODT_OFF) & 0x1f; +- soc_pm.bu->ddr_phy_calibration[0] |= modified_gray_code[index]; ++ soc_pm.bu->ddr_phy_calibration[0] |= modified_fix_code[index] << DDR3PHY_ZQ0SR0_PDODT_OFF; + + /* Store pull-up on-die termination impedance select. */ + index = (tmp >> DDR3PHY_ZQ0SRO_PUODT_OFF) & 0x1f; +- soc_pm.bu->ddr_phy_calibration[0] |= modified_gray_code[index]; ++ soc_pm.bu->ddr_phy_calibration[0] |= modified_fix_code[index] << DDR3PHY_ZQ0SRO_PUODT_OFF; + + /* + * The 1st 8 words of memory might get corrupted in the process +-- +2.39.5 + diff --git a/queue-6.14/arm-tegra-switch-dsi-b-clock-parent-to-plld-on-tegra.patch b/queue-6.14/arm-tegra-switch-dsi-b-clock-parent-to-plld-on-tegra.patch new file mode 100644 index 0000000000..911b896c21 --- /dev/null +++ b/queue-6.14/arm-tegra-switch-dsi-b-clock-parent-to-plld-on-tegra.patch @@ -0,0 +1,36 @@ +From 7ef665c99d00c85722243b8f44f4fe335e6f8620 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 26 Feb 2025 12:56:11 +0200 +Subject: ARM: tegra: Switch DSI-B clock parent to PLLD on Tegra114 + +From: Svyatoslav Ryhel + +[ Upstream commit 2b3db788f2f614b875b257cdb079adadedc060f3 ] + +PLLD is usually used as parent clock for internal video devices, like +DSI for example, while PLLD2 is used as parent for HDMI. + +Signed-off-by: Svyatoslav Ryhel +Link: https://lore.kernel.org/r/20250226105615.61087-3-clamor95@gmail.com +Signed-off-by: Thierry Reding +Signed-off-by: Sasha Levin +--- + arch/arm/boot/dts/nvidia/tegra114.dtsi | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/arm/boot/dts/nvidia/tegra114.dtsi b/arch/arm/boot/dts/nvidia/tegra114.dtsi +index 86f14e2fd29f3..6c057b5069514 100644 +--- a/arch/arm/boot/dts/nvidia/tegra114.dtsi ++++ b/arch/arm/boot/dts/nvidia/tegra114.dtsi +@@ -139,7 +139,7 @@ dsib: dsi@54400000 { + reg = <0x54400000 0x00040000>; + clocks = <&tegra_car TEGRA114_CLK_DSIB>, + <&tegra_car TEGRA114_CLK_DSIBLP>, +- <&tegra_car TEGRA114_CLK_PLL_D2_OUT0>; ++ <&tegra_car TEGRA114_CLK_PLL_D_OUT0>; + clock-names = "dsi", "lp", "parent"; + resets = <&tegra_car 82>; + reset-names = "dsi"; +-- +2.39.5 + diff --git a/queue-6.14/arm64-add-support-for-hip09-spectre-bhb-mitigation.patch b/queue-6.14/arm64-add-support-for-hip09-spectre-bhb-mitigation.patch new file mode 100644 index 0000000000..35d730c089 --- /dev/null +++ b/queue-6.14/arm64-add-support-for-hip09-spectre-bhb-mitigation.patch @@ -0,0 +1,58 @@ +From 9cdb4b1a5cb8e5313ef1338375a59b722d152dc9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 25 Mar 2025 22:19:00 +0800 +Subject: arm64: Add support for HIP09 Spectre-BHB mitigation + +From: Jinqian Yang + +[ Upstream commit e18c09b204e81702ea63b9f1a81ab003b72e3174 ] + +The HIP09 processor is vulnerable to the Spectre-BHB (Branch History +Buffer) attack, which can be exploited to leak information through +branch prediction side channels. This commit adds the MIDR of HIP09 +to the list for software mitigation. + +Signed-off-by: Jinqian Yang +Link: https://lore.kernel.org/r/20250325141900.2057314-1-yangjinqian1@huawei.com +Signed-off-by: Catalin Marinas +Signed-off-by: Sasha Levin +--- + arch/arm64/include/asm/cputype.h | 2 ++ + arch/arm64/kernel/proton-pack.c | 1 + + 2 files changed, 3 insertions(+) + +diff --git a/arch/arm64/include/asm/cputype.h b/arch/arm64/include/asm/cputype.h +index 8c6bd9da3b1ba..3381fdc081ad2 100644 +--- a/arch/arm64/include/asm/cputype.h ++++ b/arch/arm64/include/asm/cputype.h +@@ -133,6 +133,7 @@ + #define FUJITSU_CPU_PART_A64FX 0x001 + + #define HISI_CPU_PART_TSV110 0xD01 ++#define HISI_CPU_PART_HIP09 0xD02 + + #define APPLE_CPU_PART_M1_ICESTORM 0x022 + #define APPLE_CPU_PART_M1_FIRESTORM 0x023 +@@ -210,6 +211,7 @@ + #define MIDR_NVIDIA_CARMEL MIDR_CPU_MODEL(ARM_CPU_IMP_NVIDIA, NVIDIA_CPU_PART_CARMEL) + #define MIDR_FUJITSU_A64FX MIDR_CPU_MODEL(ARM_CPU_IMP_FUJITSU, FUJITSU_CPU_PART_A64FX) + #define MIDR_HISI_TSV110 MIDR_CPU_MODEL(ARM_CPU_IMP_HISI, HISI_CPU_PART_TSV110) ++#define MIDR_HISI_HIP09 MIDR_CPU_MODEL(ARM_CPU_IMP_HISI, HISI_CPU_PART_HIP09) + #define MIDR_APPLE_M1_ICESTORM MIDR_CPU_MODEL(ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M1_ICESTORM) + #define MIDR_APPLE_M1_FIRESTORM MIDR_CPU_MODEL(ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M1_FIRESTORM) + #define MIDR_APPLE_M1_ICESTORM_PRO MIDR_CPU_MODEL(ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M1_ICESTORM_PRO) +diff --git a/arch/arm64/kernel/proton-pack.c b/arch/arm64/kernel/proton-pack.c +index 8ef3335ecff72..31eaf15d2079a 100644 +--- a/arch/arm64/kernel/proton-pack.c ++++ b/arch/arm64/kernel/proton-pack.c +@@ -904,6 +904,7 @@ static u8 spectre_bhb_loop_affected(void) + MIDR_ALL_VERSIONS(MIDR_CORTEX_A77), + MIDR_ALL_VERSIONS(MIDR_NEOVERSE_N1), + MIDR_ALL_VERSIONS(MIDR_QCOM_KRYO_4XX_GOLD), ++ MIDR_ALL_VERSIONS(MIDR_HISI_HIP09), + {}, + }; + static const struct midr_range spectre_bhb_k11_list[] = { +-- +2.39.5 + diff --git a/queue-6.14/arm64-mm-check-pmd_table-in-pmd_trans_huge.patch b/queue-6.14/arm64-mm-check-pmd_table-in-pmd_trans_huge.patch new file mode 100644 index 0000000000..fbcc8da459 --- /dev/null +++ b/queue-6.14/arm64-mm-check-pmd_table-in-pmd_trans_huge.patch @@ -0,0 +1,73 @@ +From 86343684e505ca066859f4440c6511ba1a6e5a20 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 21 Feb 2025 10:12:26 +0530 +Subject: arm64/mm: Check pmd_table() in pmd_trans_huge() + +From: Ryan Roberts + +[ Upstream commit d1770e909898c108e8c7d30ca039053e8818a9c9 ] + +Check for pmd_table() in pmd_trans_huge() rather then just checking for the +PMD_TABLE_BIT. But ensure all present-invalid entries are handled correctly +by always setting PTE_VALID before checking with pmd_table(). + +Cc: Will Deacon +Cc: Ard Biesheuvel +Cc: Ryan Roberts +Cc: Mark Rutland +Cc: linux-arm-kernel@lists.infradead.org +Cc: linux-kernel@vger.kernel.org +Signed-off-by: Ryan Roberts +Signed-off-by: Anshuman Khandual +Link: https://lore.kernel.org/r/20250221044227.1145393-8-anshuman.khandual@arm.com +Signed-off-by: Catalin Marinas +Signed-off-by: Sasha Levin +--- + arch/arm64/include/asm/pgtable.h | 24 ++++++++++++------------ + 1 file changed, 12 insertions(+), 12 deletions(-) + +diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h +index 0b2a2ad1b9e83..abf990ce175b1 100644 +--- a/arch/arm64/include/asm/pgtable.h ++++ b/arch/arm64/include/asm/pgtable.h +@@ -548,18 +548,6 @@ static inline int pmd_protnone(pmd_t pmd) + #endif + + #define pmd_present(pmd) pte_present(pmd_pte(pmd)) +- +-/* +- * THP definitions. +- */ +- +-#ifdef CONFIG_TRANSPARENT_HUGEPAGE +-static inline int pmd_trans_huge(pmd_t pmd) +-{ +- return pmd_val(pmd) && pmd_present(pmd) && !(pmd_val(pmd) & PMD_TABLE_BIT); +-} +-#endif /* CONFIG_TRANSPARENT_HUGEPAGE */ +- + #define pmd_dirty(pmd) pte_dirty(pmd_pte(pmd)) + #define pmd_young(pmd) pte_young(pmd_pte(pmd)) + #define pmd_valid(pmd) pte_valid(pmd_pte(pmd)) +@@ -724,6 +712,18 @@ extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn, + #define pmd_leaf_size(pmd) (pmd_cont(pmd) ? CONT_PMD_SIZE : PMD_SIZE) + #define pte_leaf_size(pte) (pte_cont(pte) ? CONT_PTE_SIZE : PAGE_SIZE) + ++#ifdef CONFIG_TRANSPARENT_HUGEPAGE ++static inline int pmd_trans_huge(pmd_t pmd) ++{ ++ /* ++ * If pmd is present-invalid, pmd_table() won't detect it ++ * as a table, so force the valid bit for the comparison. ++ */ ++ return pmd_val(pmd) && pmd_present(pmd) && ++ !pmd_table(__pmd(pmd_val(pmd) | PTE_VALID)); ++} ++#endif /* CONFIG_TRANSPARENT_HUGEPAGE */ ++ + #if defined(CONFIG_ARM64_64K_PAGES) || CONFIG_PGTABLE_LEVELS < 3 + static inline bool pud_sect(pud_t pud) { return false; } + static inline bool pud_table(pud_t pud) { return true; } +-- +2.39.5 + diff --git a/queue-6.14/arm64-mm-check-pud_type_table-in-pud_bad.patch b/queue-6.14/arm64-mm-check-pud_type_table-in-pud_bad.patch new file mode 100644 index 0000000000..d33474a349 --- /dev/null +++ b/queue-6.14/arm64-mm-check-pud_type_table-in-pud_bad.patch @@ -0,0 +1,49 @@ +From 572faea04689a0419a74406e1681dd08cfaf72de Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 21 Feb 2025 10:12:25 +0530 +Subject: arm64/mm: Check PUD_TYPE_TABLE in pud_bad() + +From: Ryan Roberts + +[ Upstream commit bfb1d2b9021c21891427acc86eb848ccedeb274e ] + +pud_bad() is currently defined in terms of pud_table(). Although for some +configs, pud_table() is hard-coded to true i.e. when using 64K base pages +or when page table levels are less than 3. + +pud_bad() is intended to check that the pud is configured correctly. Hence +let's open-code the same check that the full version of pud_table() uses +into pud_bad(). Then it always performs the check regardless of the config. + +Cc: Will Deacon +Cc: Ard Biesheuvel +Cc: Ryan Roberts +Cc: Mark Rutland +Cc: linux-arm-kernel@lists.infradead.org +Cc: linux-kernel@vger.kernel.org +Signed-off-by: Ryan Roberts +Signed-off-by: Anshuman Khandual +Link: https://lore.kernel.org/r/20250221044227.1145393-7-anshuman.khandual@arm.com +Signed-off-by: Catalin Marinas +Signed-off-by: Sasha Levin +--- + arch/arm64/include/asm/pgtable.h | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h +index abf990ce175b1..665f90443f9e8 100644 +--- a/arch/arm64/include/asm/pgtable.h ++++ b/arch/arm64/include/asm/pgtable.h +@@ -805,7 +805,8 @@ static inline unsigned long pmd_page_vaddr(pmd_t pmd) + pr_err("%s:%d: bad pmd %016llx.\n", __FILE__, __LINE__, pmd_val(e)) + + #define pud_none(pud) (!pud_val(pud)) +-#define pud_bad(pud) (!pud_table(pud)) ++#define pud_bad(pud) ((pud_val(pud) & PUD_TYPE_MASK) != \ ++ PUD_TYPE_TABLE) + #define pud_present(pud) pte_present(pud_pte(pud)) + #ifndef __PAGETABLE_PMD_FOLDED + #define pud_leaf(pud) (pud_present(pud) && !pud_table(pud)) +-- +2.39.5 + diff --git a/queue-6.14/arm64-tegra-p2597-fix-gpio-for-vdd-1v8-dis-regulator.patch b/queue-6.14/arm64-tegra-p2597-fix-gpio-for-vdd-1v8-dis-regulator.patch new file mode 100644 index 0000000000..86a87f483f --- /dev/null +++ b/queue-6.14/arm64-tegra-p2597-fix-gpio-for-vdd-1v8-dis-regulator.patch @@ -0,0 +1,37 @@ +From e43db54c5e685e5659cf567c6b10f782b0fed4b2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 24 Feb 2025 12:17:36 +0000 +Subject: arm64: tegra: p2597: Fix gpio for vdd-1v8-dis regulator + +From: Diogo Ivo + +[ Upstream commit f34621f31e3be81456c903287f7e4c0609829e29 ] + +According to the board schematics the enable pin of this regulator is +connected to gpio line #9 of the first instance of the TCA9539 +GPIO expander, so adjust it. + +Signed-off-by: Diogo Ivo +Link: https://lore.kernel.org/r/20250224-diogo-gpio_exp-v1-1-80fb84ac48c6@tecnico.ulisboa.pt +Signed-off-by: Thierry Reding +Signed-off-by: Sasha Levin +--- + arch/arm64/boot/dts/nvidia/tegra210-p2597.dtsi | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/arm64/boot/dts/nvidia/tegra210-p2597.dtsi b/arch/arm64/boot/dts/nvidia/tegra210-p2597.dtsi +index 63b94a04308e8..38d49d612c0c1 100644 +--- a/arch/arm64/boot/dts/nvidia/tegra210-p2597.dtsi ++++ b/arch/arm64/boot/dts/nvidia/tegra210-p2597.dtsi +@@ -1686,7 +1686,7 @@ vdd_1v8_dis: regulator-vdd-1v8-dis { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; +- gpio = <&exp1 14 GPIO_ACTIVE_HIGH>; ++ gpio = <&exp1 9 GPIO_ACTIVE_HIGH>; + enable-active-high; + vin-supply = <&vdd_1v8>; + }; +-- +2.39.5 + diff --git a/queue-6.14/arm64-tegra-resize-aperture-for-the-igx-pcie-c5-slot.patch b/queue-6.14/arm64-tegra-resize-aperture-for-the-igx-pcie-c5-slot.patch new file mode 100644 index 0000000000..a910221a24 --- /dev/null +++ b/queue-6.14/arm64-tegra-resize-aperture-for-the-igx-pcie-c5-slot.patch @@ -0,0 +1,48 @@ +From b17ff675d485859f9ee6308ac3d1e86bd2bbc7cd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 16 Jan 2025 15:19:03 +0000 +Subject: arm64: tegra: Resize aperture for the IGX PCIe C5 slot + +From: Jon Hunter + +[ Upstream commit 6d4bfe6d86af1ef52bdb4592c9afb2037f24f2c4 ] + +Some discrete graphics cards such as the NVIDIA RTX A6000 support +resizable BARs. When connecting an A6000 card to the NVIDIA IGX Orin +platform, resizing the BAR1 aperture to 8GB fails because the current +device-tree configuration for the PCIe C5 slot cannot support this. +Fix this by updating the device-tree 'reg' and 'ranges' properties for +the PCIe C5 slot to support this. + +Signed-off-by: Jon Hunter +Link: https://lore.kernel.org/r/20250116151903.476047-1-jonathanh@nvidia.com +Signed-off-by: Thierry Reding +Signed-off-by: Sasha Levin +--- + .../boot/dts/nvidia/tegra234-p3740-0002+p3701-0008.dts | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/arch/arm64/boot/dts/nvidia/tegra234-p3740-0002+p3701-0008.dts b/arch/arm64/boot/dts/nvidia/tegra234-p3740-0002+p3701-0008.dts +index 36e8880537460..9ce55b4d2de89 100644 +--- a/arch/arm64/boot/dts/nvidia/tegra234-p3740-0002+p3701-0008.dts ++++ b/arch/arm64/boot/dts/nvidia/tegra234-p3740-0002+p3701-0008.dts +@@ -302,6 +302,16 @@ pcie@14160000 { + }; + + pcie@141a0000 { ++ reg = <0x00 0x141a0000 0x0 0x00020000 /* appl registers (128K) */ ++ 0x00 0x3a000000 0x0 0x00040000 /* configuration space (256K) */ ++ 0x00 0x3a040000 0x0 0x00040000 /* iATU_DMA reg space (256K) */ ++ 0x00 0x3a080000 0x0 0x00040000 /* DBI reg space (256K) */ ++ 0x2e 0x20000000 0x0 0x10000000>; /* ECAM (256MB) */ ++ ++ ranges = <0x81000000 0x00 0x3a100000 0x00 0x3a100000 0x0 0x00100000 /* downstream I/O (1MB) */ ++ 0x82000000 0x00 0x40000000 0x2e 0x30000000 0x0 0x08000000 /* non-prefetchable memory (128MB) */ ++ 0xc3000000 0x28 0x00000000 0x28 0x00000000 0x6 0x20000000>; /* prefetchable memory (25088MB) */ ++ + status = "okay"; + vddio-pex-ctl-supply = <&vdd_1v8_ls>; + phys = <&p2u_nvhs_0>, <&p2u_nvhs_1>, <&p2u_nvhs_2>, +-- +2.39.5 + diff --git a/queue-6.14/arm64-zynqmp-add-clock-output-names-property-in-cloc.patch b/queue-6.14/arm64-zynqmp-add-clock-output-names-property-in-cloc.patch new file mode 100644 index 0000000000..05088acfb7 --- /dev/null +++ b/queue-6.14/arm64-zynqmp-add-clock-output-names-property-in-cloc.patch @@ -0,0 +1,80 @@ +From 32516cbba63b33e5730563bccc5a80bfc63b70ce Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 22 Nov 2024 01:57:12 -0800 +Subject: arm64: zynqmp: add clock-output-names property in clock nodes + +From: Naman Trivedi + +[ Upstream commit 385a59e7f7fb3438466a0712cc14672c708bbd57 ] + +Add clock-output-names property to clock nodes, so that the resulting +clock name do not change when clock node name is changed. +Also, replace underscores with hyphens in the clock node names as per +dt-schema rule. + +Signed-off-by: Naman Trivedi +Acked-by: Senthil Nathan Thangaraj +Link: https://lore.kernel.org/r/20241122095712.1166883-1-naman.trivedimanojbhai@amd.com +Signed-off-by: Michal Simek +Signed-off-by: Sasha Levin +--- + arch/arm64/boot/dts/xilinx/zynqmp-clk-ccf.dtsi | 15 ++++++++++----- + 1 file changed, 10 insertions(+), 5 deletions(-) + +diff --git a/arch/arm64/boot/dts/xilinx/zynqmp-clk-ccf.dtsi b/arch/arm64/boot/dts/xilinx/zynqmp-clk-ccf.dtsi +index 60d1b1acf9a03..385fed8a852af 100644 +--- a/arch/arm64/boot/dts/xilinx/zynqmp-clk-ccf.dtsi ++++ b/arch/arm64/boot/dts/xilinx/zynqmp-clk-ccf.dtsi +@@ -10,39 +10,44 @@ + + #include + / { +- pss_ref_clk: pss_ref_clk { ++ pss_ref_clk: pss-ref-clk { + bootph-all; + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <33333333>; ++ clock-output-names = "pss_ref_clk"; + }; + +- video_clk: video_clk { ++ video_clk: video-clk { + bootph-all; + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <27000000>; ++ clock-output-names = "video_clk"; + }; + +- pss_alt_ref_clk: pss_alt_ref_clk { ++ pss_alt_ref_clk: pss-alt-ref-clk { + bootph-all; + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <0>; ++ clock-output-names = "pss_alt_ref_clk"; + }; + +- gt_crx_ref_clk: gt_crx_ref_clk { ++ gt_crx_ref_clk: gt-crx-ref-clk { + bootph-all; + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <108000000>; ++ clock-output-names = "gt_crx_ref_clk"; + }; + +- aux_ref_clk: aux_ref_clk { ++ aux_ref_clk: aux-ref-clk { + bootph-all; + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <27000000>; ++ clock-output-names = "aux_ref_clk"; + }; + }; + +-- +2.39.5 + diff --git a/queue-6.14/asoc-codecs-pcm3168a-allow-for-24-bit-in-provider-mo.patch b/queue-6.14/asoc-codecs-pcm3168a-allow-for-24-bit-in-provider-mo.patch new file mode 100644 index 0000000000..bdc88ff1d9 --- /dev/null +++ b/queue-6.14/asoc-codecs-pcm3168a-allow-for-24-bit-in-provider-mo.patch @@ -0,0 +1,40 @@ +From 491c74204b2114923fee42d9dff5430219521126 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 3 Feb 2025 15:10:43 +0100 +Subject: ASoC: codecs: pcm3168a: Allow for 24-bit in provider mode + +From: Cezary Rojewski + +[ Upstream commit 7d92a38d67e5d937b64b20aa4fd14451ee1772f3 ] + +As per codec device specification, 24-bit is allowed in provider mode. +Update the code to reflect that. + +Signed-off-by: Cezary Rojewski +Link: https://patch.msgid.link/20250203141051.2361323-4-cezary.rojewski@intel.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/codecs/pcm3168a.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/sound/soc/codecs/pcm3168a.c b/sound/soc/codecs/pcm3168a.c +index fac0617ab95b6..6cbb8d0535b02 100644 +--- a/sound/soc/codecs/pcm3168a.c ++++ b/sound/soc/codecs/pcm3168a.c +@@ -493,9 +493,9 @@ static int pcm3168a_hw_params(struct snd_pcm_substream *substream, + } + break; + case 24: +- if (provider_mode || (format == SND_SOC_DAIFMT_DSP_A) || +- (format == SND_SOC_DAIFMT_DSP_B)) { +- dev_err(component->dev, "24-bit slots not supported in provider mode, or consumer mode using DSP\n"); ++ if (!provider_mode && ((format == SND_SOC_DAIFMT_DSP_A) || ++ (format == SND_SOC_DAIFMT_DSP_B))) { ++ dev_err(component->dev, "24-bit slots not supported in consumer mode using DSP\n"); + return -EINVAL; + } + break; +-- +2.39.5 + diff --git a/queue-6.14/asoc-codecs-wsa883x-correct-vi-sense-channel-mask.patch b/queue-6.14/asoc-codecs-wsa883x-correct-vi-sense-channel-mask.patch new file mode 100644 index 0000000000..d1a4e33090 --- /dev/null +++ b/queue-6.14/asoc-codecs-wsa883x-correct-vi-sense-channel-mask.patch @@ -0,0 +1,38 @@ +From e5d46a77bce5d53e0b86e47b95f099851d1e8c6e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 12 Mar 2025 20:24:59 +0100 +Subject: ASoC: codecs: wsa883x: Correct VI sense channel mask + +From: Krzysztof Kozlowski + +[ Upstream commit ed3b274abc4008efffebf1997968a3f2720a86d3 ] + +VI sense port on WSA883x speaker takes only one channel, so use 0x1 as +channel mask. This fixes garbage being recorded by the speaker when +testing the VI sense feedback path. + +Cc: Srinivas Kandagatla +Signed-off-by: Krzysztof Kozlowski +Link: https://patch.msgid.link/20250312-asoc-wsa88xx-visense-v1-1-9ca705881122@linaro.org +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/codecs/wsa883x.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/sound/soc/codecs/wsa883x.c b/sound/soc/codecs/wsa883x.c +index 47da5674d7c92..e31b7fb104e6c 100644 +--- a/sound/soc/codecs/wsa883x.c ++++ b/sound/soc/codecs/wsa883x.c +@@ -529,7 +529,7 @@ static const struct sdw_port_config wsa883x_pconfig[WSA883X_MAX_SWR_PORTS] = { + }, + [WSA883X_PORT_VISENSE] = { + .num = WSA883X_PORT_VISENSE + 1, +- .ch_mask = 0x3, ++ .ch_mask = 0x1, + }, + }; + +-- +2.39.5 + diff --git a/queue-6.14/asoc-codecs-wsa884x-correct-vi-sense-channel-mask.patch b/queue-6.14/asoc-codecs-wsa884x-correct-vi-sense-channel-mask.patch new file mode 100644 index 0000000000..67ed795c00 --- /dev/null +++ b/queue-6.14/asoc-codecs-wsa884x-correct-vi-sense-channel-mask.patch @@ -0,0 +1,38 @@ +From 42135e421810a700b1358625b71281351306372a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 12 Mar 2025 20:25:00 +0100 +Subject: ASoC: codecs: wsa884x: Correct VI sense channel mask + +From: Krzysztof Kozlowski + +[ Upstream commit 060fac202eb8e5c83961f0e0bf6dad8ab6e46643 ] + +VI sense port on WSA883x speaker takes only one channel, so use 0x1 as +channel mask. This fixes garbage being recorded by the speaker when +testing the VI sense feedback path. + +Cc: Srinivas Kandagatla +Signed-off-by: Krzysztof Kozlowski +Link: https://patch.msgid.link/20250312-asoc-wsa88xx-visense-v1-2-9ca705881122@linaro.org +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/codecs/wsa884x.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/sound/soc/codecs/wsa884x.c b/sound/soc/codecs/wsa884x.c +index 560a2c04b6955..18b0ee8f15a55 100644 +--- a/sound/soc/codecs/wsa884x.c ++++ b/sound/soc/codecs/wsa884x.c +@@ -891,7 +891,7 @@ static const struct sdw_port_config wsa884x_pconfig[WSA884X_MAX_SWR_PORTS] = { + }, + [WSA884X_PORT_VISENSE] = { + .num = WSA884X_PORT_VISENSE + 1, +- .ch_mask = 0x3, ++ .ch_mask = 0x1, + }, + [WSA884X_PORT_CPS] = { + .num = WSA884X_PORT_CPS + 1, +-- +2.39.5 + diff --git a/queue-6.14/asoc-cs42l43-disable-headphone-clamps-during-type-de.patch b/queue-6.14/asoc-cs42l43-disable-headphone-clamps-during-type-de.patch new file mode 100644 index 0000000000..8592fa11f3 --- /dev/null +++ b/queue-6.14/asoc-cs42l43-disable-headphone-clamps-during-type-de.patch @@ -0,0 +1,50 @@ +From fc8150f4c070de9f96ed9def2fb7033d1e0712b5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 23 Apr 2025 10:09:44 +0100 +Subject: ASoC: cs42l43: Disable headphone clamps during type detection + +From: Charles Keepax + +[ Upstream commit 70ad2e6bd180f94be030aef56e59693e36d945f3 ] + +The headphone clamps cause fairly loud pops during type detect +because they sink current from the detection process itself. Disable +the clamps whilst the type detect runs, to improve the detection +pop performance. + +Signed-off-by: Charles Keepax +Link: https://patch.msgid.link/20250423090944.1504538-1-ckeepax@opensource.cirrus.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/codecs/cs42l43-jack.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/sound/soc/codecs/cs42l43-jack.c b/sound/soc/codecs/cs42l43-jack.c +index 20e6ab6f0d4ad..6165ac16c3a95 100644 +--- a/sound/soc/codecs/cs42l43-jack.c ++++ b/sound/soc/codecs/cs42l43-jack.c +@@ -654,6 +654,10 @@ static int cs42l43_run_type_detect(struct cs42l43_codec *priv) + + reinit_completion(&priv->type_detect); + ++ regmap_update_bits(cs42l43->regmap, CS42L43_STEREO_MIC_CLAMP_CTRL, ++ CS42L43_SMIC_HPAMP_CLAMP_DIS_FRC_VAL_MASK, ++ CS42L43_SMIC_HPAMP_CLAMP_DIS_FRC_VAL_MASK); ++ + cs42l43_start_hs_bias(priv, true); + regmap_update_bits(cs42l43->regmap, CS42L43_HS2, + CS42L43_HSDET_MODE_MASK, 0x3 << CS42L43_HSDET_MODE_SHIFT); +@@ -665,6 +669,9 @@ static int cs42l43_run_type_detect(struct cs42l43_codec *priv) + CS42L43_HSDET_MODE_MASK, 0x2 << CS42L43_HSDET_MODE_SHIFT); + cs42l43_stop_hs_bias(priv); + ++ regmap_update_bits(cs42l43->regmap, CS42L43_STEREO_MIC_CLAMP_CTRL, ++ CS42L43_SMIC_HPAMP_CLAMP_DIS_FRC_VAL_MASK, 0); ++ + if (!time_left) + return -ETIMEDOUT; + +-- +2.39.5 + diff --git a/queue-6.14/asoc-imx-card-adjust-over-allocation-of-memory-in-im.patch b/queue-6.14/asoc-imx-card-adjust-over-allocation-of-memory-in-im.patch new file mode 100644 index 0000000000..4da34d8b7d --- /dev/null +++ b/queue-6.14/asoc-imx-card-adjust-over-allocation-of-memory-in-im.patch @@ -0,0 +1,40 @@ +From bffa28a9208592089e868ab261deeaa68599e94d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 6 Apr 2025 16:08:54 -0500 +Subject: ASoC: imx-card: Adjust over allocation of memory in + imx_card_parse_of() + +From: Chenyuan Yang + +[ Upstream commit a9a69c3b38c89d7992fb53db4abb19104b531d32 ] + +Incorrect types are used as sizeof() arguments in devm_kcalloc(). +It should be sizeof(dai_link_data) for link_data instead of +sizeof(snd_soc_dai_link). + +This is found by our static analysis tool. + +Signed-off-by: Chenyuan Yang +Link: https://patch.msgid.link/20250406210854.149316-1-chenyuan0y@gmail.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/fsl/imx-card.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/sound/soc/fsl/imx-card.c b/sound/soc/fsl/imx-card.c +index 21f617f6f9fa8..566214cb3d60c 100644 +--- a/sound/soc/fsl/imx-card.c ++++ b/sound/soc/fsl/imx-card.c +@@ -543,7 +543,7 @@ static int imx_card_parse_of(struct imx_card_data *data) + if (!card->dai_link) + return -ENOMEM; + +- data->link_data = devm_kcalloc(dev, num_links, sizeof(*link), GFP_KERNEL); ++ data->link_data = devm_kcalloc(dev, num_links, sizeof(*link_data), GFP_KERNEL); + if (!data->link_data) + return -ENOMEM; + +-- +2.39.5 + diff --git a/queue-6.14/asoc-intel-bytcr_rt5640-add-dmi-quirk-for-acer-aspir.patch b/queue-6.14/asoc-intel-bytcr_rt5640-add-dmi-quirk-for-acer-aspir.patch new file mode 100644 index 0000000000..4a6f209ac3 --- /dev/null +++ b/queue-6.14/asoc-intel-bytcr_rt5640-add-dmi-quirk-for-acer-aspir.patch @@ -0,0 +1,48 @@ +From 9f4f24185a20566bc046232af7a1e516c8eb5466 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 20 Apr 2025 10:56:59 +0200 +Subject: ASoC: Intel: bytcr_rt5640: Add DMI quirk for Acer Aspire SW3-013 + +From: Takashi Iwai + +[ Upstream commit a549b927ea3f5e50b1394209b64e6e17e31d4db8 ] + +Acer Aspire SW3-013 requires the very same quirk as other Acer Aspire +model for making it working. + +Link: https://bugzilla.kernel.org/show_bug.cgi?id=220011 +Signed-off-by: Takashi Iwai +Link: https://patch.msgid.link/20250420085716.12095-1-tiwai@suse.de +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/intel/boards/bytcr_rt5640.c | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +diff --git a/sound/soc/intel/boards/bytcr_rt5640.c b/sound/soc/intel/boards/bytcr_rt5640.c +index 6446cda0f8572..0f3b8f44e7011 100644 +--- a/sound/soc/intel/boards/bytcr_rt5640.c ++++ b/sound/soc/intel/boards/bytcr_rt5640.c +@@ -576,6 +576,19 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = { + BYT_RT5640_SSP0_AIF2 | + BYT_RT5640_MCLK_EN), + }, ++ { /* Acer Aspire SW3-013 */ ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "Acer"), ++ DMI_MATCH(DMI_PRODUCT_NAME, "Aspire SW3-013"), ++ }, ++ .driver_data = (void *)(BYT_RT5640_DMIC1_MAP | ++ BYT_RT5640_JD_SRC_JD2_IN4N | ++ BYT_RT5640_OVCD_TH_2000UA | ++ BYT_RT5640_OVCD_SF_0P75 | ++ BYT_RT5640_DIFF_MIC | ++ BYT_RT5640_SSP0_AIF1 | ++ BYT_RT5640_MCLK_EN), ++ }, + { + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Acer"), +-- +2.39.5 + diff --git a/queue-6.14/asoc-intel-sdw_utils-add-volume-limit-to-cs35l56-spe.patch b/queue-6.14/asoc-intel-sdw_utils-add-volume-limit-to-cs35l56-spe.patch new file mode 100644 index 0000000000..953505e8b5 --- /dev/null +++ b/queue-6.14/asoc-intel-sdw_utils-add-volume-limit-to-cs35l56-spe.patch @@ -0,0 +1,105 @@ +From 12d7e4f7c5dbc8b92a3bff459def8b22f2548754 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 30 Apr 2025 11:31:20 +0100 +Subject: ASoC: intel/sdw_utils: Add volume limit to cs35l56 speakers + +From: Stefan Binding + +[ Upstream commit d5463e531c128ff1b141fdba2e13345cd50028a4 ] + +The volume control for cs35l56 speakers has a maximum gain of +12 dB. +However, for many use cases, this can cause distorted audio, depending +various factors, such as other signal-processing elements in the chain, +for example if the audio passes through a gain control before reaching +the amp or the signal path has been tuned for a particular maximum +gain in the amp. + +In the case of systems which use the soc_sdw_* driver, audio will +likely be distorted in all cases above 0 dB, therefore add a volume +limit of 400, which is 0 dB maximum volume inside this driver. + +The volume limit should be applied to both soundwire and soundwire +bridge configurations. + +Signed-off-by: Stefan Binding +Link: https://patch.msgid.link/20250430103134.24579-3-sbinding@opensource.cirrus.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + include/sound/soc_sdw_utils.h | 1 + + sound/soc/sdw_utils/soc_sdw_bridge_cs35l56.c | 4 ++++ + sound/soc/sdw_utils/soc_sdw_cs_amp.c | 24 ++++++++++++++++++++ + 3 files changed, 29 insertions(+) + +diff --git a/include/sound/soc_sdw_utils.h b/include/sound/soc_sdw_utils.h +index 36a4a1e1d8ca2..d8bd5d37131aa 100644 +--- a/include/sound/soc_sdw_utils.h ++++ b/include/sound/soc_sdw_utils.h +@@ -226,6 +226,7 @@ int asoc_sdw_cs_amp_init(struct snd_soc_card *card, + bool playback); + int asoc_sdw_cs_spk_feedback_rtd_init(struct snd_soc_pcm_runtime *rtd, + struct snd_soc_dai *dai); ++int asoc_sdw_cs35l56_volume_limit(struct snd_soc_card *card, const char *name_prefix); + + /* MAXIM codec support */ + int asoc_sdw_maxim_init(struct snd_soc_card *card, +diff --git a/sound/soc/sdw_utils/soc_sdw_bridge_cs35l56.c b/sound/soc/sdw_utils/soc_sdw_bridge_cs35l56.c +index 246e5c2e0af55..c7e55f4433514 100644 +--- a/sound/soc/sdw_utils/soc_sdw_bridge_cs35l56.c ++++ b/sound/soc/sdw_utils/soc_sdw_bridge_cs35l56.c +@@ -60,6 +60,10 @@ static int asoc_sdw_bridge_cs35l56_asp_init(struct snd_soc_pcm_runtime *rtd) + + /* 4 x 16-bit sample slots and FSYNC=48000, BCLK=3.072 MHz */ + for_each_rtd_codec_dais(rtd, i, codec_dai) { ++ ret = asoc_sdw_cs35l56_volume_limit(card, codec_dai->component->name_prefix); ++ if (ret) ++ return ret; ++ + ret = snd_soc_dai_set_tdm_slot(codec_dai, tx_mask, rx_mask, 4, 16); + if (ret < 0) + return ret; +diff --git a/sound/soc/sdw_utils/soc_sdw_cs_amp.c b/sound/soc/sdw_utils/soc_sdw_cs_amp.c +index 4b6181cf29716..35b550bcd4ded 100644 +--- a/sound/soc/sdw_utils/soc_sdw_cs_amp.c ++++ b/sound/soc/sdw_utils/soc_sdw_cs_amp.c +@@ -16,6 +16,25 @@ + + #define CODEC_NAME_SIZE 8 + #define CS_AMP_CHANNELS_PER_AMP 4 ++#define CS35L56_SPK_VOLUME_0DB 400 /* 0dB Max */ ++ ++int asoc_sdw_cs35l56_volume_limit(struct snd_soc_card *card, const char *name_prefix) ++{ ++ char *volume_ctl_name; ++ int ret; ++ ++ volume_ctl_name = kasprintf(GFP_KERNEL, "%s Speaker Volume", name_prefix); ++ if (!volume_ctl_name) ++ return -ENOMEM; ++ ++ ret = snd_soc_limit_volume(card, volume_ctl_name, CS35L56_SPK_VOLUME_0DB); ++ if (ret) ++ dev_err(card->dev, "%s limit set failed: %d\n", volume_ctl_name, ret); ++ ++ kfree(volume_ctl_name); ++ return ret; ++} ++EXPORT_SYMBOL_NS(asoc_sdw_cs35l56_volume_limit, "SND_SOC_SDW_UTILS"); + + int asoc_sdw_cs_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai) + { +@@ -40,6 +59,11 @@ int asoc_sdw_cs_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai + + snprintf(widget_name, sizeof(widget_name), "%s SPK", + codec_dai->component->name_prefix); ++ ++ ret = asoc_sdw_cs35l56_volume_limit(card, codec_dai->component->name_prefix); ++ if (ret) ++ return ret; ++ + ret = snd_soc_dapm_add_routes(&card->dapm, &route, 1); + if (ret) + return ret; +-- +2.39.5 + diff --git a/queue-6.14/asoc-intel-sdw_utils-add-volume-limit-to-cs42l43-spe.patch b/queue-6.14/asoc-intel-sdw_utils-add-volume-limit-to-cs42l43-spe.patch new file mode 100644 index 0000000000..95f8ee72d7 --- /dev/null +++ b/queue-6.14/asoc-intel-sdw_utils-add-volume-limit-to-cs42l43-spe.patch @@ -0,0 +1,60 @@ +From 44112ed71664d5436614bf979ac92e7dadca4134 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 30 Apr 2025 11:31:19 +0100 +Subject: ASoC: intel/sdw_utils: Add volume limit to cs42l43 speakers + +From: Stefan Binding + +[ Upstream commit 02b44a2b2bdcee03cbb92484d31e9ca1b91b2a38 ] + +The volume control for cs42l43 speakers has a maximum gain of +31.5 dB. +However, for many use cases, this can cause distorted audio, depending +various factors, such as other signal-processing elements in the chain, +for example if the audio passes through a gain control before reaching +the codec or the signal path has been tuned for a particular maximum +gain in the codec. + +In the case of systems which use the soc_sdw_cs42l43 driver, audio will +likely be distorted in all cases above 0 dB, therefore add a volume +limit of 128, which is 0 dB maximum volume inside this driver. + +Signed-off-by: Stefan Binding +Reviewed-by: Charles Keepax +Link: https://patch.msgid.link/20250430103134.24579-2-sbinding@opensource.cirrus.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/sdw_utils/soc_sdw_cs42l43.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/sound/soc/sdw_utils/soc_sdw_cs42l43.c b/sound/soc/sdw_utils/soc_sdw_cs42l43.c +index 668c9d28a1c12..b415d45d520d0 100644 +--- a/sound/soc/sdw_utils/soc_sdw_cs42l43.c ++++ b/sound/soc/sdw_utils/soc_sdw_cs42l43.c +@@ -20,6 +20,8 @@ + #include + #include + ++#define CS42L43_SPK_VOLUME_0DB 128 /* 0dB Max */ ++ + static const struct snd_soc_dapm_route cs42l43_hs_map[] = { + { "Headphone", NULL, "cs42l43 AMP3_OUT" }, + { "Headphone", NULL, "cs42l43 AMP4_OUT" }, +@@ -117,6 +119,14 @@ int asoc_sdw_cs42l43_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_so + return -ENOMEM; + } + ++ ret = snd_soc_limit_volume(card, "cs42l43 Speaker Digital Volume", ++ CS42L43_SPK_VOLUME_0DB); ++ if (ret) ++ dev_err(card->dev, "cs42l43 speaker volume limit failed: %d\n", ret); ++ else ++ dev_info(card->dev, "Setting CS42L43 Speaker volume limit to %d\n", ++ CS42L43_SPK_VOLUME_0DB); ++ + ret = snd_soc_dapm_add_routes(&card->dapm, cs42l43_spk_map, + ARRAY_SIZE(cs42l43_spk_map)); + if (ret) +-- +2.39.5 + diff --git a/queue-6.14/asoc-mediatek-mt6359-add-stub-for-mt6359_accdet_enab.patch b/queue-6.14/asoc-mediatek-mt6359-add-stub-for-mt6359_accdet_enab.patch new file mode 100644 index 0000000000..7360246bd9 --- /dev/null +++ b/queue-6.14/asoc-mediatek-mt6359-add-stub-for-mt6359_accdet_enab.patch @@ -0,0 +1,48 @@ +From 56e13e31fc8aa7c938fbdc5b53a719e8c77b7f63 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Mar 2025 16:52:17 -0300 +Subject: ASoC: mediatek: mt6359: Add stub for mt6359_accdet_enable_jack_detect +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Nícolas F. R. A. Prado + +[ Upstream commit 0116a7d84b32537a10d9bea1fd1bfc06577ef527 ] + +Add a stub for mt6359_accdet_enable_jack_detect() to prevent linker +failures in the machine sound drivers calling it when +CONFIG_SND_SOC_MT6359_ACCDET is not enabled. + +Suggested-by: AngeloGioacchino Del Regno +Signed-off-by: Nícolas F. R. A. Prado +Link: https://patch.msgid.link/20250306-mt8188-accdet-v3-3-7828e835ff4b@collabora.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/codecs/mt6359-accdet.h | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/sound/soc/codecs/mt6359-accdet.h b/sound/soc/codecs/mt6359-accdet.h +index c234f2f4276a1..78ada3a5bfae5 100644 +--- a/sound/soc/codecs/mt6359-accdet.h ++++ b/sound/soc/codecs/mt6359-accdet.h +@@ -123,6 +123,15 @@ struct mt6359_accdet { + struct workqueue_struct *jd_workqueue; + }; + ++#if IS_ENABLED(CONFIG_SND_SOC_MT6359_ACCDET) + int mt6359_accdet_enable_jack_detect(struct snd_soc_component *component, + struct snd_soc_jack *jack); ++#else ++static inline int ++mt6359_accdet_enable_jack_detect(struct snd_soc_component *component, ++ struct snd_soc_jack *jack) ++{ ++ return -EOPNOTSUPP; ++} ++#endif + #endif +-- +2.39.5 + diff --git a/queue-6.14/asoc-mediatek-mt8188-add-reference-for-dmic-clocks.patch b/queue-6.14/asoc-mediatek-mt8188-add-reference-for-dmic-clocks.patch new file mode 100644 index 0000000000..fdec1709e7 --- /dev/null +++ b/queue-6.14/asoc-mediatek-mt8188-add-reference-for-dmic-clocks.patch @@ -0,0 +1,68 @@ +From 26cc06b0925f999cb78d2cc91450ea134be7aca7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 25 Feb 2025 11:33:48 -0300 +Subject: ASoC: mediatek: mt8188: Add reference for dmic clocks +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Nícolas F. R. A. Prado + +[ Upstream commit bf1800073f4d55f08191b034c86b95881e99b6fd ] + +Add the names for the dmic clocks, aud_afe_dmic* and aud_dmic_hires*, so +they can be acquired and enabled by the platform driver. + +Signed-off-by: Nícolas F. R. A. Prado +Reviewed-by: AngeloGioacchino Del Regno +Link: https://patch.msgid.link/20250225-genio700-dmic-v2-2-3076f5b50ef7@collabora.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/mediatek/mt8188/mt8188-afe-clk.c | 8 ++++++++ + sound/soc/mediatek/mt8188/mt8188-afe-clk.h | 8 ++++++++ + 2 files changed, 16 insertions(+) + +diff --git a/sound/soc/mediatek/mt8188/mt8188-afe-clk.c b/sound/soc/mediatek/mt8188/mt8188-afe-clk.c +index e69c1bb2cb239..7f411b8577823 100644 +--- a/sound/soc/mediatek/mt8188/mt8188-afe-clk.c ++++ b/sound/soc/mediatek/mt8188/mt8188-afe-clk.c +@@ -58,7 +58,15 @@ static const char *aud_clks[MT8188_CLK_NUM] = { + [MT8188_CLK_AUD_ADC] = "aud_adc", + [MT8188_CLK_AUD_DAC_HIRES] = "aud_dac_hires", + [MT8188_CLK_AUD_A1SYS_HP] = "aud_a1sys_hp", ++ [MT8188_CLK_AUD_AFE_DMIC1] = "aud_afe_dmic1", ++ [MT8188_CLK_AUD_AFE_DMIC2] = "aud_afe_dmic2", ++ [MT8188_CLK_AUD_AFE_DMIC3] = "aud_afe_dmic3", ++ [MT8188_CLK_AUD_AFE_DMIC4] = "aud_afe_dmic4", + [MT8188_CLK_AUD_ADC_HIRES] = "aud_adc_hires", ++ [MT8188_CLK_AUD_DMIC_HIRES1] = "aud_dmic_hires1", ++ [MT8188_CLK_AUD_DMIC_HIRES2] = "aud_dmic_hires2", ++ [MT8188_CLK_AUD_DMIC_HIRES3] = "aud_dmic_hires3", ++ [MT8188_CLK_AUD_DMIC_HIRES4] = "aud_dmic_hires4", + [MT8188_CLK_AUD_I2SIN] = "aud_i2sin", + [MT8188_CLK_AUD_TDM_IN] = "aud_tdm_in", + [MT8188_CLK_AUD_I2S_OUT] = "aud_i2s_out", +diff --git a/sound/soc/mediatek/mt8188/mt8188-afe-clk.h b/sound/soc/mediatek/mt8188/mt8188-afe-clk.h +index ec53c171c170a..c6c78d684f3ee 100644 +--- a/sound/soc/mediatek/mt8188/mt8188-afe-clk.h ++++ b/sound/soc/mediatek/mt8188/mt8188-afe-clk.h +@@ -54,7 +54,15 @@ enum { + MT8188_CLK_AUD_ADC, + MT8188_CLK_AUD_DAC_HIRES, + MT8188_CLK_AUD_A1SYS_HP, ++ MT8188_CLK_AUD_AFE_DMIC1, ++ MT8188_CLK_AUD_AFE_DMIC2, ++ MT8188_CLK_AUD_AFE_DMIC3, ++ MT8188_CLK_AUD_AFE_DMIC4, + MT8188_CLK_AUD_ADC_HIRES, ++ MT8188_CLK_AUD_DMIC_HIRES1, ++ MT8188_CLK_AUD_DMIC_HIRES2, ++ MT8188_CLK_AUD_DMIC_HIRES3, ++ MT8188_CLK_AUD_DMIC_HIRES4, + MT8188_CLK_AUD_I2SIN, + MT8188_CLK_AUD_TDM_IN, + MT8188_CLK_AUD_I2S_OUT, +-- +2.39.5 + diff --git a/queue-6.14/asoc-mediatek-mt8188-treat-dmic_gainx_cur-as-non-vol.patch b/queue-6.14/asoc-mediatek-mt8188-treat-dmic_gainx_cur-as-non-vol.patch new file mode 100644 index 0000000000..b710fc8840 --- /dev/null +++ b/queue-6.14/asoc-mediatek-mt8188-treat-dmic_gainx_cur-as-non-vol.patch @@ -0,0 +1,55 @@ +From ef2d751ff692b41e55a44e7a3b64187348fe1163 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 25 Feb 2025 11:33:49 -0300 +Subject: ASoC: mediatek: mt8188: Treat DMIC_GAINx_CUR as non-volatile +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Nícolas F. R. A. Prado + +[ Upstream commit 7d87bde21c73731ddaf15e572020f80999c38ee3 ] + +The DMIC_GAINx_CUR registers contain the current (as in present) gain of +each DMIC. During capture, this gain will ramp up until a target value +is reached, and therefore the register is volatile since it is updated +automatically by hardware. + +However, after capture the register's value returns to the value that +was written to it. So reading these registers returns the current gain, +and writing configures the initial gain for every capture. + +>From an audio configuration perspective, reading the instantaneous gain +is not really useful. Instead, reading back the initial gain that was +configured is the desired behavior. For that reason, consider the +DMIC_GAINx_CUR registers as non-volatile, so the regmap's cache can be +used to retrieve the values, rather than requiring pm runtime resuming +the device. + +Signed-off-by: Nícolas F. R. A. Prado +Reviewed-by: AngeloGioacchino Del Regno +Link: https://patch.msgid.link/20250225-genio700-dmic-v2-3-3076f5b50ef7@collabora.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/mediatek/mt8188/mt8188-afe-pcm.c | 4 ---- + 1 file changed, 4 deletions(-) + +diff --git a/sound/soc/mediatek/mt8188/mt8188-afe-pcm.c b/sound/soc/mediatek/mt8188/mt8188-afe-pcm.c +index 73e5c63aeec87..d36520c6272dd 100644 +--- a/sound/soc/mediatek/mt8188/mt8188-afe-pcm.c ++++ b/sound/soc/mediatek/mt8188/mt8188-afe-pcm.c +@@ -2855,10 +2855,6 @@ static bool mt8188_is_volatile_reg(struct device *dev, unsigned int reg) + case AFE_DMIC3_SRC_DEBUG_MON0: + case AFE_DMIC3_UL_SRC_MON0: + case AFE_DMIC3_UL_SRC_MON1: +- case DMIC_GAIN1_CUR: +- case DMIC_GAIN2_CUR: +- case DMIC_GAIN3_CUR: +- case DMIC_GAIN4_CUR: + case ETDM_IN1_MONITOR: + case ETDM_IN2_MONITOR: + case ETDM_OUT1_MONITOR: +-- +2.39.5 + diff --git a/queue-6.14/asoc-ops-enforce-platform-maximum-on-initial-value.patch b/queue-6.14/asoc-ops-enforce-platform-maximum-on-initial-value.patch new file mode 100644 index 0000000000..fc652ef938 --- /dev/null +++ b/queue-6.14/asoc-ops-enforce-platform-maximum-on-initial-value.patch @@ -0,0 +1,75 @@ +From f544b9d71044602e2c971a80e78a87cada75089d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 8 Feb 2025 00:57:22 +0000 +Subject: ASoC: ops: Enforce platform maximum on initial value +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Martin PoviÅ¡er + +[ Upstream commit 783db6851c1821d8b983ffb12b99c279ff64f2ee ] + +Lower the volume if it is violating the platform maximum at its initial +value (i.e. at the time of the 'snd_soc_limit_volume' call). + +Signed-off-by: Martin PoviÅ¡er +[Cherry picked from the Asahi kernel with fixups -- broonie] +Signed-off-by: Mark Brown +Link: https://patch.msgid.link/20250208-asoc-volume-limit-v1-1-b98fcf4cdbad@kernel.org +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/soc-ops.c | 29 ++++++++++++++++++++++++++++- + 1 file changed, 28 insertions(+), 1 deletion(-) + +diff --git a/sound/soc/soc-ops.c b/sound/soc/soc-ops.c +index b0e4e4168f38d..fb11003d56cf6 100644 +--- a/sound/soc/soc-ops.c ++++ b/sound/soc/soc-ops.c +@@ -639,6 +639,33 @@ int snd_soc_get_volsw_range(struct snd_kcontrol *kcontrol, + } + EXPORT_SYMBOL_GPL(snd_soc_get_volsw_range); + ++static int snd_soc_clip_to_platform_max(struct snd_kcontrol *kctl) ++{ ++ struct soc_mixer_control *mc = (struct soc_mixer_control *)kctl->private_value; ++ struct snd_ctl_elem_value uctl; ++ int ret; ++ ++ if (!mc->platform_max) ++ return 0; ++ ++ ret = kctl->get(kctl, &uctl); ++ if (ret < 0) ++ return ret; ++ ++ if (uctl.value.integer.value[0] > mc->platform_max) ++ uctl.value.integer.value[0] = mc->platform_max; ++ ++ if (snd_soc_volsw_is_stereo(mc) && ++ uctl.value.integer.value[1] > mc->platform_max) ++ uctl.value.integer.value[1] = mc->platform_max; ++ ++ ret = kctl->put(kctl, &uctl); ++ if (ret < 0) ++ return ret; ++ ++ return 0; ++} ++ + /** + * snd_soc_limit_volume - Set new limit to an existing volume control. + * +@@ -663,7 +690,7 @@ int snd_soc_limit_volume(struct snd_soc_card *card, + struct soc_mixer_control *mc = (struct soc_mixer_control *)kctl->private_value; + if (max <= mc->max - mc->min) { + mc->platform_max = max; +- ret = 0; ++ ret = snd_soc_clip_to_platform_max(kctl); + } + } + return ret; +-- +2.39.5 + diff --git a/queue-6.14/asoc-pcm6240-drop-bogus-code-handling-irq-as-gpio.patch b/queue-6.14/asoc-pcm6240-drop-bogus-code-handling-irq-as-gpio.patch new file mode 100644 index 0000000000..3a9489f07a --- /dev/null +++ b/queue-6.14/asoc-pcm6240-drop-bogus-code-handling-irq-as-gpio.patch @@ -0,0 +1,131 @@ +From 1da39871bce05a83ffd4357fa9329a2f5d73000c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 12 Mar 2025 14:31:52 +0100 +Subject: ASoC: pcm6240: Drop bogus code handling IRQ as GPIO + +From: Linus Walleij + +[ Upstream commit 17fdf318f5fbe5c27353ae917c0c5a2899d9c259 ] + +The current code for the IRQ in pcm6240 makes no sense: +it looks up an IRQ with of_irq_get(), treat it as a GPIO +by issuing gpio_request(), gpio_direction_input() +and gpio_to_irq() on it. + +This is just wrong, if the device tree assigns the IRQ +from a GPIO number this is just incorrect: it is clearly +stated that GPIO providers and IRQ providers are +orthogonal. + +It is possible to look up an IRQ to a corresponding GPIO +line but this is taking an IRQ and pretending it's a +GPIO, which is just semantically wrong. + +Drop the offending code and treat the IRQ that we get +from the device tree as any other IRQ, see for example +other codec drivers. + +The DT bindings for this codec does not have any in-tree +DTS files, which may explain why things are weird. + +As a bonus, this moves the driver away from the legacy + include. + +Signed-off-by: Linus Walleij +Link: https://patch.msgid.link/20250312-pcm-codecs-v1-3-41ffc4f8fc5c@linaro.org +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/codecs/pcm6240.c | 28 +++++++--------------------- + sound/soc/codecs/pcm6240.h | 7 +------ + 2 files changed, 8 insertions(+), 27 deletions(-) + +diff --git a/sound/soc/codecs/pcm6240.c b/sound/soc/codecs/pcm6240.c +index 4ff39e0b95b27..b2bd2f172ae76 100644 +--- a/sound/soc/codecs/pcm6240.c ++++ b/sound/soc/codecs/pcm6240.c +@@ -14,7 +14,7 @@ + + #include + #include +-#include ++#include + #include + #include + #include +@@ -2035,10 +2035,8 @@ static const struct regmap_config pcmdevice_i2c_regmap = { + + static void pcmdevice_remove(struct pcmdevice_priv *pcm_dev) + { +- if (gpio_is_valid(pcm_dev->irq_info.gpio)) { +- gpio_free(pcm_dev->irq_info.gpio); +- free_irq(pcm_dev->irq_info.nmb, pcm_dev); +- } ++ if (pcm_dev->irq) ++ free_irq(pcm_dev->irq, pcm_dev); + mutex_destroy(&pcm_dev->codec_lock); + } + +@@ -2109,7 +2107,7 @@ static int pcmdevice_i2c_probe(struct i2c_client *i2c) + ndev = 1; + dev_addrs[0] = i2c->addr; + } +- pcm_dev->irq_info.gpio = of_irq_get(np, 0); ++ pcm_dev->irq = of_irq_get(np, 0); + + for (i = 0; i < ndev; i++) + pcm_dev->addr[i] = dev_addrs[i]; +@@ -2132,22 +2130,10 @@ static int pcmdevice_i2c_probe(struct i2c_client *i2c) + + if (pcm_dev->chip_id == PCM1690) + goto skip_interrupt; +- if (gpio_is_valid(pcm_dev->irq_info.gpio)) { +- dev_dbg(pcm_dev->dev, "irq-gpio = %d", pcm_dev->irq_info.gpio); +- +- ret = gpio_request(pcm_dev->irq_info.gpio, "PCMDEV-IRQ"); +- if (!ret) { +- int gpio = pcm_dev->irq_info.gpio; +- +- gpio_direction_input(gpio); +- pcm_dev->irq_info.nmb = gpio_to_irq(gpio); +- +- } else +- dev_err(pcm_dev->dev, "%s: GPIO %d request error\n", +- __func__, pcm_dev->irq_info.gpio); ++ if (pcm_dev->irq) { ++ dev_dbg(pcm_dev->dev, "irq = %d", pcm_dev->irq); + } else +- dev_err(pcm_dev->dev, "Looking up irq-gpio failed %d\n", +- pcm_dev->irq_info.gpio); ++ dev_err(pcm_dev->dev, "No irq provided\n"); + + skip_interrupt: + ret = devm_snd_soc_register_component(&i2c->dev, +diff --git a/sound/soc/codecs/pcm6240.h b/sound/soc/codecs/pcm6240.h +index 1e125bb972860..2d8f9e798139a 100644 +--- a/sound/soc/codecs/pcm6240.h ++++ b/sound/soc/codecs/pcm6240.h +@@ -208,11 +208,6 @@ struct pcmdevice_regbin { + struct pcmdevice_config_info **cfg_info; + }; + +-struct pcmdevice_irqinfo { +- int gpio; +- int nmb; +-}; +- + struct pcmdevice_priv { + struct snd_soc_component *component; + struct i2c_client *client; +@@ -221,7 +216,7 @@ struct pcmdevice_priv { + struct gpio_desc *hw_rst; + struct regmap *regmap; + struct pcmdevice_regbin regbin; +- struct pcmdevice_irqinfo irq_info; ++ int irq; + unsigned int addr[PCMDEVICE_MAX_I2C_DEVICES]; + unsigned int chip_id; + int cur_conf; +-- +2.39.5 + diff --git a/queue-6.14/asoc-qcom-sm8250-explicitly-set-format-in-sm8250_be_.patch b/queue-6.14/asoc-qcom-sm8250-explicitly-set-format-in-sm8250_be_.patch new file mode 100644 index 0000000000..c4a8ced95b --- /dev/null +++ b/queue-6.14/asoc-qcom-sm8250-explicitly-set-format-in-sm8250_be_.patch @@ -0,0 +1,49 @@ +From 4342fa55c01ed83a3fe04cc22b5be6c628731ed1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 28 Feb 2025 16:14:30 +0000 +Subject: ASoC: qcom: sm8250: explicitly set format in + sm8250_be_hw_params_fixup() + +From: Alexey Klimov + +[ Upstream commit 89be3c15a58b2ccf31e969223c8ac93ca8932d81 ] + +Setting format to s16le is required for compressed playback on compatible +soundcards. + +Cc: Srinivas Kandagatla +Signed-off-by: Alexey Klimov +Link: https://patch.msgid.link/20250228161430.373961-1-alexey.klimov@linaro.org +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/qcom/sm8250.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/sound/soc/qcom/sm8250.c b/sound/soc/qcom/sm8250.c +index 45e0c33fc3f37..9039107972e2b 100644 +--- a/sound/soc/qcom/sm8250.c ++++ b/sound/soc/qcom/sm8250.c +@@ -7,6 +7,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -39,9 +40,11 @@ static int sm8250_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, + SNDRV_PCM_HW_PARAM_RATE); + struct snd_interval *channels = hw_param_interval(params, + SNDRV_PCM_HW_PARAM_CHANNELS); ++ struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); + + rate->min = rate->max = 48000; + channels->min = channels->max = 2; ++ snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S16_LE); + + return 0; + } +-- +2.39.5 + diff --git a/queue-6.14/asoc-rt722-sdca-add-some-missing-readable-registers.patch b/queue-6.14/asoc-rt722-sdca-add-some-missing-readable-registers.patch new file mode 100644 index 0000000000..5065e408d0 --- /dev/null +++ b/queue-6.14/asoc-rt722-sdca-add-some-missing-readable-registers.patch @@ -0,0 +1,98 @@ +From 55bb761a764cf8c6fa27436c070dfc8f22e11628 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 Jan 2025 15:44:07 +0000 +Subject: ASoC: rt722-sdca: Add some missing readable registers + +From: Charles Keepax + +[ Upstream commit f9a5c4b6afc79073491acdab7f1e943ee3a19fbb ] + +Add a few missing registers from the readable register callback. + +Suggested-by: Shuming Fan +Signed-off-by: Charles Keepax +Reviewed-by: Pierre-Louis Bossart +Link: https://patch.msgid.link/20250107154408.814455-6-ckeepax@opensource.cirrus.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/codecs/rt722-sdca-sdw.c | 49 +++++++++++++++++++++++++++++-- + 1 file changed, 46 insertions(+), 3 deletions(-) + +diff --git a/sound/soc/codecs/rt722-sdca-sdw.c b/sound/soc/codecs/rt722-sdca-sdw.c +index 4d3043627bd04..cfb030e71e5c5 100644 +--- a/sound/soc/codecs/rt722-sdca-sdw.c ++++ b/sound/soc/codecs/rt722-sdca-sdw.c +@@ -28,9 +28,50 @@ static bool rt722_sdca_readable_register(struct device *dev, unsigned int reg) + 0): + case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT_GE49, RT722_SDCA_CTL_DETECTED_MODE, + 0): +- case SDW_SDCA_CTL(FUNC_NUM_HID, RT722_SDCA_ENT_HID01, RT722_SDCA_CTL_HIDTX_CURRENT_OWNER, +- 0) ... SDW_SDCA_CTL(FUNC_NUM_HID, RT722_SDCA_ENT_HID01, +- RT722_SDCA_CTL_HIDTX_MESSAGE_LENGTH, 0): ++ case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT_XU03, RT722_SDCA_CTL_SELECTED_MODE, ++ 0): ++ case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT_USER_FU05, ++ RT722_SDCA_CTL_FU_MUTE, CH_L) ... ++ SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT_USER_FU05, ++ RT722_SDCA_CTL_FU_MUTE, CH_R): ++ case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT_XU0D, ++ RT722_SDCA_CTL_SELECTED_MODE, 0): ++ case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT_USER_FU0F, ++ RT722_SDCA_CTL_FU_MUTE, CH_L) ... ++ SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT_USER_FU0F, ++ RT722_SDCA_CTL_FU_MUTE, CH_R): ++ case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT_PDE40, ++ RT722_SDCA_CTL_REQ_POWER_STATE, 0): ++ case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT_PDE12, ++ RT722_SDCA_CTL_REQ_POWER_STATE, 0): ++ case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT_CS01, ++ RT722_SDCA_CTL_SAMPLE_FREQ_INDEX, 0): ++ case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT_CS11, ++ RT722_SDCA_CTL_SAMPLE_FREQ_INDEX, 0): ++ case SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT722_SDCA_ENT_USER_FU1E, ++ RT722_SDCA_CTL_FU_MUTE, CH_01) ... ++ SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT722_SDCA_ENT_USER_FU1E, ++ RT722_SDCA_CTL_FU_MUTE, CH_04): ++ case SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT722_SDCA_ENT_IT26, ++ RT722_SDCA_CTL_VENDOR_DEF, 0): ++ case SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT722_SDCA_ENT_PDE2A, ++ RT722_SDCA_CTL_REQ_POWER_STATE, 0): ++ case SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT722_SDCA_ENT_CS1F, ++ RT722_SDCA_CTL_SAMPLE_FREQ_INDEX, 0): ++ case SDW_SDCA_CTL(FUNC_NUM_HID, RT722_SDCA_ENT_HID01, ++ RT722_SDCA_CTL_HIDTX_CURRENT_OWNER, 0) ... ++ SDW_SDCA_CTL(FUNC_NUM_HID, RT722_SDCA_ENT_HID01, ++ RT722_SDCA_CTL_HIDTX_MESSAGE_LENGTH, 0): ++ case SDW_SDCA_CTL(FUNC_NUM_AMP, RT722_SDCA_ENT_USER_FU06, ++ RT722_SDCA_CTL_FU_MUTE, CH_L) ... ++ SDW_SDCA_CTL(FUNC_NUM_AMP, RT722_SDCA_ENT_USER_FU06, ++ RT722_SDCA_CTL_FU_MUTE, CH_R): ++ case SDW_SDCA_CTL(FUNC_NUM_AMP, RT722_SDCA_ENT_OT23, ++ RT722_SDCA_CTL_VENDOR_DEF, CH_08): ++ case SDW_SDCA_CTL(FUNC_NUM_AMP, RT722_SDCA_ENT_PDE23, ++ RT722_SDCA_CTL_REQ_POWER_STATE, 0): ++ case SDW_SDCA_CTL(FUNC_NUM_AMP, RT722_SDCA_ENT_CS31, ++ RT722_SDCA_CTL_SAMPLE_FREQ_INDEX, 0): + case RT722_BUF_ADDR_HID1 ... RT722_BUF_ADDR_HID2: + return true; + default: +@@ -74,6 +115,7 @@ static bool rt722_sdca_mbq_readable_register(struct device *dev, unsigned int re + case 0x5600000 ... 0x5600007: + case 0x5700000 ... 0x5700004: + case 0x5800000 ... 0x5800004: ++ case 0x5810000: + case 0x5b00003: + case 0x5c00011: + case 0x5d00006: +@@ -81,6 +123,7 @@ static bool rt722_sdca_mbq_readable_register(struct device *dev, unsigned int re + case 0x5f00030: + case 0x6100000 ... 0x6100051: + case 0x6100055 ... 0x6100057: ++ case 0x6100060: + case 0x6100062: + case 0x6100064 ... 0x6100065: + case 0x6100067: +-- +2.39.5 + diff --git a/queue-6.14/asoc-sma1307-add-null-check-in-sma1307_setting_loade.patch b/queue-6.14/asoc-sma1307-add-null-check-in-sma1307_setting_loade.patch new file mode 100644 index 0000000000..164d650743 --- /dev/null +++ b/queue-6.14/asoc-sma1307-add-null-check-in-sma1307_setting_loade.patch @@ -0,0 +1,85 @@ +From 2fc55ed1d59cd9b8e0f11963a462a396f845a4c4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 10 Mar 2025 20:57:14 -0500 +Subject: ASoC: sma1307: Add NULL check in sma1307_setting_loaded() + +From: Chenyuan Yang + +[ Upstream commit 0ec6bd16705fe21d6429d6b8f7981eae2142bba8 ] + +All varibale allocated by kzalloc and devm_kzalloc could be NULL. +Multiple pointer checks and their cleanup are added. + +This issue is found by our static analysis tool + +Signed-off-by: Chenyuan Yang +Link: https://patch.msgid.link/20250311015714.1333857-1-chenyuan0y@gmail.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/codecs/sma1307.c | 28 ++++++++++++++++++++++++++++ + 1 file changed, 28 insertions(+) + +diff --git a/sound/soc/codecs/sma1307.c b/sound/soc/codecs/sma1307.c +index 480bcea48541e..b9d8136fe3dc1 100644 +--- a/sound/soc/codecs/sma1307.c ++++ b/sound/soc/codecs/sma1307.c +@@ -1728,6 +1728,11 @@ static void sma1307_setting_loaded(struct sma1307_priv *sma1307, const char *fil + } + + data = kzalloc(fw->size, GFP_KERNEL); ++ if (!data) { ++ release_firmware(fw); ++ sma1307->set.status = false; ++ return; ++ } + size = fw->size >> 2; + memcpy(data, fw->data, fw->size); + +@@ -1741,6 +1746,12 @@ static void sma1307_setting_loaded(struct sma1307_priv *sma1307, const char *fil + sma1307->set.header = devm_kzalloc(sma1307->dev, + sma1307->set.header_size, + GFP_KERNEL); ++ if (!sma1307->set.header) { ++ kfree(data); ++ sma1307->set.status = false; ++ return; ++ } ++ + memcpy(sma1307->set.header, data, + sma1307->set.header_size * sizeof(int)); + +@@ -1756,6 +1767,13 @@ static void sma1307_setting_loaded(struct sma1307_priv *sma1307, const char *fil + sma1307->set.def + = devm_kzalloc(sma1307->dev, + sma1307->set.def_size * sizeof(int), GFP_KERNEL); ++ if (!sma1307->set.def) { ++ kfree(data); ++ kfree(sma1307->set.header); ++ sma1307->set.status = false; ++ return; ++ } ++ + memcpy(sma1307->set.def, + &data[sma1307->set.header_size], + sma1307->set.def_size * sizeof(int)); +@@ -1768,6 +1786,16 @@ static void sma1307_setting_loaded(struct sma1307_priv *sma1307, const char *fil + = devm_kzalloc(sma1307->dev, + sma1307->set.mode_size * 2 * sizeof(int), + GFP_KERNEL); ++ if (!sma1307->set.mode_set[i]) { ++ kfree(data); ++ kfree(sma1307->set.header); ++ kfree(sma1307->set.def); ++ for (int j = 0; j < i; j++) ++ kfree(sma1307->set.mode_set[j]); ++ sma1307->set.status = false; ++ return; ++ } ++ + for (int j = 0; j < sma1307->set.mode_size; j++) { + sma1307->set.mode_set[i][2 * j] + = data[offset + ((num_mode + 1) * j)]; +-- +2.39.5 + diff --git a/queue-6.14/asoc-sma1307-fix-error-handling-in-sma1307_setting_l.patch b/queue-6.14/asoc-sma1307-fix-error-handling-in-sma1307_setting_l.patch new file mode 100644 index 0000000000..f07da42c88 --- /dev/null +++ b/queue-6.14/asoc-sma1307-fix-error-handling-in-sma1307_setting_l.patch @@ -0,0 +1,91 @@ +From f4966881edd405db56985a0639c1d14297b45ff0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 21 Mar 2025 17:35:25 +0300 +Subject: ASoC: sma1307: Fix error handling in sma1307_setting_loaded() + +From: Dan Carpenter + +[ Upstream commit 012a6efcc805308b1d90a1056ba963eb08858645 ] + +There are a couple bugs in this code: + +1) The cleanup code calls kfree(sma1307->set.header) and + kfree(sma1307->set.def) but those functions were allocated using + devm_kzalloc(). It results in a double free. Delete all these + kfree() calls. + +2) A missing call to kfree(data) if the checksum was wrong on this error + path: + if ((sma1307->set.checksum >> 8) != SMA1307_SETTING_CHECKSUM) { + Since the "data" pointer is supposed to be freed on every return, I + changed that to use the __free(kfree) cleanup attribute. + +Fixes: 0ec6bd16705f ("ASoC: sma1307: Add NULL check in sma1307_setting_loaded()") +Signed-off-by: Dan Carpenter +Link: https://patch.msgid.link/8d32dd96-1404-4373-9b6c-c612a9c18c4c@stanley.mountain +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/codecs/sma1307.c | 11 ++--------- + 1 file changed, 2 insertions(+), 9 deletions(-) + +diff --git a/sound/soc/codecs/sma1307.c b/sound/soc/codecs/sma1307.c +index b9d8136fe3dc1..793abec56dd27 100644 +--- a/sound/soc/codecs/sma1307.c ++++ b/sound/soc/codecs/sma1307.c +@@ -1710,7 +1710,7 @@ static void sma1307_check_fault_worker(struct work_struct *work) + static void sma1307_setting_loaded(struct sma1307_priv *sma1307, const char *file) + { + const struct firmware *fw; +- int *data, size, offset, num_mode; ++ int size, offset, num_mode; + int ret; + + ret = request_firmware(&fw, file, sma1307->dev); +@@ -1727,7 +1727,7 @@ static void sma1307_setting_loaded(struct sma1307_priv *sma1307, const char *fil + return; + } + +- data = kzalloc(fw->size, GFP_KERNEL); ++ int *data __free(kfree) = kzalloc(fw->size, GFP_KERNEL); + if (!data) { + release_firmware(fw); + sma1307->set.status = false; +@@ -1747,7 +1747,6 @@ static void sma1307_setting_loaded(struct sma1307_priv *sma1307, const char *fil + sma1307->set.header_size, + GFP_KERNEL); + if (!sma1307->set.header) { +- kfree(data); + sma1307->set.status = false; + return; + } +@@ -1768,8 +1767,6 @@ static void sma1307_setting_loaded(struct sma1307_priv *sma1307, const char *fil + = devm_kzalloc(sma1307->dev, + sma1307->set.def_size * sizeof(int), GFP_KERNEL); + if (!sma1307->set.def) { +- kfree(data); +- kfree(sma1307->set.header); + sma1307->set.status = false; + return; + } +@@ -1787,9 +1784,6 @@ static void sma1307_setting_loaded(struct sma1307_priv *sma1307, const char *fil + sma1307->set.mode_size * 2 * sizeof(int), + GFP_KERNEL); + if (!sma1307->set.mode_set[i]) { +- kfree(data); +- kfree(sma1307->set.header); +- kfree(sma1307->set.def); + for (int j = 0; j < i; j++) + kfree(sma1307->set.mode_set[j]); + sma1307->set.status = false; +@@ -1804,7 +1798,6 @@ static void sma1307_setting_loaded(struct sma1307_priv *sma1307, const char *fil + } + } + +- kfree(data); + sma1307->set.status = true; + + } +-- +2.39.5 + diff --git a/queue-6.14/asoc-soc-dai-check-return-value-at-snd_soc_dai_set_t.patch b/queue-6.14/asoc-soc-dai-check-return-value-at-snd_soc_dai_set_t.patch new file mode 100644 index 0000000000..21c5f568d0 --- /dev/null +++ b/queue-6.14/asoc-soc-dai-check-return-value-at-snd_soc_dai_set_t.patch @@ -0,0 +1,54 @@ +From 71e5fe9e8e44b570730b10a5727be547d9d4d8dd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 12 Feb 2025 02:24:38 +0000 +Subject: ASoC: soc-dai: check return value at snd_soc_dai_set_tdm_slot() + +From: Kuninori Morimoto + +[ Upstream commit 7f1186a8d738661b941b298fd6d1d5725ed71428 ] + +snd_soc_dai_set_tdm_slot() calls .xlate_tdm_slot_mask() or +snd_soc_xlate_tdm_slot_mask(), but didn't check its return value. +Let's check it. + +This patch might break existing driver. In such case, let's makes +each func to void instead of int. + +Signed-off-by: Kuninori Morimoto +Link: https://patch.msgid.link/87o6z7yk61.wl-kuninori.morimoto.gx@renesas.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/soc-dai.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +diff --git a/sound/soc/soc-dai.c b/sound/soc/soc-dai.c +index ca0308f6d41c1..dc7283ee4dfb0 100644 +--- a/sound/soc/soc-dai.c ++++ b/sound/soc/soc-dai.c +@@ -275,10 +275,11 @@ int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai, + + if (dai->driver->ops && + dai->driver->ops->xlate_tdm_slot_mask) +- dai->driver->ops->xlate_tdm_slot_mask(slots, +- &tx_mask, &rx_mask); ++ ret = dai->driver->ops->xlate_tdm_slot_mask(slots, &tx_mask, &rx_mask); + else +- snd_soc_xlate_tdm_slot_mask(slots, &tx_mask, &rx_mask); ++ ret = snd_soc_xlate_tdm_slot_mask(slots, &tx_mask, &rx_mask); ++ if (ret) ++ goto err; + + for_each_pcm_streams(stream) + snd_soc_dai_tdm_mask_set(dai, stream, *tdm_mask[stream]); +@@ -287,6 +288,7 @@ int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai, + dai->driver->ops->set_tdm_slot) + ret = dai->driver->ops->set_tdm_slot(dai, tx_mask, rx_mask, + slots, slot_width); ++err: + return soc_dai_ret(dai, ret); + } + EXPORT_SYMBOL_GPL(snd_soc_dai_set_tdm_slot); +-- +2.39.5 + diff --git a/queue-6.14/asoc-sun4i-codec-correct-dapm-widgets-and-controls-f.patch b/queue-6.14/asoc-sun4i-codec-correct-dapm-widgets-and-controls-f.patch new file mode 100644 index 0000000000..e59085c9ad --- /dev/null +++ b/queue-6.14/asoc-sun4i-codec-correct-dapm-widgets-and-controls-f.patch @@ -0,0 +1,55 @@ +From 8e03b7b3bca2c32a98f7cd96de934381b2e11c8f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 15 Feb 2025 11:02:24 +1300 +Subject: ASoC: sun4i-codec: correct dapm widgets and controls for h616 + +From: Ryan Walklin + +[ Upstream commit ae5f76d4044d1580849316c49290678605e0889d ] + +The previous H616 support patch added a single LINEOUT DAPM pin switch +to the card controls. As the codec in this SoC only has a single route, +this seemed reasonable at the time, however is redundant given the +existing DAPM codec widget definitions controlling the digital and +analog sides of the codec. + +It is also insufficient to describe the scenario where separate +components (muxes, jack detection etc) are used to modify the audio +route external to the SoC. For example the Anbernic RG(##)XX series of +devices uses a headphone jack detection switch, GPIO-controlled speaker +amplifier and a passive external mux chip to route audio. + +Remove the redundant LINEOUT card control, and add a Speaker pin switch +control and Headphone DAPM widget to allow control of the above +hardware. + +Signed-off-by: Chris Morgan +Signed-off-by: Ryan Walklin +Tested-by: Philippe Simons +Link: https://patch.msgid.link/20250214220247.10810-3-ryan@testtoast.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/sunxi/sun4i-codec.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/sound/soc/sunxi/sun4i-codec.c b/sound/soc/sunxi/sun4i-codec.c +index 06e85b34fdf68..3701f56c72756 100644 +--- a/sound/soc/sunxi/sun4i-codec.c ++++ b/sound/soc/sunxi/sun4i-codec.c +@@ -1962,10 +1962,11 @@ static const struct snd_soc_component_driver sun50i_h616_codec_codec = { + }; + + static const struct snd_kcontrol_new sun50i_h616_card_controls[] = { +- SOC_DAPM_PIN_SWITCH("LINEOUT"), ++ SOC_DAPM_PIN_SWITCH("Speaker"), + }; + + static const struct snd_soc_dapm_widget sun50i_h616_codec_card_dapm_widgets[] = { ++ SND_SOC_DAPM_HP("Headphone", NULL), + SND_SOC_DAPM_LINE("Line Out", NULL), + SND_SOC_DAPM_SPK("Speaker", sun4i_codec_spk_event), + }; +-- +2.39.5 + diff --git a/queue-6.14/asoc-sun4i-codec-support-hp-det-gpios-property.patch b/queue-6.14/asoc-sun4i-codec-support-hp-det-gpios-property.patch new file mode 100644 index 0000000000..1cc7856dc8 --- /dev/null +++ b/queue-6.14/asoc-sun4i-codec-support-hp-det-gpios-property.patch @@ -0,0 +1,128 @@ +From 05d597df8d53da68b4e6a2f4368ed7461910fe24 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 15 Feb 2025 11:02:25 +1300 +Subject: ASoC: sun4i-codec: support hp-det-gpios property + +From: Ryan Walklin + +[ Upstream commit a149377c033afe6557c50892ebbfc0e8b7e2e253 ] + +Add support for GPIO headphone detection with the hp-det-gpios +property. In order for this to properly disable the path upon +removal of headphones, the output must be labelled Headphone which +is a common sink in the driver. + +Describe a headphone jack and detection GPIO in the driver, check for +a corresponding device tree node, and enable jack detection in a new +machine init function if described. + +Signed-off-by: Chris Morgan +Signed-off-by: Ryan Walklin + +-- +Changelog v1..v2: +- Separate DAPM changes into separate patch and add rationale. + +Tested-by: Philippe Simons +Link: https://patch.msgid.link/20250214220247.10810-4-ryan@testtoast.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/sunxi/sun4i-codec.c | 53 +++++++++++++++++++++++++++++++++++ + 1 file changed, 53 insertions(+) + +diff --git a/sound/soc/sunxi/sun4i-codec.c b/sound/soc/sunxi/sun4i-codec.c +index 886b3fa537d26..06e85b34fdf68 100644 +--- a/sound/soc/sunxi/sun4i-codec.c ++++ b/sound/soc/sunxi/sun4i-codec.c +@@ -22,6 +22,7 @@ + #include + + #include ++#include + #include + #include + #include +@@ -331,6 +332,7 @@ struct sun4i_codec { + struct clk *clk_module; + struct reset_control *rst; + struct gpio_desc *gpio_pa; ++ struct gpio_desc *gpio_hp; + + /* ADC_FIFOC register is at different offset on different SoCs */ + struct regmap_field *reg_adc_fifoc; +@@ -1583,6 +1585,49 @@ static struct snd_soc_dai_driver dummy_cpu_dai = { + .ops = &dummy_dai_ops, + }; + ++static struct snd_soc_jack sun4i_headphone_jack; ++ ++static struct snd_soc_jack_pin sun4i_headphone_jack_pins[] = { ++ { .pin = "Headphone", .mask = SND_JACK_HEADPHONE }, ++}; ++ ++static struct snd_soc_jack_gpio sun4i_headphone_jack_gpio = { ++ .name = "hp-det", ++ .report = SND_JACK_HEADPHONE, ++ .debounce_time = 150, ++}; ++ ++static int sun4i_codec_machine_init(struct snd_soc_pcm_runtime *rtd) ++{ ++ struct snd_soc_card *card = rtd->card; ++ struct sun4i_codec *scodec = snd_soc_card_get_drvdata(card); ++ int ret; ++ ++ if (scodec->gpio_hp) { ++ ret = snd_soc_card_jack_new_pins(card, "Headphone Jack", ++ SND_JACK_HEADPHONE, ++ &sun4i_headphone_jack, ++ sun4i_headphone_jack_pins, ++ ARRAY_SIZE(sun4i_headphone_jack_pins)); ++ if (ret) { ++ dev_err(rtd->dev, ++ "Headphone jack creation failed: %d\n", ret); ++ return ret; ++ } ++ ++ sun4i_headphone_jack_gpio.desc = scodec->gpio_hp; ++ ret = snd_soc_jack_add_gpios(&sun4i_headphone_jack, 1, ++ &sun4i_headphone_jack_gpio); ++ ++ if (ret) { ++ dev_err(rtd->dev, "Headphone GPIO not added: %d\n", ret); ++ return ret; ++ } ++ } ++ ++ return 0; ++} ++ + static struct snd_soc_dai_link *sun4i_codec_create_link(struct device *dev, + int *num_links) + { +@@ -1608,6 +1653,7 @@ static struct snd_soc_dai_link *sun4i_codec_create_link(struct device *dev, + link->codecs->name = dev_name(dev); + link->platforms->name = dev_name(dev); + link->dai_fmt = SND_SOC_DAIFMT_I2S; ++ link->init = sun4i_codec_machine_init; + + *num_links = 1; + +@@ -2301,6 +2347,13 @@ static int sun4i_codec_probe(struct platform_device *pdev) + return ret; + } + ++ scodec->gpio_hp = devm_gpiod_get_optional(&pdev->dev, "hp-det", GPIOD_IN); ++ if (IS_ERR(scodec->gpio_hp)) { ++ ret = PTR_ERR(scodec->gpio_hp); ++ dev_err_probe(&pdev->dev, ret, "Failed to get hp-det gpio\n"); ++ return ret; ++ } ++ + /* reg_field setup */ + scodec->reg_adc_fifoc = devm_regmap_field_alloc(&pdev->dev, + scodec->regmap, +-- +2.39.5 + diff --git a/queue-6.14/asoc-tas2764-add-reg-defaults-for-tas2764_int_clk_cf.patch b/queue-6.14/asoc-tas2764-add-reg-defaults-for-tas2764_int_clk_cf.patch new file mode 100644 index 0000000000..ffd6b57f18 --- /dev/null +++ b/queue-6.14/asoc-tas2764-add-reg-defaults-for-tas2764_int_clk_cf.patch @@ -0,0 +1,33 @@ +From 2929ff79d54a666f11a39cb24be50f8bfc4588e5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 8 Feb 2025 01:03:27 +0000 +Subject: ASoC: tas2764: Add reg defaults for TAS2764_INT_CLK_CFG + +From: Hector Martin + +[ Upstream commit d64c4c3d1c578f98d70db1c5e2535b47adce9d07 ] + +Signed-off-by: Hector Martin +Signed-off-by: Mark Brown +Link: https://patch.msgid.link/20250208-asoc-tas2764-v1-4-dbab892a69b5@kernel.org +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/codecs/tas2764.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/sound/soc/codecs/tas2764.c b/sound/soc/codecs/tas2764.c +index 58315eab492a1..bc0a73fc7ab41 100644 +--- a/sound/soc/codecs/tas2764.c ++++ b/sound/soc/codecs/tas2764.c +@@ -634,6 +634,7 @@ static const struct reg_default tas2764_reg_defaults[] = { + { TAS2764_TDM_CFG2, 0x0a }, + { TAS2764_TDM_CFG3, 0x10 }, + { TAS2764_TDM_CFG5, 0x42 }, ++ { TAS2764_INT_CLK_CFG, 0x19 }, + }; + + static const struct regmap_range_cfg tas2764_regmap_ranges[] = { +-- +2.39.5 + diff --git a/queue-6.14/asoc-tas2764-mark-sw_reset-as-volatile.patch b/queue-6.14/asoc-tas2764-mark-sw_reset-as-volatile.patch new file mode 100644 index 0000000000..f18e628d3a --- /dev/null +++ b/queue-6.14/asoc-tas2764-mark-sw_reset-as-volatile.patch @@ -0,0 +1,35 @@ +From 11963ee4b7329839024ec2c677d2193c1e6e4058 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 8 Feb 2025 01:03:26 +0000 +Subject: ASoC: tas2764: Mark SW_RESET as volatile + +From: Hector Martin + +[ Upstream commit f37f1748564ac51d32f7588bd7bfc99913ccab8e ] + +Since the bit is self-clearing. + +Signed-off-by: Hector Martin +Signed-off-by: Mark Brown +Link: https://patch.msgid.link/20250208-asoc-tas2764-v1-3-dbab892a69b5@kernel.org +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/codecs/tas2764.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/sound/soc/codecs/tas2764.c b/sound/soc/codecs/tas2764.c +index bc0a73fc7ab41..31f94c8cf2844 100644 +--- a/sound/soc/codecs/tas2764.c ++++ b/sound/soc/codecs/tas2764.c +@@ -652,6 +652,7 @@ static const struct regmap_range_cfg tas2764_regmap_ranges[] = { + static bool tas2764_volatile_register(struct device *dev, unsigned int reg) + { + switch (reg) { ++ case TAS2764_SW_RST: + case TAS2764_INT_LTCH0 ... TAS2764_INT_LTCH4: + case TAS2764_INT_CLK_CFG: + return true; +-- +2.39.5 + diff --git a/queue-6.14/asoc-tas2764-power-up-down-amp-on-mute-ops.patch b/queue-6.14/asoc-tas2764-power-up-down-amp-on-mute-ops.patch new file mode 100644 index 0000000000..8812007977 --- /dev/null +++ b/queue-6.14/asoc-tas2764-power-up-down-amp-on-mute-ops.patch @@ -0,0 +1,108 @@ +From c85a7a3468d1daec003ef3fe171adcd7e4bedf18 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 8 Feb 2025 01:03:24 +0000 +Subject: ASoC: tas2764: Power up/down amp on mute ops + +From: Hector Martin + +[ Upstream commit 1c3b5f37409682184669457a5bdf761268eafbe5 ] + +The ASoC convention is that clocks are removed after codec mute, and +power up/down is more about top level power management. For these chips, +the "mute" state still expects a TDM clock, and yanking the clock in +this state will trigger clock errors. So, do the full +shutdown<->mute<->active transition on the mute operation, so the amp is +in software shutdown by the time the clocks are removed. + +This fixes TDM clock errors when streams are stopped. + +Signed-off-by: Hector Martin +Signed-off-by: Mark Brown +Link: https://patch.msgid.link/20250208-asoc-tas2764-v1-1-dbab892a69b5@kernel.org +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/codecs/tas2764.c | 51 ++++++++++++++++---------------------- + 1 file changed, 21 insertions(+), 30 deletions(-) + +diff --git a/sound/soc/codecs/tas2764.c b/sound/soc/codecs/tas2764.c +index 31f94c8cf2844..39a7d39536fe6 100644 +--- a/sound/soc/codecs/tas2764.c ++++ b/sound/soc/codecs/tas2764.c +@@ -180,33 +180,6 @@ static SOC_ENUM_SINGLE_DECL( + static const struct snd_kcontrol_new tas2764_asi1_mux = + SOC_DAPM_ENUM("ASI1 Source", tas2764_ASI1_src_enum); + +-static int tas2764_dac_event(struct snd_soc_dapm_widget *w, +- struct snd_kcontrol *kcontrol, int event) +-{ +- struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); +- struct tas2764_priv *tas2764 = snd_soc_component_get_drvdata(component); +- int ret; +- +- switch (event) { +- case SND_SOC_DAPM_POST_PMU: +- tas2764->dac_powered = true; +- ret = tas2764_update_pwr_ctrl(tas2764); +- break; +- case SND_SOC_DAPM_PRE_PMD: +- tas2764->dac_powered = false; +- ret = tas2764_update_pwr_ctrl(tas2764); +- break; +- default: +- dev_err(tas2764->dev, "Unsupported event\n"); +- return -EINVAL; +- } +- +- if (ret < 0) +- return ret; +- +- return 0; +-} +- + static const struct snd_kcontrol_new isense_switch = + SOC_DAPM_SINGLE("Switch", TAS2764_PWR_CTRL, TAS2764_ISENSE_POWER_EN, 1, 1); + static const struct snd_kcontrol_new vsense_switch = +@@ -219,8 +192,7 @@ static const struct snd_soc_dapm_widget tas2764_dapm_widgets[] = { + 1, &isense_switch), + SND_SOC_DAPM_SWITCH("VSENSE", TAS2764_PWR_CTRL, TAS2764_VSENSE_POWER_EN, + 1, &vsense_switch), +- SND_SOC_DAPM_DAC_E("DAC", NULL, SND_SOC_NOPM, 0, 0, tas2764_dac_event, +- SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), ++ SND_SOC_DAPM_DAC("DAC", NULL, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_OUTPUT("OUT"), + SND_SOC_DAPM_SIGGEN("VMON"), + SND_SOC_DAPM_SIGGEN("IMON") +@@ -241,9 +213,28 @@ static int tas2764_mute(struct snd_soc_dai *dai, int mute, int direction) + { + struct tas2764_priv *tas2764 = + snd_soc_component_get_drvdata(dai->component); ++ int ret; ++ ++ if (!mute) { ++ tas2764->dac_powered = true; ++ ret = tas2764_update_pwr_ctrl(tas2764); ++ if (ret) ++ return ret; ++ } + + tas2764->unmuted = !mute; +- return tas2764_update_pwr_ctrl(tas2764); ++ ret = tas2764_update_pwr_ctrl(tas2764); ++ if (ret) ++ return ret; ++ ++ if (mute) { ++ tas2764->dac_powered = false; ++ ret = tas2764_update_pwr_ctrl(tas2764); ++ if (ret) ++ return ret; ++ } ++ ++ return 0; + } + + static int tas2764_set_bitwidth(struct tas2764_priv *tas2764, int bitwidth) +-- +2.39.5 + diff --git a/queue-6.14/auxdisplay-charlcd-partially-revert-move-hwidth-and-.patch b/queue-6.14/auxdisplay-charlcd-partially-revert-move-hwidth-and-.patch new file mode 100644 index 0000000000..7e9c4bbdc8 --- /dev/null +++ b/queue-6.14/auxdisplay-charlcd-partially-revert-move-hwidth-and-.patch @@ -0,0 +1,117 @@ +From e1fa420a06af2750033c554ef077af277f7a5fb6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 24 Feb 2025 19:27:38 +0200 +Subject: auxdisplay: charlcd: Partially revert "Move hwidth and bwidth to + struct hd44780_common" + +From: Andy Shevchenko + +[ Upstream commit 09965a142078080fe7807bab0f6f1890cb5987a4 ] + +Commit 2545c1c948a6 ("auxdisplay: Move hwidth and bwidth to struct +hd44780_common") makes charlcd_alloc() argument-less effectively dropping +the single allocation for the struct charlcd_priv object along with +the driver specific one. Restore that behaviour here. + +Signed-off-by: Andy Shevchenko +Reviewed-by: Geert Uytterhoeven +Signed-off-by: Sasha Levin +--- + drivers/auxdisplay/charlcd.c | 5 +++-- + drivers/auxdisplay/charlcd.h | 5 +++-- + drivers/auxdisplay/hd44780.c | 2 +- + drivers/auxdisplay/lcd2s.c | 2 +- + drivers/auxdisplay/panel.c | 2 +- + 5 files changed, 9 insertions(+), 7 deletions(-) + +diff --git a/drivers/auxdisplay/charlcd.c b/drivers/auxdisplay/charlcd.c +index 19b619376d48b..09020bb8ad15f 100644 +--- a/drivers/auxdisplay/charlcd.c ++++ b/drivers/auxdisplay/charlcd.c +@@ -595,18 +595,19 @@ static int charlcd_init(struct charlcd *lcd) + return 0; + } + +-struct charlcd *charlcd_alloc(void) ++struct charlcd *charlcd_alloc(unsigned int drvdata_size) + { + struct charlcd_priv *priv; + struct charlcd *lcd; + +- priv = kzalloc(sizeof(*priv), GFP_KERNEL); ++ priv = kzalloc(sizeof(*priv) + drvdata_size, GFP_KERNEL); + if (!priv) + return NULL; + + priv->esc_seq.len = -1; + + lcd = &priv->lcd; ++ lcd->drvdata = priv->drvdata; + + return lcd; + } +diff --git a/drivers/auxdisplay/charlcd.h b/drivers/auxdisplay/charlcd.h +index 4d4287209d04c..d10b89740bcae 100644 +--- a/drivers/auxdisplay/charlcd.h ++++ b/drivers/auxdisplay/charlcd.h +@@ -51,7 +51,7 @@ struct charlcd { + unsigned long y; + } addr; + +- void *drvdata; ++ void *drvdata; /* Set by charlcd_alloc() */ + }; + + /** +@@ -95,7 +95,8 @@ struct charlcd_ops { + }; + + void charlcd_backlight(struct charlcd *lcd, enum charlcd_onoff on); +-struct charlcd *charlcd_alloc(void); ++ ++struct charlcd *charlcd_alloc(unsigned int drvdata_size); + void charlcd_free(struct charlcd *lcd); + + int charlcd_register(struct charlcd *lcd); +diff --git a/drivers/auxdisplay/hd44780.c b/drivers/auxdisplay/hd44780.c +index 9d0ae9c02e9ba..1d67fe3243412 100644 +--- a/drivers/auxdisplay/hd44780.c ++++ b/drivers/auxdisplay/hd44780.c +@@ -226,7 +226,7 @@ static int hd44780_probe(struct platform_device *pdev) + if (!hdc) + return -ENOMEM; + +- lcd = charlcd_alloc(); ++ lcd = charlcd_alloc(0); + if (!lcd) + goto fail1; + +diff --git a/drivers/auxdisplay/lcd2s.c b/drivers/auxdisplay/lcd2s.c +index a28daa4ffbf75..c71ebb925971b 100644 +--- a/drivers/auxdisplay/lcd2s.c ++++ b/drivers/auxdisplay/lcd2s.c +@@ -307,7 +307,7 @@ static int lcd2s_i2c_probe(struct i2c_client *i2c) + if (err < 0) + return err; + +- lcd = charlcd_alloc(); ++ lcd = charlcd_alloc(0); + if (!lcd) + return -ENOMEM; + +diff --git a/drivers/auxdisplay/panel.c b/drivers/auxdisplay/panel.c +index 6dc8798d01f98..4da142692d55f 100644 +--- a/drivers/auxdisplay/panel.c ++++ b/drivers/auxdisplay/panel.c +@@ -835,7 +835,7 @@ static void lcd_init(void) + if (!hdc) + return; + +- charlcd = charlcd_alloc(); ++ charlcd = charlcd_alloc(0); + if (!charlcd) { + kfree(hdc); + return; +-- +2.39.5 + diff --git a/queue-6.14/badblocks-fix-a-nonsense-warn_on-which-checks-whethe.patch b/queue-6.14/badblocks-fix-a-nonsense-warn_on-which-checks-whethe.patch new file mode 100644 index 0000000000..b7016470c2 --- /dev/null +++ b/queue-6.14/badblocks-fix-a-nonsense-warn_on-which-checks-whethe.patch @@ -0,0 +1,55 @@ +From 571c55ef7955f3fe0ad50b77cc3f67a4eed4dd23 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 9 Mar 2025 12:05:56 -0400 +Subject: badblocks: Fix a nonsense WARN_ON() which checks whether a u64 + variable < 0 + +From: Coly Li + +[ Upstream commit 7e76336e14de9a2b67af96012ddd46c5676cf340 ] + +In _badblocks_check(), there are lines of code like this, +1246 sectors -= len; +[snipped] +1251 WARN_ON(sectors < 0); + +The WARN_ON() at line 1257 doesn't make sense because sectors is +unsigned long long type and never to be <0. + +Fix it by checking directly checking whether sectors is less than len. + +Reported-by: Dan Carpenter +Signed-off-by: Coly Li +Reviewed-by: Yu Kuai +Link: https://lore.kernel.org/r/20250309160556.42854-1-colyli@kernel.org +Signed-off-by: Jens Axboe +Signed-off-by: Sasha Levin +--- + block/badblocks.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/block/badblocks.c b/block/badblocks.c +index dc147c0179612..23acdf7c6f363 100644 +--- a/block/badblocks.c ++++ b/block/badblocks.c +@@ -1246,14 +1246,15 @@ static int _badblocks_check(struct badblocks *bb, sector_t s, sector_t sectors, + len = sectors; + + update_sectors: ++ /* This situation should never happen */ ++ WARN_ON(sectors < len); ++ + s += len; + sectors -= len; + + if (sectors > 0) + goto re_check; + +- WARN_ON(sectors < 0); +- + if (unacked_badblocks > 0) + rv = -1; + else if (acked_badblocks > 0) +-- +2.39.5 + diff --git a/queue-6.14/blk-cgroup-improve-policy-registration-error-handlin.patch b/queue-6.14/blk-cgroup-improve-policy-registration-error-handlin.patch new file mode 100644 index 0000000000..b55b6d1af1 --- /dev/null +++ b/queue-6.14/blk-cgroup-improve-policy-registration-error-handlin.patch @@ -0,0 +1,94 @@ +From c3c5ac9594d9a9d26dd88ea5079b022abca055c9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Mar 2025 10:29:24 +0800 +Subject: blk-cgroup: improve policy registration error handling +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Chen Linxuan + +[ Upstream commit e1a0202c6bfda24002a3ae2115154fa90104c649 ] + +This patch improve the returned error code of blkcg_policy_register(). + +1. Move the validation check for cpd/pd_alloc_fn and cpd/pd_free_fn + function pairs to the start of blkcg_policy_register(). This ensures + we immediately return -EINVAL if the function pairs are not correctly + provided, rather than returning -ENOSPC after locking and unlocking + mutexes unnecessarily. + + Those locks should not contention any problems, as error of policy + registration is a super cold path. + +2. Return -ENOMEM when cpd_alloc_fn() failed. + +Co-authored-by: Wen Tao +Signed-off-by: Wen Tao +Signed-off-by: Chen Linxuan +Reviewed-by: Michal Koutný +Acked-by: Tejun Heo +Reviewed-by: Yu Kuai +Link: https://lore.kernel.org/r/3E333A73B6B6DFC0+20250317022924.150907-1-chenlinxuan@uniontech.com +Signed-off-by: Jens Axboe +Signed-off-by: Sasha Levin +--- + block/blk-cgroup.c | 22 ++++++++++++---------- + 1 file changed, 12 insertions(+), 10 deletions(-) + +diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c +index c94efae5bcfaf..8b07015db819a 100644 +--- a/block/blk-cgroup.c ++++ b/block/blk-cgroup.c +@@ -1727,27 +1727,27 @@ int blkcg_policy_register(struct blkcg_policy *pol) + struct blkcg *blkcg; + int i, ret; + ++ /* ++ * Make sure cpd/pd_alloc_fn and cpd/pd_free_fn in pairs, and policy ++ * without pd_alloc_fn/pd_free_fn can't be activated. ++ */ ++ if ((!pol->cpd_alloc_fn ^ !pol->cpd_free_fn) || ++ (!pol->pd_alloc_fn ^ !pol->pd_free_fn)) ++ return -EINVAL; ++ + mutex_lock(&blkcg_pol_register_mutex); + mutex_lock(&blkcg_pol_mutex); + + /* find an empty slot */ +- ret = -ENOSPC; + for (i = 0; i < BLKCG_MAX_POLS; i++) + if (!blkcg_policy[i]) + break; + if (i >= BLKCG_MAX_POLS) { + pr_warn("blkcg_policy_register: BLKCG_MAX_POLS too small\n"); ++ ret = -ENOSPC; + goto err_unlock; + } + +- /* +- * Make sure cpd/pd_alloc_fn and cpd/pd_free_fn in pairs, and policy +- * without pd_alloc_fn/pd_free_fn can't be activated. +- */ +- if ((!pol->cpd_alloc_fn ^ !pol->cpd_free_fn) || +- (!pol->pd_alloc_fn ^ !pol->pd_free_fn)) +- goto err_unlock; +- + /* register @pol */ + pol->plid = i; + blkcg_policy[pol->plid] = pol; +@@ -1758,8 +1758,10 @@ int blkcg_policy_register(struct blkcg_policy *pol) + struct blkcg_policy_data *cpd; + + cpd = pol->cpd_alloc_fn(GFP_KERNEL); +- if (!cpd) ++ if (!cpd) { ++ ret = -ENOMEM; + goto err_free_cpds; ++ } + + blkcg->cpd[pol->plid] = cpd; + cpd->blkcg = blkcg; +-- +2.39.5 + diff --git a/queue-6.14/blk-throttle-don-t-take-carryover-for-prioritized-pr.patch b/queue-6.14/blk-throttle-don-t-take-carryover-for-prioritized-pr.patch new file mode 100644 index 0000000000..a817ddcf4d --- /dev/null +++ b/queue-6.14/blk-throttle-don-t-take-carryover-for-prioritized-pr.patch @@ -0,0 +1,64 @@ +From 7c9b5f8a6247f0a7b9425df9f82267b3c3ab9d1d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Mar 2025 12:31:20 +0800 +Subject: blk-throttle: don't take carryover for prioritized processing of + metadata + +From: Ming Lei + +[ Upstream commit a9fc8868b350cbf4ff730a4ea9651319cc669516 ] + +Commit 29390bb5661d ("blk-throttle: support prioritized processing of metadata") +takes bytes/ios carryover for prioritized processing of metadata. Turns out +we can support it by charging it directly without trimming slice, and the +result is same with carryover. + +Cc: Tejun Heo +Cc: Josef Bacik +Cc: Yu Kuai +Signed-off-by: Ming Lei +Acked-by: Tejun Heo +Link: https://lore.kernel.org/r/20250305043123.3938491-3-ming.lei@redhat.com +Signed-off-by: Jens Axboe +Signed-off-by: Sasha Levin +--- + block/blk-throttle.c | 15 +++++---------- + 1 file changed, 5 insertions(+), 10 deletions(-) + +diff --git a/block/blk-throttle.c b/block/blk-throttle.c +index a52f0d6b40ad4..762fbbd388c87 100644 +--- a/block/blk-throttle.c ++++ b/block/blk-throttle.c +@@ -1623,13 +1623,6 @@ static bool tg_within_limit(struct throtl_grp *tg, struct bio *bio, bool rw) + return tg_may_dispatch(tg, bio, NULL); + } + +-static void tg_dispatch_in_debt(struct throtl_grp *tg, struct bio *bio, bool rw) +-{ +- if (!bio_flagged(bio, BIO_BPS_THROTTLED)) +- tg->carryover_bytes[rw] -= throtl_bio_data_size(bio); +- tg->carryover_ios[rw]--; +-} +- + bool __blk_throtl_bio(struct bio *bio) + { + struct request_queue *q = bdev_get_queue(bio->bi_bdev); +@@ -1666,10 +1659,12 @@ bool __blk_throtl_bio(struct bio *bio) + /* + * IOs which may cause priority inversions are + * dispatched directly, even if they're over limit. +- * Debts are handled by carryover_bytes/ios while +- * calculating wait time. ++ * ++ * Charge and dispatch directly, and our throttle ++ * control algorithm is adaptive, and extra IO bytes ++ * will be throttled for paying the debt + */ +- tg_dispatch_in_debt(tg, bio, rw); ++ throtl_charge_bio(tg, bio); + } else { + /* if above limits, break to queue */ + break; +-- +2.39.5 + diff --git a/queue-6.14/block-acquire-q-limits_lock-while-reading-sysfs-attr.patch b/queue-6.14/block-acquire-q-limits_lock-while-reading-sysfs-attr.patch new file mode 100644 index 0000000000..9ff8d0c26b --- /dev/null +++ b/queue-6.14/block-acquire-q-limits_lock-while-reading-sysfs-attr.patch @@ -0,0 +1,253 @@ +From 9f167debab5dc7e5a53132b2ecb62ab6b3928361 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 4 Mar 2025 15:52:30 +0530 +Subject: block: acquire q->limits_lock while reading sysfs attributes + +From: Nilay Shroff + +[ Upstream commit 6e51a1279cd60cb93e3379ff140d8fa6c39ecf20 ] + +There're few sysfs attributes(RW) whose store method is protected +with q->limits_lock, however the corresponding show method of these +attributes run holding q->sysfs_lock and that doesn't make sense +as ideally the show method of these attributes should also run +holding q->limits_lock instead of q->sysfs_lock. Hence update the +show method of these sysfs attributes so that reading of these +attributes acquire q->limits_lock instead of q->sysfs_lock. + +Similarly, there're few sysfs attributes(RO) whose show method is +currently protected with q->sysfs_lock however updates to these +attributes could occur using atomic limit update APIs such as queue_ +limits_start_update() and queue_limits_commit_update() which run +holding q->limits_lock. So that means that reading these attributes +holding q->sysfs_lock doesn't make sense. Hence update the show method +of these sysfs attributes(RO) such that they run with holding q-> +limits_lock instead of q->sysfs_lock. + +We have defined a new macro QUEUE_LIM_RO_ENTRY() which uses new ->show_ +limit() method and it runs holding q->limits_lock. All existing sysfs +attributes(RO) which needs protection using q->limits_lock while +reading have been now updated to use this new macro for initialization. + +Also, the existing QUEUE_LIM_RW_ENTRY() is updated to use new ->show_ +limit() method for reading attributes instead of existing ->show() +method. As ->show_limit() runs holding q->limits_lock, the existing +sysfs attributes(RW) requiring protection are now inherently protected +using q->limits_lock instead of q->sysfs_lock. + +Reviewed-by: Christoph Hellwig +Reviewed-by: Hannes Reinecke +Reviewed-by: Ming Lei +Signed-off-by: Nilay Shroff +Link: https://lore.kernel.org/r/20250304102551.2533767-2-nilay@linux.ibm.com +Signed-off-by: Jens Axboe +Signed-off-by: Sasha Levin +--- + block/blk-sysfs.c | 102 +++++++++++++++++++++++++++++----------------- + 1 file changed, 65 insertions(+), 37 deletions(-) + +diff --git a/block/blk-sysfs.c b/block/blk-sysfs.c +index 7802186849074..dc4037e27e36e 100644 +--- a/block/blk-sysfs.c ++++ b/block/blk-sysfs.c +@@ -23,9 +23,12 @@ + struct queue_sysfs_entry { + struct attribute attr; + ssize_t (*show)(struct gendisk *disk, char *page); ++ ssize_t (*show_limit)(struct gendisk *disk, char *page); ++ + ssize_t (*store)(struct gendisk *disk, const char *page, size_t count); + int (*store_limit)(struct gendisk *disk, const char *page, + size_t count, struct queue_limits *lim); ++ + void (*load_module)(struct gendisk *disk, const char *page, size_t count); + }; + +@@ -412,10 +415,16 @@ static struct queue_sysfs_entry _prefix##_entry = { \ + .store = _prefix##_store, \ + }; + ++#define QUEUE_LIM_RO_ENTRY(_prefix, _name) \ ++static struct queue_sysfs_entry _prefix##_entry = { \ ++ .attr = { .name = _name, .mode = 0444 }, \ ++ .show_limit = _prefix##_show, \ ++} ++ + #define QUEUE_LIM_RW_ENTRY(_prefix, _name) \ + static struct queue_sysfs_entry _prefix##_entry = { \ + .attr = { .name = _name, .mode = 0644 }, \ +- .show = _prefix##_show, \ ++ .show_limit = _prefix##_show, \ + .store_limit = _prefix##_store, \ + } + +@@ -430,39 +439,39 @@ static struct queue_sysfs_entry _prefix##_entry = { \ + QUEUE_RW_ENTRY(queue_requests, "nr_requests"); + QUEUE_RW_ENTRY(queue_ra, "read_ahead_kb"); + QUEUE_LIM_RW_ENTRY(queue_max_sectors, "max_sectors_kb"); +-QUEUE_RO_ENTRY(queue_max_hw_sectors, "max_hw_sectors_kb"); +-QUEUE_RO_ENTRY(queue_max_segments, "max_segments"); +-QUEUE_RO_ENTRY(queue_max_integrity_segments, "max_integrity_segments"); +-QUEUE_RO_ENTRY(queue_max_segment_size, "max_segment_size"); ++QUEUE_LIM_RO_ENTRY(queue_max_hw_sectors, "max_hw_sectors_kb"); ++QUEUE_LIM_RO_ENTRY(queue_max_segments, "max_segments"); ++QUEUE_LIM_RO_ENTRY(queue_max_integrity_segments, "max_integrity_segments"); ++QUEUE_LIM_RO_ENTRY(queue_max_segment_size, "max_segment_size"); + QUEUE_RW_LOAD_MODULE_ENTRY(elv_iosched, "scheduler"); + +-QUEUE_RO_ENTRY(queue_logical_block_size, "logical_block_size"); +-QUEUE_RO_ENTRY(queue_physical_block_size, "physical_block_size"); +-QUEUE_RO_ENTRY(queue_chunk_sectors, "chunk_sectors"); +-QUEUE_RO_ENTRY(queue_io_min, "minimum_io_size"); +-QUEUE_RO_ENTRY(queue_io_opt, "optimal_io_size"); ++QUEUE_LIM_RO_ENTRY(queue_logical_block_size, "logical_block_size"); ++QUEUE_LIM_RO_ENTRY(queue_physical_block_size, "physical_block_size"); ++QUEUE_LIM_RO_ENTRY(queue_chunk_sectors, "chunk_sectors"); ++QUEUE_LIM_RO_ENTRY(queue_io_min, "minimum_io_size"); ++QUEUE_LIM_RO_ENTRY(queue_io_opt, "optimal_io_size"); + +-QUEUE_RO_ENTRY(queue_max_discard_segments, "max_discard_segments"); +-QUEUE_RO_ENTRY(queue_discard_granularity, "discard_granularity"); +-QUEUE_RO_ENTRY(queue_max_hw_discard_sectors, "discard_max_hw_bytes"); ++QUEUE_LIM_RO_ENTRY(queue_max_discard_segments, "max_discard_segments"); ++QUEUE_LIM_RO_ENTRY(queue_discard_granularity, "discard_granularity"); ++QUEUE_LIM_RO_ENTRY(queue_max_hw_discard_sectors, "discard_max_hw_bytes"); + QUEUE_LIM_RW_ENTRY(queue_max_discard_sectors, "discard_max_bytes"); + QUEUE_RO_ENTRY(queue_discard_zeroes_data, "discard_zeroes_data"); + +-QUEUE_RO_ENTRY(queue_atomic_write_max_sectors, "atomic_write_max_bytes"); +-QUEUE_RO_ENTRY(queue_atomic_write_boundary_sectors, ++QUEUE_LIM_RO_ENTRY(queue_atomic_write_max_sectors, "atomic_write_max_bytes"); ++QUEUE_LIM_RO_ENTRY(queue_atomic_write_boundary_sectors, + "atomic_write_boundary_bytes"); +-QUEUE_RO_ENTRY(queue_atomic_write_unit_max, "atomic_write_unit_max_bytes"); +-QUEUE_RO_ENTRY(queue_atomic_write_unit_min, "atomic_write_unit_min_bytes"); ++QUEUE_LIM_RO_ENTRY(queue_atomic_write_unit_max, "atomic_write_unit_max_bytes"); ++QUEUE_LIM_RO_ENTRY(queue_atomic_write_unit_min, "atomic_write_unit_min_bytes"); + + QUEUE_RO_ENTRY(queue_write_same_max, "write_same_max_bytes"); +-QUEUE_RO_ENTRY(queue_max_write_zeroes_sectors, "write_zeroes_max_bytes"); +-QUEUE_RO_ENTRY(queue_max_zone_append_sectors, "zone_append_max_bytes"); +-QUEUE_RO_ENTRY(queue_zone_write_granularity, "zone_write_granularity"); ++QUEUE_LIM_RO_ENTRY(queue_max_write_zeroes_sectors, "write_zeroes_max_bytes"); ++QUEUE_LIM_RO_ENTRY(queue_max_zone_append_sectors, "zone_append_max_bytes"); ++QUEUE_LIM_RO_ENTRY(queue_zone_write_granularity, "zone_write_granularity"); + +-QUEUE_RO_ENTRY(queue_zoned, "zoned"); ++QUEUE_LIM_RO_ENTRY(queue_zoned, "zoned"); + QUEUE_RO_ENTRY(queue_nr_zones, "nr_zones"); +-QUEUE_RO_ENTRY(queue_max_open_zones, "max_open_zones"); +-QUEUE_RO_ENTRY(queue_max_active_zones, "max_active_zones"); ++QUEUE_LIM_RO_ENTRY(queue_max_open_zones, "max_open_zones"); ++QUEUE_LIM_RO_ENTRY(queue_max_active_zones, "max_active_zones"); + + QUEUE_RW_ENTRY(queue_nomerges, "nomerges"); + QUEUE_LIM_RW_ENTRY(queue_iostats_passthrough, "iostats_passthrough"); +@@ -470,16 +479,16 @@ QUEUE_RW_ENTRY(queue_rq_affinity, "rq_affinity"); + QUEUE_RW_ENTRY(queue_poll, "io_poll"); + QUEUE_RW_ENTRY(queue_poll_delay, "io_poll_delay"); + QUEUE_LIM_RW_ENTRY(queue_wc, "write_cache"); +-QUEUE_RO_ENTRY(queue_fua, "fua"); +-QUEUE_RO_ENTRY(queue_dax, "dax"); ++QUEUE_LIM_RO_ENTRY(queue_fua, "fua"); ++QUEUE_LIM_RO_ENTRY(queue_dax, "dax"); + QUEUE_RW_ENTRY(queue_io_timeout, "io_timeout"); +-QUEUE_RO_ENTRY(queue_virt_boundary_mask, "virt_boundary_mask"); +-QUEUE_RO_ENTRY(queue_dma_alignment, "dma_alignment"); ++QUEUE_LIM_RO_ENTRY(queue_virt_boundary_mask, "virt_boundary_mask"); ++QUEUE_LIM_RO_ENTRY(queue_dma_alignment, "dma_alignment"); + + /* legacy alias for logical_block_size: */ + static struct queue_sysfs_entry queue_hw_sector_size_entry = { +- .attr = {.name = "hw_sector_size", .mode = 0444 }, +- .show = queue_logical_block_size_show, ++ .attr = {.name = "hw_sector_size", .mode = 0444 }, ++ .show_limit = queue_logical_block_size_show, + }; + + QUEUE_LIM_RW_ENTRY(queue_rotational, "rotational"); +@@ -561,7 +570,9 @@ QUEUE_RW_ENTRY(queue_wb_lat, "wbt_lat_usec"); + + /* Common attributes for bio-based and request-based queues. */ + static struct attribute *queue_attrs[] = { +- &queue_ra_entry.attr, ++ /* ++ * Attributes which are protected with q->limits_lock. ++ */ + &queue_max_hw_sectors_entry.attr, + &queue_max_sectors_entry.attr, + &queue_max_segments_entry.attr, +@@ -577,37 +588,46 @@ static struct attribute *queue_attrs[] = { + &queue_discard_granularity_entry.attr, + &queue_max_discard_sectors_entry.attr, + &queue_max_hw_discard_sectors_entry.attr, +- &queue_discard_zeroes_data_entry.attr, + &queue_atomic_write_max_sectors_entry.attr, + &queue_atomic_write_boundary_sectors_entry.attr, + &queue_atomic_write_unit_min_entry.attr, + &queue_atomic_write_unit_max_entry.attr, +- &queue_write_same_max_entry.attr, + &queue_max_write_zeroes_sectors_entry.attr, + &queue_max_zone_append_sectors_entry.attr, + &queue_zone_write_granularity_entry.attr, + &queue_rotational_entry.attr, + &queue_zoned_entry.attr, +- &queue_nr_zones_entry.attr, + &queue_max_open_zones_entry.attr, + &queue_max_active_zones_entry.attr, +- &queue_nomerges_entry.attr, + &queue_iostats_passthrough_entry.attr, + &queue_iostats_entry.attr, + &queue_stable_writes_entry.attr, + &queue_add_random_entry.attr, +- &queue_poll_entry.attr, + &queue_wc_entry.attr, + &queue_fua_entry.attr, + &queue_dax_entry.attr, +- &queue_poll_delay_entry.attr, + &queue_virt_boundary_mask_entry.attr, + &queue_dma_alignment_entry.attr, ++ ++ /* ++ * Attributes which are protected with q->sysfs_lock. ++ */ ++ &queue_ra_entry.attr, ++ &queue_discard_zeroes_data_entry.attr, ++ &queue_write_same_max_entry.attr, ++ &queue_nr_zones_entry.attr, ++ &queue_nomerges_entry.attr, ++ &queue_poll_entry.attr, ++ &queue_poll_delay_entry.attr, ++ + NULL, + }; + + /* Request-based queue attributes that are not relevant for bio-based queues. */ + static struct attribute *blk_mq_queue_attrs[] = { ++ /* ++ * Attributes which are protected with q->sysfs_lock. ++ */ + &queue_requests_entry.attr, + &elv_iosched_entry.attr, + &queue_rq_affinity_entry.attr, +@@ -666,8 +686,16 @@ queue_attr_show(struct kobject *kobj, struct attribute *attr, char *page) + struct gendisk *disk = container_of(kobj, struct gendisk, queue_kobj); + ssize_t res; + +- if (!entry->show) ++ if (!entry->show && !entry->show_limit) + return -EIO; ++ ++ if (entry->show_limit) { ++ mutex_lock(&disk->queue->limits_lock); ++ res = entry->show_limit(disk, page); ++ mutex_unlock(&disk->queue->limits_lock); ++ return res; ++ } ++ + mutex_lock(&disk->queue->sysfs_lock); + res = entry->show(disk, page); + mutex_unlock(&disk->queue->sysfs_lock); +-- +2.39.5 + diff --git a/queue-6.14/block-fix-race-between-set_blocksize-and-read-paths.patch b/queue-6.14/block-fix-race-between-set_blocksize-and-read-paths.patch new file mode 100644 index 0000000000..0729ffc974 --- /dev/null +++ b/queue-6.14/block-fix-race-between-set_blocksize-and-read-paths.patch @@ -0,0 +1,216 @@ +From d84b8e15b814ba4e58268921d63c2bb4a84a374a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 23 Apr 2025 12:53:42 -0700 +Subject: block: fix race between set_blocksize and read paths + +From: Darrick J. Wong + +[ Upstream commit c0e473a0d226479e8e925d5ba93f751d8df628e9 ] + +With the new large sector size support, it's now the case that +set_blocksize can change i_blksize and the folio order in a manner that +conflicts with a concurrent reader and causes a kernel crash. + +Specifically, let's say that udev-worker calls libblkid to detect the +labels on a block device. The read call can create an order-0 folio to +read the first 4096 bytes from the disk. But then udev is preempted. + +Next, someone tries to mount an 8k-sectorsize filesystem from the same +block device. The filesystem calls set_blksize, which sets i_blksize to +8192 and the minimum folio order to 1. + +Now udev resumes, still holding the order-0 folio it allocated. It then +tries to schedule a read bio and do_mpage_readahead tries to create +bufferheads for the folio. Unfortunately, blocks_per_folio == 0 because +the page size is 4096 but the blocksize is 8192 so no bufferheads are +attached and the bh walk never sets bdev. We then submit the bio with a +NULL block device and crash. + +Therefore, truncate the page cache after flushing but before updating +i_blksize. However, that's not enough -- we also need to lock out file +IO and page faults during the update. Take both the i_rwsem and the +invalidate_lock in exclusive mode for invalidations, and in shared mode +for read/write operations. + +I don't know if this is the correct fix, but xfs/259 found it. + +Signed-off-by: Darrick J. Wong +Reviewed-by: Christoph Hellwig +Reviewed-by: Luis Chamberlain +Tested-by: Shin'ichiro Kawasaki +Link: https://lore.kernel.org/r/174543795699.4139148.2086129139322431423.stgit@frogsfrogsfrogs +Signed-off-by: Jens Axboe +Signed-off-by: Sasha Levin +--- + block/bdev.c | 17 +++++++++++++++++ + block/blk-zoned.c | 5 ++++- + block/fops.c | 16 ++++++++++++++++ + block/ioctl.c | 6 ++++++ + 4 files changed, 43 insertions(+), 1 deletion(-) + +diff --git a/block/bdev.c b/block/bdev.c +index 5aebcf437f17c..74f2fe8aa1604 100644 +--- a/block/bdev.c ++++ b/block/bdev.c +@@ -167,9 +167,26 @@ int set_blocksize(struct file *file, int size) + + /* Don't change the size if it is same as current */ + if (inode->i_blkbits != blksize_bits(size)) { ++ /* ++ * Flush and truncate the pagecache before we reconfigure the ++ * mapping geometry because folio sizes are variable now. If a ++ * reader has already allocated a folio whose size is smaller ++ * than the new min_order but invokes readahead after the new ++ * min_order becomes visible, readahead will think there are ++ * "zero" blocks per folio and crash. Take the inode and ++ * invalidation locks to avoid racing with ++ * read/write/fallocate. ++ */ ++ inode_lock(inode); ++ filemap_invalidate_lock(inode->i_mapping); ++ + sync_blockdev(bdev); ++ kill_bdev(bdev); ++ + inode->i_blkbits = blksize_bits(size); + kill_bdev(bdev); ++ filemap_invalidate_unlock(inode->i_mapping); ++ inode_unlock(inode); + } + return 0; + } +diff --git a/block/blk-zoned.c b/block/blk-zoned.c +index 0c77244a35c92..8f15d1aa6eb89 100644 +--- a/block/blk-zoned.c ++++ b/block/blk-zoned.c +@@ -343,6 +343,7 @@ int blkdev_zone_mgmt_ioctl(struct block_device *bdev, blk_mode_t mode, + op = REQ_OP_ZONE_RESET; + + /* Invalidate the page cache, including dirty pages. */ ++ inode_lock(bdev->bd_mapping->host); + filemap_invalidate_lock(bdev->bd_mapping); + ret = blkdev_truncate_zone_range(bdev, mode, &zrange); + if (ret) +@@ -364,8 +365,10 @@ int blkdev_zone_mgmt_ioctl(struct block_device *bdev, blk_mode_t mode, + ret = blkdev_zone_mgmt(bdev, op, zrange.sector, zrange.nr_sectors); + + fail: +- if (cmd == BLKRESETZONE) ++ if (cmd == BLKRESETZONE) { + filemap_invalidate_unlock(bdev->bd_mapping); ++ inode_unlock(bdev->bd_mapping->host); ++ } + + return ret; + } +diff --git a/block/fops.c b/block/fops.c +index d23ddb2dc1138..82b672d15ea4f 100644 +--- a/block/fops.c ++++ b/block/fops.c +@@ -746,7 +746,14 @@ static ssize_t blkdev_write_iter(struct kiocb *iocb, struct iov_iter *from) + ret = direct_write_fallback(iocb, from, ret, + blkdev_buffered_write(iocb, from)); + } else { ++ /* ++ * Take i_rwsem and invalidate_lock to avoid racing with ++ * set_blocksize changing i_blkbits/folio order and punching ++ * out the pagecache. ++ */ ++ inode_lock_shared(bd_inode); + ret = blkdev_buffered_write(iocb, from); ++ inode_unlock_shared(bd_inode); + } + + if (ret > 0) +@@ -757,6 +764,7 @@ static ssize_t blkdev_write_iter(struct kiocb *iocb, struct iov_iter *from) + + static ssize_t blkdev_read_iter(struct kiocb *iocb, struct iov_iter *to) + { ++ struct inode *bd_inode = bdev_file_inode(iocb->ki_filp); + struct block_device *bdev = I_BDEV(iocb->ki_filp->f_mapping->host); + loff_t size = bdev_nr_bytes(bdev); + loff_t pos = iocb->ki_pos; +@@ -793,7 +801,13 @@ static ssize_t blkdev_read_iter(struct kiocb *iocb, struct iov_iter *to) + goto reexpand; + } + ++ /* ++ * Take i_rwsem and invalidate_lock to avoid racing with set_blocksize ++ * changing i_blkbits/folio order and punching out the pagecache. ++ */ ++ inode_lock_shared(bd_inode); + ret = filemap_read(iocb, to, ret); ++ inode_unlock_shared(bd_inode); + + reexpand: + if (unlikely(shorted)) +@@ -836,6 +850,7 @@ static long blkdev_fallocate(struct file *file, int mode, loff_t start, + if ((start | len) & (bdev_logical_block_size(bdev) - 1)) + return -EINVAL; + ++ inode_lock(inode); + filemap_invalidate_lock(inode->i_mapping); + + /* +@@ -868,6 +883,7 @@ static long blkdev_fallocate(struct file *file, int mode, loff_t start, + + fail: + filemap_invalidate_unlock(inode->i_mapping); ++ inode_unlock(inode); + return error; + } + +diff --git a/block/ioctl.c b/block/ioctl.c +index 6554b728bae6a..919066b4bb49c 100644 +--- a/block/ioctl.c ++++ b/block/ioctl.c +@@ -141,6 +141,7 @@ static int blk_ioctl_discard(struct block_device *bdev, blk_mode_t mode, + if (err) + return err; + ++ inode_lock(bdev->bd_mapping->host); + filemap_invalidate_lock(bdev->bd_mapping); + err = truncate_bdev_range(bdev, mode, start, start + len - 1); + if (err) +@@ -173,6 +174,7 @@ static int blk_ioctl_discard(struct block_device *bdev, blk_mode_t mode, + blk_finish_plug(&plug); + fail: + filemap_invalidate_unlock(bdev->bd_mapping); ++ inode_unlock(bdev->bd_mapping->host); + return err; + } + +@@ -198,12 +200,14 @@ static int blk_ioctl_secure_erase(struct block_device *bdev, blk_mode_t mode, + end > bdev_nr_bytes(bdev)) + return -EINVAL; + ++ inode_lock(bdev->bd_mapping->host); + filemap_invalidate_lock(bdev->bd_mapping); + err = truncate_bdev_range(bdev, mode, start, end - 1); + if (!err) + err = blkdev_issue_secure_erase(bdev, start >> 9, len >> 9, + GFP_KERNEL); + filemap_invalidate_unlock(bdev->bd_mapping); ++ inode_unlock(bdev->bd_mapping->host); + return err; + } + +@@ -235,6 +239,7 @@ static int blk_ioctl_zeroout(struct block_device *bdev, blk_mode_t mode, + return -EINVAL; + + /* Invalidate the page cache, including dirty pages */ ++ inode_lock(bdev->bd_mapping->host); + filemap_invalidate_lock(bdev->bd_mapping); + err = truncate_bdev_range(bdev, mode, start, end); + if (err) +@@ -245,6 +250,7 @@ static int blk_ioctl_zeroout(struct block_device *bdev, blk_mode_t mode, + + fail: + filemap_invalidate_unlock(bdev->bd_mapping); ++ inode_unlock(bdev->bd_mapping->host); + return err; + } + +-- +2.39.5 + diff --git a/queue-6.14/block-hoist-block-size-validation-code-to-a-separate.patch b/queue-6.14/block-hoist-block-size-validation-code-to-a-separate.patch new file mode 100644 index 0000000000..c336ba22c0 --- /dev/null +++ b/queue-6.14/block-hoist-block-size-validation-code-to-a-separate.patch @@ -0,0 +1,89 @@ +From b1afbe5a121c263813e0e52d8c8091166fb667e9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 23 Apr 2025 12:53:57 -0700 +Subject: block: hoist block size validation code to a separate function + +From: Darrick J. Wong + +[ Upstream commit e03463d247ddac66e71143468373df3d74a3a6bd ] + +Hoist the block size validation code to bdev_validate_blocksize so that +we can call it from filesystems that don't care about the bdev pagecache +manipulations of set_blocksize. + +Signed-off-by: Darrick J. Wong +Reviewed-by: Luis Chamberlain +Reviewed-by: Christoph Hellwig +Link: https://lore.kernel.org/r/174543795720.4139148.840349813093799165.stgit@frogsfrogsfrogs +Signed-off-by: Jens Axboe +Signed-off-by: Sasha Levin +--- + block/bdev.c | 33 +++++++++++++++++++++++++++------ + include/linux/blkdev.h | 1 + + 2 files changed, 28 insertions(+), 6 deletions(-) + +diff --git a/block/bdev.c b/block/bdev.c +index 74f2fe8aa1604..9bb7e041bd9ce 100644 +--- a/block/bdev.c ++++ b/block/bdev.c +@@ -150,18 +150,39 @@ static void set_init_blocksize(struct block_device *bdev) + BD_INODE(bdev)->i_blkbits = blksize_bits(bsize); + } + +-int set_blocksize(struct file *file, int size) ++/** ++ * bdev_validate_blocksize - check that this block size is acceptable ++ * @bdev: blockdevice to check ++ * @block_size: block size to check ++ * ++ * For block device users that do not use buffer heads or the block device ++ * page cache, make sure that this block size can be used with the device. ++ * ++ * Return: On success zero is returned, negative error code on failure. ++ */ ++int bdev_validate_blocksize(struct block_device *bdev, int block_size) + { +- struct inode *inode = file->f_mapping->host; +- struct block_device *bdev = I_BDEV(inode); +- +- if (blk_validate_block_size(size)) ++ if (blk_validate_block_size(block_size)) + return -EINVAL; + + /* Size cannot be smaller than the size supported by the device */ +- if (size < bdev_logical_block_size(bdev)) ++ if (block_size < bdev_logical_block_size(bdev)) + return -EINVAL; + ++ return 0; ++} ++EXPORT_SYMBOL_GPL(bdev_validate_blocksize); ++ ++int set_blocksize(struct file *file, int size) ++{ ++ struct inode *inode = file->f_mapping->host; ++ struct block_device *bdev = I_BDEV(inode); ++ int ret; ++ ++ ret = bdev_validate_blocksize(bdev, size); ++ if (ret) ++ return ret; ++ + if (!file->private_data) + return -EINVAL; + +diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h +index 0fec27d6b986c..844af92bea1e4 100644 +--- a/include/linux/blkdev.h ++++ b/include/linux/blkdev.h +@@ -1616,6 +1616,7 @@ static inline void bio_end_io_acct(struct bio *bio, unsigned long start_time) + return bio_end_io_acct_remapped(bio, start_time, bio->bi_bdev); + } + ++int bdev_validate_blocksize(struct block_device *bdev, int block_size); + int set_blocksize(struct file *file, int size); + + int lookup_bdev(const char *pathname, dev_t *dev); +-- +2.39.5 + diff --git a/queue-6.14/block-mark-bounce-buffering-as-incompatible-with-int.patch b/queue-6.14/block-mark-bounce-buffering-as-incompatible-with-int.patch new file mode 100644 index 0000000000..d63d588cad --- /dev/null +++ b/queue-6.14/block-mark-bounce-buffering-as-incompatible-with-int.patch @@ -0,0 +1,59 @@ +From 9c28d57bd498c81ce1ff636c2d580be1b5b0e388 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 25 Feb 2025 07:44:31 -0800 +Subject: block: mark bounce buffering as incompatible with integrity + +From: Christoph Hellwig + +[ Upstream commit 5fd0268a8806d35dcaf89139bfcda92be51b2b2f ] + +None of the few drivers still using the legacy block layer bounce +buffering support integrity metadata. Explicitly mark the features as +incompatible and stop creating the slab and mempool for integrity +buffers for the bounce bio_set. + +Signed-off-by: Christoph Hellwig +Reviewed-by: Anuj Gupta +Reviewed-by: Martin K. Petersen +Reviewed-by: Hannes Reinecke +Reviewed-by: Johannes Thumshirn +Link: https://lore.kernel.org/r/20250225154449.422989-2-hch@lst.de +Signed-off-by: Jens Axboe +Signed-off-by: Sasha Levin +--- + block/blk-settings.c | 5 +++++ + block/bounce.c | 2 -- + 2 files changed, 5 insertions(+), 2 deletions(-) + +diff --git a/block/blk-settings.c b/block/blk-settings.c +index 67b119ffa1689..c430c10c864b6 100644 +--- a/block/blk-settings.c ++++ b/block/blk-settings.c +@@ -124,6 +124,11 @@ static int blk_validate_integrity_limits(struct queue_limits *lim) + return 0; + } + ++ if (lim->features & BLK_FEAT_BOUNCE_HIGH) { ++ pr_warn("no bounce buffer support for integrity metadata\n"); ++ return -EINVAL; ++ } ++ + if (!IS_ENABLED(CONFIG_BLK_DEV_INTEGRITY)) { + pr_warn("integrity support disabled.\n"); + return -EINVAL; +diff --git a/block/bounce.c b/block/bounce.c +index 0d898cd5ec497..09a9616cf2094 100644 +--- a/block/bounce.c ++++ b/block/bounce.c +@@ -41,8 +41,6 @@ static void init_bounce_bioset(void) + + ret = bioset_init(&bounce_bio_set, BIO_POOL_SIZE, 0, BIOSET_NEED_BVECS); + BUG_ON(ret); +- if (bioset_integrity_create(&bounce_bio_set, BIO_POOL_SIZE)) +- BUG_ON(1); + + ret = bioset_init(&bounce_bio_split, BIO_POOL_SIZE, 0, 0); + BUG_ON(ret); +-- +2.39.5 + diff --git a/queue-6.14/block-only-update-request-sector-if-needed.patch b/queue-6.14/block-only-update-request-sector-if-needed.patch new file mode 100644 index 0000000000..38e7d72a1e --- /dev/null +++ b/queue-6.14/block-only-update-request-sector-if-needed.patch @@ -0,0 +1,50 @@ +From e323ee2093795c9375d9f3d5943e88c5a69f78d0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 6 May 2025 13:27:30 +0200 +Subject: block: only update request sector if needed + +From: Johannes Thumshirn + +[ Upstream commit db492e24f9b05547ba12b4783f09c9d943cf42fe ] + +In case of a ZONE APPEND write, regardless of native ZONE APPEND or the +emulation layer in the zone write plugging code, the sector the data got +written to by the device needs to be updated in the bio. + +At the moment, this is done for every native ZONE APPEND write and every +request that is flagged with 'BIO_ZONE_WRITE_PLUGGING'. But thus +superfluously updates the sector for regular writes to a zoned block +device. + +Check if a bio is a native ZONE APPEND write or if the bio is flagged as +'BIO_EMULATES_ZONE_APPEND', meaning the block layer's zone write plugging +code handles the ZONE APPEND and translates it into a regular write and +back. Only if one of these two criterion is met, update the sector in the +bio upon completion. + +Signed-off-by: Johannes Thumshirn +Reviewed-by: Christoph Hellwig +Link: https://lore.kernel.org/r/dea089581cb6b777c1cd1500b38ac0b61df4b2d1.1746530748.git.jth@kernel.org +Signed-off-by: Jens Axboe +Signed-off-by: Sasha Levin +--- + block/blk.h | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/block/blk.h b/block/blk.h +index 9dcc92c7f2b50..c14f415de5228 100644 +--- a/block/blk.h ++++ b/block/blk.h +@@ -480,7 +480,8 @@ static inline void blk_zone_update_request_bio(struct request *rq, + * the original BIO sector so that blk_zone_write_plug_bio_endio() can + * lookup the zone write plug. + */ +- if (req_op(rq) == REQ_OP_ZONE_APPEND || bio_zone_write_plugging(bio)) ++ if (req_op(rq) == REQ_OP_ZONE_APPEND || ++ bio_flagged(bio, BIO_EMULATES_ZONE_APPEND)) + bio->bi_iter.bi_sector = rq->__sector; + } + void blk_zone_write_plug_bio_endio(struct bio *bio); +-- +2.39.5 + diff --git a/queue-6.14/bluetooth-btmtksdio-prevent-enabling-interrupts-afte.patch b/queue-6.14/bluetooth-btmtksdio-prevent-enabling-interrupts-afte.patch new file mode 100644 index 0000000000..3abfccc614 --- /dev/null +++ b/queue-6.14/bluetooth-btmtksdio-prevent-enabling-interrupts-afte.patch @@ -0,0 +1,45 @@ +From f6d09e15227f761697dffbf10934f9f9d49b2a70 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 11 Mar 2025 18:25:22 -0700 +Subject: Bluetooth: btmtksdio: Prevent enabling interrupts after IRQ handler + removal + +From: Sean Wang + +[ Upstream commit 6ac4233afb9a389a7629b7f812395d1d1eca5a83 ] + +Ensure interrupts are not re-enabled when the IRQ handler has already been +removed. This prevents unexpected IRQ handler execution due to stale or +unhandled interrupts. + +Modify btmtksdio_txrx_work to check if bdev->func->irq_handler exists +before calling sdio_writel to enable interrupts. + +Co-developed-by: Pedro Tsai +Signed-off-by: Pedro Tsai +Co-developed-by: Felix Freimann +Signed-off-by: Felix Freimann +Signed-off-by: Sean Wang +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + drivers/bluetooth/btmtksdio.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/bluetooth/btmtksdio.c b/drivers/bluetooth/btmtksdio.c +index bd5464bde174f..edd5eead1e93b 100644 +--- a/drivers/bluetooth/btmtksdio.c ++++ b/drivers/bluetooth/btmtksdio.c +@@ -610,7 +610,8 @@ static void btmtksdio_txrx_work(struct work_struct *work) + } while (int_status || time_is_before_jiffies(txrx_timeout)); + + /* Enable interrupt */ +- sdio_writel(bdev->func, C_INT_EN_SET, MTK_REG_CHLPCR, NULL); ++ if (bdev->func->irq_handler) ++ sdio_writel(bdev->func, C_INT_EN_SET, MTK_REG_CHLPCR, NULL); + + sdio_release_host(bdev->func); + +-- +2.39.5 + diff --git a/queue-6.14/bluetooth-disable-sco-support-if-read_voice_setting-.patch b/queue-6.14/bluetooth-disable-sco-support-if-read_voice_setting-.patch new file mode 100644 index 0000000000..437c2a1b5d --- /dev/null +++ b/queue-6.14/bluetooth-disable-sco-support-if-read_voice_setting-.patch @@ -0,0 +1,37 @@ +From 77457a5abbcdbe18a59fc1571fb1bf7c52b8ff0a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 1 Mar 2025 03:23:00 -0300 +Subject: Bluetooth: Disable SCO support if READ_VOICE_SETTING is + unsupported/broken + +From: Pedro Nishiyama + +[ Upstream commit 14d17c78a4b1660c443bae9d38c814edea506f62 ] + +A SCO connection without the proper voice_setting can cause +the controller to lock up. + +Signed-off-by: Pedro Nishiyama +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/hci_event.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c +index ab940ec698c0f..7152a1ca56778 100644 +--- a/net/bluetooth/hci_event.c ++++ b/net/bluetooth/hci_event.c +@@ -930,6 +930,9 @@ static u8 hci_cc_read_buffer_size(struct hci_dev *hdev, void *data, + hdev->sco_pkts = 8; + } + ++ if (!read_voice_setting_capable(hdev)) ++ hdev->sco_pkts = 0; ++ + hdev->acl_cnt = hdev->acl_pkts; + hdev->sco_cnt = hdev->sco_pkts; + +-- +2.39.5 + diff --git a/queue-6.14/bnxt_en-query-fw-parameters-when-the-caps_change-bit.patch b/queue-6.14/bnxt_en-query-fw-parameters-when-the-caps_change-bit.patch new file mode 100644 index 0000000000..94de8b66d4 --- /dev/null +++ b/queue-6.14/bnxt_en-query-fw-parameters-when-the-caps_change-bit.patch @@ -0,0 +1,57 @@ +From 024d1bb7f270f3601c38a51cc2e0754e3f7fe8b3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 10 Mar 2025 11:31:26 -0700 +Subject: bnxt_en: Query FW parameters when the CAPS_CHANGE bit is set + +From: shantiprasad shettar + +[ Upstream commit a6c81e32aeacbfd530d576fa401edd506ec966ef ] + +Newer FW can set the CAPS_CHANGE flag during ifup if some capabilities +or configurations have changed. For example, the CoS queue +configurations may have changed. Support this new flag by treating it +almost like FW reset. The driver will essentially rediscover all +features and capabilities, reconfigure all backing store context memory, +reset everything to default, and reserve all resources. + +Reviewed-by: Somnath Kotur +Reviewed-by: Pavan Chebbi +Signed-off-by: shantiprasad shettar +Signed-off-by: Michael Chan +Link: https://patch.msgid.link/20250310183129.3154117-5-michael.chan@broadcom.com +Reviewed-by: Jacob Keller +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/broadcom/bnxt/bnxt.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c +index bd8b9cb05ae98..1a19c922009d1 100644 +--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c ++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c +@@ -12104,6 +12104,7 @@ static int bnxt_hwrm_if_change(struct bnxt *bp, bool up) + struct hwrm_func_drv_if_change_input *req; + bool fw_reset = !bp->irq_tbl; + bool resc_reinit = false; ++ bool caps_change = false; + int rc, retry = 0; + u32 flags = 0; + +@@ -12159,8 +12160,11 @@ static int bnxt_hwrm_if_change(struct bnxt *bp, bool up) + set_bit(BNXT_STATE_ABORT_ERR, &bp->state); + return -ENODEV; + } +- if (resc_reinit || fw_reset) { +- if (fw_reset) { ++ if (flags & FUNC_DRV_IF_CHANGE_RESP_FLAGS_CAPS_CHANGE) ++ caps_change = true; ++ ++ if (resc_reinit || fw_reset || caps_change) { ++ if (fw_reset || caps_change) { + set_bit(BNXT_STATE_FW_RESET_DET, &bp->state); + if (!test_bit(BNXT_STATE_IN_FW_RESET, &bp->state)) + bnxt_ulp_irq_stop(bp); +-- +2.39.5 + diff --git a/queue-6.14/bnxt_en-set-npar-1.2-support-when-registering-with-f.patch b/queue-6.14/bnxt_en-set-npar-1.2-support-when-registering-with-f.patch new file mode 100644 index 0000000000..9c3a899774 --- /dev/null +++ b/queue-6.14/bnxt_en-set-npar-1.2-support-when-registering-with-f.patch @@ -0,0 +1,77 @@ +From 099dd05b4c77fd0d1a6cf6c26441e9593975fa3c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 12 Feb 2025 17:12:29 -0800 +Subject: bnxt_en: Set NPAR 1.2 support when registering with firmware + +From: Michael Chan + +[ Upstream commit ebdf7fe488c512b18add66b6c26e11e4d3830213 ] + +NPAR (Network interface card partitioning)[1] 1.2 adds a transparent +VLAN tag for all packets between the NIC and the switch. Because of +that, RX VLAN acceleration cannot be supported for any additional +host configured VLANs. The driver has to acknowledge that it can +support no RX VLAN acceleration and set the NPAR 1.2 supported flag +when registering with the FW. Otherwise, the FW call will fail and +the driver will abort on these NPAR 1.2 NICs with this error: + +bnxt_en 0000:26:00.0 (unnamed net_device) (uninitialized): hwrm req_type 0x1d seq id 0xb error 0x2 + +[1] https://techdocs.broadcom.com/us/en/storage-and-ethernet-connectivity/ethernet-nic-controllers/bcm957xxx/adapters/introduction/features/network-partitioning-npar.html + +Reviewed-by: Somnath Kotur +Reviewed-by: Michal Swiatkowski +Signed-off-by: Michael Chan +Link: https://patch.msgid.link/20250213011240.1640031-2-michael.chan@broadcom.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/broadcom/bnxt/bnxt.c | 5 +++++ + drivers/net/ethernet/broadcom/bnxt/bnxt.h | 1 + + 2 files changed, 6 insertions(+) + +diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c +index 1a19c922009d1..d844cf621dd23 100644 +--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c ++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c +@@ -5589,6 +5589,8 @@ int bnxt_hwrm_func_drv_rgtr(struct bnxt *bp, unsigned long *bmap, int bmap_size, + if (bp->fw_cap & BNXT_FW_CAP_ERROR_RECOVERY) + flags |= FUNC_DRV_RGTR_REQ_FLAGS_ERROR_RECOVERY_SUPPORT | + FUNC_DRV_RGTR_REQ_FLAGS_MASTER_SUPPORT; ++ if (bp->fw_cap & BNXT_FW_CAP_NPAR_1_2) ++ flags |= FUNC_DRV_RGTR_REQ_FLAGS_NPAR_1_2_SUPPORT; + req->flags = cpu_to_le32(flags); + req->ver_maj_8b = DRV_VER_MAJ; + req->ver_min_8b = DRV_VER_MIN; +@@ -8389,6 +8391,7 @@ static int bnxt_hwrm_func_qcfg(struct bnxt *bp) + + switch (resp->port_partition_type) { + case FUNC_QCFG_RESP_PORT_PARTITION_TYPE_NPAR1_0: ++ case FUNC_QCFG_RESP_PORT_PARTITION_TYPE_NPAR1_2: + case FUNC_QCFG_RESP_PORT_PARTITION_TYPE_NPAR1_5: + case FUNC_QCFG_RESP_PORT_PARTITION_TYPE_NPAR2_0: + bp->port_partition_type = resp->port_partition_type; +@@ -9553,6 +9556,8 @@ static int __bnxt_hwrm_func_qcaps(struct bnxt *bp) + bp->fw_cap |= BNXT_FW_CAP_HOT_RESET_IF; + if (BNXT_PF(bp) && (flags_ext & FUNC_QCAPS_RESP_FLAGS_EXT_FW_LIVEPATCH_SUPPORTED)) + bp->fw_cap |= BNXT_FW_CAP_LIVEPATCH; ++ if (flags_ext & FUNC_QCAPS_RESP_FLAGS_EXT_NPAR_1_2_SUPPORTED) ++ bp->fw_cap |= BNXT_FW_CAP_NPAR_1_2; + if (BNXT_PF(bp) && (flags_ext & FUNC_QCAPS_RESP_FLAGS_EXT_DFLT_VLAN_TPID_PCP_SUPPORTED)) + bp->fw_cap |= BNXT_FW_CAP_DFLT_VLAN_TPID_PCP; + if (flags_ext & FUNC_QCAPS_RESP_FLAGS_EXT_BS_V2_SUPPORTED) +diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.h b/drivers/net/ethernet/broadcom/bnxt/bnxt.h +index d621fb621f30c..f91d9d8eacb97 100644 +--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h ++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h +@@ -2498,6 +2498,7 @@ struct bnxt { + #define BNXT_FW_CAP_CFA_RFS_RING_TBL_IDX_V3 BIT_ULL(39) + #define BNXT_FW_CAP_VNIC_RE_FLUSH BIT_ULL(40) + #define BNXT_FW_CAP_SW_MAX_RESOURCE_LIMITS BIT_ULL(41) ++ #define BNXT_FW_CAP_NPAR_1_2 BIT_ULL(42) + + u32 fw_dbg_cap; + +-- +2.39.5 + diff --git a/queue-6.14/bonding-report-duplicate-mac-address-in-all-situatio.patch b/queue-6.14/bonding-report-duplicate-mac-address-in-all-situatio.patch new file mode 100644 index 0000000000..6c91d74dd8 --- /dev/null +++ b/queue-6.14/bonding-report-duplicate-mac-address-in-all-situatio.patch @@ -0,0 +1,47 @@ +From fedd93f605a29be19d1102d7f1051bca1ba1add7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 25 Feb 2025 03:39:14 +0000 +Subject: bonding: report duplicate MAC address in all situations +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Hangbin Liu + +[ Upstream commit 28d68d396a1cd21591e8c6d74afbde33a7ea107e ] + +Normally, a bond uses the MAC address of the first added slave as the bond’s +MAC address. And the bond will set active slave’s MAC address to bond’s +address if fail_over_mac is set to none (0) or follow (2). + +When the first slave is removed, the bond will still use the removed slave’s +MAC address, which can lead to a duplicate MAC address and potentially cause +issues with the switch. To avoid confusion, let's warn the user in all +situations, including when fail_over_mac is set to 2 or not in active-backup +mode. + +Signed-off-by: Hangbin Liu +Reviewed-by: Nikolay Aleksandrov +Link: https://patch.msgid.link/20250225033914.18617-1-liuhangbin@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/bonding/bond_main.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c +index 4da5fcb7def47..203d3467dcbcd 100644 +--- a/drivers/net/bonding/bond_main.c ++++ b/drivers/net/bonding/bond_main.c +@@ -2551,7 +2551,7 @@ static int __bond_release_one(struct net_device *bond_dev, + + RCU_INIT_POINTER(bond->current_arp_slave, NULL); + +- if (!all && (!bond->params.fail_over_mac || ++ if (!all && (bond->params.fail_over_mac != BOND_FOM_ACTIVE || + BOND_MODE(bond) != BOND_MODE_ACTIVEBACKUP)) { + if (ether_addr_equal_64bits(bond_dev->dev_addr, slave->perm_hwaddr) && + bond_has_slaves(bond)) +-- +2.39.5 + diff --git a/queue-6.14/book3s64-radix-fix-compile-errors-when-config_arch_w.patch b/queue-6.14/book3s64-radix-fix-compile-errors-when-config_arch_w.patch new file mode 100644 index 0000000000..5b282fcf35 --- /dev/null +++ b/queue-6.14/book3s64-radix-fix-compile-errors-when-config_arch_w.patch @@ -0,0 +1,45 @@ +From 413945f13cd00d58eaf0c6ae4d627efaedb9fedf Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 10 Mar 2025 07:44:09 -0500 +Subject: book3s64/radix: Fix compile errors when + CONFIG_ARCH_WANT_OPTIMIZE_DAX_VMEMMAP=n + +From: Ritesh Harjani (IBM) + +[ Upstream commit 29bdc1f1c1df80868fb35bc69d1f073183adc6de ] + +Fix compile errors when CONFIG_ARCH_WANT_OPTIMIZE_DAX_VMEMMAP=n + +Signed-off-by: Ritesh Harjani (IBM) +Signed-off-by: Donet Tom +Signed-off-by: Madhavan Srinivasan +Link: https://patch.msgid.link/8231763344223c193e3452eab0ae8ea966aff466.1741609795.git.donettom@linux.ibm.com +Signed-off-by: Sasha Levin +--- + arch/powerpc/mm/book3s64/radix_pgtable.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/arch/powerpc/mm/book3s64/radix_pgtable.c b/arch/powerpc/mm/book3s64/radix_pgtable.c +index 128c011afc481..9f764bc42b8cc 100644 +--- a/arch/powerpc/mm/book3s64/radix_pgtable.c ++++ b/arch/powerpc/mm/book3s64/radix_pgtable.c +@@ -976,7 +976,7 @@ int __meminit radix__vmemmap_create_mapping(unsigned long start, + return 0; + } + +- ++#ifdef CONFIG_ARCH_WANT_OPTIMIZE_DAX_VMEMMAP + bool vmemmap_can_optimize(struct vmem_altmap *altmap, struct dev_pagemap *pgmap) + { + if (radix_enabled()) +@@ -984,6 +984,7 @@ bool vmemmap_can_optimize(struct vmem_altmap *altmap, struct dev_pagemap *pgmap) + + return false; + } ++#endif + + int __meminit vmemmap_check_pmd(pmd_t *pmdp, int node, + unsigned long addr, unsigned long next) +-- +2.39.5 + diff --git a/queue-6.14/bpf-abort-verification-if-env-cur_state-loop_entry-n.patch b/queue-6.14/bpf-abort-verification-if-env-cur_state-loop_entry-n.patch new file mode 100644 index 0000000000..7d46bd219b --- /dev/null +++ b/queue-6.14/bpf-abort-verification-if-env-cur_state-loop_entry-n.patch @@ -0,0 +1,44 @@ +From 660ea29bcc54cea0b7e664ab14d192a99a42a19f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 24 Feb 2025 16:38:38 -0800 +Subject: bpf: abort verification if env->cur_state->loop_entry != NULL + +From: Eduard Zingerman + +[ Upstream commit f3c2d243a36ef23be07bc2bce7c6a5cb6e07d9e3 ] + +In addition to warning abort verification with -EFAULT. +If env->cur_state->loop_entry != NULL something is irrecoverably +buggy. + +Fixes: bbbc02b7445e ("bpf: copy_verifier_state() should copy 'loop_entry' field") +Suggested-by: Andrii Nakryiko +Signed-off-by: Eduard Zingerman +Acked-by: Andrii Nakryiko +Link: https://lore.kernel.org/r/20250225003838.135319-1-eddyz87@gmail.com +Signed-off-by: Alexei Starovoitov +Signed-off-by: Sasha Levin +--- + kernel/bpf/verifier.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c +index 4392436ba7511..1841467c4f2e5 100644 +--- a/kernel/bpf/verifier.c ++++ b/kernel/bpf/verifier.c +@@ -19265,8 +19265,10 @@ static int do_check(struct bpf_verifier_env *env) + return err; + break; + } else { +- if (WARN_ON_ONCE(env->cur_state->loop_entry)) +- env->cur_state->loop_entry = NULL; ++ if (WARN_ON_ONCE(env->cur_state->loop_entry)) { ++ verbose(env, "verifier bug: env->cur_state->loop_entry != NULL\n"); ++ return -EFAULT; ++ } + do_print_state = true; + continue; + } +-- +2.39.5 + diff --git a/queue-6.14/bpf-allow-pre-ordering-for-bpf-cgroup-progs.patch b/queue-6.14/bpf-allow-pre-ordering-for-bpf-cgroup-progs.patch new file mode 100644 index 0000000000..c0179f8aef --- /dev/null +++ b/queue-6.14/bpf-allow-pre-ordering-for-bpf-cgroup-progs.patch @@ -0,0 +1,223 @@ +From cb7b489bf28ad53fee98de808363b2eb2bb4324e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 24 Feb 2025 15:01:16 -0800 +Subject: bpf: Allow pre-ordering for bpf cgroup progs + +From: Yonghong Song + +[ Upstream commit 4b82b181a26cff8bf7adc3a85a88d121d92edeaf ] + +Currently for bpf progs in a cgroup hierarchy, the effective prog array +is computed from bottom cgroup to upper cgroups (post-ordering). For +example, the following cgroup hierarchy + root cgroup: p1, p2 + subcgroup: p3, p4 +have BPF_F_ALLOW_MULTI for both cgroup levels. +The effective cgroup array ordering looks like + p3 p4 p1 p2 +and at run time, progs will execute based on that order. + +But in some cases, it is desirable to have root prog executes earlier than +children progs (pre-ordering). For example, + - prog p1 intends to collect original pkt dest addresses. + - prog p3 will modify original pkt dest addresses to a proxy address for + security reason. +The end result is that prog p1 gets proxy address which is not what it +wants. Putting p1 to every child cgroup is not desirable either as it +will duplicate itself in many child cgroups. And this is exactly a use case +we are encountering in Meta. + +To fix this issue, let us introduce a flag BPF_F_PREORDER. If the flag +is specified at attachment time, the prog has higher priority and the +ordering with that flag will be from top to bottom (pre-ordering). +For example, in the above example, + root cgroup: p1, p2 + subcgroup: p3, p4 +Let us say p2 and p4 are marked with BPF_F_PREORDER. The final +effective array ordering will be + p2 p4 p3 p1 + +Suggested-by: Andrii Nakryiko +Acked-by: Andrii Nakryiko +Signed-off-by: Yonghong Song +Link: https://lore.kernel.org/r/20250224230116.283071-1-yonghong.song@linux.dev +Signed-off-by: Alexei Starovoitov +Signed-off-by: Sasha Levin +--- + include/linux/bpf-cgroup.h | 1 + + include/uapi/linux/bpf.h | 1 + + kernel/bpf/cgroup.c | 33 +++++++++++++++++++++++++-------- + kernel/bpf/syscall.c | 3 ++- + tools/include/uapi/linux/bpf.h | 1 + + 5 files changed, 30 insertions(+), 9 deletions(-) + +diff --git a/include/linux/bpf-cgroup.h b/include/linux/bpf-cgroup.h +index 7fc69083e7450..9de7adb682948 100644 +--- a/include/linux/bpf-cgroup.h ++++ b/include/linux/bpf-cgroup.h +@@ -111,6 +111,7 @@ struct bpf_prog_list { + struct bpf_prog *prog; + struct bpf_cgroup_link *link; + struct bpf_cgroup_storage *storage[MAX_BPF_CGROUP_STORAGE_TYPE]; ++ u32 flags; + }; + + int cgroup_bpf_inherit(struct cgroup *cgrp); +diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h +index 2acf9b3363717..89242184a1937 100644 +--- a/include/uapi/linux/bpf.h ++++ b/include/uapi/linux/bpf.h +@@ -1207,6 +1207,7 @@ enum bpf_perf_event_type { + #define BPF_F_BEFORE (1U << 3) + #define BPF_F_AFTER (1U << 4) + #define BPF_F_ID (1U << 5) ++#define BPF_F_PREORDER (1U << 6) + #define BPF_F_LINK BPF_F_LINK /* 1 << 13 */ + + /* If BPF_F_STRICT_ALIGNMENT is used in BPF_PROG_LOAD command, the +diff --git a/kernel/bpf/cgroup.c b/kernel/bpf/cgroup.c +index 46e5db65dbc8d..84f58f3d028a3 100644 +--- a/kernel/bpf/cgroup.c ++++ b/kernel/bpf/cgroup.c +@@ -369,7 +369,7 @@ static struct bpf_prog *prog_list_prog(struct bpf_prog_list *pl) + /* count number of elements in the list. + * it's slow but the list cannot be long + */ +-static u32 prog_list_length(struct hlist_head *head) ++static u32 prog_list_length(struct hlist_head *head, int *preorder_cnt) + { + struct bpf_prog_list *pl; + u32 cnt = 0; +@@ -377,6 +377,8 @@ static u32 prog_list_length(struct hlist_head *head) + hlist_for_each_entry(pl, head, node) { + if (!prog_list_prog(pl)) + continue; ++ if (preorder_cnt && (pl->flags & BPF_F_PREORDER)) ++ (*preorder_cnt)++; + cnt++; + } + return cnt; +@@ -400,7 +402,7 @@ static bool hierarchy_allows_attach(struct cgroup *cgrp, + + if (flags & BPF_F_ALLOW_MULTI) + return true; +- cnt = prog_list_length(&p->bpf.progs[atype]); ++ cnt = prog_list_length(&p->bpf.progs[atype], NULL); + WARN_ON_ONCE(cnt > 1); + if (cnt == 1) + return !!(flags & BPF_F_ALLOW_OVERRIDE); +@@ -423,12 +425,12 @@ static int compute_effective_progs(struct cgroup *cgrp, + struct bpf_prog_array *progs; + struct bpf_prog_list *pl; + struct cgroup *p = cgrp; +- int cnt = 0; ++ int i, j, cnt = 0, preorder_cnt = 0, fstart, bstart, init_bstart; + + /* count number of effective programs by walking parents */ + do { + if (cnt == 0 || (p->bpf.flags[atype] & BPF_F_ALLOW_MULTI)) +- cnt += prog_list_length(&p->bpf.progs[atype]); ++ cnt += prog_list_length(&p->bpf.progs[atype], &preorder_cnt); + p = cgroup_parent(p); + } while (p); + +@@ -439,20 +441,34 @@ static int compute_effective_progs(struct cgroup *cgrp, + /* populate the array with effective progs */ + cnt = 0; + p = cgrp; ++ fstart = preorder_cnt; ++ bstart = preorder_cnt - 1; + do { + if (cnt > 0 && !(p->bpf.flags[atype] & BPF_F_ALLOW_MULTI)) + continue; + ++ init_bstart = bstart; + hlist_for_each_entry(pl, &p->bpf.progs[atype], node) { + if (!prog_list_prog(pl)) + continue; + +- item = &progs->items[cnt]; ++ if (pl->flags & BPF_F_PREORDER) { ++ item = &progs->items[bstart]; ++ bstart--; ++ } else { ++ item = &progs->items[fstart]; ++ fstart++; ++ } + item->prog = prog_list_prog(pl); + bpf_cgroup_storages_assign(item->cgroup_storage, + pl->storage); + cnt++; + } ++ ++ /* reverse pre-ordering progs at this cgroup level */ ++ for (i = bstart + 1, j = init_bstart; i < j; i++, j--) ++ swap(progs->items[i], progs->items[j]); ++ + } while ((p = cgroup_parent(p))); + + *array = progs; +@@ -663,7 +679,7 @@ static int __cgroup_bpf_attach(struct cgroup *cgrp, + */ + return -EPERM; + +- if (prog_list_length(progs) >= BPF_CGROUP_MAX_PROGS) ++ if (prog_list_length(progs, NULL) >= BPF_CGROUP_MAX_PROGS) + return -E2BIG; + + pl = find_attach_entry(progs, prog, link, replace_prog, +@@ -698,6 +714,7 @@ static int __cgroup_bpf_attach(struct cgroup *cgrp, + + pl->prog = prog; + pl->link = link; ++ pl->flags = flags; + bpf_cgroup_storages_assign(pl->storage, storage); + cgrp->bpf.flags[atype] = saved_flags; + +@@ -1073,7 +1090,7 @@ static int __cgroup_bpf_query(struct cgroup *cgrp, const union bpf_attr *attr, + lockdep_is_held(&cgroup_mutex)); + total_cnt += bpf_prog_array_length(effective); + } else { +- total_cnt += prog_list_length(&cgrp->bpf.progs[atype]); ++ total_cnt += prog_list_length(&cgrp->bpf.progs[atype], NULL); + } + } + +@@ -1105,7 +1122,7 @@ static int __cgroup_bpf_query(struct cgroup *cgrp, const union bpf_attr *attr, + u32 id; + + progs = &cgrp->bpf.progs[atype]; +- cnt = min_t(int, prog_list_length(progs), total_cnt); ++ cnt = min_t(int, prog_list_length(progs, NULL), total_cnt); + i = 0; + hlist_for_each_entry(pl, progs, node) { + prog = prog_list_prog(pl); +diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c +index 87f886ed33bc3..8c42c094f0d1e 100644 +--- a/kernel/bpf/syscall.c ++++ b/kernel/bpf/syscall.c +@@ -4169,7 +4169,8 @@ static int bpf_prog_attach_check_attach_type(const struct bpf_prog *prog, + #define BPF_F_ATTACH_MASK_BASE \ + (BPF_F_ALLOW_OVERRIDE | \ + BPF_F_ALLOW_MULTI | \ +- BPF_F_REPLACE) ++ BPF_F_REPLACE | \ ++ BPF_F_PREORDER) + + #define BPF_F_ATTACH_MASK_MPROG \ + (BPF_F_REPLACE | \ +diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h +index 2acf9b3363717..89242184a1937 100644 +--- a/tools/include/uapi/linux/bpf.h ++++ b/tools/include/uapi/linux/bpf.h +@@ -1207,6 +1207,7 @@ enum bpf_perf_event_type { + #define BPF_F_BEFORE (1U << 3) + #define BPF_F_AFTER (1U << 4) + #define BPF_F_ID (1U << 5) ++#define BPF_F_PREORDER (1U << 6) + #define BPF_F_LINK BPF_F_LINK /* 1 << 13 */ + + /* If BPF_F_STRICT_ALIGNMENT is used in BPF_PROG_LOAD command, the +-- +2.39.5 + diff --git a/queue-6.14/bpf-arm64-silence-ubsan-negation-overflow-warning.patch b/queue-6.14/bpf-arm64-silence-ubsan-negation-overflow-warning.patch new file mode 100644 index 0000000000..89837e966d --- /dev/null +++ b/queue-6.14/bpf-arm64-silence-ubsan-negation-overflow-warning.patch @@ -0,0 +1,60 @@ +From 0975780bdc4f437d30ba5c9257822b6eb9ab185a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 18 Feb 2025 00:02:40 -0800 +Subject: bpf: arm64: Silence "UBSAN: negation-overflow" warning + +From: Song Liu + +[ Upstream commit 239860828f8660e2be487e2fbdae2640cce3fd67 ] + +With UBSAN, test_bpf.ko triggers warnings like: + +UBSAN: negation-overflow in arch/arm64/net/bpf_jit_comp.c:1333:28 +negation of -2147483648 cannot be represented in type 's32' (aka 'int'): + +Silence these warnings by casting imm to u32 first. + +Reported-by: Breno Leitao +Signed-off-by: Song Liu +Tested-by: Breno Leitao +Link: https://lore.kernel.org/r/20250218080240.2431257-1-song@kernel.org +Signed-off-by: Alexei Starovoitov +Signed-off-by: Sasha Levin +--- + arch/arm64/net/bpf_jit_comp.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/arch/arm64/net/bpf_jit_comp.c b/arch/arm64/net/bpf_jit_comp.c +index 3126881fe6768..970c49bb7ed47 100644 +--- a/arch/arm64/net/bpf_jit_comp.c ++++ b/arch/arm64/net/bpf_jit_comp.c +@@ -274,7 +274,7 @@ static inline void emit_a64_add_i(const bool is64, const int dst, const int src, + { + if (is_addsub_imm(imm)) { + emit(A64_ADD_I(is64, dst, src, imm), ctx); +- } else if (is_addsub_imm(-imm)) { ++ } else if (is_addsub_imm(-(u32)imm)) { + emit(A64_SUB_I(is64, dst, src, -imm), ctx); + } else { + emit_a64_mov_i(is64, tmp, imm, ctx); +@@ -1208,7 +1208,7 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx, + case BPF_ALU64 | BPF_SUB | BPF_K: + if (is_addsub_imm(imm)) { + emit(A64_SUB_I(is64, dst, dst, imm), ctx); +- } else if (is_addsub_imm(-imm)) { ++ } else if (is_addsub_imm(-(u32)imm)) { + emit(A64_ADD_I(is64, dst, dst, -imm), ctx); + } else { + emit_a64_mov_i(is64, tmp, imm, ctx); +@@ -1379,7 +1379,7 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx, + case BPF_JMP32 | BPF_JSLE | BPF_K: + if (is_addsub_imm(imm)) { + emit(A64_CMP_I(is64, dst, imm), ctx); +- } else if (is_addsub_imm(-imm)) { ++ } else if (is_addsub_imm(-(u32)imm)) { + emit(A64_CMN_I(is64, dst, -imm), ctx); + } else { + emit_a64_mov_i(is64, tmp, imm, ctx); +-- +2.39.5 + diff --git a/queue-6.14/bpf-copy_verifier_state-should-copy-loop_entry-field.patch b/queue-6.14/bpf-copy_verifier_state-should-copy-loop_entry-field.patch new file mode 100644 index 0000000000..56e817f1b4 --- /dev/null +++ b/queue-6.14/bpf-copy_verifier_state-should-copy-loop_entry-field.patch @@ -0,0 +1,89 @@ +From 2cf0389fa61d40c380f3c3d1e5249511d3c473dd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 15 Feb 2025 03:03:52 -0800 +Subject: bpf: copy_verifier_state() should copy 'loop_entry' field + +From: Eduard Zingerman + +[ Upstream commit bbbc02b7445ebfda13e4847f4f1413c6480a85a9 ] + +The bpf_verifier_state.loop_entry state should be copied by +copy_verifier_state(). Otherwise, .loop_entry values from unrelated +states would poison env->cur_state. + +Additionally, env->stack should not contain any states with +.loop_entry != NULL. The states in env->stack are yet to be verified, +while .loop_entry is set for states that reached an equivalent state. +This means that env->cur_state->loop_entry should always be NULL after +pop_stack(). + +See the selftest in the next commit for an example of the program that +is not safe yet is accepted by verifier w/o this fix. + +This change has some verification performance impact for selftests: + +File Program Insns (A) Insns (B) Insns (DIFF) States (A) States (B) States (DIFF) +---------------------------------- ---------------------------- --------- --------- -------------- ---------- ---------- ------------- +arena_htab.bpf.o arena_htab_llvm 717 426 -291 (-40.59%) 57 37 -20 (-35.09%) +arena_htab_asm.bpf.o arena_htab_asm 597 445 -152 (-25.46%) 47 37 -10 (-21.28%) +arena_list.bpf.o arena_list_del 309 279 -30 (-9.71%) 23 14 -9 (-39.13%) +iters.bpf.o iter_subprog_check_stacksafe 155 141 -14 (-9.03%) 15 14 -1 (-6.67%) +iters.bpf.o iter_subprog_iters 1094 1003 -91 (-8.32%) 88 83 -5 (-5.68%) +iters.bpf.o loop_state_deps2 479 725 +246 (+51.36%) 46 63 +17 (+36.96%) +kmem_cache_iter.bpf.o open_coded_iter 63 59 -4 (-6.35%) 7 6 -1 (-14.29%) +verifier_bits_iter.bpf.o max_words 92 84 -8 (-8.70%) 8 7 -1 (-12.50%) +verifier_iterating_callbacks.bpf.o cond_break2 113 107 -6 (-5.31%) 12 12 +0 (+0.00%) + +And significant negative impact for sched_ext: + +File Program Insns (A) Insns (B) Insns (DIFF) States (A) States (B) States (DIFF) +----------------- ---------------------- --------- --------- -------------------- ---------- ---------- ------------------ +bpf.bpf.o lavd_init 7039 14723 +7684 (+109.16%) 490 1139 +649 (+132.45%) +bpf.bpf.o layered_dispatch 11485 10548 -937 (-8.16%) 848 762 -86 (-10.14%) +bpf.bpf.o layered_dump 7422 1000001 +992579 (+13373.47%) 681 31178 +30497 (+4478.27%) +bpf.bpf.o layered_enqueue 16854 71127 +54273 (+322.02%) 1611 6450 +4839 (+300.37%) +bpf.bpf.o p2dq_dispatch 665 791 +126 (+18.95%) 68 78 +10 (+14.71%) +bpf.bpf.o p2dq_init 2343 2980 +637 (+27.19%) 201 237 +36 (+17.91%) +bpf.bpf.o refresh_layer_cpumasks 16487 674760 +658273 (+3992.68%) 1770 65370 +63600 (+3593.22%) +bpf.bpf.o rusty_select_cpu 1937 40872 +38935 (+2010.07%) 177 3210 +3033 (+1713.56%) +scx_central.bpf.o central_dispatch 636 2687 +2051 (+322.48%) 63 227 +164 (+260.32%) +scx_nest.bpf.o nest_init 636 815 +179 (+28.14%) 60 73 +13 (+21.67%) +scx_qmap.bpf.o qmap_dispatch 2393 3580 +1187 (+49.60%) 196 253 +57 (+29.08%) +scx_qmap.bpf.o qmap_dump 233 318 +85 (+36.48%) 22 30 +8 (+36.36%) +scx_qmap.bpf.o qmap_init 16367 17436 +1069 (+6.53%) 603 669 +66 (+10.95%) + +Note 'layered_dump' program, which now hits 1M instructions limit. +This impact would be mitigated in the next patch. + +Signed-off-by: Eduard Zingerman +Link: https://lore.kernel.org/r/20250215110411.3236773-2-eddyz87@gmail.com +Signed-off-by: Alexei Starovoitov +Signed-off-by: Sasha Levin +--- + kernel/bpf/verifier.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c +index 68715b18df5e2..0752e8e556389 100644 +--- a/kernel/bpf/verifier.c ++++ b/kernel/bpf/verifier.c +@@ -1661,6 +1661,7 @@ static int copy_verifier_state(struct bpf_verifier_state *dst_state, + dst_state->callback_unroll_depth = src->callback_unroll_depth; + dst_state->used_as_loop_entry = src->used_as_loop_entry; + dst_state->may_goto_depth = src->may_goto_depth; ++ dst_state->loop_entry = src->loop_entry; + for (i = 0; i <= src->curframe; i++) { + dst = dst_state->frame[i]; + if (!dst) { +@@ -19264,6 +19265,8 @@ static int do_check(struct bpf_verifier_env *env) + return err; + break; + } else { ++ if (WARN_ON_ONCE(env->cur_state->loop_entry)) ++ env->cur_state->loop_entry = NULL; + do_print_state = true; + continue; + } +-- +2.39.5 + diff --git a/queue-6.14/bpf-don-t-do-clean_live_states-when-state-loop_entry.patch b/queue-6.14/bpf-don-t-do-clean_live_states-when-state-loop_entry.patch new file mode 100644 index 0000000000..790df6f54d --- /dev/null +++ b/queue-6.14/bpf-don-t-do-clean_live_states-when-state-loop_entry.patch @@ -0,0 +1,104 @@ +From c897c66288748b76a15149ef63802a7bf694d2db Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 15 Feb 2025 03:03:54 -0800 +Subject: bpf: don't do clean_live_states when state->loop_entry->branches > 0 + +From: Eduard Zingerman + +[ Upstream commit 9e63fdb0cbdf3268c86638a8274f4d5549a82820 ] + +verifier.c:is_state_visited() uses RANGE_WITHIN states comparison rules +for cached states that have loop_entry with non-zero branches count +(meaning that loop_entry's verification is not yet done). + +The RANGE_WITHIN rules in regsafe()/stacksafe() require register and +stack objects types to be identical in current and old states. + +verifier.c:clean_live_states() replaces registers and stack spills +with NOT_INIT/STACK_INVALID marks, if these registers/stack spills are +not read in any child state. This means that clean_live_states() works +against loop convergence logic under some conditions. See selftest in +the next patch for a specific example. + +Mitigate this by prohibiting clean_verifier_state() when +state->loop_entry->branches > 0. + +This undoes negative verification performance impact of the +copy_verifier_state() fix from the previous patch. +Below is comparison between master and current patch. + +selftests: + +File Program Insns (A) Insns (B) Insns (DIFF) States (A) States (B) States (DIFF) +---------------------------------- ---------------------------- --------- --------- --------------- ---------- ---------- -------------- +arena_htab.bpf.o arena_htab_llvm 717 423 -294 (-41.00%) 57 37 -20 (-35.09%) +arena_htab_asm.bpf.o arena_htab_asm 597 445 -152 (-25.46%) 47 37 -10 (-21.28%) +arena_list.bpf.o arena_list_add 1493 1822 +329 (+22.04%) 30 37 +7 (+23.33%) +arena_list.bpf.o arena_list_del 309 261 -48 (-15.53%) 23 15 -8 (-34.78%) +iters.bpf.o checkpoint_states_deletion 18125 22154 +4029 (+22.23%) 818 918 +100 (+12.22%) +iters.bpf.o iter_nested_deeply_iters 593 367 -226 (-38.11%) 67 43 -24 (-35.82%) +iters.bpf.o iter_nested_iters 813 772 -41 (-5.04%) 79 72 -7 (-8.86%) +iters.bpf.o iter_subprog_check_stacksafe 155 135 -20 (-12.90%) 15 14 -1 (-6.67%) +iters.bpf.o iter_subprog_iters 1094 808 -286 (-26.14%) 88 68 -20 (-22.73%) +iters.bpf.o loop_state_deps2 479 356 -123 (-25.68%) 46 35 -11 (-23.91%) +iters.bpf.o triple_continue 35 31 -4 (-11.43%) 3 3 +0 (+0.00%) +kmem_cache_iter.bpf.o open_coded_iter 63 59 -4 (-6.35%) 7 6 -1 (-14.29%) +mptcp_subflow.bpf.o _getsockopt_subflow 501 446 -55 (-10.98%) 25 23 -2 (-8.00%) +pyperf600_iter.bpf.o on_event 12339 6379 -5960 (-48.30%) 441 286 -155 (-35.15%) +verifier_bits_iter.bpf.o max_words 92 84 -8 (-8.70%) 8 7 -1 (-12.50%) +verifier_iterating_callbacks.bpf.o cond_break2 113 192 +79 (+69.91%) 12 21 +9 (+75.00%) + +sched_ext: + +File Program Insns (A) Insns (B) Insns (DIFF) States (A) States (B) States (DIFF) +----------------- ---------------------- --------- --------- ----------------- ---------- ---------- ---------------- +bpf.bpf.o layered_dispatch 11485 9039 -2446 (-21.30%) 848 662 -186 (-21.93%) +bpf.bpf.o layered_dump 7422 5022 -2400 (-32.34%) 681 298 -383 (-56.24%) +bpf.bpf.o layered_enqueue 16854 13753 -3101 (-18.40%) 1611 1308 -303 (-18.81%) +bpf.bpf.o layered_init 1000001 5549 -994452 (-99.45%) 84672 523 -84149 (-99.38%) +bpf.bpf.o layered_runnable 3149 1899 -1250 (-39.70%) 288 151 -137 (-47.57%) +bpf.bpf.o p2dq_init 2343 1936 -407 (-17.37%) 201 170 -31 (-15.42%) +bpf.bpf.o refresh_layer_cpumasks 16487 1285 -15202 (-92.21%) 1770 120 -1650 (-93.22%) +bpf.bpf.o rusty_select_cpu 1937 1386 -551 (-28.45%) 177 125 -52 (-29.38%) +scx_central.bpf.o central_dispatch 636 600 -36 (-5.66%) 63 59 -4 (-6.35%) +scx_central.bpf.o central_init 913 632 -281 (-30.78%) 48 39 -9 (-18.75%) +scx_nest.bpf.o nest_init 636 601 -35 (-5.50%) 60 58 -2 (-3.33%) +scx_pair.bpf.o pair_dispatch 1000001 1914 -998087 (-99.81%) 58169 142 -58027 (-99.76%) +scx_qmap.bpf.o qmap_dispatch 2393 2187 -206 (-8.61%) 196 174 -22 (-11.22%) +scx_qmap.bpf.o qmap_init 16367 22777 +6410 (+39.16%) 603 768 +165 (+27.36%) + +'layered_init' and 'pair_dispatch' hit 1M on master, but are verified +ok with this patch. + +Signed-off-by: Eduard Zingerman +Link: https://lore.kernel.org/r/20250215110411.3236773-4-eddyz87@gmail.com +Signed-off-by: Alexei Starovoitov +Signed-off-by: Sasha Levin +--- + kernel/bpf/verifier.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c +index e2801472c0ae4..68715b18df5e2 100644 +--- a/kernel/bpf/verifier.c ++++ b/kernel/bpf/verifier.c +@@ -17830,12 +17830,16 @@ static void clean_verifier_state(struct bpf_verifier_env *env, + static void clean_live_states(struct bpf_verifier_env *env, int insn, + struct bpf_verifier_state *cur) + { ++ struct bpf_verifier_state *loop_entry; + struct bpf_verifier_state_list *sl; + + sl = *explored_state(env, insn); + while (sl) { + if (sl->state.branches) + goto next; ++ loop_entry = get_loop_entry(&sl->state); ++ if (loop_entry && loop_entry->branches) ++ goto next; + if (sl->state.insn_idx != insn || + !same_callsites(&sl->state, cur)) + goto next; +-- +2.39.5 + diff --git a/queue-6.14/bpf-fix-possible-endless-loop-in-bpf-map-iteration.patch b/queue-6.14/bpf-fix-possible-endless-loop-in-bpf-map-iteration.patch new file mode 100644 index 0000000000..41b0888310 --- /dev/null +++ b/queue-6.14/bpf-fix-possible-endless-loop-in-bpf-map-iteration.patch @@ -0,0 +1,37 @@ +From 8b9554d18434ea5039f2e447372901c3ce096823 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 24 Apr 2025 11:32:51 -0400 +Subject: bpf: fix possible endless loop in BPF map iteration + +From: Brandon Kammerdiener + +[ Upstream commit 75673fda0c557ae26078177dd14d4857afbf128d ] + +The _safe variant used here gets the next element before running the callback, +avoiding the endless loop condition. + +Signed-off-by: Brandon Kammerdiener +Link: https://lore.kernel.org/r/20250424153246.141677-2-brandon.kammerdiener@intel.com +Signed-off-by: Alexei Starovoitov +Acked-by: Hou Tao +Signed-off-by: Sasha Levin +--- + kernel/bpf/hashtab.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/kernel/bpf/hashtab.c b/kernel/bpf/hashtab.c +index c308300fc72f6..c620ffb2b6629 100644 +--- a/kernel/bpf/hashtab.c ++++ b/kernel/bpf/hashtab.c +@@ -2224,7 +2224,7 @@ static long bpf_for_each_hash_elem(struct bpf_map *map, bpf_callback_t callback_ + b = &htab->buckets[i]; + rcu_read_lock(); + head = &b->head; +- hlist_nulls_for_each_entry_rcu(elem, n, head, hash_node) { ++ hlist_nulls_for_each_entry_safe(elem, n, head, hash_node) { + key = elem->key; + if (is_percpu) { + /* current cpu value for percpu map */ +-- +2.39.5 + diff --git a/queue-6.14/bpf-make-every-prog-keep-a-copy-of-ctx_arg_info.patch b/queue-6.14/bpf-make-every-prog-keep-a-copy-of-ctx_arg_info.patch new file mode 100644 index 0000000000..f07c038442 --- /dev/null +++ b/queue-6.14/bpf-make-every-prog-keep-a-copy-of-ctx_arg_info.patch @@ -0,0 +1,172 @@ +From 475cfc2665dfdafcc8a384965eb8467cdd9af06f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Feb 2025 11:06:36 -0800 +Subject: bpf: Make every prog keep a copy of ctx_arg_info + +From: Amery Hung + +[ Upstream commit 432051806f614ca512da401b80257b95b2a2241e ] + +Currently, ctx_arg_info is read-only in the view of the verifier since +it is shared among programs of the same attach type. Make each program +have their own copy of ctx_arg_info so that we can use it to store +program specific information. + +In the next patch where we support acquiring a referenced kptr through a +struct_ops argument tagged with "__ref", ctx_arg_info->ref_obj_id will +be used to store the unique reference object id of the argument. This +avoids creating a requirement in the verifier that "__ref" tagged +arguments must be the first set of references acquired [0]. + +[0] https://lore.kernel.org/bpf/20241220195619.2022866-2-amery.hung@gmail.com/ + +Signed-off-by: Amery Hung +Acked-by: Eduard Zingerman +Acked-by: Martin KaFai Lau +Link: https://lore.kernel.org/r/20250217190640.1748177-2-ameryhung@gmail.com +Signed-off-by: Alexei Starovoitov +Signed-off-by: Sasha Levin +--- + include/linux/bpf.h | 7 +++++-- + kernel/bpf/bpf_iter.c | 13 ++++++------- + kernel/bpf/syscall.c | 1 + + kernel/bpf/verifier.c | 22 ++++++++++++---------- + 4 files changed, 24 insertions(+), 19 deletions(-) + +diff --git a/include/linux/bpf.h b/include/linux/bpf.h +index f3f50e29d6392..f4df39e8c7357 100644 +--- a/include/linux/bpf.h ++++ b/include/linux/bpf.h +@@ -1507,7 +1507,7 @@ struct bpf_prog_aux { + u32 max_rdonly_access; + u32 max_rdwr_access; + struct btf *attach_btf; +- const struct bpf_ctx_arg_aux *ctx_arg_info; ++ struct bpf_ctx_arg_aux *ctx_arg_info; + void __percpu *priv_stack_ptr; + struct mutex dst_mutex; /* protects dst_* pointers below, *after* prog becomes visible */ + struct bpf_prog *dst_prog; +@@ -1945,6 +1945,9 @@ static inline void bpf_struct_ops_desc_release(struct bpf_struct_ops_desc *st_op + + #endif + ++int bpf_prog_ctx_arg_info_init(struct bpf_prog *prog, ++ const struct bpf_ctx_arg_aux *info, u32 cnt); ++ + #if defined(CONFIG_CGROUP_BPF) && defined(CONFIG_BPF_LSM) + int bpf_trampoline_link_cgroup_shim(struct bpf_prog *prog, + int cgroup_atype); +@@ -2546,7 +2549,7 @@ struct bpf_iter__bpf_map_elem { + + int bpf_iter_reg_target(const struct bpf_iter_reg *reg_info); + void bpf_iter_unreg_target(const struct bpf_iter_reg *reg_info); +-bool bpf_iter_prog_supported(struct bpf_prog *prog); ++int bpf_iter_prog_supported(struct bpf_prog *prog); + const struct bpf_func_proto * + bpf_iter_get_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog); + int bpf_iter_link_attach(const union bpf_attr *attr, bpfptr_t uattr, struct bpf_prog *prog); +diff --git a/kernel/bpf/bpf_iter.c b/kernel/bpf/bpf_iter.c +index 106735145948b..380e9a7cac75d 100644 +--- a/kernel/bpf/bpf_iter.c ++++ b/kernel/bpf/bpf_iter.c +@@ -335,7 +335,7 @@ static void cache_btf_id(struct bpf_iter_target_info *tinfo, + tinfo->btf_id = prog->aux->attach_btf_id; + } + +-bool bpf_iter_prog_supported(struct bpf_prog *prog) ++int bpf_iter_prog_supported(struct bpf_prog *prog) + { + const char *attach_fname = prog->aux->attach_func_name; + struct bpf_iter_target_info *tinfo = NULL, *iter; +@@ -344,7 +344,7 @@ bool bpf_iter_prog_supported(struct bpf_prog *prog) + int prefix_len = strlen(prefix); + + if (strncmp(attach_fname, prefix, prefix_len)) +- return false; ++ return -EINVAL; + + mutex_lock(&targets_mutex); + list_for_each_entry(iter, &targets, list) { +@@ -360,12 +360,11 @@ bool bpf_iter_prog_supported(struct bpf_prog *prog) + } + mutex_unlock(&targets_mutex); + +- if (tinfo) { +- prog->aux->ctx_arg_info_size = tinfo->reg_info->ctx_arg_info_size; +- prog->aux->ctx_arg_info = tinfo->reg_info->ctx_arg_info; +- } ++ if (!tinfo) ++ return -EINVAL; + +- return tinfo != NULL; ++ return bpf_prog_ctx_arg_info_init(prog, tinfo->reg_info->ctx_arg_info, ++ tinfo->reg_info->ctx_arg_info_size); + } + + const struct bpf_func_proto * +diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c +index 8c42c094f0d1e..32a8d5fd98612 100644 +--- a/kernel/bpf/syscall.c ++++ b/kernel/bpf/syscall.c +@@ -2314,6 +2314,7 @@ static void __bpf_prog_put_noref(struct bpf_prog *prog, bool deferred) + kvfree(prog->aux->jited_linfo); + kvfree(prog->aux->linfo); + kfree(prog->aux->kfunc_tab); ++ kfree(prog->aux->ctx_arg_info); + if (prog->aux->attach_btf) + btf_put(prog->aux->attach_btf); + +diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c +index 0752e8e556389..4392436ba7511 100644 +--- a/kernel/bpf/verifier.c ++++ b/kernel/bpf/verifier.c +@@ -22429,6 +22429,15 @@ static void print_verification_stats(struct bpf_verifier_env *env) + env->peak_states, env->longest_mark_read_walk); + } + ++int bpf_prog_ctx_arg_info_init(struct bpf_prog *prog, ++ const struct bpf_ctx_arg_aux *info, u32 cnt) ++{ ++ prog->aux->ctx_arg_info = kmemdup_array(info, cnt, sizeof(*info), GFP_KERNEL); ++ prog->aux->ctx_arg_info_size = cnt; ++ ++ return prog->aux->ctx_arg_info ? 0 : -ENOMEM; ++} ++ + static int check_struct_ops_btf_id(struct bpf_verifier_env *env) + { + const struct btf_type *t, *func_proto; +@@ -22509,17 +22518,12 @@ static int check_struct_ops_btf_id(struct bpf_verifier_env *env) + return -EACCES; + } + +- /* btf_ctx_access() used this to provide argument type info */ +- prog->aux->ctx_arg_info = +- st_ops_desc->arg_info[member_idx].info; +- prog->aux->ctx_arg_info_size = +- st_ops_desc->arg_info[member_idx].cnt; +- + prog->aux->attach_func_proto = func_proto; + prog->aux->attach_func_name = mname; + env->ops = st_ops->verifier_ops; + +- return 0; ++ return bpf_prog_ctx_arg_info_init(prog, st_ops_desc->arg_info[member_idx].info, ++ st_ops_desc->arg_info[member_idx].cnt); + } + #define SECURITY_PREFIX "security_" + +@@ -22996,9 +23000,7 @@ static int check_attach_btf_id(struct bpf_verifier_env *env) + prog->aux->attach_btf_trace = true; + return 0; + } else if (prog->expected_attach_type == BPF_TRACE_ITER) { +- if (!bpf_iter_prog_supported(prog)) +- return -EINVAL; +- return 0; ++ return bpf_iter_prog_supported(prog); + } + + if (prog->type == BPF_PROG_TYPE_LSM) { +-- +2.39.5 + diff --git a/queue-6.14/bpf-prevent-unsafe-access-to-the-sock-fields-in-the-.patch b/queue-6.14/bpf-prevent-unsafe-access-to-the-sock-fields-in-the-.patch new file mode 100644 index 0000000000..1d659b1ced --- /dev/null +++ b/queue-6.14/bpf-prevent-unsafe-access-to-the-sock-fields-in-the-.patch @@ -0,0 +1,150 @@ +From bde15bbd09f5c71ce5cd34e322dc50311ffefa42 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 20 Feb 2025 15:29:31 +0800 +Subject: bpf: Prevent unsafe access to the sock fields in the BPF timestamping + callback + +From: Jason Xing + +[ Upstream commit fd93eaffb3f977b23bc0a48d4c8616e654fcf133 ] + +The subsequent patch will implement BPF TX timestamping. It will +call the sockops BPF program without holding the sock lock. + +This breaks the current assumption that all sock ops programs will +hold the sock lock. The sock's fields of the uapi's bpf_sock_ops +requires this assumption. + +To address this, a new "u8 is_locked_tcp_sock;" field is added. This +patch sets it in the current sock_ops callbacks. The "is_fullsock" +test is then replaced by the "is_locked_tcp_sock" test during +sock_ops_convert_ctx_access(). + +The new TX timestamping callbacks added in the subsequent patch will +not have this set. This will prevent unsafe access from the new +timestamping callbacks. + +Potentially, we could allow read-only access. However, this would +require identifying which callback is read-safe-only and also requires +additional BPF instruction rewrites in the covert_ctx. Since the BPF +program can always read everything from a socket (e.g., by using +bpf_core_cast), this patch keeps it simple and disables all read +and write access to any socket fields through the bpf_sock_ops +UAPI from the new TX timestamping callback. + +Moreover, note that some of the fields in bpf_sock_ops are specific +to tcp_sock, and sock_ops currently only supports tcp_sock. In +the future, UDP timestamping will be added, which will also break +this assumption. The same idea used in this patch will be reused. +Considering that the current sock_ops only supports tcp_sock, the +variable is named is_locked_"tcp"_sock. + +Signed-off-by: Jason Xing +Signed-off-by: Martin KaFai Lau +Link: https://patch.msgid.link/20250220072940.99994-4-kerneljasonxing@gmail.com +Signed-off-by: Sasha Levin +--- + include/linux/filter.h | 1 + + include/net/tcp.h | 1 + + net/core/filter.c | 8 ++++---- + net/ipv4/tcp_input.c | 2 ++ + net/ipv4/tcp_output.c | 2 ++ + 5 files changed, 10 insertions(+), 4 deletions(-) + +diff --git a/include/linux/filter.h b/include/linux/filter.h +index a3ea462815957..d36d5d5180b11 100644 +--- a/include/linux/filter.h ++++ b/include/linux/filter.h +@@ -1508,6 +1508,7 @@ struct bpf_sock_ops_kern { + void *skb_data_end; + u8 op; + u8 is_fullsock; ++ u8 is_locked_tcp_sock; + u8 remaining_opt_len; + u64 temp; /* temp and everything after is not + * initialized to 0 before calling +diff --git a/include/net/tcp.h b/include/net/tcp.h +index 2d08473a6dc00..33c50ea976c88 100644 +--- a/include/net/tcp.h ++++ b/include/net/tcp.h +@@ -2671,6 +2671,7 @@ static inline int tcp_call_bpf(struct sock *sk, int op, u32 nargs, u32 *args) + memset(&sock_ops, 0, offsetof(struct bpf_sock_ops_kern, temp)); + if (sk_fullsock(sk)) { + sock_ops.is_fullsock = 1; ++ sock_ops.is_locked_tcp_sock = 1; + sock_owned_by_me(sk); + } + +diff --git a/net/core/filter.c b/net/core/filter.c +index 6c8fbc96b14a3..7e6ad73df6b17 100644 +--- a/net/core/filter.c ++++ b/net/core/filter.c +@@ -10367,10 +10367,10 @@ static u32 sock_ops_convert_ctx_access(enum bpf_access_type type, + } \ + *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF( \ + struct bpf_sock_ops_kern, \ +- is_fullsock), \ ++ is_locked_tcp_sock), \ + fullsock_reg, si->src_reg, \ + offsetof(struct bpf_sock_ops_kern, \ +- is_fullsock)); \ ++ is_locked_tcp_sock)); \ + *insn++ = BPF_JMP_IMM(BPF_JEQ, fullsock_reg, 0, jmp); \ + if (si->dst_reg == si->src_reg) \ + *insn++ = BPF_LDX_MEM(BPF_DW, reg, si->src_reg, \ +@@ -10455,10 +10455,10 @@ static u32 sock_ops_convert_ctx_access(enum bpf_access_type type, + temp)); \ + *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF( \ + struct bpf_sock_ops_kern, \ +- is_fullsock), \ ++ is_locked_tcp_sock), \ + reg, si->dst_reg, \ + offsetof(struct bpf_sock_ops_kern, \ +- is_fullsock)); \ ++ is_locked_tcp_sock)); \ + *insn++ = BPF_JMP_IMM(BPF_JEQ, reg, 0, 2); \ + *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF( \ + struct bpf_sock_ops_kern, sk),\ +diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c +index 1b09b4d76c296..d1ed4ac74e1d0 100644 +--- a/net/ipv4/tcp_input.c ++++ b/net/ipv4/tcp_input.c +@@ -169,6 +169,7 @@ static void bpf_skops_parse_hdr(struct sock *sk, struct sk_buff *skb) + memset(&sock_ops, 0, offsetof(struct bpf_sock_ops_kern, temp)); + sock_ops.op = BPF_SOCK_OPS_PARSE_HDR_OPT_CB; + sock_ops.is_fullsock = 1; ++ sock_ops.is_locked_tcp_sock = 1; + sock_ops.sk = sk; + bpf_skops_init_skb(&sock_ops, skb, tcp_hdrlen(skb)); + +@@ -185,6 +186,7 @@ static void bpf_skops_established(struct sock *sk, int bpf_op, + memset(&sock_ops, 0, offsetof(struct bpf_sock_ops_kern, temp)); + sock_ops.op = bpf_op; + sock_ops.is_fullsock = 1; ++ sock_ops.is_locked_tcp_sock = 1; + sock_ops.sk = sk; + /* sk with TCP_REPAIR_ON does not have skb in tcp_finish_connect */ + if (skb) +diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c +index 6031d7f7f5198..2398b0fc62225 100644 +--- a/net/ipv4/tcp_output.c ++++ b/net/ipv4/tcp_output.c +@@ -525,6 +525,7 @@ static void bpf_skops_hdr_opt_len(struct sock *sk, struct sk_buff *skb, + sock_owned_by_me(sk); + + sock_ops.is_fullsock = 1; ++ sock_ops.is_locked_tcp_sock = 1; + sock_ops.sk = sk; + } + +@@ -570,6 +571,7 @@ static void bpf_skops_write_hdr_opt(struct sock *sk, struct sk_buff *skb, + sock_owned_by_me(sk); + + sock_ops.is_fullsock = 1; ++ sock_ops.is_locked_tcp_sock = 1; + sock_ops.sk = sk; + } + +-- +2.39.5 + diff --git a/queue-6.14/bpf-return-prog-btf_id-without-capable-check.patch b/queue-6.14/bpf-return-prog-btf_id-without-capable-check.patch new file mode 100644 index 0000000000..7f33f20c3a --- /dev/null +++ b/queue-6.14/bpf-return-prog-btf_id-without-capable-check.patch @@ -0,0 +1,47 @@ +From 0257fa043584e21c1ab5ae765e34cb302eb402dc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Mar 2025 17:40:37 +0000 +Subject: bpf: Return prog btf_id without capable check + +From: Mykyta Yatsenko + +[ Upstream commit 07651ccda9ff10a8ca427670cdd06ce2c8e4269c ] + +Return prog's btf_id from bpf_prog_get_info_by_fd regardless of capable +check. This patch enables scenario, when freplace program, running +from user namespace, requires to query target prog's btf. + +Signed-off-by: Mykyta Yatsenko +Signed-off-by: Andrii Nakryiko +Acked-by: Yonghong Song +Link: https://lore.kernel.org/bpf/20250317174039.161275-3-mykyta.yatsenko5@gmail.com +Signed-off-by: Sasha Levin +--- + kernel/bpf/syscall.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c +index 1c2caae0d8946..87f886ed33bc3 100644 +--- a/kernel/bpf/syscall.c ++++ b/kernel/bpf/syscall.c +@@ -4733,6 +4733,8 @@ static int bpf_prog_get_info_by_fd(struct file *file, + info.recursion_misses = stats.misses; + + info.verified_insns = prog->aux->verified_insns; ++ if (prog->aux->btf) ++ info.btf_id = btf_obj_id(prog->aux->btf); + + if (!bpf_capable()) { + info.jited_prog_len = 0; +@@ -4879,8 +4881,6 @@ static int bpf_prog_get_info_by_fd(struct file *file, + } + } + +- if (prog->aux->btf) +- info.btf_id = btf_obj_id(prog->aux->btf); + info.attach_btf_id = prog->aux->attach_btf_id; + if (attach_btf) + info.attach_btf_obj_id = btf_obj_id(attach_btf); +-- +2.39.5 + diff --git a/queue-6.14/bpf-search-and-add-kfuncs-in-struct_ops-prologue-and.patch b/queue-6.14/bpf-search-and-add-kfuncs-in-struct_ops-prologue-and.patch new file mode 100644 index 0000000000..362e60ca95 --- /dev/null +++ b/queue-6.14/bpf-search-and-add-kfuncs-in-struct_ops-prologue-and.patch @@ -0,0 +1,86 @@ +From 087c9b131768c055ac56f7e8c971dbd5ac7cdf3b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 25 Feb 2025 15:35:44 -0800 +Subject: bpf: Search and add kfuncs in struct_ops prologue and epilogue + +From: Amery Hung + +[ Upstream commit d519594ee2445d7cd1ad51f4db4cee58f8213400 ] + +Currently, add_kfunc_call() is only invoked once before the main +verification loop. Therefore, the verifier could not find the +bpf_kfunc_btf_tab of a new kfunc call which is not seen in user defined +struct_ops operators but introduced in gen_prologue or gen_epilogue +during do_misc_fixup(). Fix this by searching kfuncs in the patching +instruction buffer and add them to prog->aux->kfunc_tab. + +Signed-off-by: Amery Hung +Acked-by: Eduard Zingerman +Acked-by: Martin KaFai Lau +Link: https://lore.kernel.org/r/20250225233545.285481-1-ameryhung@gmail.com +Signed-off-by: Alexei Starovoitov +Signed-off-by: Sasha Levin +--- + kernel/bpf/verifier.c | 25 ++++++++++++++++++++++++- + 1 file changed, 24 insertions(+), 1 deletion(-) + +diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c +index db95b76f5c139..e2801472c0ae4 100644 +--- a/kernel/bpf/verifier.c ++++ b/kernel/bpf/verifier.c +@@ -3206,6 +3206,21 @@ bpf_jit_find_kfunc_model(const struct bpf_prog *prog, + return res ? &res->func_model : NULL; + } + ++static int add_kfunc_in_insns(struct bpf_verifier_env *env, ++ struct bpf_insn *insn, int cnt) ++{ ++ int i, ret; ++ ++ for (i = 0; i < cnt; i++, insn++) { ++ if (bpf_pseudo_kfunc_call(insn)) { ++ ret = add_kfunc_call(env, insn->imm, insn->off); ++ if (ret < 0) ++ return ret; ++ } ++ } ++ return 0; ++} ++ + static int add_subprog_and_kfunc(struct bpf_verifier_env *env) + { + struct bpf_subprog_info *subprog = env->subprog_info; +@@ -20334,7 +20349,7 @@ static int convert_ctx_accesses(struct bpf_verifier_env *env) + { + struct bpf_subprog_info *subprogs = env->subprog_info; + const struct bpf_verifier_ops *ops = env->ops; +- int i, cnt, size, ctx_field_size, delta = 0, epilogue_cnt = 0; ++ int i, cnt, size, ctx_field_size, ret, delta = 0, epilogue_cnt = 0; + const int insn_cnt = env->prog->len; + struct bpf_insn *epilogue_buf = env->epilogue_buf; + struct bpf_insn *insn_buf = env->insn_buf; +@@ -20363,6 +20378,10 @@ static int convert_ctx_accesses(struct bpf_verifier_env *env) + return -ENOMEM; + env->prog = new_prog; + delta += cnt - 1; ++ ++ ret = add_kfunc_in_insns(env, epilogue_buf, epilogue_cnt - 1); ++ if (ret < 0) ++ return ret; + } + } + +@@ -20383,6 +20402,10 @@ static int convert_ctx_accesses(struct bpf_verifier_env *env) + + env->prog = new_prog; + delta += cnt - 1; ++ ++ ret = add_kfunc_in_insns(env, insn_buf, cnt - 1); ++ if (ret < 0) ++ return ret; + } + } + +-- +2.39.5 + diff --git a/queue-6.14/bpf-use-kallsyms-to-find-the-function-name-of-a-stru.patch b/queue-6.14/bpf-use-kallsyms-to-find-the-function-name-of-a-stru.patch new file mode 100644 index 0000000000..b55cf93498 --- /dev/null +++ b/queue-6.14/bpf-use-kallsyms-to-find-the-function-name-of-a-stru.patch @@ -0,0 +1,253 @@ +From 79f498a51c216ddd2ef0ce65ccf6c71686fc0fef Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 27 Jan 2025 14:27:19 -0800 +Subject: bpf: Use kallsyms to find the function name of a struct_ops's stub + function + +From: Martin KaFai Lau + +[ Upstream commit 12fdd29d5d71d2987a1aec434b704d850a4d7fcb ] + +In commit 1611603537a4 ("bpf: Create argument information for nullable arguments."), +it introduced a "__nullable" tagging at the argument name of a +stub function. Some background on the commit: +it requires to tag the stub function instead of directly tagging +the "ops" of a struct. This is because the btf func_proto of the "ops" +does not have the argument name and the "__nullable" is tagged at +the argument name. + +To find the stub function of a "ops", it currently relies on a naming +convention on the stub function "st_ops__ops_name". +e.g. tcp_congestion_ops__ssthresh. However, the new kernel +sub system implementing bpf_struct_ops have missed this and +have been surprised that the "__nullable" and the to-be-landed +"__ref" tagging was not effective. + +One option would be to give a warning whenever the stub function does +not follow the naming convention, regardless if it requires arg tagging +or not. + +Instead, this patch uses the kallsyms_lookup approach and removes +the requirement on the naming convention. The st_ops->cfi_stubs has +all the stub function kernel addresses. kallsyms_lookup() is used to +lookup the function name. With the function name, BTF can be used to +find the BTF func_proto. The existing "__nullable" arg name searching +logic will then fall through. + +One notable change is, +if it failed in kallsyms_lookup or it failed in looking up the stub +function name from the BTF, the bpf_struct_ops registration will fail. +This is different from the previous behavior that it silently ignored +the "st_ops__ops_name" function not found error. + +The "tcp_congestion_ops", "sched_ext_ops", and "hid_bpf_ops" can still be +registered successfully after this patch. There is struct_ops_maybe_null +selftest to cover the "__nullable" tagging. + +Other minor changes: +1. Removed the "%s__%s" format from the pr_warn because the naming + convention is removed. +2. The existing bpf_struct_ops_supported() is also moved earlier + because prepare_arg_info needs to use it to decide if the + stub function is NULL before calling the prepare_arg_info. + +Cc: Tejun Heo +Cc: Benjamin Tissoires +Cc: Yonghong Song +Cc: Amery Hung +Signed-off-by: Martin KaFai Lau +Reviewed-by: Amery Hung +Link: https://lore.kernel.org/r/20250127222719.2544255-1-martin.lau@linux.dev +Signed-off-by: Alexei Starovoitov +Signed-off-by: Sasha Levin +--- + kernel/bpf/bpf_struct_ops.c | 98 +++++++++++++++++-------------------- + 1 file changed, 44 insertions(+), 54 deletions(-) + +diff --git a/kernel/bpf/bpf_struct_ops.c b/kernel/bpf/bpf_struct_ops.c +index 040fb1cd840b6..9b7f3b9c52622 100644 +--- a/kernel/bpf/bpf_struct_ops.c ++++ b/kernel/bpf/bpf_struct_ops.c +@@ -146,39 +146,6 @@ void bpf_struct_ops_image_free(void *image) + } + + #define MAYBE_NULL_SUFFIX "__nullable" +-#define MAX_STUB_NAME 128 +- +-/* Return the type info of a stub function, if it exists. +- * +- * The name of a stub function is made up of the name of the struct_ops and +- * the name of the function pointer member, separated by "__". For example, +- * if the struct_ops type is named "foo_ops" and the function pointer +- * member is named "bar", the stub function name would be "foo_ops__bar". +- */ +-static const struct btf_type * +-find_stub_func_proto(const struct btf *btf, const char *st_op_name, +- const char *member_name) +-{ +- char stub_func_name[MAX_STUB_NAME]; +- const struct btf_type *func_type; +- s32 btf_id; +- int cp; +- +- cp = snprintf(stub_func_name, MAX_STUB_NAME, "%s__%s", +- st_op_name, member_name); +- if (cp >= MAX_STUB_NAME) { +- pr_warn("Stub function name too long\n"); +- return NULL; +- } +- btf_id = btf_find_by_name_kind(btf, stub_func_name, BTF_KIND_FUNC); +- if (btf_id < 0) +- return NULL; +- func_type = btf_type_by_id(btf, btf_id); +- if (!func_type) +- return NULL; +- +- return btf_type_by_id(btf, func_type->type); /* FUNC_PROTO */ +-} + + /* Prepare argument info for every nullable argument of a member of a + * struct_ops type. +@@ -203,27 +170,42 @@ find_stub_func_proto(const struct btf *btf, const char *st_op_name, + static int prepare_arg_info(struct btf *btf, + const char *st_ops_name, + const char *member_name, +- const struct btf_type *func_proto, ++ const struct btf_type *func_proto, void *stub_func_addr, + struct bpf_struct_ops_arg_info *arg_info) + { + const struct btf_type *stub_func_proto, *pointed_type; + const struct btf_param *stub_args, *args; + struct bpf_ctx_arg_aux *info, *info_buf; + u32 nargs, arg_no, info_cnt = 0; ++ char ksym[KSYM_SYMBOL_LEN]; ++ const char *stub_fname; ++ s32 stub_func_id; + u32 arg_btf_id; + int offset; + +- stub_func_proto = find_stub_func_proto(btf, st_ops_name, member_name); +- if (!stub_func_proto) +- return 0; ++ stub_fname = kallsyms_lookup((unsigned long)stub_func_addr, NULL, NULL, NULL, ksym); ++ if (!stub_fname) { ++ pr_warn("Cannot find the stub function name for the %s in struct %s\n", ++ member_name, st_ops_name); ++ return -ENOENT; ++ } ++ ++ stub_func_id = btf_find_by_name_kind(btf, stub_fname, BTF_KIND_FUNC); ++ if (stub_func_id < 0) { ++ pr_warn("Cannot find the stub function %s in btf\n", stub_fname); ++ return -ENOENT; ++ } ++ ++ stub_func_proto = btf_type_by_id(btf, stub_func_id); ++ stub_func_proto = btf_type_by_id(btf, stub_func_proto->type); + + /* Check if the number of arguments of the stub function is the same + * as the number of arguments of the function pointer. + */ + nargs = btf_type_vlen(func_proto); + if (nargs != btf_type_vlen(stub_func_proto)) { +- pr_warn("the number of arguments of the stub function %s__%s does not match the number of arguments of the member %s of struct %s\n", +- st_ops_name, member_name, member_name, st_ops_name); ++ pr_warn("the number of arguments of the stub function %s does not match the number of arguments of the member %s of struct %s\n", ++ stub_fname, member_name, st_ops_name); + return -EINVAL; + } + +@@ -253,21 +235,21 @@ static int prepare_arg_info(struct btf *btf, + &arg_btf_id); + if (!pointed_type || + !btf_type_is_struct(pointed_type)) { +- pr_warn("stub function %s__%s has %s tagging to an unsupported type\n", +- st_ops_name, member_name, MAYBE_NULL_SUFFIX); ++ pr_warn("stub function %s has %s tagging to an unsupported type\n", ++ stub_fname, MAYBE_NULL_SUFFIX); + goto err_out; + } + + offset = btf_ctx_arg_offset(btf, func_proto, arg_no); + if (offset < 0) { +- pr_warn("stub function %s__%s has an invalid trampoline ctx offset for arg#%u\n", +- st_ops_name, member_name, arg_no); ++ pr_warn("stub function %s has an invalid trampoline ctx offset for arg#%u\n", ++ stub_fname, arg_no); + goto err_out; + } + + if (args[arg_no].type != stub_args[arg_no].type) { +- pr_warn("arg#%u type in stub function %s__%s does not match with its original func_proto\n", +- arg_no, st_ops_name, member_name); ++ pr_warn("arg#%u type in stub function %s does not match with its original func_proto\n", ++ arg_no, stub_fname); + goto err_out; + } + +@@ -324,6 +306,13 @@ static bool is_module_member(const struct btf *btf, u32 id) + return !strcmp(btf_name_by_offset(btf, t->name_off), "module"); + } + ++int bpf_struct_ops_supported(const struct bpf_struct_ops *st_ops, u32 moff) ++{ ++ void *func_ptr = *(void **)(st_ops->cfi_stubs + moff); ++ ++ return func_ptr ? 0 : -ENOTSUPP; ++} ++ + int bpf_struct_ops_desc_init(struct bpf_struct_ops_desc *st_ops_desc, + struct btf *btf, + struct bpf_verifier_log *log) +@@ -387,7 +376,10 @@ int bpf_struct_ops_desc_init(struct bpf_struct_ops_desc *st_ops_desc, + + for_each_member(i, t, member) { + const struct btf_type *func_proto; ++ void **stub_func_addr; ++ u32 moff; + ++ moff = __btf_member_bit_offset(t, member) / 8; + mname = btf_name_by_offset(btf, member->name_off); + if (!*mname) { + pr_warn("anon member in struct %s is not supported\n", +@@ -413,7 +405,11 @@ int bpf_struct_ops_desc_init(struct bpf_struct_ops_desc *st_ops_desc, + func_proto = btf_type_resolve_func_ptr(btf, + member->type, + NULL); +- if (!func_proto) ++ ++ /* The member is not a function pointer or ++ * the function pointer is not supported. ++ */ ++ if (!func_proto || bpf_struct_ops_supported(st_ops, moff)) + continue; + + if (btf_distill_func_proto(log, btf, +@@ -425,8 +421,9 @@ int bpf_struct_ops_desc_init(struct bpf_struct_ops_desc *st_ops_desc, + goto errout; + } + ++ stub_func_addr = *(void **)(st_ops->cfi_stubs + moff); + err = prepare_arg_info(btf, st_ops->name, mname, +- func_proto, ++ func_proto, stub_func_addr, + arg_info + i); + if (err) + goto errout; +@@ -1152,13 +1149,6 @@ void bpf_struct_ops_put(const void *kdata) + bpf_map_put(&st_map->map); + } + +-int bpf_struct_ops_supported(const struct bpf_struct_ops *st_ops, u32 moff) +-{ +- void *func_ptr = *(void **)(st_ops->cfi_stubs + moff); +- +- return func_ptr ? 0 : -ENOTSUPP; +-} +- + static bool bpf_struct_ops_valid_to_reg(struct bpf_map *map) + { + struct bpf_struct_ops_map *st_map = (struct bpf_struct_ops_map *)map; +-- +2.39.5 + diff --git a/queue-6.14/bpftool-fix-readlink-usage-in-get_fd_type.patch b/queue-6.14/bpftool-fix-readlink-usage-in-get_fd_type.patch new file mode 100644 index 0000000000..5bc4f6d88f --- /dev/null +++ b/queue-6.14/bpftool-fix-readlink-usage-in-get_fd_type.patch @@ -0,0 +1,49 @@ +From a81a41498bb460b6c0a48b0fc1bf7f3f15480a16 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 29 Jan 2025 08:18:57 +0100 +Subject: bpftool: Fix readlink usage in get_fd_type + +From: Viktor Malik + +[ Upstream commit 0053f7d39d491b6138d7c526876d13885cbb65f1 ] + +The `readlink(path, buf, sizeof(buf))` call reads at most sizeof(buf) +bytes and *does not* append null-terminator to buf. With respect to +that, fix two pieces in get_fd_type: + +1. Change the truncation check to contain sizeof(buf) rather than + sizeof(path). +2. Append null-terminator to buf. + +Reported by Coverity. + +Signed-off-by: Viktor Malik +Signed-off-by: Andrii Nakryiko +Reviewed-by: Quentin Monnet +Link: https://lore.kernel.org/bpf/20250129071857.75182-1-vmalik@redhat.com +Signed-off-by: Alexei Starovoitov +Signed-off-by: Sasha Levin +--- + tools/bpf/bpftool/common.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/tools/bpf/bpftool/common.c b/tools/bpf/bpftool/common.c +index b921231d602e4..ecfa790adc13f 100644 +--- a/tools/bpf/bpftool/common.c ++++ b/tools/bpf/bpftool/common.c +@@ -461,10 +461,11 @@ int get_fd_type(int fd) + p_err("can't read link type: %s", strerror(errno)); + return -1; + } +- if (n == sizeof(path)) { ++ if (n == sizeof(buf)) { + p_err("can't read link type: path too long!"); + return -1; + } ++ buf[n] = '\0'; + + if (strstr(buf, "bpf-map")) + return BPF_OBJ_MAP; +-- +2.39.5 + diff --git a/queue-6.14/bpftool-using-the-right-format-specifiers.patch b/queue-6.14/bpftool-using-the-right-format-specifiers.patch new file mode 100644 index 0000000000..cab48feca1 --- /dev/null +++ b/queue-6.14/bpftool-using-the-right-format-specifiers.patch @@ -0,0 +1,349 @@ +From b5a99ae00ce91508b8084a80b3013f463332378f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 11 Mar 2025 19:28:09 +0800 +Subject: bpftool: Using the right format specifiers + +From: Jiayuan Chen + +[ Upstream commit 3775be3417cc3243b0df0492bd308559dcf0560b ] + +Fixed some formatting specifiers errors, such as using %d for int and %u +for unsigned int, as well as other byte-length types. + +Perform type cast using the type derived from the data type itself, for +example, if it's originally an int, it will be cast to unsigned int if +forced to unsigned. + +Signed-off-by: Jiayuan Chen +Signed-off-by: Andrii Nakryiko +Link: https://lore.kernel.org/bpf/20250311112809.81901-3-jiayuan.chen@linux.dev +Signed-off-by: Sasha Levin +--- + kernel/bpf/disasm.c | 4 ++-- + tools/bpf/bpftool/btf.c | 14 +++++++------- + tools/bpf/bpftool/btf_dumper.c | 2 +- + tools/bpf/bpftool/cgroup.c | 2 +- + tools/bpf/bpftool/common.c | 4 ++-- + tools/bpf/bpftool/jit_disasm.c | 3 ++- + tools/bpf/bpftool/map_perf_ring.c | 6 +++--- + tools/bpf/bpftool/net.c | 4 ++-- + tools/bpf/bpftool/netlink_dumper.c | 6 +++--- + tools/bpf/bpftool/prog.c | 12 ++++++------ + tools/bpf/bpftool/tracelog.c | 2 +- + tools/bpf/bpftool/xlated_dumper.c | 6 +++--- + 12 files changed, 33 insertions(+), 32 deletions(-) + +diff --git a/kernel/bpf/disasm.c b/kernel/bpf/disasm.c +index 309c4aa1b026a..c235acbd65095 100644 +--- a/kernel/bpf/disasm.c ++++ b/kernel/bpf/disasm.c +@@ -202,7 +202,7 @@ void print_bpf_insn(const struct bpf_insn_cbs *cbs, + insn->dst_reg, class == BPF_ALU ? 'w' : 'r', + insn->dst_reg); + } else if (is_addr_space_cast(insn)) { +- verbose(cbs->private_data, "(%02x) r%d = addr_space_cast(r%d, %d, %d)\n", ++ verbose(cbs->private_data, "(%02x) r%d = addr_space_cast(r%d, %u, %u)\n", + insn->code, insn->dst_reg, + insn->src_reg, ((u32)insn->imm) >> 16, (u16)insn->imm); + } else if (is_mov_percpu_addr(insn)) { +@@ -369,7 +369,7 @@ void print_bpf_insn(const struct bpf_insn_cbs *cbs, + insn->code, class == BPF_JMP32 ? 'w' : 'r', + insn->dst_reg, + bpf_jmp_string[BPF_OP(insn->code) >> 4], +- insn->imm, insn->off); ++ (u32)insn->imm, insn->off); + } + } else { + verbose(cbs->private_data, "(%02x) %s\n", +diff --git a/tools/bpf/bpftool/btf.c b/tools/bpf/bpftool/btf.c +index 2636655ac1808..6b14cbfa58aa2 100644 +--- a/tools/bpf/bpftool/btf.c ++++ b/tools/bpf/bpftool/btf.c +@@ -253,7 +253,7 @@ static int dump_btf_type(const struct btf *btf, __u32 id, + if (btf_kflag(t)) + printf("\n\t'%s' val=%d", name, v->val); + else +- printf("\n\t'%s' val=%u", name, v->val); ++ printf("\n\t'%s' val=%u", name, (__u32)v->val); + } + } + if (json_output) +@@ -1022,7 +1022,7 @@ static int do_dump(int argc, char **argv) + for (i = 0; i < root_type_cnt; i++) { + if (root_type_ids[i] == root_id) { + err = -EINVAL; +- p_err("duplicate root_id %d supplied", root_id); ++ p_err("duplicate root_id %u supplied", root_id); + goto done; + } + } +@@ -1132,7 +1132,7 @@ build_btf_type_table(struct hashmap *tab, enum bpf_obj_type type, + break; + default: + err = -1; +- p_err("unexpected object type: %d", type); ++ p_err("unexpected object type: %u", type); + goto err_free; + } + if (err) { +@@ -1155,7 +1155,7 @@ build_btf_type_table(struct hashmap *tab, enum bpf_obj_type type, + break; + default: + err = -1; +- p_err("unexpected object type: %d", type); ++ p_err("unexpected object type: %u", type); + goto err_free; + } + if (fd < 0) { +@@ -1188,7 +1188,7 @@ build_btf_type_table(struct hashmap *tab, enum bpf_obj_type type, + break; + default: + err = -1; +- p_err("unexpected object type: %d", type); ++ p_err("unexpected object type: %u", type); + goto err_free; + } + if (!btf_id) +@@ -1254,12 +1254,12 @@ show_btf_plain(struct bpf_btf_info *info, int fd, + + n = 0; + hashmap__for_each_key_entry(btf_prog_table, entry, info->id) { +- printf("%s%lu", n++ == 0 ? " prog_ids " : ",", entry->value); ++ printf("%s%lu", n++ == 0 ? " prog_ids " : ",", (unsigned long)entry->value); + } + + n = 0; + hashmap__for_each_key_entry(btf_map_table, entry, info->id) { +- printf("%s%lu", n++ == 0 ? " map_ids " : ",", entry->value); ++ printf("%s%lu", n++ == 0 ? " map_ids " : ",", (unsigned long)entry->value); + } + + emit_obj_refs_plain(refs_table, info->id, "\n\tpids "); +diff --git a/tools/bpf/bpftool/btf_dumper.c b/tools/bpf/bpftool/btf_dumper.c +index 527fe867a8fbd..4e896d8a2416e 100644 +--- a/tools/bpf/bpftool/btf_dumper.c ++++ b/tools/bpf/bpftool/btf_dumper.c +@@ -653,7 +653,7 @@ static int __btf_dumper_type_only(const struct btf *btf, __u32 type_id, + case BTF_KIND_ARRAY: + array = (struct btf_array *)(t + 1); + BTF_PRINT_TYPE(array->type); +- BTF_PRINT_ARG("[%d]", array->nelems); ++ BTF_PRINT_ARG("[%u]", array->nelems); + break; + case BTF_KIND_PTR: + BTF_PRINT_TYPE(t->type); +diff --git a/tools/bpf/bpftool/cgroup.c b/tools/bpf/bpftool/cgroup.c +index 9af426d432993..93b139bfb9880 100644 +--- a/tools/bpf/bpftool/cgroup.c ++++ b/tools/bpf/bpftool/cgroup.c +@@ -191,7 +191,7 @@ static int show_bpf_prog(int id, enum bpf_attach_type attach_type, + if (attach_btf_name) + printf(" %-15s", attach_btf_name); + else if (info.attach_btf_id) +- printf(" attach_btf_obj_id=%d attach_btf_id=%d", ++ printf(" attach_btf_obj_id=%u attach_btf_id=%u", + info.attach_btf_obj_id, info.attach_btf_id); + printf("\n"); + } +diff --git a/tools/bpf/bpftool/common.c b/tools/bpf/bpftool/common.c +index 9b75639434b81..b921231d602e4 100644 +--- a/tools/bpf/bpftool/common.c ++++ b/tools/bpf/bpftool/common.c +@@ -713,7 +713,7 @@ ifindex_to_arch(__u32 ifindex, __u64 ns_dev, __u64 ns_ino, const char **opt) + int vendor_id; + + if (!ifindex_to_name_ns(ifindex, ns_dev, ns_ino, devname)) { +- p_err("Can't get net device name for ifindex %d: %s", ifindex, ++ p_err("Can't get net device name for ifindex %u: %s", ifindex, + strerror(errno)); + return NULL; + } +@@ -738,7 +738,7 @@ ifindex_to_arch(__u32 ifindex, __u64 ns_dev, __u64 ns_ino, const char **opt) + /* No NFP support in LLVM, we have no valid triple to return. */ + default: + p_err("Can't get arch name for device vendor id 0x%04x", +- vendor_id); ++ (unsigned int)vendor_id); + return NULL; + } + } +diff --git a/tools/bpf/bpftool/jit_disasm.c b/tools/bpf/bpftool/jit_disasm.c +index c032d2c6ab6d5..8895b4e1f6903 100644 +--- a/tools/bpf/bpftool/jit_disasm.c ++++ b/tools/bpf/bpftool/jit_disasm.c +@@ -343,7 +343,8 @@ int disasm_print_insn(unsigned char *image, ssize_t len, int opcodes, + { + const struct bpf_line_info *linfo = NULL; + unsigned int nr_skip = 0; +- int count, i, pc = 0; ++ int count, i; ++ unsigned int pc = 0; + disasm_ctx_t ctx; + + if (!len) +diff --git a/tools/bpf/bpftool/map_perf_ring.c b/tools/bpf/bpftool/map_perf_ring.c +index 21d7d447e1f3b..552b4ca40c27c 100644 +--- a/tools/bpf/bpftool/map_perf_ring.c ++++ b/tools/bpf/bpftool/map_perf_ring.c +@@ -91,15 +91,15 @@ print_bpf_output(void *private_data, int cpu, struct perf_event_header *event) + jsonw_end_object(json_wtr); + } else { + if (e->header.type == PERF_RECORD_SAMPLE) { +- printf("== @%lld.%09lld CPU: %d index: %d =====\n", ++ printf("== @%llu.%09llu CPU: %d index: %d =====\n", + e->time / 1000000000ULL, e->time % 1000000000ULL, + cpu, idx); + fprint_hex(stdout, e->data, e->size, " "); + printf("\n"); + } else if (e->header.type == PERF_RECORD_LOST) { +- printf("lost %lld events\n", lost->lost); ++ printf("lost %llu events\n", lost->lost); + } else { +- printf("unknown event type=%d size=%d\n", ++ printf("unknown event type=%u size=%u\n", + e->header.type, e->header.size); + } + } +diff --git a/tools/bpf/bpftool/net.c b/tools/bpf/bpftool/net.c +index d2242d9f84411..64f958f437b01 100644 +--- a/tools/bpf/bpftool/net.c ++++ b/tools/bpf/bpftool/net.c +@@ -476,7 +476,7 @@ static void __show_dev_tc_bpf(const struct ip_devname_ifindex *dev, + for (i = 0; i < optq.count; i++) { + NET_START_OBJECT; + NET_DUMP_STR("devname", "%s", dev->devname); +- NET_DUMP_UINT("ifindex", "(%u)", dev->ifindex); ++ NET_DUMP_UINT("ifindex", "(%u)", (unsigned int)dev->ifindex); + NET_DUMP_STR("kind", " %s", attach_loc_strings[loc]); + ret = __show_dev_tc_bpf_name(prog_ids[i], prog_name, + sizeof(prog_name)); +@@ -831,7 +831,7 @@ static void show_link_netfilter(void) + if (err) { + if (errno == ENOENT) + break; +- p_err("can't get next link: %s (id %d)", strerror(errno), id); ++ p_err("can't get next link: %s (id %u)", strerror(errno), id); + break; + } + +diff --git a/tools/bpf/bpftool/netlink_dumper.c b/tools/bpf/bpftool/netlink_dumper.c +index 5f65140b003b2..0a3c7e96c797a 100644 +--- a/tools/bpf/bpftool/netlink_dumper.c ++++ b/tools/bpf/bpftool/netlink_dumper.c +@@ -45,7 +45,7 @@ static int do_xdp_dump_one(struct nlattr *attr, unsigned int ifindex, + NET_START_OBJECT; + if (name) + NET_DUMP_STR("devname", "%s", name); +- NET_DUMP_UINT("ifindex", "(%d)", ifindex); ++ NET_DUMP_UINT("ifindex", "(%u)", ifindex); + + if (mode == XDP_ATTACHED_MULTI) { + if (json_output) { +@@ -74,7 +74,7 @@ int do_xdp_dump(struct ifinfomsg *ifinfo, struct nlattr **tb) + if (!tb[IFLA_XDP]) + return 0; + +- return do_xdp_dump_one(tb[IFLA_XDP], ifinfo->ifi_index, ++ return do_xdp_dump_one(tb[IFLA_XDP], (unsigned int)ifinfo->ifi_index, + libbpf_nla_getattr_str(tb[IFLA_IFNAME])); + } + +@@ -168,7 +168,7 @@ int do_filter_dump(struct tcmsg *info, struct nlattr **tb, const char *kind, + NET_START_OBJECT; + if (devname[0] != '\0') + NET_DUMP_STR("devname", "%s", devname); +- NET_DUMP_UINT("ifindex", "(%u)", ifindex); ++ NET_DUMP_UINT("ifindex", "(%u)", (unsigned int)ifindex); + NET_DUMP_STR("kind", " %s", kind); + ret = do_bpf_filter_dump(tb[TCA_OPTIONS]); + NET_END_OBJECT_FINAL; +diff --git a/tools/bpf/bpftool/prog.c b/tools/bpf/bpftool/prog.c +index 52ffb74ae4e89..f010295350be5 100644 +--- a/tools/bpf/bpftool/prog.c ++++ b/tools/bpf/bpftool/prog.c +@@ -521,10 +521,10 @@ static void print_prog_header_plain(struct bpf_prog_info *info, int fd) + print_dev_plain(info->ifindex, info->netns_dev, info->netns_ino); + printf("%s", info->gpl_compatible ? " gpl" : ""); + if (info->run_time_ns) +- printf(" run_time_ns %lld run_cnt %lld", ++ printf(" run_time_ns %llu run_cnt %llu", + info->run_time_ns, info->run_cnt); + if (info->recursion_misses) +- printf(" recursion_misses %lld", info->recursion_misses); ++ printf(" recursion_misses %llu", info->recursion_misses); + printf("\n"); + } + +@@ -569,7 +569,7 @@ static void print_prog_plain(struct bpf_prog_info *info, int fd, bool orphaned) + } + + if (info->btf_id) +- printf("\n\tbtf_id %d", info->btf_id); ++ printf("\n\tbtf_id %u", info->btf_id); + + emit_obj_refs_plain(refs_table, info->id, "\n\tpids "); + +@@ -1164,7 +1164,7 @@ static int get_run_data(const char *fname, void **data_ptr, unsigned int *size) + } + if (nb_read > buf_size - block_size) { + if (buf_size == UINT32_MAX) { +- p_err("data_in/ctx_in is too long (max: %d)", ++ p_err("data_in/ctx_in is too long (max: %u)", + UINT32_MAX); + goto err_free; + } +@@ -2252,7 +2252,7 @@ static char *profile_target_name(int tgt_fd) + + t = btf__type_by_id(btf, func_info.type_id); + if (!t) { +- p_err("btf %d doesn't have type %d", ++ p_err("btf %u doesn't have type %u", + info.btf_id, func_info.type_id); + goto out; + } +@@ -2330,7 +2330,7 @@ static int profile_open_perf_events(struct profiler_bpf *obj) + continue; + for (cpu = 0; cpu < obj->rodata->num_cpu; cpu++) { + if (profile_open_perf_event(m, cpu, map_fd)) { +- p_err("failed to create event %s on cpu %d", ++ p_err("failed to create event %s on cpu %u", + metrics[m].name, cpu); + return -1; + } +diff --git a/tools/bpf/bpftool/tracelog.c b/tools/bpf/bpftool/tracelog.c +index bf1f022127972..31d806e3bdaaa 100644 +--- a/tools/bpf/bpftool/tracelog.c ++++ b/tools/bpf/bpftool/tracelog.c +@@ -78,7 +78,7 @@ static bool get_tracefs_pipe(char *mnt) + return false; + + /* Allow room for NULL terminating byte and pipe file name */ +- snprintf(format, sizeof(format), "%%*s %%%zds %%99s %%*s %%*d %%*d\\n", ++ snprintf(format, sizeof(format), "%%*s %%%zus %%99s %%*s %%*d %%*d\\n", + PATH_MAX - strlen(pipe_name) - 1); + while (fscanf(fp, format, mnt, type) == 2) + if (strcmp(type, fstype) == 0) { +diff --git a/tools/bpf/bpftool/xlated_dumper.c b/tools/bpf/bpftool/xlated_dumper.c +index d0094345fb2bc..5e7cb8b36fef2 100644 +--- a/tools/bpf/bpftool/xlated_dumper.c ++++ b/tools/bpf/bpftool/xlated_dumper.c +@@ -199,13 +199,13 @@ static const char *print_imm(void *private_data, + + if (insn->src_reg == BPF_PSEUDO_MAP_FD) + snprintf(dd->scratch_buff, sizeof(dd->scratch_buff), +- "map[id:%u]", insn->imm); ++ "map[id:%d]", insn->imm); + else if (insn->src_reg == BPF_PSEUDO_MAP_VALUE) + snprintf(dd->scratch_buff, sizeof(dd->scratch_buff), +- "map[id:%u][0]+%u", insn->imm, (insn + 1)->imm); ++ "map[id:%d][0]+%d", insn->imm, (insn + 1)->imm); + else if (insn->src_reg == BPF_PSEUDO_MAP_IDX_VALUE) + snprintf(dd->scratch_buff, sizeof(dd->scratch_buff), +- "map[idx:%u]+%u", insn->imm, (insn + 1)->imm); ++ "map[idx:%d]+%d", insn->imm, (insn + 1)->imm); + else if (insn->src_reg == BPF_PSEUDO_FUNC) + snprintf(dd->scratch_buff, sizeof(dd->scratch_buff), + "subprog[%+d]", insn->imm); +-- +2.39.5 + diff --git a/queue-6.14/bridge-mdb-allow-replace-of-a-host-joined-group.patch b/queue-6.14/bridge-mdb-allow-replace-of-a-host-joined-group.patch new file mode 100644 index 0000000000..513d309f26 --- /dev/null +++ b/queue-6.14/bridge-mdb-allow-replace-of-a-host-joined-group.patch @@ -0,0 +1,67 @@ +From d4da1d68011b437d787e07c265a1f4726a38efc0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 4 Feb 2025 18:37:15 +0100 +Subject: bridge: mdb: Allow replace of a host-joined group + +From: Petr Machata + +[ Upstream commit d9e9f6d7b7d0c520bb87f19d2cbc57aeeb2091d5 ] + +Attempts to replace an MDB group membership of the host itself are +currently bounced: + + # ip link add name br up type bridge vlan_filtering 1 + # bridge mdb replace dev br port br grp 239.0.0.1 vid 2 + # bridge mdb replace dev br port br grp 239.0.0.1 vid 2 + Error: bridge: Group is already joined by host. + +A similar operation done on a member port would succeed. Ignore the check +for replacement of host group memberships as well. + +The bit of code that this enables is br_multicast_host_join(), which, for +already-joined groups only refreshes the MC group expiration timer, which +is desirable; and a userspace notification, also desirable. + +Change a selftest that exercises this code path from expecting a rejection +to expecting a pass. The rest of MDB selftests pass without modification. + +Signed-off-by: Petr Machata +Reviewed-by: Ido Schimmel +Acked-by: Nikolay Aleksandrov +Link: https://patch.msgid.link/e5c5188b9787ae806609e7ca3aa2a0a501b9b5c4.1738685648.git.petrm@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/bridge/br_mdb.c | 2 +- + tools/testing/selftests/net/forwarding/bridge_mdb.sh | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/net/bridge/br_mdb.c b/net/bridge/br_mdb.c +index 1a52a0bca086d..7e1ad229e1330 100644 +--- a/net/bridge/br_mdb.c ++++ b/net/bridge/br_mdb.c +@@ -1040,7 +1040,7 @@ static int br_mdb_add_group(const struct br_mdb_config *cfg, + + /* host join */ + if (!port) { +- if (mp->host_joined) { ++ if (mp->host_joined && !(cfg->nlflags & NLM_F_REPLACE)) { + NL_SET_ERR_MSG_MOD(extack, "Group is already joined by host"); + return -EEXIST; + } +diff --git a/tools/testing/selftests/net/forwarding/bridge_mdb.sh b/tools/testing/selftests/net/forwarding/bridge_mdb.sh +index d9d587454d207..8c1597ebc2d38 100755 +--- a/tools/testing/selftests/net/forwarding/bridge_mdb.sh ++++ b/tools/testing/selftests/net/forwarding/bridge_mdb.sh +@@ -149,7 +149,7 @@ cfg_test_host_common() + check_err $? "Failed to add $name host entry" + + bridge mdb replace dev br0 port br0 grp $grp $state vid 10 &> /dev/null +- check_fail $? "Managed to replace $name host entry" ++ check_err $? "Failed to replace $name host entry" + + bridge mdb del dev br0 port br0 grp $grp $state vid 10 + bridge mdb get dev br0 grp $grp vid 10 &> /dev/null +-- +2.39.5 + diff --git a/queue-6.14/btrfs-allow-buffered-write-to-avoid-full-page-read-i.patch b/queue-6.14/btrfs-allow-buffered-write-to-avoid-full-page-read-i.patch new file mode 100644 index 0000000000..375af835b9 --- /dev/null +++ b/queue-6.14/btrfs-allow-buffered-write-to-avoid-full-page-read-i.patch @@ -0,0 +1,122 @@ +From de0860d610aaaee77a8c5c713c41fea584ac83b3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 30 Oct 2024 17:04:02 +1030 +Subject: btrfs: allow buffered write to avoid full page read if it's block + aligned + +From: Qu Wenruo + +[ Upstream commit 0d31ca6584f21821c708752d379871b9fce2dc48 ] + +[BUG] +Since the support of block size (sector size) < page size for btrfs, +test case generic/563 fails with 4K block size and 64K page size: + + --- tests/generic/563.out 2024-04-25 18:13:45.178550333 +0930 + +++ /home/adam/xfstests-dev/results//generic/563.out.bad 2024-09-30 09:09:16.155312379 +0930 + @@ -3,7 +3,8 @@ + read is in range + write is in range + write -> read/write + -read is in range + +read has value of 8388608 + +read is NOT in range -33792 .. 33792 + write is in range + ... + +[CAUSE] +The test case creates a 8MiB file, then does buffered write into the 8MiB +using 4K block size, to overwrite the whole file. + +On 4K page sized systems, since the write range covers the full block and +page, btrfs will not bother reading the page, just like what XFS and EXT4 +do. + +But on 64K page sized systems, although the 4K sized write is still block +aligned, it's not page aligned anymore, thus btrfs will read the full +page, which will be accounted by cgroup and fail the test. + +As the test case itself expects such 4K block aligned write should not +trigger any read. + +Such expected behavior is an optimization to reduce folio reads when +possible, and unfortunately btrfs does not implement such optimization. + +[FIX] +To skip the full page read, we need to do the following modification: + +- Do not trigger full page read as long as the buffered write is block + aligned + This is pretty simple by modifying the check inside + prepare_uptodate_page(). + +- Skip already uptodate blocks during full page read + Or we can lead to the following data corruption: + + 0 32K 64K + |///////| | + + Where the file range [0, 32K) is dirtied by buffered write, the + remaining range [32K, 64K) is not. + + When reading the full page, since [0,32K) is only dirtied but not + written back, there is no data extent map for it, but a hole covering + [0, 64k). + + If we continue reading the full page range [0, 64K), the dirtied range + will be filled with 0 (since there is only a hole covering the whole + range). + This causes the dirtied range to get lost. + +With this optimization, btrfs can pass generic/563 even if the page size +is larger than fs block size. + +Reviewed-by: Filipe Manana +Signed-off-by: Qu Wenruo +Signed-off-by: David Sterba +Signed-off-by: Sasha Levin +--- + fs/btrfs/extent_io.c | 4 ++++ + fs/btrfs/file.c | 5 +++-- + 2 files changed, 7 insertions(+), 2 deletions(-) + +diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c +index 06922529f19dc..13b5359ea1b77 100644 +--- a/fs/btrfs/extent_io.c ++++ b/fs/btrfs/extent_io.c +@@ -974,6 +974,10 @@ static int btrfs_do_readpage(struct folio *folio, struct extent_map **em_cached, + end_folio_read(folio, true, cur, iosize); + break; + } ++ if (btrfs_folio_test_uptodate(fs_info, folio, cur, blocksize)) { ++ end_folio_read(folio, true, cur, blocksize); ++ continue; ++ } + em = get_extent_map(BTRFS_I(inode), folio, cur, end - cur + 1, em_cached); + if (IS_ERR(em)) { + end_folio_read(folio, false, cur, end + 1 - cur); +diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c +index cd4e40a719186..61ad1a79e5698 100644 +--- a/fs/btrfs/file.c ++++ b/fs/btrfs/file.c +@@ -804,14 +804,15 @@ static int prepare_uptodate_folio(struct inode *inode, struct folio *folio, u64 + { + u64 clamp_start = max_t(u64, pos, folio_pos(folio)); + u64 clamp_end = min_t(u64, pos + len, folio_pos(folio) + folio_size(folio)); ++ const u32 blocksize = inode_to_fs_info(inode)->sectorsize; + int ret = 0; + + if (folio_test_uptodate(folio)) + return 0; + + if (!force_uptodate && +- IS_ALIGNED(clamp_start, PAGE_SIZE) && +- IS_ALIGNED(clamp_end, PAGE_SIZE)) ++ IS_ALIGNED(clamp_start, blocksize) && ++ IS_ALIGNED(clamp_end, blocksize)) + return 0; + + ret = btrfs_read_folio(NULL, folio); +-- +2.39.5 + diff --git a/queue-6.14/btrfs-avoid-linker-error-in-btrfs_find_create_tree_b.patch b/queue-6.14/btrfs-avoid-linker-error-in-btrfs_find_create_tree_b.patch new file mode 100644 index 0000000000..b84704c900 --- /dev/null +++ b/queue-6.14/btrfs-avoid-linker-error-in-btrfs_find_create_tree_b.patch @@ -0,0 +1,61 @@ +From abd9d431df5dd3f2f8a8dba68c14a5baaf54937a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Mar 2025 10:58:46 +0000 +Subject: btrfs: avoid linker error in btrfs_find_create_tree_block() + +From: Mark Harmstone + +[ Upstream commit 7ef3cbf17d2734ca66c4ed8573be45f4e461e7ee ] + +The inline function btrfs_is_testing() is hardcoded to return 0 if +CONFIG_BTRFS_FS_RUN_SANITY_TESTS is not set. Currently we're relying on +the compiler optimizing out the call to alloc_test_extent_buffer() in +btrfs_find_create_tree_block(), as it's not been defined (it's behind an + #ifdef). + +Add a stub version of alloc_test_extent_buffer() to avoid linker errors +on non-standard optimization levels. This problem was seen on GCC 14 +with -O0 and is helps to see symbols that would be otherwise optimized +out. + +Reviewed-by: Qu Wenruo +Signed-off-by: Mark Harmstone +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Signed-off-by: Sasha Levin +--- + fs/btrfs/extent_io.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c +index c021aae8875eb..06922529f19dc 100644 +--- a/fs/btrfs/extent_io.c ++++ b/fs/btrfs/extent_io.c +@@ -2842,10 +2842,10 @@ struct extent_buffer *find_extent_buffer(struct btrfs_fs_info *fs_info, + return eb; + } + +-#ifdef CONFIG_BTRFS_FS_RUN_SANITY_TESTS + struct extent_buffer *alloc_test_extent_buffer(struct btrfs_fs_info *fs_info, + u64 start) + { ++#ifdef CONFIG_BTRFS_FS_RUN_SANITY_TESTS + struct extent_buffer *eb, *exists = NULL; + int ret; + +@@ -2881,8 +2881,11 @@ struct extent_buffer *alloc_test_extent_buffer(struct btrfs_fs_info *fs_info, + free_eb: + btrfs_release_extent_buffer(eb); + return exists; +-} ++#else ++ /* Stub to avoid linker error when compiled with optimizations turned off. */ ++ return NULL; + #endif ++} + + static struct extent_buffer *grab_extent_buffer(struct btrfs_fs_info *fs_info, + struct folio *folio) +-- +2.39.5 + diff --git a/queue-6.14/btrfs-avoid-null-pointer-dereference-if-no-valid-csu.patch b/queue-6.14/btrfs-avoid-null-pointer-dereference-if-no-valid-csu.patch new file mode 100644 index 0000000000..54a7b417f0 --- /dev/null +++ b/queue-6.14/btrfs-avoid-null-pointer-dereference-if-no-valid-csu.patch @@ -0,0 +1,73 @@ +From 20a2aed836f59b9e516ce116a4059fbc93299361 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 29 Apr 2025 15:17:50 +0930 +Subject: btrfs: avoid NULL pointer dereference if no valid csum tree + +From: Qu Wenruo + +[ Upstream commit f95d186255b319c48a365d47b69bd997fecb674e ] + +[BUG] +When trying read-only scrub on a btrfs with rescue=idatacsums mount +option, it will crash with the following call trace: + + BUG: kernel NULL pointer dereference, address: 0000000000000208 + #PF: supervisor read access in kernel mode + #PF: error_code(0x0000) - not-present page + CPU: 1 UID: 0 PID: 835 Comm: btrfs Tainted: G O 6.15.0-rc3-custom+ #236 PREEMPT(full) + Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS unknown 02/02/2022 + RIP: 0010:btrfs_lookup_csums_bitmap+0x49/0x480 [btrfs] + Call Trace: + + scrub_find_fill_first_stripe+0x35b/0x3d0 [btrfs] + scrub_simple_mirror+0x175/0x290 [btrfs] + scrub_stripe+0x5f7/0x6f0 [btrfs] + scrub_chunk+0x9a/0x150 [btrfs] + scrub_enumerate_chunks+0x333/0x660 [btrfs] + btrfs_scrub_dev+0x23e/0x600 [btrfs] + btrfs_ioctl+0x1dcf/0x2f80 [btrfs] + __x64_sys_ioctl+0x97/0xc0 + do_syscall_64+0x4f/0x120 + entry_SYSCALL_64_after_hwframe+0x76/0x7e + +[CAUSE] +Mount option "rescue=idatacsums" will completely skip loading the csum +tree, so that any data read will not find any data csum thus we will +ignore data checksum verification. + +Normally call sites utilizing csum tree will check the fs state flag +NO_DATA_CSUMS bit, but unfortunately scrub does not check that bit at all. + +This results in scrub to call btrfs_search_slot() on a NULL pointer +and triggered above crash. + +[FIX] +Check both extent and csum tree root before doing any tree search. + +Reviewed-by: Johannes Thumshirn +Signed-off-by: Qu Wenruo +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Signed-off-by: Sasha Levin +--- + fs/btrfs/scrub.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c +index 531312efee8df..5d0060eb8ff4c 100644 +--- a/fs/btrfs/scrub.c ++++ b/fs/btrfs/scrub.c +@@ -1541,8 +1541,8 @@ static int scrub_find_fill_first_stripe(struct btrfs_block_group *bg, + u64 extent_gen; + int ret; + +- if (unlikely(!extent_root)) { +- btrfs_err(fs_info, "no valid extent root for scrub"); ++ if (unlikely(!extent_root || !csum_root)) { ++ btrfs_err(fs_info, "no valid extent or csum root for scrub"); + return -EUCLEAN; + } + memset(stripe->sectors, 0, sizeof(struct scrub_sector_verification) * +-- +2.39.5 + diff --git a/queue-6.14/btrfs-compression-adjust-cb-compressed_folios-alloca.patch b/queue-6.14/btrfs-compression-adjust-cb-compressed_folios-alloca.patch new file mode 100644 index 0000000000..066db836d5 --- /dev/null +++ b/queue-6.14/btrfs-compression-adjust-cb-compressed_folios-alloca.patch @@ -0,0 +1,43 @@ +From 74eddc5ca0e4d2724897f9dc63213bdf2f6d3f6a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 25 Apr 2025 23:23:29 -0700 +Subject: btrfs: compression: adjust cb->compressed_folios allocation type + +From: Kees Cook + +[ Upstream commit 6f9a8ab796c6528d22de3c504c81fce7dde63d8a ] + +In preparation for making the kmalloc() family of allocators type aware, +we need to make sure that the returned type from the allocation matches +the type of the variable being assigned. (Before, the allocator would +always return "void *", which can be implicitly cast to any pointer type.) + +The assigned type is "struct folio **" but the returned type will be +"struct page **". These are the same allocation size (pointer size), but +the types don't match. Adjust the allocation type to match the assignment. + +Reviewed-by: Qu Wenruo +Signed-off-by: Kees Cook +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Signed-off-by: Sasha Levin +--- + fs/btrfs/compression.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/fs/btrfs/compression.c b/fs/btrfs/compression.c +index 0c4d486c3048d..18d2210dc7249 100644 +--- a/fs/btrfs/compression.c ++++ b/fs/btrfs/compression.c +@@ -606,7 +606,7 @@ void btrfs_submit_compressed_read(struct btrfs_bio *bbio) + free_extent_map(em); + + cb->nr_folios = DIV_ROUND_UP(compressed_len, PAGE_SIZE); +- cb->compressed_folios = kcalloc(cb->nr_folios, sizeof(struct page *), GFP_NOFS); ++ cb->compressed_folios = kcalloc(cb->nr_folios, sizeof(struct folio *), GFP_NOFS); + if (!cb->compressed_folios) { + ret = BLK_STS_RESOURCE; + goto out_free_bio; +-- +2.39.5 + diff --git a/queue-6.14/btrfs-correct-the-order-of-prelim_ref-arguments-in-b.patch b/queue-6.14/btrfs-correct-the-order-of-prelim_ref-arguments-in-b.patch new file mode 100644 index 0000000000..9fbe933e2b --- /dev/null +++ b/queue-6.14/btrfs-correct-the-order-of-prelim_ref-arguments-in-b.patch @@ -0,0 +1,82 @@ +From 4709e0dfd837569e1b89c5769067da7a453ebafc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 25 Apr 2025 09:25:06 -0400 +Subject: btrfs: correct the order of prelim_ref arguments in btrfs__prelim_ref + +From: Goldwyn Rodrigues + +[ Upstream commit bc7e0975093567f51be8e1bdf4aa5900a3cf0b1e ] + +btrfs_prelim_ref() calls the old and new reference variables in the +incorrect order. This causes a NULL pointer dereference because oldref +is passed as NULL to trace_btrfs_prelim_ref_insert(). + +Note, trace_btrfs_prelim_ref_insert() is being called with newref as +oldref (and oldref as NULL) on purpose in order to print out +the values of newref. + +To reproduce: +echo 1 > /sys/kernel/debug/tracing/events/btrfs/btrfs_prelim_ref_insert/enable + +Perform some writeback operations. + +Backtrace: +BUG: kernel NULL pointer dereference, address: 0000000000000018 + #PF: supervisor read access in kernel mode + #PF: error_code(0x0000) - not-present page + PGD 115949067 P4D 115949067 PUD 11594a067 PMD 0 + Oops: Oops: 0000 [#1] SMP NOPTI + CPU: 1 UID: 0 PID: 1188 Comm: fsstress Not tainted 6.15.0-rc2-tester+ #47 PREEMPT(voluntary) 7ca2cef72d5e9c600f0c7718adb6462de8149622 + Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS rel-1.16.3-2-gc13ff2cd-prebuilt.qemu.org 04/01/2014 + RIP: 0010:trace_event_raw_event_btrfs__prelim_ref+0x72/0x130 + Code: e8 43 81 9f ff 48 85 c0 74 78 4d 85 e4 0f 84 8f 00 00 00 49 8b 94 24 c0 06 00 00 48 8b 0a 48 89 48 08 48 8b 52 08 48 89 50 10 <49> 8b 55 18 48 89 50 18 49 8b 55 20 48 89 50 20 41 0f b6 55 28 88 + RSP: 0018:ffffce44820077a0 EFLAGS: 00010286 + RAX: ffff8c6b403f9014 RBX: ffff8c6b55825730 RCX: 304994edf9cf506b + RDX: d8b11eb7f0fdb699 RSI: ffff8c6b403f9010 RDI: ffff8c6b403f9010 + RBP: 0000000000000001 R08: 0000000000000001 R09: 0000000000000010 + R10: 00000000ffffffff R11: 0000000000000000 R12: ffff8c6b4e8fb000 + R13: 0000000000000000 R14: ffffce44820077a8 R15: ffff8c6b4abd1540 + FS: 00007f4dc6813740(0000) GS:ffff8c6c1d378000(0000) knlGS:0000000000000000 + CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 + CR2: 0000000000000018 CR3: 000000010eb42000 CR4: 0000000000750ef0 + PKRU: 55555554 + Call Trace: + + prelim_ref_insert+0x1c1/0x270 + find_parent_nodes+0x12a6/0x1ee0 + ? __entry_text_end+0x101f06/0x101f09 + ? srso_alias_return_thunk+0x5/0xfbef5 + ? srso_alias_return_thunk+0x5/0xfbef5 + ? srso_alias_return_thunk+0x5/0xfbef5 + ? srso_alias_return_thunk+0x5/0xfbef5 + btrfs_is_data_extent_shared+0x167/0x640 + ? fiemap_process_hole+0xd0/0x2c0 + extent_fiemap+0xa5c/0xbc0 + ? __entry_text_end+0x101f05/0x101f09 + btrfs_fiemap+0x7e/0xd0 + do_vfs_ioctl+0x425/0x9d0 + __x64_sys_ioctl+0x75/0xc0 + +Signed-off-by: Goldwyn Rodrigues +Signed-off-by: David Sterba +Signed-off-by: Sasha Levin +--- + include/trace/events/btrfs.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/include/trace/events/btrfs.h b/include/trace/events/btrfs.h +index 549ab3b419618..3efc00cc1bcd2 100644 +--- a/include/trace/events/btrfs.h ++++ b/include/trace/events/btrfs.h +@@ -1928,7 +1928,7 @@ DECLARE_EVENT_CLASS(btrfs__prelim_ref, + TP_PROTO(const struct btrfs_fs_info *fs_info, + const struct prelim_ref *oldref, + const struct prelim_ref *newref, u64 tree_size), +- TP_ARGS(fs_info, newref, oldref, tree_size), ++ TP_ARGS(fs_info, oldref, newref, tree_size), + + TP_STRUCT__entry_btrfs( + __field( u64, root_id ) +-- +2.39.5 + diff --git a/queue-6.14/btrfs-fix-non-empty-delayed-iputs-list-on-unmount-du.patch b/queue-6.14/btrfs-fix-non-empty-delayed-iputs-list-on-unmount-du.patch new file mode 100644 index 0000000000..376921ca42 --- /dev/null +++ b/queue-6.14/btrfs-fix-non-empty-delayed-iputs-list-on-unmount-du.patch @@ -0,0 +1,85 @@ +From 722828e75e3307e75867cb7f14a25db6d9f1a9d8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Mar 2025 14:25:38 +0000 +Subject: btrfs: fix non-empty delayed iputs list on unmount due to async + workers + +From: Filipe Manana + +[ Upstream commit cda76788f8b0f7de3171100e3164ec1ce702292e ] + +At close_ctree() after we have ran delayed iputs either explicitly through +calling btrfs_run_delayed_iputs() or later during the call to +btrfs_commit_super() or btrfs_error_commit_super(), we assert that the +delayed iputs list is empty. + +We have (another) race where this assertion might fail because we have +queued an async write into the fs_info->workers workqueue. Here's how it +happens: + +1) We are submitting a data bio for an inode that is not the data + relocation inode, so we call btrfs_wq_submit_bio(); + +2) btrfs_wq_submit_bio() submits a work for the fs_info->workers queue + that will run run_one_async_done(); + +3) We enter close_ctree(), flush several work queues except + fs_info->workers, explicitly run delayed iputs with a call to + btrfs_run_delayed_iputs() and then again shortly after by calling + btrfs_commit_super() or btrfs_error_commit_super(), which also run + delayed iputs; + +4) run_one_async_done() is executed in the work queue, and because there + was an IO error (bio->bi_status is not 0) it calls btrfs_bio_end_io(), + which drops the final reference on the associated ordered extent by + calling btrfs_put_ordered_extent() - and that adds a delayed iput for + the inode; + +5) At close_ctree() we find that after stopping the cleaner and + transaction kthreads the delayed iputs list is not empty, failing the + following assertion: + + ASSERT(list_empty(&fs_info->delayed_iputs)); + +Fix this by flushing the fs_info->workers workqueue before running delayed +iputs at close_ctree(). + +David reported this when running generic/648, which exercises IO error +paths by using the DM error table. + +Reported-by: David Sterba +Reviewed-by: Qu Wenruo +Signed-off-by: Filipe Manana +Signed-off-by: David Sterba +Signed-off-by: Sasha Levin +--- + fs/btrfs/disk-io.c | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c +index e4eda8b0f9381..cc8d736937012 100644 +--- a/fs/btrfs/disk-io.c ++++ b/fs/btrfs/disk-io.c +@@ -4356,6 +4356,19 @@ void __cold close_ctree(struct btrfs_fs_info *fs_info) + */ + btrfs_flush_workqueue(fs_info->delalloc_workers); + ++ /* ++ * We can have ordered extents getting their last reference dropped from ++ * the fs_info->workers queue because for async writes for data bios we ++ * queue a work for that queue, at btrfs_wq_submit_bio(), that runs ++ * run_one_async_done() which calls btrfs_bio_end_io() in case the bio ++ * has an error, and that later function can do the final ++ * btrfs_put_ordered_extent() on the ordered extent attached to the bio, ++ * which adds a delayed iput for the inode. So we must flush the queue ++ * so that we don't have delayed iputs after committing the current ++ * transaction below and stopping the cleaner and transaction kthreads. ++ */ ++ btrfs_flush_workqueue(fs_info->workers); ++ + /* + * When finishing a compressed write bio we schedule a work queue item + * to finish an ordered extent - btrfs_finish_compressed_write_work() +-- +2.39.5 + diff --git a/queue-6.14/btrfs-get-zone-unusable-bytes-while-holding-lock-at-.patch b/queue-6.14/btrfs-get-zone-unusable-bytes-while-holding-lock-at-.patch new file mode 100644 index 0000000000..55113904bf --- /dev/null +++ b/queue-6.14/btrfs-get-zone-unusable-bytes-while-holding-lock-at-.patch @@ -0,0 +1,68 @@ +From 36608c3c5c389dd40cb9e5a4c1c1147204c62374 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 21 Feb 2025 16:12:15 +0000 +Subject: btrfs: get zone unusable bytes while holding lock at + btrfs_reclaim_bgs_work() + +From: Filipe Manana + +[ Upstream commit 1283b8c125a83bf7a7dbe90c33d3472b6d7bf612 ] + +At btrfs_reclaim_bgs_work(), we are grabbing a block group's zone unusable +bytes while not under the protection of the block group's spinlock, so +this can trigger race reports from KCSAN (or similar tools) since that +field is typically updated while holding the lock, such as at +__btrfs_add_free_space_zoned() for example. + +Fix this by grabbing the zone unusable bytes while we are still in the +critical section holding the block group's spinlock, which is right above +where we are currently grabbing it. + +Reviewed-by: Johannes Thumshirn +Signed-off-by: Filipe Manana +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Signed-off-by: Sasha Levin +--- + fs/btrfs/block-group.c | 18 +++++++++++------- + 1 file changed, 11 insertions(+), 7 deletions(-) + +diff --git a/fs/btrfs/block-group.c b/fs/btrfs/block-group.c +index b96b235943344..b14faa1d57b8c 100644 +--- a/fs/btrfs/block-group.c ++++ b/fs/btrfs/block-group.c +@@ -1888,6 +1888,17 @@ void btrfs_reclaim_bgs_work(struct work_struct *work) + up_write(&space_info->groups_sem); + goto next; + } ++ ++ /* ++ * Cache the zone_unusable value before turning the block group ++ * to read only. As soon as the block group is read only it's ++ * zone_unusable value gets moved to the block group's read-only ++ * bytes and isn't available for calculations anymore. We also ++ * cache it before unlocking the block group, to prevent races ++ * (reports from KCSAN and such tools) with tasks updating it. ++ */ ++ zone_unusable = bg->zone_unusable; ++ + spin_unlock(&bg->lock); + spin_unlock(&space_info->lock); + +@@ -1904,13 +1915,6 @@ void btrfs_reclaim_bgs_work(struct work_struct *work) + goto next; + } + +- /* +- * Cache the zone_unusable value before turning the block group +- * to read only. As soon as the blog group is read only it's +- * zone_unusable value gets moved to the block group's read-only +- * bytes and isn't available for calculations anymore. +- */ +- zone_unusable = bg->zone_unusable; + ret = inc_block_group_ro(bg, 0); + up_write(&space_info->groups_sem); + if (ret < 0) +-- +2.39.5 + diff --git a/queue-6.14/btrfs-handle-empty-eb-folios-in-num_extent_folios.patch b/queue-6.14/btrfs-handle-empty-eb-folios-in-num_extent_folios.patch new file mode 100644 index 0000000000..8de81bd590 --- /dev/null +++ b/queue-6.14/btrfs-handle-empty-eb-folios-in-num_extent_folios.patch @@ -0,0 +1,39 @@ +From 7db5ab545e46d9ee68658adac32d2164c6297f91 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 25 Apr 2025 12:47:50 -0700 +Subject: btrfs: handle empty eb->folios in num_extent_folios() + +From: Boris Burkov + +[ Upstream commit d6fe0c69b3aa5c985380b794bdf8e6e9b1811e60 ] + +num_extent_folios() unconditionally calls folio_order() on +eb->folios[0]. If that is NULL this will be a segfault. It is reasonable +for it to return 0 as the number of folios in the eb when the first +entry is NULL, so do that instead. + +Reviewed-by: Qu Wenruo +Signed-off-by: Boris Burkov +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Signed-off-by: Sasha Levin +--- + fs/btrfs/extent_io.h | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/fs/btrfs/extent_io.h b/fs/btrfs/extent_io.h +index 6c5328bfabc22..2aefc64cdd295 100644 +--- a/fs/btrfs/extent_io.h ++++ b/fs/btrfs/extent_io.h +@@ -297,6 +297,8 @@ static inline int num_extent_pages(const struct extent_buffer *eb) + */ + static inline int num_extent_folios(const struct extent_buffer *eb) + { ++ if (!eb->folios[0]) ++ return 0; + if (folio_order(eb->folios[0])) + return 1; + return num_extent_pages(eb); +-- +2.39.5 + diff --git a/queue-6.14/btrfs-make-btrfs_discard_workfn-block_group-ref-expl.patch b/queue-6.14/btrfs-make-btrfs_discard_workfn-block_group-ref-expl.patch new file mode 100644 index 0000000000..6cfd3f77ad --- /dev/null +++ b/queue-6.14/btrfs-make-btrfs_discard_workfn-block_group-ref-expl.patch @@ -0,0 +1,106 @@ +From e9dd737ab199bd7a989845fb9ed3b9f5d9938caf Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 3 Mar 2025 15:01:05 -0800 +Subject: btrfs: make btrfs_discard_workfn() block_group ref explicit + +From: Boris Burkov + +[ Upstream commit 895c6721d310c036dcfebb5ab845822229fa35eb ] + +Currently, the async discard machinery owns a ref to the block_group +when the block_group is queued on a discard list. However, to handle +races with discard cancellation and the discard workfn, we have a +specific logic to detect that the block_group is *currently* running in +the workfn, to protect the workfn's usage amidst cancellation. + +As far as I can tell, this doesn't have any overt bugs (though +finish_discard_pass() and remove_from_discard_list() racing can have a +surprising outcome for the caller of remove_from_discard_list() in that +it is again added at the end). + +But it is needlessly complicated to rely on locking and the nullity of +discard_ctl->block_group. Simplify this significantly by just taking a +refcount while we are in the workfn and unconditionally drop it in both +the remove and workfn paths, regardless of if they race. + +Reviewed-by: Filipe Manana +Signed-off-by: Boris Burkov +Signed-off-by: David Sterba +Signed-off-by: Sasha Levin +--- + fs/btrfs/discard.c | 34 ++++++++++++++++------------------ + 1 file changed, 16 insertions(+), 18 deletions(-) + +diff --git a/fs/btrfs/discard.c b/fs/btrfs/discard.c +index e9cdc1759dada..de23c4b3515e5 100644 +--- a/fs/btrfs/discard.c ++++ b/fs/btrfs/discard.c +@@ -168,13 +168,7 @@ static bool remove_from_discard_list(struct btrfs_discard_ctl *discard_ctl, + block_group->discard_eligible_time = 0; + queued = !list_empty(&block_group->discard_list); + list_del_init(&block_group->discard_list); +- /* +- * If the block group is currently running in the discard workfn, we +- * don't want to deref it, since it's still being used by the workfn. +- * The workfn will notice this case and deref the block group when it is +- * finished. +- */ +- if (queued && !running) ++ if (queued) + btrfs_put_block_group(block_group); + + spin_unlock(&discard_ctl->lock); +@@ -273,9 +267,10 @@ static struct btrfs_block_group *peek_discard_list( + block_group->discard_cursor = block_group->start; + block_group->discard_state = BTRFS_DISCARD_EXTENTS; + } +- discard_ctl->block_group = block_group; + } + if (block_group) { ++ btrfs_get_block_group(block_group); ++ discard_ctl->block_group = block_group; + *discard_state = block_group->discard_state; + *discard_index = block_group->discard_index; + } +@@ -506,9 +501,20 @@ static void btrfs_discard_workfn(struct work_struct *work) + + block_group = peek_discard_list(discard_ctl, &discard_state, + &discard_index, now); +- if (!block_group || !btrfs_run_discard_work(discard_ctl)) ++ if (!block_group) + return; ++ if (!btrfs_run_discard_work(discard_ctl)) { ++ spin_lock(&discard_ctl->lock); ++ btrfs_put_block_group(block_group); ++ discard_ctl->block_group = NULL; ++ spin_unlock(&discard_ctl->lock); ++ return; ++ } + if (now < block_group->discard_eligible_time) { ++ spin_lock(&discard_ctl->lock); ++ btrfs_put_block_group(block_group); ++ discard_ctl->block_group = NULL; ++ spin_unlock(&discard_ctl->lock); + btrfs_discard_schedule_work(discard_ctl, false); + return; + } +@@ -560,15 +566,7 @@ static void btrfs_discard_workfn(struct work_struct *work) + spin_lock(&discard_ctl->lock); + discard_ctl->prev_discard = trimmed; + discard_ctl->prev_discard_time = now; +- /* +- * If the block group was removed from the discard list while it was +- * running in this workfn, then we didn't deref it, since this function +- * still owned that reference. But we set the discard_ctl->block_group +- * back to NULL, so we can use that condition to know that now we need +- * to deref the block_group. +- */ +- if (discard_ctl->block_group == NULL) +- btrfs_put_block_group(block_group); ++ btrfs_put_block_group(block_group); + discard_ctl->block_group = NULL; + __btrfs_discard_schedule_work(discard_ctl, now, false); + spin_unlock(&discard_ctl->lock); +-- +2.39.5 + diff --git a/queue-6.14/btrfs-prevent-inline-data-extents-read-from-touching.patch b/queue-6.14/btrfs-prevent-inline-data-extents-read-from-touching.patch new file mode 100644 index 0000000000..9cdb02765d --- /dev/null +++ b/queue-6.14/btrfs-prevent-inline-data-extents-read-from-touching.patch @@ -0,0 +1,121 @@ +From 6a2d904623a8d1711b6b5065845d52cb3f2be60a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 15 Nov 2024 19:15:34 +1030 +Subject: btrfs: prevent inline data extents read from touching blocks beyond + its range + +From: Qu Wenruo + +[ Upstream commit 1a5b5668d711d3d1ef447446beab920826decec3 ] + +Currently reading an inline data extent will zero out the remaining +range in the page. + +This is not yet causing problems even for block size < page size +(subpage) cases because: + +1) An inline data extent always starts at file offset 0 + Meaning at page read, we always read the inline extent first, before + any other blocks in the page. Then later blocks are properly read out + and re-fill the zeroed out ranges. + +2) Currently btrfs will read out the whole page if a buffered write is + not page aligned + So a page is either fully uptodate at buffered write time (covers the + whole page), or we will read out the whole page first. + Meaning there is nothing to lose for such an inline extent read. + +But it's still not ideal: + +- We're zeroing out the page twice + Once done by read_inline_extent()/uncompress_inline(), once done by + btrfs_do_readpage() for ranges beyond i_size. + +- We're touching blocks that don't belong to the inline extent + In the incoming patches, we can have a partial uptodate folio, of + which some dirty blocks can exist while the page is not fully uptodate: + + The page size is 16K and block size is 4K: + + 0 4K 8K 12K 16K + | | |/////////| | + + And range [8K, 12K) is dirtied by a buffered write, the remaining + blocks are not uptodate. + + If range [0, 4K) contains an inline data extent, and we try to read + the whole page, the current behavior will overwrite range [8K, 12K) + with zero and cause data loss. + +So to make the behavior more consistent and in preparation for future +changes, limit the inline data extents read to only zero out the range +inside the first block, not the whole page. + +Reviewed-by: Filipe Manana +Signed-off-by: Qu Wenruo +Signed-off-by: David Sterba +Signed-off-by: Sasha Levin +--- + fs/btrfs/inode.c | 14 ++++++++------ + 1 file changed, 8 insertions(+), 6 deletions(-) + +diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c +index 9a648fb130230..a7136311a13c6 100644 +--- a/fs/btrfs/inode.c ++++ b/fs/btrfs/inode.c +@@ -6779,6 +6779,7 @@ static noinline int uncompress_inline(struct btrfs_path *path, + { + int ret; + struct extent_buffer *leaf = path->nodes[0]; ++ const u32 blocksize = leaf->fs_info->sectorsize; + char *tmp; + size_t max_size; + unsigned long inline_size; +@@ -6795,7 +6796,7 @@ static noinline int uncompress_inline(struct btrfs_path *path, + + read_extent_buffer(leaf, tmp, ptr, inline_size); + +- max_size = min_t(unsigned long, PAGE_SIZE, max_size); ++ max_size = min_t(unsigned long, blocksize, max_size); + ret = btrfs_decompress(compress_type, tmp, folio, 0, inline_size, + max_size); + +@@ -6807,14 +6808,15 @@ static noinline int uncompress_inline(struct btrfs_path *path, + * cover that region here. + */ + +- if (max_size < PAGE_SIZE) +- folio_zero_range(folio, max_size, PAGE_SIZE - max_size); ++ if (max_size < blocksize) ++ folio_zero_range(folio, max_size, blocksize - max_size); + kfree(tmp); + return ret; + } + + static int read_inline_extent(struct btrfs_path *path, struct folio *folio) + { ++ const u32 blocksize = path->nodes[0]->fs_info->sectorsize; + struct btrfs_file_extent_item *fi; + void *kaddr; + size_t copy_size; +@@ -6829,14 +6831,14 @@ static int read_inline_extent(struct btrfs_path *path, struct folio *folio) + if (btrfs_file_extent_compression(path->nodes[0], fi) != BTRFS_COMPRESS_NONE) + return uncompress_inline(path, folio, fi); + +- copy_size = min_t(u64, PAGE_SIZE, ++ copy_size = min_t(u64, blocksize, + btrfs_file_extent_ram_bytes(path->nodes[0], fi)); + kaddr = kmap_local_folio(folio, 0); + read_extent_buffer(path->nodes[0], kaddr, + btrfs_file_extent_inline_start(fi), copy_size); + kunmap_local(kaddr); +- if (copy_size < PAGE_SIZE) +- folio_zero_range(folio, copy_size, PAGE_SIZE - copy_size); ++ if (copy_size < blocksize) ++ folio_zero_range(folio, copy_size, blocksize - copy_size); + return 0; + } + +-- +2.39.5 + diff --git a/queue-6.14/btrfs-properly-limit-inline-data-extent-according-to.patch b/queue-6.14/btrfs-properly-limit-inline-data-extent-according-to.patch new file mode 100644 index 0000000000..4b1e518f0e --- /dev/null +++ b/queue-6.14/btrfs-properly-limit-inline-data-extent-according-to.patch @@ -0,0 +1,72 @@ +From ec02842137bdccb74ed331a1b0a335ee22eb179c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 25 Feb 2025 14:30:44 +1030 +Subject: btrfs: properly limit inline data extent according to block size + +From: Qu Wenruo + +[ Upstream commit 23019d3e6617a8ec99a8d2f5947aa3dd8a74a1b8 ] + +Btrfs utilizes inline data extent for the following cases: + +- Regular small files +- Symlinks + +And "btrfs check" detects any file extents that are too large as an +error. + +It's not a problem for 4K block size, but for the incoming smaller +block sizes (2K), it can cause problems due to bad limits: + +- Non-compressed inline data extents + We do not allow a non-compressed inline data extent to be as large as + block size. + +- Symlinks + Currently the only real limit on symlinks are 4K, which can be larger + than 2K block size. + +These will result btrfs-check to report too large file extents. + +Fix it by adding proper size checks for the above cases. + +Signed-off-by: Qu Wenruo +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Signed-off-by: Sasha Levin +--- + fs/btrfs/inode.c | 11 ++++++++++- + 1 file changed, 10 insertions(+), 1 deletion(-) + +diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c +index a06fca7934d55..9a648fb130230 100644 +--- a/fs/btrfs/inode.c ++++ b/fs/btrfs/inode.c +@@ -583,6 +583,10 @@ static bool can_cow_file_range_inline(struct btrfs_inode *inode, + if (size > fs_info->sectorsize) + return false; + ++ /* We do not allow a non-compressed extent to be as large as block size. */ ++ if (data_len >= fs_info->sectorsize) ++ return false; ++ + /* We cannot exceed the maximum inline data size. */ + if (data_len > BTRFS_MAX_INLINE_DATA_SIZE(fs_info)) + return false; +@@ -8671,7 +8675,12 @@ static int btrfs_symlink(struct mnt_idmap *idmap, struct inode *dir, + struct extent_buffer *leaf; + + name_len = strlen(symname); +- if (name_len > BTRFS_MAX_INLINE_DATA_SIZE(fs_info)) ++ /* ++ * Symlinks utilize uncompressed inline extent data, which should not ++ * reach block size. ++ */ ++ if (name_len > BTRFS_MAX_INLINE_DATA_SIZE(fs_info) || ++ name_len >= fs_info->sectorsize) + return -ENAMETOOLONG; + + inode = new_inode(dir->i_sb); +-- +2.39.5 + diff --git a/queue-6.14/btrfs-run-btrfs_error_commit_super-early.patch b/queue-6.14/btrfs-run-btrfs_error_commit_super-early.patch new file mode 100644 index 0000000000..b579601c43 --- /dev/null +++ b/queue-6.14/btrfs-run-btrfs_error_commit_super-early.patch @@ -0,0 +1,98 @@ +From 92b4068394e97e1a7647cdfd139395727c70b526 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 7 Mar 2025 14:36:10 +1030 +Subject: btrfs: run btrfs_error_commit_super() early + +From: Qu Wenruo + +[ Upstream commit df94a342efb451deb0e32b495d1d6cd4bb3a1648 ] + +[BUG] +Even after all the error fixes related the +"ASSERT(list_empty(&fs_info->delayed_iputs));" in close_ctree(), I can +still hit it reliably with my experimental 2K block size. + +[CAUSE] +In my case, all the error is triggered after the fs is already in error +status. + +I find the following call trace to be the cause of race: + + Main thread | endio_write_workers +---------------------------------------------+--------------------------- +close_ctree() | +|- btrfs_error_commit_super() | +| |- btrfs_cleanup_transaction() | +| | |- btrfs_destroy_all_ordered_extents() | +| | |- btrfs_wait_ordered_roots() | +| |- btrfs_run_delayed_iputs() | +| | btrfs_finish_ordered_io() +| | |- btrfs_put_ordered_extent() +| | |- btrfs_add_delayed_iput() +|- ASSERT(list_empty(delayed_iputs)) | + !!! Triggered !!! + +The root cause is that, btrfs_wait_ordered_roots() only wait for +ordered extents to finish their IOs, not to wait for them to finish and +removed. + +[FIX] +Since btrfs_error_commit_super() will flush and wait for all ordered +extents, it should be executed early, before we start flushing the +workqueues. + +And since btrfs_error_commit_super() now runs early, there is no need to +run btrfs_run_delayed_iputs() inside it, so just remove the +btrfs_run_delayed_iputs() call from btrfs_error_commit_super(). + +Reviewed-by: Filipe Manana +Signed-off-by: Qu Wenruo +Signed-off-by: David Sterba +Signed-off-by: Sasha Levin +--- + fs/btrfs/disk-io.c | 15 ++++++++------- + 1 file changed, 8 insertions(+), 7 deletions(-) + +diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c +index ca821e5966bd3..e4eda8b0f9381 100644 +--- a/fs/btrfs/disk-io.c ++++ b/fs/btrfs/disk-io.c +@@ -4328,6 +4328,14 @@ void __cold close_ctree(struct btrfs_fs_info *fs_info) + /* clear out the rbtree of defraggable inodes */ + btrfs_cleanup_defrag_inodes(fs_info); + ++ /* ++ * Handle the error fs first, as it will flush and wait for all ordered ++ * extents. This will generate delayed iputs, thus we want to handle ++ * it first. ++ */ ++ if (unlikely(BTRFS_FS_ERROR(fs_info))) ++ btrfs_error_commit_super(fs_info); ++ + /* + * Wait for any fixup workers to complete. + * If we don't wait for them here and they are still running by the time +@@ -4418,9 +4426,6 @@ void __cold close_ctree(struct btrfs_fs_info *fs_info) + btrfs_err(fs_info, "commit super ret %d", ret); + } + +- if (BTRFS_FS_ERROR(fs_info)) +- btrfs_error_commit_super(fs_info); +- + kthread_stop(fs_info->transaction_kthread); + kthread_stop(fs_info->cleaner_kthread); + +@@ -4543,10 +4548,6 @@ static void btrfs_error_commit_super(struct btrfs_fs_info *fs_info) + /* cleanup FS via transaction */ + btrfs_cleanup_transaction(fs_info); + +- mutex_lock(&fs_info->cleaner_mutex); +- btrfs_run_delayed_iputs(fs_info); +- mutex_unlock(&fs_info->cleaner_mutex); +- + down_write(&fs_info->cleanup_work_sem); + up_write(&fs_info->cleanup_work_sem); + } +-- +2.39.5 + diff --git a/queue-6.14/btrfs-send-return-enametoolong-when-attempting-a-pat.patch b/queue-6.14/btrfs-send-return-enametoolong-when-attempting-a-pat.patch new file mode 100644 index 0000000000..246e872912 --- /dev/null +++ b/queue-6.14/btrfs-send-return-enametoolong-when-attempting-a-pat.patch @@ -0,0 +1,46 @@ +From 2d6a6727aa46abc99e5caa90478efe96eace8f86 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Feb 2025 13:09:25 +0000 +Subject: btrfs: send: return -ENAMETOOLONG when attempting a path that is too + long + +From: Filipe Manana + +[ Upstream commit a77749b3e21813566cea050bbb3414ae74562eba ] + +When attempting to build a too long path we are currently returning +-ENOMEM, which is very odd and misleading. So update fs_path_ensure_buf() +to return -ENAMETOOLONG instead. Also, while at it, move the WARN_ON() +into the if statement's expression, as it makes it clear what is being +tested and also has the effect of adding 'unlikely' to the statement, +which allows the compiler to generate better code as this condition is +never expected to happen. + +Signed-off-by: Filipe Manana +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Signed-off-by: Sasha Levin +--- + fs/btrfs/send.c | 6 ++---- + 1 file changed, 2 insertions(+), 4 deletions(-) + +diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c +index f437138fefbc5..bb8a0945b0fd3 100644 +--- a/fs/btrfs/send.c ++++ b/fs/btrfs/send.c +@@ -487,10 +487,8 @@ static int fs_path_ensure_buf(struct fs_path *p, int len) + if (p->buf_len >= len) + return 0; + +- if (len > PATH_MAX) { +- WARN_ON(1); +- return -ENOMEM; +- } ++ if (WARN_ON(len > PATH_MAX)) ++ return -ENAMETOOLONG; + + path_len = p->end - p->start; + old_buf_len = p->buf_len; +-- +2.39.5 + diff --git a/queue-6.14/btrfs-tree-checker-adjust-error-code-for-header-leve.patch b/queue-6.14/btrfs-tree-checker-adjust-error-code-for-header-leve.patch new file mode 100644 index 0000000000..41e389bd47 --- /dev/null +++ b/queue-6.14/btrfs-tree-checker-adjust-error-code-for-header-leve.patch @@ -0,0 +1,38 @@ +From fe0bd02d7a5156ff8edc67af7f606637ec353ef4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 4 Apr 2025 20:19:41 +0200 +Subject: btrfs: tree-checker: adjust error code for header level check + +From: David Sterba + +[ Upstream commit f1ab0171e9be96fd530329fa54761cff5e09ea95 ] + +The whole tree checker returns EUCLEAN, except the one check in +btrfs_verify_level_key(). This was inherited from the function that was +moved from disk-io.c in 2cac5af16537 ("btrfs: move +btrfs_verify_level_key into tree-checker.c") but this should be unified +with the rest. + +Reviewed-by: Qu Wenruo +Signed-off-by: David Sterba +Signed-off-by: Sasha Levin +--- + fs/btrfs/tree-checker.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/fs/btrfs/tree-checker.c b/fs/btrfs/tree-checker.c +index 43979891f7c89..2b66a6130269a 100644 +--- a/fs/btrfs/tree-checker.c ++++ b/fs/btrfs/tree-checker.c +@@ -2235,7 +2235,7 @@ int btrfs_verify_level_key(struct extent_buffer *eb, + btrfs_err(fs_info, + "tree level mismatch detected, bytenr=%llu level expected=%u has=%u", + eb->start, check->level, found_level); +- return -EIO; ++ return -EUCLEAN; + } + + if (!check->has_first_key) +-- +2.39.5 + diff --git a/queue-6.14/btrfs-zoned-exit-btrfs_can_activate_zone-if-btrfs_fs.patch b/queue-6.14/btrfs-zoned-exit-btrfs_can_activate_zone-if-btrfs_fs.patch new file mode 100644 index 0000000000..c364ff0f82 --- /dev/null +++ b/queue-6.14/btrfs-zoned-exit-btrfs_can_activate_zone-if-btrfs_fs.patch @@ -0,0 +1,40 @@ +From 1136d333d91088ecf2d5189367540a84e60449a0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 12 Feb 2025 15:05:00 +0100 +Subject: btrfs: zoned: exit btrfs_can_activate_zone if + BTRFS_FS_NEED_ZONE_FINISH is set + +From: Johannes Thumshirn + +[ Upstream commit 26b38e28162ef4ceb1e0482299820fbbd7dbcd92 ] + +If BTRFS_FS_NEED_ZONE_FINISH is already set for the whole filesystem, exit +early in btrfs_can_activate_zone(). There's no need to check if +BTRFS_FS_NEED_ZONE_FINISH needs to be set if it is already set. + +Reviewed-by: Naohiro Aota +Signed-off-by: Johannes Thumshirn +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Signed-off-by: Sasha Levin +--- + fs/btrfs/zoned.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/fs/btrfs/zoned.c b/fs/btrfs/zoned.c +index f39656668967c..4a3e02b49f295 100644 +--- a/fs/btrfs/zoned.c ++++ b/fs/btrfs/zoned.c +@@ -2344,6 +2344,9 @@ bool btrfs_can_activate_zone(struct btrfs_fs_devices *fs_devices, u64 flags) + if (!btrfs_is_zoned(fs_info)) + return true; + ++ if (test_bit(BTRFS_FS_NEED_ZONE_FINISH, &fs_info->flags)) ++ return false; ++ + /* Check if there is a device with active zones left */ + mutex_lock(&fs_info->chunk_mutex); + spin_lock(&fs_info->zone_active_bgs_lock); +-- +2.39.5 + diff --git a/queue-6.14/can-c_can-use-of_property_present-to-test-existence-.patch b/queue-6.14/can-c_can-use-of_property_present-to-test-existence-.patch new file mode 100644 index 0000000000..4a5440ae55 --- /dev/null +++ b/queue-6.14/can-c_can-use-of_property_present-to-test-existence-.patch @@ -0,0 +1,38 @@ +From 746254ec92f6b9f536016342522ce0be0451ca6f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 12 Feb 2025 21:23:14 +0100 +Subject: can: c_can: Use of_property_present() to test existence of DT + property + +From: Krzysztof Kozlowski + +[ Upstream commit ab1bc2290fd8311d49b87c29f1eb123fcb581bee ] + +of_property_read_bool() should be used only on boolean properties. + +Cc: Rob Herring +Signed-off-by: Krzysztof Kozlowski +Reviewed-by: Vincent Mailhol +Link: https://patch.msgid.link/20250212-syscon-phandle-args-can-v2-3-ac9a1253396b@linaro.org +Signed-off-by: Marc Kleine-Budde +Signed-off-by: Sasha Levin +--- + drivers/net/can/c_can/c_can_platform.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/can/c_can/c_can_platform.c b/drivers/net/can/c_can/c_can_platform.c +index 399844809bbea..bb6071a758f36 100644 +--- a/drivers/net/can/c_can/c_can_platform.c ++++ b/drivers/net/can/c_can/c_can_platform.c +@@ -324,7 +324,7 @@ static int c_can_plat_probe(struct platform_device *pdev) + /* Check if we need custom RAMINIT via syscon. Mostly for TI + * platforms. Only supported with DT boot. + */ +- if (np && of_property_read_bool(np, "syscon-raminit")) { ++ if (np && of_property_present(np, "syscon-raminit")) { + u32 id; + struct c_can_raminit *raminit = &priv->raminit_sys; + +-- +2.39.5 + diff --git a/queue-6.14/cgroup-fix-compilation-issue-due-to-cgroup_mutex-not.patch b/queue-6.14/cgroup-fix-compilation-issue-due-to-cgroup_mutex-not.patch new file mode 100644 index 0000000000..6af47b2509 --- /dev/null +++ b/queue-6.14/cgroup-fix-compilation-issue-due-to-cgroup_mutex-not.patch @@ -0,0 +1,48 @@ +From b995b20e853ec049933bcef95531354cee783bb3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 17 Apr 2025 07:30:00 +0000 +Subject: cgroup: Fix compilation issue due to cgroup_mutex not being exported +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: gaoxu + +[ Upstream commit 87c259a7a359e73e6c52c68fcbec79988999b4e6 ] + +When adding folio_memcg function call in the zram module for +Android16-6.12, the following error occurs during compilation: +ERROR: modpost: "cgroup_mutex" [../soc-repo/zram.ko] undefined! + +This error is caused by the indirect call to lockdep_is_held(&cgroup_mutex) +within folio_memcg. The export setting for cgroup_mutex is controlled by +the CONFIG_PROVE_RCU macro. If CONFIG_LOCKDEP is enabled while +CONFIG_PROVE_RCU is not, this compilation error will occur. + +To resolve this issue, add a parallel macro CONFIG_LOCKDEP control to +ensure cgroup_mutex is properly exported when needed. + +Signed-off-by: gao xu +Acked-by: Michal Koutný +Signed-off-by: Tejun Heo +Signed-off-by: Sasha Levin +--- + kernel/cgroup/cgroup.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/kernel/cgroup/cgroup.c b/kernel/cgroup/cgroup.c +index 68d58753c75c3..660d27a0cb3d4 100644 +--- a/kernel/cgroup/cgroup.c ++++ b/kernel/cgroup/cgroup.c +@@ -90,7 +90,7 @@ + DEFINE_MUTEX(cgroup_mutex); + DEFINE_SPINLOCK(css_set_lock); + +-#ifdef CONFIG_PROVE_RCU ++#if (defined CONFIG_PROVE_RCU || defined CONFIG_LOCKDEP) + EXPORT_SYMBOL_GPL(cgroup_mutex); + EXPORT_SYMBOL_GPL(css_set_lock); + #endif +-- +2.39.5 + diff --git a/queue-6.14/cgroup-rstat-avoid-disabling-irqs-for-o-num_cpu.patch b/queue-6.14/cgroup-rstat-avoid-disabling-irqs-for-o-num_cpu.patch new file mode 100644 index 0000000000..d74b49ddb3 --- /dev/null +++ b/queue-6.14/cgroup-rstat-avoid-disabling-irqs-for-o-num_cpu.patch @@ -0,0 +1,111 @@ +From b13fe3febaa9ce6e118034d99e829f0052b5317d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 19 Mar 2025 00:13:30 -0700 +Subject: cgroup/rstat: avoid disabling irqs for O(num_cpu) +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Eric Dumazet + +[ Upstream commit 0efc297a3c4974dbd609ee36fc6345720b6ca735 ] + +cgroup_rstat_flush_locked() grabs the irq safe cgroup_rstat_lock while +iterating all possible cpus. It only drops the lock if there is +scheduler or spin lock contention. If neither, then interrupts can be +disabled for a long time. On large machines this can disable interrupts +for a long enough time to drop network packets. On 400+ CPU machines +I've seen interrupt disabled for over 40 msec. + +Prevent rstat from disabling interrupts while processing all possible +cpus. Instead drop and reacquire cgroup_rstat_lock for each cpu. This +approach was previously discussed in +https://lore.kernel.org/lkml/ZBz%2FV5a7%2F6PZeM7S@slm.duckdns.org/, +though this was in the context of an non-irq rstat spin lock. + +Benchmark this change with: +1) a single stat_reader process with 400 threads, each reading a test + memcg's memory.stat repeatedly for 10 seconds. +2) 400 memory hog processes running in the test memcg and repeatedly + charging memory until oom killed. Then they repeat charging and oom + killing. + +v6.14-rc6 with CONFIG_IRQSOFF_TRACER with stat_reader and hogs, finds +interrupts are disabled by rstat for 45341 usec: + # => started at: _raw_spin_lock_irq + # => ended at: cgroup_rstat_flush + # + # + # _------=> CPU# + # / _-----=> irqs-off/BH-disabled + # | / _----=> need-resched + # || / _---=> hardirq/softirq + # ||| / _--=> preempt-depth + # |||| / _-=> migrate-disable + # ||||| / delay + # cmd pid |||||| time | caller + # \ / |||||| \ | / + stat_rea-96532 52d.... 0us*: _raw_spin_lock_irq + stat_rea-96532 52d.... 45342us : cgroup_rstat_flush + stat_rea-96532 52d.... 45342us : tracer_hardirqs_on <-cgroup_rstat_flush + stat_rea-96532 52d.... 45343us : + => memcg1_stat_format + => memory_stat_format + => memory_stat_show + => seq_read_iter + => vfs_read + => ksys_read + => do_syscall_64 + => entry_SYSCALL_64_after_hwframe + +With this patch the CONFIG_IRQSOFF_TRACER doesn't find rstat to be the +longest holder. The longest irqs-off holder has irqs disabled for +4142 usec, a huge reduction from previous 45341 usec rstat finding. + +Running stat_reader memory.stat reader for 10 seconds: +- without memory hogs: 9.84M accesses => 12.7M accesses +- with memory hogs: 9.46M accesses => 11.1M accesses +The throughput of memory.stat access improves. + +The mode of memory.stat access latency after grouping by of 2 buckets: +- without memory hogs: 64 usec => 16 usec +- with memory hogs: 64 usec => 8 usec +The memory.stat latency improves. + +Signed-off-by: Eric Dumazet +Signed-off-by: Greg Thelen +Tested-by: Greg Thelen +Acked-by: Michal Koutný +Reviewed-by: Yosry Ahmed +Signed-off-by: Tejun Heo +Signed-off-by: Sasha Levin +--- + kernel/cgroup/rstat.c | 12 +++++------- + 1 file changed, 5 insertions(+), 7 deletions(-) + +diff --git a/kernel/cgroup/rstat.c b/kernel/cgroup/rstat.c +index 3e01781aeb7bd..c4ce2f5a9745f 100644 +--- a/kernel/cgroup/rstat.c ++++ b/kernel/cgroup/rstat.c +@@ -323,13 +323,11 @@ static void cgroup_rstat_flush_locked(struct cgroup *cgrp) + rcu_read_unlock(); + } + +- /* play nice and yield if necessary */ +- if (need_resched() || spin_needbreak(&cgroup_rstat_lock)) { +- __cgroup_rstat_unlock(cgrp, cpu); +- if (!cond_resched()) +- cpu_relax(); +- __cgroup_rstat_lock(cgrp, cpu); +- } ++ /* play nice and avoid disabling interrupts for a long time */ ++ __cgroup_rstat_unlock(cgrp, cpu); ++ if (!cond_resched()) ++ cpu_relax(); ++ __cgroup_rstat_lock(cgrp, cpu); + } + } + +-- +2.39.5 + diff --git a/queue-6.14/cifs-add-fallback-for-smb2-create-without-file_read_.patch b/queue-6.14/cifs-add-fallback-for-smb2-create-without-file_read_.patch new file mode 100644 index 0000000000..35c8896f06 --- /dev/null +++ b/queue-6.14/cifs-add-fallback-for-smb2-create-without-file_read_.patch @@ -0,0 +1,65 @@ +From c229d8ebe8717878fecdedfc30ccefa904523f0c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 9 Dec 2024 20:44:23 +0100 +Subject: cifs: Add fallback for SMB2 CREATE without FILE_READ_ATTRIBUTES +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Pali Rohár + +[ Upstream commit e255612b5ed9f179abe8196df7c2ba09dd227900 ] + +Some operations, like WRITE, does not require FILE_READ_ATTRIBUTES access. + +So when FILE_READ_ATTRIBUTES is not explicitly requested for +smb2_open_file() then first try to do SMB2 CREATE with FILE_READ_ATTRIBUTES +access (like it was before) and then fallback to SMB2 CREATE without +FILE_READ_ATTRIBUTES access (less common case). + +This change allows to complete WRITE operation to a file when it does not +grant FILE_READ_ATTRIBUTES permission and its parent directory does not +grant READ_DATA permission (parent directory READ_DATA is implicit grant of +child FILE_READ_ATTRIBUTES permission). + +Signed-off-by: Pali Rohár +Signed-off-by: Steve French +Signed-off-by: Sasha Levin +--- + fs/smb/client/smb2file.c | 11 ++++++++++- + 1 file changed, 10 insertions(+), 1 deletion(-) + +diff --git a/fs/smb/client/smb2file.c b/fs/smb/client/smb2file.c +index d609a20fb98a9..2d726e9b950cf 100644 +--- a/fs/smb/client/smb2file.c ++++ b/fs/smb/client/smb2file.c +@@ -152,16 +152,25 @@ int smb2_open_file(const unsigned int xid, struct cifs_open_parms *oparms, __u32 + int err_buftype = CIFS_NO_BUFFER; + struct cifs_fid *fid = oparms->fid; + struct network_resiliency_req nr_ioctl_req; ++ bool retry_without_read_attributes = false; + + smb2_path = cifs_convert_path_to_utf16(oparms->path, oparms->cifs_sb); + if (smb2_path == NULL) + return -ENOMEM; + +- oparms->desired_access |= FILE_READ_ATTRIBUTES; ++ if (!(oparms->desired_access & FILE_READ_ATTRIBUTES)) { ++ oparms->desired_access |= FILE_READ_ATTRIBUTES; ++ retry_without_read_attributes = true; ++ } + smb2_oplock = SMB2_OPLOCK_LEVEL_BATCH; + + rc = SMB2_open(xid, oparms, smb2_path, &smb2_oplock, smb2_data, NULL, &err_iov, + &err_buftype); ++ if (rc == -EACCES && retry_without_read_attributes) { ++ oparms->desired_access &= ~FILE_READ_ATTRIBUTES; ++ rc = SMB2_open(xid, oparms, smb2_path, &smb2_oplock, smb2_data, NULL, &err_iov, ++ &err_buftype); ++ } + if (rc && data) { + struct smb2_hdr *hdr = err_iov.iov_base; + +-- +2.39.5 + diff --git a/queue-6.14/cifs-add-validation-check-for-the-fields-in-smb_aces.patch b/queue-6.14/cifs-add-validation-check-for-the-fields-in-smb_aces.patch new file mode 100644 index 0000000000..122c149a7c --- /dev/null +++ b/queue-6.14/cifs-add-validation-check-for-the-fields-in-smb_aces.patch @@ -0,0 +1,58 @@ +From 8da7c0a2c40b8465a0460f463748009216f92eb7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 12 Feb 2025 17:52:19 +0900 +Subject: cifs: add validation check for the fields in smb_aces + +From: Namjae Jeon + +[ Upstream commit eeb827f2922eb07ffbf7d53569cc95b38272646f ] + +cifs.ko is missing validation check when accessing smb_aces. +This patch add validation check for the fields in smb_aces. + +Signed-off-by: Namjae Jeon +Signed-off-by: Steve French +Signed-off-by: Sasha Levin +--- + fs/smb/client/cifsacl.c | 17 ++++++++++++++++- + 1 file changed, 16 insertions(+), 1 deletion(-) + +diff --git a/fs/smb/client/cifsacl.c b/fs/smb/client/cifsacl.c +index 64bd68f750f84..f9d577f2d59bb 100644 +--- a/fs/smb/client/cifsacl.c ++++ b/fs/smb/client/cifsacl.c +@@ -811,7 +811,23 @@ static void parse_dacl(struct smb_acl *pdacl, char *end_of_acl, + return; + + for (i = 0; i < num_aces; ++i) { ++ if (end_of_acl - acl_base < acl_size) ++ break; ++ + ppace[i] = (struct smb_ace *) (acl_base + acl_size); ++ acl_base = (char *)ppace[i]; ++ acl_size = offsetof(struct smb_ace, sid) + ++ offsetof(struct smb_sid, sub_auth); ++ ++ if (end_of_acl - acl_base < acl_size || ++ ppace[i]->sid.num_subauth == 0 || ++ ppace[i]->sid.num_subauth > SID_MAX_SUB_AUTHORITIES || ++ (end_of_acl - acl_base < ++ acl_size + sizeof(__le32) * ppace[i]->sid.num_subauth) || ++ (le16_to_cpu(ppace[i]->size) < ++ acl_size + sizeof(__le32) * ppace[i]->sid.num_subauth)) ++ break; ++ + #ifdef CONFIG_CIFS_DEBUG2 + dump_ace(ppace[i], end_of_acl); + #endif +@@ -855,7 +871,6 @@ static void parse_dacl(struct smb_acl *pdacl, char *end_of_acl, + (void *)ppace[i], + sizeof(struct smb_ace)); */ + +- acl_base = (char *)ppace[i]; + acl_size = le16_to_cpu(ppace[i]->size); + } + +-- +2.39.5 + diff --git a/queue-6.14/cifs-check-if-server-supports-reparse-points-before-.patch b/queue-6.14/cifs-check-if-server-supports-reparse-points-before-.patch new file mode 100644 index 0000000000..f5dcd9deae --- /dev/null +++ b/queue-6.14/cifs-check-if-server-supports-reparse-points-before-.patch @@ -0,0 +1,97 @@ +From 6bd7988657340114d49927daacb198b872fcbe69 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 19 Oct 2024 13:34:18 +0200 +Subject: cifs: Check if server supports reparse points before using them +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Pali Rohár + +[ Upstream commit 6c06be908ca190e2d8feae1cf452d78598cd0b94 ] + +Do not attempt to query or create reparse point when server fs does not +support it. This will prevent creating unusable empty object on the server. + +Signed-off-by: Pali Rohár +Signed-off-by: Steve French +Signed-off-by: Sasha Levin +--- + fs/smb/client/cifssmb.c | 3 +++ + fs/smb/client/link.c | 3 ++- + fs/smb/client/smb2inode.c | 8 ++++++++ + fs/smb/client/smb2ops.c | 4 ++-- + 4 files changed, 15 insertions(+), 3 deletions(-) + +diff --git a/fs/smb/client/cifssmb.c b/fs/smb/client/cifssmb.c +index e90811f321944..53e3e8282cb2a 100644 +--- a/fs/smb/client/cifssmb.c ++++ b/fs/smb/client/cifssmb.c +@@ -2725,6 +2725,9 @@ int cifs_query_reparse_point(const unsigned int xid, + if (cap_unix(tcon->ses)) + return -EOPNOTSUPP; + ++ if (!(le32_to_cpu(tcon->fsAttrInfo.Attributes) & FILE_SUPPORTS_REPARSE_POINTS)) ++ return -EOPNOTSUPP; ++ + oparms = (struct cifs_open_parms) { + .tcon = tcon, + .cifs_sb = cifs_sb, +diff --git a/fs/smb/client/link.c b/fs/smb/client/link.c +index 34a026243287f..769752ad2c5ce 100644 +--- a/fs/smb/client/link.c ++++ b/fs/smb/client/link.c +@@ -643,7 +643,8 @@ cifs_symlink(struct mnt_idmap *idmap, struct inode *inode, + case CIFS_SYMLINK_TYPE_NATIVE: + case CIFS_SYMLINK_TYPE_NFS: + case CIFS_SYMLINK_TYPE_WSL: +- if (server->ops->create_reparse_symlink) { ++ if (server->ops->create_reparse_symlink && ++ (le32_to_cpu(pTcon->fsAttrInfo.Attributes) & FILE_SUPPORTS_REPARSE_POINTS)) { + rc = server->ops->create_reparse_symlink(xid, inode, + direntry, + pTcon, +diff --git a/fs/smb/client/smb2inode.c b/fs/smb/client/smb2inode.c +index 826b57a5a2a8d..e9fd3e204a6f4 100644 +--- a/fs/smb/client/smb2inode.c ++++ b/fs/smb/client/smb2inode.c +@@ -1273,6 +1273,14 @@ struct inode *smb2_get_reparse_inode(struct cifs_open_info_data *data, + int rc; + int i; + ++ /* ++ * If server filesystem does not support reparse points then do not ++ * attempt to create reparse point. This will prevent creating unusable ++ * empty object on the server. ++ */ ++ if (!(le32_to_cpu(tcon->fsAttrInfo.Attributes) & FILE_SUPPORTS_REPARSE_POINTS)) ++ return ERR_PTR(-EOPNOTSUPP); ++ + oparms = CIFS_OPARMS(cifs_sb, tcon, full_path, + SYNCHRONIZE | DELETE | + FILE_READ_ATTRIBUTES | +diff --git a/fs/smb/client/smb2ops.c b/fs/smb/client/smb2ops.c +index 6795970d4de6e..fbb3686292134 100644 +--- a/fs/smb/client/smb2ops.c ++++ b/fs/smb/client/smb2ops.c +@@ -5237,7 +5237,7 @@ static int smb2_make_node(unsigned int xid, struct inode *inode, + const char *full_path, umode_t mode, dev_t dev) + { + struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); +- int rc; ++ int rc = -EOPNOTSUPP; + + /* + * Check if mounted with mount parm 'sfu' mount parm. +@@ -5248,7 +5248,7 @@ static int smb2_make_node(unsigned int xid, struct inode *inode, + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) { + rc = cifs_sfu_make_node(xid, inode, dentry, tcon, + full_path, mode, dev); +- } else { ++ } else if (le32_to_cpu(tcon->fsAttrInfo.Attributes) & FILE_SUPPORTS_REPARSE_POINTS) { + rc = smb2_mknod_reparse(xid, inode, dentry, tcon, + full_path, mode, dev); + } +-- +2.39.5 + diff --git a/queue-6.14/cifs-fix-access_flags_to_smbopen_mode.patch b/queue-6.14/cifs-fix-access_flags_to_smbopen_mode.patch new file mode 100644 index 0000000000..9aa8a9b88a --- /dev/null +++ b/queue-6.14/cifs-fix-access_flags_to_smbopen_mode.patch @@ -0,0 +1,69 @@ +From f3854f7e9d4f1136b16f3327fa1ac3bda34a2e9e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 17 Nov 2024 11:50:18 +0100 +Subject: cifs: Fix access_flags_to_smbopen_mode +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Pali Rohár + +[ Upstream commit 6aa9f1c9cd09c1c39a35da4fe5f43446ec18ce1e ] + +When converting access_flags to SMBOPEN mode, check for all possible access +flags, not only GENERIC_READ and GENERIC_WRITE flags. + +Signed-off-by: Pali Rohár +Signed-off-by: Steve French +Signed-off-by: Sasha Levin +--- + fs/smb/client/cifssmb.c | 32 ++++++++++++++++++++++++-------- + 1 file changed, 24 insertions(+), 8 deletions(-) + +diff --git a/fs/smb/client/cifssmb.c b/fs/smb/client/cifssmb.c +index 4fc9485c5d91a..c2abe79f0dd3b 100644 +--- a/fs/smb/client/cifssmb.c ++++ b/fs/smb/client/cifssmb.c +@@ -1038,15 +1038,31 @@ static __u16 convert_disposition(int disposition) + static int + access_flags_to_smbopen_mode(const int access_flags) + { +- int masked_flags = access_flags & (GENERIC_READ | GENERIC_WRITE); +- +- if (masked_flags == GENERIC_READ) +- return SMBOPEN_READ; +- else if (masked_flags == GENERIC_WRITE) ++ /* ++ * SYSTEM_SECURITY grants both read and write access to SACL, treat is as read/write. ++ * MAXIMUM_ALLOWED grants as many access as possible, so treat it as read/write too. ++ * SYNCHRONIZE as is does not grant any specific access, so do not check its mask. ++ * If only SYNCHRONIZE bit is specified then fallback to read access. ++ */ ++ bool with_write_flags = access_flags & (FILE_WRITE_DATA | FILE_APPEND_DATA | FILE_WRITE_EA | ++ FILE_DELETE_CHILD | FILE_WRITE_ATTRIBUTES | DELETE | ++ WRITE_DAC | WRITE_OWNER | SYSTEM_SECURITY | ++ MAXIMUM_ALLOWED | GENERIC_WRITE | GENERIC_ALL); ++ bool with_read_flags = access_flags & (FILE_READ_DATA | FILE_READ_EA | FILE_EXECUTE | ++ FILE_READ_ATTRIBUTES | READ_CONTROL | ++ SYSTEM_SECURITY | MAXIMUM_ALLOWED | GENERIC_ALL | ++ GENERIC_EXECUTE | GENERIC_READ); ++ bool with_execute_flags = access_flags & (FILE_EXECUTE | MAXIMUM_ALLOWED | GENERIC_ALL | ++ GENERIC_EXECUTE); ++ ++ if (with_write_flags && with_read_flags) ++ return SMBOPEN_READWRITE; ++ else if (with_write_flags) + return SMBOPEN_WRITE; +- +- /* just go for read/write */ +- return SMBOPEN_READWRITE; ++ else if (with_execute_flags) ++ return SMBOPEN_EXECUTE; ++ else ++ return SMBOPEN_READ; + } + + int +-- +2.39.5 + diff --git a/queue-6.14/cifs-fix-and-improve-cifs_query_path_info-and-cifs_q.patch b/queue-6.14/cifs-fix-and-improve-cifs_query_path_info-and-cifs_q.patch new file mode 100644 index 0000000000..d6c8d72782 --- /dev/null +++ b/queue-6.14/cifs-fix-and-improve-cifs_query_path_info-and-cifs_q.patch @@ -0,0 +1,183 @@ +From 394091d87f4b52b7c33c8043cbd90467f1c4e9cb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 30 Dec 2024 20:34:18 +0100 +Subject: cifs: Fix and improve cifs_query_path_info() and + cifs_query_file_info() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Pali Rohár + +[ Upstream commit 1041c117a2c33cdffc4f695ac4b469e9124d24d5 ] + +When CAP_NT_SMBS was not negotiated then do not issue CIFSSMBQPathInfo() +and CIFSSMBQFileInfo() commands. CIFSSMBQPathInfo() is not supported by +non-NT Win9x SMB server and CIFSSMBQFileInfo() returns from Win9x SMB +server bogus data in Attributes field (for example lot of files are marked +as reparse points, even Win9x does not support them and read-only bit is +not marked for read-only files). Correct information is returned by +CIFSFindFirst() or SMBQueryInformation() command. + +So as a fallback in cifs_query_path_info() function use CIFSFindFirst() +with SMB_FIND_FILE_FULL_DIRECTORY_INFO level which is supported by both NT +and non-NT servers and as a last option use SMBQueryInformation() as it was +before. + +And in function cifs_query_file_info() immediately returns -EOPNOTSUPP when +not communicating with NT server. Client then revalidate inode entry by the +cifs_query_path_info() call, which is working fine. So fstat() syscall on +already opened file will receive correct information. + +Note that both fallback functions in non-UNICODE mode expands wildcards. +Therefore those fallback functions cannot be used on paths which contain +SMB wildcard characters (* ? " > <). + +CIFSFindFirst() returns all 4 time attributes as opposite of +SMBQueryInformation() which returns only one. + +With this change it is possible to query all 4 times attributes from Win9x +server and at the same time, client minimize sending of unsupported +commands to server. + +Signed-off-by: Pali Rohár +Signed-off-by: Steve French +Signed-off-by: Sasha Levin +--- + fs/smb/client/smb1ops.c | 103 ++++++++++++++++++++++++++++++++++++---- + 1 file changed, 95 insertions(+), 8 deletions(-) + +diff --git a/fs/smb/client/smb1ops.c b/fs/smb/client/smb1ops.c +index 73a689b4ccdff..98f52f705cf6d 100644 +--- a/fs/smb/client/smb1ops.c ++++ b/fs/smb/client/smb1ops.c +@@ -541,24 +541,104 @@ static int cifs_query_path_info(const unsigned int xid, + const char *full_path, + struct cifs_open_info_data *data) + { +- int rc; ++ int rc = -EOPNOTSUPP; + FILE_ALL_INFO fi = {}; ++ struct cifs_search_info search_info = {}; ++ bool non_unicode_wildcard = false; + + data->reparse_point = false; + data->adjust_tz = false; + +- /* could do find first instead but this returns more info */ +- rc = CIFSSMBQPathInfo(xid, tcon, full_path, &fi, 0 /* not legacy */, cifs_sb->local_nls, +- cifs_remap(cifs_sb)); + /* +- * BB optimize code so we do not make the above call when server claims +- * no NT SMB support and the above call failed at least once - set flag +- * in tcon or mount. ++ * First try CIFSSMBQPathInfo() function which returns more info ++ * (NumberOfLinks) than CIFSFindFirst() fallback function. ++ * Some servers like Win9x do not support SMB_QUERY_FILE_ALL_INFO over ++ * TRANS2_QUERY_PATH_INFORMATION, but supports it with filehandle over ++ * TRANS2_QUERY_FILE_INFORMATION (function CIFSSMBQFileInfo(). But SMB ++ * Open command on non-NT servers works only for files, does not work ++ * for directories. And moreover Win9x SMB server returns bogus data in ++ * SMB_QUERY_FILE_ALL_INFO Attributes field. So for non-NT servers, ++ * do not even use CIFSSMBQPathInfo() or CIFSSMBQFileInfo() function. ++ */ ++ if (tcon->ses->capabilities & CAP_NT_SMBS) ++ rc = CIFSSMBQPathInfo(xid, tcon, full_path, &fi, 0 /* not legacy */, ++ cifs_sb->local_nls, cifs_remap(cifs_sb)); ++ ++ /* ++ * Non-UNICODE variant of fallback functions below expands wildcards, ++ * so they cannot be used for querying paths with wildcard characters. + */ +- if ((rc == -EOPNOTSUPP) || (rc == -EINVAL)) { ++ if (rc && !(tcon->ses->capabilities & CAP_UNICODE) && strpbrk(full_path, "*?\"><")) ++ non_unicode_wildcard = true; ++ ++ /* ++ * Then fallback to CIFSFindFirst() which works also with non-NT servers ++ * but does not does not provide NumberOfLinks. ++ */ ++ if ((rc == -EOPNOTSUPP || rc == -EINVAL) && ++ !non_unicode_wildcard) { ++ if (!(tcon->ses->capabilities & tcon->ses->server->vals->cap_nt_find)) ++ search_info.info_level = SMB_FIND_FILE_INFO_STANDARD; ++ else ++ search_info.info_level = SMB_FIND_FILE_FULL_DIRECTORY_INFO; ++ rc = CIFSFindFirst(xid, tcon, full_path, cifs_sb, NULL, ++ CIFS_SEARCH_CLOSE_ALWAYS | CIFS_SEARCH_CLOSE_AT_END, ++ &search_info, false); ++ if (rc == 0) { ++ if (!(tcon->ses->capabilities & tcon->ses->server->vals->cap_nt_find)) { ++ FIND_FILE_STANDARD_INFO *di; ++ int offset = tcon->ses->server->timeAdj; ++ ++ di = (FIND_FILE_STANDARD_INFO *)search_info.srch_entries_start; ++ fi.CreationTime = cpu_to_le64(cifs_UnixTimeToNT(cnvrtDosUnixTm( ++ di->CreationDate, di->CreationTime, offset))); ++ fi.LastAccessTime = cpu_to_le64(cifs_UnixTimeToNT(cnvrtDosUnixTm( ++ di->LastAccessDate, di->LastAccessTime, offset))); ++ fi.LastWriteTime = cpu_to_le64(cifs_UnixTimeToNT(cnvrtDosUnixTm( ++ di->LastWriteDate, di->LastWriteTime, offset))); ++ fi.ChangeTime = fi.LastWriteTime; ++ fi.Attributes = cpu_to_le32(le16_to_cpu(di->Attributes)); ++ fi.AllocationSize = cpu_to_le64(le32_to_cpu(di->AllocationSize)); ++ fi.EndOfFile = cpu_to_le64(le32_to_cpu(di->DataSize)); ++ } else { ++ FILE_FULL_DIRECTORY_INFO *di; ++ ++ di = (FILE_FULL_DIRECTORY_INFO *)search_info.srch_entries_start; ++ fi.CreationTime = di->CreationTime; ++ fi.LastAccessTime = di->LastAccessTime; ++ fi.LastWriteTime = di->LastWriteTime; ++ fi.ChangeTime = di->ChangeTime; ++ fi.Attributes = di->ExtFileAttributes; ++ fi.AllocationSize = di->AllocationSize; ++ fi.EndOfFile = di->EndOfFile; ++ fi.EASize = di->EaSize; ++ } ++ fi.NumberOfLinks = cpu_to_le32(1); ++ fi.DeletePending = 0; ++ fi.Directory = !!(le32_to_cpu(fi.Attributes) & ATTR_DIRECTORY); ++ cifs_buf_release(search_info.ntwrk_buf_start); ++ } else if (!full_path[0]) { ++ /* ++ * CIFSFindFirst() does not work on root path if the ++ * root path was exported on the server from the top ++ * level path (drive letter). ++ */ ++ rc = -EOPNOTSUPP; ++ } ++ } ++ ++ /* ++ * If everything failed then fallback to the legacy SMB command ++ * SMB_COM_QUERY_INFORMATION which works with all servers, but ++ * provide just few information. ++ */ ++ if ((rc == -EOPNOTSUPP || rc == -EINVAL) && !non_unicode_wildcard) { + rc = SMBQueryInformation(xid, tcon, full_path, &fi, cifs_sb->local_nls, + cifs_remap(cifs_sb)); + data->adjust_tz = true; ++ } else if ((rc == -EOPNOTSUPP || rc == -EINVAL) && non_unicode_wildcard) { ++ /* Path with non-UNICODE wildcard character cannot exist. */ ++ rc = -ENOENT; + } + + if (!rc) { +@@ -637,6 +717,13 @@ static int cifs_query_file_info(const unsigned int xid, struct cifs_tcon *tcon, + int rc; + FILE_ALL_INFO fi = {}; + ++ /* ++ * CIFSSMBQFileInfo() for non-NT servers returns bogus data in ++ * Attributes fields. So do not use this command for non-NT servers. ++ */ ++ if (!(tcon->ses->capabilities & CAP_NT_SMBS)) ++ return -EOPNOTSUPP; ++ + if (cfile->symlink_target) { + data->symlink_target = kstrdup(cfile->symlink_target, GFP_KERNEL); + if (!data->symlink_target) +-- +2.39.5 + diff --git a/queue-6.14/cifs-fix-changing-times-and-read-only-attr-over-smb1.patch b/queue-6.14/cifs-fix-changing-times-and-read-only-attr-over-smb1.patch new file mode 100644 index 0000000000..dcc3563dc3 --- /dev/null +++ b/queue-6.14/cifs-fix-changing-times-and-read-only-attr-over-smb1.patch @@ -0,0 +1,334 @@ +From a869d57f7a2aae1be05417bed98262fd2799d01a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 30 Dec 2024 21:32:39 +0100 +Subject: cifs: Fix changing times and read-only attr over SMB1 + smb_set_file_info() function +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Pali Rohár + +[ Upstream commit f122121796f91168d0894c2710b8dd71330a34f8 ] + +Function CIFSSMBSetPathInfo() is not supported by non-NT servers and +returns error. Fallback code via open filehandle and CIFSSMBSetFileInfo() +does not work neither because CIFS_open() works also only on NT server. + +Therefore currently the whole smb_set_file_info() function as a SMB1 +callback for the ->set_file_info() does not work with older non-NT SMB +servers, like Win9x and others. + +This change implements fallback code in smb_set_file_info() which will +works with any server and allows to change time values and also to set or +clear read-only attributes. + +To make existing fallback code via CIFSSMBSetFileInfo() working with also +non-NT servers, it is needed to change open function from CIFS_open() +(which is NT specific) to cifs_open_file() which works with any server +(this is just a open wrapper function which choose the correct open +function supported by the server). + +CIFSSMBSetFileInfo() is working also on non-NT servers, but zero time +values are not treated specially. So first it is needed to fill all time +values if some of them are missing, via cifs_query_path_info() call. + +There is another issue, opening file in write-mode (needed for changing +attributes) is not possible when the file has read-only attribute set. +The only option how to clear read-only attribute is via SMB_COM_SETATTR +command. And opening directory is not possible neither and here the +SMB_COM_SETATTR command is the only option how to change attributes. +And CIFSSMBSetFileInfo() does not honor setting read-only attribute, so +for setting is also needed to use SMB_COM_SETATTR command. + +Existing code in cifs_query_path_info() is already using SMB_COM_GETATTR as +a fallback code path (function SMBQueryInformation()), so introduce a new +function SMBSetInformation which will implement SMB_COM_SETATTR command. + +My testing showed that Windows XP SMB1 client is also using SMB_COM_SETATTR +command for setting or clearing read-only attribute against non-NT server. +So this can prove that this is the correct way how to do it. + +With this change it is possible set all 4 time values and all attributes, +including clearing and setting read-only bit on non-NT SMB servers. +Tested against Win98 SMB1 server. + +This change fixes "touch" command which was failing when called on existing +file. And fixes also "chmod +w" and "chmod -w" commands which were also +failing (as they are changing read-only attribute). + +Note that this change depends on following change +"cifs: Improve cifs_query_path_info() and cifs_query_file_info()" +as it require to query all 4 time attribute values. + +Signed-off-by: Pali Rohár +Signed-off-by: Steve French +Signed-off-by: Sasha Levin +--- + fs/smb/client/cifspdu.h | 5 +- + fs/smb/client/cifsproto.h | 4 ++ + fs/smb/client/cifssmb.c | 57 +++++++++++++++++++ + fs/smb/client/smb1ops.c | 112 +++++++++++++++++++++++++++++++++++--- + 4 files changed, 166 insertions(+), 12 deletions(-) + +diff --git a/fs/smb/client/cifspdu.h b/fs/smb/client/cifspdu.h +index 48d0d6f439cf4..cf9ca7e49b8bc 100644 +--- a/fs/smb/client/cifspdu.h ++++ b/fs/smb/client/cifspdu.h +@@ -1266,10 +1266,9 @@ typedef struct smb_com_query_information_rsp { + typedef struct smb_com_setattr_req { + struct smb_hdr hdr; /* wct = 8 */ + __le16 attr; +- __le16 time_low; +- __le16 time_high; ++ __le32 last_write_time; + __le16 reserved[5]; /* must be zero */ +- __u16 ByteCount; ++ __le16 ByteCount; + __u8 BufferFormat; /* 4 = ASCII */ + unsigned char fileName[]; + } __attribute__((packed)) SETATTR_REQ; +diff --git a/fs/smb/client/cifsproto.h b/fs/smb/client/cifsproto.h +index 1609ca825d825..2dd5a485a1e04 100644 +--- a/fs/smb/client/cifsproto.h ++++ b/fs/smb/client/cifsproto.h +@@ -395,6 +395,10 @@ extern int CIFSSMBQFSUnixInfo(const unsigned int xid, struct cifs_tcon *tcon); + extern int CIFSSMBQFSPosixInfo(const unsigned int xid, struct cifs_tcon *tcon, + struct kstatfs *FSData); + ++extern int SMBSetInformation(const unsigned int xid, struct cifs_tcon *tcon, ++ const char *fileName, __le32 attributes, __le64 write_time, ++ const struct nls_table *nls_codepage, ++ struct cifs_sb_info *cifs_sb); + extern int CIFSSMBSetPathInfo(const unsigned int xid, struct cifs_tcon *tcon, + const char *fileName, const FILE_BASIC_INFO *data, + const struct nls_table *nls_codepage, +diff --git a/fs/smb/client/cifssmb.c b/fs/smb/client/cifssmb.c +index 53e3e8282cb2a..4059550859a9b 100644 +--- a/fs/smb/client/cifssmb.c ++++ b/fs/smb/client/cifssmb.c +@@ -5168,6 +5168,63 @@ CIFSSMBSetFileSize(const unsigned int xid, struct cifs_tcon *tcon, + return rc; + } + ++int ++SMBSetInformation(const unsigned int xid, struct cifs_tcon *tcon, ++ const char *fileName, __le32 attributes, __le64 write_time, ++ const struct nls_table *nls_codepage, ++ struct cifs_sb_info *cifs_sb) ++{ ++ SETATTR_REQ *pSMB; ++ SETATTR_RSP *pSMBr; ++ struct timespec64 ts; ++ int bytes_returned; ++ int name_len; ++ int rc; ++ ++ cifs_dbg(FYI, "In %s path %s\n", __func__, fileName); ++ ++retry: ++ rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB, ++ (void **) &pSMBr); ++ if (rc) ++ return rc; ++ ++ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { ++ name_len = ++ cifsConvertToUTF16((__le16 *) pSMB->fileName, ++ fileName, PATH_MAX, nls_codepage, ++ cifs_remap(cifs_sb)); ++ name_len++; /* trailing null */ ++ name_len *= 2; ++ } else { ++ name_len = copy_path_name(pSMB->fileName, fileName); ++ } ++ /* Only few attributes can be set by this command, others are not accepted by Win9x. */ ++ pSMB->attr = cpu_to_le16(le32_to_cpu(attributes) & ++ (ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM | ATTR_ARCHIVE)); ++ /* Zero write time value (in both NT and SETATTR formats) means to not change it. */ ++ if (le64_to_cpu(write_time) != 0) { ++ ts = cifs_NTtimeToUnix(write_time); ++ pSMB->last_write_time = cpu_to_le32(ts.tv_sec); ++ } ++ pSMB->BufferFormat = 0x04; ++ name_len++; /* account for buffer type byte */ ++ inc_rfc1001_len(pSMB, (__u16)name_len); ++ pSMB->ByteCount = cpu_to_le16(name_len); ++ ++ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, ++ (struct smb_hdr *) pSMBr, &bytes_returned, 0); ++ if (rc) ++ cifs_dbg(FYI, "Send error in %s = %d\n", __func__, rc); ++ ++ cifs_buf_release(pSMB); ++ ++ if (rc == -EAGAIN) ++ goto retry; ++ ++ return rc; ++} ++ + /* Some legacy servers such as NT4 require that the file times be set on + an open handle, rather than by pathname - this is awkward due to + potential access conflicts on the open, but it is unavoidable for these +diff --git a/fs/smb/client/smb1ops.c b/fs/smb/client/smb1ops.c +index 98f52f705cf6d..47c815f34bc36 100644 +--- a/fs/smb/client/smb1ops.c ++++ b/fs/smb/client/smb1ops.c +@@ -894,6 +894,9 @@ smb_set_file_info(struct inode *inode, const char *full_path, + struct cifs_fid fid; + struct cifs_open_parms oparms; + struct cifsFileInfo *open_file; ++ FILE_BASIC_INFO new_buf; ++ struct cifs_open_info_data query_data; ++ __le64 write_time = buf->LastWriteTime; + struct cifsInodeInfo *cinode = CIFS_I(inode); + struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); + struct tcon_link *tlink = NULL; +@@ -901,20 +904,58 @@ smb_set_file_info(struct inode *inode, const char *full_path, + + /* if the file is already open for write, just use that fileid */ + open_file = find_writable_file(cinode, FIND_WR_FSUID_ONLY); ++ + if (open_file) { + fid.netfid = open_file->fid.netfid; + netpid = open_file->pid; + tcon = tlink_tcon(open_file->tlink); +- goto set_via_filehandle; ++ } else { ++ tlink = cifs_sb_tlink(cifs_sb); ++ if (IS_ERR(tlink)) { ++ rc = PTR_ERR(tlink); ++ tlink = NULL; ++ goto out; ++ } ++ tcon = tlink_tcon(tlink); + } + +- tlink = cifs_sb_tlink(cifs_sb); +- if (IS_ERR(tlink)) { +- rc = PTR_ERR(tlink); +- tlink = NULL; +- goto out; ++ /* ++ * Non-NT servers interprets zero time value in SMB_SET_FILE_BASIC_INFO ++ * over TRANS2_SET_FILE_INFORMATION as a valid time value. NT servers ++ * interprets zero time value as do not change existing value on server. ++ * API of ->set_file_info() callback expects that zero time value has ++ * the NT meaning - do not change. Therefore if server is non-NT and ++ * some time values in "buf" are zero, then fetch missing time values. ++ */ ++ if (!(tcon->ses->capabilities & CAP_NT_SMBS) && ++ (!buf->CreationTime || !buf->LastAccessTime || ++ !buf->LastWriteTime || !buf->ChangeTime)) { ++ rc = cifs_query_path_info(xid, tcon, cifs_sb, full_path, &query_data); ++ if (rc) { ++ if (open_file) { ++ cifsFileInfo_put(open_file); ++ open_file = NULL; ++ } ++ goto out; ++ } ++ /* ++ * Original write_time from buf->LastWriteTime is preserved ++ * as SMBSetInformation() interprets zero as do not change. ++ */ ++ new_buf = *buf; ++ buf = &new_buf; ++ if (!buf->CreationTime) ++ buf->CreationTime = query_data.fi.CreationTime; ++ if (!buf->LastAccessTime) ++ buf->LastAccessTime = query_data.fi.LastAccessTime; ++ if (!buf->LastWriteTime) ++ buf->LastWriteTime = query_data.fi.LastWriteTime; ++ if (!buf->ChangeTime) ++ buf->ChangeTime = query_data.fi.ChangeTime; + } +- tcon = tlink_tcon(tlink); ++ ++ if (open_file) ++ goto set_via_filehandle; + + rc = CIFSSMBSetPathInfo(xid, tcon, full_path, buf, cifs_sb->local_nls, + cifs_sb); +@@ -935,8 +976,45 @@ smb_set_file_info(struct inode *inode, const char *full_path, + .fid = &fid, + }; + +- cifs_dbg(FYI, "calling SetFileInfo since SetPathInfo for times not supported by this server\n"); +- rc = CIFS_open(xid, &oparms, &oplock, NULL); ++ if (S_ISDIR(inode->i_mode) && !(tcon->ses->capabilities & CAP_NT_SMBS)) { ++ /* Opening directory path is not possible on non-NT servers. */ ++ rc = -EOPNOTSUPP; ++ } else { ++ /* ++ * Use cifs_open_file() instead of CIFS_open() as the ++ * cifs_open_file() selects the correct function which ++ * works also on non-NT servers. ++ */ ++ rc = cifs_open_file(xid, &oparms, &oplock, NULL); ++ /* ++ * Opening path for writing on non-NT servers is not ++ * possible when the read-only attribute is already set. ++ * Non-NT server in this case returns -EACCES. For those ++ * servers the only possible way how to clear the read-only ++ * bit is via SMB_COM_SETATTR command. ++ */ ++ if (rc == -EACCES && ++ (cinode->cifsAttrs & ATTR_READONLY) && ++ le32_to_cpu(buf->Attributes) != 0 && /* 0 = do not change attrs */ ++ !(le32_to_cpu(buf->Attributes) & ATTR_READONLY) && ++ !(tcon->ses->capabilities & CAP_NT_SMBS)) ++ rc = -EOPNOTSUPP; ++ } ++ ++ /* Fallback to SMB_COM_SETATTR command when absolutelty needed. */ ++ if (rc == -EOPNOTSUPP) { ++ cifs_dbg(FYI, "calling SetInformation since SetPathInfo for attrs/times not supported by this server\n"); ++ rc = SMBSetInformation(xid, tcon, full_path, ++ buf->Attributes != 0 ? buf->Attributes : cpu_to_le32(cinode->cifsAttrs), ++ write_time, ++ cifs_sb->local_nls, cifs_sb); ++ if (rc == 0) ++ cinode->cifsAttrs = le32_to_cpu(buf->Attributes); ++ else ++ rc = -EACCES; ++ goto out; ++ } ++ + if (rc != 0) { + if (rc == -EIO) + rc = -EINVAL; +@@ -944,6 +1022,7 @@ smb_set_file_info(struct inode *inode, const char *full_path, + } + + netpid = current->tgid; ++ cifs_dbg(FYI, "calling SetFileInfo since SetPathInfo for attrs/times not supported by this server\n"); + + set_via_filehandle: + rc = CIFSSMBSetFileInfo(xid, tcon, buf, fid.netfid, netpid); +@@ -954,6 +1033,21 @@ smb_set_file_info(struct inode *inode, const char *full_path, + CIFSSMBClose(xid, tcon, fid.netfid); + else + cifsFileInfo_put(open_file); ++ ++ /* ++ * Setting the read-only bit is not honered on non-NT servers when done ++ * via open-semantics. So for setting it, use SMB_COM_SETATTR command. ++ * This command works only after the file is closed, so use it only when ++ * operation was called without the filehandle. ++ */ ++ if (open_file == NULL && ++ !(tcon->ses->capabilities & CAP_NT_SMBS) && ++ le32_to_cpu(buf->Attributes) & ATTR_READONLY) { ++ SMBSetInformation(xid, tcon, full_path, ++ buf->Attributes, ++ 0 /* do not change write time */, ++ cifs_sb->local_nls, cifs_sb); ++ } + out: + if (tlink != NULL) + cifs_put_tlink(tlink); +-- +2.39.5 + diff --git a/queue-6.14/cifs-fix-establishing-netbios-session-for-smb2-conne.patch b/queue-6.14/cifs-fix-establishing-netbios-session-for-smb2-conne.patch new file mode 100644 index 0000000000..8d6f946b9b --- /dev/null +++ b/queue-6.14/cifs-fix-establishing-netbios-session-for-smb2-conne.patch @@ -0,0 +1,120 @@ +From 6a97dfe0fba87dea589c74a6f355d7ec02fc063c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 30 Oct 2024 22:46:20 +0100 +Subject: cifs: Fix establishing NetBIOS session for SMB2+ connection +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Pali Rohár + +[ Upstream commit 781802aa5a5950f99899f13ff9d760f5db81d36d ] + +Function ip_rfc1001_connect() which establish NetBIOS session for SMB +connections, currently uses smb_send() function for sending NetBIOS Session +Request packet. This function expects that the passed buffer is SMB packet +and for SMB2+ connections it mangles packet header, which breaks prepared +NetBIOS Session Request packet. Result is that this function send garbage +packet for SMB2+ connection, which SMB2+ server cannot parse. That function +is not mangling packets for SMB1 connections, so it somehow works for SMB1. + +Fix this problem and instead of smb_send(), use smb_send_kvec() function +which does not mangle prepared packet, this function send them as is. Just +API of this function takes struct msghdr (kvec) instead of packet buffer. + +[MS-SMB2] specification allows SMB2 protocol to use NetBIOS as a transport +protocol. NetBIOS can be used over TCP via port 139. So this is a valid +configuration, just not so common. And even recent Windows versions (e.g. +Windows Server 2022) still supports this configuration: SMB over TCP port +139, including for modern SMB2 and SMB3 dialects. + +This change fixes SMB2 and SMB3 connections over TCP port 139 which +requires establishing of NetBIOS session. Tested that this change fixes +establishing of SMB2 and SMB3 connections with Windows Server 2022. + +Signed-off-by: Pali Rohár +Signed-off-by: Steve French +Signed-off-by: Sasha Levin +--- + fs/smb/client/cifsproto.h | 3 +++ + fs/smb/client/connect.c | 20 +++++++++++++++----- + fs/smb/client/transport.c | 2 +- + 3 files changed, 19 insertions(+), 6 deletions(-) + +diff --git a/fs/smb/client/cifsproto.h b/fs/smb/client/cifsproto.h +index 278092a15f890..1609ca825d825 100644 +--- a/fs/smb/client/cifsproto.h ++++ b/fs/smb/client/cifsproto.h +@@ -31,6 +31,9 @@ extern void cifs_small_buf_release(void *); + extern void free_rsp_buf(int, void *); + extern int smb_send(struct TCP_Server_Info *, struct smb_hdr *, + unsigned int /* length */); ++extern int smb_send_kvec(struct TCP_Server_Info *server, ++ struct msghdr *msg, ++ size_t *sent); + extern unsigned int _get_xid(void); + extern void _free_xid(unsigned int); + #define get_xid() \ +diff --git a/fs/smb/client/connect.c b/fs/smb/client/connect.c +index 92685fc675b59..22f29d2725928 100644 +--- a/fs/smb/client/connect.c ++++ b/fs/smb/client/connect.c +@@ -3028,8 +3028,10 @@ ip_rfc1001_connect(struct TCP_Server_Info *server) + * sessinit is sent but no second negprot + */ + struct rfc1002_session_packet req = {}; +- struct smb_hdr *smb_buf = (struct smb_hdr *)&req; ++ struct msghdr msg = {}; ++ struct kvec iov = {}; + unsigned int len; ++ size_t sent; + + req.trailer.session_req.called_len = sizeof(req.trailer.session_req.called_name); + +@@ -3058,10 +3060,18 @@ ip_rfc1001_connect(struct TCP_Server_Info *server) + * As per rfc1002, @len must be the number of bytes that follows the + * length field of a rfc1002 session request payload. + */ +- len = sizeof(req) - offsetof(struct rfc1002_session_packet, trailer.session_req); ++ len = sizeof(req.trailer.session_req); ++ req.type = RFC1002_SESSION_REQUEST; ++ req.flags = 0; ++ req.length = cpu_to_be16(len); ++ len += offsetof(typeof(req), trailer.session_req); ++ iov.iov_base = &req; ++ iov.iov_len = len; ++ iov_iter_kvec(&msg.msg_iter, ITER_SOURCE, &iov, 1, len); ++ rc = smb_send_kvec(server, &msg, &sent); ++ if (rc < 0 || len != sent) ++ return (rc == -EINTR || rc == -EAGAIN) ? rc : -ECONNABORTED; + +- smb_buf->smb_buf_length = cpu_to_be32((RFC1002_SESSION_REQUEST << 24) | len); +- rc = smb_send(server, smb_buf, len); + /* + * RFC1001 layer in at least one server requires very short break before + * negprot presumably because not expecting negprot to follow so fast. +@@ -3070,7 +3080,7 @@ ip_rfc1001_connect(struct TCP_Server_Info *server) + */ + usleep_range(1000, 2000); + +- return rc; ++ return 0; + } + + static int +diff --git a/fs/smb/client/transport.c b/fs/smb/client/transport.c +index 0dc80959ce488..03434dbe9374c 100644 +--- a/fs/smb/client/transport.c ++++ b/fs/smb/client/transport.c +@@ -179,7 +179,7 @@ delete_mid(struct mid_q_entry *mid) + * Our basic "send data to server" function. Should be called with srv_mutex + * held. The caller is responsible for handling the results. + */ +-static int ++int + smb_send_kvec(struct TCP_Server_Info *server, struct msghdr *smb_msg, + size_t *sent) + { +-- +2.39.5 + diff --git a/queue-6.14/cifs-fix-getting-dacl-only-xattr-system.cifs_acl-and.patch b/queue-6.14/cifs-fix-getting-dacl-only-xattr-system.cifs_acl-and.patch new file mode 100644 index 0000000000..417c3e5044 --- /dev/null +++ b/queue-6.14/cifs-fix-getting-dacl-only-xattr-system.cifs_acl-and.patch @@ -0,0 +1,116 @@ +From 63b82974ec2080d666dc79e223853ae9f0098327 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 14 Oct 2024 13:47:04 +0200 +Subject: cifs: Fix getting DACL-only xattr system.cifs_acl and system.smb3_acl +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Pali Rohár + +[ Upstream commit ad9364a6835c45c52f47587ffbe0577bb7cd4c5b ] + +Currently ->get_acl() callback always create request for OWNER, GROUP and +DACL, even when only DACLs was requested by user. Change API callback to +request only information for which the caller asked. Therefore when only +DACLs requested, then SMB client will prepare and send DACL-only request. + +This change fixes retrieving of "system.cifs_acl" and "system.smb3_acl" +xattrs to contain only DACL structure as documented. + +Note that setting/changing of "system.cifs_acl" and "system.smb3_acl" +xattrs already takes only DACL structure and ignores all other fields. + +Signed-off-by: Pali Rohár +Signed-off-by: Steve French +Signed-off-by: Sasha Levin +--- + fs/smb/client/cifsacl.c | 4 ++-- + fs/smb/client/cifssmb.c | 3 +-- + fs/smb/client/smb2pdu.c | 4 +--- + fs/smb/client/xattr.c | 15 +++++++++++---- + 4 files changed, 15 insertions(+), 11 deletions(-) + +diff --git a/fs/smb/client/cifsacl.c b/fs/smb/client/cifsacl.c +index f9d577f2d59bb..63b3b1290bed2 100644 +--- a/fs/smb/client/cifsacl.c ++++ b/fs/smb/client/cifsacl.c +@@ -1565,7 +1565,7 @@ cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr, + int rc = 0; + struct tcon_link *tlink = cifs_sb_tlink(cifs_sb); + struct smb_version_operations *ops; +- const u32 info = 0; ++ const u32 info = OWNER_SECINFO | GROUP_SECINFO | DACL_SECINFO; + + cifs_dbg(NOISY, "converting ACL to mode for %s\n", path); + +@@ -1619,7 +1619,7 @@ id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 *pnmode, + struct tcon_link *tlink; + struct smb_version_operations *ops; + bool mode_from_sid, id_from_sid; +- const u32 info = 0; ++ const u32 info = OWNER_SECINFO | GROUP_SECINFO | DACL_SECINFO; + bool posix; + + tlink = cifs_sb_tlink(cifs_sb); +diff --git a/fs/smb/client/cifssmb.c b/fs/smb/client/cifssmb.c +index c2abe79f0dd3b..e90811f321944 100644 +--- a/fs/smb/client/cifssmb.c ++++ b/fs/smb/client/cifssmb.c +@@ -3416,8 +3416,7 @@ CIFSSMBGetCIFSACL(const unsigned int xid, struct cifs_tcon *tcon, __u16 fid, + /* BB TEST with big acls that might need to be e.g. larger than 16K */ + pSMB->MaxSetupCount = 0; + pSMB->Fid = fid; /* file handle always le */ +- pSMB->AclFlags = cpu_to_le32(CIFS_ACL_OWNER | CIFS_ACL_GROUP | +- CIFS_ACL_DACL | info); ++ pSMB->AclFlags = cpu_to_le32(info); + pSMB->ByteCount = cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */ + inc_rfc1001_len(pSMB, 11); + iov[0].iov_base = (char *)pSMB; +diff --git a/fs/smb/client/smb2pdu.c b/fs/smb/client/smb2pdu.c +index ed3ffcb80aef0..d080c777906b4 100644 +--- a/fs/smb/client/smb2pdu.c ++++ b/fs/smb/client/smb2pdu.c +@@ -3910,12 +3910,10 @@ SMB2_query_acl(const unsigned int xid, struct cifs_tcon *tcon, + u64 persistent_fid, u64 volatile_fid, + void **data, u32 *plen, u32 extra_info) + { +- __u32 additional_info = OWNER_SECINFO | GROUP_SECINFO | DACL_SECINFO | +- extra_info; + *plen = 0; + + return query_info(xid, tcon, persistent_fid, volatile_fid, +- 0, SMB2_O_INFO_SECURITY, additional_info, ++ 0, SMB2_O_INFO_SECURITY, extra_info, + SMB2_MAX_BUFFER_SIZE, MIN_SEC_DESC_LEN, data, plen); + } + +diff --git a/fs/smb/client/xattr.c b/fs/smb/client/xattr.c +index 58a584f0b27e9..7d49f38f01f3e 100644 +--- a/fs/smb/client/xattr.c ++++ b/fs/smb/client/xattr.c +@@ -320,10 +320,17 @@ static int cifs_xattr_get(const struct xattr_handler *handler, + if (pTcon->ses->server->ops->get_acl == NULL) + goto out; /* rc already EOPNOTSUPP */ + +- if (handler->flags == XATTR_CIFS_NTSD_FULL) { +- extra_info = SACL_SECINFO; +- } else { +- extra_info = 0; ++ switch (handler->flags) { ++ case XATTR_CIFS_NTSD_FULL: ++ extra_info = OWNER_SECINFO | GROUP_SECINFO | DACL_SECINFO | SACL_SECINFO; ++ break; ++ case XATTR_CIFS_NTSD: ++ extra_info = OWNER_SECINFO | GROUP_SECINFO | DACL_SECINFO; ++ break; ++ case XATTR_CIFS_ACL: ++ default: ++ extra_info = DACL_SECINFO; ++ break; + } + pacl = pTcon->ses->server->ops->get_acl(cifs_sb, + inode, full_path, &acllen, extra_info); +-- +2.39.5 + diff --git a/queue-6.14/cifs-fix-negotiate-retry-functionality.patch b/queue-6.14/cifs-fix-negotiate-retry-functionality.patch new file mode 100644 index 0000000000..70dd7fc816 --- /dev/null +++ b/queue-6.14/cifs-fix-negotiate-retry-functionality.patch @@ -0,0 +1,107 @@ +From b320205ffd2b21bf54054fa2a02597c26f7369ae Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 2 Nov 2024 20:06:50 +0100 +Subject: cifs: Fix negotiate retry functionality +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Pali Rohár + +[ Upstream commit e94e882a6d69525c07589222cf3a6ff57ad12b5b ] + +SMB negotiate retry functionality in cifs_negotiate() is currently broken +and does not work when doing socket reconnect. Caller of this function, +which is cifs_negotiate_protocol() requires that tcpStatus after successful +execution of negotiate callback stay in CifsInNegotiate. But if the +CIFSSMBNegotiate() called from cifs_negotiate() fails due to connection +issues then tcpStatus is changed as so repeated CIFSSMBNegotiate() call +does not help. + +Fix this problem by moving retrying code from negotiate callback (which is +either cifs_negotiate() or smb2_negotiate()) to cifs_negotiate_protocol() +which is caller of those callbacks. This allows to properly handle and +implement correct transistions between tcpStatus states as function +cifs_negotiate_protocol() already handles it. + +With this change, cifs_negotiate_protocol() now handles also -EAGAIN error +set by the RFC1002_NEGATIVE_SESSION_RESPONSE processing after reconnecting +with NetBIOS session. + +Signed-off-by: Pali Rohár +Signed-off-by: Steve French +Signed-off-by: Sasha Levin +--- + fs/smb/client/connect.c | 10 ++++++++++ + fs/smb/client/smb1ops.c | 7 ------- + fs/smb/client/smb2ops.c | 3 --- + 3 files changed, 10 insertions(+), 10 deletions(-) + +diff --git a/fs/smb/client/connect.c b/fs/smb/client/connect.c +index cc9c912db8def..92685fc675b59 100644 +--- a/fs/smb/client/connect.c ++++ b/fs/smb/client/connect.c +@@ -3922,11 +3922,13 @@ int + cifs_negotiate_protocol(const unsigned int xid, struct cifs_ses *ses, + struct TCP_Server_Info *server) + { ++ bool in_retry = false; + int rc = 0; + + if (!server->ops->need_neg || !server->ops->negotiate) + return -ENOSYS; + ++retry: + /* only send once per connect */ + spin_lock(&server->srv_lock); + if (server->tcpStatus != CifsGood && +@@ -3946,6 +3948,14 @@ cifs_negotiate_protocol(const unsigned int xid, struct cifs_ses *ses, + spin_unlock(&server->srv_lock); + + rc = server->ops->negotiate(xid, ses, server); ++ if (rc == -EAGAIN) { ++ /* Allow one retry attempt */ ++ if (!in_retry) { ++ in_retry = true; ++ goto retry; ++ } ++ rc = -EHOSTDOWN; ++ } + if (rc == 0) { + spin_lock(&server->srv_lock); + if (server->tcpStatus == CifsInNegotiate) +diff --git a/fs/smb/client/smb1ops.c b/fs/smb/client/smb1ops.c +index 808970e4a7142..e28cdaca47e12 100644 +--- a/fs/smb/client/smb1ops.c ++++ b/fs/smb/client/smb1ops.c +@@ -426,13 +426,6 @@ cifs_negotiate(const unsigned int xid, + { + int rc; + rc = CIFSSMBNegotiate(xid, ses, server); +- if (rc == -EAGAIN) { +- /* retry only once on 1st time connection */ +- set_credits(server, 1); +- rc = CIFSSMBNegotiate(xid, ses, server); +- if (rc == -EAGAIN) +- rc = -EHOSTDOWN; +- } + return rc; + } + +diff --git a/fs/smb/client/smb2ops.c b/fs/smb/client/smb2ops.c +index 7aeac8dd9a1d1..6f89e087629fe 100644 +--- a/fs/smb/client/smb2ops.c ++++ b/fs/smb/client/smb2ops.c +@@ -464,9 +464,6 @@ smb2_negotiate(const unsigned int xid, + server->CurrentMid = 0; + spin_unlock(&server->mid_lock); + rc = SMB2_negotiate(xid, ses, server); +- /* BB we probably don't need to retry with modern servers */ +- if (rc == -EAGAIN) +- rc = -EHOSTDOWN; + return rc; + } + +-- +2.39.5 + diff --git a/queue-6.14/cifs-fix-querying-and-creating-mf-symlinks-over-smb1.patch b/queue-6.14/cifs-fix-querying-and-creating-mf-symlinks-over-smb1.patch new file mode 100644 index 0000000000..ed1dfb591a --- /dev/null +++ b/queue-6.14/cifs-fix-querying-and-creating-mf-symlinks-over-smb1.patch @@ -0,0 +1,69 @@ +From 613ab6a850103ba8fc664e9be0a6bd36307cbf2f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 28 Dec 2024 21:09:54 +0100 +Subject: cifs: Fix querying and creating MF symlinks over SMB1 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Pali Rohár + +[ Upstream commit 4236ac9fe5b8b42756070d4abfb76fed718e87c2 ] + +Old SMB1 servers without CAP_NT_SMBS do not support CIFS_open() function +and instead SMBLegacyOpen() needs to be used. This logic is already handled +in cifs_open_file() function, which is server->ops->open callback function. + +So for querying and creating MF symlinks use open callback function instead +of CIFS_open() function directly. + +This change fixes querying and creating new MF symlinks on Windows 98. +Currently cifs_query_mf_symlink() is not able to detect MF symlink and +cifs_create_mf_symlink() is failing with EIO error. + +Signed-off-by: Pali Rohár +Signed-off-by: Steve French +Signed-off-by: Sasha Levin +--- + fs/smb/client/link.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/fs/smb/client/link.c b/fs/smb/client/link.c +index 6e6c09cc5ce7a..34a026243287f 100644 +--- a/fs/smb/client/link.c ++++ b/fs/smb/client/link.c +@@ -258,7 +258,7 @@ cifs_query_mf_symlink(unsigned int xid, struct cifs_tcon *tcon, + struct cifs_open_parms oparms; + struct cifs_io_parms io_parms = {0}; + int buf_type = CIFS_NO_BUFFER; +- FILE_ALL_INFO file_info; ++ struct cifs_open_info_data query_data; + + oparms = (struct cifs_open_parms) { + .tcon = tcon, +@@ -270,11 +270,11 @@ cifs_query_mf_symlink(unsigned int xid, struct cifs_tcon *tcon, + .fid = &fid, + }; + +- rc = CIFS_open(xid, &oparms, &oplock, &file_info); ++ rc = tcon->ses->server->ops->open(xid, &oparms, &oplock, &query_data); + if (rc) + return rc; + +- if (file_info.EndOfFile != cpu_to_le64(CIFS_MF_SYMLINK_FILE_SIZE)) { ++ if (query_data.fi.EndOfFile != cpu_to_le64(CIFS_MF_SYMLINK_FILE_SIZE)) { + rc = -ENOENT; + /* it's not a symlink */ + goto out; +@@ -313,7 +313,7 @@ cifs_create_mf_symlink(unsigned int xid, struct cifs_tcon *tcon, + .fid = &fid, + }; + +- rc = CIFS_open(xid, &oparms, &oplock, NULL); ++ rc = tcon->ses->server->ops->open(xid, &oparms, &oplock, NULL); + if (rc) + return rc; + +-- +2.39.5 + diff --git a/queue-6.14/cifs-set-default-netbios-rfc1001-server-name-to-host.patch b/queue-6.14/cifs-set-default-netbios-rfc1001-server-name-to-host.patch new file mode 100644 index 0000000000..fa76ed2216 --- /dev/null +++ b/queue-6.14/cifs-set-default-netbios-rfc1001-server-name-to-host.patch @@ -0,0 +1,59 @@ +From c890a6f48b5ebdfc88efa08c90dbb4b8379ed127 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 27 Oct 2024 12:10:52 +0100 +Subject: cifs: Set default Netbios RFC1001 server name to hostname in UNC +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Pali Rohár + +[ Upstream commit be786e509c1af9b2dcf25c3d601f05c8c251f482 ] + +Windows SMB servers (including SMB2+) which are working over RFC1001 +require that Netbios server name specified in RFC1001 Session Request +packet is same as the UNC host name. Netbios server name can be already +specified manually via -o servern= option. + +With this change the RFC1001 server name is set automatically by extracting +the hostname from the mount source. + +Signed-off-by: Pali Rohár +Signed-off-by: Steve French +Signed-off-by: Sasha Levin +--- + fs/smb/client/fs_context.c | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/fs/smb/client/fs_context.c b/fs/smb/client/fs_context.c +index 00af8dd5aa689..b877def5a3664 100644 +--- a/fs/smb/client/fs_context.c ++++ b/fs/smb/client/fs_context.c +@@ -1118,6 +1118,7 @@ static int smb3_fs_context_parse_param(struct fs_context *fc, + int i, opt; + bool is_smb3 = !strcmp(fc->fs_type->name, "smb3"); + bool skip_parsing = false; ++ char *hostname; + + cifs_dbg(FYI, "CIFS: parsing cifs mount option '%s'\n", param->key); + +@@ -1450,6 +1451,16 @@ static int smb3_fs_context_parse_param(struct fs_context *fc, + cifs_errorf(fc, "OOM when copying UNC string\n"); + goto cifs_parse_mount_err; + } ++ hostname = extract_hostname(ctx->UNC); ++ if (IS_ERR(hostname)) { ++ cifs_errorf(fc, "Cannot extract hostname from UNC string\n"); ++ goto cifs_parse_mount_err; ++ } ++ /* last byte, type, is 0x20 for servr type */ ++ memset(ctx->target_rfc1001_name, 0x20, RFC1001_NAME_LEN_WITH_NULL); ++ for (i = 0; i < RFC1001_NAME_LEN && hostname[i] != 0; i++) ++ ctx->target_rfc1001_name[i] = toupper(hostname[i]); ++ kfree(hostname); + break; + case Opt_user: + kfree(ctx->username); +-- +2.39.5 + diff --git a/queue-6.14/clk-imx8mp-inform-ccf-of-maximum-frequency-of-clocks.patch b/queue-6.14/clk-imx8mp-inform-ccf-of-maximum-frequency-of-clocks.patch new file mode 100644 index 0000000000..680895d80a --- /dev/null +++ b/queue-6.14/clk-imx8mp-inform-ccf-of-maximum-frequency-of-clocks.patch @@ -0,0 +1,214 @@ +From 905858e4e7c12e9521daf1135adccb22fa07bfc9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 18 Feb 2025 19:26:46 +0100 +Subject: clk: imx8mp: inform CCF of maximum frequency of clocks + +From: Ahmad Fatoum + +[ Upstream commit 06a61b5cb6a8638fa8823cd09b17233b29696fa2 ] + +The IMX8MPCEC datasheet lists maximum frequencies allowed for different +modules. Some of these limits are universal, but some depend on +whether the SoC is operating in nominal or in overdrive mode. + +The imx8mp.dtsi currently assumes overdrive mode and configures some +clocks in accordance with this. Boards wishing to make use of nominal +mode will need to override some of the clock rates manually. + +As operating the clocks outside of their allowed range can lead to +difficult to debug issues, it makes sense to register the maximum rates +allowed in the driver, so the CCF can take them into account. + +Reviewed-by: Peng Fan +Signed-off-by: Ahmad Fatoum +Link: https://lore.kernel.org/r/20250218-imx8m-clk-v4-6-b7697dc2dcd0@pengutronix.de +Signed-off-by: Abel Vesa +Signed-off-by: Sasha Levin +--- + drivers/clk/imx/clk-imx8mp.c | 151 +++++++++++++++++++++++++++++++++++ + 1 file changed, 151 insertions(+) + +diff --git a/drivers/clk/imx/clk-imx8mp.c b/drivers/clk/imx/clk-imx8mp.c +index fb18f507f1213..fe6dac70f1a15 100644 +--- a/drivers/clk/imx/clk-imx8mp.c ++++ b/drivers/clk/imx/clk-imx8mp.c +@@ -8,6 +8,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -406,11 +407,151 @@ static const char * const imx8mp_clkout_sels[] = {"audio_pll1_out", "audio_pll2_ + static struct clk_hw **hws; + static struct clk_hw_onecell_data *clk_hw_data; + ++struct imx8mp_clock_constraints { ++ unsigned int clkid; ++ u32 maxrate; ++}; ++ ++/* ++ * Below tables are taken from IMX8MPCEC Rev. 2.1, 07/2023 ++ * Table 13. Maximum frequency of modules. ++ * Probable typos fixed are marked with a comment. ++ */ ++static const struct imx8mp_clock_constraints imx8mp_clock_common_constraints[] = { ++ { IMX8MP_CLK_A53_DIV, 1000 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_ENET_AXI, 266666667 }, /* Datasheet claims 266MHz */ ++ { IMX8MP_CLK_NAND_USDHC_BUS, 266666667 }, /* Datasheet claims 266MHz */ ++ { IMX8MP_CLK_MEDIA_APB, 200 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_HDMI_APB, 133333333 }, /* Datasheet claims 133MHz */ ++ { IMX8MP_CLK_ML_AXI, 800 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_AHB, 133333333 }, ++ { IMX8MP_CLK_IPG_ROOT, 66666667 }, ++ { IMX8MP_CLK_AUDIO_AHB, 400 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_MEDIA_DISP2_PIX, 170 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_DRAM_ALT, 666666667 }, ++ { IMX8MP_CLK_DRAM_APB, 200 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_CAN1, 80 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_CAN2, 80 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_PCIE_AUX, 10 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_I2C5, 66666667 }, /* Datasheet claims 66MHz */ ++ { IMX8MP_CLK_I2C6, 66666667 }, /* Datasheet claims 66MHz */ ++ { IMX8MP_CLK_SAI1, 66666667 }, /* Datasheet claims 66MHz */ ++ { IMX8MP_CLK_SAI2, 66666667 }, /* Datasheet claims 66MHz */ ++ { IMX8MP_CLK_SAI3, 66666667 }, /* Datasheet claims 66MHz */ ++ { IMX8MP_CLK_SAI5, 66666667 }, /* Datasheet claims 66MHz */ ++ { IMX8MP_CLK_SAI6, 66666667 }, /* Datasheet claims 66MHz */ ++ { IMX8MP_CLK_ENET_QOS, 125 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_ENET_QOS_TIMER, 200 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_ENET_REF, 125 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_ENET_TIMER, 125 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_ENET_PHY_REF, 125 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_NAND, 500 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_QSPI, 400 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_USDHC1, 400 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_USDHC2, 400 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_I2C1, 66666667 }, /* Datasheet claims 66MHz */ ++ { IMX8MP_CLK_I2C2, 66666667 }, /* Datasheet claims 66MHz */ ++ { IMX8MP_CLK_I2C3, 66666667 }, /* Datasheet claims 66MHz */ ++ { IMX8MP_CLK_I2C4, 66666667 }, /* Datasheet claims 66MHz */ ++ { IMX8MP_CLK_UART1, 80 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_UART2, 80 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_UART3, 80 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_UART4, 80 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_ECSPI1, 80 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_ECSPI2, 80 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_PWM1, 66666667 }, /* Datasheet claims 66MHz */ ++ { IMX8MP_CLK_PWM2, 66666667 }, /* Datasheet claims 66MHz */ ++ { IMX8MP_CLK_PWM3, 66666667 }, /* Datasheet claims 66MHz */ ++ { IMX8MP_CLK_PWM4, 66666667 }, /* Datasheet claims 66MHz */ ++ { IMX8MP_CLK_GPT1, 100 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_GPT2, 100 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_GPT3, 100 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_GPT4, 100 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_GPT5, 100 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_GPT6, 100 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_WDOG, 66666667 }, /* Datasheet claims 66MHz */ ++ { IMX8MP_CLK_IPP_DO_CLKO1, 200 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_IPP_DO_CLKO2, 200 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_HDMI_REF_266M, 266 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_USDHC3, 400 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_MEDIA_MIPI_PHY1_REF, 300 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_MEDIA_DISP1_PIX, 250 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_MEDIA_CAM2_PIX, 277 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_MEDIA_LDB, 595 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_MEDIA_MIPI_TEST_BYTE, 200 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_ECSPI3, 80 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_PDM, 200 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_SAI7, 66666667 }, /* Datasheet claims 66MHz */ ++ { IMX8MP_CLK_MAIN_AXI, 400 * HZ_PER_MHZ }, ++ { /* Sentinel */ } ++}; ++ ++static const struct imx8mp_clock_constraints imx8mp_clock_nominal_constraints[] = { ++ { IMX8MP_CLK_M7_CORE, 600 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_ML_CORE, 800 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_GPU3D_CORE, 800 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_GPU3D_SHADER_CORE, 800 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_GPU2D_CORE, 800 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_AUDIO_AXI_SRC, 600 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_HSIO_AXI, 400 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_MEDIA_ISP, 400 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_VPU_BUS, 600 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_MEDIA_AXI, 400 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_HDMI_AXI, 400 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_GPU_AXI, 600 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_GPU_AHB, 300 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_NOC, 800 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_NOC_IO, 600 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_ML_AHB, 300 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_VPU_G1, 600 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_VPU_G2, 500 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_MEDIA_CAM1_PIX, 400 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_VPU_VC8000E, 400 * HZ_PER_MHZ }, /* Datasheet claims 500MHz */ ++ { IMX8MP_CLK_DRAM_CORE, 800 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_GIC, 400 * HZ_PER_MHZ }, ++ { /* Sentinel */ } ++}; ++ ++static const struct imx8mp_clock_constraints imx8mp_clock_overdrive_constraints[] = { ++ { IMX8MP_CLK_M7_CORE, 800 * HZ_PER_MHZ}, ++ { IMX8MP_CLK_ML_CORE, 1000 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_GPU3D_CORE, 1000 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_GPU3D_SHADER_CORE, 1000 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_GPU2D_CORE, 1000 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_AUDIO_AXI_SRC, 800 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_HSIO_AXI, 500 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_MEDIA_ISP, 500 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_VPU_BUS, 800 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_MEDIA_AXI, 500 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_HDMI_AXI, 500 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_GPU_AXI, 800 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_GPU_AHB, 400 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_NOC, 1000 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_NOC_IO, 800 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_ML_AHB, 400 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_VPU_G1, 800 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_VPU_G2, 700 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_MEDIA_CAM1_PIX, 500 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_VPU_VC8000E, 500 * HZ_PER_MHZ }, /* Datasheet claims 400MHz */ ++ { IMX8MP_CLK_DRAM_CORE, 1000 * HZ_PER_MHZ }, ++ { IMX8MP_CLK_GIC, 500 * HZ_PER_MHZ }, ++ { /* Sentinel */ } ++}; ++ ++static void imx8mp_clocks_apply_constraints(const struct imx8mp_clock_constraints constraints[]) ++{ ++ const struct imx8mp_clock_constraints *constr; ++ ++ for (constr = constraints; constr->clkid; constr++) ++ clk_hw_set_rate_range(hws[constr->clkid], 0, constr->maxrate); ++} ++ + static int imx8mp_clocks_probe(struct platform_device *pdev) + { + struct device *dev = &pdev->dev; + struct device_node *np; + void __iomem *anatop_base, *ccm_base; ++ const char *opmode; + int err; + + np = of_find_compatible_node(NULL, NULL, "fsl,imx8mp-anatop"); +@@ -715,6 +856,16 @@ static int imx8mp_clocks_probe(struct platform_device *pdev) + + imx_check_clk_hws(hws, IMX8MP_CLK_END); + ++ imx8mp_clocks_apply_constraints(imx8mp_clock_common_constraints); ++ ++ err = of_property_read_string(np, "fsl,operating-mode", &opmode); ++ if (!err) { ++ if (!strcmp(opmode, "nominal")) ++ imx8mp_clocks_apply_constraints(imx8mp_clock_nominal_constraints); ++ else if (!strcmp(opmode, "overdrive")) ++ imx8mp_clocks_apply_constraints(imx8mp_clock_overdrive_constraints); ++ } ++ + err = of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_hw_data); + if (err < 0) { + dev_err(dev, "failed to register hws for i.MX8MP\n"); +-- +2.39.5 + diff --git a/queue-6.14/clk-qcom-camcc-sm8250-use-clk_rcg2_shared_ops-for-so.patch b/queue-6.14/clk-qcom-camcc-sm8250-use-clk_rcg2_shared_ops-for-so.patch new file mode 100644 index 0000000000..a776f9ee24 --- /dev/null +++ b/queue-6.14/clk-qcom-camcc-sm8250-use-clk_rcg2_shared_ops-for-so.patch @@ -0,0 +1,285 @@ +From e0ef362fb30fa3291d57394a846097145482e044 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 22 Jan 2025 22:26:12 +0000 +Subject: clk: qcom: camcc-sm8250: Use clk_rcg2_shared_ops for some RCGs + +From: Jordan Crouse + +[ Upstream commit 52b10b591f83dc6d9a1d6c2dc89433470a787ecd ] + +Update some RCGs on the sm8250 camera clock controller to use +clk_rcg2_shared_ops. The shared_ops ensure the RCGs get parked +to the XO during clock disable to prevent the clocks from locking up +when the GDSC is enabled. These mirror similar fixes for other controllers +such as commit e5c359f70e4b ("clk: qcom: camcc: Update the clock ops for +the SC7180"). + +Signed-off-by: Jordan Crouse +Reviewed-by: Dmitry Baryshkov +Reviewed-by: Bryan O'Donoghue +Link: https://lore.kernel.org/r/20250122222612.32351-1-jorcrous@amazon.com +Signed-off-by: Bjorn Andersson +Signed-off-by: Sasha Levin +--- + drivers/clk/qcom/camcc-sm8250.c | 56 ++++++++++++++++----------------- + 1 file changed, 28 insertions(+), 28 deletions(-) + +diff --git a/drivers/clk/qcom/camcc-sm8250.c b/drivers/clk/qcom/camcc-sm8250.c +index 34d2f17520dcc..450ddbebd35f2 100644 +--- a/drivers/clk/qcom/camcc-sm8250.c ++++ b/drivers/clk/qcom/camcc-sm8250.c +@@ -411,7 +411,7 @@ static struct clk_rcg2 cam_cc_bps_clk_src = { + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, +- .ops = &clk_rcg2_ops, ++ .ops = &clk_rcg2_shared_ops, + }, + }; + +@@ -433,7 +433,7 @@ static struct clk_rcg2 cam_cc_camnoc_axi_clk_src = { + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, +- .ops = &clk_rcg2_ops, ++ .ops = &clk_rcg2_shared_ops, + }, + }; + +@@ -454,7 +454,7 @@ static struct clk_rcg2 cam_cc_cci_0_clk_src = { + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, +- .ops = &clk_rcg2_ops, ++ .ops = &clk_rcg2_shared_ops, + }, + }; + +@@ -469,7 +469,7 @@ static struct clk_rcg2 cam_cc_cci_1_clk_src = { + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, +- .ops = &clk_rcg2_ops, ++ .ops = &clk_rcg2_shared_ops, + }, + }; + +@@ -490,7 +490,7 @@ static struct clk_rcg2 cam_cc_cphy_rx_clk_src = { + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, +- .ops = &clk_rcg2_ops, ++ .ops = &clk_rcg2_shared_ops, + }, + }; + +@@ -511,7 +511,7 @@ static struct clk_rcg2 cam_cc_csi0phytimer_clk_src = { + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, +- .ops = &clk_rcg2_ops, ++ .ops = &clk_rcg2_shared_ops, + }, + }; + +@@ -526,7 +526,7 @@ static struct clk_rcg2 cam_cc_csi1phytimer_clk_src = { + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, +- .ops = &clk_rcg2_ops, ++ .ops = &clk_rcg2_shared_ops, + }, + }; + +@@ -556,7 +556,7 @@ static struct clk_rcg2 cam_cc_csi3phytimer_clk_src = { + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, +- .ops = &clk_rcg2_ops, ++ .ops = &clk_rcg2_shared_ops, + }, + }; + +@@ -571,7 +571,7 @@ static struct clk_rcg2 cam_cc_csi4phytimer_clk_src = { + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, +- .ops = &clk_rcg2_ops, ++ .ops = &clk_rcg2_shared_ops, + }, + }; + +@@ -586,7 +586,7 @@ static struct clk_rcg2 cam_cc_csi5phytimer_clk_src = { + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, +- .ops = &clk_rcg2_ops, ++ .ops = &clk_rcg2_shared_ops, + }, + }; + +@@ -611,7 +611,7 @@ static struct clk_rcg2 cam_cc_fast_ahb_clk_src = { + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, +- .ops = &clk_rcg2_ops, ++ .ops = &clk_rcg2_shared_ops, + }, + }; + +@@ -634,7 +634,7 @@ static struct clk_rcg2 cam_cc_fd_core_clk_src = { + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, +- .ops = &clk_rcg2_ops, ++ .ops = &clk_rcg2_shared_ops, + }, + }; + +@@ -649,7 +649,7 @@ static struct clk_rcg2 cam_cc_icp_clk_src = { + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, +- .ops = &clk_rcg2_ops, ++ .ops = &clk_rcg2_shared_ops, + }, + }; + +@@ -673,7 +673,7 @@ static struct clk_rcg2 cam_cc_ife_0_clk_src = { + .parent_data = cam_cc_parent_data_2, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_2), + .flags = CLK_SET_RATE_PARENT, +- .ops = &clk_rcg2_ops, ++ .ops = &clk_rcg2_shared_ops, + }, + }; + +@@ -710,7 +710,7 @@ static struct clk_rcg2 cam_cc_ife_0_csid_clk_src = { + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, +- .ops = &clk_rcg2_ops, ++ .ops = &clk_rcg2_shared_ops, + }, + }; + +@@ -734,7 +734,7 @@ static struct clk_rcg2 cam_cc_ife_1_clk_src = { + .parent_data = cam_cc_parent_data_3, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_3), + .flags = CLK_SET_RATE_PARENT, +- .ops = &clk_rcg2_ops, ++ .ops = &clk_rcg2_shared_ops, + }, + }; + +@@ -749,7 +749,7 @@ static struct clk_rcg2 cam_cc_ife_1_csid_clk_src = { + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, +- .ops = &clk_rcg2_ops, ++ .ops = &clk_rcg2_shared_ops, + }, + }; + +@@ -771,7 +771,7 @@ static struct clk_rcg2 cam_cc_ife_lite_clk_src = { + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, +- .ops = &clk_rcg2_ops, ++ .ops = &clk_rcg2_shared_ops, + }, + }; + +@@ -786,7 +786,7 @@ static struct clk_rcg2 cam_cc_ife_lite_csid_clk_src = { + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, +- .ops = &clk_rcg2_ops, ++ .ops = &clk_rcg2_shared_ops, + }, + }; + +@@ -810,7 +810,7 @@ static struct clk_rcg2 cam_cc_ipe_0_clk_src = { + .parent_data = cam_cc_parent_data_4, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_4), + .flags = CLK_SET_RATE_PARENT, +- .ops = &clk_rcg2_ops, ++ .ops = &clk_rcg2_shared_ops, + }, + }; + +@@ -825,7 +825,7 @@ static struct clk_rcg2 cam_cc_jpeg_clk_src = { + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, +- .ops = &clk_rcg2_ops, ++ .ops = &clk_rcg2_shared_ops, + }, + }; + +@@ -847,7 +847,7 @@ static struct clk_rcg2 cam_cc_mclk0_clk_src = { + .parent_data = cam_cc_parent_data_1, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_1), + .flags = CLK_SET_RATE_PARENT, +- .ops = &clk_rcg2_ops, ++ .ops = &clk_rcg2_shared_ops, + }, + }; + +@@ -862,7 +862,7 @@ static struct clk_rcg2 cam_cc_mclk1_clk_src = { + .parent_data = cam_cc_parent_data_1, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_1), + .flags = CLK_SET_RATE_PARENT, +- .ops = &clk_rcg2_ops, ++ .ops = &clk_rcg2_shared_ops, + }, + }; + +@@ -877,7 +877,7 @@ static struct clk_rcg2 cam_cc_mclk2_clk_src = { + .parent_data = cam_cc_parent_data_1, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_1), + .flags = CLK_SET_RATE_PARENT, +- .ops = &clk_rcg2_ops, ++ .ops = &clk_rcg2_shared_ops, + }, + }; + +@@ -892,7 +892,7 @@ static struct clk_rcg2 cam_cc_mclk3_clk_src = { + .parent_data = cam_cc_parent_data_1, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_1), + .flags = CLK_SET_RATE_PARENT, +- .ops = &clk_rcg2_ops, ++ .ops = &clk_rcg2_shared_ops, + }, + }; + +@@ -907,7 +907,7 @@ static struct clk_rcg2 cam_cc_mclk4_clk_src = { + .parent_data = cam_cc_parent_data_1, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_1), + .flags = CLK_SET_RATE_PARENT, +- .ops = &clk_rcg2_ops, ++ .ops = &clk_rcg2_shared_ops, + }, + }; + +@@ -922,7 +922,7 @@ static struct clk_rcg2 cam_cc_mclk5_clk_src = { + .parent_data = cam_cc_parent_data_1, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_1), + .flags = CLK_SET_RATE_PARENT, +- .ops = &clk_rcg2_ops, ++ .ops = &clk_rcg2_shared_ops, + }, + }; + +@@ -993,7 +993,7 @@ static struct clk_rcg2 cam_cc_slow_ahb_clk_src = { + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, +- .ops = &clk_rcg2_ops, ++ .ops = &clk_rcg2_shared_ops, + }, + }; + +-- +2.39.5 + diff --git a/queue-6.14/clk-qcom-clk-alpha-pll-do-not-use-random-stack-value.patch b/queue-6.14/clk-qcom-clk-alpha-pll-do-not-use-random-stack-value.patch new file mode 100644 index 0000000000..bd0efe7303 --- /dev/null +++ b/queue-6.14/clk-qcom-clk-alpha-pll-do-not-use-random-stack-value.patch @@ -0,0 +1,143 @@ +From 3f05998db340f3ce49dc46957aedd5bbebb198de Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 12 Feb 2025 21:01:35 +0100 +Subject: clk: qcom: clk-alpha-pll: Do not use random stack value for recalc + rate + +From: Krzysztof Kozlowski + +[ Upstream commit 7a243e1b814a02ab40793026ef64223155d86395 ] + +If regmap_read() fails, random stack value was used in calculating new +frequency in recalc_rate() callbacks. Such failure is really not +expected as these are all MMIO reads, however code should be here +correct and bail out. This also avoids possible warning on +uninitialized value. + +Signed-off-by: Krzysztof Kozlowski +Link: https://lore.kernel.org/r/20250212-b4-clk-qcom-clean-v3-1-499f37444f5d@linaro.org +Signed-off-by: Bjorn Andersson +Signed-off-by: Sasha Levin +--- + drivers/clk/qcom/clk-alpha-pll.c | 52 ++++++++++++++++++++++---------- + 1 file changed, 36 insertions(+), 16 deletions(-) + +diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c +index 9a65d14acf71c..cec0afea8e446 100644 +--- a/drivers/clk/qcom/clk-alpha-pll.c ++++ b/drivers/clk/qcom/clk-alpha-pll.c +@@ -709,14 +709,19 @@ clk_alpha_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) + struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); + u32 alpha_width = pll_alpha_width(pll); + +- regmap_read(pll->clkr.regmap, PLL_L_VAL(pll), &l); ++ if (regmap_read(pll->clkr.regmap, PLL_L_VAL(pll), &l)) ++ return 0; ++ ++ if (regmap_read(pll->clkr.regmap, PLL_USER_CTL(pll), &ctl)) ++ return 0; + +- regmap_read(pll->clkr.regmap, PLL_USER_CTL(pll), &ctl); + if (ctl & PLL_ALPHA_EN) { +- regmap_read(pll->clkr.regmap, PLL_ALPHA_VAL(pll), &low); ++ if (regmap_read(pll->clkr.regmap, PLL_ALPHA_VAL(pll), &low)) ++ return 0; + if (alpha_width > 32) { +- regmap_read(pll->clkr.regmap, PLL_ALPHA_VAL_U(pll), +- &high); ++ if (regmap_read(pll->clkr.regmap, PLL_ALPHA_VAL_U(pll), ++ &high)) ++ return 0; + a = (u64)high << 32 | low; + } else { + a = low & GENMASK(alpha_width - 1, 0); +@@ -942,8 +947,11 @@ alpha_pll_huayra_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) + struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); + u32 l, alpha = 0, ctl, alpha_m, alpha_n; + +- regmap_read(pll->clkr.regmap, PLL_L_VAL(pll), &l); +- regmap_read(pll->clkr.regmap, PLL_USER_CTL(pll), &ctl); ++ if (regmap_read(pll->clkr.regmap, PLL_L_VAL(pll), &l)) ++ return 0; ++ ++ if (regmap_read(pll->clkr.regmap, PLL_USER_CTL(pll), &ctl)) ++ return 0; + + if (ctl & PLL_ALPHA_EN) { + regmap_read(pll->clkr.regmap, PLL_ALPHA_VAL(pll), &alpha); +@@ -1137,8 +1145,11 @@ clk_trion_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) + struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); + u32 l, frac, alpha_width = pll_alpha_width(pll); + +- regmap_read(pll->clkr.regmap, PLL_L_VAL(pll), &l); +- regmap_read(pll->clkr.regmap, PLL_ALPHA_VAL(pll), &frac); ++ if (regmap_read(pll->clkr.regmap, PLL_L_VAL(pll), &l)) ++ return 0; ++ ++ if (regmap_read(pll->clkr.regmap, PLL_ALPHA_VAL(pll), &frac)) ++ return 0; + + return alpha_pll_calc_rate(parent_rate, l, frac, alpha_width); + } +@@ -1196,7 +1207,8 @@ clk_alpha_pll_postdiv_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) + struct clk_alpha_pll_postdiv *pll = to_clk_alpha_pll_postdiv(hw); + u32 ctl; + +- regmap_read(pll->clkr.regmap, PLL_USER_CTL(pll), &ctl); ++ if (regmap_read(pll->clkr.regmap, PLL_USER_CTL(pll), &ctl)) ++ return 0; + + ctl >>= PLL_POST_DIV_SHIFT; + ctl &= PLL_POST_DIV_MASK(pll); +@@ -1412,8 +1424,11 @@ static unsigned long alpha_pll_fabia_recalc_rate(struct clk_hw *hw, + struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); + u32 l, frac, alpha_width = pll_alpha_width(pll); + +- regmap_read(pll->clkr.regmap, PLL_L_VAL(pll), &l); +- regmap_read(pll->clkr.regmap, PLL_FRAC(pll), &frac); ++ if (regmap_read(pll->clkr.regmap, PLL_L_VAL(pll), &l)) ++ return 0; ++ ++ if (regmap_read(pll->clkr.regmap, PLL_FRAC(pll), &frac)) ++ return 0; + + return alpha_pll_calc_rate(parent_rate, l, frac, alpha_width); + } +@@ -1563,7 +1578,8 @@ clk_trion_pll_postdiv_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) + struct regmap *regmap = pll->clkr.regmap; + u32 i, div = 1, val; + +- regmap_read(regmap, PLL_USER_CTL(pll), &val); ++ if (regmap_read(regmap, PLL_USER_CTL(pll), &val)) ++ return 0; + + val >>= pll->post_div_shift; + val &= PLL_POST_DIV_MASK(pll); +@@ -2484,9 +2500,12 @@ static unsigned long alpha_pll_lucid_evo_recalc_rate(struct clk_hw *hw, + struct regmap *regmap = pll->clkr.regmap; + u32 l, frac; + +- regmap_read(regmap, PLL_L_VAL(pll), &l); ++ if (regmap_read(regmap, PLL_L_VAL(pll), &l)) ++ return 0; + l &= LUCID_EVO_PLL_L_VAL_MASK; +- regmap_read(regmap, PLL_ALPHA_VAL(pll), &frac); ++ ++ if (regmap_read(regmap, PLL_ALPHA_VAL(pll), &frac)) ++ return 0; + + return alpha_pll_calc_rate(parent_rate, l, frac, pll_alpha_width(pll)); + } +@@ -2699,7 +2718,8 @@ static unsigned long clk_rivian_evo_pll_recalc_rate(struct clk_hw *hw, + struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); + u32 l; + +- regmap_read(pll->clkr.regmap, PLL_L_VAL(pll), &l); ++ if (regmap_read(pll->clkr.regmap, PLL_L_VAL(pll), &l)) ++ return 0; + + return parent_rate * l; + } +-- +2.39.5 + diff --git a/queue-6.14/clk-qcom-ipq5018-allow-it-to-be-bulid-on-arm32.patch b/queue-6.14/clk-qcom-ipq5018-allow-it-to-be-bulid-on-arm32.patch new file mode 100644 index 0000000000..7dc6368a9e --- /dev/null +++ b/queue-6.14/clk-qcom-ipq5018-allow-it-to-be-bulid-on-arm32.patch @@ -0,0 +1,40 @@ +From e28592b361b940858d6aee1459c15b7f642b43e7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 8 Oct 2024 00:34:12 +0800 +Subject: clk: qcom: ipq5018: allow it to be bulid on arm32 + +From: Karl Chan + +[ Upstream commit 5d02941c83997b58e8fc15390290c7c6975acaff ] + +There are some ipq5018 based device's firmware only can able to boot +arm32 but the clock driver dont allow it to be compiled on arm32. +Therefore allow GCC for IPQ5018 to be selected when building ARM32 +kernel + +Signed-off-by: Karl Chan +Reviewed-by: Dmitry Baryshkov +Link: https://lore.kernel.org/r/20241007163414.32458-4-exxxxkc@getgoogleoff.me +[bjorn: Updated commit message, per Dmitry's suggestion] +Signed-off-by: Bjorn Andersson +Signed-off-by: Sasha Levin +--- + drivers/clk/qcom/Kconfig | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig +index 69bbf62ba3cd7..d470ed007854c 100644 +--- a/drivers/clk/qcom/Kconfig ++++ b/drivers/clk/qcom/Kconfig +@@ -217,7 +217,7 @@ config IPQ_GCC_4019 + + config IPQ_GCC_5018 + tristate "IPQ5018 Global Clock Controller" +- depends on ARM64 || COMPILE_TEST ++ depends on ARM || ARM64 || COMPILE_TEST + help + Support for global clock controller on ipq5018 devices. + Say Y if you want to use peripheral devices such as UART, SPI, +-- +2.39.5 + diff --git a/queue-6.14/clk-qcom-lpassaudiocc-sc7280-add-support-for-lpass-r.patch b/queue-6.14/clk-qcom-lpassaudiocc-sc7280-add-support-for-lpass-r.patch new file mode 100644 index 0000000000..492630cc51 --- /dev/null +++ b/queue-6.14/clk-qcom-lpassaudiocc-sc7280-add-support-for-lpass-r.patch @@ -0,0 +1,95 @@ +From e1e21cc754be891f99d9af28b849888f7b83eba2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 21 Feb 2025 15:04:55 +0530 +Subject: clk: qcom: lpassaudiocc-sc7280: Add support for LPASS resets for + QCM6490 + +From: Taniya Das + +[ Upstream commit cdbbc480f4146cb659af97f4020601fde5fb65a7 ] + +On the QCM6490 boards, the LPASS firmware controls the complete clock +controller functionalities and associated power domains. However, only +the LPASS resets required to be controlled by the high level OS. Thus, +add support for the resets in the clock driver to enable the Audio SW +driver to assert/deassert the audio resets as needed. + +Reviewed-by: Dmitry Baryshkov +Signed-off-by: Taniya Das +Link: https://lore.kernel.org/r/20250221-lpass_qcm6490_resets-v5-2-6be0c0949a83@quicinc.com +Signed-off-by: Bjorn Andersson +Signed-off-by: Sasha Levin +--- + drivers/clk/qcom/lpassaudiocc-sc7280.c | 23 +++++++++++++++++++---- + 1 file changed, 19 insertions(+), 4 deletions(-) + +diff --git a/drivers/clk/qcom/lpassaudiocc-sc7280.c b/drivers/clk/qcom/lpassaudiocc-sc7280.c +index 45e7264770866..22169da08a51a 100644 +--- a/drivers/clk/qcom/lpassaudiocc-sc7280.c ++++ b/drivers/clk/qcom/lpassaudiocc-sc7280.c +@@ -1,6 +1,7 @@ + // SPDX-License-Identifier: GPL-2.0-only + /* + * Copyright (c) 2021, The Linux Foundation. All rights reserved. ++ * Copyright (c) 2025, Qualcomm Innovation Center, Inc. All rights reserved. + */ + + #include +@@ -713,14 +714,24 @@ static const struct qcom_reset_map lpass_audio_cc_sc7280_resets[] = { + [LPASS_AUDIO_SWR_WSA_CGCR] = { 0xb0, 1 }, + }; + ++static const struct regmap_config lpass_audio_cc_sc7280_reset_regmap_config = { ++ .name = "lpassaudio_cc_reset", ++ .reg_bits = 32, ++ .reg_stride = 4, ++ .val_bits = 32, ++ .fast_io = true, ++ .max_register = 0xc8, ++}; ++ + static const struct qcom_cc_desc lpass_audio_cc_reset_sc7280_desc = { +- .config = &lpass_audio_cc_sc7280_regmap_config, ++ .config = &lpass_audio_cc_sc7280_reset_regmap_config, + .resets = lpass_audio_cc_sc7280_resets, + .num_resets = ARRAY_SIZE(lpass_audio_cc_sc7280_resets), + }; + + static const struct of_device_id lpass_audio_cc_sc7280_match_table[] = { +- { .compatible = "qcom,sc7280-lpassaudiocc" }, ++ { .compatible = "qcom,qcm6490-lpassaudiocc", .data = &lpass_audio_cc_reset_sc7280_desc }, ++ { .compatible = "qcom,sc7280-lpassaudiocc", .data = &lpass_audio_cc_sc7280_desc }, + { } + }; + MODULE_DEVICE_TABLE(of, lpass_audio_cc_sc7280_match_table); +@@ -752,13 +763,17 @@ static int lpass_audio_cc_sc7280_probe(struct platform_device *pdev) + struct regmap *regmap; + int ret; + ++ desc = device_get_match_data(&pdev->dev); ++ ++ if (of_device_is_compatible(pdev->dev.of_node, "qcom,qcm6490-lpassaudiocc")) ++ return qcom_cc_probe_by_index(pdev, 1, desc); ++ + ret = lpass_audio_setup_runtime_pm(pdev); + if (ret) + return ret; + + lpass_audio_cc_sc7280_regmap_config.name = "lpassaudio_cc"; + lpass_audio_cc_sc7280_regmap_config.max_register = 0x2f000; +- desc = &lpass_audio_cc_sc7280_desc; + + regmap = qcom_cc_map(pdev, desc); + if (IS_ERR(regmap)) { +@@ -772,7 +787,7 @@ static int lpass_audio_cc_sc7280_probe(struct platform_device *pdev) + regmap_write(regmap, 0x4, 0x3b); + regmap_write(regmap, 0x8, 0xff05); + +- ret = qcom_cc_really_probe(&pdev->dev, &lpass_audio_cc_sc7280_desc, regmap); ++ ret = qcom_cc_really_probe(&pdev->dev, desc, regmap); + if (ret) { + dev_err(&pdev->dev, "Failed to register LPASS AUDIO CC clocks\n"); + goto exit; +-- +2.39.5 + diff --git a/queue-6.14/clk-renesas-rzg2l-cpg-refactor-runtime-pm-clock-vali.patch b/queue-6.14/clk-renesas-rzg2l-cpg-refactor-runtime-pm-clock-vali.patch new file mode 100644 index 0000000000..ad0076967b --- /dev/null +++ b/queue-6.14/clk-renesas-rzg2l-cpg-refactor-runtime-pm-clock-vali.patch @@ -0,0 +1,165 @@ +From dd7aded6545163b9011b481775bfabe916569497 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 16 Dec 2024 21:02:01 +0000 +Subject: clk: renesas: rzg2l-cpg: Refactor Runtime PM clock validation + +From: Lad Prabhakar + +[ Upstream commit f6f73b891bf6beff069fcacc7b4a796e1009bf26 ] + +Refactor rzg2l_cpg_attach_dev to delegate clock validation for Runtime PM +to the updated rzg2l_cpg_is_pm_clk function. Ensure validation of clocks +associated with the power domain while excluding external and core clocks. +Prevent incorrect Runtime PM management for clocks outside the domain's +scope. + +Update rzg2l_cpg_is_pm_clk to operate on a per-power-domain basis. Verify +clkspec.np against the domain's device node, check argument validity, and +validate clock type (CPG_MOD). Use the no_pm_mod_clks array to exclude +specific clocks from PM management. + +Signed-off-by: Lad Prabhakar +Reviewed-by: Geert Uytterhoeven +Link: https://lore.kernel.org/20241216210201.239855-1-prabhakar.mahadev-lad.rj@bp.renesas.com +Signed-off-by: Geert Uytterhoeven +Signed-off-by: Sasha Levin +--- + drivers/clk/renesas/rzg2l-cpg.c | 102 +++++++++++++++++--------------- + 1 file changed, 54 insertions(+), 48 deletions(-) + +diff --git a/drivers/clk/renesas/rzg2l-cpg.c b/drivers/clk/renesas/rzg2l-cpg.c +index 4bd8862dc82be..91928db411dcd 100644 +--- a/drivers/clk/renesas/rzg2l-cpg.c ++++ b/drivers/clk/renesas/rzg2l-cpg.c +@@ -1549,28 +1549,6 @@ static int rzg2l_cpg_reset_controller_register(struct rzg2l_cpg_priv *priv) + return devm_reset_controller_register(priv->dev, &priv->rcdev); + } + +-static bool rzg2l_cpg_is_pm_clk(struct rzg2l_cpg_priv *priv, +- const struct of_phandle_args *clkspec) +-{ +- const struct rzg2l_cpg_info *info = priv->info; +- unsigned int id; +- unsigned int i; +- +- if (clkspec->args_count != 2) +- return false; +- +- if (clkspec->args[0] != CPG_MOD) +- return false; +- +- id = clkspec->args[1] + info->num_total_core_clks; +- for (i = 0; i < info->num_no_pm_mod_clks; i++) { +- if (info->no_pm_mod_clks[i] == id) +- return false; +- } +- +- return true; +-} +- + /** + * struct rzg2l_cpg_pm_domains - RZ/G2L PM domains data structure + * @onecell_data: cell data +@@ -1595,45 +1573,73 @@ struct rzg2l_cpg_pd { + u16 id; + }; + ++static bool rzg2l_cpg_is_pm_clk(struct rzg2l_cpg_pd *pd, ++ const struct of_phandle_args *clkspec) ++{ ++ if (clkspec->np != pd->genpd.dev.of_node || clkspec->args_count != 2) ++ return false; ++ ++ switch (clkspec->args[0]) { ++ case CPG_MOD: { ++ struct rzg2l_cpg_priv *priv = pd->priv; ++ const struct rzg2l_cpg_info *info = priv->info; ++ unsigned int id = clkspec->args[1]; ++ ++ if (id >= priv->num_mod_clks) ++ return false; ++ ++ id += info->num_total_core_clks; ++ ++ for (unsigned int i = 0; i < info->num_no_pm_mod_clks; i++) { ++ if (info->no_pm_mod_clks[i] == id) ++ return false; ++ } ++ ++ return true; ++ } ++ ++ case CPG_CORE: ++ default: ++ return false; ++ } ++} ++ + static int rzg2l_cpg_attach_dev(struct generic_pm_domain *domain, struct device *dev) + { + struct rzg2l_cpg_pd *pd = container_of(domain, struct rzg2l_cpg_pd, genpd); +- struct rzg2l_cpg_priv *priv = pd->priv; + struct device_node *np = dev->of_node; + struct of_phandle_args clkspec; + bool once = true; + struct clk *clk; ++ unsigned int i; + int error; +- int i = 0; +- +- while (!of_parse_phandle_with_args(np, "clocks", "#clock-cells", i, +- &clkspec)) { +- if (rzg2l_cpg_is_pm_clk(priv, &clkspec)) { +- if (once) { +- once = false; +- error = pm_clk_create(dev); +- if (error) { +- of_node_put(clkspec.np); +- goto err; +- } +- } +- clk = of_clk_get_from_provider(&clkspec); ++ ++ for (i = 0; !of_parse_phandle_with_args(np, "clocks", "#clock-cells", i, &clkspec); i++) { ++ if (!rzg2l_cpg_is_pm_clk(pd, &clkspec)) { + of_node_put(clkspec.np); +- if (IS_ERR(clk)) { +- error = PTR_ERR(clk); +- goto fail_destroy; +- } ++ continue; ++ } + +- error = pm_clk_add_clk(dev, clk); ++ if (once) { ++ once = false; ++ error = pm_clk_create(dev); + if (error) { +- dev_err(dev, "pm_clk_add_clk failed %d\n", +- error); +- goto fail_put; ++ of_node_put(clkspec.np); ++ goto err; + } +- } else { +- of_node_put(clkspec.np); + } +- i++; ++ clk = of_clk_get_from_provider(&clkspec); ++ of_node_put(clkspec.np); ++ if (IS_ERR(clk)) { ++ error = PTR_ERR(clk); ++ goto fail_destroy; ++ } ++ ++ error = pm_clk_add_clk(dev, clk); ++ if (error) { ++ dev_err(dev, "pm_clk_add_clk failed %d\n", error); ++ goto fail_put; ++ } + } + + return 0; +-- +2.39.5 + diff --git a/queue-6.14/clk-sunxi-ng-h616-reparent-gpu-clock-during-frequenc.patch b/queue-6.14/clk-sunxi-ng-h616-reparent-gpu-clock-during-frequenc.patch new file mode 100644 index 0000000000..d5b74f397b --- /dev/null +++ b/queue-6.14/clk-sunxi-ng-h616-reparent-gpu-clock-during-frequenc.patch @@ -0,0 +1,103 @@ +From abf286553b07f40eaeb2f98f4f5d211142a31d42 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 20 Feb 2025 12:38:08 +0100 +Subject: clk: sunxi-ng: h616: Reparent GPU clock during frequency changes + +From: Philippe Simons + +[ Upstream commit eb963d7948ce6571939c6875424b557b25f16610 ] + +The H616 manual does not state that the GPU PLL supports +dynamic frequency configuration, so we must take extra care when changing +the frequency. Currently any attempt to do device DVFS on the GPU lead +to panfrost various ooops, and GPU hangs. + +The manual describes the algorithm for changing the PLL +frequency, which the CPU PLL notifier code already support, so we reuse +that to reparent the GPU clock to GPU1 clock during frequency +changes. + +Signed-off-by: Philippe Simons +Reviewed-by: Andre Przywara +Reviewed-by: Jernej Skrabec +Link: https://patch.msgid.link/20250220113808.1122414-2-simons.philippe@gmail.com +Signed-off-by: Chen-Yu Tsai +Signed-off-by: Sasha Levin +--- + drivers/clk/sunxi-ng/ccu-sun50i-h616.c | 36 +++++++++++++++++++++++++- + 1 file changed, 35 insertions(+), 1 deletion(-) + +diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-h616.c b/drivers/clk/sunxi-ng/ccu-sun50i-h616.c +index 190816c35da9f..6050cbfa922e2 100644 +--- a/drivers/clk/sunxi-ng/ccu-sun50i-h616.c ++++ b/drivers/clk/sunxi-ng/ccu-sun50i-h616.c +@@ -328,10 +328,16 @@ static SUNXI_CCU_M_WITH_MUX_GATE(gpu0_clk, "gpu0", gpu0_parents, 0x670, + 24, 1, /* mux */ + BIT(31), /* gate */ + CLK_SET_RATE_PARENT); ++ ++/* ++ * This clk is needed as a temporary fall back during GPU PLL freq changes. ++ * Set CLK_IS_CRITICAL flag to prevent from being disabled. ++ */ ++#define SUN50I_H616_GPU_CLK1_REG 0x674 + static SUNXI_CCU_M_WITH_GATE(gpu1_clk, "gpu1", "pll-periph0-2x", 0x674, + 0, 2, /* M */ + BIT(31),/* gate */ +- 0); ++ CLK_IS_CRITICAL); + + static SUNXI_CCU_GATE(bus_gpu_clk, "bus-gpu", "psi-ahb1-ahb2", + 0x67c, BIT(0), 0); +@@ -1120,6 +1126,19 @@ static struct ccu_pll_nb sun50i_h616_pll_cpu_nb = { + .lock = BIT(28), + }; + ++static struct ccu_mux_nb sun50i_h616_gpu_nb = { ++ .common = &gpu0_clk.common, ++ .cm = &gpu0_clk.mux, ++ .delay_us = 1, /* manual doesn't really say */ ++ .bypass_index = 1, /* GPU_CLK1@400MHz */ ++}; ++ ++static struct ccu_pll_nb sun50i_h616_pll_gpu_nb = { ++ .common = &pll_gpu_clk.common, ++ .enable = BIT(29), /* LOCK_ENABLE */ ++ .lock = BIT(28), ++}; ++ + static int sun50i_h616_ccu_probe(struct platform_device *pdev) + { + void __iomem *reg; +@@ -1170,6 +1189,14 @@ static int sun50i_h616_ccu_probe(struct platform_device *pdev) + val |= BIT(0); + writel(val, reg + SUN50I_H616_PLL_AUDIO_REG); + ++ /* ++ * Set the input-divider for the gpu1 clock to 3, to reach a safe 400 MHz. ++ */ ++ val = readl(reg + SUN50I_H616_GPU_CLK1_REG); ++ val &= ~GENMASK(1, 0); ++ val |= 2; ++ writel(val, reg + SUN50I_H616_GPU_CLK1_REG); ++ + /* + * First clock parent (osc32K) is unusable for CEC. But since there + * is no good way to force parent switch (both run with same frequency), +@@ -1190,6 +1217,13 @@ static int sun50i_h616_ccu_probe(struct platform_device *pdev) + /* Re-lock the CPU PLL after any rate changes */ + ccu_pll_notifier_register(&sun50i_h616_pll_cpu_nb); + ++ /* Reparent GPU during GPU PLL rate changes */ ++ ccu_mux_notifier_register(pll_gpu_clk.common.hw.clk, ++ &sun50i_h616_gpu_nb); ++ ++ /* Re-lock the GPU PLL after any rate changes */ ++ ccu_pll_notifier_register(&sun50i_h616_pll_gpu_nb); ++ + return 0; + } + +-- +2.39.5 + diff --git a/queue-6.14/clocksource-drivers-timer-riscv-stop-stimecmp-when-c.patch b/queue-6.14/clocksource-drivers-timer-riscv-stop-stimecmp-when-c.patch new file mode 100644 index 0000000000..15409e8f44 --- /dev/null +++ b/queue-6.14/clocksource-drivers-timer-riscv-stop-stimecmp-when-c.patch @@ -0,0 +1,45 @@ +From 452f0251b89f2545a122cc9273211224b349d5b2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 19 Feb 2025 19:41:35 +0800 +Subject: clocksource/drivers/timer-riscv: Stop stimecmp when cpu hotplug + +From: Nick Hu + +[ Upstream commit 70c93b026ed07078e933583591aa9ca6701cd9da ] + +Stop the timer when the cpu is going to be offline otherwise the +timer interrupt may be pending while performing power-down. + +Suggested-by: Anup Patel +Link: https://lore.kernel.org/lkml/20240829033904.477200-3-nick.hu@sifive.com/T/#u +Signed-off-by: Nick Hu +Reviewed-by: Anup Patel +Acked-by: Daniel Lezcano +Link: https://lore.kernel.org/r/20250219114135.27764-3-nick.hu@sifive.com +Signed-off-by: Alexandre Ghiti +Signed-off-by: Sasha Levin +--- + drivers/clocksource/timer-riscv.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/drivers/clocksource/timer-riscv.c b/drivers/clocksource/timer-riscv.c +index 48ce50c5f5e68..4d7cf338824a3 100644 +--- a/drivers/clocksource/timer-riscv.c ++++ b/drivers/clocksource/timer-riscv.c +@@ -126,7 +126,13 @@ static int riscv_timer_starting_cpu(unsigned int cpu) + + static int riscv_timer_dying_cpu(unsigned int cpu) + { ++ /* ++ * Stop the timer when the cpu is going to be offline otherwise ++ * the timer interrupt may be pending while performing power-down. ++ */ ++ riscv_clock_event_stop(); + disable_percpu_irq(riscv_clock_event_irq); ++ + return 0; + } + +-- +2.39.5 + diff --git a/queue-6.14/clocksource-mips-gic-timer-enable-counter-when-cpus-.patch b/queue-6.14/clocksource-mips-gic-timer-enable-counter-when-cpus-.patch new file mode 100644 index 0000000000..826d1f411d --- /dev/null +++ b/queue-6.14/clocksource-mips-gic-timer-enable-counter-when-cpus-.patch @@ -0,0 +1,68 @@ +From ee8206dced1f1bb3c86cf8bf6aa0ade3c7bbc03b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 29 Jan 2025 13:32:47 +0100 +Subject: clocksource: mips-gic-timer: Enable counter when CPUs start +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Paul Burton + +[ Upstream commit 3128b0a2e0cf6e07aa78e5f8cf7dd9cd59dc8174 ] + +In multi-cluster MIPS I6500 systems there is a GIC in each cluster, +each with its own counter. When a cluster powers up the counter will +be stopped, with the COUNTSTOP bit set in the GIC_CONFIG register. + +In single cluster systems, it has been fine to clear COUNTSTOP once +in gic_clocksource_of_init() to start the counter. In multi-cluster +systems, this will only have started the counter in the boot cluster, +and any CPUs in other clusters will find their counter stopped which +will break the GIC clock_event_device. + +Resolve this by having CPUs clear the COUNTSTOP bit when they come +online, using the existing gic_starting_cpu() CPU hotplug callback. This +will allow CPUs in secondary clusters to ensure that the cluster's GIC +counter is running as expected. + +Signed-off-by: Paul Burton +Signed-off-by: Chao-ying Fu +Signed-off-by: Dragan Mladjenovic +Signed-off-by: Aleksandar Rikalo +Reviewed-by: Philippe Mathieu-Daudé +Tested-by: Serge Semin +Tested-by: Gregory CLEMENT +Acked-by: Daniel Lezcano +Signed-off-by: Thomas Bogendoerfer +Signed-off-by: Sasha Levin +--- + drivers/clocksource/mips-gic-timer.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/clocksource/mips-gic-timer.c b/drivers/clocksource/mips-gic-timer.c +index 7907b740497a5..abb685a080a5b 100644 +--- a/drivers/clocksource/mips-gic-timer.c ++++ b/drivers/clocksource/mips-gic-timer.c +@@ -115,6 +115,9 @@ static void gic_update_frequency(void *data) + + static int gic_starting_cpu(unsigned int cpu) + { ++ /* Ensure the GIC counter is running */ ++ clear_gic_config(GIC_CONFIG_COUNTSTOP); ++ + gic_clockevent_cpu_init(cpu, this_cpu_ptr(&gic_clockevent_device)); + return 0; + } +@@ -288,9 +291,6 @@ static int __init gic_clocksource_of_init(struct device_node *node) + pr_warn("Unable to register clock notifier\n"); + } + +- /* And finally start the counter */ +- clear_gic_config(GIC_CONFIG_COUNTSTOP); +- + /* + * It's safe to use the MIPS GIC timer as a sched clock source only if + * its ticks are stable, which is true on either the platforms with +-- +2.39.5 + diff --git a/queue-6.14/coresight-change-coresight_trace_id_map-s-lock-type-.patch b/queue-6.14/coresight-change-coresight_trace_id_map-s-lock-type-.patch new file mode 100644 index 0000000000..01f6d34cf9 --- /dev/null +++ b/queue-6.14/coresight-change-coresight_trace_id_map-s-lock-type-.patch @@ -0,0 +1,143 @@ +From a7d4ef4a96f212a070eb5307084b91b68d82a792 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Mar 2025 12:11:04 +0000 +Subject: coresight: change coresight_trace_id_map's lock type to + raw_spinlock_t + +From: Yeoreum Yun + +[ Upstream commit 4cf364ca57d851e192ce02e98d314d22fa514895 ] + +coresight_trace_id_map->lock can be acquired while coresight devices' +drvdata_lock. + +But the drvdata_lock can be raw_spinlock_t (i.e) coresight-etm4x. + +To address this, change type of coresight_trace_id_map->lock to +raw_spinlock_t + +Signed-off-by: Yeoreum Yun +Reviewed-by: James Clark +Reviewed-by: Mike Leach +Signed-off-by: Suzuki K Poulose +Link: https://lore.kernel.org/r/20250306121110.1647948-4-yeoreum.yun@arm.com +Signed-off-by: Sasha Levin +--- + drivers/hwtracing/coresight/coresight-core.c | 2 +- + .../hwtracing/coresight/coresight-trace-id.c | 22 +++++++++---------- + include/linux/coresight.h | 2 +- + 3 files changed, 13 insertions(+), 13 deletions(-) + +diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c +index 4936dc2f7a56b..4fe837b02e314 100644 +--- a/drivers/hwtracing/coresight/coresight-core.c ++++ b/drivers/hwtracing/coresight/coresight-core.c +@@ -1249,7 +1249,7 @@ struct coresight_device *coresight_register(struct coresight_desc *desc) + + if (csdev->type == CORESIGHT_DEV_TYPE_SINK || + csdev->type == CORESIGHT_DEV_TYPE_LINKSINK) { +- spin_lock_init(&csdev->perf_sink_id_map.lock); ++ raw_spin_lock_init(&csdev->perf_sink_id_map.lock); + csdev->perf_sink_id_map.cpu_map = alloc_percpu(atomic_t); + if (!csdev->perf_sink_id_map.cpu_map) { + kfree(csdev); +diff --git a/drivers/hwtracing/coresight/coresight-trace-id.c b/drivers/hwtracing/coresight/coresight-trace-id.c +index 378af743be455..7ed337d54d3e3 100644 +--- a/drivers/hwtracing/coresight/coresight-trace-id.c ++++ b/drivers/hwtracing/coresight/coresight-trace-id.c +@@ -22,7 +22,7 @@ enum trace_id_flags { + static DEFINE_PER_CPU(atomic_t, id_map_default_cpu_ids) = ATOMIC_INIT(0); + static struct coresight_trace_id_map id_map_default = { + .cpu_map = &id_map_default_cpu_ids, +- .lock = __SPIN_LOCK_UNLOCKED(id_map_default.lock) ++ .lock = __RAW_SPIN_LOCK_UNLOCKED(id_map_default.lock) + }; + + /* #define TRACE_ID_DEBUG 1 */ +@@ -131,11 +131,11 @@ static void coresight_trace_id_release_all(struct coresight_trace_id_map *id_map + unsigned long flags; + int cpu; + +- spin_lock_irqsave(&id_map->lock, flags); ++ raw_spin_lock_irqsave(&id_map->lock, flags); + bitmap_zero(id_map->used_ids, CORESIGHT_TRACE_IDS_MAX); + for_each_possible_cpu(cpu) + atomic_set(per_cpu_ptr(id_map->cpu_map, cpu), 0); +- spin_unlock_irqrestore(&id_map->lock, flags); ++ raw_spin_unlock_irqrestore(&id_map->lock, flags); + DUMP_ID_MAP(id_map); + } + +@@ -144,7 +144,7 @@ static int _coresight_trace_id_get_cpu_id(int cpu, struct coresight_trace_id_map + unsigned long flags; + int id; + +- spin_lock_irqsave(&id_map->lock, flags); ++ raw_spin_lock_irqsave(&id_map->lock, flags); + + /* check for existing allocation for this CPU */ + id = _coresight_trace_id_read_cpu_id(cpu, id_map); +@@ -171,7 +171,7 @@ static int _coresight_trace_id_get_cpu_id(int cpu, struct coresight_trace_id_map + atomic_set(per_cpu_ptr(id_map->cpu_map, cpu), id); + + get_cpu_id_out_unlock: +- spin_unlock_irqrestore(&id_map->lock, flags); ++ raw_spin_unlock_irqrestore(&id_map->lock, flags); + + DUMP_ID_CPU(cpu, id); + DUMP_ID_MAP(id_map); +@@ -188,12 +188,12 @@ static void _coresight_trace_id_put_cpu_id(int cpu, struct coresight_trace_id_ma + if (!id) + return; + +- spin_lock_irqsave(&id_map->lock, flags); ++ raw_spin_lock_irqsave(&id_map->lock, flags); + + coresight_trace_id_free(id, id_map); + atomic_set(per_cpu_ptr(id_map->cpu_map, cpu), 0); + +- spin_unlock_irqrestore(&id_map->lock, flags); ++ raw_spin_unlock_irqrestore(&id_map->lock, flags); + DUMP_ID_CPU(cpu, id); + DUMP_ID_MAP(id_map); + } +@@ -204,9 +204,9 @@ static int coresight_trace_id_map_get_system_id(struct coresight_trace_id_map *i + unsigned long flags; + int id; + +- spin_lock_irqsave(&id_map->lock, flags); ++ raw_spin_lock_irqsave(&id_map->lock, flags); + id = coresight_trace_id_alloc_new_id(id_map, preferred_id, traceid_flags); +- spin_unlock_irqrestore(&id_map->lock, flags); ++ raw_spin_unlock_irqrestore(&id_map->lock, flags); + + DUMP_ID(id); + DUMP_ID_MAP(id_map); +@@ -217,9 +217,9 @@ static void coresight_trace_id_map_put_system_id(struct coresight_trace_id_map * + { + unsigned long flags; + +- spin_lock_irqsave(&id_map->lock, flags); ++ raw_spin_lock_irqsave(&id_map->lock, flags); + coresight_trace_id_free(id, id_map); +- spin_unlock_irqrestore(&id_map->lock, flags); ++ raw_spin_unlock_irqrestore(&id_map->lock, flags); + + DUMP_ID(id); + DUMP_ID_MAP(id_map); +diff --git a/include/linux/coresight.h b/include/linux/coresight.h +index 6ddcbb8be5165..d5ca0292550b2 100644 +--- a/include/linux/coresight.h ++++ b/include/linux/coresight.h +@@ -238,7 +238,7 @@ struct coresight_trace_id_map { + DECLARE_BITMAP(used_ids, CORESIGHT_TRACE_IDS_MAX); + atomic_t __percpu *cpu_map; + atomic_t perf_cs_etm_session_active; +- spinlock_t lock; ++ raw_spinlock_t lock; + }; + + /** +-- +2.39.5 + diff --git a/queue-6.14/coresight-etb10-change-etb_drvdata-spinlock-s-type-t.patch b/queue-6.14/coresight-etb10-change-etb_drvdata-spinlock-s-type-t.patch new file mode 100644 index 0000000000..efedfd2724 --- /dev/null +++ b/queue-6.14/coresight-etb10-change-etb_drvdata-spinlock-s-type-t.patch @@ -0,0 +1,149 @@ +From c9dfeffe7703fb5208b8a73d1b276069bc018247 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Mar 2025 12:11:06 +0000 +Subject: coresight-etb10: change etb_drvdata spinlock's type to raw_spinlock_t + +From: Yeoreum Yun + +[ Upstream commit 6b80c0abe475ed1017c5e862636049aa1cc17a1a ] + +In coresight-etb10 drivers, etb_drvdata->spinlock can be held +during __schedule() by perf_event_task_sched_out()/in(). + +Since etb_drvdata->spinlock type is spinlock_t and +perf_event_task_sched_out()/in() is called after acquiring rq_lock, +which is raw_spinlock_t (an unsleepable lock), +this poses an issue in PREEMPT_RT kernel where spinlock_t is sleepable. + +To address this, change type etb_drvdata->spinlock in coresight-etb10 drivers, +which can be called by perf_event_task_sched_out()/in(), +from spinlock_t to raw_spinlock_t. + +Reviewed-by: James Clark +Reviewed-by: Mike Leach +Signed-off-by: Yeoreum Yun +Signed-off-by: Suzuki K Poulose +Link: https://lore.kernel.org/r/20250306121110.1647948-6-yeoreum.yun@arm.com +Signed-off-by: Sasha Levin +--- + drivers/hwtracing/coresight/coresight-etb10.c | 26 +++++++++---------- + 1 file changed, 13 insertions(+), 13 deletions(-) + +diff --git a/drivers/hwtracing/coresight/coresight-etb10.c b/drivers/hwtracing/coresight/coresight-etb10.c +index aea9ac9c4bd06..7948597d483d2 100644 +--- a/drivers/hwtracing/coresight/coresight-etb10.c ++++ b/drivers/hwtracing/coresight/coresight-etb10.c +@@ -84,7 +84,7 @@ struct etb_drvdata { + struct clk *atclk; + struct coresight_device *csdev; + struct miscdevice miscdev; +- spinlock_t spinlock; ++ raw_spinlock_t spinlock; + local_t reading; + pid_t pid; + u8 *buf; +@@ -145,7 +145,7 @@ static int etb_enable_sysfs(struct coresight_device *csdev) + unsigned long flags; + struct etb_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); + +- spin_lock_irqsave(&drvdata->spinlock, flags); ++ raw_spin_lock_irqsave(&drvdata->spinlock, flags); + + /* Don't messup with perf sessions. */ + if (coresight_get_mode(csdev) == CS_MODE_PERF) { +@@ -163,7 +163,7 @@ static int etb_enable_sysfs(struct coresight_device *csdev) + + csdev->refcnt++; + out: +- spin_unlock_irqrestore(&drvdata->spinlock, flags); ++ raw_spin_unlock_irqrestore(&drvdata->spinlock, flags); + return ret; + } + +@@ -176,7 +176,7 @@ static int etb_enable_perf(struct coresight_device *csdev, void *data) + struct perf_output_handle *handle = data; + struct cs_buffers *buf = etm_perf_sink_config(handle); + +- spin_lock_irqsave(&drvdata->spinlock, flags); ++ raw_spin_lock_irqsave(&drvdata->spinlock, flags); + + /* No need to continue if the component is already in used by sysFS. */ + if (coresight_get_mode(drvdata->csdev) == CS_MODE_SYSFS) { +@@ -219,7 +219,7 @@ static int etb_enable_perf(struct coresight_device *csdev, void *data) + } + + out: +- spin_unlock_irqrestore(&drvdata->spinlock, flags); ++ raw_spin_unlock_irqrestore(&drvdata->spinlock, flags); + return ret; + } + +@@ -352,11 +352,11 @@ static int etb_disable(struct coresight_device *csdev) + struct etb_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); + unsigned long flags; + +- spin_lock_irqsave(&drvdata->spinlock, flags); ++ raw_spin_lock_irqsave(&drvdata->spinlock, flags); + + csdev->refcnt--; + if (csdev->refcnt) { +- spin_unlock_irqrestore(&drvdata->spinlock, flags); ++ raw_spin_unlock_irqrestore(&drvdata->spinlock, flags); + return -EBUSY; + } + +@@ -366,7 +366,7 @@ static int etb_disable(struct coresight_device *csdev) + /* Dissociate from monitored process. */ + drvdata->pid = -1; + coresight_set_mode(csdev, CS_MODE_DISABLED); +- spin_unlock_irqrestore(&drvdata->spinlock, flags); ++ raw_spin_unlock_irqrestore(&drvdata->spinlock, flags); + + dev_dbg(&csdev->dev, "ETB disabled\n"); + return 0; +@@ -443,7 +443,7 @@ static unsigned long etb_update_buffer(struct coresight_device *csdev, + + capacity = drvdata->buffer_depth * ETB_FRAME_SIZE_WORDS; + +- spin_lock_irqsave(&drvdata->spinlock, flags); ++ raw_spin_lock_irqsave(&drvdata->spinlock, flags); + + /* Don't do anything if another tracer is using this sink */ + if (csdev->refcnt != 1) +@@ -566,7 +566,7 @@ static unsigned long etb_update_buffer(struct coresight_device *csdev, + __etb_enable_hw(drvdata); + CS_LOCK(drvdata->base); + out: +- spin_unlock_irqrestore(&drvdata->spinlock, flags); ++ raw_spin_unlock_irqrestore(&drvdata->spinlock, flags); + + return to_read; + } +@@ -587,13 +587,13 @@ static void etb_dump(struct etb_drvdata *drvdata) + { + unsigned long flags; + +- spin_lock_irqsave(&drvdata->spinlock, flags); ++ raw_spin_lock_irqsave(&drvdata->spinlock, flags); + if (coresight_get_mode(drvdata->csdev) == CS_MODE_SYSFS) { + __etb_disable_hw(drvdata); + etb_dump_hw(drvdata); + __etb_enable_hw(drvdata); + } +- spin_unlock_irqrestore(&drvdata->spinlock, flags); ++ raw_spin_unlock_irqrestore(&drvdata->spinlock, flags); + + dev_dbg(&drvdata->csdev->dev, "ETB dumped\n"); + } +@@ -746,7 +746,7 @@ static int etb_probe(struct amba_device *adev, const struct amba_id *id) + drvdata->base = base; + desc.access = CSDEV_ACCESS_IOMEM(base); + +- spin_lock_init(&drvdata->spinlock); ++ raw_spin_lock_init(&drvdata->spinlock); + + drvdata->buffer_depth = etb_get_buffer_depth(drvdata); + +-- +2.39.5 + diff --git a/queue-6.14/cpufreq-add-sm8650-to-cpufreq-dt-platdev-blocklist.patch b/queue-6.14/cpufreq-add-sm8650-to-cpufreq-dt-platdev-blocklist.patch new file mode 100644 index 0000000000..43747b54d9 --- /dev/null +++ b/queue-6.14/cpufreq-add-sm8650-to-cpufreq-dt-platdev-blocklist.patch @@ -0,0 +1,39 @@ +From a96811ead052549039116ec90eca6f46b159880f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 5 Apr 2025 00:42:19 +0800 +Subject: cpufreq: Add SM8650 to cpufreq-dt-platdev blocklist + +From: Pengyu Luo + +[ Upstream commit fc5414a4774e14e51a93499a6adfdc45f2de82e0 ] + +SM8650 have already been supported by qcom-cpufreq-hw driver, but +never been added to cpufreq-dt-platdev. This makes noise + +[ 0.388525] cpufreq-dt cpufreq-dt: failed register driver: -17 +[ 0.388537] cpufreq-dt cpufreq-dt: probe with driver cpufreq-dt failed with error -17 + +So adding it to the cpufreq-dt-platdev driver's blocklist to fix it. + +Signed-off-by: Pengyu Luo +Signed-off-by: Viresh Kumar +Signed-off-by: Sasha Levin +--- + drivers/cpufreq/cpufreq-dt-platdev.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c b/drivers/cpufreq/cpufreq-dt-platdev.c +index 2aa00769cf09d..a010da0f6337f 100644 +--- a/drivers/cpufreq/cpufreq-dt-platdev.c ++++ b/drivers/cpufreq/cpufreq-dt-platdev.c +@@ -175,6 +175,7 @@ static const struct of_device_id blocklist[] __initconst = { + { .compatible = "qcom,sm8350", }, + { .compatible = "qcom,sm8450", }, + { .compatible = "qcom,sm8550", }, ++ { .compatible = "qcom,sm8650", }, + + { .compatible = "st,stih407", }, + { .compatible = "st,stih410", }, +-- +2.39.5 + diff --git a/queue-6.14/cpufreq-amd-pstate-remove-unnecessary-driver_lock-in.patch b/queue-6.14/cpufreq-amd-pstate-remove-unnecessary-driver_lock-in.patch new file mode 100644 index 0000000000..747c8adbe2 --- /dev/null +++ b/queue-6.14/cpufreq-amd-pstate-remove-unnecessary-driver_lock-in.patch @@ -0,0 +1,37 @@ +From 32df8429ab52fedd70a6806300767b44d844c0de Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 30 Jan 2025 08:52:52 +0000 +Subject: cpufreq: amd-pstate: Remove unnecessary driver_lock in set_boost + +From: Dhananjay Ugwekar + +[ Upstream commit db1cafc77aaaf871509da06f4a864e9af6d6791f ] + +set_boost is a per-policy function call, hence a driver wide lock is +unnecessary. Also this mutex_acquire can collide with the mutex_acquire +from the mode-switch path in status_store(), which can lead to a +deadlock. So, remove it. + +Signed-off-by: Dhananjay Ugwekar +Acked-by: Mario Limonciello +Signed-off-by: Viresh Kumar +Signed-off-by: Sasha Levin +--- + drivers/cpufreq/amd-pstate.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/drivers/cpufreq/amd-pstate.c b/drivers/cpufreq/amd-pstate.c +index 1b26845703f68..a27749d948b46 100644 +--- a/drivers/cpufreq/amd-pstate.c ++++ b/drivers/cpufreq/amd-pstate.c +@@ -746,7 +746,6 @@ static int amd_pstate_set_boost(struct cpufreq_policy *policy, int state) + pr_err("Boost mode is not supported by this processor or SBIOS\n"); + return -EOPNOTSUPP; + } +- guard(mutex)(&amd_pstate_driver_lock); + + ret = amd_pstate_cpu_boost_update(policy, state); + refresh_frequency_limits(policy); +-- +2.39.5 + diff --git a/queue-6.14/cpufreq-tegra186-share-policy-per-cluster.patch b/queue-6.14/cpufreq-tegra186-share-policy-per-cluster.patch new file mode 100644 index 0000000000..d121112084 --- /dev/null +++ b/queue-6.14/cpufreq-tegra186-share-policy-per-cluster.patch @@ -0,0 +1,47 @@ +From 29e00595bde32c56a6ea7eb2e3f58e59e7e6fabe Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 10 Mar 2025 00:28:48 -0500 +Subject: cpufreq: tegra186: Share policy per cluster + +From: Aaron Kling + +[ Upstream commit be4ae8c19492cd6d5de61ccb34ffb3f5ede5eec8 ] + +This functionally brings tegra186 in line with tegra210 and tegra194, +sharing a cpufreq policy between all cores in a cluster. + +Reviewed-by: Sumit Gupta +Acked-by: Thierry Reding +Signed-off-by: Aaron Kling +Signed-off-by: Viresh Kumar +Signed-off-by: Sasha Levin +--- + drivers/cpufreq/tegra186-cpufreq.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/drivers/cpufreq/tegra186-cpufreq.c b/drivers/cpufreq/tegra186-cpufreq.c +index c7761eb99f3cc..92aa50f016660 100644 +--- a/drivers/cpufreq/tegra186-cpufreq.c ++++ b/drivers/cpufreq/tegra186-cpufreq.c +@@ -73,11 +73,18 @@ static int tegra186_cpufreq_init(struct cpufreq_policy *policy) + { + struct tegra186_cpufreq_data *data = cpufreq_get_driver_data(); + unsigned int cluster = data->cpus[policy->cpu].bpmp_cluster_id; ++ u32 cpu; + + policy->freq_table = data->clusters[cluster].table; + policy->cpuinfo.transition_latency = 300 * 1000; + policy->driver_data = NULL; + ++ /* set same policy for all cpus in a cluster */ ++ for (cpu = 0; cpu < ARRAY_SIZE(tegra186_cpus); cpu++) { ++ if (data->cpus[cpu].bpmp_cluster_id == cluster) ++ cpumask_set_cpu(cpu, policy->cpus); ++ } ++ + return 0; + } + +-- +2.39.5 + diff --git a/queue-6.14/cpuidle-menu-avoid-discarding-useful-information.patch b/queue-6.14/cpuidle-menu-avoid-discarding-useful-information.patch new file mode 100644 index 0000000000..acb9f10c24 --- /dev/null +++ b/queue-6.14/cpuidle-menu-avoid-discarding-useful-information.patch @@ -0,0 +1,65 @@ +From 4636aac1aa5e33108d0b70f6ea77c9e9cc973b59 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Feb 2025 15:29:05 +0100 +Subject: cpuidle: menu: Avoid discarding useful information + +From: Rafael J. Wysocki + +[ Upstream commit 85975daeaa4d6ec560bfcd354fc9c08ad7f38888 ] + +When giving up on making a high-confidence prediction, +get_typical_interval() always returns UINT_MAX which means that the +next idle interval prediction will be based entirely on the time till +the next timer. However, the information represented by the most +recent intervals may not be completely useless in those cases. + +Namely, the largest recent idle interval is an upper bound on the +recently observed idle duration, so it is reasonable to assume that +the next idle duration is unlikely to exceed it. Moreover, this is +still true after eliminating the suspected outliers if the sample +set still under consideration is at least as large as 50% of the +maximum sample set size. + +Accordingly, make get_typical_interval() return the current maximum +recent interval value in that case instead of UINT_MAX. + +Signed-off-by: Rafael J. Wysocki +Reported-by: Artem Bityutskiy +Tested-by: Artem Bityutskiy +Reviewed-by: Christian Loehle +Tested-by: Christian Loehle +Tested-by: Aboorva Devarajan +Link: https://patch.msgid.link/7770672.EvYhyI6sBW@rjwysocki.net +Signed-off-by: Sasha Levin +--- + drivers/cpuidle/governors/menu.c | 13 ++++++++++++- + 1 file changed, 12 insertions(+), 1 deletion(-) + +diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c +index 28363bfa3e4c9..42b77d820d0fb 100644 +--- a/drivers/cpuidle/governors/menu.c ++++ b/drivers/cpuidle/governors/menu.c +@@ -192,8 +192,19 @@ static unsigned int get_typical_interval(struct menu_device *data) + * This can deal with workloads that have long pauses interspersed + * with sporadic activity with a bunch of short pauses. + */ +- if ((divisor * 4) <= INTERVALS * 3) ++ if (divisor * 4 <= INTERVALS * 3) { ++ /* ++ * If there are sufficiently many data points still under ++ * consideration after the outliers have been eliminated, ++ * returning without a prediction would be a mistake because it ++ * is likely that the next interval will not exceed the current ++ * maximum, so return the latter in that case. ++ */ ++ if (divisor >= INTERVALS / 2) ++ return max; ++ + return UINT_MAX; ++ } + + thresh = max - 1; + goto again; +-- +2.39.5 + diff --git a/queue-6.14/crypto-ahash-set-default-reqsize-from-ahash_alg.patch b/queue-6.14/crypto-ahash-set-default-reqsize-from-ahash_alg.patch new file mode 100644 index 0000000000..4f24a6d1eb --- /dev/null +++ b/queue-6.14/crypto-ahash-set-default-reqsize-from-ahash_alg.patch @@ -0,0 +1,66 @@ +From b78106c5c1af0c11c1df4f7957ba3ec9e1b76803 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 16 Feb 2025 11:07:24 +0800 +Subject: crypto: ahash - Set default reqsize from ahash_alg + +From: Herbert Xu + +[ Upstream commit 9e01aaa1033d6e40f8d7cf4f20931a61ce9e3f04 ] + +Add a reqsize field to struct ahash_alg and use it to set the +default reqsize so that algorithms with a static reqsize are +not forced to create an init_tfm function. + +Signed-off-by: Herbert Xu +Signed-off-by: Sasha Levin +--- + crypto/ahash.c | 4 ++++ + include/crypto/hash.h | 3 +++ + 2 files changed, 7 insertions(+) + +diff --git a/crypto/ahash.c b/crypto/ahash.c +index b08b89ec26ec5..63960465eea17 100644 +--- a/crypto/ahash.c ++++ b/crypto/ahash.c +@@ -489,6 +489,7 @@ static int crypto_ahash_init_tfm(struct crypto_tfm *tfm) + struct ahash_alg *alg = crypto_ahash_alg(hash); + + crypto_ahash_set_statesize(hash, alg->halg.statesize); ++ crypto_ahash_set_reqsize(hash, alg->reqsize); + + if (tfm->__crt_alg->cra_type == &crypto_shash_type) + return crypto_init_ahash_using_shash(tfm); +@@ -654,6 +655,9 @@ static int ahash_prepare_alg(struct ahash_alg *alg) + if (alg->halg.statesize == 0) + return -EINVAL; + ++ if (alg->reqsize && alg->reqsize < alg->halg.statesize) ++ return -EINVAL; ++ + err = hash_prepare_alg(&alg->halg); + if (err) + return err; +diff --git a/include/crypto/hash.h b/include/crypto/hash.h +index 2d5ea9f9ff43e..6692253f0b5be 100644 +--- a/include/crypto/hash.h ++++ b/include/crypto/hash.h +@@ -132,6 +132,7 @@ struct ahash_request { + * This is a counterpart to @init_tfm, used to remove + * various changes set in @init_tfm. + * @clone_tfm: Copy transform into new object, may allocate memory. ++ * @reqsize: Size of the request context. + * @halg: see struct hash_alg_common + */ + struct ahash_alg { +@@ -148,6 +149,8 @@ struct ahash_alg { + void (*exit_tfm)(struct crypto_ahash *tfm); + int (*clone_tfm)(struct crypto_ahash *dst, struct crypto_ahash *src); + ++ unsigned int reqsize; ++ + struct hash_alg_common halg; + }; + +-- +2.39.5 + diff --git a/queue-6.14/crypto-lzo-fix-compression-buffer-overrun.patch b/queue-6.14/crypto-lzo-fix-compression-buffer-overrun.patch new file mode 100644 index 0000000000..8554f5a950 --- /dev/null +++ b/queue-6.14/crypto-lzo-fix-compression-buffer-overrun.patch @@ -0,0 +1,374 @@ +From 8fce077b224f582f53b70a8cae0cc28fdfaeb89b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 27 Feb 2025 17:04:46 +0800 +Subject: crypto: lzo - Fix compression buffer overrun + +From: Herbert Xu + +[ Upstream commit cc47f07234f72cbd8e2c973cdbf2a6730660a463 ] + +Unlike the decompression code, the compression code in LZO never +checked for output overruns. It instead assumes that the caller +always provides enough buffer space, disregarding the buffer length +provided by the caller. + +Add a safe compression interface that checks for the end of buffer +before each write. Use the safe interface in crypto/lzo. + +Signed-off-by: Herbert Xu +Reviewed-by: David Sterba +Signed-off-by: Herbert Xu +Signed-off-by: Sasha Levin +--- + crypto/lzo-rle.c | 2 +- + crypto/lzo.c | 2 +- + include/linux/lzo.h | 8 +++ + lib/lzo/Makefile | 2 +- + lib/lzo/lzo1x_compress.c | 102 +++++++++++++++++++++++++--------- + lib/lzo/lzo1x_compress_safe.c | 18 ++++++ + 6 files changed, 106 insertions(+), 28 deletions(-) + create mode 100644 lib/lzo/lzo1x_compress_safe.c + +diff --git a/crypto/lzo-rle.c b/crypto/lzo-rle.c +index 0631d975bfac1..0abc2d87f0420 100644 +--- a/crypto/lzo-rle.c ++++ b/crypto/lzo-rle.c +@@ -55,7 +55,7 @@ static int __lzorle_compress(const u8 *src, unsigned int slen, + size_t tmp_len = *dlen; /* size_t(ulong) <-> uint on 64 bit */ + int err; + +- err = lzorle1x_1_compress(src, slen, dst, &tmp_len, ctx); ++ err = lzorle1x_1_compress_safe(src, slen, dst, &tmp_len, ctx); + + if (err != LZO_E_OK) + return -EINVAL; +diff --git a/crypto/lzo.c b/crypto/lzo.c +index ebda132dd22bf..8338851c7406a 100644 +--- a/crypto/lzo.c ++++ b/crypto/lzo.c +@@ -55,7 +55,7 @@ static int __lzo_compress(const u8 *src, unsigned int slen, + size_t tmp_len = *dlen; /* size_t(ulong) <-> uint on 64 bit */ + int err; + +- err = lzo1x_1_compress(src, slen, dst, &tmp_len, ctx); ++ err = lzo1x_1_compress_safe(src, slen, dst, &tmp_len, ctx); + + if (err != LZO_E_OK) + return -EINVAL; +diff --git a/include/linux/lzo.h b/include/linux/lzo.h +index e95c7d1092b28..4d30e3624acd2 100644 +--- a/include/linux/lzo.h ++++ b/include/linux/lzo.h +@@ -24,10 +24,18 @@ + int lzo1x_1_compress(const unsigned char *src, size_t src_len, + unsigned char *dst, size_t *dst_len, void *wrkmem); + ++/* Same as above but does not write more than dst_len to dst. */ ++int lzo1x_1_compress_safe(const unsigned char *src, size_t src_len, ++ unsigned char *dst, size_t *dst_len, void *wrkmem); ++ + /* This requires 'wrkmem' of size LZO1X_1_MEM_COMPRESS */ + int lzorle1x_1_compress(const unsigned char *src, size_t src_len, + unsigned char *dst, size_t *dst_len, void *wrkmem); + ++/* Same as above but does not write more than dst_len to dst. */ ++int lzorle1x_1_compress_safe(const unsigned char *src, size_t src_len, ++ unsigned char *dst, size_t *dst_len, void *wrkmem); ++ + /* safe decompression with overrun testing */ + int lzo1x_decompress_safe(const unsigned char *src, size_t src_len, + unsigned char *dst, size_t *dst_len); +diff --git a/lib/lzo/Makefile b/lib/lzo/Makefile +index 2f58fafbbdddc..fc7b2b7ef4b20 100644 +--- a/lib/lzo/Makefile ++++ b/lib/lzo/Makefile +@@ -1,5 +1,5 @@ + # SPDX-License-Identifier: GPL-2.0-only +-lzo_compress-objs := lzo1x_compress.o ++lzo_compress-objs := lzo1x_compress.o lzo1x_compress_safe.o + lzo_decompress-objs := lzo1x_decompress_safe.o + + obj-$(CONFIG_LZO_COMPRESS) += lzo_compress.o +diff --git a/lib/lzo/lzo1x_compress.c b/lib/lzo/lzo1x_compress.c +index 47d6d43ea9578..7b10ca86a8930 100644 +--- a/lib/lzo/lzo1x_compress.c ++++ b/lib/lzo/lzo1x_compress.c +@@ -18,11 +18,22 @@ + #include + #include "lzodefs.h" + +-static noinline size_t +-lzo1x_1_do_compress(const unsigned char *in, size_t in_len, +- unsigned char *out, size_t *out_len, +- size_t ti, void *wrkmem, signed char *state_offset, +- const unsigned char bitstream_version) ++#undef LZO_UNSAFE ++ ++#ifndef LZO_SAFE ++#define LZO_UNSAFE 1 ++#define LZO_SAFE(name) name ++#define HAVE_OP(x) 1 ++#endif ++ ++#define NEED_OP(x) if (!HAVE_OP(x)) goto output_overrun ++ ++static noinline int ++LZO_SAFE(lzo1x_1_do_compress)(const unsigned char *in, size_t in_len, ++ unsigned char **out, unsigned char *op_end, ++ size_t *tp, void *wrkmem, ++ signed char *state_offset, ++ const unsigned char bitstream_version) + { + const unsigned char *ip; + unsigned char *op; +@@ -30,8 +41,9 @@ lzo1x_1_do_compress(const unsigned char *in, size_t in_len, + const unsigned char * const ip_end = in + in_len - 20; + const unsigned char *ii; + lzo_dict_t * const dict = (lzo_dict_t *) wrkmem; ++ size_t ti = *tp; + +- op = out; ++ op = *out; + ip = in; + ii = ip; + ip += ti < 4 ? 4 - ti : 0; +@@ -116,25 +128,32 @@ lzo1x_1_do_compress(const unsigned char *in, size_t in_len, + if (t != 0) { + if (t <= 3) { + op[*state_offset] |= t; ++ NEED_OP(4); + COPY4(op, ii); + op += t; + } else if (t <= 16) { ++ NEED_OP(17); + *op++ = (t - 3); + COPY8(op, ii); + COPY8(op + 8, ii + 8); + op += t; + } else { + if (t <= 18) { ++ NEED_OP(1); + *op++ = (t - 3); + } else { + size_t tt = t - 18; ++ NEED_OP(1); + *op++ = 0; + while (unlikely(tt > 255)) { + tt -= 255; ++ NEED_OP(1); + *op++ = 0; + } ++ NEED_OP(1); + *op++ = tt; + } ++ NEED_OP(t); + do { + COPY8(op, ii); + COPY8(op + 8, ii + 8); +@@ -151,6 +170,7 @@ lzo1x_1_do_compress(const unsigned char *in, size_t in_len, + if (unlikely(run_length)) { + ip += run_length; + run_length -= MIN_ZERO_RUN_LENGTH; ++ NEED_OP(4); + put_unaligned_le32((run_length << 21) | 0xfffc18 + | (run_length & 0x7), op); + op += 4; +@@ -243,10 +263,12 @@ lzo1x_1_do_compress(const unsigned char *in, size_t in_len, + ip += m_len; + if (m_len <= M2_MAX_LEN && m_off <= M2_MAX_OFFSET) { + m_off -= 1; ++ NEED_OP(2); + *op++ = (((m_len - 1) << 5) | ((m_off & 7) << 2)); + *op++ = (m_off >> 3); + } else if (m_off <= M3_MAX_OFFSET) { + m_off -= 1; ++ NEED_OP(1); + if (m_len <= M3_MAX_LEN) + *op++ = (M3_MARKER | (m_len - 2)); + else { +@@ -254,14 +276,18 @@ lzo1x_1_do_compress(const unsigned char *in, size_t in_len, + *op++ = M3_MARKER | 0; + while (unlikely(m_len > 255)) { + m_len -= 255; ++ NEED_OP(1); + *op++ = 0; + } ++ NEED_OP(1); + *op++ = (m_len); + } ++ NEED_OP(2); + *op++ = (m_off << 2); + *op++ = (m_off >> 6); + } else { + m_off -= 0x4000; ++ NEED_OP(1); + if (m_len <= M4_MAX_LEN) + *op++ = (M4_MARKER | ((m_off >> 11) & 8) + | (m_len - 2)); +@@ -282,11 +308,14 @@ lzo1x_1_do_compress(const unsigned char *in, size_t in_len, + m_len -= M4_MAX_LEN; + *op++ = (M4_MARKER | ((m_off >> 11) & 8)); + while (unlikely(m_len > 255)) { ++ NEED_OP(1); + m_len -= 255; + *op++ = 0; + } ++ NEED_OP(1); + *op++ = (m_len); + } ++ NEED_OP(2); + *op++ = (m_off << 2); + *op++ = (m_off >> 6); + } +@@ -295,14 +324,20 @@ lzo1x_1_do_compress(const unsigned char *in, size_t in_len, + ii = ip; + goto next; + } +- *out_len = op - out; +- return in_end - (ii - ti); ++ *out = op; ++ *tp = in_end - (ii - ti); ++ return LZO_E_OK; ++ ++output_overrun: ++ return LZO_E_OUTPUT_OVERRUN; + } + +-static int lzogeneric1x_1_compress(const unsigned char *in, size_t in_len, +- unsigned char *out, size_t *out_len, +- void *wrkmem, const unsigned char bitstream_version) ++static int LZO_SAFE(lzogeneric1x_1_compress)( ++ const unsigned char *in, size_t in_len, ++ unsigned char *out, size_t *out_len, ++ void *wrkmem, const unsigned char bitstream_version) + { ++ unsigned char * const op_end = out + *out_len; + const unsigned char *ip = in; + unsigned char *op = out; + unsigned char *data_start; +@@ -326,14 +361,18 @@ static int lzogeneric1x_1_compress(const unsigned char *in, size_t in_len, + while (l > 20) { + size_t ll = min_t(size_t, l, m4_max_offset + 1); + uintptr_t ll_end = (uintptr_t) ip + ll; ++ int err; ++ + if ((ll_end + ((t + ll) >> 5)) <= ll_end) + break; + BUILD_BUG_ON(D_SIZE * sizeof(lzo_dict_t) > LZO1X_1_MEM_COMPRESS); + memset(wrkmem, 0, D_SIZE * sizeof(lzo_dict_t)); +- t = lzo1x_1_do_compress(ip, ll, op, out_len, t, wrkmem, +- &state_offset, bitstream_version); ++ err = LZO_SAFE(lzo1x_1_do_compress)( ++ ip, ll, &op, op_end, &t, wrkmem, ++ &state_offset, bitstream_version); ++ if (err != LZO_E_OK) ++ return err; + ip += ll; +- op += *out_len; + l -= ll; + } + t += l; +@@ -342,20 +381,26 @@ static int lzogeneric1x_1_compress(const unsigned char *in, size_t in_len, + const unsigned char *ii = in + in_len - t; + + if (op == data_start && t <= 238) { ++ NEED_OP(1); + *op++ = (17 + t); + } else if (t <= 3) { + op[state_offset] |= t; + } else if (t <= 18) { ++ NEED_OP(1); + *op++ = (t - 3); + } else { + size_t tt = t - 18; ++ NEED_OP(1); + *op++ = 0; + while (tt > 255) { + tt -= 255; ++ NEED_OP(1); + *op++ = 0; + } ++ NEED_OP(1); + *op++ = tt; + } ++ NEED_OP(t); + if (t >= 16) do { + COPY8(op, ii); + COPY8(op + 8, ii + 8); +@@ -368,31 +413,38 @@ static int lzogeneric1x_1_compress(const unsigned char *in, size_t in_len, + } while (--t > 0); + } + ++ NEED_OP(3); + *op++ = M4_MARKER | 1; + *op++ = 0; + *op++ = 0; + + *out_len = op - out; + return LZO_E_OK; ++ ++output_overrun: ++ return LZO_E_OUTPUT_OVERRUN; + } + +-int lzo1x_1_compress(const unsigned char *in, size_t in_len, +- unsigned char *out, size_t *out_len, +- void *wrkmem) ++int LZO_SAFE(lzo1x_1_compress)(const unsigned char *in, size_t in_len, ++ unsigned char *out, size_t *out_len, ++ void *wrkmem) + { +- return lzogeneric1x_1_compress(in, in_len, out, out_len, wrkmem, 0); ++ return LZO_SAFE(lzogeneric1x_1_compress)( ++ in, in_len, out, out_len, wrkmem, 0); + } + +-int lzorle1x_1_compress(const unsigned char *in, size_t in_len, +- unsigned char *out, size_t *out_len, +- void *wrkmem) ++int LZO_SAFE(lzorle1x_1_compress)(const unsigned char *in, size_t in_len, ++ unsigned char *out, size_t *out_len, ++ void *wrkmem) + { +- return lzogeneric1x_1_compress(in, in_len, out, out_len, +- wrkmem, LZO_VERSION); ++ return LZO_SAFE(lzogeneric1x_1_compress)( ++ in, in_len, out, out_len, wrkmem, LZO_VERSION); + } + +-EXPORT_SYMBOL_GPL(lzo1x_1_compress); +-EXPORT_SYMBOL_GPL(lzorle1x_1_compress); ++EXPORT_SYMBOL_GPL(LZO_SAFE(lzo1x_1_compress)); ++EXPORT_SYMBOL_GPL(LZO_SAFE(lzorle1x_1_compress)); + ++#ifndef LZO_UNSAFE + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("LZO1X-1 Compressor"); ++#endif +diff --git a/lib/lzo/lzo1x_compress_safe.c b/lib/lzo/lzo1x_compress_safe.c +new file mode 100644 +index 0000000000000..371c9f8494928 +--- /dev/null ++++ b/lib/lzo/lzo1x_compress_safe.c +@@ -0,0 +1,18 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * LZO1X Compressor from LZO ++ * ++ * Copyright (C) 1996-2012 Markus F.X.J. Oberhumer ++ * ++ * The full LZO package can be found at: ++ * http://www.oberhumer.com/opensource/lzo/ ++ * ++ * Changed for Linux kernel use by: ++ * Nitin Gupta ++ * Richard Purdie ++ */ ++ ++#define LZO_SAFE(name) name##_safe ++#define HAVE_OP(x) ((size_t)(op_end - op) >= (size_t)(x)) ++ ++#include "lzo1x_compress.c" +-- +2.39.5 + diff --git a/queue-6.14/crypto-mxs-dcp-only-set-otp_key-bit-for-otp-key.patch b/queue-6.14/crypto-mxs-dcp-only-set-otp_key-bit-for-otp-key.patch new file mode 100644 index 0000000000..180f9f4caf --- /dev/null +++ b/queue-6.14/crypto-mxs-dcp-only-set-otp_key-bit-for-otp-key.patch @@ -0,0 +1,45 @@ +From c2c6242e6031e34c0d4d0c273e6791f1ab7f5bd0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 24 Feb 2025 08:42:25 +0100 +Subject: crypto: mxs-dcp - Only set OTP_KEY bit for OTP key + +From: Sven Schwermer + +[ Upstream commit caa9dbb76ff52ec848a57245062aaeaa07740adc ] + +While MXS_DCP_CONTROL0_OTP_KEY is set, the CRYPTO_KEY (DCP_PAES_KEY_OTP) +is used even if the UNIQUE_KEY (DCP_PAES_KEY_UNIQUE) is selected. This +is not clearly documented, but this implementation is consistent with +NXP's downstream kernel fork and optee_os. + +Signed-off-by: Sven Schwermer +Signed-off-by: Herbert Xu +Signed-off-by: Sasha Levin +--- + drivers/crypto/mxs-dcp.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/crypto/mxs-dcp.c b/drivers/crypto/mxs-dcp.c +index d94a26c3541a0..133ebc9982362 100644 +--- a/drivers/crypto/mxs-dcp.c ++++ b/drivers/crypto/mxs-dcp.c +@@ -265,12 +265,12 @@ static int mxs_dcp_run_aes(struct dcp_async_ctx *actx, + MXS_DCP_CONTROL0_INTERRUPT | + MXS_DCP_CONTROL0_ENABLE_CIPHER; + +- if (key_referenced) +- /* Set OTP key bit to select the key via KEY_SELECT. */ +- desc->control0 |= MXS_DCP_CONTROL0_OTP_KEY; +- else ++ if (!key_referenced) + /* Payload contains the key. */ + desc->control0 |= MXS_DCP_CONTROL0_PAYLOAD_KEY; ++ else if (actx->key[0] == DCP_PAES_KEY_OTP) ++ /* Set OTP key bit to select the key via KEY_SELECT. */ ++ desc->control0 |= MXS_DCP_CONTROL0_OTP_KEY; + + if (rctx->enc) + desc->control0 |= MXS_DCP_CONTROL0_CIPHER_ENCRYPT; +-- +2.39.5 + diff --git a/queue-6.14/crypto-octeontx2-suppress-auth-failure-screaming-due.patch b/queue-6.14/crypto-octeontx2-suppress-auth-failure-screaming-due.patch new file mode 100644 index 0000000000..4061518f45 --- /dev/null +++ b/queue-6.14/crypto-octeontx2-suppress-auth-failure-screaming-due.patch @@ -0,0 +1,43 @@ +From 3a5be13db66f2cff9733a113ee32ec6d671c745d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Mar 2025 13:27:05 +0530 +Subject: crypto: octeontx2 - suppress auth failure screaming due to negative + tests + +From: Shashank Gupta + +[ Upstream commit 64b7871522a4cba99d092e1c849d6f9092868aaa ] + +This patch addresses an issue where authentication failures were being +erroneously reported due to negative test failures in the "ccm(aes)" +selftest. +pr_debug suppress unnecessary screaming of these tests. + +Signed-off-by: Shashank Gupta +Signed-off-by: Herbert Xu +Signed-off-by: Sasha Levin +--- + drivers/crypto/marvell/octeontx2/otx2_cptvf_reqmgr.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/drivers/crypto/marvell/octeontx2/otx2_cptvf_reqmgr.c b/drivers/crypto/marvell/octeontx2/otx2_cptvf_reqmgr.c +index 5387c68f3c9df..4262441070372 100644 +--- a/drivers/crypto/marvell/octeontx2/otx2_cptvf_reqmgr.c ++++ b/drivers/crypto/marvell/octeontx2/otx2_cptvf_reqmgr.c +@@ -264,9 +264,10 @@ static int cpt_process_ccode(struct otx2_cptlfs_info *lfs, + break; + } + +- dev_err(&pdev->dev, +- "Request failed with software error code 0x%x\n", +- cpt_status->s.uc_compcode); ++ pr_debug("Request failed with software error code 0x%x: algo = %s driver = %s\n", ++ cpt_status->s.uc_compcode, ++ info->req->areq->tfm->__crt_alg->cra_name, ++ info->req->areq->tfm->__crt_alg->cra_driver_name); + otx2_cpt_dump_sg_list(pdev, info->req); + break; + } +-- +2.39.5 + diff --git a/queue-6.14/crypto-skcipher-zap-type-in-crypto_alloc_sync_skciph.patch b/queue-6.14/crypto-skcipher-zap-type-in-crypto_alloc_sync_skciph.patch new file mode 100644 index 0000000000..6cc4038276 --- /dev/null +++ b/queue-6.14/crypto-skcipher-zap-type-in-crypto_alloc_sync_skciph.patch @@ -0,0 +1,33 @@ +From aedd55876d9a1116ef17dab126e6b103b8500781 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 15 Feb 2025 08:57:51 +0800 +Subject: crypto: skcipher - Zap type in crypto_alloc_sync_skcipher + +From: Herbert Xu + +[ Upstream commit ee509efc74ddbc59bb5d6fd6e050f9ef25f74bff ] + +The type needs to be zeroed as otherwise the user could use it to +allocate an asynchronous sync skcipher. + +Signed-off-by: Herbert Xu +Signed-off-by: Sasha Levin +--- + crypto/skcipher.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/crypto/skcipher.c b/crypto/skcipher.c +index a9eb2dcf28982..2d2b1589a0097 100644 +--- a/crypto/skcipher.c ++++ b/crypto/skcipher.c +@@ -681,6 +681,7 @@ struct crypto_sync_skcipher *crypto_alloc_sync_skcipher( + + /* Only sync algorithms allowed. */ + mask |= CRYPTO_ALG_ASYNC | CRYPTO_ALG_SKCIPHER_REQSIZE_LARGE; ++ type &= ~(CRYPTO_ALG_ASYNC | CRYPTO_ALG_SKCIPHER_REQSIZE_LARGE); + + tfm = crypto_alloc_tfm(alg_name, &crypto_skcipher_type, type, mask); + +-- +2.39.5 + diff --git a/queue-6.14/dlm-make-tcp-still-work-in-multi-link-env.patch b/queue-6.14/dlm-make-tcp-still-work-in-multi-link-env.patch new file mode 100644 index 0000000000..80d9134fe3 --- /dev/null +++ b/queue-6.14/dlm-make-tcp-still-work-in-multi-link-env.patch @@ -0,0 +1,37 @@ +From a0f1a794b640c15fb298bf5dde189fba6e5d53fe Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 10 Mar 2025 15:36:21 +0800 +Subject: dlm: make tcp still work in multi-link env + +From: Heming Zhao + +[ Upstream commit 03d2b62208a336a3bb984b9465ef6d89a046ea22 ] + +This patch bypasses multi-link errors in TCP mode, allowing dlm +to operate on the first tcp link. + +Signed-off-by: Heming Zhao +Signed-off-by: David Teigland +Signed-off-by: Sasha Levin +--- + fs/dlm/lowcomms.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/fs/dlm/lowcomms.c b/fs/dlm/lowcomms.c +index d28141829c051..70abd4da17a63 100644 +--- a/fs/dlm/lowcomms.c ++++ b/fs/dlm/lowcomms.c +@@ -1826,8 +1826,8 @@ static int dlm_tcp_listen_validate(void) + { + /* We don't support multi-homed hosts */ + if (dlm_local_count > 1) { +- log_print("TCP protocol can't handle multi-homed hosts, try SCTP"); +- return -EINVAL; ++ log_print("Detect multi-homed hosts but use only the first IP address."); ++ log_print("Try SCTP, if you want to enable multi-link."); + } + + return 0; +-- +2.39.5 + diff --git a/queue-6.14/dm-cache-prevent-bug_on-by-blocking-retries-on-faile.patch b/queue-6.14/dm-cache-prevent-bug_on-by-blocking-retries-on-faile.patch new file mode 100644 index 0000000000..670c8f2d6f --- /dev/null +++ b/queue-6.14/dm-cache-prevent-bug_on-by-blocking-retries-on-faile.patch @@ -0,0 +1,121 @@ +From fdf782a38445155ff9f22039d1ae32cbd8a261a0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Mar 2025 16:41:50 +0800 +Subject: dm cache: prevent BUG_ON by blocking retries on failed device resumes + +From: Ming-Hung Tsai + +[ Upstream commit 5da692e2262b8f81993baa9592f57d12c2703dea ] + +A cache device failing to resume due to mapping errors should not be +retried, as the failure leaves a partially initialized policy object. +Repeating the resume operation risks triggering BUG_ON when reloading +cache mappings into the incomplete policy object. + +Reproduce steps: + +1. create a cache metadata consisting of 512 or more cache blocks, + with some mappings stored in the first array block of the mapping + array. Here we use cache_restore v1.0 to build the metadata. + +cat <> cmeta.xml + + + + + +EOF +dmsetup create cmeta --table "0 8192 linear /dev/sdc 0" +cache_restore -i cmeta.xml -o /dev/mapper/cmeta --metadata-version=2 +dmsetup remove cmeta + +2. wipe the second array block of the mapping array to simulate + data degradations. + +mapping_root=$(dd if=/dev/sdc bs=1c count=8 skip=192 \ +2>/dev/null | hexdump -e '1/8 "%u\n"') +ablock=$(dd if=/dev/sdc bs=1c count=8 skip=$((4096*mapping_root+2056)) \ +2>/dev/null | hexdump -e '1/8 "%u\n"') +dd if=/dev/zero of=/dev/sdc bs=4k count=1 seek=$ablock + +3. try bringing up the cache device. The resume is expected to fail + due to the broken array block. + +dmsetup create cmeta --table "0 8192 linear /dev/sdc 0" +dmsetup create cdata --table "0 65536 linear /dev/sdc 8192" +dmsetup create corig --table "0 524288 linear /dev/sdc 262144" +dmsetup create cache --notable +dmsetup load cache --table "0 524288 cache /dev/mapper/cmeta \ +/dev/mapper/cdata /dev/mapper/corig 128 2 metadata2 writethrough smq 0" +dmsetup resume cache + +4. try resuming the cache again. An unexpected BUG_ON is triggered + while loading cache mappings. + +dmsetup resume cache + +Kernel logs: + +(snip) +------------[ cut here ]------------ +kernel BUG at drivers/md/dm-cache-policy-smq.c:752! +Oops: invalid opcode: 0000 [#1] PREEMPT SMP KASAN NOPTI +CPU: 0 UID: 0 PID: 332 Comm: dmsetup Not tainted 6.13.4 #3 +RIP: 0010:smq_load_mapping+0x3e5/0x570 + +Fix by disallowing resume operations for devices that failed the +initial attempt. + +Signed-off-by: Ming-Hung Tsai +Signed-off-by: Mikulas Patocka +Signed-off-by: Sasha Levin +--- + drivers/md/dm-cache-target.c | 24 ++++++++++++++++++++++++ + 1 file changed, 24 insertions(+) + +diff --git a/drivers/md/dm-cache-target.c b/drivers/md/dm-cache-target.c +index 9cb797a561d6e..6cee5eac8b9e2 100644 +--- a/drivers/md/dm-cache-target.c ++++ b/drivers/md/dm-cache-target.c +@@ -2899,6 +2899,27 @@ static dm_cblock_t get_cache_dev_size(struct cache *cache) + return to_cblock(size); + } + ++static bool can_resume(struct cache *cache) ++{ ++ /* ++ * Disallow retrying the resume operation for devices that failed the ++ * first resume attempt, as the failure leaves the policy object partially ++ * initialized. Retrying could trigger BUG_ON when loading cache mappings ++ * into the incomplete policy object. ++ */ ++ if (cache->sized && !cache->loaded_mappings) { ++ if (get_cache_mode(cache) != CM_WRITE) ++ DMERR("%s: unable to resume a failed-loaded cache, please check metadata.", ++ cache_device_name(cache)); ++ else ++ DMERR("%s: unable to resume cache due to missing proper cache table reload", ++ cache_device_name(cache)); ++ return false; ++ } ++ ++ return true; ++} ++ + static bool can_resize(struct cache *cache, dm_cblock_t new_size) + { + if (from_cblock(new_size) > from_cblock(cache->cache_size)) { +@@ -2947,6 +2968,9 @@ static int cache_preresume(struct dm_target *ti) + struct cache *cache = ti->private; + dm_cblock_t csize = get_cache_dev_size(cache); + ++ if (!can_resume(cache)) ++ return -EINVAL; ++ + /* + * Check to see if the cache has resized. + */ +-- +2.39.5 + diff --git a/queue-6.14/dm-fix-unconditional-io-throttle-caused-by-req_prefl.patch b/queue-6.14/dm-fix-unconditional-io-throttle-caused-by-req_prefl.patch new file mode 100644 index 0000000000..aaaf4b3812 --- /dev/null +++ b/queue-6.14/dm-fix-unconditional-io-throttle-caused-by-req_prefl.patch @@ -0,0 +1,82 @@ +From ba646a5dba24e411a43c29c5387996d093cfc934 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 20 Feb 2025 19:20:14 +0800 +Subject: dm: fix unconditional IO throttle caused by REQ_PREFLUSH + +From: Jinliang Zheng + +[ Upstream commit 88f7f56d16f568f19e1a695af34a7f4a6ce537a6 ] + +When a bio with REQ_PREFLUSH is submitted to dm, __send_empty_flush() +generates a flush_bio with REQ_OP_WRITE | REQ_PREFLUSH | REQ_SYNC, +which causes the flush_bio to be throttled by wbt_wait(). + +An example from v5.4, similar problem also exists in upstream: + + crash> bt 2091206 + PID: 2091206 TASK: ffff2050df92a300 CPU: 109 COMMAND: "kworker/u260:0" + #0 [ffff800084a2f7f0] __switch_to at ffff80004008aeb8 + #1 [ffff800084a2f820] __schedule at ffff800040bfa0c4 + #2 [ffff800084a2f880] schedule at ffff800040bfa4b4 + #3 [ffff800084a2f8a0] io_schedule at ffff800040bfa9c4 + #4 [ffff800084a2f8c0] rq_qos_wait at ffff8000405925bc + #5 [ffff800084a2f940] wbt_wait at ffff8000405bb3a0 + #6 [ffff800084a2f9a0] __rq_qos_throttle at ffff800040592254 + #7 [ffff800084a2f9c0] blk_mq_make_request at ffff80004057cf38 + #8 [ffff800084a2fa60] generic_make_request at ffff800040570138 + #9 [ffff800084a2fae0] submit_bio at ffff8000405703b4 + #10 [ffff800084a2fb50] xlog_write_iclog at ffff800001280834 [xfs] + #11 [ffff800084a2fbb0] xlog_sync at ffff800001280c3c [xfs] + #12 [ffff800084a2fbf0] xlog_state_release_iclog at ffff800001280df4 [xfs] + #13 [ffff800084a2fc10] xlog_write at ffff80000128203c [xfs] + #14 [ffff800084a2fcd0] xlog_cil_push at ffff8000012846dc [xfs] + #15 [ffff800084a2fda0] xlog_cil_push_work at ffff800001284a2c [xfs] + #16 [ffff800084a2fdb0] process_one_work at ffff800040111d08 + #17 [ffff800084a2fe00] worker_thread at ffff8000401121cc + #18 [ffff800084a2fe70] kthread at ffff800040118de4 + +After commit 2def2845cc33 ("xfs: don't allow log IO to be throttled"), +the metadata submitted by xlog_write_iclog() should not be throttled. +But due to the existence of the dm layer, throttling flush_bio indirectly +causes the metadata bio to be throttled. + +Fix this by conditionally adding REQ_IDLE to flush_bio.bi_opf, which makes +wbt_should_throttle() return false to avoid wbt_wait(). + +Signed-off-by: Jinliang Zheng +Reviewed-by: Tianxiang Peng +Reviewed-by: Hao Peng +Signed-off-by: Mikulas Patocka +Signed-off-by: Sasha Levin +--- + drivers/md/dm.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/drivers/md/dm.c b/drivers/md/dm.c +index 4d1e42891d246..5ab7574c0c76a 100644 +--- a/drivers/md/dm.c ++++ b/drivers/md/dm.c +@@ -1540,14 +1540,18 @@ static void __send_empty_flush(struct clone_info *ci) + { + struct dm_table *t = ci->map; + struct bio flush_bio; ++ blk_opf_t opf = REQ_OP_WRITE | REQ_PREFLUSH | REQ_SYNC; ++ ++ if ((ci->io->orig_bio->bi_opf & (REQ_IDLE | REQ_SYNC)) == ++ (REQ_IDLE | REQ_SYNC)) ++ opf |= REQ_IDLE; + + /* + * Use an on-stack bio for this, it's safe since we don't + * need to reference it after submit. It's just used as + * the basis for the clone(s). + */ +- bio_init(&flush_bio, ci->io->md->disk->part0, NULL, 0, +- REQ_OP_WRITE | REQ_PREFLUSH | REQ_SYNC); ++ bio_init(&flush_bio, ci->io->md->disk->part0, NULL, 0, opf); + + ci->bio = &flush_bio; + ci->sector_count = 0; +-- +2.39.5 + diff --git a/queue-6.14/dm-restrict-dm-device-size-to-2-63-512-bytes.patch b/queue-6.14/dm-restrict-dm-device-size-to-2-63-512-bytes.patch new file mode 100644 index 0000000000..b140ec8c9f --- /dev/null +++ b/queue-6.14/dm-restrict-dm-device-size-to-2-63-512-bytes.patch @@ -0,0 +1,39 @@ +From 9844a31eed65a7e4b5eae44726683393f6583b9c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 14 Mar 2025 13:51:32 +0100 +Subject: dm: restrict dm device size to 2^63-512 bytes + +From: Mikulas Patocka + +[ Upstream commit 45fc728515c14f53f6205789de5bfd72a95af3b8 ] + +The devices with size >= 2^63 bytes can't be used reliably by userspace +because the type off_t is a signed 64-bit integer. + +Therefore, we limit the maximum size of a device mapper device to +2^63-512 bytes. + +Signed-off-by: Mikulas Patocka +Signed-off-by: Sasha Levin +--- + drivers/md/dm-table.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c +index efc6ec25e0c5d..4752966fdb3f4 100644 +--- a/drivers/md/dm-table.c ++++ b/drivers/md/dm-table.c +@@ -698,6 +698,10 @@ int dm_table_add_target(struct dm_table *t, const char *type, + DMERR("%s: zero-length target", dm_device_name(t->md)); + return -EINVAL; + } ++ if (start + len < start || start + len > LLONG_MAX >> SECTOR_SHIFT) { ++ DMERR("%s: too large device", dm_device_name(t->md)); ++ return -EINVAL; ++ } + + ti->type = dm_get_target_type(type); + if (!ti->type) { +-- +2.39.5 + diff --git a/queue-6.14/dm-vdo-indexer-prevent-unterminated-string-warning.patch b/queue-6.14/dm-vdo-indexer-prevent-unterminated-string-warning.patch new file mode 100644 index 0000000000..6a43a8c9f0 --- /dev/null +++ b/queue-6.14/dm-vdo-indexer-prevent-unterminated-string-warning.patch @@ -0,0 +1,53 @@ +From 932aaded959c8a09440d6776db7b9e6207b5f68a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 29 Jan 2025 18:27:12 -0500 +Subject: dm vdo indexer: prevent unterminated string warning +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Chung Chung + +[ Upstream commit f4e99b846c90163d350c69d6581ac38dd5818eb8 ] + +Fix array initialization that triggers a warning: + +error: initializer-string for array of ‘unsigned char’ is too long + [-Werror=unterminated-string-initialization] + +Signed-off-by: Chung Chung +Signed-off-by: Matthew Sakai +Signed-off-by: Mikulas Patocka +Signed-off-by: Sasha Levin +--- + drivers/md/dm-vdo/indexer/index-layout.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/drivers/md/dm-vdo/indexer/index-layout.c b/drivers/md/dm-vdo/indexer/index-layout.c +index af8fab83b0f3e..61edf2b72427d 100644 +--- a/drivers/md/dm-vdo/indexer/index-layout.c ++++ b/drivers/md/dm-vdo/indexer/index-layout.c +@@ -54,7 +54,6 @@ + * Each save also has a unique nonce. + */ + +-#define MAGIC_SIZE 32 + #define NONCE_INFO_SIZE 32 + #define MAX_SAVES 2 + +@@ -98,9 +97,11 @@ enum region_type { + #define SUPER_VERSION_CURRENT 3 + #define SUPER_VERSION_MAXIMUM 7 + +-static const u8 LAYOUT_MAGIC[MAGIC_SIZE] = "*ALBIREO*SINGLE*FILE*LAYOUT*001*"; ++static const u8 LAYOUT_MAGIC[] = "*ALBIREO*SINGLE*FILE*LAYOUT*001*"; + static const u64 REGION_MAGIC = 0x416c6252676e3031; /* 'AlbRgn01' */ + ++#define MAGIC_SIZE (sizeof(LAYOUT_MAGIC) - 1) ++ + struct region_header { + u64 magic; + u64 region_blocks; +-- +2.39.5 + diff --git a/queue-6.14/dm-vdo-use-a-short-static-string-for-thread-name-pre.patch b/queue-6.14/dm-vdo-use-a-short-static-string-for-thread-name-pre.patch new file mode 100644 index 0000000000..dd4792d168 --- /dev/null +++ b/queue-6.14/dm-vdo-use-a-short-static-string-for-thread-name-pre.patch @@ -0,0 +1,76 @@ +From 31cad9ec1911a586b4a74f901a1e5b84e7ff1279 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 29 Jan 2025 18:26:05 -0500 +Subject: dm vdo: use a short static string for thread name prefix +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Matthew Sakai + +[ Upstream commit 3280c9313c9adce01550cc9f00edfb1dc7c744da ] + +Also remove MODULE_NAME and a BUG_ON check, both unneeded. + +This fixes a warning about string truncation in snprintf that +will never happen in practice: + +drivers/md/dm-vdo/vdo.c: In function ‘vdo_make’: +drivers/md/dm-vdo/vdo.c:564:5: error: ‘%s’ directive output may be truncated writing up to 55 bytes into a region of size 16 [-Werror=format-truncation=] + "%s%u", MODULE_NAME, instance); + ^~ +drivers/md/dm-vdo/vdo.c:563:2: note: ‘snprintf’ output between 2 and 66 bytes into a destination of size 16 + snprintf(vdo->thread_name_prefix, sizeof(vdo->thread_name_prefix), + ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + "%s%u", MODULE_NAME, instance); + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Reported-by: John Garry +Reviewed-by: John Garry +Signed-off-by: Matthew Sakai +Signed-off-by: Mikulas Patocka +Signed-off-by: Sasha Levin +--- + drivers/md/dm-vdo/vdo.c | 11 +---------- + 1 file changed, 1 insertion(+), 10 deletions(-) + +diff --git a/drivers/md/dm-vdo/vdo.c b/drivers/md/dm-vdo/vdo.c +index a7e32baab4afd..80b6086740225 100644 +--- a/drivers/md/dm-vdo/vdo.c ++++ b/drivers/md/dm-vdo/vdo.c +@@ -31,9 +31,7 @@ + + #include + #include +-#include + #include +-#include + #include + #include + #include +@@ -142,12 +140,6 @@ static void finish_vdo_request_queue(void *ptr) + vdo_unregister_allocating_thread(); + } + +-#ifdef MODULE +-#define MODULE_NAME THIS_MODULE->name +-#else +-#define MODULE_NAME "dm-vdo" +-#endif /* MODULE */ +- + static const struct vdo_work_queue_type default_queue_type = { + .start = start_vdo_request_queue, + .finish = finish_vdo_request_queue, +@@ -559,8 +551,7 @@ int vdo_make(unsigned int instance, struct device_config *config, char **reason, + *vdo_ptr = vdo; + + snprintf(vdo->thread_name_prefix, sizeof(vdo->thread_name_prefix), +- "%s%u", MODULE_NAME, instance); +- BUG_ON(vdo->thread_name_prefix[0] == '\0'); ++ "vdo%u", instance); + result = vdo_allocate(vdo->thread_config.thread_count, + struct vdo_thread, __func__, &vdo->threads); + if (result != VDO_SUCCESS) { +-- +2.39.5 + diff --git a/queue-6.14/dm-vdo-vio-pool-allow-variable-sized-metadata-vios.patch b/queue-6.14/dm-vdo-vio-pool-allow-variable-sized-metadata-vios.patch new file mode 100644 index 0000000000..0d641519b1 --- /dev/null +++ b/queue-6.14/dm-vdo-vio-pool-allow-variable-sized-metadata-vios.patch @@ -0,0 +1,208 @@ +From 921200c5e2f6a07ad93419d800d6a1a2fbf7abc7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 31 Jan 2025 21:18:05 -0500 +Subject: dm vdo vio-pool: allow variable-sized metadata vios + +From: Ken Raeburn + +[ Upstream commit f979da512553a41a657f2c1198277e84d66f8ce3 ] + +With larger-sized metadata vio pools, vdo will sometimes need to +issue I/O with a smaller size than the allocated size. Since +vio_reset_bio is where the bvec array and I/O size are initialized, +this reset interface must now specify what I/O size to use. + +Signed-off-by: Ken Raeburn +Signed-off-by: Matthew Sakai +Signed-off-by: Mikulas Patocka +Signed-off-by: Sasha Levin +--- + drivers/md/dm-vdo/io-submitter.c | 6 ++++-- + drivers/md/dm-vdo/io-submitter.h | 18 +++++++++++++--- + drivers/md/dm-vdo/types.h | 3 +++ + drivers/md/dm-vdo/vio.c | 36 +++++++++++++++++++------------- + drivers/md/dm-vdo/vio.h | 2 ++ + 5 files changed, 46 insertions(+), 19 deletions(-) + +diff --git a/drivers/md/dm-vdo/io-submitter.c b/drivers/md/dm-vdo/io-submitter.c +index 421e5436c32c9..11d47770b54d2 100644 +--- a/drivers/md/dm-vdo/io-submitter.c ++++ b/drivers/md/dm-vdo/io-submitter.c +@@ -327,6 +327,7 @@ void vdo_submit_data_vio(struct data_vio *data_vio) + * @error_handler: the handler for submission or I/O errors (may be NULL) + * @operation: the type of I/O to perform + * @data: the buffer to read or write (may be NULL) ++ * @size: the I/O amount in bytes + * + * The vio is enqueued on a vdo bio queue so that bio submission (which may block) does not block + * other vdo threads. +@@ -338,7 +339,7 @@ void vdo_submit_data_vio(struct data_vio *data_vio) + */ + void __submit_metadata_vio(struct vio *vio, physical_block_number_t physical, + bio_end_io_t callback, vdo_action_fn error_handler, +- blk_opf_t operation, char *data) ++ blk_opf_t operation, char *data, int size) + { + int result; + struct vdo_completion *completion = &vio->completion; +@@ -349,7 +350,8 @@ void __submit_metadata_vio(struct vio *vio, physical_block_number_t physical, + + vdo_reset_completion(completion); + completion->error_handler = error_handler; +- result = vio_reset_bio(vio, data, callback, operation | REQ_META, physical); ++ result = vio_reset_bio_with_size(vio, data, size, callback, operation | REQ_META, ++ physical); + if (result != VDO_SUCCESS) { + continue_vio(vio, result); + return; +diff --git a/drivers/md/dm-vdo/io-submitter.h b/drivers/md/dm-vdo/io-submitter.h +index 80748699496f2..3088f11055fdd 100644 +--- a/drivers/md/dm-vdo/io-submitter.h ++++ b/drivers/md/dm-vdo/io-submitter.h +@@ -8,6 +8,7 @@ + + #include + ++#include "constants.h" + #include "types.h" + + struct io_submitter; +@@ -26,14 +27,25 @@ void vdo_submit_data_vio(struct data_vio *data_vio); + + void __submit_metadata_vio(struct vio *vio, physical_block_number_t physical, + bio_end_io_t callback, vdo_action_fn error_handler, +- blk_opf_t operation, char *data); ++ blk_opf_t operation, char *data, int size); + + static inline void vdo_submit_metadata_vio(struct vio *vio, physical_block_number_t physical, + bio_end_io_t callback, vdo_action_fn error_handler, + blk_opf_t operation) + { + __submit_metadata_vio(vio, physical, callback, error_handler, +- operation, vio->data); ++ operation, vio->data, vio->block_count * VDO_BLOCK_SIZE); ++} ++ ++static inline void vdo_submit_metadata_vio_with_size(struct vio *vio, ++ physical_block_number_t physical, ++ bio_end_io_t callback, ++ vdo_action_fn error_handler, ++ blk_opf_t operation, ++ int size) ++{ ++ __submit_metadata_vio(vio, physical, callback, error_handler, ++ operation, vio->data, size); + } + + static inline void vdo_submit_flush_vio(struct vio *vio, bio_end_io_t callback, +@@ -41,7 +53,7 @@ static inline void vdo_submit_flush_vio(struct vio *vio, bio_end_io_t callback, + { + /* FIXME: Can we just use REQ_OP_FLUSH? */ + __submit_metadata_vio(vio, 0, callback, error_handler, +- REQ_OP_WRITE | REQ_PREFLUSH, NULL); ++ REQ_OP_WRITE | REQ_PREFLUSH, NULL, 0); + } + + #endif /* VDO_IO_SUBMITTER_H */ +diff --git a/drivers/md/dm-vdo/types.h b/drivers/md/dm-vdo/types.h +index dbe892b10f265..cdf36e7d77021 100644 +--- a/drivers/md/dm-vdo/types.h ++++ b/drivers/md/dm-vdo/types.h +@@ -376,6 +376,9 @@ struct vio { + /* The size of this vio in blocks */ + unsigned int block_count; + ++ /* The amount of data to be read or written, in bytes */ ++ unsigned int io_size; ++ + /* The data being read or written. */ + char *data; + +diff --git a/drivers/md/dm-vdo/vio.c b/drivers/md/dm-vdo/vio.c +index e710f3c5a972d..725d87ecf2150 100644 +--- a/drivers/md/dm-vdo/vio.c ++++ b/drivers/md/dm-vdo/vio.c +@@ -188,14 +188,23 @@ void vdo_set_bio_properties(struct bio *bio, struct vio *vio, bio_end_io_t callb + + /* + * Prepares the bio to perform IO with the specified buffer. May only be used on a VDO-allocated +- * bio, as it assumes the bio wraps a 4k buffer that is 4k aligned, but there does not have to be a +- * vio associated with the bio. ++ * bio, as it assumes the bio wraps a 4k-multiple buffer that is 4k aligned, but there does not ++ * have to be a vio associated with the bio. + */ + int vio_reset_bio(struct vio *vio, char *data, bio_end_io_t callback, + blk_opf_t bi_opf, physical_block_number_t pbn) + { +- int bvec_count, offset, len, i; ++ return vio_reset_bio_with_size(vio, data, vio->block_count * VDO_BLOCK_SIZE, ++ callback, bi_opf, pbn); ++} ++ ++int vio_reset_bio_with_size(struct vio *vio, char *data, int size, bio_end_io_t callback, ++ blk_opf_t bi_opf, physical_block_number_t pbn) ++{ ++ int bvec_count, offset, i; + struct bio *bio = vio->bio; ++ int vio_size = vio->block_count * VDO_BLOCK_SIZE; ++ int remaining; + + bio_reset(bio, bio->bi_bdev, bi_opf); + vdo_set_bio_properties(bio, vio, callback, bi_opf, pbn); +@@ -205,22 +214,21 @@ int vio_reset_bio(struct vio *vio, char *data, bio_end_io_t callback, + bio->bi_ioprio = 0; + bio->bi_io_vec = bio->bi_inline_vecs; + bio->bi_max_vecs = vio->block_count + 1; +- len = VDO_BLOCK_SIZE * vio->block_count; ++ if (VDO_ASSERT(size <= vio_size, "specified size %d is not greater than allocated %d", ++ size, vio_size) != VDO_SUCCESS) ++ size = vio_size; ++ vio->io_size = size; + offset = offset_in_page(data); +- bvec_count = DIV_ROUND_UP(offset + len, PAGE_SIZE); ++ bvec_count = DIV_ROUND_UP(offset + size, PAGE_SIZE); ++ remaining = size; + +- /* +- * If we knew that data was always on one page, or contiguous pages, we wouldn't need the +- * loop. But if we're using vmalloc, it's not impossible that the data is in different +- * pages that can't be merged in bio_add_page... +- */ +- for (i = 0; (i < bvec_count) && (len > 0); i++) { ++ for (i = 0; (i < bvec_count) && (remaining > 0); i++) { + struct page *page; + int bytes_added; + int bytes = PAGE_SIZE - offset; + +- if (bytes > len) +- bytes = len; ++ if (bytes > remaining) ++ bytes = remaining; + + page = is_vmalloc_addr(data) ? vmalloc_to_page(data) : virt_to_page(data); + bytes_added = bio_add_page(bio, page, bytes, offset); +@@ -232,7 +240,7 @@ int vio_reset_bio(struct vio *vio, char *data, bio_end_io_t callback, + } + + data += bytes; +- len -= bytes; ++ remaining -= bytes; + offset = 0; + } + +diff --git a/drivers/md/dm-vdo/vio.h b/drivers/md/dm-vdo/vio.h +index 3490e9f59b04a..74e8fd7c8c029 100644 +--- a/drivers/md/dm-vdo/vio.h ++++ b/drivers/md/dm-vdo/vio.h +@@ -123,6 +123,8 @@ void vdo_set_bio_properties(struct bio *bio, struct vio *vio, bio_end_io_t callb + + int vio_reset_bio(struct vio *vio, char *data, bio_end_io_t callback, + blk_opf_t bi_opf, physical_block_number_t pbn); ++int vio_reset_bio_with_size(struct vio *vio, char *data, int size, bio_end_io_t callback, ++ blk_opf_t bi_opf, physical_block_number_t pbn); + + void update_vio_error_stats(struct vio *vio, const char *format, ...) + __printf(2, 3); +-- +2.39.5 + diff --git a/queue-6.14/dma-mapping-avoid-potential-unused-data-compilation-.patch b/queue-6.14/dma-mapping-avoid-potential-unused-data-compilation-.patch new file mode 100644 index 0000000000..5a55c85e9c --- /dev/null +++ b/queue-6.14/dma-mapping-avoid-potential-unused-data-compilation-.patch @@ -0,0 +1,50 @@ +From 476cb6b8905e19cee5f5002df5a6716eb3d860c7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 15 Apr 2025 09:56:59 +0200 +Subject: dma-mapping: avoid potential unused data compilation warning + +From: Marek Szyprowski + +[ Upstream commit c9b19ea63036fc537a69265acea1b18dabd1cbd3 ] + +When CONFIG_NEED_DMA_MAP_STATE is not defined, dma-mapping clients might +report unused data compilation warnings for dma_unmap_*() calls +arguments. Redefine macros for those calls to let compiler to notice that +it is okay when the provided arguments are not used. + +Reported-by: Andy Shevchenko +Suggested-by: Jakub Kicinski +Signed-off-by: Marek Szyprowski +Tested-by: Andy Shevchenko +Link: https://lore.kernel.org/r/20250415075659.428549-1-m.szyprowski@samsung.com +Signed-off-by: Sasha Levin +--- + include/linux/dma-mapping.h | 12 ++++++++---- + 1 file changed, 8 insertions(+), 4 deletions(-) + +diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h +index b79925b1c4333..85ab710ec0e72 100644 +--- a/include/linux/dma-mapping.h ++++ b/include/linux/dma-mapping.h +@@ -629,10 +629,14 @@ static inline int dma_mmap_wc(struct device *dev, + #else + #define DEFINE_DMA_UNMAP_ADDR(ADDR_NAME) + #define DEFINE_DMA_UNMAP_LEN(LEN_NAME) +-#define dma_unmap_addr(PTR, ADDR_NAME) (0) +-#define dma_unmap_addr_set(PTR, ADDR_NAME, VAL) do { } while (0) +-#define dma_unmap_len(PTR, LEN_NAME) (0) +-#define dma_unmap_len_set(PTR, LEN_NAME, VAL) do { } while (0) ++#define dma_unmap_addr(PTR, ADDR_NAME) \ ++ ({ typeof(PTR) __p __maybe_unused = PTR; 0; }) ++#define dma_unmap_addr_set(PTR, ADDR_NAME, VAL) \ ++ do { typeof(PTR) __p __maybe_unused = PTR; } while (0) ++#define dma_unmap_len(PTR, LEN_NAME) \ ++ ({ typeof(PTR) __p __maybe_unused = PTR; 0; }) ++#define dma_unmap_len_set(PTR, LEN_NAME, VAL) \ ++ do { typeof(PTR) __p __maybe_unused = PTR; } while (0) + #endif + + #endif /* _LINUX_DMA_MAPPING_H */ +-- +2.39.5 + diff --git a/queue-6.14/dma-mapping-fix-warning-reported-for-missing-prototy.patch b/queue-6.14/dma-mapping-fix-warning-reported-for-missing-prototy.patch new file mode 100644 index 0000000000..c85d98ba4d --- /dev/null +++ b/queue-6.14/dma-mapping-fix-warning-reported-for-missing-prototy.patch @@ -0,0 +1,66 @@ +From 5915980b96f18903b1e14b52b4488182783e8790 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 22 Apr 2025 21:40:34 +1000 +Subject: dma-mapping: Fix warning reported for missing prototype + +From: Balbir Singh + +[ Upstream commit cae5572ec9261f752af834cdaaf5a0ba0afcf256 ] + +lkp reported a warning about missing prototype for a recent patch. + +The kernel-doc style comments are out of sync, move them to the right +function. + +Cc: Marek Szyprowski +Cc: Christoph Hellwig + +Reported-by: kernel test robot +Closes: https://lore.kernel.org/oe-kbuild-all/202504190615.g9fANxHw-lkp@intel.com/ + +Signed-off-by: Balbir Singh +[mszyprow: reformatted subject] +Signed-off-by: Marek Szyprowski +Link: https://lore.kernel.org/r/20250422114034.3535515-1-balbirs@nvidia.com +Signed-off-by: Sasha Levin +--- + kernel/dma/mapping.c | 16 ++++++++-------- + 1 file changed, 8 insertions(+), 8 deletions(-) + +diff --git a/kernel/dma/mapping.c b/kernel/dma/mapping.c +index 67da08fa67237..051a32988040f 100644 +--- a/kernel/dma/mapping.c ++++ b/kernel/dma/mapping.c +@@ -910,14 +910,6 @@ int dma_set_coherent_mask(struct device *dev, u64 mask) + } + EXPORT_SYMBOL(dma_set_coherent_mask); + +-/** +- * dma_addressing_limited - return if the device is addressing limited +- * @dev: device to check +- * +- * Return %true if the devices DMA mask is too small to address all memory in +- * the system, else %false. Lack of addressing bits is the prime reason for +- * bounce buffering, but might not be the only one. +- */ + static bool __dma_addressing_limited(struct device *dev) + { + const struct dma_map_ops *ops = get_dma_ops(dev); +@@ -931,6 +923,14 @@ static bool __dma_addressing_limited(struct device *dev) + return !dma_direct_all_ram_mapped(dev); + } + ++/** ++ * dma_addressing_limited - return if the device is addressing limited ++ * @dev: device to check ++ * ++ * Return %true if the devices DMA mask is too small to address all memory in ++ * the system, else %false. Lack of addressing bits is the prime reason for ++ * bounce buffering, but might not be the only one. ++ */ + bool dma_addressing_limited(struct device *dev) + { + if (!__dma_addressing_limited(dev)) +-- +2.39.5 + diff --git a/queue-6.14/dma-mapping.c-dev_dbg-support-for-dma_addressing_lim.patch b/queue-6.14/dma-mapping.c-dev_dbg-support-for-dma_addressing_lim.patch new file mode 100644 index 0000000000..bf8a2a91a6 --- /dev/null +++ b/queue-6.14/dma-mapping.c-dev_dbg-support-for-dma_addressing_lim.patch @@ -0,0 +1,83 @@ +From b77e818f7f80bf2b0176d96179bbff3495cc5125 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 14 Apr 2025 21:37:52 +1000 +Subject: dma/mapping.c: dev_dbg support for dma_addressing_limited +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Balbir Singh + +[ Upstream commit 2042c352e21d19eaf5f9e22fb6afce72293ef28c ] + +In the debug and resolution of an issue involving forced use of bounce +buffers, 7170130e4c72 ("x86/mm/init: Handle the special case of device +private pages in add_pages(), to not increase max_pfn and trigger +dma_addressing_limited() bounce buffers"). It would have been easier +to debug the issue if dma_addressing_limited() had debug information +about the device not being able to address all of memory and thus forcing +all accesses through a bounce buffer. Please see[2] + +Implement dev_dbg to debug the potential use of bounce buffers +when we hit the condition. When swiotlb is used, +dma_addressing_limited() is used to determine the size of maximum dma +buffer size in dma_direct_max_mapping_size(). The debug prints could be +triggered in that check as well (when enabled). + +Link: https://lore.kernel.org/lkml/20250401000752.249348-1-balbirs@nvidia.com/ [1] +Link: https://lore.kernel.org/lkml/20250310112206.4168-1-spasswolf@web.de/ [2] + +Cc: Marek Szyprowski +Cc: Robin Murphy +Cc: "Christian König" +Cc: Ingo Molnar +Cc: Kees Cook +Cc: Bjorn Helgaas +Cc: Linus Torvalds +Cc: Peter Zijlstra +Cc: Andy Lutomirski +Cc: Alex Deucher +Cc: Bert Karwatzki +Cc: Christoph Hellwig + +Signed-off-by: Balbir Singh +Reviewed-by: Christoph Hellwig +Signed-off-by: Marek Szyprowski +Link: https://lore.kernel.org/r/20250414113752.3298276-1-balbirs@nvidia.com +Signed-off-by: Sasha Levin +--- + kernel/dma/mapping.c | 11 ++++++++++- + 1 file changed, 10 insertions(+), 1 deletion(-) + +diff --git a/kernel/dma/mapping.c b/kernel/dma/mapping.c +index cda127027e48a..67da08fa67237 100644 +--- a/kernel/dma/mapping.c ++++ b/kernel/dma/mapping.c +@@ -918,7 +918,7 @@ EXPORT_SYMBOL(dma_set_coherent_mask); + * the system, else %false. Lack of addressing bits is the prime reason for + * bounce buffering, but might not be the only one. + */ +-bool dma_addressing_limited(struct device *dev) ++static bool __dma_addressing_limited(struct device *dev) + { + const struct dma_map_ops *ops = get_dma_ops(dev); + +@@ -930,6 +930,15 @@ bool dma_addressing_limited(struct device *dev) + return false; + return !dma_direct_all_ram_mapped(dev); + } ++ ++bool dma_addressing_limited(struct device *dev) ++{ ++ if (!__dma_addressing_limited(dev)) ++ return false; ++ ++ dev_dbg(dev, "device is DMA addressing limited\n"); ++ return true; ++} + EXPORT_SYMBOL_GPL(dma_addressing_limited); + + size_t dma_max_mapping_size(struct device *dev) +-- +2.39.5 + diff --git a/queue-6.14/dmaengine-ti-k3-udma-glue-drop-skip_fdq-argument-fro.patch b/queue-6.14/dmaengine-ti-k3-udma-glue-drop-skip_fdq-argument-fro.patch new file mode 100644 index 0000000000..57ae591216 --- /dev/null +++ b/queue-6.14/dmaengine-ti-k3-udma-glue-drop-skip_fdq-argument-fro.patch @@ -0,0 +1,197 @@ +From 54a9db82e32011419d2e3a6c30b30b40a8579327 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 24 Feb 2025 16:04:17 +0200 +Subject: dmaengine: ti: k3-udma-glue: Drop skip_fdq argument from + k3_udma_glue_reset_rx_chn + +From: Roger Quadros + +[ Upstream commit 0da30874729baeb01889b0eca16cfda122687503 ] + +The user of k3_udma_glue_reset_rx_chn() e.g. ti_am65_cpsw_nuss can +run on multiple platforms having different DMA architectures. +On some platforms there can be one FDQ for all flows in the RX channel +while for others there is a separate FDQ for each flow in the RX channel. + +So far we have been relying on the skip_fdq argument of +k3_udma_glue_reset_rx_chn(). + +Instead of relying on the user to provide this information, infer it +based on DMA architecture during k3_udma_glue_request_rx_chn() and save it +in an internal flag 'single_fdq'. Use that flag at +k3_udma_glue_reset_rx_chn() to deicide if the FDQ needs +to be cleared for every flow or just for flow 0. + +Fixes the below issue on ti_am65_cpsw_nuss driver on AM62-SK. + +> ip link set eth1 down +> ip link set eth0 down +> ethtool -L eth0 rx 8 +> ip link set eth0 up +> modprobe -r ti_am65_cpsw_nuss + +[ 103.045726] ------------[ cut here ]------------ +[ 103.050505] k3_knav_desc_pool size 512000 != avail 64000 +[ 103.050703] WARNING: CPU: 1 PID: 450 at drivers/net/ethernet/ti/k3-cppi-desc-pool.c:33 k3_cppi_desc_pool_destroy+0xa0/0xa8 [k3_cppi_desc_pool] +[ 103.068810] Modules linked in: ti_am65_cpsw_nuss(-) k3_cppi_desc_pool snd_soc_hdmi_codec crct10dif_ce snd_soc_simple_card snd_soc_simple_card_utils display_connector rtc_ti_k3 k3_j72xx_bandgap tidss drm_client_lib snd_soc_davinci_mcas +p drm_dma_helper tps6598x phylink snd_soc_ti_udma rti_wdt drm_display_helper snd_soc_tlv320aic3x_i2c typec at24 phy_gmii_sel snd_soc_ti_edma snd_soc_tlv320aic3x sii902x snd_soc_ti_sdma sa2ul omap_mailbox drm_kms_helper authenc cfg80211 r +fkill fuse drm drm_panel_orientation_quirks backlight ip_tables x_tables ipv6 [last unloaded: k3_cppi_desc_pool] +[ 103.119950] CPU: 1 UID: 0 PID: 450 Comm: modprobe Not tainted 6.13.0-rc7-00001-g9c5e3435fa66 #1011 +[ 103.119968] Hardware name: Texas Instruments AM625 SK (DT) +[ 103.119974] pstate: 80000005 (Nzcv daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--) +[ 103.119983] pc : k3_cppi_desc_pool_destroy+0xa0/0xa8 [k3_cppi_desc_pool] +[ 103.148007] lr : k3_cppi_desc_pool_destroy+0xa0/0xa8 [k3_cppi_desc_pool] +[ 103.154709] sp : ffff8000826ebbc0 +[ 103.158015] x29: ffff8000826ebbc0 x28: ffff0000090b6300 x27: 0000000000000000 +[ 103.165145] x26: 0000000000000000 x25: 0000000000000000 x24: ffff0000019df6b0 +[ 103.172271] x23: ffff0000019df6b8 x22: ffff0000019df410 x21: ffff8000826ebc88 +[ 103.179397] x20: 000000000007d000 x19: ffff00000a3b3000 x18: 0000000000000000 +[ 103.186522] x17: 0000000000000000 x16: 0000000000000000 x15: 000001e8c35e1cde +[ 103.193647] x14: 0000000000000396 x13: 000000000000035c x12: 0000000000000000 +[ 103.200772] x11: 000000000000003a x10: 00000000000009c0 x9 : ffff8000826eba20 +[ 103.207897] x8 : ffff0000090b6d20 x7 : ffff00007728c180 x6 : ffff00007728c100 +[ 103.215022] x5 : 0000000000000001 x4 : ffff000000508a50 x3 : ffff7ffff6146000 +[ 103.222147] x2 : 0000000000000000 x1 : e300b4173ee6b200 x0 : 0000000000000000 +[ 103.229274] Call trace: +[ 103.231714] k3_cppi_desc_pool_destroy+0xa0/0xa8 [k3_cppi_desc_pool] (P) +[ 103.238408] am65_cpsw_nuss_free_rx_chns+0x28/0x4c [ti_am65_cpsw_nuss] +[ 103.244942] devm_action_release+0x14/0x20 +[ 103.249040] release_nodes+0x3c/0x68 +[ 103.252610] devres_release_all+0x8c/0xdc +[ 103.256614] device_unbind_cleanup+0x18/0x60 +[ 103.260876] device_release_driver_internal+0xf8/0x178 +[ 103.266004] driver_detach+0x50/0x9c +[ 103.269571] bus_remove_driver+0x6c/0xbc +[ 103.273485] driver_unregister+0x30/0x60 +[ 103.277401] platform_driver_unregister+0x14/0x20 +[ 103.282096] am65_cpsw_nuss_driver_exit+0x18/0xff4 [ti_am65_cpsw_nuss] +[ 103.288620] __arm64_sys_delete_module+0x17c/0x25c +[ 103.293404] invoke_syscall+0x44/0x100 +[ 103.297149] el0_svc_common.constprop.0+0xc0/0xe0 +[ 103.301845] do_el0_svc+0x1c/0x28 +[ 103.305155] el0_svc+0x28/0x98 +[ 103.308207] el0t_64_sync_handler+0xc8/0xcc +[ 103.312384] el0t_64_sync+0x198/0x19c +[ 103.316040] ---[ end trace 0000000000000000 ]--- + +Signed-off-by: Roger Quadros +Acked-by: Jakub Kicinski +Acked-by: Peter Ujfalusi +Link: https://lore.kernel.org/r/20250224-k3-udma-glue-single-fdq-v2-1-cbe7621f2507@kernel.org +Signed-off-by: Vinod Koul +Signed-off-by: Sasha Levin +--- + drivers/dma/ti/k3-udma-glue.c | 15 +++++++++++---- + drivers/net/ethernet/ti/am65-cpsw-nuss.c | 4 ++-- + drivers/net/ethernet/ti/icssg/icssg_common.c | 2 +- + include/linux/dma/k3-udma-glue.h | 3 +-- + 4 files changed, 15 insertions(+), 9 deletions(-) + +diff --git a/drivers/dma/ti/k3-udma-glue.c b/drivers/dma/ti/k3-udma-glue.c +index 7c224c3ab7a07..f87d244cc2d67 100644 +--- a/drivers/dma/ti/k3-udma-glue.c ++++ b/drivers/dma/ti/k3-udma-glue.c +@@ -84,6 +84,7 @@ struct k3_udma_glue_rx_channel { + struct k3_udma_glue_rx_flow *flows; + u32 flow_num; + u32 flows_ready; ++ bool single_fdq; /* one FDQ for all flows */ + }; + + static void k3_udma_chan_dev_release(struct device *dev) +@@ -970,10 +971,13 @@ k3_udma_glue_request_rx_chn_priv(struct device *dev, const char *name, + + ep_cfg = rx_chn->common.ep_config; + +- if (xudma_is_pktdma(rx_chn->common.udmax)) ++ if (xudma_is_pktdma(rx_chn->common.udmax)) { + rx_chn->udma_rchan_id = ep_cfg->mapped_channel_id; +- else ++ rx_chn->single_fdq = false; ++ } else { + rx_chn->udma_rchan_id = -1; ++ rx_chn->single_fdq = true; ++ } + + /* request and cfg UDMAP RX channel */ + rx_chn->udma_rchanx = xudma_rchan_get(rx_chn->common.udmax, +@@ -1103,6 +1107,9 @@ k3_udma_glue_request_remote_rx_chn_common(struct k3_udma_glue_rx_channel *rx_chn + rx_chn->common.chan_dev.dma_coherent = true; + dma_coerce_mask_and_coherent(&rx_chn->common.chan_dev, + DMA_BIT_MASK(48)); ++ rx_chn->single_fdq = false; ++ } else { ++ rx_chn->single_fdq = true; + } + + ret = k3_udma_glue_allocate_rx_flows(rx_chn, cfg); +@@ -1453,7 +1460,7 @@ EXPORT_SYMBOL_GPL(k3_udma_glue_tdown_rx_chn); + + void k3_udma_glue_reset_rx_chn(struct k3_udma_glue_rx_channel *rx_chn, + u32 flow_num, void *data, +- void (*cleanup)(void *data, dma_addr_t desc_dma), bool skip_fdq) ++ void (*cleanup)(void *data, dma_addr_t desc_dma)) + { + struct k3_udma_glue_rx_flow *flow = &rx_chn->flows[flow_num]; + struct device *dev = rx_chn->common.dev; +@@ -1465,7 +1472,7 @@ void k3_udma_glue_reset_rx_chn(struct k3_udma_glue_rx_channel *rx_chn, + dev_dbg(dev, "RX reset flow %u occ_rx %u\n", flow_num, occ_rx); + + /* Skip RX FDQ in case one FDQ is used for the set of flows */ +- if (skip_fdq) ++ if (rx_chn->single_fdq && flow_num) + goto do_reset; + + /* +diff --git a/drivers/net/ethernet/ti/am65-cpsw-nuss.c b/drivers/net/ethernet/ti/am65-cpsw-nuss.c +index afe8127fd32be..cac67babe4559 100644 +--- a/drivers/net/ethernet/ti/am65-cpsw-nuss.c ++++ b/drivers/net/ethernet/ti/am65-cpsw-nuss.c +@@ -515,7 +515,7 @@ static void am65_cpsw_destroy_rxq(struct am65_cpsw_common *common, int id) + napi_disable(&flow->napi_rx); + hrtimer_cancel(&flow->rx_hrtimer); + k3_udma_glue_reset_rx_chn(rx_chn->rx_chn, id, rx_chn, +- am65_cpsw_nuss_rx_cleanup, !!id); ++ am65_cpsw_nuss_rx_cleanup); + + for (port = 0; port < common->port_num; port++) { + if (!common->ports[port].ndev) +@@ -3433,7 +3433,7 @@ static int am65_cpsw_nuss_register_ndevs(struct am65_cpsw_common *common) + for (i = 0; i < common->rx_ch_num_flows; i++) + k3_udma_glue_reset_rx_chn(rx_chan->rx_chn, i, + rx_chan, +- am65_cpsw_nuss_rx_cleanup, !!i); ++ am65_cpsw_nuss_rx_cleanup); + + k3_udma_glue_disable_rx_chn(rx_chan->rx_chn); + +diff --git a/drivers/net/ethernet/ti/icssg/icssg_common.c b/drivers/net/ethernet/ti/icssg/icssg_common.c +index 74f0f200a89d4..62065416e8861 100644 +--- a/drivers/net/ethernet/ti/icssg/icssg_common.c ++++ b/drivers/net/ethernet/ti/icssg/icssg_common.c +@@ -955,7 +955,7 @@ void prueth_reset_rx_chan(struct prueth_rx_chn *chn, + + for (i = 0; i < num_flows; i++) + k3_udma_glue_reset_rx_chn(chn->rx_chn, i, chn, +- prueth_rx_cleanup, !!i); ++ prueth_rx_cleanup); + if (disable) + k3_udma_glue_disable_rx_chn(chn->rx_chn); + } +diff --git a/include/linux/dma/k3-udma-glue.h b/include/linux/dma/k3-udma-glue.h +index 2dea217629d0a..5d43881e6fb77 100644 +--- a/include/linux/dma/k3-udma-glue.h ++++ b/include/linux/dma/k3-udma-glue.h +@@ -138,8 +138,7 @@ int k3_udma_glue_rx_get_irq(struct k3_udma_glue_rx_channel *rx_chn, + u32 flow_num); + void k3_udma_glue_reset_rx_chn(struct k3_udma_glue_rx_channel *rx_chn, + u32 flow_num, void *data, +- void (*cleanup)(void *data, dma_addr_t desc_dma), +- bool skip_fdq); ++ void (*cleanup)(void *data, dma_addr_t desc_dma)); + int k3_udma_glue_rx_flow_enable(struct k3_udma_glue_rx_channel *rx_chn, + u32 flow_idx); + int k3_udma_glue_rx_flow_disable(struct k3_udma_glue_rx_channel *rx_chn, +-- +2.39.5 + diff --git a/queue-6.14/dpll-add-an-assertion-to-check-freq_supported_num.patch b/queue-6.14/dpll-add-an-assertion-to-check-freq_supported_num.patch new file mode 100644 index 0000000000..bf523140bd --- /dev/null +++ b/queue-6.14/dpll-add-an-assertion-to-check-freq_supported_num.patch @@ -0,0 +1,43 @@ +From 7d00e7dc1055c18845a6a21a8003e5d22fd8d5a7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 28 Feb 2025 15:02:10 +0000 +Subject: dpll: Add an assertion to check freq_supported_num + +From: Jiasheng Jiang + +[ Upstream commit 39e912a959c19338855b768eaaee2917d7841f71 ] + +Since the driver is broken in the case that src->freq_supported is not +NULL but src->freq_supported_num is 0, add an assertion for it. + +Signed-off-by: Jiasheng Jiang +Reviewed-by: Jiri Pirko +Reviewed-by: Vadim Fedorenko +Reviewed-by: Arkadiusz Kubalewski +Link: https://patch.msgid.link/20250228150210.34404-1-jiashengjiangcool@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/dpll/dpll_core.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/drivers/dpll/dpll_core.c b/drivers/dpll/dpll_core.c +index 1877201d1aa9f..20bdc52f63a50 100644 +--- a/drivers/dpll/dpll_core.c ++++ b/drivers/dpll/dpll_core.c +@@ -443,8 +443,11 @@ static void dpll_pin_prop_free(struct dpll_pin_properties *prop) + static int dpll_pin_prop_dup(const struct dpll_pin_properties *src, + struct dpll_pin_properties *dst) + { ++ if (WARN_ON(src->freq_supported && !src->freq_supported_num)) ++ return -EINVAL; ++ + memcpy(dst, src, sizeof(*dst)); +- if (src->freq_supported && src->freq_supported_num) { ++ if (src->freq_supported) { + size_t freq_size = src->freq_supported_num * + sizeof(*src->freq_supported); + dst->freq_supported = kmemdup(src->freq_supported, +-- +2.39.5 + diff --git a/queue-6.14/dql-fix-dql-limit-value-when-reset.patch b/queue-6.14/dql-fix-dql-limit-value-when-reset.patch new file mode 100644 index 0000000000..3198f44423 --- /dev/null +++ b/queue-6.14/dql-fix-dql-limit-value-when-reset.patch @@ -0,0 +1,46 @@ +From 6fc181843107b6a8617e94a7242b4d5c3829a5c0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 19 Mar 2025 16:57:51 +0800 +Subject: dql: Fix dql->limit value when reset. + +From: Jing Su + +[ Upstream commit 3a17f23f7c36bac3a3584aaf97d3e3e0b2790396 ] + +Executing dql_reset after setting a non-zero value for limit_min can +lead to an unreasonable situation where dql->limit is less than +dql->limit_min. + +For instance, after setting +/sys/class/net/eth*/queues/tx-0/byte_queue_limits/limit_min, +an ifconfig down/up operation might cause the ethernet driver to call +netdev_tx_reset_queue, which in turn invokes dql_reset. + +In this case, dql->limit is reset to 0 while dql->limit_min remains +non-zero value, which is unexpected. The limit should always be +greater than or equal to limit_min. + +Signed-off-by: Jing Su +Link: https://patch.msgid.link/Z9qHD1s/NEuQBdgH@pilot-ThinkCentre-M930t-N000 +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + lib/dynamic_queue_limits.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/lib/dynamic_queue_limits.c b/lib/dynamic_queue_limits.c +index c1b7638a594ac..f97a752e900a0 100644 +--- a/lib/dynamic_queue_limits.c ++++ b/lib/dynamic_queue_limits.c +@@ -190,7 +190,7 @@ EXPORT_SYMBOL(dql_completed); + void dql_reset(struct dql *dql) + { + /* Reset all dynamic values */ +- dql->limit = 0; ++ dql->limit = dql->min_limit; + dql->num_queued = 0; + dql->num_completed = 0; + dql->last_obj_cnt = 0; +-- +2.39.5 + diff --git a/queue-6.14/driver-core-faux-only-create-the-device-if-probe-suc.patch b/queue-6.14/driver-core-faux-only-create-the-device-if-probe-suc.patch new file mode 100644 index 0000000000..28dab41dd0 --- /dev/null +++ b/queue-6.14/driver-core-faux-only-create-the-device-if-probe-suc.patch @@ -0,0 +1,64 @@ +From 469a5bbb0cefbe5ae7373c935815c35540dd31a2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 25 Feb 2025 07:35:46 +0100 +Subject: driver core: faux: only create the device if probe() succeeds + +From: Greg Kroah-Hartman + +[ Upstream commit 21b0dc55bed6d9b5dd5d1ad22b75d9d1c7426bbc ] + +It's really hard to know if a faux device properly passes the callback +to probe() without having to poke around in the faux_device structure +and then clean up. Instead of having to have every user of the api do +this logic, just do it in the faux device core itself. + +This makes the use of a custom probe() callback for a faux device much +simpler overall. + +Suggested-by: Kurt Borja +Cc: Rafael J. Wysocki +Reviewed-by: Kurt Borja +Reviewed-by: Danilo Krummrich +Link: https://lore.kernel.org/r/2025022545-unroasted-common-fa0e@gregkh +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/base/faux.c | 15 ++++++++++++++- + 1 file changed, 14 insertions(+), 1 deletion(-) + +diff --git a/drivers/base/faux.c b/drivers/base/faux.c +index 531e9d789ee04..407c1d1aad50b 100644 +--- a/drivers/base/faux.c ++++ b/drivers/base/faux.c +@@ -102,7 +102,9 @@ static void faux_device_release(struct device *dev) + * + * Note, when this function is called, the functions specified in struct + * faux_ops can be called before the function returns, so be prepared for +- * everything to be properly initialized before that point in time. ++ * everything to be properly initialized before that point in time. If the ++ * probe callback (if one is present) does NOT succeed, the creation of the ++ * device will fail and NULL will be returned. + * + * Return: + * * NULL if an error happened with creating the device +@@ -147,6 +149,17 @@ struct faux_device *faux_device_create_with_groups(const char *name, + return NULL; + } + ++ /* ++ * Verify that we did bind the driver to the device (i.e. probe worked), ++ * if not, let's fail the creation as trying to guess if probe was ++ * successful is almost impossible to determine by the caller. ++ */ ++ if (!dev->driver) { ++ dev_err(dev, "probe did not succeed, tearing down the device\n"); ++ faux_device_destroy(faux_dev); ++ faux_dev = NULL; ++ } ++ + return faux_dev; + } + EXPORT_SYMBOL_GPL(faux_device_create_with_groups); +-- +2.39.5 + diff --git a/queue-6.14/drm-add-valid-clones-check.patch b/queue-6.14/drm-add-valid-clones-check.patch new file mode 100644 index 0000000000..e6bc129fc4 --- /dev/null +++ b/queue-6.14/drm-add-valid-clones-check.patch @@ -0,0 +1,70 @@ +From 405e6cdabda45e49545617dfbf8856085c47a71c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 16 Dec 2024 16:43:14 -0800 +Subject: drm: Add valid clones check + +From: Jessica Zhang + +[ Upstream commit 41b4b11da02157c7474caf41d56baae0e941d01a ] + +Check that all encoders attached to a given CRTC are valid +possible_clones of each other. + +Signed-off-by: Jessica Zhang +Reviewed-by: Maxime Ripard +Link: https://patchwork.freedesktop.org/patch/msgid/20241216-concurrent-wb-v4-3-fe220297a7f0@quicinc.com +Signed-off-by: Dmitry Baryshkov +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/drm_atomic_helper.c | 28 ++++++++++++++++++++++++++++ + 1 file changed, 28 insertions(+) + +diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c +index 32902f77f00dd..40e4e1b6c9110 100644 +--- a/drivers/gpu/drm/drm_atomic_helper.c ++++ b/drivers/gpu/drm/drm_atomic_helper.c +@@ -574,6 +574,30 @@ mode_valid(struct drm_atomic_state *state) + return 0; + } + ++static int drm_atomic_check_valid_clones(struct drm_atomic_state *state, ++ struct drm_crtc *crtc) ++{ ++ struct drm_encoder *drm_enc; ++ struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, ++ crtc); ++ ++ drm_for_each_encoder_mask(drm_enc, crtc->dev, crtc_state->encoder_mask) { ++ if (!drm_enc->possible_clones) { ++ DRM_DEBUG("enc%d possible_clones is 0\n", drm_enc->base.id); ++ continue; ++ } ++ ++ if ((crtc_state->encoder_mask & drm_enc->possible_clones) != ++ crtc_state->encoder_mask) { ++ DRM_DEBUG("crtc%d failed valid clone check for mask 0x%x\n", ++ crtc->base.id, crtc_state->encoder_mask); ++ return -EINVAL; ++ } ++ } ++ ++ return 0; ++} ++ + /** + * drm_atomic_helper_check_modeset - validate state object for modeset changes + * @dev: DRM device +@@ -745,6 +769,10 @@ drm_atomic_helper_check_modeset(struct drm_device *dev, + ret = drm_atomic_add_affected_planes(state, crtc); + if (ret != 0) + return ret; ++ ++ ret = drm_atomic_check_valid_clones(state, crtc); ++ if (ret != 0) ++ return ret; + } + + /* +-- +2.39.5 + diff --git a/queue-6.14/drm-amd-display-account-for-oto-prefetch-bandwidth-w.patch b/queue-6.14/drm-amd-display-account-for-oto-prefetch-bandwidth-w.patch new file mode 100644 index 0000000000..5f7a7611b1 --- /dev/null +++ b/queue-6.14/drm-amd-display-account-for-oto-prefetch-bandwidth-w.patch @@ -0,0 +1,218 @@ +From 144b8b91a2ac75a10c0dbd7e245fb32458406d7c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 13 Jan 2025 14:13:51 -0500 +Subject: drm/amd/display: Account For OTO Prefetch Bandwidth When Calculating + Urgent Bandwidth + +From: Austin Zheng + +[ Upstream commit 36681f15bb12b5c01df924379cdab9234259825c ] + +[Why] +1) The current calculations for OTO prefetch bandwidth do not consider the number of DPP pipes in use. +As a result, OTO prefetch bandwidth may be larger than the vactive bandwidth if multiple DPP pipes are used. +OTO prefetch bandwidth should never exceed the vactive bandwidth. + +2) Mode programming may be mismatched with mode support +In cases where mode support has chosen to use the equalized (equ) prefetch schedule, +mode programming may end up using oto prefetch schedule instead. +The bandwidth required to do the oto schedule may end up being higher than the equ schedule. +This can cause the required urgent bandwidth to exceed the available urgent bandwidth. + +[How] +Output the oto prefetch bandwidth and incorperate it into the urgent bandwidth calculations +even if the prefetch schedule being used is not the oto schedule. + +Reviewed-by: Dillon Varone +Signed-off-by: Austin Zheng +Signed-off-by: Zaeem Mohamed +Tested-by: Daniel Wheeler +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + .../src/dml2_core/dml2_core_dcn4_calcs.c | 25 ++++++++++++++++++- + .../src/dml2_core/dml2_core_shared_types.h | 5 ++++ + 2 files changed, 29 insertions(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_dcn4_calcs.c b/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_dcn4_calcs.c +index 8ad7704b76691..913f33c31cf38 100644 +--- a/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_dcn4_calcs.c ++++ b/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_dcn4_calcs.c +@@ -4915,6 +4915,7 @@ static double get_urgent_bandwidth_required( + double ReadBandwidthChroma[], + double PrefetchBandwidthLuma[], + double PrefetchBandwidthChroma[], ++ double PrefetchBandwidthOto[], + double excess_vactive_fill_bw_l[], + double excess_vactive_fill_bw_c[], + double cursor_bw[], +@@ -4978,8 +4979,9 @@ static double get_urgent_bandwidth_required( + l->vm_row_bw = NumberOfDPP[k] * prefetch_vmrow_bw[k]; + l->flip_and_active_bw = l->per_plane_flip_bw[k] + ReadBandwidthLuma[k] * l->adj_factor_p0 + ReadBandwidthChroma[k] * l->adj_factor_p1 + cursor_bw[k] * l->adj_factor_cur; + l->flip_and_prefetch_bw = l->per_plane_flip_bw[k] + NumberOfDPP[k] * (PrefetchBandwidthLuma[k] * l->adj_factor_p0_pre + PrefetchBandwidthChroma[k] * l->adj_factor_p1_pre) + prefetch_cursor_bw[k] * l->adj_factor_cur_pre; ++ l->flip_and_prefetch_bw_oto = l->per_plane_flip_bw[k] + NumberOfDPP[k] * (PrefetchBandwidthOto[k] * l->adj_factor_p0_pre + PrefetchBandwidthChroma[k] * l->adj_factor_p1_pre) + prefetch_cursor_bw[k] * l->adj_factor_cur_pre; + l->active_and_excess_bw = (ReadBandwidthLuma[k] + excess_vactive_fill_bw_l[k]) * l->tmp_nom_adj_factor_p0 + (ReadBandwidthChroma[k] + excess_vactive_fill_bw_c[k]) * l->tmp_nom_adj_factor_p1 + dpte_row_bw[k] + meta_row_bw[k]; +- surface_required_bw[k] = math_max4(l->vm_row_bw, l->flip_and_active_bw, l->flip_and_prefetch_bw, l->active_and_excess_bw); ++ surface_required_bw[k] = math_max5(l->vm_row_bw, l->flip_and_active_bw, l->flip_and_prefetch_bw, l->active_and_excess_bw, l->flip_and_prefetch_bw_oto); + + /* export peak required bandwidth for the surface */ + surface_peak_required_bw[k] = math_max2(surface_required_bw[k], surface_peak_required_bw[k]); +@@ -5177,6 +5179,7 @@ static bool CalculatePrefetchSchedule(struct dml2_core_internal_scratch *scratch + s->Tsw_est3 = 0.0; + s->cursor_prefetch_bytes = 0; + *p->prefetch_cursor_bw = 0; ++ *p->RequiredPrefetchBWOTO = 0.0; + + dcc_mrq_enable = (p->dcc_enable && p->mrq_present); + +@@ -5390,6 +5393,9 @@ static bool CalculatePrefetchSchedule(struct dml2_core_internal_scratch *scratch + s->prefetch_bw_oto += (p->swath_width_chroma_ub * p->myPipe->BytePerPixelC) / s->LineTime; + } + ++ /* oto prefetch bw should be always be less than total vactive bw */ ++ DML2_ASSERT(s->prefetch_bw_oto < s->per_pipe_vactive_sw_bw * p->myPipe->DPPPerSurface); ++ + s->prefetch_bw_oto = math_max2(s->per_pipe_vactive_sw_bw, s->prefetch_bw_oto) * p->mall_prefetch_sdp_overhead_factor; + + s->prefetch_bw_oto = math_min2(s->prefetch_bw_oto, *p->prefetch_sw_bytes/(s->min_Lsw_oto*s->LineTime)); +@@ -5400,6 +5406,12 @@ static bool CalculatePrefetchSchedule(struct dml2_core_internal_scratch *scratch + p->vm_bytes * p->HostVMInefficiencyFactor / (31 * s->LineTime) - *p->Tno_bw, + (p->PixelPTEBytesPerRow * p->HostVMInefficiencyFactor + p->meta_row_bytes + tdlut_row_bytes) / (15 * s->LineTime)); + ++ /* oto bw needs to be outputted even if the oto schedule isn't being used to avoid ms/mp mismatch. ++ * mp will fail if ms decides to use equ schedule and mp decides to use oto schedule ++ * and the required bandwidth increases when going from ms to mp ++ */ ++ *p->RequiredPrefetchBWOTO = s->prefetch_bw_oto; ++ + #ifdef __DML_VBA_DEBUG__ + dml2_printf("DML::%s: vactive_sw_bw_l = %f\n", __func__, p->vactive_sw_bw_l); + dml2_printf("DML::%s: vactive_sw_bw_c = %f\n", __func__, p->vactive_sw_bw_c); +@@ -6160,6 +6172,7 @@ static void calculate_peak_bandwidth_required( + p->surface_read_bandwidth_c, + l->zero_array, //PrefetchBandwidthLuma, + l->zero_array, //PrefetchBandwidthChroma, ++ l->zero_array, //PrefetchBWOTO + l->zero_array, + l->zero_array, + l->zero_array, +@@ -6196,6 +6209,7 @@ static void calculate_peak_bandwidth_required( + p->surface_read_bandwidth_c, + l->zero_array, //PrefetchBandwidthLuma, + l->zero_array, //PrefetchBandwidthChroma, ++ l->zero_array, //PrefetchBWOTO + p->excess_vactive_fill_bw_l, + p->excess_vactive_fill_bw_c, + p->cursor_bw, +@@ -6232,6 +6246,7 @@ static void calculate_peak_bandwidth_required( + p->surface_read_bandwidth_c, + p->prefetch_bandwidth_l, + p->prefetch_bandwidth_c, ++ p->prefetch_bandwidth_oto, // to prevent ms/mp mismatch when oto bw > total vactive bw + p->excess_vactive_fill_bw_l, + p->excess_vactive_fill_bw_c, + p->cursor_bw, +@@ -6268,6 +6283,7 @@ static void calculate_peak_bandwidth_required( + p->surface_read_bandwidth_c, + p->prefetch_bandwidth_l, + p->prefetch_bandwidth_c, ++ p->prefetch_bandwidth_oto, // to prevent ms/mp mismatch when oto bw > total vactive bw + p->excess_vactive_fill_bw_l, + p->excess_vactive_fill_bw_c, + p->cursor_bw, +@@ -6304,6 +6320,7 @@ static void calculate_peak_bandwidth_required( + p->surface_read_bandwidth_c, + p->prefetch_bandwidth_l, + p->prefetch_bandwidth_c, ++ p->prefetch_bandwidth_oto, // to prevent ms/mp mismatch when oto bw > total vactive bw + p->excess_vactive_fill_bw_l, + p->excess_vactive_fill_bw_c, + p->cursor_bw, +@@ -9066,6 +9083,7 @@ static bool dml_core_mode_support(struct dml2_core_calcs_mode_support_ex *in_out + CalculatePrefetchSchedule_params->VRatioPrefetchC = &mode_lib->ms.VRatioPreC[k]; + CalculatePrefetchSchedule_params->RequiredPrefetchPixelDataBWLuma = &mode_lib->ms.RequiredPrefetchPixelDataBWLuma[k]; // prefetch_sw_bw_l + CalculatePrefetchSchedule_params->RequiredPrefetchPixelDataBWChroma = &mode_lib->ms.RequiredPrefetchPixelDataBWChroma[k]; // prefetch_sw_bw_c ++ CalculatePrefetchSchedule_params->RequiredPrefetchBWOTO = &mode_lib->ms.RequiredPrefetchBWOTO[k]; + CalculatePrefetchSchedule_params->NotEnoughTimeForDynamicMetadata = &mode_lib->ms.NoTimeForDynamicMetadata[k]; + CalculatePrefetchSchedule_params->Tno_bw = &mode_lib->ms.Tno_bw[k]; + CalculatePrefetchSchedule_params->Tno_bw_flip = &mode_lib->ms.Tno_bw_flip[k]; +@@ -9210,6 +9228,7 @@ static bool dml_core_mode_support(struct dml2_core_calcs_mode_support_ex *in_out + calculate_peak_bandwidth_params->surface_read_bandwidth_c = mode_lib->ms.vactive_sw_bw_c; + calculate_peak_bandwidth_params->prefetch_bandwidth_l = mode_lib->ms.RequiredPrefetchPixelDataBWLuma; + calculate_peak_bandwidth_params->prefetch_bandwidth_c = mode_lib->ms.RequiredPrefetchPixelDataBWChroma; ++ calculate_peak_bandwidth_params->prefetch_bandwidth_oto = mode_lib->ms.RequiredPrefetchBWOTO; + calculate_peak_bandwidth_params->excess_vactive_fill_bw_l = mode_lib->ms.excess_vactive_fill_bw_l; + calculate_peak_bandwidth_params->excess_vactive_fill_bw_c = mode_lib->ms.excess_vactive_fill_bw_c; + calculate_peak_bandwidth_params->cursor_bw = mode_lib->ms.cursor_bw; +@@ -9376,6 +9395,7 @@ static bool dml_core_mode_support(struct dml2_core_calcs_mode_support_ex *in_out + calculate_peak_bandwidth_params->surface_read_bandwidth_c = mode_lib->ms.vactive_sw_bw_c; + calculate_peak_bandwidth_params->prefetch_bandwidth_l = mode_lib->ms.RequiredPrefetchPixelDataBWLuma; + calculate_peak_bandwidth_params->prefetch_bandwidth_c = mode_lib->ms.RequiredPrefetchPixelDataBWChroma; ++ calculate_peak_bandwidth_params->prefetch_bandwidth_oto = mode_lib->ms.RequiredPrefetchBWOTO; + calculate_peak_bandwidth_params->excess_vactive_fill_bw_l = mode_lib->ms.excess_vactive_fill_bw_l; + calculate_peak_bandwidth_params->excess_vactive_fill_bw_c = mode_lib->ms.excess_vactive_fill_bw_c; + calculate_peak_bandwidth_params->cursor_bw = mode_lib->ms.cursor_bw; +@@ -11292,6 +11312,7 @@ static bool dml_core_mode_programming(struct dml2_core_calcs_mode_programming_ex + CalculatePrefetchSchedule_params->VRatioPrefetchC = &mode_lib->mp.VRatioPrefetchC[k]; + CalculatePrefetchSchedule_params->RequiredPrefetchPixelDataBWLuma = &mode_lib->mp.RequiredPrefetchPixelDataBWLuma[k]; + CalculatePrefetchSchedule_params->RequiredPrefetchPixelDataBWChroma = &mode_lib->mp.RequiredPrefetchPixelDataBWChroma[k]; ++ CalculatePrefetchSchedule_params->RequiredPrefetchBWOTO = &s->dummy_single_array[0][k]; + CalculatePrefetchSchedule_params->NotEnoughTimeForDynamicMetadata = &mode_lib->mp.NotEnoughTimeForDynamicMetadata[k]; + CalculatePrefetchSchedule_params->Tno_bw = &mode_lib->mp.Tno_bw[k]; + CalculatePrefetchSchedule_params->Tno_bw_flip = &mode_lib->mp.Tno_bw_flip[k]; +@@ -11434,6 +11455,7 @@ static bool dml_core_mode_programming(struct dml2_core_calcs_mode_programming_ex + calculate_peak_bandwidth_params->surface_read_bandwidth_c = mode_lib->mp.vactive_sw_bw_c; + calculate_peak_bandwidth_params->prefetch_bandwidth_l = mode_lib->mp.RequiredPrefetchPixelDataBWLuma; + calculate_peak_bandwidth_params->prefetch_bandwidth_c = mode_lib->mp.RequiredPrefetchPixelDataBWChroma; ++ calculate_peak_bandwidth_params->prefetch_bandwidth_oto = s->dummy_single_array[0]; + calculate_peak_bandwidth_params->excess_vactive_fill_bw_l = mode_lib->mp.excess_vactive_fill_bw_l; + calculate_peak_bandwidth_params->excess_vactive_fill_bw_c = mode_lib->mp.excess_vactive_fill_bw_c; + calculate_peak_bandwidth_params->cursor_bw = mode_lib->mp.cursor_bw; +@@ -11566,6 +11588,7 @@ static bool dml_core_mode_programming(struct dml2_core_calcs_mode_programming_ex + calculate_peak_bandwidth_params->surface_read_bandwidth_c = mode_lib->mp.vactive_sw_bw_c; + calculate_peak_bandwidth_params->prefetch_bandwidth_l = mode_lib->mp.RequiredPrefetchPixelDataBWLuma; + calculate_peak_bandwidth_params->prefetch_bandwidth_c = mode_lib->mp.RequiredPrefetchPixelDataBWChroma; ++ calculate_peak_bandwidth_params->prefetch_bandwidth_oto = s->dummy_single_array[k]; + calculate_peak_bandwidth_params->excess_vactive_fill_bw_l = mode_lib->mp.excess_vactive_fill_bw_l; + calculate_peak_bandwidth_params->excess_vactive_fill_bw_c = mode_lib->mp.excess_vactive_fill_bw_c; + calculate_peak_bandwidth_params->cursor_bw = mode_lib->mp.cursor_bw; +diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_shared_types.h b/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_shared_types.h +index 23c0fca5515fe..b7cb017b59baa 100644 +--- a/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_shared_types.h ++++ b/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_shared_types.h +@@ -484,6 +484,8 @@ struct dml2_core_internal_mode_support { + double WriteBandwidth[DML2_MAX_PLANES][DML2_MAX_WRITEBACK]; + double RequiredPrefetchPixelDataBWLuma[DML2_MAX_PLANES]; + double RequiredPrefetchPixelDataBWChroma[DML2_MAX_PLANES]; ++ /* oto bw should also be considered when calculating urgent bw to avoid situations oto/equ mismatches between ms and mp */ ++ double RequiredPrefetchBWOTO[DML2_MAX_PLANES]; + double cursor_bw[DML2_MAX_PLANES]; + double prefetch_cursor_bw[DML2_MAX_PLANES]; + double prefetch_vmrow_bw[DML2_MAX_PLANES]; +@@ -1381,6 +1383,7 @@ struct dml2_core_shared_get_urgent_bandwidth_required_locals { + double vm_row_bw; + double flip_and_active_bw; + double flip_and_prefetch_bw; ++ double flip_and_prefetch_bw_oto; + double active_and_excess_bw; + }; + +@@ -1792,6 +1795,7 @@ struct dml2_core_calcs_CalculatePrefetchSchedule_params { + double *VRatioPrefetchC; + double *RequiredPrefetchPixelDataBWLuma; + double *RequiredPrefetchPixelDataBWChroma; ++ double *RequiredPrefetchBWOTO; + bool *NotEnoughTimeForDynamicMetadata; + double *Tno_bw; + double *Tno_bw_flip; +@@ -2025,6 +2029,7 @@ struct dml2_core_calcs_calculate_peak_bandwidth_required_params { + double *surface_read_bandwidth_c; + double *prefetch_bandwidth_l; + double *prefetch_bandwidth_c; ++ double *prefetch_bandwidth_oto; + double *excess_vactive_fill_bw_l; + double *excess_vactive_fill_bw_c; + double *cursor_bw; +-- +2.39.5 + diff --git a/queue-6.14/drm-amd-display-add-opp-recout-adjustment.patch b/queue-6.14/drm-amd-display-add-opp-recout-adjustment.patch new file mode 100644 index 0000000000..a81316ba06 --- /dev/null +++ b/queue-6.14/drm-amd-display-add-opp-recout-adjustment.patch @@ -0,0 +1,130 @@ +From c9e5720c802a163c0a96de59a08e5b0f04d02ae3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 20 Jan 2025 12:35:23 -0500 +Subject: drm/amd/display: Add opp recout adjustment + +From: Navid Assadian + +[ Upstream commit fba4d19f3731483ee8565f9e9bb7ed9fc89479e8 ] + +[Why] +For subsampled YUV output formats, more pixels can get fetched and be +used for scaling. + +[How] +Add the adjustment to the calculated recout, so the viewport covers the +corresponding pixels on the source plane. + +Signed-off-by: Navid Assadian +Reviewed-by: Samson Tam +Tested-by: Daniel Wheeler +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/display/dc/spl/dc_spl.c | 31 +++++++++++++++---- + .../gpu/drm/amd/display/dc/spl/dc_spl_types.h | 10 ++++++ + 2 files changed, 35 insertions(+), 6 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/spl/dc_spl.c b/drivers/gpu/drm/amd/display/dc/spl/dc_spl.c +index 22602f088553d..153b7a8904e1e 100644 +--- a/drivers/gpu/drm/amd/display/dc/spl/dc_spl.c ++++ b/drivers/gpu/drm/amd/display/dc/spl/dc_spl.c +@@ -76,6 +76,21 @@ static struct spl_rect shift_rec(const struct spl_rect *rec_in, int x, int y) + return rec_out; + } + ++static void spl_opp_adjust_rect(struct spl_rect *rec, const struct spl_opp_adjust *adjust) ++{ ++ if ((rec->x + adjust->x) >= 0) ++ rec->x += adjust->x; ++ ++ if ((rec->y + adjust->y) >= 0) ++ rec->y += adjust->y; ++ ++ if ((rec->width + adjust->width) >= 1) ++ rec->width += adjust->width; ++ ++ if ((rec->height + adjust->height) >= 1) ++ rec->height += adjust->height; ++} ++ + static struct spl_rect calculate_plane_rec_in_timing_active( + struct spl_in *spl_in, + const struct spl_rect *rec_in) +@@ -723,13 +738,15 @@ static void spl_handle_3d_recout(struct spl_in *spl_in, struct spl_rect *recout) + } + } + +-static void spl_clamp_viewport(struct spl_rect *viewport) ++static void spl_clamp_viewport(struct spl_rect *viewport, int min_viewport_size) + { ++ if (min_viewport_size == 0) ++ min_viewport_size = MIN_VIEWPORT_SIZE; + /* Clamp minimum viewport size */ +- if (viewport->height < MIN_VIEWPORT_SIZE) +- viewport->height = MIN_VIEWPORT_SIZE; +- if (viewport->width < MIN_VIEWPORT_SIZE) +- viewport->width = MIN_VIEWPORT_SIZE; ++ if (viewport->height < min_viewport_size) ++ viewport->height = min_viewport_size; ++ if (viewport->width < min_viewport_size) ++ viewport->width = min_viewport_size; + } + + static enum scl_mode spl_get_dscl_mode(const struct spl_in *spl_in, +@@ -1800,6 +1817,8 @@ static bool spl_calculate_number_of_taps(struct spl_in *spl_in, struct spl_scrat + spl_calculate_recout(spl_in, spl_scratch, spl_out); + /* depends on pixel format */ + spl_calculate_scaling_ratios(spl_in, spl_scratch, spl_out); ++ /* Adjust recout for opp if needed */ ++ spl_opp_adjust_rect(&spl_scratch->scl_data.recout, &spl_in->basic_in.opp_recout_adjust); + /* depends on scaling ratios and recout, does not calculate offset yet */ + spl_calculate_viewport_size(spl_in, spl_scratch); + +@@ -1836,7 +1855,7 @@ bool spl_calculate_scaler_params(struct spl_in *spl_in, struct spl_out *spl_out) + // Handle 3d recout + spl_handle_3d_recout(spl_in, &spl_scratch.scl_data.recout); + // Clamp +- spl_clamp_viewport(&spl_scratch.scl_data.viewport); ++ spl_clamp_viewport(&spl_scratch.scl_data.viewport, spl_in->min_viewport_size); + + // Save all calculated parameters in dscl_prog_data structure to program hw registers + spl_set_dscl_prog_data(spl_in, &spl_scratch, spl_out, enable_easf_v, enable_easf_h, enable_isharp); +diff --git a/drivers/gpu/drm/amd/display/dc/spl/dc_spl_types.h b/drivers/gpu/drm/amd/display/dc/spl/dc_spl_types.h +index 5d139cf51e89b..1c3949b24611f 100644 +--- a/drivers/gpu/drm/amd/display/dc/spl/dc_spl_types.h ++++ b/drivers/gpu/drm/amd/display/dc/spl/dc_spl_types.h +@@ -427,6 +427,14 @@ struct spl_out { + + // SPL inputs + ++// opp extra adjustment for rect ++struct spl_opp_adjust { ++ int x; ++ int y; ++ int width; ++ int height; ++}; ++ + // Basic input information + struct basic_in { + enum spl_pixel_format format; // Pixel Format +@@ -444,6 +452,7 @@ struct basic_in { + } num_slices_recout_width; + } num_h_slices_recout_width_align; + int mpc_h_slice_index; // previous mpc_combine_v - split_idx ++ struct spl_opp_adjust opp_recout_adjust; + // Inputs for adaptive scaler - TODO + enum spl_transfer_func_type tf_type; /* Transfer function type */ + enum spl_transfer_func_predefined tf_predefined_type; /* Transfer function predefined type */ +@@ -535,6 +544,7 @@ struct spl_in { + bool is_hdr_on; + int h_active; + int v_active; ++ int min_viewport_size; + int sdr_white_level_nits; + enum sharpen_policy sharpen_policy; + }; +-- +2.39.5 + diff --git a/queue-6.14/drm-amd-display-add-support-for-disconnected-edp-str.patch b/queue-6.14/drm-amd-display-add-support-for-disconnected-edp-str.patch new file mode 100644 index 0000000000..bdd0fec320 --- /dev/null +++ b/queue-6.14/drm-amd-display-add-support-for-disconnected-edp-str.patch @@ -0,0 +1,54 @@ +From ea71cdda73d2a5d6bfdd47db95d2ab3f033352ce Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 7 Feb 2025 13:46:53 -0500 +Subject: drm/amd/display: Add support for disconnected eDP streams + +From: Harry VanZyllDeJong + +[ Upstream commit 6571bef25fe48c642f7a69ccf7c3198b317c136a ] + +[Why] +eDP may not be connected to the GPU on driver start causing +fail enumeration. + +[How] +Move the virtual signal type check before the eDP connector +signal check. + +Reviewed-by: Wenjing Liu +Signed-off-by: Harry VanZyllDeJong +Signed-off-by: Roman Li +Tested-by: Daniel Wheeler +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + .../drm/amd/display/dc/link/protocols/link_dp_capability.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c +index 6d7131369f00b..28843e9882d39 100644 +--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c ++++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c +@@ -945,6 +945,9 @@ bool link_decide_link_settings(struct dc_stream_state *stream, + * TODO: add MST specific link training routine + */ + decide_mst_link_settings(link, link_setting); ++ } else if (stream->signal == SIGNAL_TYPE_VIRTUAL) { ++ link_setting->lane_count = LANE_COUNT_FOUR; ++ link_setting->link_rate = LINK_RATE_HIGH3; + } else if (link->connector_signal == SIGNAL_TYPE_EDP) { + /* enable edp link optimization for DSC eDP case */ + if (stream->timing.flags.DSC) { +@@ -967,9 +970,6 @@ bool link_decide_link_settings(struct dc_stream_state *stream, + } else { + edp_decide_link_settings(link, link_setting, req_bw); + } +- } else if (stream->signal == SIGNAL_TYPE_VIRTUAL) { +- link_setting->lane_count = LANE_COUNT_FOUR; +- link_setting->link_rate = LINK_RATE_HIGH3; + } else { + decide_dp_link_settings(link, link_setting, req_bw); + } +-- +2.39.5 + diff --git a/queue-6.14/drm-amd-display-ammend-dcpg-ip-control-sequences-to-.patch b/queue-6.14/drm-amd-display-ammend-dcpg-ip-control-sequences-to-.patch new file mode 100644 index 0000000000..5b31fd56cb --- /dev/null +++ b/queue-6.14/drm-amd-display-ammend-dcpg-ip-control-sequences-to-.patch @@ -0,0 +1,135 @@ +From 9d40dfbefe3e2127f6cc75d95ebf5f919dc72bf7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 14 Jan 2025 12:14:26 -0500 +Subject: drm/amd/display: Ammend DCPG IP control sequences to align with HW + guidance + +From: Dillon Varone + +[ Upstream commit cbd97d621ece1d92c3542e52f8af7c04cd2c6afb ] + +[WHY&HOW] +IP_REQUEST_CNTL should only be toggled off when it was originally, never +unconditionally. + +Reviewed-by: Alvin Lee +Signed-off-by: Dillon Varone +Signed-off-by: Zaeem Mohamed +Tested-by: Daniel Wheeler +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + .../amd/display/dc/hwss/dcn20/dcn20_hwseq.c | 14 +++++--- + .../amd/display/dc/hwss/dcn401/dcn401_hwseq.c | 34 +++++++++++++++++++ + .../amd/display/dc/hwss/dcn401/dcn401_hwseq.h | 3 ++ + .../amd/display/dc/hwss/dcn401/dcn401_init.c | 2 +- + 4 files changed, 48 insertions(+), 5 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c +index f7e31aec32058..1a07973ead4f5 100644 +--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c ++++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c +@@ -1264,14 +1264,18 @@ static void dcn20_power_on_plane_resources( + struct dce_hwseq *hws, + struct pipe_ctx *pipe_ctx) + { ++ uint32_t org_ip_request_cntl = 0; ++ + DC_LOGGER_INIT(hws->ctx->logger); + + if (hws->funcs.dpp_root_clock_control) + hws->funcs.dpp_root_clock_control(hws, pipe_ctx->plane_res.dpp->inst, true); + + if (REG(DC_IP_REQUEST_CNTL)) { +- REG_SET(DC_IP_REQUEST_CNTL, 0, +- IP_REQUEST_EN, 1); ++ REG_GET(DC_IP_REQUEST_CNTL, IP_REQUEST_EN, &org_ip_request_cntl); ++ if (org_ip_request_cntl == 0) ++ REG_SET(DC_IP_REQUEST_CNTL, 0, ++ IP_REQUEST_EN, 1); + + if (hws->funcs.dpp_pg_control) + hws->funcs.dpp_pg_control(hws, pipe_ctx->plane_res.dpp->inst, true); +@@ -1279,8 +1283,10 @@ static void dcn20_power_on_plane_resources( + if (hws->funcs.hubp_pg_control) + hws->funcs.hubp_pg_control(hws, pipe_ctx->plane_res.hubp->inst, true); + +- REG_SET(DC_IP_REQUEST_CNTL, 0, +- IP_REQUEST_EN, 0); ++ if (org_ip_request_cntl == 0) ++ REG_SET(DC_IP_REQUEST_CNTL, 0, ++ IP_REQUEST_EN, 0); ++ + DC_LOG_DEBUG( + "Un-gated front end for pipe %d\n", pipe_ctx->plane_res.hubp->inst); + } +diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c +index 284f011f5643d..a6f2aff84267d 100644 +--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c ++++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c +@@ -2655,3 +2655,37 @@ void dcn401_detect_pipe_changes(struct dc_state *old_state, + new_pipe->update_flags.bits.test_pattern_changed = 1; + } + } ++ ++void dcn401_plane_atomic_power_down(struct dc *dc, ++ struct dpp *dpp, ++ struct hubp *hubp) ++{ ++ struct dce_hwseq *hws = dc->hwseq; ++ uint32_t org_ip_request_cntl = 0; ++ ++ DC_LOGGER_INIT(dc->ctx->logger); ++ ++ REG_GET(DC_IP_REQUEST_CNTL, IP_REQUEST_EN, &org_ip_request_cntl); ++ if (org_ip_request_cntl == 0) ++ REG_SET(DC_IP_REQUEST_CNTL, 0, ++ IP_REQUEST_EN, 1); ++ ++ if (hws->funcs.dpp_pg_control) ++ hws->funcs.dpp_pg_control(hws, dpp->inst, false); ++ ++ if (hws->funcs.hubp_pg_control) ++ hws->funcs.hubp_pg_control(hws, hubp->inst, false); ++ ++ hubp->funcs->hubp_reset(hubp); ++ dpp->funcs->dpp_reset(dpp); ++ ++ if (org_ip_request_cntl == 0) ++ REG_SET(DC_IP_REQUEST_CNTL, 0, ++ IP_REQUEST_EN, 0); ++ ++ DC_LOG_DEBUG( ++ "Power gated front end %d\n", hubp->inst); ++ ++ if (hws->funcs.dpp_root_clock_control) ++ hws->funcs.dpp_root_clock_control(hws, dpp->inst, false); ++} +diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.h b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.h +index 17cea748789e1..dbd69d215b8bc 100644 +--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.h ++++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.h +@@ -102,4 +102,7 @@ void dcn401_detect_pipe_changes( + struct dc_state *new_state, + struct pipe_ctx *old_pipe, + struct pipe_ctx *new_pipe); ++void dcn401_plane_atomic_power_down(struct dc *dc, ++ struct dpp *dpp, ++ struct hubp *hubp); + #endif /* __DC_HWSS_DCN401_H__ */ +diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_init.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_init.c +index 44cb376f97c17..a4e3501fadbbe 100644 +--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_init.c ++++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_init.c +@@ -123,7 +123,7 @@ static const struct hwseq_private_funcs dcn401_private_funcs = { + .disable_vga = dcn20_disable_vga, + .bios_golden_init = dcn10_bios_golden_init, + .plane_atomic_disable = dcn20_plane_atomic_disable, +- .plane_atomic_power_down = dcn10_plane_atomic_power_down, ++ .plane_atomic_power_down = dcn401_plane_atomic_power_down, + .enable_power_gating_plane = dcn32_enable_power_gating_plane, + .hubp_pg_control = dcn32_hubp_pg_control, + .program_all_writeback_pipes_in_tree = dcn30_program_all_writeback_pipes_in_tree, +-- +2.39.5 + diff --git a/queue-6.14/drm-amd-display-calculate-the-remain-segments-for-al.patch b/queue-6.14/drm-amd-display-calculate-the-remain-segments-for-al.patch new file mode 100644 index 0000000000..39a60c2d78 --- /dev/null +++ b/queue-6.14/drm-amd-display-calculate-the-remain-segments-for-al.patch @@ -0,0 +1,95 @@ +From 678160d9fb7eafe7bd1327c3e8430dff276a5ab1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 27 Feb 2025 20:09:14 +0800 +Subject: drm/amd/display: calculate the remain segments for all pipes + +From: Zhikai Zhai + +[ Upstream commit d3069feecdb5542604d29b59acfd1fd213bad95b ] + +[WHY] +In some cases the remain de-tile buffer segments will be greater +than zero if we don't add the non-top pipe to calculate, at +this time the override de-tile buffer size will be valid and used. +But it makes the de-tile buffer segments used finally for all of pipes +exceed the maximum. + +[HOW] +Add the non-top pipe to calculate the remain de-tile buffer segments. +Don't set override size to use the average according to pipe count +if the value exceed the maximum. + +Reviewed-by: Charlene Liu +Signed-off-by: Zhikai Zhai +Signed-off-by: Tom Chung +Tested-by: Daniel Wheeler +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + .../dc/resource/dcn315/dcn315_resource.c | 42 +++++++++---------- + 1 file changed, 20 insertions(+), 22 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn315/dcn315_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn315/dcn315_resource.c +index 14acef036b5a0..6c2bb3f63be15 100644 +--- a/drivers/gpu/drm/amd/display/dc/resource/dcn315/dcn315_resource.c ++++ b/drivers/gpu/drm/amd/display/dc/resource/dcn315/dcn315_resource.c +@@ -1698,7 +1698,7 @@ static int dcn315_populate_dml_pipes_from_context( + pipes[pipe_cnt].dout.dsc_input_bpc = 0; + DC_FP_START(); + dcn31_zero_pipe_dcc_fraction(pipes, pipe_cnt); +- if (pixel_rate_crb && !pipe->top_pipe && !pipe->prev_odm_pipe) { ++ if (pixel_rate_crb) { + int bpp = source_format_to_bpp(pipes[pipe_cnt].pipe.src.source_format); + /* Ceil to crb segment size */ + int approx_det_segs_required_for_pstate = dcn_get_approx_det_segs_required_for_pstate( +@@ -1755,28 +1755,26 @@ static int dcn315_populate_dml_pipes_from_context( + continue; + } + +- if (!pipe->top_pipe && !pipe->prev_odm_pipe) { +- bool split_required = pipe->stream->timing.pix_clk_100hz >= dcn_get_max_non_odm_pix_rate_100hz(&dc->dml.soc) +- || (pipe->plane_state && pipe->plane_state->src_rect.width > 5120); +- +- if (remaining_det_segs > MIN_RESERVED_DET_SEGS && crb_pipes != 0) +- pipes[pipe_cnt].pipe.src.det_size_override += (remaining_det_segs - MIN_RESERVED_DET_SEGS) / crb_pipes + +- (crb_idx < (remaining_det_segs - MIN_RESERVED_DET_SEGS) % crb_pipes ? 1 : 0); +- if (pipes[pipe_cnt].pipe.src.det_size_override > 2 * DCN3_15_MAX_DET_SEGS) { +- /* Clamp to 2 pipe split max det segments */ +- remaining_det_segs += pipes[pipe_cnt].pipe.src.det_size_override - 2 * (DCN3_15_MAX_DET_SEGS); +- pipes[pipe_cnt].pipe.src.det_size_override = 2 * DCN3_15_MAX_DET_SEGS; +- } +- if (pipes[pipe_cnt].pipe.src.det_size_override > DCN3_15_MAX_DET_SEGS || split_required) { +- /* If we are splitting we must have an even number of segments */ +- remaining_det_segs += pipes[pipe_cnt].pipe.src.det_size_override % 2; +- pipes[pipe_cnt].pipe.src.det_size_override -= pipes[pipe_cnt].pipe.src.det_size_override % 2; +- } +- /* Convert segments into size for DML use */ +- pipes[pipe_cnt].pipe.src.det_size_override *= DCN3_15_CRB_SEGMENT_SIZE_KB; +- +- crb_idx++; ++ bool split_required = pipe->stream->timing.pix_clk_100hz >= dcn_get_max_non_odm_pix_rate_100hz(&dc->dml.soc) ++ || (pipe->plane_state && pipe->plane_state->src_rect.width > 5120); ++ ++ if (remaining_det_segs > MIN_RESERVED_DET_SEGS && crb_pipes != 0) ++ pipes[pipe_cnt].pipe.src.det_size_override += (remaining_det_segs - MIN_RESERVED_DET_SEGS) / crb_pipes + ++ (crb_idx < (remaining_det_segs - MIN_RESERVED_DET_SEGS) % crb_pipes ? 1 : 0); ++ if (pipes[pipe_cnt].pipe.src.det_size_override > 2 * DCN3_15_MAX_DET_SEGS) { ++ /* Clamp to 2 pipe split max det segments */ ++ remaining_det_segs += pipes[pipe_cnt].pipe.src.det_size_override - 2 * (DCN3_15_MAX_DET_SEGS); ++ pipes[pipe_cnt].pipe.src.det_size_override = 2 * DCN3_15_MAX_DET_SEGS; ++ } ++ if (pipes[pipe_cnt].pipe.src.det_size_override > DCN3_15_MAX_DET_SEGS || split_required) { ++ /* If we are splitting we must have an even number of segments */ ++ remaining_det_segs += pipes[pipe_cnt].pipe.src.det_size_override % 2; ++ pipes[pipe_cnt].pipe.src.det_size_override -= pipes[pipe_cnt].pipe.src.det_size_override % 2; + } ++ /* Convert segments into size for DML use */ ++ pipes[pipe_cnt].pipe.src.det_size_override *= DCN3_15_CRB_SEGMENT_SIZE_KB; ++ ++ crb_idx++; + pipe_cnt++; + } + } +-- +2.39.5 + diff --git a/queue-6.14/drm-amd-display-call-fp-protect-before-mode-programm.patch b/queue-6.14/drm-amd-display-call-fp-protect-before-mode-programm.patch new file mode 100644 index 0000000000..e9fad30b49 --- /dev/null +++ b/queue-6.14/drm-amd-display-call-fp-protect-before-mode-programm.patch @@ -0,0 +1,73 @@ +From bf4a0c678ba742424cd8675f0700546381eab492 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 17 Apr 2025 10:24:29 -0400 +Subject: drm/amd/display: Call FP Protect Before Mode Programming/Mode Support + +From: Austin Zheng + +[ Upstream commit eba692ca3abca258b3214a6e4126afefad1822f0 ] + +[Why] +Memory allocation occurs within dml21_validate() for adding phantom planes. +May cause kernel to be tainted due to usage of FP Start. + +[How] +Move FP start from dml21_validate to before mode programming/mode support. +Calculations requiring floating point are all done within mode programming +or mode support. + +Reviewed-by: Alvin Lee +Signed-off-by: Austin Zheng +Signed-off-by: Ray Wu +Tested-by: Daniel Wheeler +Signed-off-by: Alex Deucher +(cherry picked from commit fe3250f10819b411808ab9ae1d824c5fc9b59170) +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_wrapper.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_wrapper.c b/drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_wrapper.c +index 5d16f36ec95c8..ed6584535e898 100644 +--- a/drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_wrapper.c ++++ b/drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_wrapper.c +@@ -234,7 +234,9 @@ static bool dml21_mode_check_and_programming(const struct dc *in_dc, struct dc_s + if (!result) + return false; + ++ DC_FP_START(); + result = dml2_build_mode_programming(mode_programming); ++ DC_FP_END(); + if (!result) + return false; + +@@ -277,7 +279,9 @@ static bool dml21_check_mode_support(const struct dc *in_dc, struct dc_state *co + mode_support->dml2_instance = dml_init->dml2_instance; + dml21_map_dc_state_into_dml_display_cfg(in_dc, context, dml_ctx); + dml_ctx->v21.mode_programming.dml2_instance->scratch.build_mode_programming_locals.mode_programming_params.programming = dml_ctx->v21.mode_programming.programming; ++ DC_FP_START(); + is_supported = dml2_check_mode_supported(mode_support); ++ DC_FP_END(); + if (!is_supported) + return false; + +@@ -288,16 +292,12 @@ bool dml21_validate(const struct dc *in_dc, struct dc_state *context, struct dml + { + bool out = false; + +- DC_FP_START(); +- + /* Use dml_validate_only for fast_validate path */ + if (fast_validate) + out = dml21_check_mode_support(in_dc, context, dml_ctx); + else + out = dml21_mode_check_and_programming(in_dc, context, dml_ctx); + +- DC_FP_END(); +- + return out; + } + +-- +2.39.5 + diff --git a/queue-6.14/drm-amd-display-correct-timing_adjust_pending-flag-s.patch b/queue-6.14/drm-amd-display-correct-timing_adjust_pending-flag-s.patch new file mode 100644 index 0000000000..aef1ed1263 --- /dev/null +++ b/queue-6.14/drm-amd-display-correct-timing_adjust_pending-flag-s.patch @@ -0,0 +1,45 @@ +From ba0f8a83948c429f8b30510b6b071567dad0a38c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 28 Feb 2025 10:35:23 +0800 +Subject: drm/amd/display: Correct timing_adjust_pending flag setting. + +From: Zhongwei Zhang + +[ Upstream commit 34935701b7ed1a1ef449310ba041f10964b23cf4 ] + +[Why&How] +stream->adjust will be overwritten by update->crtc_timing_adjust. +We should set update->crtc_timing_adjust->timing_adjust_pending +and then overwrite stream->adjust. +Reset update->crtc_timing_adjust->timing_adjust_pending after +the assignment. + +Reviewed-by: Charlene Liu +Signed-off-by: Zhongwei Zhang +Signed-off-by: Tom Chung +Tested-by: Daniel Wheeler +Signed-off-by: Alex Deucher +Stable-dep-of: 874697e12793 ("drm/amd/display: Defer BW-optimization-blocked DRR adjustments") +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/display/dc/core/dc.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c +index a444fe1e0838a..e70b097cf478d 100644 +--- a/drivers/gpu/drm/amd/display/dc/core/dc.c ++++ b/drivers/gpu/drm/amd/display/dc/core/dc.c +@@ -3131,8 +3131,9 @@ static void copy_stream_update_to_stream(struct dc *dc, + if (update->crtc_timing_adjust) { + if (stream->adjust.v_total_min != update->crtc_timing_adjust->v_total_min || + stream->adjust.v_total_max != update->crtc_timing_adjust->v_total_max) +- stream->adjust.timing_adjust_pending = true; ++ update->crtc_timing_adjust->timing_adjust_pending = true; + stream->adjust = *update->crtc_timing_adjust; ++ update->crtc_timing_adjust->timing_adjust_pending = false; + } + + if (update->dpms_off) +-- +2.39.5 + diff --git a/queue-6.14/drm-amd-display-defer-bw-optimization-blocked-drr-ad.patch b/queue-6.14/drm-amd-display-defer-bw-optimization-blocked-drr-ad.patch new file mode 100644 index 0000000000..5385c13314 --- /dev/null +++ b/queue-6.14/drm-amd-display-defer-bw-optimization-blocked-drr-ad.patch @@ -0,0 +1,75 @@ +From d1ac63be1590dc6c45ec39a6254285b32a04bd21 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 16 Apr 2025 02:54:26 -0400 +Subject: drm/amd/display: Defer BW-optimization-blocked DRR adjustments + +From: John Olender + +[ Upstream commit 874697e127931bf50a37ce9d96ee80f3a08a0c38 ] + +[Why & How] +Instead of dropping DRR updates, defer them. This fixes issues where +monitor continues to see incorrect refresh rate after VRR was turned off +by userspace. + +Fixes: 32953485c558 ("drm/amd/display: Do not update DRR while BW optimizations pending") +Link: https://gitlab.freedesktop.org/drm/amd/-/issues/3546 +Reviewed-by: Sun peng Li +Signed-off-by: John Olender +Signed-off-by: Aurabindo Pillai +Signed-off-by: Ray Wu +Tested-by: Daniel Wheeler +Signed-off-by: Alex Deucher +(cherry picked from commit 53761b7ecd83e6fbb9f2206f8c980a6aa308c844) +Cc: stable@vger.kernel.org +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 2 ++ + drivers/gpu/drm/amd/display/dc/core/dc.c | 10 +++++++--- + 2 files changed, 9 insertions(+), 3 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +index 4a8d76a4f3ce6..ee79a54de6d19 100644 +--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c ++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +@@ -367,6 +367,8 @@ get_crtc_by_otg_inst(struct amdgpu_device *adev, + static inline bool is_dc_timing_adjust_needed(struct dm_crtc_state *old_state, + struct dm_crtc_state *new_state) + { ++ if (new_state->stream->adjust.timing_adjust_pending) ++ return true; + if (new_state->freesync_config.state == VRR_STATE_ACTIVE_FIXED) + return true; + else if (amdgpu_dm_crtc_vrr_active(old_state) != amdgpu_dm_crtc_vrr_active(new_state)) +diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c +index e70b097cf478d..722175e347fdc 100644 +--- a/drivers/gpu/drm/amd/display/dc/core/dc.c ++++ b/drivers/gpu/drm/amd/display/dc/core/dc.c +@@ -438,9 +438,12 @@ bool dc_stream_adjust_vmin_vmax(struct dc *dc, + * Don't adjust DRR while there's bandwidth optimizations pending to + * avoid conflicting with firmware updates. + */ +- if (dc->ctx->dce_version > DCE_VERSION_MAX) +- if (dc->optimized_required || dc->wm_optimized_required) ++ if (dc->ctx->dce_version > DCE_VERSION_MAX) { ++ if (dc->optimized_required || dc->wm_optimized_required) { ++ stream->adjust.timing_adjust_pending = true; + return false; ++ } ++ } + + dc_exit_ips_for_hw_access(dc); + +@@ -3130,7 +3133,8 @@ static void copy_stream_update_to_stream(struct dc *dc, + + if (update->crtc_timing_adjust) { + if (stream->adjust.v_total_min != update->crtc_timing_adjust->v_total_min || +- stream->adjust.v_total_max != update->crtc_timing_adjust->v_total_max) ++ stream->adjust.v_total_max != update->crtc_timing_adjust->v_total_max || ++ stream->adjust.timing_adjust_pending) + update->crtc_timing_adjust->timing_adjust_pending = true; + stream->adjust = *update->crtc_timing_adjust; + update->crtc_timing_adjust->timing_adjust_pending = false; +-- +2.39.5 + diff --git a/queue-6.14/drm-amd-display-dm-drop-hw_support-check-in-amdgpu_d.patch b/queue-6.14/drm-amd-display-dm-drop-hw_support-check-in-amdgpu_d.patch new file mode 100644 index 0000000000..7b21c0f618 --- /dev/null +++ b/queue-6.14/drm-amd-display-dm-drop-hw_support-check-in-amdgpu_d.patch @@ -0,0 +1,34 @@ +From b0779980722dac03c41a452591f2dc66ae9ca50b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 17 Dec 2024 09:25:18 -0500 +Subject: drm/amd/display/dm: drop hw_support check in amdgpu_dm_i2c_xfer() + +From: Alex Deucher + +[ Upstream commit 33da70bd1e115d7d73f45fb1c09f5ecc448f3f13 ] + +DC supports SW i2c as well. Drop the check. + +Reviewed-by: Harry Wentland +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +index 2cfc18401f3f2..7b1fd3b28e9b5 100644 +--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c ++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +@@ -8382,7 +8382,7 @@ static int amdgpu_dm_i2c_xfer(struct i2c_adapter *i2c_adap, + int i; + int result = -EIO; + +- if (!ddc_service->ddc_pin || !ddc_service->ddc_pin->hw_info.hw_supported) ++ if (!ddc_service->ddc_pin) + return result; + + cmd.payloads = kcalloc(num, sizeof(struct i2c_payload), GFP_KERNEL); +-- +2.39.5 + diff --git a/queue-6.14/drm-amd-display-do-not-enable-replay-when-vtotal-upd.patch b/queue-6.14/drm-amd-display-do-not-enable-replay-when-vtotal-upd.patch new file mode 100644 index 0000000000..b3af7615d4 --- /dev/null +++ b/queue-6.14/drm-amd-display-do-not-enable-replay-when-vtotal-upd.patch @@ -0,0 +1,268 @@ +From 18e2449381305bced8aa7e747c78d454ba7d2862 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 13 Feb 2025 16:18:34 +0800 +Subject: drm/amd/display: Do not enable replay when vtotal update is pending. + +From: Danny Wang + +[ Upstream commit bd00b29b5f236dce677089319176dee5872b5a7a ] + +[Why&How] +Vtotal is not applied to HW when handling vsync interrupt. +Make sure vtotal is aligned before enable replay. + +Reviewed-by: Anthony Koo +Reviewed-by: Robin Chen +Signed-off-by: Danny Wang +Signed-off-by: Zhongwei Zhang +Signed-off-by: Tom Chung +Tested-by: Daniel Wheeler +Signed-off-by: Alex Deucher +Stable-dep-of: 874697e12793 ("drm/amd/display: Defer BW-optimization-blocked DRR adjustments") +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/display/dc/core/dc.c | 9 +++++++-- + .../gpu/drm/amd/display/dc/core/dc_hw_sequencer.c | 15 +++++++++++++++ + drivers/gpu/drm/amd/display/dc/dc_hw_types.h | 1 + + .../drm/amd/display/dc/hwss/dce110/dce110_hwseq.c | 7 ++----- + .../drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c | 7 ++----- + .../drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c | 8 ++------ + .../drm/amd/display/dc/hwss/dcn31/dcn31_hwseq.c | 4 +--- + .../drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c | 3 +-- + .../drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c | 10 +++------- + .../gpu/drm/amd/display/dc/hwss/hw_sequencer.h | 6 ++++++ + 10 files changed, 40 insertions(+), 30 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c +index 4683c7ef4507f..a444fe1e0838a 100644 +--- a/drivers/gpu/drm/amd/display/dc/core/dc.c ++++ b/drivers/gpu/drm/amd/display/dc/core/dc.c +@@ -452,6 +452,7 @@ bool dc_stream_adjust_vmin_vmax(struct dc *dc, + + if (dc->caps.max_v_total != 0 && + (adjust->v_total_max > dc->caps.max_v_total || adjust->v_total_min > dc->caps.max_v_total)) { ++ stream->adjust.timing_adjust_pending = false; + if (adjust->allow_otg_v_count_halt) + return set_long_vtotal(dc, stream, adjust); + else +@@ -465,7 +466,7 @@ bool dc_stream_adjust_vmin_vmax(struct dc *dc, + dc->hwss.set_drr(&pipe, + 1, + *adjust); +- ++ stream->adjust.timing_adjust_pending = false; + return true; + } + } +@@ -3127,8 +3128,12 @@ static void copy_stream_update_to_stream(struct dc *dc, + if (update->vrr_active_fixed) + stream->vrr_active_fixed = *update->vrr_active_fixed; + +- if (update->crtc_timing_adjust) ++ if (update->crtc_timing_adjust) { ++ if (stream->adjust.v_total_min != update->crtc_timing_adjust->v_total_min || ++ stream->adjust.v_total_max != update->crtc_timing_adjust->v_total_max) ++ stream->adjust.timing_adjust_pending = true; + stream->adjust = *update->crtc_timing_adjust; ++ } + + if (update->dpms_off) + stream->dpms_off = *update->dpms_off; +diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c +index 6eb9bae3af912..a49604b7701f7 100644 +--- a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c ++++ b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c +@@ -609,6 +609,21 @@ void set_p_state_switch_method( + } + } + ++void set_drr_and_clear_adjust_pending( ++ struct pipe_ctx *pipe_ctx, ++ struct dc_stream_state *stream, ++ struct drr_params *params) ++{ ++ /* params can be null.*/ ++ if (pipe_ctx && pipe_ctx->stream_res.tg && ++ pipe_ctx->stream_res.tg->funcs->set_drr) ++ pipe_ctx->stream_res.tg->funcs->set_drr( ++ pipe_ctx->stream_res.tg, params); ++ ++ if (stream) ++ stream->adjust.timing_adjust_pending = false; ++} ++ + void get_fams2_visual_confirm_color( + struct dc *dc, + struct dc_state *context, +diff --git a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h +index 5ac55601a6da1..37e381fc7f02a 100644 +--- a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h ++++ b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h +@@ -1015,6 +1015,7 @@ struct dc_crtc_timing_adjust { + uint32_t v_total_mid; + uint32_t v_total_mid_frame_num; + uint32_t allow_otg_v_count_halt; ++ uint8_t timing_adjust_pending; + }; + + +diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c +index 81f4c386c2875..fc4fb4055ab00 100644 +--- a/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c ++++ b/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c +@@ -1654,9 +1654,7 @@ enum dc_status dce110_apply_single_controller_ctx_to_hw( + + params.vertical_total_min = stream->adjust.v_total_min; + params.vertical_total_max = stream->adjust.v_total_max; +- if (pipe_ctx->stream_res.tg->funcs->set_drr) +- pipe_ctx->stream_res.tg->funcs->set_drr( +- pipe_ctx->stream_res.tg, ¶ms); ++ set_drr_and_clear_adjust_pending(pipe_ctx, stream, ¶ms); + + // DRR should set trigger event to monitor surface update event + if (stream->adjust.v_total_min != 0 && stream->adjust.v_total_max != 0) +@@ -2104,8 +2102,7 @@ static void set_drr(struct pipe_ctx **pipe_ctx, + struct timing_generator *tg = pipe_ctx[i]->stream_res.tg; + + if ((tg != NULL) && tg->funcs) { +- if (tg->funcs->set_drr) +- tg->funcs->set_drr(tg, ¶ms); ++ set_drr_and_clear_adjust_pending(pipe_ctx[i], pipe_ctx[i]->stream, ¶ms); + if (adjust.v_total_max != 0 && adjust.v_total_min != 0) + if (tg->funcs->set_static_screen_control) + tg->funcs->set_static_screen_control( +diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c +index 13f9e9b439f6a..4c89bf6725b3b 100644 +--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c ++++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c +@@ -1112,9 +1112,7 @@ static void dcn10_reset_back_end_for_pipe( + pipe_ctx->stream_res.tg->funcs->disable_crtc(pipe_ctx->stream_res.tg); + + pipe_ctx->stream_res.tg->funcs->enable_optc_clock(pipe_ctx->stream_res.tg, false); +- if (pipe_ctx->stream_res.tg->funcs->set_drr) +- pipe_ctx->stream_res.tg->funcs->set_drr( +- pipe_ctx->stream_res.tg, NULL); ++ set_drr_and_clear_adjust_pending(pipe_ctx, pipe_ctx->stream, NULL); + if (dc_is_hdmi_tmds_signal(pipe_ctx->stream->signal)) + pipe_ctx->stream->link->phy_state.symclk_ref_cnts.otg = 0; + } +@@ -3217,8 +3215,7 @@ void dcn10_set_drr(struct pipe_ctx **pipe_ctx, + struct timing_generator *tg = pipe_ctx[i]->stream_res.tg; + + if ((tg != NULL) && tg->funcs) { +- if (tg->funcs->set_drr) +- tg->funcs->set_drr(tg, ¶ms); ++ set_drr_and_clear_adjust_pending(pipe_ctx[i], pipe_ctx[i]->stream, ¶ms); + if (adjust.v_total_max != 0 && adjust.v_total_min != 0) + if (tg->funcs->set_static_screen_control) + tg->funcs->set_static_screen_control( +diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c +index b78096a7690ee..f7e31aec32058 100644 +--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c ++++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c +@@ -952,9 +952,7 @@ enum dc_status dcn20_enable_stream_timing( + params.vertical_total_max = stream->adjust.v_total_max; + params.vertical_total_mid = stream->adjust.v_total_mid; + params.vertical_total_mid_frame_num = stream->adjust.v_total_mid_frame_num; +- if (pipe_ctx->stream_res.tg->funcs->set_drr) +- pipe_ctx->stream_res.tg->funcs->set_drr( +- pipe_ctx->stream_res.tg, ¶ms); ++ set_drr_and_clear_adjust_pending(pipe_ctx, stream, ¶ms); + + // DRR should set trigger event to monitor surface update event + if (stream->adjust.v_total_min != 0 && stream->adjust.v_total_max != 0) +@@ -2849,9 +2847,7 @@ void dcn20_reset_back_end_for_pipe( + pipe_ctx->stream_res.tg->funcs->set_odm_bypass( + pipe_ctx->stream_res.tg, &pipe_ctx->stream->timing); + +- if (pipe_ctx->stream_res.tg->funcs->set_drr) +- pipe_ctx->stream_res.tg->funcs->set_drr( +- pipe_ctx->stream_res.tg, NULL); ++ set_drr_and_clear_adjust_pending(pipe_ctx, pipe_ctx->stream, NULL); + /* TODO - convert symclk_ref_cnts for otg to a bit map to solve + * the case where the same symclk is shared across multiple otg + * instances +diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_hwseq.c +index 03ba01f4ace18..38f8898266971 100644 +--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_hwseq.c ++++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_hwseq.c +@@ -538,9 +538,7 @@ static void dcn31_reset_back_end_for_pipe( + if (dc_is_hdmi_tmds_signal(pipe_ctx->stream->signal)) + pipe_ctx->stream->link->phy_state.symclk_ref_cnts.otg = 0; + +- if (pipe_ctx->stream_res.tg->funcs->set_drr) +- pipe_ctx->stream_res.tg->funcs->set_drr( +- pipe_ctx->stream_res.tg, NULL); ++ set_drr_and_clear_adjust_pending(pipe_ctx, pipe_ctx->stream, NULL); + + /* DPMS may already disable or */ + /* dpms_off status is incorrect due to fastboot +diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c +index b907ad1acedd9..922b8d71cf1aa 100644 +--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c ++++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c +@@ -1473,8 +1473,7 @@ void dcn35_set_drr(struct pipe_ctx **pipe_ctx, + num_frames = 2 * (frame_rate % 60); + } + } +- if (tg->funcs->set_drr) +- tg->funcs->set_drr(tg, ¶ms); ++ set_drr_and_clear_adjust_pending(pipe_ctx[i], pipe_ctx[i]->stream, ¶ms); + if (adjust.v_total_max != 0 && adjust.v_total_min != 0) + if (tg->funcs->set_static_screen_control) + tg->funcs->set_static_screen_control( +diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c +index 0d39d193dacfa..284f011f5643d 100644 +--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c ++++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c +@@ -830,10 +830,7 @@ enum dc_status dcn401_enable_stream_timing( + } + + hws->funcs.wait_for_blank_complete(pipe_ctx->stream_res.opp); +- +- if (pipe_ctx->stream_res.tg->funcs->set_drr) +- pipe_ctx->stream_res.tg->funcs->set_drr( +- pipe_ctx->stream_res.tg, ¶ms); ++ set_drr_and_clear_adjust_pending(pipe_ctx, stream, ¶ms); + + /* Event triggers and num frames initialized for DRR, but can be + * later updated for PSR use. Note DRR trigger events are generated +@@ -1866,9 +1863,8 @@ void dcn401_reset_back_end_for_pipe( + pipe_ctx->stream_res.tg->funcs->set_odm_bypass( + pipe_ctx->stream_res.tg, &pipe_ctx->stream->timing); + +- if (pipe_ctx->stream_res.tg->funcs->set_drr) +- pipe_ctx->stream_res.tg->funcs->set_drr( +- pipe_ctx->stream_res.tg, NULL); ++ set_drr_and_clear_adjust_pending(pipe_ctx, pipe_ctx->stream, NULL); ++ + /* TODO - convert symclk_ref_cnts for otg to a bit map to solve + * the case where the same symclk is shared across multiple otg + * instances +diff --git a/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h +index a7d66cfd93c91..16ef5250a02e1 100644 +--- a/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h ++++ b/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h +@@ -46,6 +46,7 @@ struct dce_hwseq; + struct link_resource; + struct dc_dmub_cmd; + struct pg_block_update; ++struct drr_params; + + struct subvp_pipe_control_lock_fast_params { + struct dc *dc; +@@ -521,6 +522,11 @@ void set_p_state_switch_method( + struct dc_state *context, + struct pipe_ctx *pipe_ctx); + ++void set_drr_and_clear_adjust_pending( ++ struct pipe_ctx *pipe_ctx, ++ struct dc_stream_state *stream, ++ struct drr_params *params); ++ + void hwss_execute_sequence(struct dc *dc, + struct block_sequence block_sequence[], + int num_steps); +-- +2.39.5 + diff --git a/queue-6.14/drm-amd-display-don-t-treat-wb-connector-as-physical.patch b/queue-6.14/drm-amd-display-don-t-treat-wb-connector-as-physical.patch new file mode 100644 index 0000000000..279dc6b712 --- /dev/null +++ b/queue-6.14/drm-amd-display-don-t-treat-wb-connector-as-physical.patch @@ -0,0 +1,157 @@ +From 0fe2bcb1865c43204c544de9abbd48748202f703 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 31 Jan 2025 11:57:49 -0500 +Subject: drm/amd/display: Don't treat wb connector as physical in + create_validate_stream_for_sink + +From: Harry Wentland + +[ Upstream commit cbf4890c6f28fb1ad733e14613fbd33c2004bced ] + +Don't try to operate on a drm_wb_connector as an amdgpu_dm_connector. +While dereferencing aconnector->base will "work" it's wrong and +might lead to unknown bad things. Just... don't. + +Reviewed-by: Alex Hung +Signed-off-by: Harry Wentland +Signed-off-by: Roman Li +Tested-by: Daniel Wheeler +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 26 ++++++++++++------- + .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 2 +- + .../display/amdgpu_dm/amdgpu_dm_mst_types.c | 6 ++--- + 3 files changed, 20 insertions(+), 14 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +index 6c2d79d84feec..2cfc18401f3f2 100644 +--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c ++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +@@ -7493,12 +7493,12 @@ static enum dc_status dm_validate_stream_and_context(struct dc *dc, + } + + struct dc_stream_state * +-create_validate_stream_for_sink(struct amdgpu_dm_connector *aconnector, ++create_validate_stream_for_sink(struct drm_connector *connector, + const struct drm_display_mode *drm_mode, + const struct dm_connector_state *dm_state, + const struct dc_stream_state *old_stream) + { +- struct drm_connector *connector = &aconnector->base; ++ struct amdgpu_dm_connector *aconnector = NULL; + struct amdgpu_device *adev = drm_to_adev(connector->dev); + struct dc_stream_state *stream; + const struct drm_connector_state *drm_state = dm_state ? &dm_state->base : NULL; +@@ -7509,8 +7509,12 @@ create_validate_stream_for_sink(struct amdgpu_dm_connector *aconnector, + if (!dm_state) + return NULL; + +- if (aconnector->dc_link->connector_signal == SIGNAL_TYPE_HDMI_TYPE_A || +- aconnector->dc_link->dpcd_caps.dongle_type == DISPLAY_DONGLE_DP_HDMI_CONVERTER) ++ if (connector->connector_type != DRM_MODE_CONNECTOR_WRITEBACK) ++ aconnector = to_amdgpu_dm_connector(connector); ++ ++ if (aconnector && ++ (aconnector->dc_link->connector_signal == SIGNAL_TYPE_HDMI_TYPE_A || ++ aconnector->dc_link->dpcd_caps.dongle_type == DISPLAY_DONGLE_DP_HDMI_CONVERTER)) + bpc_limit = 8; + + do { +@@ -7522,10 +7526,11 @@ create_validate_stream_for_sink(struct amdgpu_dm_connector *aconnector, + break; + } + +- if (aconnector->base.connector_type == DRM_MODE_CONNECTOR_WRITEBACK) ++ dc_result = dc_validate_stream(adev->dm.dc, stream); ++ ++ if (!aconnector) /* writeback connector */ + return stream; + +- dc_result = dc_validate_stream(adev->dm.dc, stream); + if (dc_result == DC_OK && stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) + dc_result = dm_dp_mst_is_port_support_mode(aconnector, stream); + +@@ -7555,7 +7560,7 @@ create_validate_stream_for_sink(struct amdgpu_dm_connector *aconnector, + __func__, __LINE__); + + aconnector->force_yuv420_output = true; +- stream = create_validate_stream_for_sink(aconnector, drm_mode, ++ stream = create_validate_stream_for_sink(connector, drm_mode, + dm_state, old_stream); + aconnector->force_yuv420_output = false; + } +@@ -7570,6 +7575,9 @@ enum drm_mode_status amdgpu_dm_connector_mode_valid(struct drm_connector *connec + struct dc_sink *dc_sink; + /* TODO: Unhardcode stream count */ + struct dc_stream_state *stream; ++ /* we always have an amdgpu_dm_connector here since we got ++ * here via the amdgpu_dm_connector_helper_funcs ++ */ + struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector); + + if ((mode->flags & DRM_MODE_FLAG_INTERLACE) || +@@ -7594,7 +7602,7 @@ enum drm_mode_status amdgpu_dm_connector_mode_valid(struct drm_connector *connec + + drm_mode_set_crtcinfo(mode, 0); + +- stream = create_validate_stream_for_sink(aconnector, mode, ++ stream = create_validate_stream_for_sink(connector, mode, + to_dm_connector_state(connector->state), + NULL); + if (stream) { +@@ -10646,7 +10654,7 @@ static int dm_update_crtc_state(struct amdgpu_display_manager *dm, + if (!drm_atomic_crtc_needs_modeset(new_crtc_state)) + goto skip_modeset; + +- new_stream = create_validate_stream_for_sink(aconnector, ++ new_stream = create_validate_stream_for_sink(connector, + &new_crtc_state->mode, + dm_new_conn_state, + dm_old_crtc_state->stream); +diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +index d2703ca7dff31..195fec9048df7 100644 +--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h ++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +@@ -989,7 +989,7 @@ int amdgpu_dm_process_dmub_set_config_sync(struct dc_context *ctx, unsigned int + struct set_config_cmd_payload *payload, enum set_config_status *operation_result); + + struct dc_stream_state * +- create_validate_stream_for_sink(struct amdgpu_dm_connector *aconnector, ++ create_validate_stream_for_sink(struct drm_connector *connector, + const struct drm_display_mode *drm_mode, + const struct dm_connector_state *dm_state, + const struct dc_stream_state *old_stream); +diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +index 8497de360640a..c3759a1c32cec 100644 +--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c ++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +@@ -1651,7 +1651,6 @@ int pre_validate_dsc(struct drm_atomic_state *state, + + if (ind >= 0) { + struct drm_connector *connector; +- struct amdgpu_dm_connector *aconnector; + struct drm_connector_state *drm_new_conn_state; + struct dm_connector_state *dm_new_conn_state; + struct dm_crtc_state *dm_old_crtc_state; +@@ -1659,15 +1658,14 @@ int pre_validate_dsc(struct drm_atomic_state *state, + connector = + amdgpu_dm_find_first_crtc_matching_connector(state, + state->crtcs[ind].ptr); +- aconnector = to_amdgpu_dm_connector(connector); + drm_new_conn_state = + drm_atomic_get_new_connector_state(state, +- &aconnector->base); ++ connector); + dm_new_conn_state = to_dm_connector_state(drm_new_conn_state); + dm_old_crtc_state = to_dm_crtc_state(state->crtcs[ind].old_state); + + local_dc_state->streams[i] = +- create_validate_stream_for_sink(aconnector, ++ create_validate_stream_for_sink(connector, + &state->crtcs[ind].new_state->mode, + dm_new_conn_state, + dm_old_crtc_state->stream); +-- +2.39.5 + diff --git a/queue-6.14/drm-amd-display-don-t-try-aux-transactions-on-discon.patch b/queue-6.14/drm-amd-display-don-t-try-aux-transactions-on-discon.patch new file mode 100644 index 0000000000..fb0664ed27 --- /dev/null +++ b/queue-6.14/drm-amd-display-don-t-try-aux-transactions-on-discon.patch @@ -0,0 +1,57 @@ +From 815ab561e01ab2d2f041463ecd8368ff0bed1981 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 28 Jan 2025 13:14:54 -0500 +Subject: drm/amd/display: Don't try AUX transactions on disconnected link + +From: Ilya Bakoulin + +[ Upstream commit e8bffa52e0253cfd689813a620e64521256bc712 ] + +[Why] +Setting link DPMS off in response to HPD disconnect creates AUX +transactions on a link that is supposed to be disconnected. This can +cause issues in some cases when the sink re-asserts HPD and expects +source to re-enable the link. + +[How] +Avoid AUX transactions on disconnected link. + +Reviewed-by: Wenjing Liu +Signed-off-by: Ilya Bakoulin +Signed-off-by: Aurabindo Pillai +Tested-by: Daniel Wheeler +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + .../gpu/drm/amd/display/dc/link/protocols/link_dp_phy.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_phy.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_phy.c +index 2c73ac87cd665..c27ffec5d84fb 100644 +--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_phy.c ++++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_phy.c +@@ -75,7 +75,8 @@ void dp_disable_link_phy(struct dc_link *link, + struct dc *dc = link->ctx->dc; + + if (!link->wa_flags.dp_keep_receiver_powered && +- !link->skip_implict_edp_power_control) ++ !link->skip_implict_edp_power_control && ++ link->type != dc_connection_none) + dpcd_write_rx_power_ctrl(link, false); + + dc->hwss.disable_link_output(link, link_res, signal); +@@ -163,8 +164,9 @@ enum dc_status dp_set_fec_ready(struct dc_link *link, const struct link_resource + } else { + if (link->fec_state == dc_link_fec_ready) { + fec_config = 0; +- core_link_write_dpcd(link, DP_FEC_CONFIGURATION, +- &fec_config, sizeof(fec_config)); ++ if (link->type != dc_connection_none) ++ core_link_write_dpcd(link, DP_FEC_CONFIGURATION, ++ &fec_config, sizeof(fec_config)); + + link_enc->funcs->fec_set_ready(link_enc, false); + link->fec_state = dc_link_fec_not_ready; +-- +2.39.5 + diff --git a/queue-6.14/drm-amd-display-enable-urgent-latency-adjustment-on-.patch b/queue-6.14/drm-amd-display-enable-urgent-latency-adjustment-on-.patch new file mode 100644 index 0000000000..834e112384 --- /dev/null +++ b/queue-6.14/drm-amd-display-enable-urgent-latency-adjustment-on-.patch @@ -0,0 +1,53 @@ +From ca009a4dc1772871e4070f32b3ace70f8ea189ea Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 2 Apr 2025 15:04:08 -0400 +Subject: drm/amd/display: Enable urgent latency adjustment on DCN35 + +From: Nicholas Susanto + +[ Upstream commit 756c85e4d0ddc497b4ad5b1f41ad54e838e06188 ] + +[Why] + +Urgent latency adjustment was disabled on DCN35 due to issues with P0 +enablement on some platforms. Without urgent latency, underflows occur +when doing certain high timing configurations. After testing, we found +that reenabling urgent latency didn't reintroduce p0 support on multiple +platforms. + +[How] + +renable urgent latency on DCN35 and setting it to 3000 Mhz. + +This reverts commit 3412860cc4c0c484f53f91b371483e6e4440c3e5. + +Reviewed-by: Charlene Liu +Signed-off-by: Nicholas Susanto +Signed-off-by: Zaeem Mohamed +Tested-by: Mark Broadworth +Signed-off-by: Alex Deucher +(cherry picked from commit cd74ce1f0cddffb3f36d0995d0f61e89f0010738) +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/display/dc/dml/dcn35/dcn35_fpu.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn35/dcn35_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn35/dcn35_fpu.c +index 47d785204f29c..beed7adbbd43e 100644 +--- a/drivers/gpu/drm/amd/display/dc/dml/dcn35/dcn35_fpu.c ++++ b/drivers/gpu/drm/amd/display/dc/dml/dcn35/dcn35_fpu.c +@@ -195,9 +195,9 @@ struct _vcs_dpi_soc_bounding_box_st dcn3_5_soc = { + .dcn_downspread_percent = 0.5, + .gpuvm_min_page_size_bytes = 4096, + .hostvm_min_page_size_bytes = 4096, +- .do_urgent_latency_adjustment = 0, ++ .do_urgent_latency_adjustment = 1, + .urgent_latency_adjustment_fabric_clock_component_us = 0, +- .urgent_latency_adjustment_fabric_clock_reference_mhz = 0, ++ .urgent_latency_adjustment_fabric_clock_reference_mhz = 3000, + }; + + void dcn35_build_wm_range_table_fpu(struct clk_mgr *clk_mgr) +-- +2.39.5 + diff --git a/queue-6.14/drm-amd-display-ensure-dmcub-idle-before-reset-on-dc.patch b/queue-6.14/drm-amd-display-ensure-dmcub-idle-before-reset-on-dc.patch new file mode 100644 index 0000000000..59037b5729 --- /dev/null +++ b/queue-6.14/drm-amd-display-ensure-dmcub-idle-before-reset-on-dc.patch @@ -0,0 +1,106 @@ +From bd2b1ba18e79049e3370e8f33d645d092172f9ab Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 19 Feb 2025 09:56:53 -0500 +Subject: drm/amd/display: Ensure DMCUB idle before reset on DCN31/DCN35 + +From: Nicholas Kazlauskas + +[ Upstream commit c707ea82c79dbd1d295ec94cc6529a5248c77757 ] + +[Why] +If we soft reset before halt finishes and there are outstanding +memory transactions then the memory interface may produce unexpected +results, such as out of order transactions when the firmware next runs. + +These can manifest as random or unexpected load/store violations. + +[How] +Increase the timeout before soft reset to ensure the DMCUB has quiesced. +This is effectively 1s maximum based on experimentation. + +Use the enable bit check on DCN31 like we're doing on DCN35 and reorder +the reset writes to follow the HW programming guide. + +Ensure we're reading SCRATCH7 instead of SCRATCH8 for the HALT code. +No current versions of DMCUB firmware use the SCRATCH8 boot bit to +dynamically switch where the HALT code goes to maintain backwards +compatibility with PSP. + +Reviewed-by: Dillon Varone +Signed-off-by: Nicholas Kazlauskas +Signed-off-by: Wayne Lin +Tested-by: Daniel Wheeler +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + .../gpu/drm/amd/display/dmub/src/dmub_dcn31.c | 17 +++++++++++------ + .../gpu/drm/amd/display/dmub/src/dmub_dcn35.c | 4 ++-- + 2 files changed, 13 insertions(+), 8 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c +index d9f31b191c693..1a68b5782cac6 100644 +--- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c ++++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c +@@ -83,8 +83,8 @@ static inline void dmub_dcn31_translate_addr(const union dmub_addr *addr_in, + void dmub_dcn31_reset(struct dmub_srv *dmub) + { + union dmub_gpint_data_register cmd; +- const uint32_t timeout = 100; +- uint32_t in_reset, scratch, i, pwait_mode; ++ const uint32_t timeout = 100000; ++ uint32_t in_reset, is_enabled, scratch, i, pwait_mode; + + REG_GET(DMCUB_CNTL2, DMCUB_SOFT_RESET, &in_reset); + +@@ -108,7 +108,7 @@ void dmub_dcn31_reset(struct dmub_srv *dmub) + } + + for (i = 0; i < timeout; ++i) { +- scratch = dmub->hw_funcs.get_gpint_response(dmub); ++ scratch = REG_READ(DMCUB_SCRATCH7); + if (scratch == DMUB_GPINT__STOP_FW_RESPONSE) + break; + +@@ -125,9 +125,14 @@ void dmub_dcn31_reset(struct dmub_srv *dmub) + /* Force reset in case we timed out, DMCUB is likely hung. */ + } + +- REG_UPDATE(DMCUB_CNTL2, DMCUB_SOFT_RESET, 1); +- REG_UPDATE(DMCUB_CNTL, DMCUB_ENABLE, 0); +- REG_UPDATE(MMHUBBUB_SOFT_RESET, DMUIF_SOFT_RESET, 1); ++ REG_GET(DMCUB_CNTL, DMCUB_ENABLE, &is_enabled); ++ ++ if (is_enabled) { ++ REG_UPDATE(DMCUB_CNTL2, DMCUB_SOFT_RESET, 1); ++ REG_UPDATE(MMHUBBUB_SOFT_RESET, DMUIF_SOFT_RESET, 1); ++ REG_UPDATE(DMCUB_CNTL, DMCUB_ENABLE, 0); ++ } ++ + REG_WRITE(DMCUB_INBOX1_RPTR, 0); + REG_WRITE(DMCUB_INBOX1_WPTR, 0); + REG_WRITE(DMCUB_OUTBOX1_RPTR, 0); +diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn35.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn35.c +index e5e77bd3c31ea..01d013a12b947 100644 +--- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn35.c ++++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn35.c +@@ -88,7 +88,7 @@ static inline void dmub_dcn35_translate_addr(const union dmub_addr *addr_in, + void dmub_dcn35_reset(struct dmub_srv *dmub) + { + union dmub_gpint_data_register cmd; +- const uint32_t timeout = 100; ++ const uint32_t timeout = 100000; + uint32_t in_reset, is_enabled, scratch, i, pwait_mode; + + REG_GET(DMCUB_CNTL2, DMCUB_SOFT_RESET, &in_reset); +@@ -113,7 +113,7 @@ void dmub_dcn35_reset(struct dmub_srv *dmub) + } + + for (i = 0; i < timeout; ++i) { +- scratch = dmub->hw_funcs.get_gpint_response(dmub); ++ scratch = REG_READ(DMCUB_SCRATCH7); + if (scratch == DMUB_GPINT__STOP_FW_RESPONSE) + break; + +-- +2.39.5 + diff --git a/queue-6.14/drm-amd-display-exit-idle-optimizations-before-acces.patch b/queue-6.14/drm-amd-display-exit-idle-optimizations-before-acces.patch new file mode 100644 index 0000000000..bdb203b14e --- /dev/null +++ b/queue-6.14/drm-amd-display-exit-idle-optimizations-before-acces.patch @@ -0,0 +1,59 @@ +From 7aad5e91d1c74e86b276a66ec45ea297aea27e6c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 3 Feb 2025 15:43:32 -0500 +Subject: drm/amd/display: Exit idle optimizations before accessing PHY + +From: Ovidiu Bunea + +[ Upstream commit c488967488d7eff7b9c527d5469c424c15377502 ] + +[why & how] +By default, DCN HW is in idle optimized state which does not allow access +to PHY registers. If BIOS powers up the DCN, it is fine because they will +power up everything. Only exit idle optimized state when not taking control +from VBIOS. + +Fixes: be704e5ef4bd ("Revert "drm/amd/display: Exit idle optimizations before attempt to access PHY"") +Reviewed-by: Charlene Liu +Signed-off-by: Ovidiu Bunea +Signed-off-by: Roman Li +Tested-by: Daniel Wheeler +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c +index 2f5f3e749a1ab..94ceccfc04982 100644 +--- a/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c ++++ b/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c +@@ -1889,6 +1889,7 @@ void dce110_enable_accelerated_mode(struct dc *dc, struct dc_state *context) + bool can_apply_edp_fast_boot = false; + bool can_apply_seamless_boot = false; + bool keep_edp_vdd_on = false; ++ struct dc_bios *dcb = dc->ctx->dc_bios; + DC_LOGGER_INIT(); + + +@@ -1965,6 +1966,8 @@ void dce110_enable_accelerated_mode(struct dc *dc, struct dc_state *context) + hws->funcs.edp_backlight_control(edp_link_with_sink, false); + } + /*resume from S3, no vbios posting, no need to power down again*/ ++ if (dcb && dcb->funcs && !dcb->funcs->is_accelerated_mode(dcb)) ++ clk_mgr_exit_optimized_pwr_state(dc, dc->clk_mgr); + + power_down_all_hw_blocks(dc); + +@@ -1977,6 +1980,8 @@ void dce110_enable_accelerated_mode(struct dc *dc, struct dc_state *context) + disable_vga_and_power_gate_all_controllers(dc); + if (edp_link_with_sink && !keep_edp_vdd_on) + dc->hwss.edp_power_control(edp_link_with_sink, false); ++ if (dcb && dcb->funcs && !dcb->funcs->is_accelerated_mode(dcb)) ++ clk_mgr_optimize_pwr_state(dc, dc->clk_mgr); + } + bios_set_scratch_acc_mode_change(dc->ctx->dc_bios, 1); + } +-- +2.39.5 + diff --git a/queue-6.14/drm-amd-display-fix-bt2020-ycbcr-limited-full-range-.patch b/queue-6.14/drm-amd-display-fix-bt2020-ycbcr-limited-full-range-.patch new file mode 100644 index 0000000000..3995931531 --- /dev/null +++ b/queue-6.14/drm-amd-display-fix-bt2020-ycbcr-limited-full-range-.patch @@ -0,0 +1,282 @@ +From 9b9709ac0ccc04f1f151059996db88fd7f15cd5a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 29 Jan 2025 14:46:27 -0500 +Subject: drm/amd/display: Fix BT2020 YCbCr limited/full range input + +From: Ilya Bakoulin + +[ Upstream commit 07bc2dcbcf403d47d6f305ef7f0d3d489491c5fb ] + +[Why] +BT2020 YCbCr input is not handled properly when full range +quantization is used and limited range is not supported at all. + +[How] +- Add enums for BT2020 YCbCr limited/full range +- Add limited range CSC matrix + +Reviewed-by: Krunoslav Kovac +Signed-off-by: Ilya Bakoulin +Signed-off-by: Roman Li +Tested-by: Robert Mader +Tested-by: Daniel Wheeler +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 6 +++--- + drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c | 2 +- + drivers/gpu/drm/amd/display/dc/basics/dc_common.c | 3 ++- + drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c | 5 +++-- + drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 4 ++-- + drivers/gpu/drm/amd/display/dc/dc_hw_types.h | 4 +++- + drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c | 3 ++- + .../gpu/drm/amd/display/dc/dio/dcn10/dcn10_stream_encoder.c | 3 ++- + .../amd/display/dc/dio/dcn401/dcn401_dio_stream_encoder.c | 3 ++- + .../amd/display/dc/hpo/dcn31/dcn31_hpo_dp_stream_encoder.c | 3 ++- + drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h | 6 +++++- + .../gpu/drm/amd/display/modules/info_packet/info_packet.c | 4 ++-- + 12 files changed, 29 insertions(+), 17 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +index ee79a54de6d19..6c2d79d84feec 100644 +--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c ++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +@@ -5650,9 +5650,9 @@ fill_plane_color_attributes(const struct drm_plane_state *plane_state, + + case DRM_COLOR_YCBCR_BT2020: + if (full_range) +- *color_space = COLOR_SPACE_2020_YCBCR; ++ *color_space = COLOR_SPACE_2020_YCBCR_FULL; + else +- return -EINVAL; ++ *color_space = COLOR_SPACE_2020_YCBCR_LIMITED; + break; + + default: +@@ -6148,7 +6148,7 @@ get_output_color_space(const struct dc_crtc_timing *dc_crtc_timing, + if (dc_crtc_timing->pixel_encoding == PIXEL_ENCODING_RGB) + color_space = COLOR_SPACE_2020_RGB_FULLRANGE; + else +- color_space = COLOR_SPACE_2020_YCBCR; ++ color_space = COLOR_SPACE_2020_YCBCR_LIMITED; + break; + case DRM_MODE_COLORIMETRY_DEFAULT: // ITU601 + default: +diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c +index 049046c604626..c7d13e743e6c8 100644 +--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c ++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c +@@ -1169,7 +1169,7 @@ static int amdgpu_current_colorspace_show(struct seq_file *m, void *data) + case COLOR_SPACE_2020_RGB_FULLRANGE: + seq_puts(m, "BT2020_RGB"); + break; +- case COLOR_SPACE_2020_YCBCR: ++ case COLOR_SPACE_2020_YCBCR_LIMITED: + seq_puts(m, "BT2020_YCC"); + break; + default: +diff --git a/drivers/gpu/drm/amd/display/dc/basics/dc_common.c b/drivers/gpu/drm/amd/display/dc/basics/dc_common.c +index b2fc4f8e64825..a51c2701da247 100644 +--- a/drivers/gpu/drm/amd/display/dc/basics/dc_common.c ++++ b/drivers/gpu/drm/amd/display/dc/basics/dc_common.c +@@ -40,7 +40,8 @@ bool is_rgb_cspace(enum dc_color_space output_color_space) + case COLOR_SPACE_YCBCR709: + case COLOR_SPACE_YCBCR601_LIMITED: + case COLOR_SPACE_YCBCR709_LIMITED: +- case COLOR_SPACE_2020_YCBCR: ++ case COLOR_SPACE_2020_YCBCR_LIMITED: ++ case COLOR_SPACE_2020_YCBCR_FULL: + return false; + default: + /* Add a case to switch */ +diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c +index 1406ee4bff801..4f54e75a8f95b 100644 +--- a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c ++++ b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c +@@ -176,7 +176,7 @@ static bool is_ycbcr2020_type( + { + bool ret = false; + +- if (color_space == COLOR_SPACE_2020_YCBCR) ++ if (color_space == COLOR_SPACE_2020_YCBCR_LIMITED || color_space == COLOR_SPACE_2020_YCBCR_FULL) + ret = true; + return ret; + } +@@ -247,7 +247,8 @@ void color_space_to_black_color( + case COLOR_SPACE_YCBCR709_BLACK: + case COLOR_SPACE_YCBCR601_LIMITED: + case COLOR_SPACE_YCBCR709_LIMITED: +- case COLOR_SPACE_2020_YCBCR: ++ case COLOR_SPACE_2020_YCBCR_LIMITED: ++ case COLOR_SPACE_2020_YCBCR_FULL: + *black_color = black_color_format[BLACK_COLOR_FORMAT_YUV_CV]; + break; + +diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +index 298668e9729c7..3367030da3414 100644 +--- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c ++++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +@@ -4247,7 +4247,7 @@ static void set_avi_info_frame( + break; + case COLOR_SPACE_2020_RGB_FULLRANGE: + case COLOR_SPACE_2020_RGB_LIMITEDRANGE: +- case COLOR_SPACE_2020_YCBCR: ++ case COLOR_SPACE_2020_YCBCR_LIMITED: + hdmi_info.bits.EC0_EC2 = COLORIMETRYEX_BT2020RGBYCBCR; + hdmi_info.bits.C0_C1 = COLORIMETRY_EXTENDED; + break; +@@ -4261,7 +4261,7 @@ static void set_avi_info_frame( + break; + } + +- if (pixel_encoding && color_space == COLOR_SPACE_2020_YCBCR && ++ if (pixel_encoding && color_space == COLOR_SPACE_2020_YCBCR_LIMITED && + stream->out_transfer_func.tf == TRANSFER_FUNCTION_GAMMA22) { + hdmi_info.bits.EC0_EC2 = 0; + hdmi_info.bits.C0_C1 = COLORIMETRY_ITU709; +diff --git a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h +index 37e381fc7f02a..d562ddeca5126 100644 +--- a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h ++++ b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h +@@ -653,7 +653,8 @@ enum dc_color_space { + COLOR_SPACE_YCBCR709_LIMITED, + COLOR_SPACE_2020_RGB_FULLRANGE, + COLOR_SPACE_2020_RGB_LIMITEDRANGE, +- COLOR_SPACE_2020_YCBCR, ++ COLOR_SPACE_2020_YCBCR_LIMITED, ++ COLOR_SPACE_2020_YCBCR_FULL, + COLOR_SPACE_ADOBERGB, + COLOR_SPACE_DCIP3, + COLOR_SPACE_DISPLAYNATIVE, +@@ -661,6 +662,7 @@ enum dc_color_space { + COLOR_SPACE_APPCTRL, + COLOR_SPACE_CUSTOMPOINTS, + COLOR_SPACE_YCBCR709_BLACK, ++ COLOR_SPACE_2020_YCBCR = COLOR_SPACE_2020_YCBCR_LIMITED, + }; + + enum dc_dither_option { +diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c +index d199e4ed2e59e..1130d7619b263 100644 +--- a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c ++++ b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c +@@ -418,7 +418,7 @@ static void dce110_stream_encoder_dp_set_stream_attribute( + dynamic_range_rgb = 1; /*limited range*/ + break; + case COLOR_SPACE_2020_RGB_FULLRANGE: +- case COLOR_SPACE_2020_YCBCR: ++ case COLOR_SPACE_2020_YCBCR_LIMITED: + case COLOR_SPACE_XR_RGB: + case COLOR_SPACE_MSREF_SCRGB: + case COLOR_SPACE_ADOBERGB: +@@ -430,6 +430,7 @@ static void dce110_stream_encoder_dp_set_stream_attribute( + case COLOR_SPACE_APPCTRL: + case COLOR_SPACE_CUSTOMPOINTS: + case COLOR_SPACE_UNKNOWN: ++ default: + /* do nothing */ + break; + } +diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_stream_encoder.c +index d01a8b8f95954..22e66b375a7fe 100644 +--- a/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_stream_encoder.c ++++ b/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_stream_encoder.c +@@ -391,7 +391,7 @@ void enc1_stream_encoder_dp_set_stream_attribute( + break; + case COLOR_SPACE_2020_RGB_LIMITEDRANGE: + case COLOR_SPACE_2020_RGB_FULLRANGE: +- case COLOR_SPACE_2020_YCBCR: ++ case COLOR_SPACE_2020_YCBCR_LIMITED: + case COLOR_SPACE_XR_RGB: + case COLOR_SPACE_MSREF_SCRGB: + case COLOR_SPACE_ADOBERGB: +@@ -404,6 +404,7 @@ void enc1_stream_encoder_dp_set_stream_attribute( + case COLOR_SPACE_CUSTOMPOINTS: + case COLOR_SPACE_UNKNOWN: + case COLOR_SPACE_YCBCR709_BLACK: ++ default: + /* do nothing */ + break; + } +diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn401/dcn401_dio_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/dcn401/dcn401_dio_stream_encoder.c +index 098c2a01a8509..9e5072627ec7b 100644 +--- a/drivers/gpu/drm/amd/display/dc/dio/dcn401/dcn401_dio_stream_encoder.c ++++ b/drivers/gpu/drm/amd/display/dc/dio/dcn401/dcn401_dio_stream_encoder.c +@@ -632,7 +632,7 @@ void enc401_stream_encoder_dp_set_stream_attribute( + break; + case COLOR_SPACE_2020_RGB_LIMITEDRANGE: + case COLOR_SPACE_2020_RGB_FULLRANGE: +- case COLOR_SPACE_2020_YCBCR: ++ case COLOR_SPACE_2020_YCBCR_LIMITED: + case COLOR_SPACE_XR_RGB: + case COLOR_SPACE_MSREF_SCRGB: + case COLOR_SPACE_ADOBERGB: +@@ -645,6 +645,7 @@ void enc401_stream_encoder_dp_set_stream_attribute( + case COLOR_SPACE_CUSTOMPOINTS: + case COLOR_SPACE_UNKNOWN: + case COLOR_SPACE_YCBCR709_BLACK: ++ default: + /* do nothing */ + break; + } +diff --git a/drivers/gpu/drm/amd/display/dc/hpo/dcn31/dcn31_hpo_dp_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/hpo/dcn31/dcn31_hpo_dp_stream_encoder.c +index 678db949cfe3c..759b453385c46 100644 +--- a/drivers/gpu/drm/amd/display/dc/hpo/dcn31/dcn31_hpo_dp_stream_encoder.c ++++ b/drivers/gpu/drm/amd/display/dc/hpo/dcn31/dcn31_hpo_dp_stream_encoder.c +@@ -323,7 +323,7 @@ static void dcn31_hpo_dp_stream_enc_set_stream_attribute( + break; + case COLOR_SPACE_2020_RGB_LIMITEDRANGE: + case COLOR_SPACE_2020_RGB_FULLRANGE: +- case COLOR_SPACE_2020_YCBCR: ++ case COLOR_SPACE_2020_YCBCR_LIMITED: + case COLOR_SPACE_XR_RGB: + case COLOR_SPACE_MSREF_SCRGB: + case COLOR_SPACE_ADOBERGB: +@@ -336,6 +336,7 @@ static void dcn31_hpo_dp_stream_enc_set_stream_attribute( + case COLOR_SPACE_CUSTOMPOINTS: + case COLOR_SPACE_UNKNOWN: + case COLOR_SPACE_YCBCR709_BLACK: ++ default: + /* do nothing */ + break; + } +diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h +index 0150f2581ee4c..0c5675d1c5936 100644 +--- a/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h ++++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h +@@ -119,10 +119,14 @@ static const struct dpp_input_csc_matrix __maybe_unused dpp_input_csc_matrix[] = + { 0x39a6, 0x2568, 0, 0xe0d6, + 0xeedd, 0x2568, 0xf925, 0x9a8, + 0, 0x2568, 0x43ee, 0xdbb2 } }, +- { COLOR_SPACE_2020_YCBCR, ++ { COLOR_SPACE_2020_YCBCR_FULL, + { 0x2F30, 0x2000, 0, 0xE869, + 0xEDB7, 0x2000, 0xFABC, 0xBC6, + 0, 0x2000, 0x3C34, 0xE1E6 } }, ++ { COLOR_SPACE_2020_YCBCR_LIMITED, ++ { 0x35B9, 0x2543, 0, 0xE2B2, ++ 0xEB2F, 0x2543, 0xFA01, 0x0B1F, ++ 0, 0x2543, 0x4489, 0xDB42 } }, + { COLOR_SPACE_2020_RGB_LIMITEDRANGE, + { 0x35E0, 0x255F, 0, 0xE2B3, + 0xEB20, 0x255F, 0xF9FD, 0xB1E, +diff --git a/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c b/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c +index a344e2e49b0ea..b3d55cac35694 100644 +--- a/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c ++++ b/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c +@@ -383,10 +383,10 @@ void mod_build_vsc_infopacket(const struct dc_stream_state *stream, + colorimetryFormat = ColorimetryYCC_DP_ITU709; + else if (cs == COLOR_SPACE_ADOBERGB) + colorimetryFormat = ColorimetryYCC_DP_AdobeYCC; +- else if (cs == COLOR_SPACE_2020_YCBCR) ++ else if (cs == COLOR_SPACE_2020_YCBCR_LIMITED) + colorimetryFormat = ColorimetryYCC_DP_ITU2020YCbCr; + +- if (cs == COLOR_SPACE_2020_YCBCR && tf == TRANSFER_FUNC_GAMMA_22) ++ if (cs == COLOR_SPACE_2020_YCBCR_LIMITED && tf == TRANSFER_FUNC_GAMMA_22) + colorimetryFormat = ColorimetryYCC_DP_ITU709; + break; + +-- +2.39.5 + diff --git a/queue-6.14/drm-amd-display-fix-check-for-identity-ratio.patch b/queue-6.14/drm-amd-display-fix-check-for-identity-ratio.patch new file mode 100644 index 0000000000..c3886c1877 --- /dev/null +++ b/queue-6.14/drm-amd-display-fix-check-for-identity-ratio.patch @@ -0,0 +1,76 @@ +From 8d98296f312c30dc9e0bec43e6ebe8e7f85970b2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Jan 2025 11:01:47 -0500 +Subject: drm/amd/display: fix check for identity ratio + +From: Samson Tam + +[ Upstream commit 0d3004647631aedb713251525a99784661574767 ] + +[Why] +IDENTITY_RATIO check uses 2 bits for integer, which only allows + checking downscale ratios up to 3. But we support up to 6x + downscale + +[How] +Update IDENTITY_RATIO to check 3 bits for integer +Add ASSERT to catch if we downscale more than 6x + +Signed-off-by: Samson Tam +Reviewed-by: Jun Lei +Tested-by: Daniel Wheeler +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/display/dc/spl/dc_spl.c | 21 ++++++++++++++++++++- + 1 file changed, 20 insertions(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/spl/dc_spl.c b/drivers/gpu/drm/amd/display/dc/spl/dc_spl.c +index 38a9a0d680581..18b423bd302a7 100644 +--- a/drivers/gpu/drm/amd/display/dc/spl/dc_spl.c ++++ b/drivers/gpu/drm/amd/display/dc/spl/dc_spl.c +@@ -8,7 +8,7 @@ + #include "dc_spl_isharp_filters.h" + #include "spl_debug.h" + +-#define IDENTITY_RATIO(ratio) (spl_fixpt_u2d19(ratio) == (1 << 19)) ++#define IDENTITY_RATIO(ratio) (spl_fixpt_u3d19(ratio) == (1 << 19)) + #define MIN_VIEWPORT_SIZE 12 + + static bool spl_is_yuv420(enum spl_pixel_format format) +@@ -887,6 +887,8 @@ static bool spl_get_isharp_en(struct spl_in *spl_in, + static void spl_get_taps_non_adaptive_scaler( + struct spl_scratch *spl_scratch, const struct spl_taps *in_taps) + { ++ bool check_max_downscale = false; ++ + if (in_taps->h_taps == 0) { + if (spl_fixpt_ceil(spl_scratch->scl_data.ratios.horz) > 1) + spl_scratch->scl_data.taps.h_taps = spl_min(2 * spl_fixpt_ceil( +@@ -926,6 +928,23 @@ static void spl_get_taps_non_adaptive_scaler( + else + spl_scratch->scl_data.taps.h_taps_c = in_taps->h_taps_c; + ++ ++ /* ++ * Max downscale supported is 6.0x. Add ASSERT to catch if go beyond that ++ */ ++ check_max_downscale = spl_fixpt_le(spl_scratch->scl_data.ratios.horz, ++ spl_fixpt_from_fraction(6, 1)); ++ SPL_ASSERT(check_max_downscale); ++ check_max_downscale = spl_fixpt_le(spl_scratch->scl_data.ratios.vert, ++ spl_fixpt_from_fraction(6, 1)); ++ SPL_ASSERT(check_max_downscale); ++ check_max_downscale = spl_fixpt_le(spl_scratch->scl_data.ratios.horz_c, ++ spl_fixpt_from_fraction(6, 1)); ++ SPL_ASSERT(check_max_downscale); ++ check_max_downscale = spl_fixpt_le(spl_scratch->scl_data.ratios.vert_c, ++ spl_fixpt_from_fraction(6, 1)); ++ SPL_ASSERT(check_max_downscale); ++ + if (IDENTITY_RATIO(spl_scratch->scl_data.ratios.horz)) + spl_scratch->scl_data.taps.h_taps = 1; + if (IDENTITY_RATIO(spl_scratch->scl_data.ratios.vert)) +-- +2.39.5 + diff --git a/queue-6.14/drm-amd-display-fix-dcn4x-init-failed.patch b/queue-6.14/drm-amd-display-fix-dcn4x-init-failed.patch new file mode 100644 index 0000000000..906c493745 --- /dev/null +++ b/queue-6.14/drm-amd-display-fix-dcn4x-init-failed.patch @@ -0,0 +1,96 @@ +From c9bc317cb096e5afdded29dfb999b1a511ec4a29 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 13 Feb 2025 12:37:10 -0500 +Subject: drm/amd/display: fix dcn4x init failed + +From: Charlene Liu + +[ Upstream commit 23ef388a84c72b0614a6c10f866ffeac7e807719 ] + +[why] +failed due to cmdtable not created. +switch atombios cmdtable as default. + +Reviewed-by: Alvin Lee +Signed-off-by: Charlene Liu +Signed-off-by: Zaeem Mohamed +Tested-by: Daniel Wheeler +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/display/dc/bios/command_table2.c | 9 --------- + .../gpu/drm/amd/display/dc/bios/command_table_helper2.c | 3 +-- + 2 files changed, 1 insertion(+), 11 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table2.c b/drivers/gpu/drm/amd/display/dc/bios/command_table2.c +index 7d18f372ce7ab..6bc59b7ef007b 100644 +--- a/drivers/gpu/drm/amd/display/dc/bios/command_table2.c ++++ b/drivers/gpu/drm/amd/display/dc/bios/command_table2.c +@@ -101,7 +101,6 @@ static void init_dig_encoder_control(struct bios_parser *bp) + bp->cmd_tbl.dig_encoder_control = encoder_control_digx_v1_5; + break; + default: +- dm_output_to_console("Don't have dig_encoder_control for v%d\n", version); + bp->cmd_tbl.dig_encoder_control = encoder_control_fallback; + break; + } +@@ -238,7 +237,6 @@ static void init_transmitter_control(struct bios_parser *bp) + bp->cmd_tbl.transmitter_control = transmitter_control_v1_7; + break; + default: +- dm_output_to_console("Don't have transmitter_control for v%d\n", crev); + bp->cmd_tbl.transmitter_control = transmitter_control_fallback; + break; + } +@@ -408,8 +406,6 @@ static void init_set_pixel_clock(struct bios_parser *bp) + bp->cmd_tbl.set_pixel_clock = set_pixel_clock_v7; + break; + default: +- dm_output_to_console("Don't have set_pixel_clock for v%d\n", +- BIOS_CMD_TABLE_PARA_REVISION(setpixelclock)); + bp->cmd_tbl.set_pixel_clock = set_pixel_clock_fallback; + break; + } +@@ -554,7 +550,6 @@ static void init_set_crtc_timing(struct bios_parser *bp) + set_crtc_using_dtd_timing_v3; + break; + default: +- dm_output_to_console("Don't have set_crtc_timing for v%d\n", dtd_version); + bp->cmd_tbl.set_crtc_timing = NULL; + break; + } +@@ -671,8 +666,6 @@ static void init_enable_crtc(struct bios_parser *bp) + bp->cmd_tbl.enable_crtc = enable_crtc_v1; + break; + default: +- dm_output_to_console("Don't have enable_crtc for v%d\n", +- BIOS_CMD_TABLE_PARA_REVISION(enablecrtc)); + bp->cmd_tbl.enable_crtc = NULL; + break; + } +@@ -864,8 +857,6 @@ static void init_set_dce_clock(struct bios_parser *bp) + bp->cmd_tbl.set_dce_clock = set_dce_clock_v2_1; + break; + default: +- dm_output_to_console("Don't have set_dce_clock for v%d\n", +- BIOS_CMD_TABLE_PARA_REVISION(setdceclock)); + bp->cmd_tbl.set_dce_clock = NULL; + break; + } +diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c b/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c +index 73458e2951034..df8139bda142b 100644 +--- a/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c ++++ b/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c +@@ -87,8 +87,7 @@ bool dal_bios_parser_init_cmd_tbl_helper2( + return true; + + default: +- /* Unsupported DCE */ +- BREAK_TO_DEBUGGER(); ++ *h = dal_cmd_tbl_helper_dce112_get_table2(); + return false; + } + } +-- +2.39.5 + diff --git a/queue-6.14/drm-amd-display-fix-dmub-reset-sequence-for-dcn401.patch b/queue-6.14/drm-amd-display-fix-dmub-reset-sequence-for-dcn401.patch new file mode 100644 index 0000000000..8b02546f92 --- /dev/null +++ b/queue-6.14/drm-amd-display-fix-dmub-reset-sequence-for-dcn401.patch @@ -0,0 +1,155 @@ +From 63c76a7de44b53e943219bf8211eba3860f961d7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 13 Feb 2025 13:10:41 -0500 +Subject: drm/amd/display: Fix DMUB reset sequence for DCN401 + +From: Dillon Varone + +[ Upstream commit 0dfcc2bf269010a6e093793034c048049a40ee93 ] + +[WHY] +It should no longer use DMCUB_SOFT_RESET as it can result +in the memory request path becoming desynchronized. + +[HOW] +To ensure robustness in the reset sequence: +1) Extend timeout on the "halt" command sent via gpint, and check for +controller to enter "wait" as a stronger guarantee that there are no +requests to memory still in flight. +2) Remove usage of DMCUB_SOFT_RESET +3) Rely on PSP to reset the controller safely + +Reviewed-by: Nicholas Kazlauskas +Signed-off-by: Dillon Varone +Signed-off-by: Wayne Lin +Tested-by: Daniel Wheeler +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + .../drm/amd/display/dmub/src/dmub_dcn401.c | 47 ++++++++++++------- + .../drm/amd/display/dmub/src/dmub_dcn401.h | 3 +- + 2 files changed, 32 insertions(+), 18 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn401.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn401.c +index 39a8cb6d7523c..e1c4fe1c6e3ee 100644 +--- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn401.c ++++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn401.c +@@ -63,8 +63,10 @@ static inline void dmub_dcn401_translate_addr(const union dmub_addr *addr_in, + void dmub_dcn401_reset(struct dmub_srv *dmub) + { + union dmub_gpint_data_register cmd; +- const uint32_t timeout = 30; +- uint32_t in_reset, scratch, i; ++ const uint32_t timeout_us = 1 * 1000 * 1000; //1s ++ const uint32_t poll_delay_us = 1; //1us ++ uint32_t i = 0; ++ uint32_t in_reset, scratch, pwait_mode; + + REG_GET(DMCUB_CNTL2, DMCUB_SOFT_RESET, &in_reset); + +@@ -75,32 +77,35 @@ void dmub_dcn401_reset(struct dmub_srv *dmub) + + dmub->hw_funcs.set_gpint(dmub, cmd); + +- /** +- * Timeout covers both the ACK and the wait +- * for remaining work to finish. +- * +- * This is mostly bound by the PHY disable sequence. +- * Each register check will be greater than 1us, so +- * don't bother using udelay. +- */ +- +- for (i = 0; i < timeout; ++i) { ++ for (i = 0; i < timeout_us; i++) { + if (dmub->hw_funcs.is_gpint_acked(dmub, cmd)) + break; ++ ++ udelay(poll_delay_us); + } + +- for (i = 0; i < timeout; ++i) { ++ for (; i < timeout_us; i++) { + scratch = dmub->hw_funcs.get_gpint_response(dmub); + if (scratch == DMUB_GPINT__STOP_FW_RESPONSE) + break; ++ ++ udelay(poll_delay_us); + } + +- /* Force reset in case we timed out, DMCUB is likely hung. */ ++ for (; i < timeout_us; i++) { ++ REG_GET(DMCUB_CNTL, DMCUB_PWAIT_MODE_STATUS, &pwait_mode); ++ if (pwait_mode & (1 << 0)) ++ break; ++ ++ udelay(poll_delay_us); ++ } ++ } ++ ++ if (i >= timeout_us) { ++ /* timeout should never occur */ ++ BREAK_TO_DEBUGGER(); + } + +- REG_UPDATE(DMCUB_CNTL2, DMCUB_SOFT_RESET, 1); +- REG_UPDATE(DMCUB_CNTL, DMCUB_ENABLE, 0); +- REG_UPDATE(MMHUBBUB_SOFT_RESET, DMUIF_SOFT_RESET, 1); + REG_WRITE(DMCUB_INBOX1_RPTR, 0); + REG_WRITE(DMCUB_INBOX1_WPTR, 0); + REG_WRITE(DMCUB_OUTBOX1_RPTR, 0); +@@ -131,7 +136,10 @@ void dmub_dcn401_backdoor_load(struct dmub_srv *dmub, + + dmub_dcn401_get_fb_base_offset(dmub, &fb_base, &fb_offset); + ++ /* reset and disable DMCUB and MMHUBBUB DMUIF */ + REG_UPDATE(DMCUB_SEC_CNTL, DMCUB_SEC_RESET, 1); ++ REG_UPDATE(MMHUBBUB_SOFT_RESET, DMUIF_SOFT_RESET, 1); ++ REG_UPDATE(DMCUB_CNTL, DMCUB_ENABLE, 0); + + dmub_dcn401_translate_addr(&cw0->offset, fb_base, fb_offset, &offset); + +@@ -151,6 +159,7 @@ void dmub_dcn401_backdoor_load(struct dmub_srv *dmub, + DMCUB_REGION3_CW1_TOP_ADDRESS, cw1->region.top, + DMCUB_REGION3_CW1_ENABLE, 1); + ++ /* release DMCUB reset only to prevent premature execution */ + REG_UPDATE_2(DMCUB_SEC_CNTL, DMCUB_SEC_RESET, 0, DMCUB_MEM_UNIT_ID, + 0x20); + } +@@ -161,7 +170,10 @@ void dmub_dcn401_backdoor_load_zfb_mode(struct dmub_srv *dmub, + { + union dmub_addr offset; + ++ /* reset and disable DMCUB and MMHUBBUB DMUIF */ + REG_UPDATE(DMCUB_SEC_CNTL, DMCUB_SEC_RESET, 1); ++ REG_UPDATE(MMHUBBUB_SOFT_RESET, DMUIF_SOFT_RESET, 1); ++ REG_UPDATE(DMCUB_CNTL, DMCUB_ENABLE, 0); + + offset = cw0->offset; + +@@ -181,6 +193,7 @@ void dmub_dcn401_backdoor_load_zfb_mode(struct dmub_srv *dmub, + DMCUB_REGION3_CW1_TOP_ADDRESS, cw1->region.top, + DMCUB_REGION3_CW1_ENABLE, 1); + ++ /* release DMCUB reset only to prevent premature execution */ + REG_UPDATE_2(DMCUB_SEC_CNTL, DMCUB_SEC_RESET, 0, DMCUB_MEM_UNIT_ID, + 0x20); + } +diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn401.h b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn401.h +index 4c8843b796950..31f95b27e227d 100644 +--- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn401.h ++++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn401.h +@@ -169,7 +169,8 @@ struct dmub_srv; + DMUB_SF(HOST_INTERRUPT_CSR, HOST_REG_INBOX0_RSP_INT_EN) \ + DMUB_SF(HOST_INTERRUPT_CSR, HOST_REG_OUTBOX0_RDY_INT_ACK) \ + DMUB_SF(HOST_INTERRUPT_CSR, HOST_REG_OUTBOX0_RDY_INT_STAT) \ +- DMUB_SF(HOST_INTERRUPT_CSR, HOST_REG_OUTBOX0_RDY_INT_EN) ++ DMUB_SF(HOST_INTERRUPT_CSR, HOST_REG_OUTBOX0_RDY_INT_EN) \ ++ DMUB_SF(DMCUB_CNTL, DMCUB_PWAIT_MODE_STATUS) + + struct dmub_srv_dcn401_reg_offset { + #define DMUB_SR(reg) uint32_t reg; +-- +2.39.5 + diff --git a/queue-6.14/drm-amd-display-fix-incorrect-dpcd-configs-while-rep.patch b/queue-6.14/drm-amd-display-fix-incorrect-dpcd-configs-while-rep.patch new file mode 100644 index 0000000000..18d979f5fe --- /dev/null +++ b/queue-6.14/drm-amd-display-fix-incorrect-dpcd-configs-while-rep.patch @@ -0,0 +1,80 @@ +From 605e8311ec7e540d5c8c9fad981ef653a380520d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 11 Feb 2025 15:45:43 +0800 +Subject: drm/amd/display: Fix incorrect DPCD configs while Replay/PSR switch + +From: Leon Huang + +[ Upstream commit 0d9cabc8f591ea1cd97c071b853b75b155c13259 ] + +[Why] +When switching between PSR/Replay, +the DPCD config of previous mode is not cleared, +resulting in unexpected behavior in TCON. + +[How] +Initialize the DPCD in setup function + +Reviewed-by: Robin Chen +Signed-off-by: Leon Huang +Signed-off-by: Tom Chung +Tested-by: Daniel Wheeler +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + .../link/protocols/link_edp_panel_control.c | 25 ++++++++++++++++--- + 1 file changed, 22 insertions(+), 3 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c +index e0e3bb8653595..1e4adbc764ea6 100644 +--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c ++++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c +@@ -675,6 +675,18 @@ bool edp_setup_psr(struct dc_link *link, + if (!link) + return false; + ++ //Clear PSR cfg ++ memset(&psr_configuration, 0, sizeof(psr_configuration)); ++ dm_helpers_dp_write_dpcd( ++ link->ctx, ++ link, ++ DP_PSR_EN_CFG, ++ &psr_configuration.raw, ++ sizeof(psr_configuration.raw)); ++ ++ if (link->psr_settings.psr_version == DC_PSR_VERSION_UNSUPPORTED) ++ return false; ++ + dc = link->ctx->dc; + dmcu = dc->res_pool->dmcu; + psr = dc->res_pool->psr; +@@ -685,9 +697,6 @@ bool edp_setup_psr(struct dc_link *link, + if (!dc_get_edp_link_panel_inst(dc, link, &panel_inst)) + return false; + +- +- memset(&psr_configuration, 0, sizeof(psr_configuration)); +- + psr_configuration.bits.ENABLE = 1; + psr_configuration.bits.CRC_VERIFICATION = 1; + psr_configuration.bits.FRAME_CAPTURE_INDICATION = +@@ -950,6 +959,16 @@ bool edp_setup_replay(struct dc_link *link, const struct dc_stream_state *stream + if (!link) + return false; + ++ //Clear Replay config ++ dm_helpers_dp_write_dpcd(link->ctx, link, ++ DP_SINK_PR_ENABLE_AND_CONFIGURATION, ++ (uint8_t *)&(replay_config.raw), sizeof(uint8_t)); ++ ++ if (!(link->replay_settings.config.replay_supported)) ++ return false; ++ ++ link->replay_settings.config.replay_error_status.raw = 0; ++ + dc = link->ctx->dc; + + replay = dc->res_pool->replay; +-- +2.39.5 + diff --git a/queue-6.14/drm-amd-display-fix-mismatch-type-comparison-in-cust.patch b/queue-6.14/drm-amd-display-fix-mismatch-type-comparison-in-cust.patch new file mode 100644 index 0000000000..2948cc3fd0 --- /dev/null +++ b/queue-6.14/drm-amd-display-fix-mismatch-type-comparison-in-cust.patch @@ -0,0 +1,60 @@ +From df4c4b0062392e2cdecda879cc3f8508db631738 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 Jan 2025 14:16:04 -0500 +Subject: drm/amd/display: Fix mismatch type comparison in custom_float + +From: Samson Tam + +[ Upstream commit 86f06bcbb54e93f3c7b5e22ae37e72882b74c4b0 ] + +[Why & How] +Passing uint into uchar function param. Pass uint instead + +Signed-off-by: Samson Tam +Reviewed-by: Alvin Lee +Tested-by: Daniel Wheeler +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/display/dc/spl/spl_fixpt31_32.c | 2 +- + drivers/gpu/drm/amd/display/dc/spl/spl_fixpt31_32.h | 4 ++-- + 2 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/spl/spl_fixpt31_32.c b/drivers/gpu/drm/amd/display/dc/spl/spl_fixpt31_32.c +index 131f1e3949d33..52d97918a3bd2 100644 +--- a/drivers/gpu/drm/amd/display/dc/spl/spl_fixpt31_32.c ++++ b/drivers/gpu/drm/amd/display/dc/spl/spl_fixpt31_32.c +@@ -346,7 +346,7 @@ struct spl_fixed31_32 spl_fixpt_exp(struct spl_fixed31_32 arg) + if (m > 0) + return spl_fixpt_shl( + spl_fixed31_32_exp_from_taylor_series(r), +- (unsigned char)m); ++ (unsigned int)m); + else + return spl_fixpt_div_int( + spl_fixed31_32_exp_from_taylor_series(r), +diff --git a/drivers/gpu/drm/amd/display/dc/spl/spl_fixpt31_32.h b/drivers/gpu/drm/amd/display/dc/spl/spl_fixpt31_32.h +index ed2647f9a0999..9f349ffe91485 100644 +--- a/drivers/gpu/drm/amd/display/dc/spl/spl_fixpt31_32.h ++++ b/drivers/gpu/drm/amd/display/dc/spl/spl_fixpt31_32.h +@@ -189,7 +189,7 @@ static inline struct spl_fixed31_32 spl_fixpt_clamp( + * @brief + * result = arg << shift + */ +-static inline struct spl_fixed31_32 spl_fixpt_shl(struct spl_fixed31_32 arg, unsigned char shift) ++static inline struct spl_fixed31_32 spl_fixpt_shl(struct spl_fixed31_32 arg, unsigned int shift) + { + SPL_ASSERT(((arg.value >= 0) && (arg.value <= LLONG_MAX >> shift)) || + ((arg.value < 0) && (arg.value >= ~(LLONG_MAX >> shift)))); +@@ -203,7 +203,7 @@ static inline struct spl_fixed31_32 spl_fixpt_shl(struct spl_fixed31_32 arg, uns + * @brief + * result = arg >> shift + */ +-static inline struct spl_fixed31_32 spl_fixpt_shr(struct spl_fixed31_32 arg, unsigned char shift) ++static inline struct spl_fixed31_32 spl_fixpt_shr(struct spl_fixed31_32 arg, unsigned int shift) + { + bool negative = arg.value < 0; + +-- +2.39.5 + diff --git a/queue-6.14/drm-amd-display-fix-mismatch-type-comparison.patch b/queue-6.14/drm-amd-display-fix-mismatch-type-comparison.patch new file mode 100644 index 0000000000..af878c1936 --- /dev/null +++ b/queue-6.14/drm-amd-display-fix-mismatch-type-comparison.patch @@ -0,0 +1,54 @@ +From 9bdd51639095e2af0bcfa1811a66b8fd15506ccc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 19 Dec 2024 17:19:09 -0500 +Subject: drm/amd/display: Fix mismatch type comparison + +From: Assadian, Navid + +[ Upstream commit 26873260d394b1e33cdd720154aedf0af95327f9 ] + +The mismatch type comparison/assignment may cause data loss. Since the +values are always non-negative, it is safe to use unsigned variables to +resolve the mismatch. + +Signed-off-by: Navid Assadian +Reviewed-by: Joshua Aberback +Tested-by: Daniel Wheeler +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/display/dc/spl/dc_spl.c | 4 ++-- + drivers/gpu/drm/amd/display/dc/spl/dc_spl_types.h | 2 +- + 2 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/spl/dc_spl.c b/drivers/gpu/drm/amd/display/dc/spl/dc_spl.c +index 18b423bd302a7..22602f088553d 100644 +--- a/drivers/gpu/drm/amd/display/dc/spl/dc_spl.c ++++ b/drivers/gpu/drm/amd/display/dc/spl/dc_spl.c +@@ -963,8 +963,8 @@ static bool spl_get_optimal_number_of_taps( + bool *enable_isharp) + { + int num_part_y, num_part_c; +- int max_taps_y, max_taps_c; +- int min_taps_y, min_taps_c; ++ unsigned int max_taps_y, max_taps_c; ++ unsigned int min_taps_y, min_taps_c; + enum lb_memory_config lb_config; + bool skip_easf = false; + bool is_subsampled = spl_is_subsampled_format(spl_in->basic_in.format); +diff --git a/drivers/gpu/drm/amd/display/dc/spl/dc_spl_types.h b/drivers/gpu/drm/amd/display/dc/spl/dc_spl_types.h +index 467af9dd90ded..5d139cf51e89b 100644 +--- a/drivers/gpu/drm/amd/display/dc/spl/dc_spl_types.h ++++ b/drivers/gpu/drm/amd/display/dc/spl/dc_spl_types.h +@@ -484,7 +484,7 @@ struct spl_sharpness_range { + }; + struct adaptive_sharpness { + bool enable; +- int sharpness_level; ++ unsigned int sharpness_level; + struct spl_sharpness_range sharpness_range; + }; + enum linear_light_scaling { // convert it in translation logic +-- +2.39.5 + diff --git a/queue-6.14/drm-amd-display-fix-p-state-type-when-p-state-is-uns.patch b/queue-6.14/drm-amd-display-fix-p-state-type-when-p-state-is-uns.patch new file mode 100644 index 0000000000..bbb2ac3348 --- /dev/null +++ b/queue-6.14/drm-amd-display-fix-p-state-type-when-p-state-is-uns.patch @@ -0,0 +1,39 @@ +From ac9bdb3f7c2d0b7fd5c69c10324cf45cc804dc9e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 12 Feb 2025 17:06:42 -0500 +Subject: drm/amd/display: Fix p-state type when p-state is unsupported + +From: Dillon Varone + +[ Upstream commit a025f424af0407b7561bd5e6217295dde3abbc2e ] + +[WHY&HOW] +P-state type would remain on previously used when unsupported which +causes confusion in logging and visual confirm, so set back to zero +when unsupported. + +Reviewed-by: Aric Cyr +Signed-off-by: Dillon Varone +Signed-off-by: Wayne Lin +Tested-by: Daniel Wheeler +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c +index a49604b7701f7..1406ee4bff801 100644 +--- a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c ++++ b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c +@@ -563,6 +563,7 @@ void set_p_state_switch_method( + if (!dc->ctx || !dc->ctx->dmub_srv || !pipe_ctx || !vba) + return; + ++ pipe_ctx->p_state_type = P_STATE_UNKNOWN; + if (vba->DRAMClockChangeSupport[vba->VoltageLevel][vba->maxMpcComb] != + dm_dram_clock_change_unsupported) { + /* MCLK switching is supported */ +-- +2.39.5 + diff --git a/queue-6.14/drm-amd-display-fixes-for-mcache-programming-in-dml2.patch b/queue-6.14/drm-amd-display-fixes-for-mcache-programming-in-dml2.patch new file mode 100644 index 0000000000..1dbfdf2408 --- /dev/null +++ b/queue-6.14/drm-amd-display-fixes-for-mcache-programming-in-dml2.patch @@ -0,0 +1,244 @@ +From 92d641083e1414a30ea30770960a950a35d13613 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 17 Jan 2025 17:49:41 -0500 +Subject: drm/amd/display: Fixes for mcache programming in DML21 + +From: Dillon Varone + +[ Upstream commit c909a49128a31bced8cfbd2dfb0a4fe56e01a6d0 ] + +[WHY & HOW] +- Fix indexing phantom planes for mcache programming in the wrapper +- Fix phantom mcache allocations to align with HW guidance +- Fix mcache assignment for chroma plane for multi-planar formats + +Reviewed-by: Austin Zheng +Signed-off-by: Dillon Varone +Signed-off-by: Alex Hung +Tested-by: Daniel Wheeler +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + .../amd/display/dc/dml2/dml21/dml21_utils.c | 1 - + .../amd/display/dc/dml2/dml21/dml21_wrapper.c | 14 +++++++++ + .../display/dc/dml2/dml21/inc/dml_top_types.h | 1 + + .../dml2/dml21/src/dml2_core/dml2_core_dcn4.c | 30 ++++++++++++++++++- + .../src/dml2_core/dml2_core_dcn4_calcs.c | 3 ++ + .../dml21/src/dml2_pmo/dml2_pmo_dcn4_fams2.c | 21 +++++++++++++ + .../dml2/dml21/src/dml2_top/dml2_top_soc15.c | 8 ----- + 7 files changed, 68 insertions(+), 10 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_utils.c b/drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_utils.c +index 1e56d995cd0e7..930e86cdb88a2 100644 +--- a/drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_utils.c ++++ b/drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_utils.c +@@ -232,7 +232,6 @@ void dml21_program_dc_pipe(struct dml2_context *dml_ctx, struct dc_state *contex + context->bw_ctx.bw.dcn.clk.dppclk_khz = pipe_ctx->plane_res.bw.dppclk_khz; + + dml21_populate_mall_allocation_size(context, dml_ctx, pln_prog, pipe_ctx); +- memcpy(&context->bw_ctx.bw.dcn.mcache_allocations[pipe_ctx->pipe_idx], &pln_prog->mcache_allocation, sizeof(struct dml2_mcache_surface_allocation)); + + bool sub_vp_enabled = is_sub_vp_enabled(pipe_ctx->stream->ctx->dc, context); + +diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_wrapper.c b/drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_wrapper.c +index d6fd13f43c08f..5d16f36ec95c8 100644 +--- a/drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_wrapper.c ++++ b/drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_wrapper.c +@@ -129,6 +129,7 @@ static void dml21_calculate_rq_and_dlg_params(const struct dc *dc, struct dc_sta + struct pipe_ctx *dc_main_pipes[__DML2_WRAPPER_MAX_STREAMS_PLANES__]; + struct pipe_ctx *dc_phantom_pipes[__DML2_WRAPPER_MAX_STREAMS_PLANES__] = {0}; + int num_pipes; ++ unsigned int dml_phantom_prog_idx; + + context->bw_ctx.bw.dcn.clk.dppclk_khz = 0; + +@@ -142,6 +143,9 @@ static void dml21_calculate_rq_and_dlg_params(const struct dc *dc, struct dc_sta + context->bw_ctx.bw.dcn.mall_ss_psr_active_size_bytes = 0; + context->bw_ctx.bw.dcn.mall_subvp_size_bytes = 0; + ++ /* phantom's start after main planes */ ++ dml_phantom_prog_idx = in_ctx->v21.mode_programming.programming->display_config.num_planes; ++ + for (dml_prog_idx = 0; dml_prog_idx < DML2_MAX_PLANES; dml_prog_idx++) { + pln_prog = &in_ctx->v21.mode_programming.programming->plane_programming[dml_prog_idx]; + +@@ -167,6 +171,16 @@ static void dml21_calculate_rq_and_dlg_params(const struct dc *dc, struct dc_sta + dml21_program_dc_pipe(in_ctx, context, dc_phantom_pipes[dc_pipe_index], pln_prog, stream_prog); + } + } ++ ++ /* copy per plane mcache allocation */ ++ memcpy(&context->bw_ctx.bw.dcn.mcache_allocations[dml_prog_idx], &pln_prog->mcache_allocation, sizeof(struct dml2_mcache_surface_allocation)); ++ if (pln_prog->phantom_plane.valid) { ++ memcpy(&context->bw_ctx.bw.dcn.mcache_allocations[dml_phantom_prog_idx], ++ &pln_prog->phantom_plane.mcache_allocation, ++ sizeof(struct dml2_mcache_surface_allocation)); ++ ++ dml_phantom_prog_idx++; ++ } + } + + /* assign global clocks */ +diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml21/inc/dml_top_types.h b/drivers/gpu/drm/amd/display/dc/dml2/dml21/inc/dml_top_types.h +index d2d053f2354d0..0ab19cf4d2421 100644 +--- a/drivers/gpu/drm/amd/display/dc/dml2/dml21/inc/dml_top_types.h ++++ b/drivers/gpu/drm/amd/display/dc/dml2/dml21/inc/dml_top_types.h +@@ -245,6 +245,7 @@ struct dml2_per_plane_programming { + struct { + bool valid; + struct dml2_plane_parameters descriptor; ++ struct dml2_mcache_surface_allocation mcache_allocation; + struct dml2_dchub_per_pipe_register_set *pipe_regs[DML2_MAX_PLANES]; + } phantom_plane; + }; +diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_dcn4.c b/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_dcn4.c +index 7216d25c783e6..44d2969a904ea 100644 +--- a/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_dcn4.c ++++ b/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_dcn4.c +@@ -253,7 +253,8 @@ static void expand_implict_subvp(const struct display_configuation_with_meta *di + static void pack_mode_programming_params_with_implicit_subvp(struct dml2_core_instance *core, const struct display_configuation_with_meta *display_cfg, + const struct dml2_display_cfg *svp_expanded_display_cfg, struct dml2_display_cfg_programming *programming, struct dml2_core_scratch *scratch) + { +- unsigned int stream_index, plane_index, pipe_offset, stream_already_populated_mask, main_plane_index; ++ unsigned int stream_index, plane_index, pipe_offset, stream_already_populated_mask, main_plane_index, mcache_index; ++ unsigned int total_main_mcaches_required = 0; + int total_pipe_regs_copied = 0; + int dml_internal_pipe_index = 0; + const struct dml2_plane_parameters *main_plane; +@@ -324,6 +325,13 @@ static void pack_mode_programming_params_with_implicit_subvp(struct dml2_core_in + + dml2_core_calcs_get_mall_allocation(&core->clean_me_up.mode_lib, &programming->plane_programming[plane_index].surface_size_mall_bytes, dml_internal_pipe_index); + ++ memcpy(&programming->plane_programming[plane_index].mcache_allocation, ++ &display_cfg->stage2.mcache_allocations[plane_index], ++ sizeof(struct dml2_mcache_surface_allocation)); ++ total_main_mcaches_required += programming->plane_programming[plane_index].mcache_allocation.num_mcaches_plane0 + ++ programming->plane_programming[plane_index].mcache_allocation.num_mcaches_plane1 - ++ (programming->plane_programming[plane_index].mcache_allocation.last_slice_sharing.plane0_plane1 ? 1 : 0); ++ + for (pipe_offset = 0; pipe_offset < programming->plane_programming[plane_index].num_dpps_required; pipe_offset++) { + // Assign storage for this pipe's register values + programming->plane_programming[plane_index].pipe_regs[pipe_offset] = &programming->pipe_regs[total_pipe_regs_copied]; +@@ -362,6 +370,22 @@ static void pack_mode_programming_params_with_implicit_subvp(struct dml2_core_in + memcpy(&programming->plane_programming[main_plane_index].phantom_plane.descriptor, phantom_plane, sizeof(struct dml2_plane_parameters)); + + dml2_core_calcs_get_mall_allocation(&core->clean_me_up.mode_lib, &programming->plane_programming[main_plane_index].svp_size_mall_bytes, dml_internal_pipe_index); ++ ++ /* generate mcache allocation, phantoms use identical mcache configuration, but in the MALL set and unique mcache ID's beginning after all main ID's */ ++ memcpy(&programming->plane_programming[main_plane_index].phantom_plane.mcache_allocation, ++ &programming->plane_programming[main_plane_index].mcache_allocation, ++ sizeof(struct dml2_mcache_surface_allocation)); ++ for (mcache_index = 0; mcache_index < programming->plane_programming[main_plane_index].phantom_plane.mcache_allocation.num_mcaches_plane0; mcache_index++) { ++ programming->plane_programming[main_plane_index].phantom_plane.mcache_allocation.global_mcache_ids_plane0[mcache_index] += total_main_mcaches_required; ++ programming->plane_programming[main_plane_index].phantom_plane.mcache_allocation.global_mcache_ids_mall_plane0[mcache_index] = ++ programming->plane_programming[main_plane_index].phantom_plane.mcache_allocation.global_mcache_ids_plane0[mcache_index]; ++ } ++ for (mcache_index = 0; mcache_index < programming->plane_programming[main_plane_index].phantom_plane.mcache_allocation.num_mcaches_plane1; mcache_index++) { ++ programming->plane_programming[main_plane_index].phantom_plane.mcache_allocation.global_mcache_ids_plane1[mcache_index] += total_main_mcaches_required; ++ programming->plane_programming[main_plane_index].phantom_plane.mcache_allocation.global_mcache_ids_mall_plane1[mcache_index] = ++ programming->plane_programming[main_plane_index].phantom_plane.mcache_allocation.global_mcache_ids_plane1[mcache_index]; ++ } ++ + for (pipe_offset = 0; pipe_offset < programming->plane_programming[main_plane_index].num_dpps_required; pipe_offset++) { + // Assign storage for this pipe's register values + programming->plane_programming[main_plane_index].phantom_plane.pipe_regs[pipe_offset] = &programming->pipe_regs[total_pipe_regs_copied]; +@@ -571,6 +595,10 @@ bool core_dcn4_mode_programming(struct dml2_core_mode_programming_in_out *in_out + + dml2_core_calcs_get_mall_allocation(&core->clean_me_up.mode_lib, &in_out->programming->plane_programming[plane_index].surface_size_mall_bytes, dml_internal_pipe_index); + ++ memcpy(&in_out->programming->plane_programming[plane_index].mcache_allocation, ++ &in_out->display_cfg->stage2.mcache_allocations[plane_index], ++ sizeof(struct dml2_mcache_surface_allocation)); ++ + for (pipe_offset = 0; pipe_offset < in_out->programming->plane_programming[plane_index].num_dpps_required; pipe_offset++) { + in_out->programming->plane_programming[plane_index].plane_descriptor = &in_out->programming->display_config.plane_descriptors[plane_index]; + +diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_dcn4_calcs.c b/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_dcn4_calcs.c +index c1ff869512f27..8ad7704b76691 100644 +--- a/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_dcn4_calcs.c ++++ b/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_dcn4_calcs.c +@@ -2638,6 +2638,9 @@ static void calculate_mcache_setting( + // Luma/Chroma combine in the last mcache + // In the case of Luma/Chroma combine-mCache (with lc_comb_mcache==1), all mCaches except the last segment are filled as much as possible, when stay aligned to mvmpg boundary + if (*p->lc_comb_mcache && l->is_dual_plane) { ++ /* if luma and chroma planes share an mcache, increase total chroma mcache count */ ++ *p->num_mcaches_c = *p->num_mcaches_c + 1; ++ + for (n = 0; n < *p->num_mcaches_l - 1; n++) + p->mcache_offsets_l[n] = (n + 1) * l->mvmpg_per_mcache_lb_l * l->mvmpg_access_width_l; + p->mcache_offsets_l[*p->num_mcaches_l - 1] = l->full_vp_access_width_l; +diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_pmo/dml2_pmo_dcn4_fams2.c b/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_pmo/dml2_pmo_dcn4_fams2.c +index a3324f7b9ba68..15c906c42ec45 100644 +--- a/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_pmo/dml2_pmo_dcn4_fams2.c ++++ b/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_pmo/dml2_pmo_dcn4_fams2.c +@@ -1082,12 +1082,21 @@ static bool all_timings_support_svp(const struct dml2_pmo_instance *pmo, + const struct dml2_fams2_meta *stream_fams2_meta; + unsigned int microschedule_vlines; + unsigned int i; ++ unsigned int mcaches_per_plane; ++ unsigned int total_mcaches_required = 0; + + unsigned int num_planes_per_stream[DML2_MAX_PLANES] = { 0 }; + + /* confirm timing it is not a centered timing */ + for (i = 0; i < display_config->display_config.num_planes; i++) { + plane_descriptor = &display_config->display_config.plane_descriptors[i]; ++ mcaches_per_plane = 0; ++ ++ if (plane_descriptor->surface.dcc.enable) { ++ mcaches_per_plane += display_config->stage2.mcache_allocations[i].num_mcaches_plane0 + ++ display_config->stage2.mcache_allocations[i].num_mcaches_plane1 - ++ (display_config->stage2.mcache_allocations[i].last_slice_sharing.plane0_plane1 ? 1 : 0); ++ } + + if (is_bit_set_in_bitfield(mask, (unsigned char)plane_descriptor->stream_index)) { + num_planes_per_stream[plane_descriptor->stream_index]++; +@@ -1098,7 +1107,19 @@ static bool all_timings_support_svp(const struct dml2_pmo_instance *pmo, + plane_descriptor->composition.rotation_angle != dml2_rotation_0) { + return false; + } ++ ++ /* phantom requires same number of mcaches as main */ ++ if (plane_descriptor->surface.dcc.enable) { ++ mcaches_per_plane *= 2; ++ } + } ++ ++ total_mcaches_required += mcaches_per_plane; ++ } ++ ++ if (total_mcaches_required > pmo->soc_bb->num_dcc_mcaches) { ++ /* too many mcaches required */ ++ return false; + } + + for (i = 0; i < DML2_MAX_PLANES; i++) { +diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_top/dml2_top_soc15.c b/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_top/dml2_top_soc15.c +index a8f58f8448e42..dc2ce5e77f579 100644 +--- a/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_top/dml2_top_soc15.c ++++ b/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_top/dml2_top_soc15.c +@@ -831,7 +831,6 @@ static bool dml2_top_soc15_build_mode_programming(struct dml2_build_mode_program + bool uclk_pstate_success = false; + bool vmin_success = false; + bool stutter_success = false; +- unsigned int i; + + memset(l, 0, sizeof(struct dml2_build_mode_programming_locals)); + memset(in_out->programming, 0, sizeof(struct dml2_display_cfg_programming)); +@@ -976,13 +975,6 @@ static bool dml2_top_soc15_build_mode_programming(struct dml2_build_mode_program + l->base_display_config_with_meta.stage5.success = true; + } + +- /* +- * Populate mcache programming +- */ +- for (i = 0; i < in_out->display_config->num_planes; i++) { +- in_out->programming->plane_programming[i].mcache_allocation = l->base_display_config_with_meta.stage2.mcache_allocations[i]; +- } +- + /* + * Call DPMM to map all requirements to minimum clock state + */ +-- +2.39.5 + diff --git a/queue-6.14/drm-amd-display-guard-against-setting-dispclk-low-fo.patch b/queue-6.14/drm-amd-display-guard-against-setting-dispclk-low-fo.patch new file mode 100644 index 0000000000..97896bbf1c --- /dev/null +++ b/queue-6.14/drm-amd-display-guard-against-setting-dispclk-low-fo.patch @@ -0,0 +1,113 @@ +From 911b79e9c141c7bc01d47781ee7ca3cae802e477 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 4 Mar 2025 23:15:56 +0800 +Subject: drm/amd/display: Guard against setting dispclk low for dcn31x + +From: Jing Zhou + +[ Upstream commit 9c2f4ae64bb6f6d83a54d88b9ee0f369cdbb9fa8 ] + +[WHY] +We should never apply a minimum dispclk value while in +prepare_bandwidth or while displays are active. This is +always an optimizaiton for when all displays are disabled. + +[HOW] +Defer dispclk optimization until safe_to_lower = true +and display_count reaches 0. + +Since 0 has a special value in this logic (ie. no dispclk +required) we also need adjust the logic that clamps it for +the actual request to PMFW. + +Reviewed-by: Charlene Liu +Reviewed-by: Chris Park +Reviewed-by: Eric Yang +Signed-off-by: Jing Zhou +Signed-off-by: Nicholas Kazlauskas +Signed-off-by: Alex Hung +Tested-by: Daniel Wheeler +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + .../dc/clk_mgr/dcn315/dcn315_clk_mgr.c | 20 +++++++++++-------- + .../dc/clk_mgr/dcn316/dcn316_clk_mgr.c | 13 +++++++++--- + 2 files changed, 22 insertions(+), 11 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c +index a0fb4481d2f1b..827b24b3442ad 100644 +--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c ++++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c +@@ -130,7 +130,7 @@ static void dcn315_update_clocks(struct clk_mgr *clk_mgr_base, + struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base); + struct dc_clocks *new_clocks = &context->bw_ctx.bw.dcn.clk; + struct dc *dc = clk_mgr_base->ctx->dc; +- int display_count; ++ int display_count = 0; + bool update_dppclk = false; + bool update_dispclk = false; + bool dpp_clock_lowered = false; +@@ -204,15 +204,19 @@ static void dcn315_update_clocks(struct clk_mgr *clk_mgr_base, + update_dppclk = true; + } + +- if (should_set_clock(safe_to_lower, new_clocks->dispclk_khz, clk_mgr_base->clks.dispclk_khz)) { +- /* No need to apply the w/a if we haven't taken over from bios yet */ +- if (clk_mgr_base->clks.dispclk_khz) +- dcn315_disable_otg_wa(clk_mgr_base, context, true); ++ if (should_set_clock(safe_to_lower, new_clocks->dispclk_khz, clk_mgr_base->clks.dispclk_khz) && ++ (new_clocks->dispclk_khz > 0 || (safe_to_lower && display_count == 0))) { ++ int requested_dispclk_khz = new_clocks->dispclk_khz; + ++ dcn315_disable_otg_wa(clk_mgr_base, context, true); ++ ++ /* Clamp the requested clock to PMFW based on their limit. */ ++ if (dc->debug.min_disp_clk_khz > 0 && requested_dispclk_khz < dc->debug.min_disp_clk_khz) ++ requested_dispclk_khz = dc->debug.min_disp_clk_khz; ++ ++ dcn315_smu_set_dispclk(clk_mgr, requested_dispclk_khz); + clk_mgr_base->clks.dispclk_khz = new_clocks->dispclk_khz; +- dcn315_smu_set_dispclk(clk_mgr, clk_mgr_base->clks.dispclk_khz); +- if (clk_mgr_base->clks.dispclk_khz) +- dcn315_disable_otg_wa(clk_mgr_base, context, false); ++ dcn315_disable_otg_wa(clk_mgr_base, context, false); + + update_dispclk = true; + } +diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn316/dcn316_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn316/dcn316_clk_mgr.c +index c3e50c3aaa609..37c39756fece4 100644 +--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn316/dcn316_clk_mgr.c ++++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn316/dcn316_clk_mgr.c +@@ -140,7 +140,7 @@ static void dcn316_update_clocks(struct clk_mgr *clk_mgr_base, + struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base); + struct dc_clocks *new_clocks = &context->bw_ctx.bw.dcn.clk; + struct dc *dc = clk_mgr_base->ctx->dc; +- int display_count; ++ int display_count = 0; + bool update_dppclk = false; + bool update_dispclk = false; + bool dpp_clock_lowered = false; +@@ -211,11 +211,18 @@ static void dcn316_update_clocks(struct clk_mgr *clk_mgr_base, + update_dppclk = true; + } + +- if (should_set_clock(safe_to_lower, new_clocks->dispclk_khz, clk_mgr_base->clks.dispclk_khz)) { ++ if (should_set_clock(safe_to_lower, new_clocks->dispclk_khz, clk_mgr_base->clks.dispclk_khz) && ++ (new_clocks->dispclk_khz > 0 || (safe_to_lower && display_count == 0))) { ++ int requested_dispclk_khz = new_clocks->dispclk_khz; ++ + dcn316_disable_otg_wa(clk_mgr_base, context, safe_to_lower, true); + ++ /* Clamp the requested clock to PMFW based on their limit. */ ++ if (dc->debug.min_disp_clk_khz > 0 && requested_dispclk_khz < dc->debug.min_disp_clk_khz) ++ requested_dispclk_khz = dc->debug.min_disp_clk_khz; ++ ++ dcn316_smu_set_dispclk(clk_mgr, requested_dispclk_khz); + clk_mgr_base->clks.dispclk_khz = new_clocks->dispclk_khz; +- dcn316_smu_set_dispclk(clk_mgr, clk_mgr_base->clks.dispclk_khz); + dcn316_disable_otg_wa(clk_mgr_base, context, safe_to_lower, false); + + update_dispclk = true; +-- +2.39.5 + diff --git a/queue-6.14/drm-amd-display-guard-against-setting-dispclk-low-wh.patch b/queue-6.14/drm-amd-display-guard-against-setting-dispclk-low-wh.patch new file mode 100644 index 0000000000..e94a934110 --- /dev/null +++ b/queue-6.14/drm-amd-display-guard-against-setting-dispclk-low-wh.patch @@ -0,0 +1,65 @@ +From 1b001607bcbb63e9db4a86f6b3deb0fc1e005293 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 3 Feb 2025 09:49:58 -0500 +Subject: drm/amd/display: Guard against setting dispclk low when active + +From: Nicholas Kazlauskas + +[ Upstream commit 72d7a7fa1f2404fd31c84a8f808b1b37021a3a9e ] + +[Why] +We should never apply a minimum dispclk value while in prepare_bandwidth +or while displays are active. This is always an optimization for when +all displays are disabled. + +[How] +Defer dispclk optimization until safe_to_lower = true and display_count +reaches 0. + +Since 0 has a special value in this logic (ie. no dispclk required) +we also need adjust the logic that clamps it for the actual request +to PMFW. + +Reviewed-by: Gabe Teeger +Reviewed-by: Leo Chen +Reviewed-by: Syed Hassan +Signed-off-by: Nicholas Kazlauskas +Signed-off-by: Roman Li +Tested-by: Daniel Wheeler +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + .../amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c | 13 +++++++++---- + 1 file changed, 9 insertions(+), 4 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c +index 1648226586e22..1f47931c2dafc 100644 +--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c ++++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c +@@ -467,14 +467,19 @@ void dcn35_update_clocks(struct clk_mgr *clk_mgr_base, + update_dppclk = true; + } + +- if (should_set_clock(safe_to_lower, new_clocks->dispclk_khz, clk_mgr_base->clks.dispclk_khz)) { ++ if (should_set_clock(safe_to_lower, new_clocks->dispclk_khz, clk_mgr_base->clks.dispclk_khz) && ++ (new_clocks->dispclk_khz > 0 || (safe_to_lower && display_count == 0))) { ++ int requested_dispclk_khz = new_clocks->dispclk_khz; ++ + dcn35_disable_otg_wa(clk_mgr_base, context, safe_to_lower, true); + +- if (dc->debug.min_disp_clk_khz > 0 && new_clocks->dispclk_khz < dc->debug.min_disp_clk_khz) +- new_clocks->dispclk_khz = dc->debug.min_disp_clk_khz; ++ /* Clamp the requested clock to PMFW based on their limit. */ ++ if (dc->debug.min_disp_clk_khz > 0 && requested_dispclk_khz < dc->debug.min_disp_clk_khz) ++ requested_dispclk_khz = dc->debug.min_disp_clk_khz; + ++ dcn35_smu_set_dispclk(clk_mgr, requested_dispclk_khz); + clk_mgr_base->clks.dispclk_khz = new_clocks->dispclk_khz; +- dcn35_smu_set_dispclk(clk_mgr, clk_mgr_base->clks.dispclk_khz); ++ + dcn35_disable_otg_wa(clk_mgr_base, context, safe_to_lower, false); + + update_dispclk = true; +-- +2.39.5 + diff --git a/queue-6.14/drm-amd-display-handle-max_downscale_src_width-fail-.patch b/queue-6.14/drm-amd-display-handle-max_downscale_src_width-fail-.patch new file mode 100644 index 0000000000..465ebac7a5 --- /dev/null +++ b/queue-6.14/drm-amd-display-handle-max_downscale_src_width-fail-.patch @@ -0,0 +1,59 @@ +From e40ee048a9c140040aaf99fad6d7055bffa017b8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 12 Feb 2025 15:17:56 -0500 +Subject: drm/amd/display: handle max_downscale_src_width fail check + +From: Yihan Zhu + +[ Upstream commit 02a940da2ccc0cc0299811379580852b405a0ea2 ] + +[WHY] +If max_downscale_src_width check fails, we exit early from TAP calculation and left a NULL +value to the scaling data structure to cause the zero divide in the DML validation. + +[HOW] +Call set default TAP calculation before early exit in get_optimal_number_of_taps due to +max downscale limit exceed. + +Reviewed-by: Samson Tam +Signed-off-by: Yihan Zhu +Signed-off-by: Zaeem Mohamed +Tested-by: Daniel Wheeler +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/display/dc/dpp/dcn30/dcn30_dpp.c | 11 ++++++----- + 1 file changed, 6 insertions(+), 5 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/dpp/dcn30/dcn30_dpp.c b/drivers/gpu/drm/amd/display/dc/dpp/dcn30/dcn30_dpp.c +index 40acebd13e46d..abf439e743f23 100644 +--- a/drivers/gpu/drm/amd/display/dc/dpp/dcn30/dcn30_dpp.c ++++ b/drivers/gpu/drm/amd/display/dc/dpp/dcn30/dcn30_dpp.c +@@ -425,11 +425,6 @@ bool dpp3_get_optimal_number_of_taps( + int min_taps_y, min_taps_c; + enum lb_memory_config lb_config; + +- if (scl_data->viewport.width > scl_data->h_active && +- dpp->ctx->dc->debug.max_downscale_src_width != 0 && +- scl_data->viewport.width > dpp->ctx->dc->debug.max_downscale_src_width) +- return false; +- + /* + * Set default taps if none are provided + * From programming guide: taps = min{ ceil(2*H_RATIO,1), 8} for downscaling +@@ -467,6 +462,12 @@ bool dpp3_get_optimal_number_of_taps( + else + scl_data->taps.h_taps_c = in_taps->h_taps_c; + ++ // Avoid null data in the scl data with this early return, proceed non-adaptive calcualtion first ++ if (scl_data->viewport.width > scl_data->h_active && ++ dpp->ctx->dc->debug.max_downscale_src_width != 0 && ++ scl_data->viewport.width > dpp->ctx->dc->debug.max_downscale_src_width) ++ return false; ++ + /*Ensure we can support the requested number of vtaps*/ + min_taps_y = dc_fixpt_ceil(scl_data->ratios.vert); + min_taps_c = dc_fixpt_ceil(scl_data->ratios.vert_c); +-- +2.39.5 + diff --git a/queue-6.14/drm-amd-display-increase-block_sequence-array-size.patch b/queue-6.14/drm-amd-display-increase-block_sequence-array-size.patch new file mode 100644 index 0000000000..7d8faebf8e --- /dev/null +++ b/queue-6.14/drm-amd-display-increase-block_sequence-array-size.patch @@ -0,0 +1,46 @@ +From d411a33e856ffb64190d600158f92692d1d4a85e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 8 Jan 2025 12:03:23 -0500 +Subject: drm/amd/display: Increase block_sequence array size + +From: Joshua Aberback + +[ Upstream commit 3a7810c212bcf2f722671dadf4b23ff70a7d23ee ] + +[Why] +It's possible to generate more than 50 steps in hwss_build_fast_sequence, +for example with a 6-pipe asic where all pipes are in one MPC chain. This +overflows the block_sequence buffer and corrupts block_sequence_steps, +causing a crash. + +[How] +Expand block_sequence to 100 items. A naive upper bound on the possible +number of steps for a 6-pipe asic, ignoring the potential for steps to be +mutually exclusive, is 91 with current code, therefore 100 is sufficient. + +Reviewed-by: Alvin Lee +Signed-off-by: Joshua Aberback +Signed-off-by: Wayne Lin +Tested-by: Daniel Wheeler +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/display/dc/inc/core_types.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h +index d558efc6e12f9..652d52040f4e6 100644 +--- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h ++++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h +@@ -627,7 +627,7 @@ struct dc_state { + */ + struct bw_context bw_ctx; + +- struct block_sequence block_sequence[50]; ++ struct block_sequence block_sequence[100]; + unsigned int block_sequence_steps; + struct dc_dmub_cmd dc_dmub_cmd[10]; + unsigned int dmub_cmd_count; +-- +2.39.5 + diff --git a/queue-6.14/drm-amd-display-initial-psr_version-with-correct-set.patch b/queue-6.14/drm-amd-display-initial-psr_version-with-correct-set.patch new file mode 100644 index 0000000000..cbcb3061db --- /dev/null +++ b/queue-6.14/drm-amd-display-initial-psr_version-with-correct-set.patch @@ -0,0 +1,40 @@ +From eb16a102ab24d94a411c8089eb263dd68a40d3de Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 13 Jan 2025 14:22:31 +0800 +Subject: drm/amd/display: Initial psr_version with correct setting + +From: Tom Chung + +[ Upstream commit d8c782cac5007e68e7484d420168f12d3490def6 ] + +[Why & How] +The initial setting for psr_version is not correct while +create a virtual link. + +The default psr_version should be DC_PSR_VERSION_UNSUPPORTED. + +Reviewed-by: Roman Li +Signed-off-by: Tom Chung +Signed-off-by: Zaeem Mohamed +Tested-by: Daniel Wheeler +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/display/dc/core/dc.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c +index 167f9d99a5408..0ce0ad7f98396 100644 +--- a/drivers/gpu/drm/amd/display/dc/core/dc.c ++++ b/drivers/gpu/drm/amd/display/dc/core/dc.c +@@ -276,6 +276,7 @@ static bool create_links( + link->link_id.type = OBJECT_TYPE_CONNECTOR; + link->link_id.id = CONNECTOR_ID_VIRTUAL; + link->link_id.enum_id = ENUM_ID_1; ++ link->psr_settings.psr_version = DC_PSR_VERSION_UNSUPPORTED; + link->link_enc = kzalloc(sizeof(*link->link_enc), GFP_KERNEL); + + if (!link->link_enc) { +-- +2.39.5 + diff --git a/queue-6.14/drm-amd-display-not-abort-link-train-when-bw-is-low.patch b/queue-6.14/drm-amd-display-not-abort-link-train-when-bw-is-low.patch new file mode 100644 index 0000000000..37e7e1d81f --- /dev/null +++ b/queue-6.14/drm-amd-display-not-abort-link-train-when-bw-is-low.patch @@ -0,0 +1,49 @@ +From a07154ee6627ce013cce21ab48e4f918b59ed4ea Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 25 Feb 2025 14:52:30 +0800 +Subject: drm/amd/display: not abort link train when bw is low + +From: Peichen Huang + +[ Upstream commit 8a21da2842bb22b2b80e5902d0438030d729bfd3 ] + +[WHY] +DP tunneling should not abort link train even bandwidth become +too low after downgrade. Otherwise, it would fail compliance test. + +[HOW} +Do link train with downgrade settings even bandwidth is not enough + +Reviewed-by: Cruise Hung +Reviewed-by: Meenakshikumar Somasundaram +Signed-off-by: Peichen Huang +Signed-off-by: Tom Chung +Tested-by: Daniel Wheeler +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + .../gpu/drm/amd/display/dc/link/protocols/link_dp_training.c | 5 +---- + 1 file changed, 1 insertion(+), 4 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.c +index 751c18e592ea5..7848ddb94456c 100644 +--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.c ++++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.c +@@ -1782,13 +1782,10 @@ bool perform_link_training_with_retries( + is_link_bw_min = ((cur_link_settings.link_rate <= LINK_RATE_LOW) && + (cur_link_settings.lane_count <= LANE_COUNT_ONE)); + +- if (is_link_bw_low) { ++ if (is_link_bw_low) + DC_LOG_WARNING( + "%s: Link(%d) bandwidth too low after fallback req_bw(%d) > link_bw(%d)\n", + __func__, link->link_index, req_bw, link_bw); +- +- return false; +- } + } + + msleep(delay_between_attempts); +-- +2.39.5 + diff --git a/queue-6.14/drm-amd-display-pass-calculated-dram_speed_mts-to-dm.patch b/queue-6.14/drm-amd-display-pass-calculated-dram_speed_mts-to-dm.patch new file mode 100644 index 0000000000..5616d580ab --- /dev/null +++ b/queue-6.14/drm-amd-display-pass-calculated-dram_speed_mts-to-dm.patch @@ -0,0 +1,69 @@ +From fd123424c6643669dca7ce6a0f2db3845cc67cd6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 13 Jan 2025 11:57:54 -0500 +Subject: drm/amd/display: pass calculated dram_speed_mts to dml2 + +From: Charlene Liu + +[ Upstream commit b40d022ec06ade9f6c809091dc188422a0f0946d ] + +[why] +currently dml2 is using a hard coded 16 to convert memclk to dram_speed_mts. +for apu, this depends on wck_ratio. + +change to pass the already calculated dram_speed_mts from fpu to dml2. + +v2: use existing calculation of dram_speed_mts for now to avoid regression + +Signed-off-by: Charlene Liu +Signed-off-by: Aurabindo Pillai +Reviewed-by: Roman Li +Tested-by: Daniel Wheeler +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/display/dc/dml/dcn35/dcn35_fpu.c | 2 ++ + drivers/gpu/drm/amd/display/dc/dml/dcn351/dcn351_fpu.c | 1 + + drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.h | 1 + + 3 files changed, 4 insertions(+) + +diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn35/dcn35_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn35/dcn35_fpu.c +index beed7adbbd43e..c90dee4e9116a 100644 +--- a/drivers/gpu/drm/amd/display/dc/dml/dcn35/dcn35_fpu.c ++++ b/drivers/gpu/drm/amd/display/dc/dml/dcn35/dcn35_fpu.c +@@ -367,6 +367,8 @@ void dcn35_update_bw_bounding_box_fpu(struct dc *dc, + clock_limits[i].socclk_mhz; + dc->dml2_options.bbox_overrides.clks_table.clk_entries[i].memclk_mhz = + clk_table->entries[i].memclk_mhz * clk_table->entries[i].wck_ratio; ++ ++ dc->dml2_options.bbox_overrides.clks_table.clk_entries[i].dram_speed_mts = clock_limits[i].dram_speed_mts; + dc->dml2_options.bbox_overrides.clks_table.clk_entries[i].dtbclk_mhz = + clock_limits[i].dtbclk_mhz; + dc->dml2_options.bbox_overrides.clks_table.num_entries_per_clk.num_dcfclk_levels = +diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn351/dcn351_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn351/dcn351_fpu.c +index d9e63c4fdd95c..17d0b4923b0cc 100644 +--- a/drivers/gpu/drm/amd/display/dc/dml/dcn351/dcn351_fpu.c ++++ b/drivers/gpu/drm/amd/display/dc/dml/dcn351/dcn351_fpu.c +@@ -401,6 +401,7 @@ void dcn351_update_bw_bounding_box_fpu(struct dc *dc, + clock_limits[i].socclk_mhz; + dc->dml2_options.bbox_overrides.clks_table.clk_entries[i].memclk_mhz = + clk_table->entries[i].memclk_mhz * clk_table->entries[i].wck_ratio; ++ dc->dml2_options.bbox_overrides.clks_table.clk_entries[i].dram_speed_mts = clock_limits[i].dram_speed_mts; + dc->dml2_options.bbox_overrides.clks_table.clk_entries[i].dtbclk_mhz = + clock_limits[i].dtbclk_mhz; + dc->dml2_options.bbox_overrides.clks_table.num_entries_per_clk.num_dcfclk_levels = +diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.h b/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.h +index 0f944fcfd5a5b..785226945699d 100644 +--- a/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.h ++++ b/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.h +@@ -159,6 +159,7 @@ struct dml2_clks_table_entry { + unsigned int dtbclk_mhz; + unsigned int dispclk_mhz; + unsigned int dppclk_mhz; ++ unsigned int dram_speed_mts; /*which is based on wck_ratio*/ + }; + + struct dml2_clks_num_entries { +-- +2.39.5 + diff --git a/queue-6.14/drm-amd-display-populate-register-address-for-dentis.patch b/queue-6.14/drm-amd-display-populate-register-address-for-dentis.patch new file mode 100644 index 0000000000..24c8b08c69 --- /dev/null +++ b/queue-6.14/drm-amd-display-populate-register-address-for-dentis.patch @@ -0,0 +1,52 @@ +From e32cbda00592d79dc6d64d5e58c10179ef06e94c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 8 Jan 2025 15:25:41 -0500 +Subject: drm/amd/display: Populate register address for dentist for dcn401 + +From: Dillon Varone + +[ Upstream commit 5f0d1ef6f16e150ee46cc00b8d233d9d271fe39e ] + +[WHY&HOW] +Address was not previously populated which can result in incorrect +clock frequencies being read on boot. + +Reviewed-by: Alvin Lee +Signed-off-by: Dillon Varone +Signed-off-by: Wayne Lin +Tested-by: Daniel Wheeler +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dcn401_clk_mgr.c | 2 ++ + drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr_internal.h | 1 + + 2 files changed, 3 insertions(+) + +diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dcn401_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dcn401_clk_mgr.c +index 8082bb8776114..a3b8e3d4a429e 100644 +--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dcn401_clk_mgr.c ++++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dcn401_clk_mgr.c +@@ -24,6 +24,8 @@ + + #include "dml/dcn401/dcn401_fpu.h" + ++#define DCN_BASE__INST0_SEG1 0x000000C0 ++ + #define mmCLK01_CLK0_CLK_PLL_REQ 0x16E37 + #define mmCLK01_CLK0_CLK0_DFS_CNTL 0x16E69 + #define mmCLK01_CLK0_CLK1_DFS_CNTL 0x16E6C +diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr_internal.h b/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr_internal.h +index 7a1ca1e98059b..221645c023b50 100644 +--- a/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr_internal.h ++++ b/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr_internal.h +@@ -221,6 +221,7 @@ enum dentist_divider_range { + CLK_SF(CLK0_CLK_PLL_REQ, FbMult_frac, mask_sh) + + #define CLK_REG_LIST_DCN401() \ ++ SR(DENTIST_DISPCLK_CNTL), \ + CLK_SR_DCN401(CLK0_CLK_PLL_REQ, CLK01, 0), \ + CLK_SR_DCN401(CLK0_CLK0_DFS_CNTL, CLK01, 0), \ + CLK_SR_DCN401(CLK0_CLK1_DFS_CNTL, CLK01, 0), \ +-- +2.39.5 + diff --git a/queue-6.14/drm-amd-display-read-lttpr-alpm-caps-during-link-cap.patch b/queue-6.14/drm-amd-display-read-lttpr-alpm-caps-during-link-cap.patch new file mode 100644 index 0000000000..72d45550f3 --- /dev/null +++ b/queue-6.14/drm-amd-display-read-lttpr-alpm-caps-during-link-cap.patch @@ -0,0 +1,92 @@ +From acd1618700d0c4a4278a32968f614751d71b787a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 4 Feb 2025 14:34:02 -0500 +Subject: drm/amd/display: Read LTTPR ALPM caps during link cap retrieval + +From: George Shen + +[ Upstream commit de84d580126eb2214937df755cfec5ef0901479e ] + +[Why] +The latest DP spec requires the DP TX to read DPCD F0000h through F0009h +when detecting LTTPR capabilities for the first time. + +[How] +Update LTTPR cap retrieval to read up to F0009h (two more bytes than the +previous F0007h), and store the LTTPR ALPM capabilities. + +Reviewed-by: Wenjing Liu +Signed-off-by: George Shen +Signed-off-by: Roman Li +Tested-by: Daniel Wheeler +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/display/dc/dc_dp_types.h | 12 ++++++++++++ + .../display/dc/link/protocols/link_dp_capability.c | 6 +++++- + 2 files changed, 17 insertions(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/dc_dp_types.h b/drivers/gpu/drm/amd/display/dc/dc_dp_types.h +index cc005da75ce4c..8bb628ab78554 100644 +--- a/drivers/gpu/drm/amd/display/dc/dc_dp_types.h ++++ b/drivers/gpu/drm/amd/display/dc/dc_dp_types.h +@@ -959,6 +959,14 @@ union dp_128b_132b_supported_lttpr_link_rates { + uint8_t raw; + }; + ++union dp_alpm_lttpr_cap { ++ struct { ++ uint8_t AUX_LESS_ALPM_SUPPORTED :1; ++ uint8_t RESERVED :7; ++ } bits; ++ uint8_t raw; ++}; ++ + union dp_sink_video_fallback_formats { + struct { + uint8_t dp_1024x768_60Hz_24bpp_support :1; +@@ -1118,6 +1126,7 @@ struct dc_lttpr_caps { + uint8_t max_ext_timeout; + union dp_main_link_channel_coding_lttpr_cap main_link_channel_coding; + union dp_128b_132b_supported_lttpr_link_rates supported_128b_132b_rates; ++ union dp_alpm_lttpr_cap alpm; + uint8_t aux_rd_interval[MAX_REPEATER_CNT - 1]; + uint8_t lttpr_ieee_oui[3]; + uint8_t lttpr_device_id[6]; +@@ -1372,6 +1381,9 @@ struct dp_trace { + #ifndef DPCD_MAX_UNCOMPRESSED_PIXEL_RATE_CAP + #define DPCD_MAX_UNCOMPRESSED_PIXEL_RATE_CAP 0x221c + #endif ++#ifndef DP_LTTPR_ALPM_CAPABILITIES ++#define DP_LTTPR_ALPM_CAPABILITIES 0xF0009 ++#endif + #ifndef DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE + #define DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE 0x50 + #endif +diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c +index 28843e9882d39..64e4ae379e346 100644 +--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c ++++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c +@@ -1502,7 +1502,7 @@ static bool dpcd_read_sink_ext_caps(struct dc_link *link) + + enum dc_status dp_retrieve_lttpr_cap(struct dc_link *link) + { +- uint8_t lttpr_dpcd_data[8] = {0}; ++ uint8_t lttpr_dpcd_data[10] = {0}; + enum dc_status status; + bool is_lttpr_present; + +@@ -1552,6 +1552,10 @@ enum dc_status dp_retrieve_lttpr_cap(struct dc_link *link) + lttpr_dpcd_data[DP_PHY_REPEATER_128B132B_RATES - + DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV]; + ++ link->dpcd_caps.lttpr_caps.alpm.raw = ++ lttpr_dpcd_data[DP_LTTPR_ALPM_CAPABILITIES - ++ DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV]; ++ + /* If this chip cap is set, at least one retimer must exist in the chain + * Override count to 1 if we receive a known bad count (0 or an invalid value) */ + if (((link->chip_caps & AMD_EXT_DISPLAY_PATH_CAPS__EXT_CHIP_MASK) == AMD_EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN) && +-- +2.39.5 + diff --git a/queue-6.14/drm-amd-display-remove-minimum-dispclk-and-apply-oem.patch b/queue-6.14/drm-amd-display-remove-minimum-dispclk-and-apply-oem.patch new file mode 100644 index 0000000000..785143288e --- /dev/null +++ b/queue-6.14/drm-amd-display-remove-minimum-dispclk-and-apply-oem.patch @@ -0,0 +1,71 @@ +From 376417c750d9d4eb845a64da5eb4d735684c31e9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 3 Mar 2025 13:53:16 -0500 +Subject: drm/amd/display: remove minimum Dispclk and apply oem panel timing. + +From: Charlene Liu + +[ Upstream commit 756e58e83e89d372b94269c0cde61fe55da76947 ] + +[why & how] +1. apply oem panel timing (not only on OLED) +2. remove MIN_DPP_DISP_CLK request in driver. + +This fix will apply for dcn31x but not +sync with DML's output. + +Reviewed-by: Ovidiu Bunea +Signed-off-by: Charlene Liu +Signed-off-by: Tom Chung +Tested-by: Daniel Wheeler +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c | 2 -- + drivers/gpu/drm/amd/display/dc/clk_mgr/dcn316/dcn316_clk_mgr.c | 2 -- + drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c | 3 ++- + 3 files changed, 2 insertions(+), 5 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c +index 827b24b3442ad..e4d22f74f9869 100644 +--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c ++++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c +@@ -194,8 +194,6 @@ static void dcn315_update_clocks(struct clk_mgr *clk_mgr_base, + // workaround: Limit dppclk to 100Mhz to avoid lower eDP panel switch to plus 4K monitor underflow. + if (new_clocks->dppclk_khz < MIN_DPP_DISP_CLK) + new_clocks->dppclk_khz = MIN_DPP_DISP_CLK; +- if (new_clocks->dispclk_khz < MIN_DPP_DISP_CLK) +- new_clocks->dispclk_khz = MIN_DPP_DISP_CLK; + + if (should_set_clock(safe_to_lower, new_clocks->dppclk_khz, clk_mgr->base.clks.dppclk_khz)) { + if (clk_mgr->base.clks.dppclk_khz > new_clocks->dppclk_khz) +diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn316/dcn316_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn316/dcn316_clk_mgr.c +index 37c39756fece4..49efea0c8fcff 100644 +--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn316/dcn316_clk_mgr.c ++++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn316/dcn316_clk_mgr.c +@@ -201,8 +201,6 @@ static void dcn316_update_clocks(struct clk_mgr *clk_mgr_base, + // workaround: Limit dppclk to 100Mhz to avoid lower eDP panel switch to plus 4K monitor underflow. + if (new_clocks->dppclk_khz < 100000) + new_clocks->dppclk_khz = 100000; +- if (new_clocks->dispclk_khz < 100000) +- new_clocks->dispclk_khz = 100000; + + if (should_set_clock(safe_to_lower, new_clocks->dppclk_khz, clk_mgr->base.clks.dppclk_khz)) { + if (clk_mgr->base.clks.dppclk_khz > new_clocks->dppclk_khz) +diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c +index fc4fb4055ab00..94ceccfc04982 100644 +--- a/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c ++++ b/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c +@@ -1065,7 +1065,8 @@ void dce110_edp_backlight_control( + DC_LOG_DC("edp_receiver_ready_T9 skipped\n"); + } + +- if (!enable && link->dpcd_sink_ext_caps.bits.oled) { ++ if (!enable) { ++ /*follow oem panel config's requirement*/ + pre_T11_delay += link->panel_config.pps.extra_pre_t11_ms; + msleep(pre_T11_delay); + } +-- +2.39.5 + diff --git a/queue-6.14/drm-amd-display-remove-tf-check-for-lls-policy.patch b/queue-6.14/drm-amd-display-remove-tf-check-for-lls-policy.patch new file mode 100644 index 0000000000..29c61ce690 --- /dev/null +++ b/queue-6.14/drm-amd-display-remove-tf-check-for-lls-policy.patch @@ -0,0 +1,90 @@ +From 22c561a70d92fa70cb5db37f649893ac2dfd27d9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 27 Jan 2025 18:27:06 -0500 +Subject: drm/amd/display: remove TF check for LLS policy + +From: Samson Tam + +[ Upstream commit 2a4519c4e9b2e1f622ab4c5f5841abdb9760cb0b ] + +[Why & How] +LLS policy not affected by TF. +Remove check in don't care case and use + pixel format only. + +Reviewed-by: Navid Assadian +Signed-off-by: Samson Tam +Signed-off-by: Aurabindo Pillai +Tested-by: Daniel Wheeler +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/display/dc/spl/dc_spl.c | 31 +++++---------------- + 1 file changed, 7 insertions(+), 24 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/spl/dc_spl.c b/drivers/gpu/drm/amd/display/dc/spl/dc_spl.c +index 153b7a8904e1e..047f05ab01810 100644 +--- a/drivers/gpu/drm/amd/display/dc/spl/dc_spl.c ++++ b/drivers/gpu/drm/amd/display/dc/spl/dc_spl.c +@@ -784,25 +784,13 @@ static enum scl_mode spl_get_dscl_mode(const struct spl_in *spl_in, + return SCL_MODE_SCALING_420_YCBCR_ENABLE; + } + +-static bool spl_choose_lls_policy(enum spl_pixel_format format, +- enum spl_transfer_func_type tf_type, +- enum spl_transfer_func_predefined tf_predefined_type, ++static void spl_choose_lls_policy(enum spl_pixel_format format, + enum linear_light_scaling *lls_pref) + { +- if (spl_is_video_format(format)) { ++ if (spl_is_subsampled_format(format)) + *lls_pref = LLS_PREF_NO; +- if ((tf_type == SPL_TF_TYPE_PREDEFINED) || +- (tf_type == SPL_TF_TYPE_DISTRIBUTED_POINTS)) +- return true; +- } else { /* RGB or YUV444 */ +- if ((tf_type == SPL_TF_TYPE_PREDEFINED) || +- (tf_type == SPL_TF_TYPE_BYPASS)) { +- *lls_pref = LLS_PREF_YES; +- return true; +- } +- } +- *lls_pref = LLS_PREF_NO; +- return false; ++ else /* RGB or YUV444 */ ++ *lls_pref = LLS_PREF_YES; + } + + /* Enable EASF ?*/ +@@ -811,7 +799,6 @@ static bool enable_easf(struct spl_in *spl_in, struct spl_scratch *spl_scratch) + int vratio = 0; + int hratio = 0; + bool skip_easf = false; +- bool lls_enable_easf = true; + + if (spl_in->disable_easf) + skip_easf = true; +@@ -827,17 +814,13 @@ static bool enable_easf(struct spl_in *spl_in, struct spl_scratch *spl_scratch) + skip_easf = true; + + /* +- * If lls_pref is LLS_PREF_DONT_CARE, then use pixel format and transfer +- * function to determine whether to use LINEAR or NONLINEAR scaling ++ * If lls_pref is LLS_PREF_DONT_CARE, then use pixel format ++ * to determine whether to use LINEAR or NONLINEAR scaling + */ + if (spl_in->lls_pref == LLS_PREF_DONT_CARE) +- lls_enable_easf = spl_choose_lls_policy(spl_in->basic_in.format, +- spl_in->basic_in.tf_type, spl_in->basic_in.tf_predefined_type, ++ spl_choose_lls_policy(spl_in->basic_in.format, + &spl_in->lls_pref); + +- if (!lls_enable_easf) +- skip_easf = true; +- + /* Check for linear scaling or EASF preferred */ + if (spl_in->lls_pref != LLS_PREF_YES && !spl_in->prefer_easf) + skip_easf = true; +-- +2.39.5 + diff --git a/queue-6.14/drm-amd-display-request-hw-cursor-on-dcn3.2-with-sub.patch b/queue-6.14/drm-amd-display-request-hw-cursor-on-dcn3.2-with-sub.patch new file mode 100644 index 0000000000..6c49b07667 --- /dev/null +++ b/queue-6.14/drm-amd-display-request-hw-cursor-on-dcn3.2-with-sub.patch @@ -0,0 +1,59 @@ +From 407cb3bd580cf0a9ae24db7e1981ad819c55f8e1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 23 Jan 2025 16:39:52 -0500 +Subject: drm/amd/display: Request HW cursor on DCN3.2 with SubVP + +From: Aric Cyr + +[ Upstream commit b74f46f3ce1e5f6336645f1e9ff47c56d5dfdef1 ] + +[why] +When SubVP is active the HW cursor size is limited to 64x64, and +anything larger will force composition which is bad for gaming on +DCN3.2 if the game uses a larger cursor. + +[how] +If HW cursor is requested, typically by a fullscreen game, do not +enable SubVP so that up to 256x256 cursor sizes are available for +DCN3.2. + +Reviewed-by: Aric Cyr +Signed-off-by: Aric Cyr +Signed-off-by: Wayne Lin +Tested-by: Daniel Wheeler +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/display/dc/core/dc.c | 3 ++- + drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c | 1 + + 2 files changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c +index 722175e347fdc..167f9d99a5408 100644 +--- a/drivers/gpu/drm/amd/display/dc/core/dc.c ++++ b/drivers/gpu/drm/amd/display/dc/core/dc.c +@@ -4912,7 +4912,8 @@ static bool full_update_required(struct dc *dc, + stream_update->lut3d_func || + stream_update->pending_test_pattern || + stream_update->crtc_timing_adjust || +- stream_update->scaler_sharpener_update)) ++ stream_update->scaler_sharpener_update || ++ stream_update->hw_cursor_req)) + return true; + + if (stream) { +diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c +index 6f490d8d7038c..56dda686e2992 100644 +--- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c ++++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c +@@ -626,6 +626,7 @@ static bool dcn32_assign_subvp_pipe(struct dc *dc, + * - Not TMZ surface + */ + if (pipe->plane_state && !pipe->top_pipe && !pipe->prev_odm_pipe && !dcn32_is_center_timing(pipe) && ++ !pipe->stream->hw_cursor_req && + !(pipe->stream->timing.pix_clk_100hz / 10000 > DCN3_2_MAX_SUBVP_PIXEL_RATE_MHZ) && + (!dcn32_is_psr_capable(pipe) || (context->stream_count == 1 && dc->caps.dmub_caps.subvp_psr)) && + dc_state_get_pipe_subvp_type(context, pipe) == SUBVP_NONE && +-- +2.39.5 + diff --git a/queue-6.14/drm-amd-display-reverse-the-visual-confirm-recouts.patch b/queue-6.14/drm-amd-display-reverse-the-visual-confirm-recouts.patch new file mode 100644 index 0000000000..efe4a6cb85 --- /dev/null +++ b/queue-6.14/drm-amd-display-reverse-the-visual-confirm-recouts.patch @@ -0,0 +1,329 @@ +From b9369a6077bfd332e8764ef17626f08b3951dd85 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 5 Dec 2024 18:51:25 -0500 +Subject: drm/amd/display: Reverse the visual confirm recouts + +From: Peterson Guo + +[ Upstream commit 3c50bf2196aaddcaffe2c7a1a7080470380cbfdd ] + +[WHY] +When checking if a pipe can disable cursor to prevent duplicate cursors, +having visual confirm on will prevent disabling cursors on planes which +cover the bottom of the screen. + +[HOW] +When checking if a plane can disable visual confirm, the pipe first +reverses these calculations before doing the checks. + +Reviewed-by: Alvin Lee +Signed-off-by: Peterson Guo +Signed-off-by: Wayne Lin +Tested-by: Daniel Wheeler +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + .../gpu/drm/amd/display/dc/core/dc_resource.c | 67 +++++++++++++++++++ + drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c | 50 +------------- + .../amd/display/dc/hwss/dcn10/dcn10_hwseq.c | 48 +------------ + .../amd/display/dc/hwss/dcn401/dcn401_hwseq.c | 48 +------------ + drivers/gpu/drm/amd/display/dc/inc/resource.h | 2 + + 5 files changed, 73 insertions(+), 142 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +index 3367030da3414..375b3b1d1d182 100644 +--- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c ++++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +@@ -941,6 +941,17 @@ static void calculate_adjust_recout_for_visual_confirm(struct pipe_ctx *pipe_ctx + *base_offset = VISUAL_CONFIRM_BASE_DEFAULT; + } + ++static void reverse_adjust_recout_for_visual_confirm(struct rect *recout, ++ struct pipe_ctx *pipe_ctx) ++{ ++ int dpp_offset, base_offset; ++ ++ calculate_adjust_recout_for_visual_confirm(pipe_ctx, &base_offset, ++ &dpp_offset); ++ recout->height += base_offset; ++ recout->height += dpp_offset; ++} ++ + static void adjust_recout_for_visual_confirm(struct rect *recout, + struct pipe_ctx *pipe_ctx) + { +@@ -1642,6 +1653,62 @@ bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx) + return res; + } + ++bool resource_can_pipe_disable_cursor(struct pipe_ctx *pipe_ctx) ++{ ++ struct pipe_ctx *test_pipe, *split_pipe; ++ struct rect r1 = pipe_ctx->plane_res.scl_data.recout; ++ int r1_right, r1_bottom; ++ int cur_layer = pipe_ctx->plane_state->layer_index; ++ ++ reverse_adjust_recout_for_visual_confirm(&r1, pipe_ctx); ++ r1_right = r1.x + r1.width; ++ r1_bottom = r1.y + r1.height; ++ ++ /** ++ * Disable the cursor if there's another pipe above this with a ++ * plane that contains this pipe's viewport to prevent double cursor ++ * and incorrect scaling artifacts. ++ */ ++ for (test_pipe = pipe_ctx->top_pipe; test_pipe; ++ test_pipe = test_pipe->top_pipe) { ++ struct rect r2; ++ int r2_right, r2_bottom; ++ // Skip invisible layer and pipe-split plane on same layer ++ if (!test_pipe->plane_state || ++ !test_pipe->plane_state->visible || ++ test_pipe->plane_state->layer_index == cur_layer) ++ continue; ++ ++ r2 = test_pipe->plane_res.scl_data.recout; ++ reverse_adjust_recout_for_visual_confirm(&r2, test_pipe); ++ r2_right = r2.x + r2.width; ++ r2_bottom = r2.y + r2.height; ++ ++ /** ++ * There is another half plane on same layer because of ++ * pipe-split, merge together per same height. ++ */ ++ for (split_pipe = pipe_ctx->top_pipe; split_pipe; ++ split_pipe = split_pipe->top_pipe) ++ if (split_pipe->plane_state->layer_index == test_pipe->plane_state->layer_index) { ++ struct rect r2_half; ++ ++ r2_half = split_pipe->plane_res.scl_data.recout; ++ reverse_adjust_recout_for_visual_confirm(&r2_half, split_pipe); ++ r2.x = min(r2_half.x, r2.x); ++ r2.width = r2.width + r2_half.width; ++ r2_right = r2.x + r2.width; ++ r2_bottom = min(r2_bottom, r2_half.y + r2_half.height); ++ break; ++ } ++ ++ if (r1.x >= r2.x && r1.y >= r2.y && r1_right <= r2_right && r1_bottom <= r2_bottom) ++ return true; ++ } ++ ++ return false; ++} ++ + + enum dc_status resource_build_scaling_params_for_context( + const struct dc *dc, +diff --git a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c +index 44ff9abe2880f..87b4c2793df3c 100644 +--- a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c ++++ b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c +@@ -991,57 +991,11 @@ void dc_dmub_srv_log_diagnostic_data(struct dc_dmub_srv *dc_dmub_srv) + DC_LOG_DEBUG(" is_cw6_en : %d", diag_data.is_cw6_enabled); + } + +-static bool dc_can_pipe_disable_cursor(struct pipe_ctx *pipe_ctx) +-{ +- struct pipe_ctx *test_pipe, *split_pipe; +- const struct scaler_data *scl_data = &pipe_ctx->plane_res.scl_data; +- struct rect r1 = scl_data->recout, r2, r2_half; +- int r1_r = r1.x + r1.width, r1_b = r1.y + r1.height, r2_r, r2_b; +- int cur_layer = pipe_ctx->plane_state->layer_index; +- +- /** +- * Disable the cursor if there's another pipe above this with a +- * plane that contains this pipe's viewport to prevent double cursor +- * and incorrect scaling artifacts. +- */ +- for (test_pipe = pipe_ctx->top_pipe; test_pipe; +- test_pipe = test_pipe->top_pipe) { +- // Skip invisible layer and pipe-split plane on same layer +- if (!test_pipe->plane_state->visible || test_pipe->plane_state->layer_index == cur_layer) +- continue; +- +- r2 = test_pipe->plane_res.scl_data.recout; +- r2_r = r2.x + r2.width; +- r2_b = r2.y + r2.height; +- +- /** +- * There is another half plane on same layer because of +- * pipe-split, merge together per same height. +- */ +- for (split_pipe = pipe_ctx->top_pipe; split_pipe; +- split_pipe = split_pipe->top_pipe) +- if (split_pipe->plane_state->layer_index == test_pipe->plane_state->layer_index) { +- r2_half = split_pipe->plane_res.scl_data.recout; +- r2.x = (r2_half.x < r2.x) ? r2_half.x : r2.x; +- r2.width = r2.width + r2_half.width; +- r2_r = r2.x + r2.width; +- break; +- } +- +- if (r1.x >= r2.x && r1.y >= r2.y && r1_r <= r2_r && r1_b <= r2_b) +- return true; +- } +- +- return false; +-} +- + static bool dc_dmub_should_update_cursor_data(struct pipe_ctx *pipe_ctx) + { + if (pipe_ctx->plane_state != NULL) { +- if (pipe_ctx->plane_state->address.type == PLN_ADDR_TYPE_VIDEO_PROGRESSIVE) +- return false; +- +- if (dc_can_pipe_disable_cursor(pipe_ctx)) ++ if (pipe_ctx->plane_state->address.type == PLN_ADDR_TYPE_VIDEO_PROGRESSIVE || ++ resource_can_pipe_disable_cursor(pipe_ctx)) + return false; + } + +diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c +index 4c89bf6725b3b..bbeaefe1ef0db 100644 +--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c ++++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c +@@ -3424,52 +3424,6 @@ void dcn10_update_dchub(struct dce_hwseq *hws, struct dchub_init_data *dh_data) + hubbub->funcs->update_dchub(hubbub, dh_data); + } + +-static bool dcn10_can_pipe_disable_cursor(struct pipe_ctx *pipe_ctx) +-{ +- struct pipe_ctx *test_pipe, *split_pipe; +- const struct scaler_data *scl_data = &pipe_ctx->plane_res.scl_data; +- struct rect r1 = scl_data->recout, r2, r2_half; +- int r1_r = r1.x + r1.width, r1_b = r1.y + r1.height, r2_r, r2_b; +- int cur_layer = pipe_ctx->plane_state->layer_index; +- +- /** +- * Disable the cursor if there's another pipe above this with a +- * plane that contains this pipe's viewport to prevent double cursor +- * and incorrect scaling artifacts. +- */ +- for (test_pipe = pipe_ctx->top_pipe; test_pipe; +- test_pipe = test_pipe->top_pipe) { +- // Skip invisible layer and pipe-split plane on same layer +- if (!test_pipe->plane_state || +- !test_pipe->plane_state->visible || +- test_pipe->plane_state->layer_index == cur_layer) +- continue; +- +- r2 = test_pipe->plane_res.scl_data.recout; +- r2_r = r2.x + r2.width; +- r2_b = r2.y + r2.height; +- +- /** +- * There is another half plane on same layer because of +- * pipe-split, merge together per same height. +- */ +- for (split_pipe = pipe_ctx->top_pipe; split_pipe; +- split_pipe = split_pipe->top_pipe) +- if (split_pipe->plane_state->layer_index == test_pipe->plane_state->layer_index) { +- r2_half = split_pipe->plane_res.scl_data.recout; +- r2.x = (r2_half.x < r2.x) ? r2_half.x : r2.x; +- r2.width = r2.width + r2_half.width; +- r2_r = r2.x + r2.width; +- break; +- } +- +- if (r1.x >= r2.x && r1.y >= r2.y && r1_r <= r2_r && r1_b <= r2_b) +- return true; +- } +- +- return false; +-} +- + void dcn10_set_cursor_position(struct pipe_ctx *pipe_ctx) + { + struct dc_cursor_position pos_cpy = pipe_ctx->stream->cursor_position; +@@ -3569,7 +3523,7 @@ void dcn10_set_cursor_position(struct pipe_ctx *pipe_ctx) + == PLN_ADDR_TYPE_VIDEO_PROGRESSIVE) + pos_cpy.enable = false; + +- if (pos_cpy.enable && dcn10_can_pipe_disable_cursor(pipe_ctx)) ++ if (pos_cpy.enable && resource_can_pipe_disable_cursor(pipe_ctx)) + pos_cpy.enable = false; + + +diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c +index a6f2aff84267d..da8afb08b9201 100644 +--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c ++++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c +@@ -972,52 +972,6 @@ void dcn401_setup_hpo_hw_control(const struct dce_hwseq *hws, bool enable) + REG_UPDATE(HPO_TOP_HW_CONTROL, HPO_IO_EN, enable); + } + +-static bool dcn401_can_pipe_disable_cursor(struct pipe_ctx *pipe_ctx) +-{ +- struct pipe_ctx *test_pipe, *split_pipe; +- const struct scaler_data *scl_data = &pipe_ctx->plane_res.scl_data; +- struct rect r1 = scl_data->recout, r2, r2_half; +- int r1_r = r1.x + r1.width, r1_b = r1.y + r1.height, r2_r, r2_b; +- int cur_layer = pipe_ctx->plane_state->layer_index; +- +- /** +- * Disable the cursor if there's another pipe above this with a +- * plane that contains this pipe's viewport to prevent double cursor +- * and incorrect scaling artifacts. +- */ +- for (test_pipe = pipe_ctx->top_pipe; test_pipe; +- test_pipe = test_pipe->top_pipe) { +- // Skip invisible layer and pipe-split plane on same layer +- if (!test_pipe->plane_state || +- !test_pipe->plane_state->visible || +- test_pipe->plane_state->layer_index == cur_layer) +- continue; +- +- r2 = test_pipe->plane_res.scl_data.recout; +- r2_r = r2.x + r2.width; +- r2_b = r2.y + r2.height; +- +- /** +- * There is another half plane on same layer because of +- * pipe-split, merge together per same height. +- */ +- for (split_pipe = pipe_ctx->top_pipe; split_pipe; +- split_pipe = split_pipe->top_pipe) +- if (split_pipe->plane_state->layer_index == test_pipe->plane_state->layer_index) { +- r2_half = split_pipe->plane_res.scl_data.recout; +- r2.x = (r2_half.x < r2.x) ? r2_half.x : r2.x; +- r2.width = r2.width + r2_half.width; +- r2_r = r2.x + r2.width; +- break; +- } +- +- if (r1.x >= r2.x && r1.y >= r2.y && r1_r <= r2_r && r1_b <= r2_b) +- return true; +- } +- +- return false; +-} +- + void adjust_hotspot_between_slices_for_2x_magnify(uint32_t cursor_width, struct dc_cursor_position *pos_cpy) + { + if (cursor_width <= 128) { +@@ -1208,7 +1162,7 @@ void dcn401_set_cursor_position(struct pipe_ctx *pipe_ctx) + pos_cpy.x = (uint32_t)x_pos; + pos_cpy.y = (uint32_t)y_pos; + +- if (pos_cpy.enable && dcn401_can_pipe_disable_cursor(pipe_ctx)) ++ if (pos_cpy.enable && resource_can_pipe_disable_cursor(pipe_ctx)) + pos_cpy.enable = false; + + x_pos = pos_cpy.x - param.recout.x; +diff --git a/drivers/gpu/drm/amd/display/dc/inc/resource.h b/drivers/gpu/drm/amd/display/dc/inc/resource.h +index cd1157d225abe..b32d07ce0f087 100644 +--- a/drivers/gpu/drm/amd/display/dc/inc/resource.h ++++ b/drivers/gpu/drm/amd/display/dc/inc/resource.h +@@ -152,6 +152,8 @@ bool resource_attach_surfaces_to_context( + struct dc_state *context, + const struct resource_pool *pool); + ++bool resource_can_pipe_disable_cursor(struct pipe_ctx *pipe_ctx); ++ + #define FREE_PIPE_INDEX_NOT_FOUND -1 + + /* +-- +2.39.5 + diff --git a/queue-6.14/drm-amd-display-skip-checking-frl_mode-bit-for-pcon-.patch b/queue-6.14/drm-amd-display-skip-checking-frl_mode-bit-for-pcon-.patch new file mode 100644 index 0000000000..246e4bd404 --- /dev/null +++ b/queue-6.14/drm-amd-display-skip-checking-frl_mode-bit-for-pcon-.patch @@ -0,0 +1,70 @@ +From d0223a85cdaa761da8c2c41d607b2cd480796383 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 14 Feb 2025 22:00:13 -0500 +Subject: drm/amd/display: Skip checking FRL_MODE bit for PCON BW determination + +From: George Shen + +[ Upstream commit 0584bbcf0c53c133081100e4f4c9fe41e598d045 ] + +[Why/How] +Certain PCON will clear the FRL_MODE bit despite supporting the link BW +indicated in the other bits. + +Thus, skip checking the FRL_MODE bit when interpreting the +hdmi_encoded_link_bw struct. + +Reviewed-by: Wenjing Liu +Signed-off-by: George Shen +Signed-off-by: Wayne Lin +Tested-by: Daniel Wheeler +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + .../dc/link/protocols/link_dp_capability.c | 30 +++++++++---------- + 1 file changed, 15 insertions(+), 15 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c +index 44f33e3bc1c59..6d7131369f00b 100644 +--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c ++++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c +@@ -250,21 +250,21 @@ static uint32_t intersect_frl_link_bw_support( + { + uint32_t supported_bw_in_kbps = max_supported_frl_bw_in_kbps; + +- // HDMI_ENCODED_LINK_BW bits are only valid if HDMI Link Configuration bit is 1 (FRL mode) +- if (hdmi_encoded_link_bw.bits.FRL_MODE) { +- if (hdmi_encoded_link_bw.bits.BW_48Gbps) +- supported_bw_in_kbps = 48000000; +- else if (hdmi_encoded_link_bw.bits.BW_40Gbps) +- supported_bw_in_kbps = 40000000; +- else if (hdmi_encoded_link_bw.bits.BW_32Gbps) +- supported_bw_in_kbps = 32000000; +- else if (hdmi_encoded_link_bw.bits.BW_24Gbps) +- supported_bw_in_kbps = 24000000; +- else if (hdmi_encoded_link_bw.bits.BW_18Gbps) +- supported_bw_in_kbps = 18000000; +- else if (hdmi_encoded_link_bw.bits.BW_9Gbps) +- supported_bw_in_kbps = 9000000; +- } ++ /* Skip checking FRL_MODE bit, as certain PCON will clear ++ * it despite supporting the link BW indicated in the other bits. ++ */ ++ if (hdmi_encoded_link_bw.bits.BW_48Gbps) ++ supported_bw_in_kbps = 48000000; ++ else if (hdmi_encoded_link_bw.bits.BW_40Gbps) ++ supported_bw_in_kbps = 40000000; ++ else if (hdmi_encoded_link_bw.bits.BW_32Gbps) ++ supported_bw_in_kbps = 32000000; ++ else if (hdmi_encoded_link_bw.bits.BW_24Gbps) ++ supported_bw_in_kbps = 24000000; ++ else if (hdmi_encoded_link_bw.bits.BW_18Gbps) ++ supported_bw_in_kbps = 18000000; ++ else if (hdmi_encoded_link_bw.bits.BW_9Gbps) ++ supported_bw_in_kbps = 9000000; + + return supported_bw_in_kbps; + } +-- +2.39.5 + diff --git a/queue-6.14/drm-amd-display-support-multiple-options-during-psr-.patch b/queue-6.14/drm-amd-display-support-multiple-options-during-psr-.patch new file mode 100644 index 0000000000..85a5326a66 --- /dev/null +++ b/queue-6.14/drm-amd-display-support-multiple-options-during-psr-.patch @@ -0,0 +1,81 @@ +From 074d8af3e2defc78c6b439711acd17da1a3e6a78 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 20 Jan 2025 11:21:46 +0800 +Subject: drm/amd/display: Support multiple options during psr entry. + +From: Martin Tsai + +[ Upstream commit 3a5fa55455db6a11248a25f24570c365f9246144 ] + +[WHY] +Some panels may not handle idle pattern properly during PSR entry. + +[HOW] +Add a condition to allow multiple options on power down +sequence during PSR1 entry. + +Reviewed-by: Anthony Koo +Signed-off-by: Martin Tsai +Signed-off-by: Alex Hung +Tested-by: Daniel Wheeler +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/display/dc/dc_types.h | 7 +++++++ + drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c | 4 ++++ + drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h | 6 ++++++ + 3 files changed, 17 insertions(+) + +diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h +index 0c2aa91f0a111..e60898c2df01a 100644 +--- a/drivers/gpu/drm/amd/display/dc/dc_types.h ++++ b/drivers/gpu/drm/amd/display/dc/dc_types.h +@@ -1033,6 +1033,13 @@ struct psr_settings { + unsigned int psr_sdp_transmit_line_num_deadline; + uint8_t force_ffu_mode; + unsigned int psr_power_opt; ++ ++ /** ++ * Some panels cannot handle idle pattern during PSR entry. ++ * To power down phy before disable stream to avoid sending ++ * idle pattern. ++ */ ++ uint8_t power_down_phy_before_disable_stream; + }; + + enum replay_coasting_vtotal_type { +diff --git a/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c b/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c +index 88c75c243bf8a..ff3b8244ba3d0 100644 +--- a/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c ++++ b/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c +@@ -418,6 +418,10 @@ static bool dmub_psr_copy_settings(struct dmub_psr *dmub, + copy_settings_data->relock_delay_frame_cnt = 0; + if (link->dpcd_caps.sink_dev_id == DP_BRANCH_DEVICE_ID_001CF8) + copy_settings_data->relock_delay_frame_cnt = 2; ++ ++ copy_settings_data->power_down_phy_before_disable_stream = ++ link->psr_settings.power_down_phy_before_disable_stream; ++ + copy_settings_data->dsc_slice_height = psr_context->dsc_slice_height; + + dc_wake_and_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT); +diff --git a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h +index d0fe324cb5371..8cf89aed024b7 100644 +--- a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h ++++ b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h +@@ -3118,6 +3118,12 @@ struct dmub_cmd_psr_copy_settings_data { + * Some panels request main link off before xth vertical line + */ + uint16_t poweroff_before_vertical_line; ++ /** ++ * Some panels cannot handle idle pattern during PSR entry. ++ * To power down phy before disable stream to avoid sending ++ * idle pattern. ++ */ ++ uint8_t power_down_phy_before_disable_stream; + }; + + /** +-- +2.39.5 + diff --git a/queue-6.14/drm-amd-display-update-cr-aux-rd-interval-interpreta.patch b/queue-6.14/drm-amd-display-update-cr-aux-rd-interval-interpreta.patch new file mode 100644 index 0000000000..1027033a9c --- /dev/null +++ b/queue-6.14/drm-amd-display-update-cr-aux-rd-interval-interpreta.patch @@ -0,0 +1,71 @@ +From c4ff5cbc1c826c0bf0359346d362c61e308541f3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 10 Jan 2025 11:35:46 -0500 +Subject: drm/amd/display: Update CR AUX RD interval interpretation + +From: George Shen + +[ Upstream commit 6a7fde433231c18164c117592d3e18ced648ad58 ] + +[Why] +DP spec updated to have the CR AUX RD interval match the EQ AUX RD +interval interpretation of DPCD 0000Eh/0220Eh for 8b/10b non-LTTPR mode +and LTTPR transparent mode cases. + +[How] +Update interpretation of DPCD 0000Eh/0220Eh for CR AUX RD interval +during 8b/10b link training. + +Reviewed-by: Michael Strauss +Reviewed-by: Wenjing Liu +Signed-off-by: George Shen +Signed-off-by: Zaeem Mohamed +Tested-by: Daniel Wheeler +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + .../display/dc/link/protocols/link_dp_training_8b_10b.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_8b_10b.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_8b_10b.c +index 3bdce32a85e3c..ae95ec48e5721 100644 +--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_8b_10b.c ++++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_8b_10b.c +@@ -36,7 +36,8 @@ + link->ctx->logger + + static int32_t get_cr_training_aux_rd_interval(struct dc_link *link, +- const struct dc_link_settings *link_settings) ++ const struct dc_link_settings *link_settings, ++ enum lttpr_mode lttpr_mode) + { + union training_aux_rd_interval training_rd_interval; + uint32_t wait_in_micro_secs = 100; +@@ -49,6 +50,8 @@ static int32_t get_cr_training_aux_rd_interval(struct dc_link *link, + DP_TRAINING_AUX_RD_INTERVAL, + (uint8_t *)&training_rd_interval, + sizeof(training_rd_interval)); ++ if (lttpr_mode != LTTPR_MODE_NON_TRANSPARENT) ++ wait_in_micro_secs = 400; + if (training_rd_interval.bits.TRAINIG_AUX_RD_INTERVAL) + wait_in_micro_secs = training_rd_interval.bits.TRAINIG_AUX_RD_INTERVAL * 4000; + } +@@ -110,7 +113,6 @@ void decide_8b_10b_training_settings( + */ + lt_settings->link_settings.link_spread = link->dp_ss_off ? + LINK_SPREAD_DISABLED : LINK_SPREAD_05_DOWNSPREAD_30KHZ; +- lt_settings->cr_pattern_time = get_cr_training_aux_rd_interval(link, link_setting); + lt_settings->eq_pattern_time = get_eq_training_aux_rd_interval(link, link_setting); + lt_settings->pattern_for_cr = decide_cr_training_pattern(link_setting); + lt_settings->pattern_for_eq = decide_eq_training_pattern(link, link_setting); +@@ -119,6 +121,7 @@ void decide_8b_10b_training_settings( + lt_settings->disallow_per_lane_settings = true; + lt_settings->always_match_dpcd_with_hw_lane_settings = true; + lt_settings->lttpr_mode = dp_decide_8b_10b_lttpr_mode(link); ++ lt_settings->cr_pattern_time = get_cr_training_aux_rd_interval(link, link_setting, lt_settings->lttpr_mode); + dp_hw_to_dpcd_lane_settings(lt_settings, lt_settings->hw_lane_settings, lt_settings->dpcd_lane_settings); + } + +-- +2.39.5 + diff --git a/queue-6.14/drm-amd-display-use-nominal-vblank-if-provided-inste.patch b/queue-6.14/drm-amd-display-use-nominal-vblank-if-provided-inste.patch new file mode 100644 index 0000000000..8ff89c5893 --- /dev/null +++ b/queue-6.14/drm-amd-display-use-nominal-vblank-if-provided-inste.patch @@ -0,0 +1,51 @@ +From 0af786cc9408dbba5afaa59b43f135f256bdeb6d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 Jan 2025 17:49:36 -0500 +Subject: drm/amd/display: Use Nominal vBlank If Provided Instead Of Capping It + +From: Austin Zheng + +[ Upstream commit 41df56b1fc24cc36fffb10e437385b3a49fbb5e2 ] + +[Why/How] +vBlank used to determine the max vStartup is based on the smallest between +the vblank provided by the timing and vblank in ip_caps. +Extra vblank time is not considered if the vblank provided by the timing ends +up being higher than what's defined by the ip_caps + +Use 1 less than the vblank size in case the timing is interlaced +so vstartup will always be less than vblank_nom. + +Reviewed-by: Dillon Varone +Signed-off-by: Austin Zheng +Signed-off-by: Wayne Lin +Tested-by: Daniel Wheeler +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + .../dc/dml2/dml21/src/dml2_core/dml2_core_dcn4_calcs.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_dcn4_calcs.c b/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_dcn4_calcs.c +index 913f33c31cf38..a72b4c05e1fbf 100644 +--- a/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_dcn4_calcs.c ++++ b/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_dcn4_calcs.c +@@ -3713,13 +3713,12 @@ static unsigned int CalculateMaxVStartup( + double line_time_us = (double)timing->h_total / ((double)timing->pixel_clock_khz / 1000); + unsigned int vblank_actual = timing->v_total - timing->v_active; + unsigned int vblank_nom_default_in_line = (unsigned int)math_floor2((double)vblank_nom_default_us / line_time_us, 1.0); +- unsigned int vblank_nom_input = (unsigned int)math_min2(timing->vblank_nom, vblank_nom_default_in_line); +- unsigned int vblank_avail = (vblank_nom_input == 0) ? vblank_nom_default_in_line : vblank_nom_input; ++ unsigned int vblank_avail = (timing->vblank_nom == 0) ? vblank_nom_default_in_line : (unsigned int)timing->vblank_nom; + + vblank_size = (unsigned int)math_min2(vblank_actual, vblank_avail); + + if (timing->interlaced && !ptoi_supported) +- max_vstartup_lines = (unsigned int)(math_floor2(vblank_size / 2.0, 1.0)); ++ max_vstartup_lines = (unsigned int)(math_floor2((vblank_size - 1) / 2.0, 1.0)); + else + max_vstartup_lines = vblank_size - (unsigned int)math_max2(1.0, math_ceil2(write_back_delay_us / line_time_us, 1.0)); + #ifdef __DML_VBA_DEBUG__ +-- +2.39.5 + diff --git a/queue-6.14/drm-amd-pm-fetch-current-power-limit-from-pmfw.patch b/queue-6.14/drm-amd-pm-fetch-current-power-limit-from-pmfw.patch new file mode 100644 index 0000000000..6898973a81 --- /dev/null +++ b/queue-6.14/drm-amd-pm-fetch-current-power-limit-from-pmfw.patch @@ -0,0 +1,35 @@ +From efd02a91000dab42c895ab5b4ee3d4d4748411da Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 18 Feb 2025 17:43:01 +0530 +Subject: drm/amd/pm: Fetch current power limit from PMFW + +From: Lijo Lazar + +[ Upstream commit b2a9e562dfa156bd53e62ce571f3f8f65d243f14 ] + +On SMU v13.0.12, always query the firmware to get the current power +limit as it could be updated through other means also. + +Signed-off-by: Lijo Lazar +Reviewed-by: Asad Kamal +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c +index ed9dac00ebfb1..f3f5b7dd15ccc 100644 +--- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c ++++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c +@@ -2802,6 +2802,7 @@ int smu_get_power_limit(void *handle, + switch (amdgpu_ip_version(adev, MP1_HWIP, 0)) { + case IP_VERSION(13, 0, 2): + case IP_VERSION(13, 0, 6): ++ case IP_VERSION(13, 0, 12): + case IP_VERSION(13, 0, 14): + case IP_VERSION(11, 0, 7): + case IP_VERSION(11, 0, 11): +-- +2.39.5 + diff --git a/queue-6.14/drm-amd-pm-skip-p2s-load-for-smu-v13.0.12.patch b/queue-6.14/drm-amd-pm-skip-p2s-load-for-smu-v13.0.12.patch new file mode 100644 index 0000000000..4e1c756054 --- /dev/null +++ b/queue-6.14/drm-amd-pm-skip-p2s-load-for-smu-v13.0.12.patch @@ -0,0 +1,38 @@ +From c02e63e0d9f6534a519ade21153b7052bebefd41 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 19 Dec 2024 19:16:37 +0800 +Subject: drm/amd/pm: Skip P2S load for SMU v13.0.12 + +From: Asad Kamal + +[ Upstream commit 1fb85819d629676f1d53f40c3fffa25a33a881e4 ] + +Skip P2S table load for SMU v13.0.12 + +Signed-off-by: Asad Kamal +Reviewed-by: Lijo Lazar +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git 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 +index da7bd9227afeb..5f2a824918e3b 100644 +--- 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 +@@ -450,8 +450,9 @@ static int smu_v13_0_6_init_microcode(struct smu_context *smu) + int var = (adev->pdev->device & 0xF); + char ucode_prefix[15]; + +- /* No need to load P2S tables in IOV mode */ +- if (amdgpu_sriov_vf(adev)) ++ /* No need to load P2S tables in IOV mode or for smu v13.0.12 */ ++ if (amdgpu_sriov_vf(adev) || ++ (amdgpu_ip_version(smu->adev, MP1_HWIP, 0) == IP_VERSION(13, 0, 12))) + return 0; + + if (!(adev->flags & AMD_IS_APU)) { +-- +2.39.5 + diff --git a/queue-6.14/drm-amdgpu-add-dce_v6_0_soft_reset-to-dce6.patch b/queue-6.14/drm-amdgpu-add-dce_v6_0_soft_reset-to-dce6.patch new file mode 100644 index 0000000000..bccf7bbdef --- /dev/null +++ b/queue-6.14/drm-amdgpu-add-dce_v6_0_soft_reset-to-dce6.patch @@ -0,0 +1,99 @@ +From 1c2c44642f12b5c84c61e60074e9611c759dd16a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 28 Feb 2025 23:11:20 -0500 +Subject: drm/amdgpu: add dce_v6_0_soft_reset() to DCE6 + +From: Alexandre Demers + +[ Upstream commit ab23db6d08efdda5d13d01a66c593d0e57f8917f ] + +DCE6 was missing soft reset, but it was easily identifiable under radeon. +This should be it, pretty much as it is done under DCE8 and DCE10. + +Signed-off-by: Alexandre Demers +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/amdgpu/dce_v6_0.c | 53 ++++++++++++++++++++++++++- + 1 file changed, 51 insertions(+), 2 deletions(-) + +diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c +index 915804a6a1d7d..ed5e06b677df1 100644 +--- a/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c ++++ b/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c +@@ -370,13 +370,41 @@ static u32 dce_v6_0_hpd_get_gpio_reg(struct amdgpu_device *adev) + return mmDC_GPIO_HPD_A; + } + ++static bool dce_v6_0_is_display_hung(struct amdgpu_device *adev) ++{ ++ u32 crtc_hung = 0; ++ u32 crtc_status[6]; ++ u32 i, j, tmp; ++ ++ for (i = 0; i < adev->mode_info.num_crtc; i++) { ++ if (RREG32(mmCRTC_CONTROL + crtc_offsets[i]) & CRTC_CONTROL__CRTC_MASTER_EN_MASK) { ++ crtc_status[i] = RREG32(mmCRTC_STATUS_HV_COUNT + crtc_offsets[i]); ++ crtc_hung |= (1 << i); ++ } ++ } ++ ++ for (j = 0; j < 10; j++) { ++ for (i = 0; i < adev->mode_info.num_crtc; i++) { ++ if (crtc_hung & (1 << i)) { ++ tmp = RREG32(mmCRTC_STATUS_HV_COUNT + crtc_offsets[i]); ++ if (tmp != crtc_status[i]) ++ crtc_hung &= ~(1 << i); ++ } ++ } ++ if (crtc_hung == 0) ++ return false; ++ udelay(100); ++ } ++ ++ return true; ++} ++ + static void dce_v6_0_set_vga_render_state(struct amdgpu_device *adev, + bool render) + { + if (!render) + WREG32(mmVGA_RENDER_CONTROL, + RREG32(mmVGA_RENDER_CONTROL) & VGA_VSTATUS_CNTL); +- + } + + static int dce_v6_0_get_num_crtc(struct amdgpu_device *adev) +@@ -2872,7 +2900,28 @@ static bool dce_v6_0_is_idle(void *handle) + + static int dce_v6_0_soft_reset(struct amdgpu_ip_block *ip_block) + { +- DRM_INFO("xxxx: dce_v6_0_soft_reset --- no impl!!\n"); ++ u32 srbm_soft_reset = 0, tmp; ++ struct amdgpu_device *adev = ip_block->adev; ++ ++ if (dce_v6_0_is_display_hung(adev)) ++ srbm_soft_reset |= SRBM_SOFT_RESET__SOFT_RESET_DC_MASK; ++ ++ if (srbm_soft_reset) { ++ tmp = RREG32(mmSRBM_SOFT_RESET); ++ tmp |= srbm_soft_reset; ++ dev_info(adev->dev, "SRBM_SOFT_RESET=0x%08X\n", tmp); ++ WREG32(mmSRBM_SOFT_RESET, tmp); ++ tmp = RREG32(mmSRBM_SOFT_RESET); ++ ++ udelay(50); ++ ++ tmp &= ~srbm_soft_reset; ++ WREG32(mmSRBM_SOFT_RESET, tmp); ++ tmp = RREG32(mmSRBM_SOFT_RESET); ++ ++ /* Wait a little for things to settle down */ ++ udelay(50); ++ } + return 0; + } + +-- +2.39.5 + diff --git a/queue-6.14/drm-amdgpu-add-offset-normalization-in-vcn-v5.0.1.patch b/queue-6.14/drm-amdgpu-add-offset-normalization-in-vcn-v5.0.1.patch new file mode 100644 index 0000000000..42cdb436f4 --- /dev/null +++ b/queue-6.14/drm-amdgpu-add-offset-normalization-in-vcn-v5.0.1.patch @@ -0,0 +1,144 @@ +From 409b0097dfe7df3c64aa2be27a4250c00e97a66f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 20 Feb 2025 13:40:31 +0530 +Subject: drm/amdgpu: Add offset normalization in VCN v5.0.1 + +From: Lijo Lazar + +[ Upstream commit 0b9647d40ef82837d5025de6daad64db775ea1c5 ] + +VCN v5.0.1 also will need register offset normalization. Reuse the logic +from VCN v4.0.3. Also, avoid HDP flush similar to VCN v4.0.3 + +Signed-off-by: Lijo Lazar +Reviewed-by: Hawking Zhang +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c | 14 ++++++++------ + drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.h | 9 +++++++++ + drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c | 20 +++++++++++--------- + 3 files changed, 28 insertions(+), 15 deletions(-) + +diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c +index a2d1a4b2f03a5..855da1149c5c8 100644 +--- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c ++++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c +@@ -31,6 +31,7 @@ + #include "soc15d.h" + #include "soc15_hw_ip.h" + #include "vcn_v2_0.h" ++#include "vcn_v4_0_3.h" + #include "mmsch_v4_0_3.h" + + #include "vcn/vcn_4_0_3_offset.h" +@@ -1462,8 +1463,8 @@ static uint64_t vcn_v4_0_3_unified_ring_get_wptr(struct amdgpu_ring *ring) + regUVD_RB_WPTR); + } + +-static void vcn_v4_0_3_enc_ring_emit_reg_wait(struct amdgpu_ring *ring, uint32_t reg, +- uint32_t val, uint32_t mask) ++void vcn_v4_0_3_enc_ring_emit_reg_wait(struct amdgpu_ring *ring, uint32_t reg, ++ uint32_t val, uint32_t mask) + { + /* Use normalized offsets when required */ + if (vcn_v4_0_3_normalizn_reqd(ring->adev)) +@@ -1475,7 +1476,8 @@ static void vcn_v4_0_3_enc_ring_emit_reg_wait(struct amdgpu_ring *ring, uint32_t + amdgpu_ring_write(ring, val); + } + +-static void vcn_v4_0_3_enc_ring_emit_wreg(struct amdgpu_ring *ring, uint32_t reg, uint32_t val) ++void vcn_v4_0_3_enc_ring_emit_wreg(struct amdgpu_ring *ring, uint32_t reg, ++ uint32_t val) + { + /* Use normalized offsets when required */ + if (vcn_v4_0_3_normalizn_reqd(ring->adev)) +@@ -1486,8 +1488,8 @@ static void vcn_v4_0_3_enc_ring_emit_wreg(struct amdgpu_ring *ring, uint32_t reg + amdgpu_ring_write(ring, val); + } + +-static void vcn_v4_0_3_enc_ring_emit_vm_flush(struct amdgpu_ring *ring, +- unsigned int vmid, uint64_t pd_addr) ++void vcn_v4_0_3_enc_ring_emit_vm_flush(struct amdgpu_ring *ring, ++ unsigned int vmid, uint64_t pd_addr) + { + struct amdgpu_vmhub *hub = &ring->adev->vmhub[ring->vm_hub]; + +@@ -1499,7 +1501,7 @@ static void vcn_v4_0_3_enc_ring_emit_vm_flush(struct amdgpu_ring *ring, + lower_32_bits(pd_addr), 0xffffffff); + } + +-static void vcn_v4_0_3_ring_emit_hdp_flush(struct amdgpu_ring *ring) ++void vcn_v4_0_3_ring_emit_hdp_flush(struct amdgpu_ring *ring) + { + /* VCN engine access for HDP flush doesn't work when RRMT is enabled. + * This is a workaround to avoid any HDP flush through VCN ring. +diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.h b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.h +index 0b046114373ae..03572a1d0c9cb 100644 +--- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.h ++++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.h +@@ -26,4 +26,13 @@ + + extern const struct amdgpu_ip_block_version vcn_v4_0_3_ip_block; + ++void vcn_v4_0_3_enc_ring_emit_reg_wait(struct amdgpu_ring *ring, uint32_t reg, ++ uint32_t val, uint32_t mask); ++ ++void vcn_v4_0_3_enc_ring_emit_wreg(struct amdgpu_ring *ring, uint32_t reg, ++ uint32_t val); ++void vcn_v4_0_3_enc_ring_emit_vm_flush(struct amdgpu_ring *ring, ++ unsigned int vmid, uint64_t pd_addr); ++void vcn_v4_0_3_ring_emit_hdp_flush(struct amdgpu_ring *ring); ++ + #endif /* __VCN_V4_0_3_H__ */ +diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c +index cdbc10d7c9fb7..f893a84282832 100644 +--- a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c ++++ b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c +@@ -29,6 +29,7 @@ + #include "soc15d.h" + #include "soc15_hw_ip.h" + #include "vcn_v2_0.h" ++#include "vcn_v4_0_3.h" + + #include "vcn/vcn_5_0_0_offset.h" + #include "vcn/vcn_5_0_0_sh_mask.h" +@@ -905,16 +906,17 @@ static const struct amdgpu_ring_funcs vcn_v5_0_1_unified_ring_vm_funcs = { + .get_rptr = vcn_v5_0_1_unified_ring_get_rptr, + .get_wptr = vcn_v5_0_1_unified_ring_get_wptr, + .set_wptr = vcn_v5_0_1_unified_ring_set_wptr, +- .emit_frame_size = +- SOC15_FLUSH_GPU_TLB_NUM_WREG * 3 + +- SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT * 4 + +- 4 + /* vcn_v2_0_enc_ring_emit_vm_flush */ +- 5 + 5 + /* vcn_v2_0_enc_ring_emit_fence x2 vm fence */ +- 1, /* vcn_v2_0_enc_ring_insert_end */ ++ .emit_frame_size = SOC15_FLUSH_GPU_TLB_NUM_WREG * 3 + ++ SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT * 4 + ++ 4 + /* vcn_v2_0_enc_ring_emit_vm_flush */ ++ 5 + ++ 5 + /* vcn_v2_0_enc_ring_emit_fence x2 vm fence */ ++ 1, /* vcn_v2_0_enc_ring_insert_end */ + .emit_ib_size = 5, /* vcn_v2_0_enc_ring_emit_ib */ + .emit_ib = vcn_v2_0_enc_ring_emit_ib, + .emit_fence = vcn_v2_0_enc_ring_emit_fence, +- .emit_vm_flush = vcn_v2_0_enc_ring_emit_vm_flush, ++ .emit_vm_flush = vcn_v4_0_3_enc_ring_emit_vm_flush, ++ .emit_hdp_flush = vcn_v4_0_3_ring_emit_hdp_flush, + .test_ring = amdgpu_vcn_enc_ring_test_ring, + .test_ib = amdgpu_vcn_unified_ring_test_ib, + .insert_nop = amdgpu_ring_insert_nop, +@@ -922,8 +924,8 @@ static const struct amdgpu_ring_funcs vcn_v5_0_1_unified_ring_vm_funcs = { + .pad_ib = amdgpu_ring_generic_pad_ib, + .begin_use = amdgpu_vcn_ring_begin_use, + .end_use = amdgpu_vcn_ring_end_use, +- .emit_wreg = vcn_v2_0_enc_ring_emit_wreg, +- .emit_reg_wait = vcn_v2_0_enc_ring_emit_reg_wait, ++ .emit_wreg = vcn_v4_0_3_enc_ring_emit_wreg, ++ .emit_reg_wait = vcn_v4_0_3_enc_ring_emit_reg_wait, + .emit_reg_write_reg_wait = amdgpu_ring_emit_reg_write_reg_wait_helper, + }; + +-- +2.39.5 + diff --git a/queue-6.14/drm-amdgpu-adjust-drm_firmware_drivers_only-handling.patch b/queue-6.14/drm-amdgpu-adjust-drm_firmware_drivers_only-handling.patch new file mode 100644 index 0000000000..ad07958c10 --- /dev/null +++ b/queue-6.14/drm-amdgpu-adjust-drm_firmware_drivers_only-handling.patch @@ -0,0 +1,65 @@ +From 21d69279617ffebaa8e8d958b4df338c6e1ff3c1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 13 Mar 2025 20:52:38 -0400 +Subject: drm/amdgpu: adjust drm_firmware_drivers_only() handling + +From: Alex Deucher + +[ Upstream commit e00e5c223878a60e391e5422d173c3382d378f87 ] + +Move to probe so we can check the PCI device type and +only apply the drm_firmware_drivers_only() check for +PCI DISPLAY classes. Also add a module parameter to +override the nomodeset kernel parameter as a workaround +for platforms that have this hardcoded on their kernel +command lines. + +Reviewed-by: Kent Russell +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 14 ++++++++++++++ + 1 file changed, 14 insertions(+) + +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +index bb8ab25ea76ad..e4ce33e69a48b 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +@@ -173,6 +173,7 @@ uint amdgpu_sdma_phase_quantum = 32; + char *amdgpu_disable_cu; + char *amdgpu_virtual_display; + bool enforce_isolation; ++int amdgpu_modeset = -1; + + /* Specifies the default granularity for SVM, used in buffer + * migration and restoration of backing memory when handling +@@ -1033,6 +1034,13 @@ module_param_named(user_partt_mode, amdgpu_user_partt_mode, uint, 0444); + module_param(enforce_isolation, bool, 0444); + MODULE_PARM_DESC(enforce_isolation, "enforce process isolation between graphics and compute . enforce_isolation = on"); + ++/** ++ * DOC: modeset (int) ++ * Override nomodeset (1 = override, -1 = auto). The default is -1 (auto). ++ */ ++MODULE_PARM_DESC(modeset, "Override nomodeset (1 = enable, -1 = auto)"); ++module_param_named(modeset, amdgpu_modeset, int, 0444); ++ + /** + * DOC: seamless (int) + * Seamless boot will keep the image on the screen during the boot process. +@@ -2244,6 +2252,12 @@ static int amdgpu_pci_probe(struct pci_dev *pdev, + int ret, retry = 0, i; + bool supports_atomic = false; + ++ if ((pdev->class >> 8) == PCI_CLASS_DISPLAY_VGA || ++ (pdev->class >> 8) == PCI_CLASS_DISPLAY_OTHER) { ++ if (drm_firmware_drivers_only() && amdgpu_modeset == -1) ++ return -EINVAL; ++ } ++ + /* skip devices which are owned by radeon */ + for (i = 0; i < ARRAY_SIZE(amdgpu_unsupported_pciidlist); i++) { + if (amdgpu_unsupported_pciidlist[i] == pdev->device) +-- +2.39.5 + diff --git a/queue-6.14/drm-amdgpu-allow-p2p-access-through-xgmi.patch b/queue-6.14/drm-amdgpu-allow-p2p-access-through-xgmi.patch new file mode 100644 index 0000000000..f85afb5968 --- /dev/null +++ b/queue-6.14/drm-amdgpu-allow-p2p-access-through-xgmi.patch @@ -0,0 +1,87 @@ +From 8216a1e33ef74729288036e44a874b3c8df2aff3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 16 Apr 2025 00:19:13 -0400 +Subject: drm/amdgpu: Allow P2P access through XGMI +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Felix Kuehling + +[ Upstream commit a92741e72f91b904c1d8c3d409ed8dbe9c1f2b26 ] + +If peer memory is accessible through XGMI, allow leaving it in VRAM +rather than forcing its migration to GTT on DMABuf attachment. + +Signed-off-by: Felix Kuehling +Tested-by: Hao (Claire) Zhou +Reviewed-by: Christian König +Signed-off-by: Alex Deucher +(cherry picked from commit 372c8d72c3680fdea3fbb2d6b089f76b4a6d596a) +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c | 30 ++++++++++++++++++++- + 1 file changed, 29 insertions(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c +index c9842a0e2a1cd..cb043296f9aec 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c +@@ -43,6 +43,29 @@ + #include + #include + ++static const struct dma_buf_attach_ops amdgpu_dma_buf_attach_ops; ++ ++/** ++ * dma_buf_attach_adev - Helper to get adev of an attachment ++ * ++ * @attach: attachment ++ * ++ * Returns: ++ * A struct amdgpu_device * if the attaching device is an amdgpu device or ++ * partition, NULL otherwise. ++ */ ++static struct amdgpu_device *dma_buf_attach_adev(struct dma_buf_attachment *attach) ++{ ++ if (attach->importer_ops == &amdgpu_dma_buf_attach_ops) { ++ struct drm_gem_object *obj = attach->importer_priv; ++ struct amdgpu_bo *bo = gem_to_amdgpu_bo(obj); ++ ++ return amdgpu_ttm_adev(bo->tbo.bdev); ++ } ++ ++ return NULL; ++} ++ + /** + * amdgpu_dma_buf_attach - &dma_buf_ops.attach implementation + * +@@ -54,11 +77,13 @@ + static int amdgpu_dma_buf_attach(struct dma_buf *dmabuf, + struct dma_buf_attachment *attach) + { ++ struct amdgpu_device *attach_adev = dma_buf_attach_adev(attach); + struct drm_gem_object *obj = dmabuf->priv; + struct amdgpu_bo *bo = gem_to_amdgpu_bo(obj); + struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev); + +- if (pci_p2pdma_distance(adev->pdev, attach->dev, false) < 0) ++ if (!amdgpu_dmabuf_is_xgmi_accessible(attach_adev, bo) && ++ pci_p2pdma_distance(adev->pdev, attach->dev, false) < 0) + attach->peer2peer = false; + + amdgpu_vm_bo_update_shared(bo); +@@ -459,6 +484,9 @@ bool amdgpu_dmabuf_is_xgmi_accessible(struct amdgpu_device *adev, + struct drm_gem_object *obj = &bo->tbo.base; + struct drm_gem_object *gobj; + ++ if (!adev) ++ return false; ++ + if (obj->import_attach) { + struct dma_buf *dma_buf = obj->import_attach->dmabuf; + +-- +2.39.5 + diff --git a/queue-6.14/drm-amdgpu-avoid-hdp-flush-on-jpeg-v5.0.1.patch b/queue-6.14/drm-amdgpu-avoid-hdp-flush-on-jpeg-v5.0.1.patch new file mode 100644 index 0000000000..79a6521008 --- /dev/null +++ b/queue-6.14/drm-amdgpu-avoid-hdp-flush-on-jpeg-v5.0.1.patch @@ -0,0 +1,62 @@ +From c1e8ee5df7c5571a5a7630e80c44aa84f9b2e052 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 20 Feb 2025 13:38:06 +0530 +Subject: drm/amdgpu: Avoid HDP flush on JPEG v5.0.1 + +From: Lijo Lazar + +[ Upstream commit a734a717dcfe1ce618301775034e598cb456665b ] + +Similar to JPEG v4.0.3, HDP flush shouldn't be performed by JPEG engine. +Keep it empty. + +Signed-off-by: Lijo Lazar +Reviewed-by: Hawking Zhang +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c | 2 +- + drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.h | 1 + + drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_1.c | 1 + + 3 files changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c +index 88f9771c16869..b2904ee494e04 100644 +--- a/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c ++++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c +@@ -637,7 +637,7 @@ static uint64_t jpeg_v4_0_3_dec_ring_get_wptr(struct amdgpu_ring *ring) + ring->pipe ? (0x40 * ring->pipe - 0xc80) : 0); + } + +-static void jpeg_v4_0_3_ring_emit_hdp_flush(struct amdgpu_ring *ring) ++void jpeg_v4_0_3_ring_emit_hdp_flush(struct amdgpu_ring *ring) + { + /* JPEG engine access for HDP flush doesn't work when RRMT is enabled. + * This is a workaround to avoid any HDP flush through JPEG ring. +diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.h b/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.h +index 747a3e5f68564..a90bf370a0025 100644 +--- a/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.h ++++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.h +@@ -56,6 +56,7 @@ void jpeg_v4_0_3_dec_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64 seq + unsigned int flags); + void jpeg_v4_0_3_dec_ring_emit_vm_flush(struct amdgpu_ring *ring, + unsigned int vmid, uint64_t pd_addr); ++void jpeg_v4_0_3_ring_emit_hdp_flush(struct amdgpu_ring *ring); + void jpeg_v4_0_3_dec_ring_nop(struct amdgpu_ring *ring, uint32_t count); + void jpeg_v4_0_3_dec_ring_insert_start(struct amdgpu_ring *ring); + void jpeg_v4_0_3_dec_ring_insert_end(struct amdgpu_ring *ring); +diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_1.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_1.c +index 40d4c32a8c2a6..f2cc11b3fd68b 100644 +--- a/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_1.c ++++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_1.c +@@ -655,6 +655,7 @@ static const struct amdgpu_ring_funcs jpeg_v5_0_1_dec_ring_vm_funcs = { + .emit_ib = jpeg_v4_0_3_dec_ring_emit_ib, + .emit_fence = jpeg_v4_0_3_dec_ring_emit_fence, + .emit_vm_flush = jpeg_v4_0_3_dec_ring_emit_vm_flush, ++ .emit_hdp_flush = jpeg_v4_0_3_ring_emit_hdp_flush, + .test_ring = amdgpu_jpeg_dec_ring_test_ring, + .test_ib = amdgpu_jpeg_dec_ring_test_ib, + .insert_nop = jpeg_v4_0_3_dec_ring_nop, +-- +2.39.5 + diff --git a/queue-6.14/drm-amdgpu-discovery-check-ip_discovery-fw-file-avai.patch b/queue-6.14/drm-amdgpu-discovery-check-ip_discovery-fw-file-avai.patch new file mode 100644 index 0000000000..c9e8737a6f --- /dev/null +++ b/queue-6.14/drm-amdgpu-discovery-check-ip_discovery-fw-file-avai.patch @@ -0,0 +1,92 @@ +From 0fe1af026c0d0bc2857fba33bd7eed8e2da7c281 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 27 Feb 2025 10:39:27 +0800 +Subject: drm/amdgpu/discovery: check ip_discovery fw file available + +From: Flora Cui + +[ Upstream commit 017fbb6690c2245b1b4ef39b66c79d2990fe63dd ] + +Signed-off-by: Flora Cui +Reviewed-by: Alex Deucher +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c | 31 ++++++++++--------- + 1 file changed, 16 insertions(+), 15 deletions(-) + +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c +index 949d74eff2946..6a6dc15273dc7 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c +@@ -113,8 +113,7 @@ + #include "amdgpu_isp.h" + #endif + +-#define FIRMWARE_IP_DISCOVERY "amdgpu/ip_discovery.bin" +-MODULE_FIRMWARE(FIRMWARE_IP_DISCOVERY); ++MODULE_FIRMWARE("amdgpu/ip_discovery.bin"); + + #define mmIP_DISCOVERY_VERSION 0x16A00 + #define mmRCC_CONFIG_MEMSIZE 0xde3 +@@ -297,21 +296,13 @@ static int amdgpu_discovery_read_binary_from_mem(struct amdgpu_device *adev, + return ret; + } + +-static int amdgpu_discovery_read_binary_from_file(struct amdgpu_device *adev, uint8_t *binary) ++static int amdgpu_discovery_read_binary_from_file(struct amdgpu_device *adev, ++ uint8_t *binary, ++ const char *fw_name) + { + const struct firmware *fw; +- const char *fw_name; + int r; + +- switch (amdgpu_discovery) { +- case 2: +- fw_name = FIRMWARE_IP_DISCOVERY; +- break; +- default: +- dev_warn(adev->dev, "amdgpu_discovery is not set properly\n"); +- return -EINVAL; +- } +- + r = request_firmware(&fw, fw_name, adev->dev); + if (r) { + dev_err(adev->dev, "can't load firmware \"%s\"\n", +@@ -404,10 +395,19 @@ static int amdgpu_discovery_verify_npsinfo(struct amdgpu_device *adev, + return 0; + } + ++static const char *amdgpu_discovery_get_fw_name(struct amdgpu_device *adev) ++{ ++ if (amdgpu_discovery == 2) ++ return "amdgpu/ip_discovery.bin"; ++ ++ return NULL; ++} ++ + static int amdgpu_discovery_init(struct amdgpu_device *adev) + { + struct table_info *info; + struct binary_header *bhdr; ++ const char *fw_name; + uint16_t offset; + uint16_t size; + uint16_t checksum; +@@ -419,9 +419,10 @@ static int amdgpu_discovery_init(struct amdgpu_device *adev) + return -ENOMEM; + + /* Read from file if it is the preferred option */ +- if (amdgpu_discovery == 2) { ++ fw_name = amdgpu_discovery_get_fw_name(adev); ++ if (fw_name != NULL) { + dev_info(adev->dev, "use ip discovery information from file"); +- r = amdgpu_discovery_read_binary_from_file(adev, adev->mman.discovery_bin); ++ r = amdgpu_discovery_read_binary_from_file(adev, adev->mman.discovery_bin, fw_name); + + if (r) { + dev_err(adev->dev, "failed to read ip discovery binary from file\n"); +-- +2.39.5 + diff --git a/queue-6.14/drm-amdgpu-do-not-program-agp-bar-regs-under-sriov-i.patch b/queue-6.14/drm-amdgpu-do-not-program-agp-bar-regs-under-sriov-i.patch new file mode 100644 index 0000000000..fb819f4427 --- /dev/null +++ b/queue-6.14/drm-amdgpu-do-not-program-agp-bar-regs-under-sriov-i.patch @@ -0,0 +1,45 @@ +From 22ce2f5ee68442539d6f766f0f77e73029340b06 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 13 Feb 2025 18:38:28 -0500 +Subject: drm/amdgpu: Do not program AGP BAR regs under SRIOV in gfxhub_v1_0.c + +From: Victor Lu + +[ Upstream commit 057fef20b8401110a7bc1c2fe9d804a8a0bf0d24 ] + +SRIOV VF does not have write access to AGP BAR regs. +Skip the writes to avoid a dmesg warning. + +Signed-off-by: Victor Lu +Acked-by: Alex Deucher +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/amdgpu/gfxhub_v1_0.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_0.c b/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_0.c +index 0e3ddea7b8e0f..a7bfc9f41d0e3 100644 +--- a/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_0.c ++++ b/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_0.c +@@ -92,12 +92,12 @@ static void gfxhub_v1_0_init_system_aperture_regs(struct amdgpu_device *adev) + { + uint64_t value; + +- /* Program the AGP BAR */ +- WREG32_SOC15_RLC(GC, 0, mmMC_VM_AGP_BASE, 0); +- WREG32_SOC15_RLC(GC, 0, mmMC_VM_AGP_BOT, adev->gmc.agp_start >> 24); +- WREG32_SOC15_RLC(GC, 0, mmMC_VM_AGP_TOP, adev->gmc.agp_end >> 24); +- + if (!amdgpu_sriov_vf(adev) || adev->asic_type <= CHIP_VEGA10) { ++ /* Program the AGP BAR */ ++ WREG32_SOC15_RLC(GC, 0, mmMC_VM_AGP_BASE, 0); ++ WREG32_SOC15_RLC(GC, 0, mmMC_VM_AGP_BOT, adev->gmc.agp_start >> 24); ++ WREG32_SOC15_RLC(GC, 0, mmMC_VM_AGP_TOP, adev->gmc.agp_end >> 24); ++ + /* Program the system aperture low logical page number. */ + WREG32_SOC15_RLC(GC, 0, mmMC_VM_SYSTEM_APERTURE_LOW_ADDR, + min(adev->gmc.fb_start, adev->gmc.agp_start) >> 18); +-- +2.39.5 + diff --git a/queue-6.14/drm-amdgpu-don-t-free-conflicting-apertures-for-non-.patch b/queue-6.14/drm-amdgpu-don-t-free-conflicting-apertures-for-non-.patch new file mode 100644 index 0000000000..d38295cd6b --- /dev/null +++ b/queue-6.14/drm-amdgpu-don-t-free-conflicting-apertures-for-non-.patch @@ -0,0 +1,49 @@ +From 084bdf49bfdc76f7187c5a71c16bfb2cd47847e7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 25 Sep 2024 10:29:31 -0400 +Subject: drm/amdgpu: don't free conflicting apertures for non-display devices + +From: Alex Deucher + +[ Upstream commit 9deacd6c55f1b31e5ab20db79df2e14ac480203c ] + +PCI_CLASS_ACCELERATOR_PROCESSING devices won't ever be +the sysfb, so there is no need to free conflicting +apertures. + +Reviewed-by: Kent Russell +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 15 +++++++++++---- + 1 file changed, 11 insertions(+), 4 deletions(-) + +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +index ea50f82b547d9..28190b0ac5fca 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +@@ -4370,10 +4370,17 @@ int amdgpu_device_init(struct amdgpu_device *adev, + if (r) + return r; + +- /* Get rid of things like offb */ +- r = aperture_remove_conflicting_pci_devices(adev->pdev, amdgpu_kms_driver.name); +- if (r) +- return r; ++ /* ++ * No need to remove conflicting FBs for non-display class devices. ++ * This prevents the sysfb from being freed accidently. ++ */ ++ if ((pdev->class >> 8) == PCI_CLASS_DISPLAY_VGA || ++ (pdev->class >> 8) == PCI_CLASS_DISPLAY_OTHER) { ++ /* Get rid of things like offb */ ++ r = aperture_remove_conflicting_pci_devices(adev->pdev, amdgpu_kms_driver.name); ++ if (r) ++ return r; ++ } + + /* Enable TMZ based on IP_VERSION */ + amdgpu_gmc_tmz_set(adev); +-- +2.39.5 + diff --git a/queue-6.14/drm-amdgpu-enlarge-the-vbios-binary-size-limit.patch b/queue-6.14/drm-amdgpu-enlarge-the-vbios-binary-size-limit.patch new file mode 100644 index 0000000000..da327e0f9a --- /dev/null +++ b/queue-6.14/drm-amdgpu-enlarge-the-vbios-binary-size-limit.patch @@ -0,0 +1,36 @@ +From d5db35a354d56558989a1b8bf52efe072c365ac9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 19 Nov 2024 15:58:39 +0800 +Subject: drm/amdgpu: enlarge the VBIOS binary size limit + +From: Shiwu Zhang + +[ Upstream commit 667b96134c9e206aebe40985650bf478935cbe04 ] + +Some chips have a larger VBIOS file so raise the size limit to support +the flashing tool. + +Signed-off-by: Shiwu Zhang +Reviewed-by: Hawking Zhang +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c +index 665cc277cdc05..6dded11a23acf 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c +@@ -44,7 +44,7 @@ + #include "amdgpu_securedisplay.h" + #include "amdgpu_atomfirmware.h" + +-#define AMD_VBIOS_FILE_MAX_SIZE_B (1024*1024*3) ++#define AMD_VBIOS_FILE_MAX_SIZE_B (1024*1024*16) + + static int psp_load_smu_fw(struct psp_context *psp); + static int psp_rap_terminate(struct psp_context *psp); +-- +2.39.5 + diff --git a/queue-6.14/drm-amdgpu-fix-missing-drain-retry-fault-the-last-en.patch b/queue-6.14/drm-amdgpu-fix-missing-drain-retry-fault-the-last-en.patch new file mode 100644 index 0000000000..714ad1a8b7 --- /dev/null +++ b/queue-6.14/drm-amdgpu-fix-missing-drain-retry-fault-the-last-en.patch @@ -0,0 +1,55 @@ +From bbdc9428e1903fad5f65a378b232d64db661bb44 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 3 Mar 2025 15:10:22 +0800 +Subject: drm/amdgpu: Fix missing drain retry fault the last entry + +From: Emily Deng + +[ Upstream commit fe2fa3be3d59ba67d6de54a0064441ec233cb50c ] + +While the entry get in svm_range_unmap_from_cpu is the last entry, and +the entry is page fault, it also need to be dropped. So for equal case, +it also need to be dropped. + +v2: +Only modify the svm_range_restore_pages. + +Signed-off-by: Emily Deng +Reviewed-by: Xiaogang Chen +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/amdgpu/amdgpu_ih.h | 3 +++ + drivers/gpu/drm/amd/amdkfd/kfd_svm.c | 2 +- + 2 files changed, 4 insertions(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ih.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ih.h +index 7d4395a5d8ac9..b0a88f92cd821 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ih.h ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ih.h +@@ -78,6 +78,9 @@ struct amdgpu_ih_ring { + #define amdgpu_ih_ts_after(t1, t2) \ + (((int64_t)((t2) << 16) - (int64_t)((t1) << 16)) > 0LL) + ++#define amdgpu_ih_ts_after_or_equal(t1, t2) \ ++ (((int64_t)((t2) << 16) - (int64_t)((t1) << 16)) >= 0LL) ++ + /* provided by the ih block */ + struct amdgpu_ih_funcs { + /* ring read/write ptr handling, called from interrupt context */ +diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c +index d1cf9dd352904..47189453b20c3 100644 +--- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c ++++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c +@@ -3024,7 +3024,7 @@ svm_range_restore_pages(struct amdgpu_device *adev, unsigned int pasid, + + /* check if this page fault time stamp is before svms->checkpoint_ts */ + if (svms->checkpoint_ts[gpuidx] != 0) { +- if (amdgpu_ih_ts_after(ts, svms->checkpoint_ts[gpuidx])) { ++ if (amdgpu_ih_ts_after_or_equal(ts, svms->checkpoint_ts[gpuidx])) { + pr_debug("draining retry fault, drop fault 0x%llx\n", addr); + r = -EAGAIN; + goto out_unlock_svms; +-- +2.39.5 + diff --git a/queue-6.14/drm-amdgpu-gfx10-add-cleaner-shader-for-gfx10.1.10.patch b/queue-6.14/drm-amdgpu-gfx10-add-cleaner-shader-for-gfx10.1.10.patch new file mode 100644 index 0000000000..855800a0d1 --- /dev/null +++ b/queue-6.14/drm-amdgpu-gfx10-add-cleaner-shader-for-gfx10.1.10.patch @@ -0,0 +1,263 @@ +From a468fc121bf5b746da2eec75c8811be27f9a3c47 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Jan 2025 12:32:07 +0530 +Subject: drm/amdgpu/gfx10: Add cleaner shader for GFX10.1.10 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Srinivasan Shanmugam + +[ Upstream commit 25961bad9212476983c570438366e1f5e9a9cf21 ] + +This commit adds the cleaner shader microcode for GFX10.1.0 GPUs. The +cleaner shader is a piece of GPU code that is used to clear or +initialize certain GPU resources, such as Local Data Share (LDS), Vector +General Purpose Registers (VGPRs), and Scalar General Purpose Registers +(SGPRs). + +Clearing these resources is important for ensuring data isolation +between different workloads running on the GPU. Without the cleaner +shader, residual data from a previous workload could potentially be +accessed by a subsequent workload, leading to data leaks and incorrect +computation results. + +The cleaner shader microcode is represented as an array of 32-bit words +(`gfx_10_1_0_cleaner_shader_hex`). This array is the binary +representation of the cleaner shader code, which is written in a +low-level GPU instruction set. + +When the cleaner shader feature is enabled, the AMDGPU driver loads this +array into a specific location in the GPU memory. The GPU then reads +this memory location to fetch and execute the cleaner shader +instructions. + +The cleaner shader is executed automatically by the GPU at the end of +each workload, before the next workload starts. This ensures that all +GPU resources are in a clean state before the start of each workload. + +This addition is part of the cleaner shader feature implementation. The +cleaner shader feature helps resource utilization by cleaning up GPU +resources after they are used. It also enhances security and reliability +by preventing data leaks between workloads. + +Cc: Christian König +Cc: Alex Deucher +Signed-off-by: Srinivasan Shanmugam +Suggested-by: Alex Deucher +Reviewed-by: Alex Deucher +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c | 14 ++ + .../drm/amd/amdgpu/gfx_v10_0_cleaner_shader.h | 35 +++++ + .../amdgpu/gfx_v10_1_10_cleaner_shader.asm | 126 ++++++++++++++++++ + 3 files changed, 175 insertions(+) + create mode 100644 drivers/gpu/drm/amd/amdgpu/gfx_v10_1_10_cleaner_shader.asm + +diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c +index 1f32c531f610e..09178d56afbf6 100644 +--- a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c ++++ b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c +@@ -4739,6 +4739,20 @@ static int gfx_v10_0_sw_init(struct amdgpu_ip_block *ip_block) + break; + } + switch (amdgpu_ip_version(adev, GC_HWIP, 0)) { ++ case IP_VERSION(10, 1, 10): ++ adev->gfx.cleaner_shader_ptr = gfx_10_1_10_cleaner_shader_hex; ++ adev->gfx.cleaner_shader_size = sizeof(gfx_10_1_10_cleaner_shader_hex); ++ if (adev->gfx.me_fw_version >= 101 && ++ adev->gfx.pfp_fw_version >= 158 && ++ adev->gfx.mec_fw_version >= 152) { ++ adev->gfx.enable_cleaner_shader = true; ++ r = amdgpu_gfx_cleaner_shader_sw_init(adev, adev->gfx.cleaner_shader_size); ++ if (r) { ++ adev->gfx.enable_cleaner_shader = false; ++ dev_err(adev->dev, "Failed to initialize cleaner shader\n"); ++ } ++ } ++ break; + case IP_VERSION(10, 3, 0): + case IP_VERSION(10, 3, 2): + case IP_VERSION(10, 3, 4): +diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0_cleaner_shader.h b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0_cleaner_shader.h +index 663c2572d440a..5255378af53c0 100644 +--- a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0_cleaner_shader.h ++++ b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0_cleaner_shader.h +@@ -21,6 +21,41 @@ + * OTHER DEALINGS IN THE SOFTWARE. + */ + ++/* Define the cleaner shader gfx_10_1_10 */ ++static const u32 gfx_10_1_10_cleaner_shader_hex[] = { ++ 0xb0804004, 0xbf8a0000, ++ 0xbf068100, 0xbf840023, ++ 0xbe8203b8, 0xbefc0380, ++ 0x7e008480, 0x7e028480, ++ 0x7e048480, 0x7e068480, ++ 0x7e088480, 0x7e0a8480, ++ 0x7e0c8480, 0x7e0e8480, ++ 0xbefc0302, 0x80828802, ++ 0xbf84fff5, 0xbe8203ff, ++ 0x80000000, 0x87020102, ++ 0xbf840012, 0xbefe03c1, ++ 0xbeff03c1, 0xd7650001, ++ 0x0001007f, 0xd7660001, ++ 0x0002027e, 0x16020288, ++ 0xbe8203bf, 0xbefc03c1, ++ 0xd9382000, 0x00020201, ++ 0xd9386040, 0x00040401, ++ 0xd70f6a01, 0x000202ff, ++ 0x00000400, 0x80828102, ++ 0xbf84fff7, 0xbefc03ff, ++ 0x00000068, 0xbe803080, ++ 0xbe813080, 0xbe823080, ++ 0xbe833080, 0x80fc847c, ++ 0xbf84fffa, 0xbeea0480, ++ 0xbeec0480, 0xbeee0480, ++ 0xbef00480, 0xbef20480, ++ 0xbef40480, 0xbef60480, ++ 0xbef80480, 0xbefa0480, ++ 0xbf810000, 0xbf9f0000, ++ 0xbf9f0000, 0xbf9f0000, ++ 0xbf9f0000, 0xbf9f0000, ++}; ++ + /* Define the cleaner shader gfx_10_3_0 */ + static const u32 gfx_10_3_0_cleaner_shader_hex[] = { + 0xb0804004, 0xbf8a0000, +diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v10_1_10_cleaner_shader.asm b/drivers/gpu/drm/amd/amdgpu/gfx_v10_1_10_cleaner_shader.asm +new file mode 100644 +index 0000000000000..9ba3359253c95 +--- /dev/null ++++ b/drivers/gpu/drm/amd/amdgpu/gfx_v10_1_10_cleaner_shader.asm +@@ -0,0 +1,126 @@ ++/* SPDX-License-Identifier: MIT */ ++/* ++ * Copyright 2025 Advanced Micro Devices, Inc. ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a ++ * copy of this software and associated documentation files (the "Software"), ++ * to deal in the Software without restriction, including without limitation ++ * the rights to use, copy, modify, merge, publish, distribute, sublicense, ++ * and/or sell copies of the Software, and to permit persons to whom the ++ * Software is furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ++ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ * OTHER DEALINGS IN THE SOFTWARE. ++ */ ++ ++// This shader is to clean LDS, SGPRs and VGPRs. It is first 64 Dwords or 256 bytes of 256 Dwords cleaner shader. ++ ++// GFX10.1 : Clear SGPRs, VGPRs and LDS ++// Launch 32 waves per CU (16 per SIMD) as a workgroup (threadgroup) to fill every wave slot ++// Waves are "wave32" and have 64 VGPRs each, which uses all 1024 VGPRs per SIMD ++// Waves are launched in "CU" mode, and the workgroup shares 64KB of LDS (half of the WGP's LDS) ++// It takes 2 workgroups to use all of LDS: one on each CU of the WGP ++// Each wave clears SGPRs 0 - 107 ++// Each wave clears VGPRs 0 - 63 ++// The first wave of the workgroup clears its 64KB of LDS ++// The shader starts with "S_BARRIER" to ensure SPI has launched all waves of the workgroup ++// before any wave in the workgroup could end. Without this, it is possible not all SGPRs get cleared. ++ ++ ++shader main ++ asic(GFX10.1) ++ type(CS) ++ wave_size(32) ++// Note: original source code from SQ team ++ ++// ++// Create 32 waves in a threadgroup (CS waves) ++// Each allocates 64 VGPRs ++// The workgroup allocates all of LDS (64kbytes) ++// ++// Takes about 2500 clocks to run. ++// (theorhetical fastest = 1024clks vgpr + 640lds = 1660 clks) ++// ++ S_BARRIER ++ s_cmp_eq_u32 s0, 1 // Bit0 is set, sgpr0 is set then clear VGPRS and LDS as FW set COMPUTE_USER_DATA_0 ++ s_cbranch_scc0 label_0023 // Clean VGPRs and LDS if sgpr0 of wave is set, scc = (s0 == 1) ++ ++ s_mov_b32 s2, 0x00000038 // Loop 64/8=8 times (loop unrolled for performance) ++ s_mov_b32 m0, 0 ++ // ++ // CLEAR VGPRs ++ // ++label_0005: ++ v_movreld_b32 v0, 0 ++ v_movreld_b32 v1, 0 ++ v_movreld_b32 v2, 0 ++ v_movreld_b32 v3, 0 ++ v_movreld_b32 v4, 0 ++ v_movreld_b32 v5, 0 ++ v_movreld_b32 v6, 0 ++ v_movreld_b32 v7, 0 ++ s_mov_b32 m0, s2 ++ s_sub_u32 s2, s2, 8 ++ s_cbranch_scc0 label_0005 ++ // ++ s_mov_b32 s2, 0x80000000 // Bit31 is first_wave ++ s_and_b32 s2, s2, s0 // sgpr0 has tg_size (first_wave) term as in ucode only COMPUTE_PGM_RSRC2.tg_size_en is set ++ s_cbranch_scc0 label_0023 // Clean LDS if its first wave of ThreadGroup/WorkGroup ++ // CLEAR LDS ++ // ++ s_mov_b32 exec_lo, 0xffffffff ++ s_mov_b32 exec_hi, 0xffffffff ++ v_mbcnt_lo_u32_b32 v1, exec_hi, 0 // Set V1 to thread-ID (0..63) ++ v_mbcnt_hi_u32_b32 v1, exec_lo, v1 // Set V1 to thread-ID (0..63) ++ v_mul_u32_u24 v1, 0x00000008, v1 // * 8, so each thread is a double-dword address (8byte) ++ s_mov_b32 s2, 0x00000003f // 64 loop iterations ++ s_mov_b32 m0, 0xffffffff ++ // Clear all of LDS space ++ // Each FirstWave of WorkGroup clears 64kbyte block ++ ++label_001F: ++ ds_write2_b64 v1, v[2:3], v[2:3] offset1:32 ++ ds_write2_b64 v1, v[4:5], v[4:5] offset0:64 offset1:96 ++ v_add_co_u32 v1, vcc, 0x00000400, v1 ++ s_sub_u32 s2, s2, 1 ++ s_cbranch_scc0 label_001F ++ ++ // ++ // CLEAR SGPRs ++ // ++label_0023: ++ s_mov_b32 m0, 0x00000068 // Loop 108/4=27 times (loop unrolled for performance) ++label_sgpr_loop: ++ s_movreld_b32 s0, 0 ++ s_movreld_b32 s1, 0 ++ s_movreld_b32 s2, 0 ++ s_movreld_b32 s3, 0 ++ s_sub_u32 m0, m0, 4 ++ s_cbranch_scc0 label_sgpr_loop ++ ++ //clear vcc ++ s_mov_b64 vcc, 0 //clear vcc ++ //s_setreg_imm32_b32 hw_reg_shader_flat_scratch_lo, 0 //clear flat scratch lo SGPR ++ //s_setreg_imm32_b32 hw_reg_shader_flat_scratch_hi, 0 //clear flat scratch hi SGPR ++ s_mov_b64 ttmp0, 0 //Clear ttmp0 and ttmp1 ++ s_mov_b64 ttmp2, 0 //Clear ttmp2 and ttmp3 ++ s_mov_b64 ttmp4, 0 //Clear ttmp4 and ttmp5 ++ s_mov_b64 ttmp6, 0 //Clear ttmp6 and ttmp7 ++ s_mov_b64 ttmp8, 0 //Clear ttmp8 and ttmp9 ++ s_mov_b64 ttmp10, 0 //Clear ttmp10 and ttmp11 ++ s_mov_b64 ttmp12, 0 //Clear ttmp12 and ttmp13 ++ s_mov_b64 ttmp14, 0 //Clear ttmp14 and ttmp15 ++ ++ s_endpgm ++ ++end ++ ++ +-- +2.39.5 + diff --git a/queue-6.14/drm-amdgpu-gfx11-don-t-read-registers-in-mqd-init.patch b/queue-6.14/drm-amdgpu-gfx11-don-t-read-registers-in-mqd-init.patch new file mode 100644 index 0000000000..3186d37d78 --- /dev/null +++ b/queue-6.14/drm-amdgpu-gfx11-don-t-read-registers-in-mqd-init.patch @@ -0,0 +1,178 @@ +From 4fc8d1aa9cec5adb3a058ac605dfa07d0549dfd5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 26 Feb 2025 15:55:33 -0500 +Subject: drm/amdgpu/gfx11: don't read registers in mqd init + +From: Alex Deucher + +[ Upstream commit e27b36ea6ba5f29e91fcfb375ea29503708fcf43 ] + +Just use the default values. There's not need to +get the value from hardware and it could cause problems +if we do that at runtime and gfxoff is active. + +Reviewed-by: Mukul Joshi +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c | 47 ++++++++++++++++++-------- + 1 file changed, 32 insertions(+), 15 deletions(-) + +diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c +index f1f53c7687410..e050c2e4ea734 100644 +--- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c ++++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c +@@ -64,6 +64,23 @@ + #define regPC_CONFIG_CNTL_1 0x194d + #define regPC_CONFIG_CNTL_1_BASE_IDX 1 + ++#define regCP_GFX_MQD_CONTROL_DEFAULT 0x00000100 ++#define regCP_GFX_HQD_VMID_DEFAULT 0x00000000 ++#define regCP_GFX_HQD_QUEUE_PRIORITY_DEFAULT 0x00000000 ++#define regCP_GFX_HQD_QUANTUM_DEFAULT 0x00000a01 ++#define regCP_GFX_HQD_CNTL_DEFAULT 0x00a00000 ++#define regCP_RB_DOORBELL_CONTROL_DEFAULT 0x00000000 ++#define regCP_GFX_HQD_RPTR_DEFAULT 0x00000000 ++ ++#define regCP_HQD_EOP_CONTROL_DEFAULT 0x00000006 ++#define regCP_HQD_PQ_DOORBELL_CONTROL_DEFAULT 0x00000000 ++#define regCP_MQD_CONTROL_DEFAULT 0x00000100 ++#define regCP_HQD_PQ_CONTROL_DEFAULT 0x00308509 ++#define regCP_HQD_PQ_DOORBELL_CONTROL_DEFAULT 0x00000000 ++#define regCP_HQD_PQ_RPTR_DEFAULT 0x00000000 ++#define regCP_HQD_PERSISTENT_STATE_DEFAULT 0x0be05501 ++#define regCP_HQD_IB_CONTROL_DEFAULT 0x00300000 ++ + MODULE_FIRMWARE("amdgpu/gc_11_0_0_pfp.bin"); + MODULE_FIRMWARE("amdgpu/gc_11_0_0_me.bin"); + MODULE_FIRMWARE("amdgpu/gc_11_0_0_mec.bin"); +@@ -3958,7 +3975,7 @@ static void gfx_v11_0_gfx_mqd_set_priority(struct amdgpu_device *adev, + if (prop->hqd_pipe_priority == AMDGPU_GFX_PIPE_PRIO_HIGH) + priority = 1; + +- tmp = RREG32_SOC15(GC, 0, regCP_GFX_HQD_QUEUE_PRIORITY); ++ tmp = regCP_GFX_HQD_QUEUE_PRIORITY_DEFAULT; + tmp = REG_SET_FIELD(tmp, CP_GFX_HQD_QUEUE_PRIORITY, PRIORITY_LEVEL, priority); + mqd->cp_gfx_hqd_queue_priority = tmp; + } +@@ -3980,14 +3997,14 @@ static int gfx_v11_0_gfx_mqd_init(struct amdgpu_device *adev, void *m, + mqd->cp_mqd_base_addr_hi = upper_32_bits(prop->mqd_gpu_addr); + + /* set up mqd control */ +- tmp = RREG32_SOC15(GC, 0, regCP_GFX_MQD_CONTROL); ++ tmp = regCP_GFX_MQD_CONTROL_DEFAULT; + tmp = REG_SET_FIELD(tmp, CP_GFX_MQD_CONTROL, VMID, 0); + tmp = REG_SET_FIELD(tmp, CP_GFX_MQD_CONTROL, PRIV_STATE, 1); + tmp = REG_SET_FIELD(tmp, CP_GFX_MQD_CONTROL, CACHE_POLICY, 0); + mqd->cp_gfx_mqd_control = tmp; + + /* set up gfx_hqd_vimd with 0x0 to indicate the ring buffer's vmid */ +- tmp = RREG32_SOC15(GC, 0, regCP_GFX_HQD_VMID); ++ tmp = regCP_GFX_HQD_VMID_DEFAULT; + tmp = REG_SET_FIELD(tmp, CP_GFX_HQD_VMID, VMID, 0); + mqd->cp_gfx_hqd_vmid = 0; + +@@ -3995,7 +4012,7 @@ static int gfx_v11_0_gfx_mqd_init(struct amdgpu_device *adev, void *m, + gfx_v11_0_gfx_mqd_set_priority(adev, mqd, prop); + + /* set up time quantum */ +- tmp = RREG32_SOC15(GC, 0, regCP_GFX_HQD_QUANTUM); ++ tmp = regCP_GFX_HQD_QUANTUM_DEFAULT; + tmp = REG_SET_FIELD(tmp, CP_GFX_HQD_QUANTUM, QUANTUM_EN, 1); + mqd->cp_gfx_hqd_quantum = tmp; + +@@ -4017,7 +4034,7 @@ static int gfx_v11_0_gfx_mqd_init(struct amdgpu_device *adev, void *m, + + /* set up the gfx_hqd_control, similar as CP_RB0_CNTL */ + rb_bufsz = order_base_2(prop->queue_size / 4) - 1; +- tmp = RREG32_SOC15(GC, 0, regCP_GFX_HQD_CNTL); ++ tmp = regCP_GFX_HQD_CNTL_DEFAULT; + tmp = REG_SET_FIELD(tmp, CP_GFX_HQD_CNTL, RB_BUFSZ, rb_bufsz); + tmp = REG_SET_FIELD(tmp, CP_GFX_HQD_CNTL, RB_BLKSZ, rb_bufsz - 2); + #ifdef __BIG_ENDIAN +@@ -4026,7 +4043,7 @@ static int gfx_v11_0_gfx_mqd_init(struct amdgpu_device *adev, void *m, + mqd->cp_gfx_hqd_cntl = tmp; + + /* set up cp_doorbell_control */ +- tmp = RREG32_SOC15(GC, 0, regCP_RB_DOORBELL_CONTROL); ++ tmp = regCP_RB_DOORBELL_CONTROL_DEFAULT; + if (prop->use_doorbell) { + tmp = REG_SET_FIELD(tmp, CP_RB_DOORBELL_CONTROL, + DOORBELL_OFFSET, prop->doorbell_index); +@@ -4038,7 +4055,7 @@ static int gfx_v11_0_gfx_mqd_init(struct amdgpu_device *adev, void *m, + mqd->cp_rb_doorbell_control = tmp; + + /* reset read and write pointers, similar to CP_RB0_WPTR/_RPTR */ +- mqd->cp_gfx_hqd_rptr = RREG32_SOC15(GC, 0, regCP_GFX_HQD_RPTR); ++ mqd->cp_gfx_hqd_rptr = regCP_GFX_HQD_RPTR_DEFAULT; + + /* active the queue */ + mqd->cp_gfx_hqd_active = 1; +@@ -4124,14 +4141,14 @@ static int gfx_v11_0_compute_mqd_init(struct amdgpu_device *adev, void *m, + mqd->cp_hqd_eop_base_addr_hi = upper_32_bits(eop_base_addr); + + /* set the EOP size, register value is 2^(EOP_SIZE+1) dwords */ +- tmp = RREG32_SOC15(GC, 0, regCP_HQD_EOP_CONTROL); ++ tmp = regCP_HQD_EOP_CONTROL_DEFAULT; + tmp = REG_SET_FIELD(tmp, CP_HQD_EOP_CONTROL, EOP_SIZE, + (order_base_2(GFX11_MEC_HPD_SIZE / 4) - 1)); + + mqd->cp_hqd_eop_control = tmp; + + /* enable doorbell? */ +- tmp = RREG32_SOC15(GC, 0, regCP_HQD_PQ_DOORBELL_CONTROL); ++ tmp = regCP_HQD_PQ_DOORBELL_CONTROL_DEFAULT; + + if (prop->use_doorbell) { + tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_DOORBELL_CONTROL, +@@ -4160,7 +4177,7 @@ static int gfx_v11_0_compute_mqd_init(struct amdgpu_device *adev, void *m, + mqd->cp_mqd_base_addr_hi = upper_32_bits(prop->mqd_gpu_addr); + + /* set MQD vmid to 0 */ +- tmp = RREG32_SOC15(GC, 0, regCP_MQD_CONTROL); ++ tmp = regCP_MQD_CONTROL_DEFAULT; + tmp = REG_SET_FIELD(tmp, CP_MQD_CONTROL, VMID, 0); + mqd->cp_mqd_control = tmp; + +@@ -4170,7 +4187,7 @@ static int gfx_v11_0_compute_mqd_init(struct amdgpu_device *adev, void *m, + mqd->cp_hqd_pq_base_hi = upper_32_bits(hqd_gpu_addr); + + /* set up the HQD, this is similar to CP_RB0_CNTL */ +- tmp = RREG32_SOC15(GC, 0, regCP_HQD_PQ_CONTROL); ++ tmp = regCP_HQD_PQ_CONTROL_DEFAULT; + tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, QUEUE_SIZE, + (order_base_2(prop->queue_size / 4) - 1)); + tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, RPTR_BLOCK_SIZE, +@@ -4196,7 +4213,7 @@ static int gfx_v11_0_compute_mqd_init(struct amdgpu_device *adev, void *m, + tmp = 0; + /* enable the doorbell if requested */ + if (prop->use_doorbell) { +- tmp = RREG32_SOC15(GC, 0, regCP_HQD_PQ_DOORBELL_CONTROL); ++ tmp = regCP_HQD_PQ_DOORBELL_CONTROL_DEFAULT; + tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_DOORBELL_CONTROL, + DOORBELL_OFFSET, prop->doorbell_index); + +@@ -4211,17 +4228,17 @@ static int gfx_v11_0_compute_mqd_init(struct amdgpu_device *adev, void *m, + mqd->cp_hqd_pq_doorbell_control = tmp; + + /* reset read and write pointers, similar to CP_RB0_WPTR/_RPTR */ +- mqd->cp_hqd_pq_rptr = RREG32_SOC15(GC, 0, regCP_HQD_PQ_RPTR); ++ mqd->cp_hqd_pq_rptr = regCP_HQD_PQ_RPTR_DEFAULT; + + /* set the vmid for the queue */ + mqd->cp_hqd_vmid = 0; + +- tmp = RREG32_SOC15(GC, 0, regCP_HQD_PERSISTENT_STATE); ++ tmp = regCP_HQD_PERSISTENT_STATE_DEFAULT; + tmp = REG_SET_FIELD(tmp, CP_HQD_PERSISTENT_STATE, PRELOAD_SIZE, 0x55); + mqd->cp_hqd_persistent_state = tmp; + + /* set MIN_IB_AVAIL_SIZE */ +- tmp = RREG32_SOC15(GC, 0, regCP_HQD_IB_CONTROL); ++ tmp = regCP_HQD_IB_CONTROL_DEFAULT; + tmp = REG_SET_FIELD(tmp, CP_HQD_IB_CONTROL, MIN_IB_AVAIL_SIZE, 3); + mqd->cp_hqd_ib_control = tmp; + +-- +2.39.5 + diff --git a/queue-6.14/drm-amdgpu-gfx12-don-t-read-registers-in-mqd-init.patch b/queue-6.14/drm-amdgpu-gfx12-don-t-read-registers-in-mqd-init.patch new file mode 100644 index 0000000000..543dfa312c --- /dev/null +++ b/queue-6.14/drm-amdgpu-gfx12-don-t-read-registers-in-mqd-init.patch @@ -0,0 +1,174 @@ +From 09118a6e6ea3d7cbb3e8ab59eed5e1d9453cddd1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 26 Feb 2025 16:08:03 -0500 +Subject: drm/amdgpu/gfx12: don't read registers in mqd init + +From: Alex Deucher + +[ Upstream commit fc3c139cf0432b79fd08e23100a559ee51cd0be4 ] + +Just use the default values. There's not need to +get the value from hardware and it could cause problems +if we do that at runtime and gfxoff is active. + +Reviewed-by: Mukul Joshi +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c | 48 ++++++++++++++++++-------- + 1 file changed, 33 insertions(+), 15 deletions(-) + +diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c +index 0c08785099f32..2ec900d50d7f8 100644 +--- a/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c ++++ b/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c +@@ -52,6 +52,24 @@ + + #define RLCG_UCODE_LOADING_START_ADDRESS 0x00002000L + ++#define regCP_GFX_MQD_CONTROL_DEFAULT 0x00000100 ++#define regCP_GFX_HQD_VMID_DEFAULT 0x00000000 ++#define regCP_GFX_HQD_QUEUE_PRIORITY_DEFAULT 0x00000000 ++#define regCP_GFX_HQD_QUANTUM_DEFAULT 0x00000a01 ++#define regCP_GFX_HQD_CNTL_DEFAULT 0x00f00000 ++#define regCP_RB_DOORBELL_CONTROL_DEFAULT 0x00000000 ++#define regCP_GFX_HQD_RPTR_DEFAULT 0x00000000 ++ ++#define regCP_HQD_EOP_CONTROL_DEFAULT 0x00000006 ++#define regCP_HQD_PQ_DOORBELL_CONTROL_DEFAULT 0x00000000 ++#define regCP_MQD_CONTROL_DEFAULT 0x00000100 ++#define regCP_HQD_PQ_CONTROL_DEFAULT 0x00308509 ++#define regCP_HQD_PQ_DOORBELL_CONTROL_DEFAULT 0x00000000 ++#define regCP_HQD_PQ_RPTR_DEFAULT 0x00000000 ++#define regCP_HQD_PERSISTENT_STATE_DEFAULT 0x0be05501 ++#define regCP_HQD_IB_CONTROL_DEFAULT 0x00300000 ++ ++ + MODULE_FIRMWARE("amdgpu/gc_12_0_0_pfp.bin"); + MODULE_FIRMWARE("amdgpu/gc_12_0_0_me.bin"); + MODULE_FIRMWARE("amdgpu/gc_12_0_0_mec.bin"); +@@ -2891,25 +2909,25 @@ static int gfx_v12_0_gfx_mqd_init(struct amdgpu_device *adev, void *m, + mqd->cp_mqd_base_addr_hi = upper_32_bits(prop->mqd_gpu_addr); + + /* set up mqd control */ +- tmp = RREG32_SOC15(GC, 0, regCP_GFX_MQD_CONTROL); ++ tmp = regCP_GFX_MQD_CONTROL_DEFAULT; + tmp = REG_SET_FIELD(tmp, CP_GFX_MQD_CONTROL, VMID, 0); + tmp = REG_SET_FIELD(tmp, CP_GFX_MQD_CONTROL, PRIV_STATE, 1); + tmp = REG_SET_FIELD(tmp, CP_GFX_MQD_CONTROL, CACHE_POLICY, 0); + mqd->cp_gfx_mqd_control = tmp; + + /* set up gfx_hqd_vimd with 0x0 to indicate the ring buffer's vmid */ +- tmp = RREG32_SOC15(GC, 0, regCP_GFX_HQD_VMID); ++ tmp = regCP_GFX_HQD_VMID_DEFAULT; + tmp = REG_SET_FIELD(tmp, CP_GFX_HQD_VMID, VMID, 0); + mqd->cp_gfx_hqd_vmid = 0; + + /* set up default queue priority level + * 0x0 = low priority, 0x1 = high priority */ +- tmp = RREG32_SOC15(GC, 0, regCP_GFX_HQD_QUEUE_PRIORITY); ++ tmp = regCP_GFX_HQD_QUEUE_PRIORITY_DEFAULT; + tmp = REG_SET_FIELD(tmp, CP_GFX_HQD_QUEUE_PRIORITY, PRIORITY_LEVEL, 0); + mqd->cp_gfx_hqd_queue_priority = tmp; + + /* set up time quantum */ +- tmp = RREG32_SOC15(GC, 0, regCP_GFX_HQD_QUANTUM); ++ tmp = regCP_GFX_HQD_QUANTUM_DEFAULT; + tmp = REG_SET_FIELD(tmp, CP_GFX_HQD_QUANTUM, QUANTUM_EN, 1); + mqd->cp_gfx_hqd_quantum = tmp; + +@@ -2931,7 +2949,7 @@ static int gfx_v12_0_gfx_mqd_init(struct amdgpu_device *adev, void *m, + + /* set up the gfx_hqd_control, similar as CP_RB0_CNTL */ + rb_bufsz = order_base_2(prop->queue_size / 4) - 1; +- tmp = RREG32_SOC15(GC, 0, regCP_GFX_HQD_CNTL); ++ tmp = regCP_GFX_HQD_CNTL_DEFAULT; + tmp = REG_SET_FIELD(tmp, CP_GFX_HQD_CNTL, RB_BUFSZ, rb_bufsz); + tmp = REG_SET_FIELD(tmp, CP_GFX_HQD_CNTL, RB_BLKSZ, rb_bufsz - 2); + #ifdef __BIG_ENDIAN +@@ -2940,7 +2958,7 @@ static int gfx_v12_0_gfx_mqd_init(struct amdgpu_device *adev, void *m, + mqd->cp_gfx_hqd_cntl = tmp; + + /* set up cp_doorbell_control */ +- tmp = RREG32_SOC15(GC, 0, regCP_RB_DOORBELL_CONTROL); ++ tmp = regCP_RB_DOORBELL_CONTROL_DEFAULT; + if (prop->use_doorbell) { + tmp = REG_SET_FIELD(tmp, CP_RB_DOORBELL_CONTROL, + DOORBELL_OFFSET, prop->doorbell_index); +@@ -2952,7 +2970,7 @@ static int gfx_v12_0_gfx_mqd_init(struct amdgpu_device *adev, void *m, + mqd->cp_rb_doorbell_control = tmp; + + /* reset read and write pointers, similar to CP_RB0_WPTR/_RPTR */ +- mqd->cp_gfx_hqd_rptr = RREG32_SOC15(GC, 0, regCP_GFX_HQD_RPTR); ++ mqd->cp_gfx_hqd_rptr = regCP_GFX_HQD_RPTR_DEFAULT; + + /* active the queue */ + mqd->cp_gfx_hqd_active = 1; +@@ -3047,14 +3065,14 @@ static int gfx_v12_0_compute_mqd_init(struct amdgpu_device *adev, void *m, + mqd->cp_hqd_eop_base_addr_hi = upper_32_bits(eop_base_addr); + + /* set the EOP size, register value is 2^(EOP_SIZE+1) dwords */ +- tmp = RREG32_SOC15(GC, 0, regCP_HQD_EOP_CONTROL); ++ tmp = regCP_HQD_EOP_CONTROL_DEFAULT; + tmp = REG_SET_FIELD(tmp, CP_HQD_EOP_CONTROL, EOP_SIZE, + (order_base_2(GFX12_MEC_HPD_SIZE / 4) - 1)); + + mqd->cp_hqd_eop_control = tmp; + + /* enable doorbell? */ +- tmp = RREG32_SOC15(GC, 0, regCP_HQD_PQ_DOORBELL_CONTROL); ++ tmp = regCP_HQD_PQ_DOORBELL_CONTROL_DEFAULT; + + if (prop->use_doorbell) { + tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_DOORBELL_CONTROL, +@@ -3083,7 +3101,7 @@ static int gfx_v12_0_compute_mqd_init(struct amdgpu_device *adev, void *m, + mqd->cp_mqd_base_addr_hi = upper_32_bits(prop->mqd_gpu_addr); + + /* set MQD vmid to 0 */ +- tmp = RREG32_SOC15(GC, 0, regCP_MQD_CONTROL); ++ tmp = regCP_MQD_CONTROL_DEFAULT; + tmp = REG_SET_FIELD(tmp, CP_MQD_CONTROL, VMID, 0); + mqd->cp_mqd_control = tmp; + +@@ -3093,7 +3111,7 @@ static int gfx_v12_0_compute_mqd_init(struct amdgpu_device *adev, void *m, + mqd->cp_hqd_pq_base_hi = upper_32_bits(hqd_gpu_addr); + + /* set up the HQD, this is similar to CP_RB0_CNTL */ +- tmp = RREG32_SOC15(GC, 0, regCP_HQD_PQ_CONTROL); ++ tmp = regCP_HQD_PQ_CONTROL_DEFAULT; + tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, QUEUE_SIZE, + (order_base_2(prop->queue_size / 4) - 1)); + tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, RPTR_BLOCK_SIZE, +@@ -3118,7 +3136,7 @@ static int gfx_v12_0_compute_mqd_init(struct amdgpu_device *adev, void *m, + tmp = 0; + /* enable the doorbell if requested */ + if (prop->use_doorbell) { +- tmp = RREG32_SOC15(GC, 0, regCP_HQD_PQ_DOORBELL_CONTROL); ++ tmp = regCP_HQD_PQ_DOORBELL_CONTROL_DEFAULT; + tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_DOORBELL_CONTROL, + DOORBELL_OFFSET, prop->doorbell_index); + +@@ -3133,17 +3151,17 @@ static int gfx_v12_0_compute_mqd_init(struct amdgpu_device *adev, void *m, + mqd->cp_hqd_pq_doorbell_control = tmp; + + /* reset read and write pointers, similar to CP_RB0_WPTR/_RPTR */ +- mqd->cp_hqd_pq_rptr = RREG32_SOC15(GC, 0, regCP_HQD_PQ_RPTR); ++ mqd->cp_hqd_pq_rptr = regCP_HQD_PQ_RPTR_DEFAULT; + + /* set the vmid for the queue */ + mqd->cp_hqd_vmid = 0; + +- tmp = RREG32_SOC15(GC, 0, regCP_HQD_PERSISTENT_STATE); ++ tmp = regCP_HQD_PERSISTENT_STATE_DEFAULT; + tmp = REG_SET_FIELD(tmp, CP_HQD_PERSISTENT_STATE, PRELOAD_SIZE, 0x55); + mqd->cp_hqd_persistent_state = tmp; + + /* set MIN_IB_AVAIL_SIZE */ +- tmp = RREG32_SOC15(GC, 0, regCP_HQD_IB_CONTROL); ++ tmp = regCP_HQD_IB_CONTROL_DEFAULT; + tmp = REG_SET_FIELD(tmp, CP_HQD_IB_CONTROL, MIN_IB_AVAIL_SIZE, 3); + mqd->cp_hqd_ib_control = tmp; + +-- +2.39.5 + diff --git a/queue-6.14/drm-amdgpu-increase-ras-bad-page-threshold.patch b/queue-6.14/drm-amdgpu-increase-ras-bad-page-threshold.patch new file mode 100644 index 0000000000..b6d76e4d52 --- /dev/null +++ b/queue-6.14/drm-amdgpu-increase-ras-bad-page-threshold.patch @@ -0,0 +1,56 @@ +From 1bbd787a90591867ac528b59796b0ebd42a07d6f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Mar 2025 11:36:49 +0800 +Subject: drm/amdgpu: increase RAS bad page threshold + +From: Tao Zhou + +[ Upstream commit 334dc5fcc3f177823115ec4e075259997c16d4a7 ] + +For default policy, driver will issue an RMA event when the number of +bad pages is greater than 8 physical rows, rather than reaches 8 +physical rows, don't rely on threshold configurable parameters in +default mode. + +Signed-off-by: Tao Zhou +Reviewed-by: Hawking Zhang +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c +index 52c16bfeccaad..12ffe4a963d31 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c +@@ -748,7 +748,7 @@ amdgpu_ras_eeprom_update_header(struct amdgpu_ras_eeprom_control *control) + /* Modify the header if it exceeds. + */ + if (amdgpu_bad_page_threshold != 0 && +- control->ras_num_bad_pages >= ras->bad_page_cnt_threshold) { ++ control->ras_num_bad_pages > ras->bad_page_cnt_threshold) { + dev_warn(adev->dev, + "Saved bad pages %d reaches threshold value %d\n", + control->ras_num_bad_pages, ras->bad_page_cnt_threshold); +@@ -806,7 +806,7 @@ amdgpu_ras_eeprom_update_header(struct amdgpu_ras_eeprom_control *control) + */ + if (amdgpu_bad_page_threshold != 0 && + control->tbl_hdr.version == RAS_TABLE_VER_V2_1 && +- control->ras_num_bad_pages < ras->bad_page_cnt_threshold) ++ control->ras_num_bad_pages <= ras->bad_page_cnt_threshold) + control->tbl_rai.health_percent = ((ras->bad_page_cnt_threshold - + control->ras_num_bad_pages) * 100) / + ras->bad_page_cnt_threshold; +@@ -1451,7 +1451,7 @@ int amdgpu_ras_eeprom_check(struct amdgpu_ras_eeprom_control *control) + res); + return -EINVAL; + } +- if (ras->bad_page_cnt_threshold > control->ras_num_bad_pages) { ++ if (ras->bad_page_cnt_threshold >= control->ras_num_bad_pages) { + /* This means that, the threshold was increased since + * the last time the system was booted, and now, + * ras->bad_page_cnt_threshold - control->num_recs > 0, +-- +2.39.5 + diff --git a/queue-6.14/drm-amdgpu-mes11-fix-set_hw_resources_1-calculation.patch b/queue-6.14/drm-amdgpu-mes11-fix-set_hw_resources_1-calculation.patch new file mode 100644 index 0000000000..0b2dcf8a04 --- /dev/null +++ b/queue-6.14/drm-amdgpu-mes11-fix-set_hw_resources_1-calculation.patch @@ -0,0 +1,41 @@ +From eeb8b48cfbac1452bc29c85c39d7862c6ad2000d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 7 Feb 2025 09:39:24 -0500 +Subject: drm/amdgpu/mes11: fix set_hw_resources_1 calculation +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Alex Deucher + +[ Upstream commit 1350dd3691b5f757a948e5b9895d62c422baeb90 ] + +It's GPU page size not CPU page size. In most cases they +are the same, but not always. This can lead to overallocation +on systems with larger pages. + +Cc: Srinivasan Shanmugam +Cc: Christian König +Reviewed-by: Christian König +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/amdgpu/mes_v11_0.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c b/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c +index 0f808ffcab943..68bb334393bb6 100644 +--- a/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c ++++ b/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c +@@ -730,7 +730,7 @@ static int mes_v11_0_set_hw_resources(struct amdgpu_mes *mes) + + static int mes_v11_0_set_hw_resources_1(struct amdgpu_mes *mes) + { +- int size = 128 * PAGE_SIZE; ++ int size = 128 * AMDGPU_GPU_PAGE_SIZE; + int ret = 0; + struct amdgpu_device *adev = mes->adev; + union MESAPI_SET_HW_RESOURCES_1 mes_set_hw_res_pkt; +-- +2.39.5 + diff --git a/queue-6.14/drm-amdgpu-reinit-fw-shared-flags-on-vcn-v5.0.1.patch b/queue-6.14/drm-amdgpu-reinit-fw-shared-flags-on-vcn-v5.0.1.patch new file mode 100644 index 0000000000..3248658ccd --- /dev/null +++ b/queue-6.14/drm-amdgpu-reinit-fw-shared-flags-on-vcn-v5.0.1.patch @@ -0,0 +1,84 @@ +From 7c550480ca0b4ba5624fd7c13dd0f5fb4812cb0c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 26 Feb 2025 12:53:48 +0530 +Subject: drm/amdgpu: Reinit FW shared flags on VCN v5.0.1 + +From: Lijo Lazar + +[ Upstream commit 6ef5ccaad76d907d4257f20de992f89c0f7a7f8e ] + +After a full device reset, shared memory region will clear out and it's +not possible to reliably save the region in case of RAS errors. +Reinitialize the flags if required. + +Signed-off-by: Lijo Lazar +Reviewed-by: Hawking Zhang +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c | 28 ++++++++++++++++++------- + 1 file changed, 20 insertions(+), 8 deletions(-) + +diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c +index 8b0b3739a5377..cdbc10d7c9fb7 100644 +--- a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c ++++ b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c +@@ -65,6 +65,22 @@ static int vcn_v5_0_1_early_init(struct amdgpu_ip_block *ip_block) + return amdgpu_vcn_early_init(adev); + } + ++static void vcn_v5_0_1_fw_shared_init(struct amdgpu_device *adev, int inst_idx) ++{ ++ struct amdgpu_vcn5_fw_shared *fw_shared; ++ ++ fw_shared = adev->vcn.inst[inst_idx].fw_shared.cpu_addr; ++ ++ if (fw_shared->sq.is_enabled) ++ return; ++ fw_shared->present_flag_0 = ++ cpu_to_le32(AMDGPU_FW_SHARED_FLAG_0_UNIFIED_QUEUE); ++ fw_shared->sq.is_enabled = 1; ++ ++ if (amdgpu_vcnfw_log) ++ amdgpu_vcn_fwlog_init(&adev->vcn.inst[inst_idx]); ++} ++ + /** + * vcn_v5_0_1_sw_init - sw init for VCN block + * +@@ -95,8 +111,6 @@ static int vcn_v5_0_1_sw_init(struct amdgpu_ip_block *ip_block) + return r; + + for (i = 0; i < adev->vcn.num_vcn_inst; i++) { +- volatile struct amdgpu_vcn5_fw_shared *fw_shared; +- + vcn_inst = GET_INST(VCN, i); + + ring = &adev->vcn.inst[i].ring_enc[0]; +@@ -111,12 +125,7 @@ static int vcn_v5_0_1_sw_init(struct amdgpu_ip_block *ip_block) + if (r) + return r; + +- fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr; +- fw_shared->present_flag_0 = cpu_to_le32(AMDGPU_FW_SHARED_FLAG_0_UNIFIED_QUEUE); +- fw_shared->sq.is_enabled = true; +- +- if (amdgpu_vcnfw_log) +- amdgpu_vcn_fwlog_init(&adev->vcn.inst[i]); ++ vcn_v5_0_1_fw_shared_init(adev, i); + } + + /* TODO: Add queue reset mask when FW fully supports it */ +@@ -188,6 +197,9 @@ static int vcn_v5_0_1_hw_init(struct amdgpu_ip_block *ip_block) + 9 * vcn_inst), + adev->vcn.inst[i].aid_id); + ++ /* Re-init fw_shared, if required */ ++ vcn_v5_0_1_fw_shared_init(adev, i); ++ + r = amdgpu_ring_test_helper(ring); + if (r) + return r; +-- +2.39.5 + diff --git a/queue-6.14/drm-amdgpu-release-xcp_mgr-on-exit.patch b/queue-6.14/drm-amdgpu-release-xcp_mgr-on-exit.patch new file mode 100644 index 0000000000..bbbdee80b6 --- /dev/null +++ b/queue-6.14/drm-amdgpu-release-xcp_mgr-on-exit.patch @@ -0,0 +1,36 @@ +From 91b46ec06a5895e75f639882a627500009c229b3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 14 Mar 2025 10:27:55 +0800 +Subject: drm/amdgpu: release xcp_mgr on exit + +From: Flora Cui + +[ Upstream commit b5aaa82e2b12feaaa6958f7fa0917ddcc03c24ee ] + +Free on driver cleanup. + +Reviewed-by: Lijo Lazar +Signed-off-by: Flora Cui +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +index c00a01c62724a..ea50f82b547d9 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +@@ -4778,6 +4778,9 @@ void amdgpu_device_fini_sw(struct amdgpu_device *adev) + kfree(adev->fru_info); + adev->fru_info = NULL; + ++ kfree(adev->xcp_mgr); ++ adev->xcp_mgr = NULL; ++ + px = amdgpu_device_supports_px(adev_to_drm(adev)); + + if (px || (!dev_is_removable(&adev->pdev->dev) && +-- +2.39.5 + diff --git a/queue-6.14/drm-amdgpu-remove-all-kfd-fences-from-the-bo-on-rele.patch b/queue-6.14/drm-amdgpu-remove-all-kfd-fences-from-the-bo-on-rele.patch new file mode 100644 index 0000000000..31decf2735 --- /dev/null +++ b/queue-6.14/drm-amdgpu-remove-all-kfd-fences-from-the-bo-on-rele.patch @@ -0,0 +1,179 @@ +From be5eede0e596af1e3235b4930e0eb99c82893b57 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 29 Jan 2025 16:28:49 +0100 +Subject: drm/amdgpu: remove all KFD fences from the BO on release +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Christian König + +[ Upstream commit cb0de06d1b0afb2d0c600ad748069f5ce27730ec ] + +Remove all KFD BOs from the private dma_resv object. + +This prevents the KFD from being evict unecessarily when an exported BO +is released. + +Signed-off-by: Christian König +Signed-off-by: James Zhu +Reviewed-by: Felix Kuehling +Reviewed-and-tested-by: James Zhu +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h | 5 +- + .../gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c | 52 ++++++++----------- + drivers/gpu/drm/amd/amdgpu/amdgpu_object.c | 38 ++++++++------ + 3 files changed, 47 insertions(+), 48 deletions(-) + +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h +index 8af67f18500a7..2f48dc5747aa2 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h +@@ -192,7 +192,7 @@ int kfd_debugfs_kfd_mem_limits(struct seq_file *m, void *data); + #if IS_ENABLED(CONFIG_HSA_AMD) + bool amdkfd_fence_check_mm(struct dma_fence *f, struct mm_struct *mm); + struct amdgpu_amdkfd_fence *to_amdgpu_amdkfd_fence(struct dma_fence *f); +-int amdgpu_amdkfd_remove_fence_on_pt_pd_bos(struct amdgpu_bo *bo); ++void amdgpu_amdkfd_remove_all_eviction_fences(struct amdgpu_bo *bo); + int amdgpu_amdkfd_evict_userptr(struct mmu_interval_notifier *mni, + unsigned long cur_seq, struct kgd_mem *mem); + int amdgpu_amdkfd_bo_validate_and_fence(struct amdgpu_bo *bo, +@@ -212,9 +212,8 @@ struct amdgpu_amdkfd_fence *to_amdgpu_amdkfd_fence(struct dma_fence *f) + } + + static inline +-int amdgpu_amdkfd_remove_fence_on_pt_pd_bos(struct amdgpu_bo *bo) ++void amdgpu_amdkfd_remove_all_eviction_fences(struct amdgpu_bo *bo) + { +- return 0; + } + + static inline +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c +index 70224b9f54f2f..c0aaa72b6c210 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c +@@ -370,40 +370,32 @@ static int amdgpu_amdkfd_remove_eviction_fence(struct amdgpu_bo *bo, + return 0; + } + +-int amdgpu_amdkfd_remove_fence_on_pt_pd_bos(struct amdgpu_bo *bo) ++/** ++ * amdgpu_amdkfd_remove_all_eviction_fences - Remove all eviction fences ++ * @bo: the BO where to remove the evictions fences from. ++ * ++ * This functions should only be used on release when all references to the BO ++ * are already dropped. We remove the eviction fence from the private copy of ++ * the dma_resv object here since that is what is used during release to ++ * determine of the BO is idle or not. ++ */ ++void amdgpu_amdkfd_remove_all_eviction_fences(struct amdgpu_bo *bo) + { +- struct amdgpu_bo *root = bo; +- struct amdgpu_vm_bo_base *vm_bo; +- struct amdgpu_vm *vm; +- struct amdkfd_process_info *info; +- struct amdgpu_amdkfd_fence *ef; +- int ret; +- +- /* we can always get vm_bo from root PD bo.*/ +- while (root->parent) +- root = root->parent; ++ struct dma_resv *resv = &bo->tbo.base._resv; ++ struct dma_fence *fence, *stub; ++ struct dma_resv_iter cursor; + +- vm_bo = root->vm_bo; +- if (!vm_bo) +- return 0; ++ dma_resv_assert_held(resv); + +- vm = vm_bo->vm; +- if (!vm) +- return 0; +- +- info = vm->process_info; +- if (!info || !info->eviction_fence) +- return 0; +- +- ef = container_of(dma_fence_get(&info->eviction_fence->base), +- struct amdgpu_amdkfd_fence, base); +- +- BUG_ON(!dma_resv_trylock(bo->tbo.base.resv)); +- ret = amdgpu_amdkfd_remove_eviction_fence(bo, ef); +- dma_resv_unlock(bo->tbo.base.resv); ++ stub = dma_fence_get_stub(); ++ dma_resv_for_each_fence(&cursor, resv, DMA_RESV_USAGE_BOOKKEEP, fence) { ++ if (!to_amdgpu_amdkfd_fence(fence)) ++ continue; + +- dma_fence_put(&ef->base); +- return ret; ++ dma_resv_replace_fences(resv, fence->context, stub, ++ DMA_RESV_USAGE_BOOKKEEP); ++ } ++ dma_fence_put(stub); + } + + static int amdgpu_amdkfd_bo_validate(struct amdgpu_bo *bo, uint32_t domain, +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c +index 00752e3f9d8ab..0b9987781f762 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c +@@ -1295,28 +1295,36 @@ void amdgpu_bo_release_notify(struct ttm_buffer_object *bo) + if (abo->kfd_bo) + amdgpu_amdkfd_release_notify(abo); + +- /* We only remove the fence if the resv has individualized. */ +- WARN_ON_ONCE(bo->type == ttm_bo_type_kernel +- && bo->base.resv != &bo->base._resv); +- if (bo->base.resv == &bo->base._resv) +- amdgpu_amdkfd_remove_fence_on_pt_pd_bos(abo); ++ /* ++ * We lock the private dma_resv object here and since the BO is about to ++ * be released nobody else should have a pointer to it. ++ * So when this locking here fails something is wrong with the reference ++ * counting. ++ */ ++ if (WARN_ON_ONCE(!dma_resv_trylock(&bo->base._resv))) ++ return; ++ ++ amdgpu_amdkfd_remove_all_eviction_fences(abo); + + if (!bo->resource || bo->resource->mem_type != TTM_PL_VRAM || + !(abo->flags & AMDGPU_GEM_CREATE_VRAM_WIPE_ON_RELEASE) || + adev->in_suspend || drm_dev_is_unplugged(adev_to_drm(adev))) +- return; ++ goto out; + +- if (WARN_ON_ONCE(!dma_resv_trylock(bo->base.resv))) +- return; ++ r = dma_resv_reserve_fences(&bo->base._resv, 1); ++ if (r) ++ goto out; + +- r = amdgpu_fill_buffer(abo, 0, bo->base.resv, &fence, true); +- if (!WARN_ON(r)) { +- amdgpu_vram_mgr_set_cleared(bo->resource); +- amdgpu_bo_fence(abo, fence, false); +- dma_fence_put(fence); +- } ++ r = amdgpu_fill_buffer(abo, 0, &bo->base._resv, &fence, true); ++ if (WARN_ON(r)) ++ goto out; ++ ++ amdgpu_vram_mgr_set_cleared(bo->resource); ++ dma_resv_add_fence(&bo->base._resv, fence, DMA_RESV_USAGE_KERNEL); ++ dma_fence_put(fence); + +- dma_resv_unlock(bo->base.resv); ++out: ++ dma_resv_unlock(&bo->base._resv); + } + + /** +-- +2.39.5 + diff --git a/queue-6.14/drm-amdgpu-reset-psp-cmd-to-null-after-releasing-the.patch b/queue-6.14/drm-amdgpu-reset-psp-cmd-to-null-after-releasing-the.patch new file mode 100644 index 0000000000..22b51257b0 --- /dev/null +++ b/queue-6.14/drm-amdgpu-reset-psp-cmd-to-null-after-releasing-the.patch @@ -0,0 +1,45 @@ +From 8c633a1f8cc2921a8376842cf1715fcf60311d71 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 7 Feb 2025 14:28:49 +0800 +Subject: drm/amdgpu: reset psp->cmd to NULL after releasing the buffer + +From: Jiang Liu + +[ Upstream commit e92f3f94cad24154fd3baae30c6dfb918492278d ] + +Reset psp->cmd to NULL after releasing the buffer in function psp_sw_fini(). + +Reviewed-by: Lijo Lazar +Signed-off-by: Jiang Liu +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c +index e5fc80ed06eae..665cc277cdc05 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c +@@ -533,7 +533,6 @@ static int psp_sw_fini(struct amdgpu_ip_block *ip_block) + { + struct amdgpu_device *adev = ip_block->adev; + struct psp_context *psp = &adev->psp; +- struct psp_gfx_cmd_resp *cmd = psp->cmd; + + psp_memory_training_fini(psp); + +@@ -543,8 +542,8 @@ static int psp_sw_fini(struct amdgpu_ip_block *ip_block) + amdgpu_ucode_release(&psp->cap_fw); + amdgpu_ucode_release(&psp->toc_fw); + +- kfree(cmd); +- cmd = NULL; ++ kfree(psp->cmd); ++ psp->cmd = NULL; + + psp_free_shared_bufs(psp); + +-- +2.39.5 + diff --git a/queue-6.14/drm-amdgpu-rework-how-isolation-is-enforced-v2.patch b/queue-6.14/drm-amdgpu-rework-how-isolation-is-enforced-v2.patch new file mode 100644 index 0000000000..d9ba0aa3f9 --- /dev/null +++ b/queue-6.14/drm-amdgpu-rework-how-isolation-is-enforced-v2.patch @@ -0,0 +1,348 @@ +From 9277ad4e70972c95f278c0da0f2f280d1603b5e1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 15 Jan 2025 13:44:26 +0100 +Subject: drm/amdgpu: rework how isolation is enforced v2 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Christian König + +[ Upstream commit bd22e44ad415ac22e3a4f9a983d2a085f6cb4427 ] + +Limiting the number of available VMIDs to enforce isolation causes some +issues with gang submit and applying certain HW workarounds which +require multiple VMIDs to work correctly. + +So instead start to track all submissions to the relevant engines in a +per partition data structure and use the dma_fences of the submissions +to enforce isolation similar to what a VMID limit does. + +v2: use ~0l for jobs without isolation to distinct it from kernel + submissions which uses NULL for the owner. Add some warning when we + are OOM. + +Signed-off-by: Christian König +Acked-by: Srinivasan Shanmugam +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/amdgpu/amdgpu.h | 13 ++- + drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 98 +++++++++++++++++++++- + drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c | 43 ++++------ + drivers/gpu/drm/amd/amdgpu/amdgpu_job.c | 16 +++- + drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c | 19 +++++ + drivers/gpu/drm/amd/amdgpu/amdgpu_sync.h | 1 + + 6 files changed, 155 insertions(+), 35 deletions(-) + +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h +index 416d2611fbf1c..90f688b3d9d36 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h +@@ -1187,9 +1187,15 @@ struct amdgpu_device { + bool debug_enable_ras_aca; + bool debug_exp_resets; + +- bool enforce_isolation[MAX_XCP]; +- /* Added this mutex for cleaner shader isolation between GFX and compute processes */ ++ /* Protection for the following isolation structure */ + struct mutex enforce_isolation_mutex; ++ bool enforce_isolation[MAX_XCP]; ++ struct amdgpu_isolation { ++ void *owner; ++ struct dma_fence *spearhead; ++ struct amdgpu_sync active; ++ struct amdgpu_sync prev; ++ } isolation[MAX_XCP]; + + struct amdgpu_init_level *init_lvl; + }; +@@ -1470,6 +1476,9 @@ void amdgpu_device_pcie_port_wreg(struct amdgpu_device *adev, + struct dma_fence *amdgpu_device_get_gang(struct amdgpu_device *adev); + struct dma_fence *amdgpu_device_switch_gang(struct amdgpu_device *adev, + struct dma_fence *gang); ++struct dma_fence *amdgpu_device_enforce_isolation(struct amdgpu_device *adev, ++ struct amdgpu_ring *ring, ++ struct amdgpu_job *job); + bool amdgpu_device_has_display_hardware(struct amdgpu_device *adev); + ssize_t amdgpu_get_soft_full_reset_mask(struct amdgpu_ring *ring); + ssize_t amdgpu_show_reset_mask(char *buf, uint32_t supported_reset); +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +index 34f0451b274c8..726c4854e6296 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +@@ -4232,6 +4232,11 @@ int amdgpu_device_init(struct amdgpu_device *adev, + mutex_init(&adev->gfx.reset_sem_mutex); + /* Initialize the mutex for cleaner shader isolation between GFX and compute processes */ + mutex_init(&adev->enforce_isolation_mutex); ++ for (i = 0; i < MAX_XCP; ++i) { ++ adev->isolation[i].spearhead = dma_fence_get_stub(); ++ amdgpu_sync_create(&adev->isolation[i].active); ++ amdgpu_sync_create(&adev->isolation[i].prev); ++ } + mutex_init(&adev->gfx.kfd_sch_mutex); + + amdgpu_device_init_apu_flags(adev); +@@ -4731,7 +4736,7 @@ void amdgpu_device_fini_hw(struct amdgpu_device *adev) + + void amdgpu_device_fini_sw(struct amdgpu_device *adev) + { +- int idx; ++ int i, idx; + bool px; + + amdgpu_device_ip_fini(adev); +@@ -4739,6 +4744,11 @@ void amdgpu_device_fini_sw(struct amdgpu_device *adev) + amdgpu_ucode_release(&adev->firmware.gpu_info_fw); + adev->accel_working = false; + dma_fence_put(rcu_dereference_protected(adev->gang_submit, true)); ++ for (i = 0; i < MAX_XCP; ++i) { ++ dma_fence_put(adev->isolation[i].spearhead); ++ amdgpu_sync_free(&adev->isolation[i].active); ++ amdgpu_sync_free(&adev->isolation[i].prev); ++ } + + amdgpu_reset_fini(adev); + +@@ -6860,6 +6870,92 @@ struct dma_fence *amdgpu_device_switch_gang(struct amdgpu_device *adev, + return NULL; + } + ++/** ++ * amdgpu_device_enforce_isolation - enforce HW isolation ++ * @adev: the amdgpu device pointer ++ * @ring: the HW ring the job is supposed to run on ++ * @job: the job which is about to be pushed to the HW ring ++ * ++ * Makes sure that only one client at a time can use the GFX block. ++ * Returns: The dependency to wait on before the job can be pushed to the HW. ++ * The function is called multiple times until NULL is returned. ++ */ ++struct dma_fence *amdgpu_device_enforce_isolation(struct amdgpu_device *adev, ++ struct amdgpu_ring *ring, ++ struct amdgpu_job *job) ++{ ++ struct amdgpu_isolation *isolation = &adev->isolation[ring->xcp_id]; ++ struct drm_sched_fence *f = job->base.s_fence; ++ struct dma_fence *dep; ++ void *owner; ++ int r; ++ ++ /* ++ * For now enforce isolation only for the GFX block since we only need ++ * the cleaner shader on those rings. ++ */ ++ if (ring->funcs->type != AMDGPU_RING_TYPE_GFX && ++ ring->funcs->type != AMDGPU_RING_TYPE_COMPUTE) ++ return NULL; ++ ++ /* ++ * All submissions where enforce isolation is false are handled as if ++ * they come from a single client. Use ~0l as the owner to distinct it ++ * from kernel submissions where the owner is NULL. ++ */ ++ owner = job->enforce_isolation ? f->owner : (void *)~0l; ++ ++ mutex_lock(&adev->enforce_isolation_mutex); ++ ++ /* ++ * The "spearhead" submission is the first one which changes the ++ * ownership to its client. We always need to wait for it to be ++ * pushed to the HW before proceeding with anything. ++ */ ++ if (&f->scheduled != isolation->spearhead && ++ !dma_fence_is_signaled(isolation->spearhead)) { ++ dep = isolation->spearhead; ++ goto out_grab_ref; ++ } ++ ++ if (isolation->owner != owner) { ++ ++ /* ++ * Wait for any gang to be assembled before switching to a ++ * different owner or otherwise we could deadlock the ++ * submissions. ++ */ ++ if (!job->gang_submit) { ++ dep = amdgpu_device_get_gang(adev); ++ if (!dma_fence_is_signaled(dep)) ++ goto out_return_dep; ++ dma_fence_put(dep); ++ } ++ ++ dma_fence_put(isolation->spearhead); ++ isolation->spearhead = dma_fence_get(&f->scheduled); ++ amdgpu_sync_move(&isolation->active, &isolation->prev); ++ isolation->owner = owner; ++ } ++ ++ /* ++ * Specifying the ring here helps to pipeline submissions even when ++ * isolation is enabled. If that is not desired for testing NULL can be ++ * used instead of the ring to enforce a CPU round trip while switching ++ * between clients. ++ */ ++ dep = amdgpu_sync_peek_fence(&isolation->prev, ring); ++ r = amdgpu_sync_fence(&isolation->active, &f->finished, GFP_NOWAIT); ++ if (r) ++ DRM_WARN("OOM tracking isolation\n"); ++ ++out_grab_ref: ++ dma_fence_get(dep); ++out_return_dep: ++ mutex_unlock(&adev->enforce_isolation_mutex); ++ return dep; ++} ++ + bool amdgpu_device_has_display_hardware(struct amdgpu_device *adev) + { + switch (adev->asic_type) { +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c +index 8e712a11aba5d..9008b7388e897 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c +@@ -287,40 +287,27 @@ static int amdgpu_vmid_grab_reserved(struct amdgpu_vm *vm, + (*id)->flushed_updates < updates || + !(*id)->last_flush || + ((*id)->last_flush->context != fence_context && +- !dma_fence_is_signaled((*id)->last_flush))) { ++ !dma_fence_is_signaled((*id)->last_flush))) ++ needs_flush = true; ++ ++ if ((*id)->owner != vm->immediate.fence_context || ++ (!adev->vm_manager.concurrent_flush && needs_flush)) { + struct dma_fence *tmp; + +- /* Wait for the gang to be assembled before using a +- * reserved VMID or otherwise the gang could deadlock. ++ /* Don't use per engine and per process VMID at the ++ * same time + */ +- tmp = amdgpu_device_get_gang(adev); +- if (!dma_fence_is_signaled(tmp) && tmp != job->gang_submit) { ++ if (adev->vm_manager.concurrent_flush) ++ ring = NULL; ++ ++ /* to prevent one context starved by another context */ ++ (*id)->pd_gpu_addr = 0; ++ tmp = amdgpu_sync_peek_fence(&(*id)->active, ring); ++ if (tmp) { + *id = NULL; +- *fence = tmp; ++ *fence = dma_fence_get(tmp); + return 0; + } +- dma_fence_put(tmp); +- +- /* Make sure the id is owned by the gang before proceeding */ +- if (!job->gang_submit || +- (*id)->owner != vm->immediate.fence_context) { +- +- /* Don't use per engine and per process VMID at the +- * same time +- */ +- if (adev->vm_manager.concurrent_flush) +- ring = NULL; +- +- /* to prevent one context starved by another context */ +- (*id)->pd_gpu_addr = 0; +- tmp = amdgpu_sync_peek_fence(&(*id)->active, ring); +- if (tmp) { +- *id = NULL; +- *fence = dma_fence_get(tmp); +- return 0; +- } +- } +- needs_flush = true; + } + + /* Good we can use this VMID. Remember this submission as +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c +index 100f044759435..685c61a05af85 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c +@@ -342,17 +342,24 @@ amdgpu_job_prepare_job(struct drm_sched_job *sched_job, + { + struct amdgpu_ring *ring = to_amdgpu_ring(s_entity->rq->sched); + struct amdgpu_job *job = to_amdgpu_job(sched_job); +- struct dma_fence *fence = NULL; ++ struct dma_fence *fence; + int r; + + r = drm_sched_entity_error(s_entity); + if (r) + goto error; + +- if (job->gang_submit) ++ if (job->gang_submit) { + fence = amdgpu_device_switch_gang(ring->adev, job->gang_submit); ++ if (fence) ++ return fence; ++ } ++ ++ fence = amdgpu_device_enforce_isolation(ring->adev, ring, job); ++ if (fence) ++ return fence; + +- if (!fence && job->vm && !job->vmid) { ++ if (job->vm && !job->vmid) { + r = amdgpu_vmid_grab(job->vm, ring, job, &fence); + if (r) { + dev_err(ring->adev->dev, "Error getting VM ID (%d)\n", r); +@@ -365,9 +372,10 @@ amdgpu_job_prepare_job(struct drm_sched_job *sched_job, + */ + if (!fence) + job->vm = NULL; ++ return fence; + } + +- return fence; ++ return NULL; + + error: + dma_fence_set_error(&job->base.s_fence->finished, r); +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c +index c586ab4c911bf..d75715b3f1870 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c +@@ -399,6 +399,25 @@ int amdgpu_sync_clone(struct amdgpu_sync *source, struct amdgpu_sync *clone) + return 0; + } + ++/** ++ * amdgpu_sync_move - move all fences from src to dst ++ * ++ * @src: source of the fences, empty after function ++ * @dst: destination for the fences ++ * ++ * Moves all fences from source to destination. All fences in destination are ++ * freed and source is empty after the function call. ++ */ ++void amdgpu_sync_move(struct amdgpu_sync *src, struct amdgpu_sync *dst) ++{ ++ unsigned int i; ++ ++ amdgpu_sync_free(dst); ++ ++ for (i = 0; i < HASH_SIZE(src->fences); ++i) ++ hlist_move_list(&src->fences[i], &dst->fences[i]); ++} ++ + /** + * amdgpu_sync_push_to_job - push fences into job + * @sync: sync object to get the fences from +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.h +index e3272dce798d7..a91a8eaf808b1 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.h ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.h +@@ -56,6 +56,7 @@ struct dma_fence *amdgpu_sync_peek_fence(struct amdgpu_sync *sync, + struct amdgpu_ring *ring); + struct dma_fence *amdgpu_sync_get_fence(struct amdgpu_sync *sync); + int amdgpu_sync_clone(struct amdgpu_sync *source, struct amdgpu_sync *clone); ++void amdgpu_sync_move(struct amdgpu_sync *src, struct amdgpu_sync *dst); + int amdgpu_sync_push_to_job(struct amdgpu_sync *sync, struct amdgpu_job *job); + int amdgpu_sync_wait(struct amdgpu_sync *sync, bool intr); + void amdgpu_sync_free(struct amdgpu_sync *sync); +-- +2.39.5 + diff --git a/queue-6.14/drm-amdgpu-rework-how-the-cleaner-shader-is-emitted-.patch b/queue-6.14/drm-amdgpu-rework-how-the-cleaner-shader-is-emitted-.patch new file mode 100644 index 0000000000..b9fb6b8710 --- /dev/null +++ b/queue-6.14/drm-amdgpu-rework-how-the-cleaner-shader-is-emitted-.patch @@ -0,0 +1,105 @@ +From 4e5064159649a302cb84e0caac996f33c430bec1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 27 Jan 2025 15:09:45 +0100 +Subject: drm/amdgpu: rework how the cleaner shader is emitted v3 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Christian König + +[ Upstream commit b7fbcd77bb467d09ba14cb4ec3b121dc85bb3100 ] + +Instead of emitting the cleaner shader for every job which has the +enforce_isolation flag set only emit it for the first submission from +every client. + +v2: add missing NULL check +v3: fix another NULL pointer deref + +Signed-off-by: Christian König +Acked-by: Srinivasan Shanmugam +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 27 ++++++++++++++++++++------ + 1 file changed, 21 insertions(+), 6 deletions(-) + +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +index 22aa4a8f11891..f0d675c0fc69c 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +@@ -754,6 +754,7 @@ int amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job, + bool need_pipe_sync) + { + struct amdgpu_device *adev = ring->adev; ++ struct amdgpu_isolation *isolation = &adev->isolation[ring->xcp_id]; + unsigned vmhub = ring->vm_hub; + struct amdgpu_vmid_mgr *id_mgr = &adev->vm_manager.id_mgr[vmhub]; + struct amdgpu_vmid *id = &id_mgr->ids[job->vmid]; +@@ -761,8 +762,9 @@ int amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job, + bool gds_switch_needed = ring->funcs->emit_gds_switch && + job->gds_switch_needed; + bool vm_flush_needed = job->vm_needs_flush; +- struct dma_fence *fence = NULL; ++ bool cleaner_shader_needed = false; + bool pasid_mapping_needed = false; ++ struct dma_fence *fence = NULL; + unsigned int patch; + int r; + +@@ -785,8 +787,12 @@ int amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job, + pasid_mapping_needed &= adev->gmc.gmc_funcs->emit_pasid_mapping && + ring->funcs->emit_wreg; + ++ cleaner_shader_needed = adev->gfx.enable_cleaner_shader && ++ ring->funcs->emit_cleaner_shader && job->base.s_fence && ++ &job->base.s_fence->scheduled == isolation->spearhead; ++ + if (!vm_flush_needed && !gds_switch_needed && !need_pipe_sync && +- !(job->enforce_isolation && !job->vmid)) ++ !cleaner_shader_needed) + return 0; + + amdgpu_ring_ib_begin(ring); +@@ -797,9 +803,7 @@ int amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job, + if (need_pipe_sync) + amdgpu_ring_emit_pipeline_sync(ring); + +- if (adev->gfx.enable_cleaner_shader && +- ring->funcs->emit_cleaner_shader && +- job->enforce_isolation) ++ if (cleaner_shader_needed) + ring->funcs->emit_cleaner_shader(ring); + + if (vm_flush_needed) { +@@ -821,7 +825,7 @@ int amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job, + job->oa_size); + } + +- if (vm_flush_needed || pasid_mapping_needed) { ++ if (vm_flush_needed || pasid_mapping_needed || cleaner_shader_needed) { + r = amdgpu_fence_emit(ring, &fence, NULL, 0); + if (r) + return r; +@@ -843,6 +847,17 @@ int amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job, + id->pasid_mapping = dma_fence_get(fence); + mutex_unlock(&id_mgr->lock); + } ++ ++ /* ++ * Make sure that all other submissions wait for the cleaner shader to ++ * finish before we push them to the HW. ++ */ ++ if (cleaner_shader_needed) { ++ mutex_lock(&adev->enforce_isolation_mutex); ++ dma_fence_put(isolation->spearhead); ++ isolation->spearhead = dma_fence_get(fence); ++ mutex_unlock(&adev->enforce_isolation_mutex); ++ } + dma_fence_put(fence); + + amdgpu_ring_patch_cond_exec(ring, patch); +-- +2.39.5 + diff --git a/queue-6.14/drm-amdgpu-set-snoop-bit-for-sdma-for-mi-series.patch b/queue-6.14/drm-amdgpu-set-snoop-bit-for-sdma-for-mi-series.patch new file mode 100644 index 0000000000..e1bb4fbe18 --- /dev/null +++ b/queue-6.14/drm-amdgpu-set-snoop-bit-for-sdma-for-mi-series.patch @@ -0,0 +1,368 @@ +From 7352224475466eb69abc7abc02f18c6e407dfc07 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 4 Feb 2025 17:57:47 -0500 +Subject: drm/amdgpu: Set snoop bit for SDMA for MI series + +From: Harish Kasiviswanathan + +[ Upstream commit 3394b1f76d3f8adf695ceed350a5dae49003eb37 ] + +SDMA writes has to probe invalidate RW lines. Set snoop bit in mmhub for +this to happen. + +v2: Missed a few mmhub_v9_4. Added now. +v3: Calculate hub offset once since it doesn't change inside the loop + Modified function names based on review comments. + +Signed-off-by: Harish Kasiviswanathan +Reviewed-by: Philip Yang +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/amdgpu/mmhub_v1_7.c | 25 ++++++++++ + drivers/gpu/drm/amd/amdgpu/mmhub_v1_8.c | 27 +++++++++++ + drivers/gpu/drm/amd/amdgpu/mmhub_v9_4.c | 31 ++++++++++++ + .../asic_reg/mmhub/mmhub_9_4_1_offset.h | 32 +++++++++++++ + .../asic_reg/mmhub/mmhub_9_4_1_sh_mask.h | 48 +++++++++++++++++++ + 5 files changed, 163 insertions(+) + +diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v1_7.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v1_7.c +index 9689e2b5d4e51..2adee2b94c37d 100644 +--- a/drivers/gpu/drm/amd/amdgpu/mmhub_v1_7.c ++++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v1_7.c +@@ -172,6 +172,30 @@ static void mmhub_v1_7_init_tlb_regs(struct amdgpu_device *adev) + WREG32_SOC15(MMHUB, 0, regMC_VM_MX_L1_TLB_CNTL, tmp); + } + ++/* Set snoop bit for SDMA so that SDMA writes probe-invalidates RW lines */ ++static void mmhub_v1_7_init_snoop_override_regs(struct amdgpu_device *adev) ++{ ++ uint32_t tmp; ++ int i; ++ uint32_t distance = regDAGB1_WRCLI_GPU_SNOOP_OVERRIDE - ++ regDAGB0_WRCLI_GPU_SNOOP_OVERRIDE; ++ ++ for (i = 0; i < 5; i++) { /* DAGB instances */ ++ tmp = RREG32_SOC15_OFFSET(MMHUB, 0, ++ regDAGB0_WRCLI_GPU_SNOOP_OVERRIDE, i * distance); ++ tmp |= (1 << 15); /* SDMA client is BIT15 */ ++ WREG32_SOC15_OFFSET(MMHUB, 0, ++ regDAGB0_WRCLI_GPU_SNOOP_OVERRIDE, i * distance, tmp); ++ ++ tmp = RREG32_SOC15_OFFSET(MMHUB, 0, ++ regDAGB0_WRCLI_GPU_SNOOP_OVERRIDE_VALUE, i * distance); ++ tmp |= (1 << 15); ++ WREG32_SOC15_OFFSET(MMHUB, 0, ++ regDAGB0_WRCLI_GPU_SNOOP_OVERRIDE_VALUE, i * distance, tmp); ++ } ++ ++} ++ + static void mmhub_v1_7_init_cache_regs(struct amdgpu_device *adev) + { + uint32_t tmp; +@@ -337,6 +361,7 @@ static int mmhub_v1_7_gart_enable(struct amdgpu_device *adev) + mmhub_v1_7_init_system_aperture_regs(adev); + mmhub_v1_7_init_tlb_regs(adev); + mmhub_v1_7_init_cache_regs(adev); ++ mmhub_v1_7_init_snoop_override_regs(adev); + + mmhub_v1_7_enable_system_domain(adev); + mmhub_v1_7_disable_identity_aperture(adev); +diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v1_8.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v1_8.c +index e646e5cef0a2e..ce013a715b864 100644 +--- a/drivers/gpu/drm/amd/amdgpu/mmhub_v1_8.c ++++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v1_8.c +@@ -213,6 +213,32 @@ static void mmhub_v1_8_init_tlb_regs(struct amdgpu_device *adev) + } + } + ++/* Set snoop bit for SDMA so that SDMA writes probe-invalidates RW lines */ ++static void mmhub_v1_8_init_snoop_override_regs(struct amdgpu_device *adev) ++{ ++ uint32_t tmp, inst_mask; ++ int i, j; ++ uint32_t distance = regDAGB1_WRCLI_GPU_SNOOP_OVERRIDE - ++ regDAGB0_WRCLI_GPU_SNOOP_OVERRIDE; ++ ++ inst_mask = adev->aid_mask; ++ for_each_inst(i, inst_mask) { ++ for (j = 0; j < 5; j++) { /* DAGB instances */ ++ tmp = RREG32_SOC15_OFFSET(MMHUB, i, ++ regDAGB0_WRCLI_GPU_SNOOP_OVERRIDE, j * distance); ++ tmp |= (1 << 15); /* SDMA client is BIT15 */ ++ WREG32_SOC15_OFFSET(MMHUB, i, ++ regDAGB0_WRCLI_GPU_SNOOP_OVERRIDE, j * distance, tmp); ++ ++ tmp = RREG32_SOC15_OFFSET(MMHUB, i, ++ regDAGB0_WRCLI_GPU_SNOOP_OVERRIDE_VALUE, j * distance); ++ tmp |= (1 << 15); ++ WREG32_SOC15_OFFSET(MMHUB, i, ++ regDAGB0_WRCLI_GPU_SNOOP_OVERRIDE_VALUE, j * distance, tmp); ++ } ++ } ++} ++ + static void mmhub_v1_8_init_cache_regs(struct amdgpu_device *adev) + { + uint32_t tmp, inst_mask; +@@ -418,6 +444,7 @@ static int mmhub_v1_8_gart_enable(struct amdgpu_device *adev) + mmhub_v1_8_init_system_aperture_regs(adev); + mmhub_v1_8_init_tlb_regs(adev); + mmhub_v1_8_init_cache_regs(adev); ++ mmhub_v1_8_init_snoop_override_regs(adev); + + mmhub_v1_8_enable_system_domain(adev); + mmhub_v1_8_disable_identity_aperture(adev); +diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v9_4.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v9_4.c +index ff1b58e446892..fe0710b55c3ac 100644 +--- a/drivers/gpu/drm/amd/amdgpu/mmhub_v9_4.c ++++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v9_4.c +@@ -198,6 +198,36 @@ static void mmhub_v9_4_init_tlb_regs(struct amdgpu_device *adev, int hubid) + hubid * MMHUB_INSTANCE_REGISTER_OFFSET, tmp); + } + ++/* Set snoop bit for SDMA so that SDMA writes probe-invalidates RW lines */ ++static void mmhub_v9_4_init_snoop_override_regs(struct amdgpu_device *adev, int hubid) ++{ ++ uint32_t tmp; ++ int i; ++ uint32_t distance = mmDAGB1_WRCLI_GPU_SNOOP_OVERRIDE - ++ mmDAGB0_WRCLI_GPU_SNOOP_OVERRIDE; ++ uint32_t huboffset = hubid * MMHUB_INSTANCE_REGISTER_OFFSET; ++ ++ for (i = 0; i < 5 - (2 * hubid); i++) { ++ /* DAGB instances 0 to 4 are in hub0 and 5 to 7 are in hub1 */ ++ tmp = RREG32_SOC15_OFFSET(MMHUB, 0, ++ mmDAGB0_WRCLI_GPU_SNOOP_OVERRIDE, ++ huboffset + i * distance); ++ tmp |= (1 << 15); /* SDMA client is BIT15 */ ++ WREG32_SOC15_OFFSET(MMHUB, 0, ++ mmDAGB0_WRCLI_GPU_SNOOP_OVERRIDE, ++ huboffset + i * distance, tmp); ++ ++ tmp = RREG32_SOC15_OFFSET(MMHUB, 0, ++ mmDAGB0_WRCLI_GPU_SNOOP_OVERRIDE_VALUE, ++ huboffset + i * distance); ++ tmp |= (1 << 15); ++ WREG32_SOC15_OFFSET(MMHUB, 0, ++ mmDAGB0_WRCLI_GPU_SNOOP_OVERRIDE_VALUE, ++ huboffset + i * distance, tmp); ++ } ++ ++} ++ + static void mmhub_v9_4_init_cache_regs(struct amdgpu_device *adev, int hubid) + { + uint32_t tmp; +@@ -392,6 +422,7 @@ static int mmhub_v9_4_gart_enable(struct amdgpu_device *adev) + if (!amdgpu_sriov_vf(adev)) + mmhub_v9_4_init_cache_regs(adev, i); + ++ mmhub_v9_4_init_snoop_override_regs(adev, i); + mmhub_v9_4_enable_system_domain(adev, i); + if (!amdgpu_sriov_vf(adev)) + mmhub_v9_4_disable_identity_aperture(adev, i); +diff --git a/drivers/gpu/drm/amd/include/asic_reg/mmhub/mmhub_9_4_1_offset.h b/drivers/gpu/drm/amd/include/asic_reg/mmhub/mmhub_9_4_1_offset.h +index c488d4a50cf46..b2252deabc17a 100644 +--- a/drivers/gpu/drm/amd/include/asic_reg/mmhub/mmhub_9_4_1_offset.h ++++ b/drivers/gpu/drm/amd/include/asic_reg/mmhub/mmhub_9_4_1_offset.h +@@ -203,6 +203,10 @@ + #define mmDAGB0_WR_DATA_CREDIT_BASE_IDX 1 + #define mmDAGB0_WR_MISC_CREDIT 0x0058 + #define mmDAGB0_WR_MISC_CREDIT_BASE_IDX 1 ++#define mmDAGB0_WRCLI_GPU_SNOOP_OVERRIDE 0x005b ++#define mmDAGB0_WRCLI_GPU_SNOOP_OVERRIDE_BASE_IDX 1 ++#define mmDAGB0_WRCLI_GPU_SNOOP_OVERRIDE_VALUE 0x005c ++#define mmDAGB0_WRCLI_GPU_SNOOP_OVERRIDE_VALUE_BASE_IDX 1 + #define mmDAGB0_WRCLI_ASK_PENDING 0x005d + #define mmDAGB0_WRCLI_ASK_PENDING_BASE_IDX 1 + #define mmDAGB0_WRCLI_GO_PENDING 0x005e +@@ -455,6 +459,10 @@ + #define mmDAGB1_WR_DATA_CREDIT_BASE_IDX 1 + #define mmDAGB1_WR_MISC_CREDIT 0x00d8 + #define mmDAGB1_WR_MISC_CREDIT_BASE_IDX 1 ++#define mmDAGB1_WRCLI_GPU_SNOOP_OVERRIDE 0x00db ++#define mmDAGB1_WRCLI_GPU_SNOOP_OVERRIDE_BASE_IDX 1 ++#define mmDAGB1_WRCLI_GPU_SNOOP_OVERRIDE_VALUE 0x00dc ++#define mmDAGB1_WRCLI_GPU_SNOOP_OVERRIDE_VALUE_BASE_IDX 1 + #define mmDAGB1_WRCLI_ASK_PENDING 0x00dd + #define mmDAGB1_WRCLI_ASK_PENDING_BASE_IDX 1 + #define mmDAGB1_WRCLI_GO_PENDING 0x00de +@@ -707,6 +715,10 @@ + #define mmDAGB2_WR_DATA_CREDIT_BASE_IDX 1 + #define mmDAGB2_WR_MISC_CREDIT 0x0158 + #define mmDAGB2_WR_MISC_CREDIT_BASE_IDX 1 ++#define mmDAGB2_WRCLI_GPU_SNOOP_OVERRIDE 0x015b ++#define mmDAGB2_WRCLI_GPU_SNOOP_OVERRIDE_BASE_IDX 1 ++#define mmDAGB2_WRCLI_GPU_SNOOP_OVERRIDE_VALUE 0x015c ++#define mmDAGB2_WRCLI_GPU_SNOOP_OVERRIDE_VALUE_BASE_IDX 1 + #define mmDAGB2_WRCLI_ASK_PENDING 0x015d + #define mmDAGB2_WRCLI_ASK_PENDING_BASE_IDX 1 + #define mmDAGB2_WRCLI_GO_PENDING 0x015e +@@ -959,6 +971,10 @@ + #define mmDAGB3_WR_DATA_CREDIT_BASE_IDX 1 + #define mmDAGB3_WR_MISC_CREDIT 0x01d8 + #define mmDAGB3_WR_MISC_CREDIT_BASE_IDX 1 ++#define mmDAGB3_WRCLI_GPU_SNOOP_OVERRIDE 0x01db ++#define mmDAGB3_WRCLI_GPU_SNOOP_OVERRIDE_BASE_IDX 1 ++#define mmDAGB3_WRCLI_GPU_SNOOP_OVERRIDE_VALUE 0x01dc ++#define mmDAGB3_WRCLI_GPU_SNOOP_OVERRIDE_VALUE_BASE_IDX 1 + #define mmDAGB3_WRCLI_ASK_PENDING 0x01dd + #define mmDAGB3_WRCLI_ASK_PENDING_BASE_IDX 1 + #define mmDAGB3_WRCLI_GO_PENDING 0x01de +@@ -1211,6 +1227,10 @@ + #define mmDAGB4_WR_DATA_CREDIT_BASE_IDX 1 + #define mmDAGB4_WR_MISC_CREDIT 0x0258 + #define mmDAGB4_WR_MISC_CREDIT_BASE_IDX 1 ++#define mmDAGB4_WRCLI_GPU_SNOOP_OVERRIDE 0x025b ++#define mmDAGB4_WRCLI_GPU_SNOOP_OVERRIDE_BASE_IDX 1 ++#define mmDAGB4_WRCLI_GPU_SNOOP_OVERRIDE_VALUE 0x025c ++#define mmDAGB4_WRCLI_GPU_SNOOP_OVERRIDE_VALUE_BASE_IDX 1 + #define mmDAGB4_WRCLI_ASK_PENDING 0x025d + #define mmDAGB4_WRCLI_ASK_PENDING_BASE_IDX 1 + #define mmDAGB4_WRCLI_GO_PENDING 0x025e +@@ -4793,6 +4813,10 @@ + #define mmDAGB5_WR_DATA_CREDIT_BASE_IDX 1 + #define mmDAGB5_WR_MISC_CREDIT 0x3058 + #define mmDAGB5_WR_MISC_CREDIT_BASE_IDX 1 ++#define mmDAGB5_WRCLI_GPU_SNOOP_OVERRIDE 0x305b ++#define mmDAGB5_WRCLI_GPU_SNOOP_OVERRIDE_BASE_IDX 1 ++#define mmDAGB5_WRCLI_GPU_SNOOP_OVERRIDE_VALUE 0x305c ++#define mmDAGB5_WRCLI_GPU_SNOOP_OVERRIDE_VALUE_BASE_IDX 1 + #define mmDAGB5_WRCLI_ASK_PENDING 0x305d + #define mmDAGB5_WRCLI_ASK_PENDING_BASE_IDX 1 + #define mmDAGB5_WRCLI_GO_PENDING 0x305e +@@ -5045,6 +5069,10 @@ + #define mmDAGB6_WR_DATA_CREDIT_BASE_IDX 1 + #define mmDAGB6_WR_MISC_CREDIT 0x30d8 + #define mmDAGB6_WR_MISC_CREDIT_BASE_IDX 1 ++#define mmDAGB6_WRCLI_GPU_SNOOP_OVERRIDE 0x30db ++#define mmDAGB6_WRCLI_GPU_SNOOP_OVERRIDE_BASE_IDX 1 ++#define mmDAGB6_WRCLI_GPU_SNOOP_OVERRIDE_VALUE 0x30dc ++#define mmDAGB6_WRCLI_GPU_SNOOP_OVERRIDE_VALUE_BASE_IDX 1 + #define mmDAGB6_WRCLI_ASK_PENDING 0x30dd + #define mmDAGB6_WRCLI_ASK_PENDING_BASE_IDX 1 + #define mmDAGB6_WRCLI_GO_PENDING 0x30de +@@ -5297,6 +5325,10 @@ + #define mmDAGB7_WR_DATA_CREDIT_BASE_IDX 1 + #define mmDAGB7_WR_MISC_CREDIT 0x3158 + #define mmDAGB7_WR_MISC_CREDIT_BASE_IDX 1 ++#define mmDAGB7_WRCLI_GPU_SNOOP_OVERRIDE 0x315b ++#define mmDAGB7_WRCLI_GPU_SNOOP_OVERRIDE_BASE_IDX 1 ++#define mmDAGB7_WRCLI_GPU_SNOOP_OVERRIDE_VALUE 0x315c ++#define mmDAGB7_WRCLI_GPU_SNOOP_OVERRIDE_VALUE_BASE_IDX 1 + #define mmDAGB7_WRCLI_ASK_PENDING 0x315d + #define mmDAGB7_WRCLI_ASK_PENDING_BASE_IDX 1 + #define mmDAGB7_WRCLI_GO_PENDING 0x315e +diff --git a/drivers/gpu/drm/amd/include/asic_reg/mmhub/mmhub_9_4_1_sh_mask.h b/drivers/gpu/drm/amd/include/asic_reg/mmhub/mmhub_9_4_1_sh_mask.h +index 2969fbf282b7d..5069d2fd467f2 100644 +--- a/drivers/gpu/drm/amd/include/asic_reg/mmhub/mmhub_9_4_1_sh_mask.h ++++ b/drivers/gpu/drm/amd/include/asic_reg/mmhub/mmhub_9_4_1_sh_mask.h +@@ -1532,6 +1532,12 @@ + //DAGB0_WRCLI_DBUS_GO_PENDING + #define DAGB0_WRCLI_DBUS_GO_PENDING__BUSY__SHIFT 0x0 + #define DAGB0_WRCLI_DBUS_GO_PENDING__BUSY_MASK 0xFFFFFFFFL ++//DAGB0_WRCLI_GPU_SNOOP_OVERRIDE ++#define DAGB0_WRCLI_GPU_SNOOP_OVERRIDE__ENABLE__SHIFT 0x0 ++#define DAGB0_WRCLI_GPU_SNOOP_OVERRIDE__ENABLE_MASK 0xFFFFFFFFL ++//DAGB0_WRCLI_GPU_SNOOP_OVERRIDE_VALUE ++#define DAGB0_WRCLI_GPU_SNOOP_OVERRIDE_VALUE__ENABLE__SHIFT 0x0 ++#define DAGB0_WRCLI_GPU_SNOOP_OVERRIDE_VALUE__ENABLE_MASK 0xFFFFFFFFL + //DAGB0_DAGB_DLY + #define DAGB0_DAGB_DLY__DLY__SHIFT 0x0 + #define DAGB0_DAGB_DLY__CLI__SHIFT 0x8 +@@ -3207,6 +3213,12 @@ + //DAGB1_WRCLI_DBUS_GO_PENDING + #define DAGB1_WRCLI_DBUS_GO_PENDING__BUSY__SHIFT 0x0 + #define DAGB1_WRCLI_DBUS_GO_PENDING__BUSY_MASK 0xFFFFFFFFL ++//DAGB1_WRCLI_GPU_SNOOP_OVERRIDE ++#define DAGB1_WRCLI_GPU_SNOOP_OVERRIDE__ENABLE__SHIFT 0x0 ++#define DAGB1_WRCLI_GPU_SNOOP_OVERRIDE__ENABLE_MASK 0xFFFFFFFFL ++//DAGB1_WRCLI_GPU_SNOOP_OVERRIDE_VALUE ++#define DAGB1_WRCLI_GPU_SNOOP_OVERRIDE_VALUE__ENABLE__SHIFT 0x0 ++#define DAGB1_WRCLI_GPU_SNOOP_OVERRIDE_VALUE__ENABLE_MASK 0xFFFFFFFFL + //DAGB1_DAGB_DLY + #define DAGB1_DAGB_DLY__DLY__SHIFT 0x0 + #define DAGB1_DAGB_DLY__CLI__SHIFT 0x8 +@@ -4882,6 +4894,12 @@ + //DAGB2_WRCLI_DBUS_GO_PENDING + #define DAGB2_WRCLI_DBUS_GO_PENDING__BUSY__SHIFT 0x0 + #define DAGB2_WRCLI_DBUS_GO_PENDING__BUSY_MASK 0xFFFFFFFFL ++//DAGB2_WRCLI_GPU_SNOOP_OVERRIDE ++#define DAGB2_WRCLI_GPU_SNOOP_OVERRIDE__ENABLE__SHIFT 0x0 ++#define DAGB2_WRCLI_GPU_SNOOP_OVERRIDE__ENABLE_MASK 0xFFFFFFFFL ++//DAGB2_WRCLI_GPU_SNOOP_OVERRIDE_VALUE ++#define DAGB2_WRCLI_GPU_SNOOP_OVERRIDE_VALUE__ENABLE__SHIFT 0x0 ++#define DAGB2_WRCLI_GPU_SNOOP_OVERRIDE_VALUE__ENABLE_MASK 0xFFFFFFFFL + //DAGB2_DAGB_DLY + #define DAGB2_DAGB_DLY__DLY__SHIFT 0x0 + #define DAGB2_DAGB_DLY__CLI__SHIFT 0x8 +@@ -6557,6 +6575,12 @@ + //DAGB3_WRCLI_DBUS_GO_PENDING + #define DAGB3_WRCLI_DBUS_GO_PENDING__BUSY__SHIFT 0x0 + #define DAGB3_WRCLI_DBUS_GO_PENDING__BUSY_MASK 0xFFFFFFFFL ++//DAGB3_WRCLI_GPU_SNOOP_OVERRIDE ++#define DAGB3_WRCLI_GPU_SNOOP_OVERRIDE__ENABLE__SHIFT 0x0 ++#define DAGB3_WRCLI_GPU_SNOOP_OVERRIDE__ENABLE_MASK 0xFFFFFFFFL ++//DAGB3_WRCLI_GPU_SNOOP_OVERRIDE_VALUE ++#define DAGB3_WRCLI_GPU_SNOOP_OVERRIDE_VALUE__ENABLE__SHIFT 0x0 ++#define DAGB3_WRCLI_GPU_SNOOP_OVERRIDE_VALUE__ENABLE_MASK 0xFFFFFFFFL + //DAGB3_DAGB_DLY + #define DAGB3_DAGB_DLY__DLY__SHIFT 0x0 + #define DAGB3_DAGB_DLY__CLI__SHIFT 0x8 +@@ -8232,6 +8256,12 @@ + //DAGB4_WRCLI_DBUS_GO_PENDING + #define DAGB4_WRCLI_DBUS_GO_PENDING__BUSY__SHIFT 0x0 + #define DAGB4_WRCLI_DBUS_GO_PENDING__BUSY_MASK 0xFFFFFFFFL ++//DAGB4_WRCLI_GPU_SNOOP_OVERRIDE ++#define DAGB4_WRCLI_GPU_SNOOP_OVERRIDE__ENABLE__SHIFT 0x0 ++#define DAGB4_WRCLI_GPU_SNOOP_OVERRIDE__ENABLE_MASK 0xFFFFFFFFL ++//DAGB4_WRCLI_GPU_SNOOP_OVERRIDE_VALUE ++#define DAGB4_WRCLI_GPU_SNOOP_OVERRIDE_VALUE__ENABLE__SHIFT 0x0 ++#define DAGB4_WRCLI_GPU_SNOOP_OVERRIDE_VALUE__ENABLE_MASK 0xFFFFFFFFL + //DAGB4_DAGB_DLY + #define DAGB4_DAGB_DLY__DLY__SHIFT 0x0 + #define DAGB4_DAGB_DLY__CLI__SHIFT 0x8 +@@ -28737,6 +28767,12 @@ + //DAGB5_WRCLI_DBUS_GO_PENDING + #define DAGB5_WRCLI_DBUS_GO_PENDING__BUSY__SHIFT 0x0 + #define DAGB5_WRCLI_DBUS_GO_PENDING__BUSY_MASK 0xFFFFFFFFL ++//DAGB5_WRCLI_GPU_SNOOP_OVERRIDE ++#define DAGB5_WRCLI_GPU_SNOOP_OVERRIDE__ENABLE__SHIFT 0x0 ++#define DAGB5_WRCLI_GPU_SNOOP_OVERRIDE__ENABLE_MASK 0xFFFFFFFFL ++//DAGB5_WRCLI_GPU_SNOOP_OVERRIDE_VALUE ++#define DAGB5_WRCLI_GPU_SNOOP_OVERRIDE_VALUE__ENABLE__SHIFT 0x0 ++#define DAGB5_WRCLI_GPU_SNOOP_OVERRIDE_VALUE__ENABLE_MASK 0xFFFFFFFFL + //DAGB5_DAGB_DLY + #define DAGB5_DAGB_DLY__DLY__SHIFT 0x0 + #define DAGB5_DAGB_DLY__CLI__SHIFT 0x8 +@@ -30412,6 +30448,12 @@ + //DAGB6_WRCLI_DBUS_GO_PENDING + #define DAGB6_WRCLI_DBUS_GO_PENDING__BUSY__SHIFT 0x0 + #define DAGB6_WRCLI_DBUS_GO_PENDING__BUSY_MASK 0xFFFFFFFFL ++//DAGB6_WRCLI_GPU_SNOOP_OVERRIDE ++#define DAGB6_WRCLI_GPU_SNOOP_OVERRIDE__ENABLE__SHIFT 0x0 ++#define DAGB6_WRCLI_GPU_SNOOP_OVERRIDE__ENABLE_MASK 0xFFFFFFFFL ++//DAGB6_WRCLI_GPU_SNOOP_OVERRIDE_VALUE ++#define DAGB6_WRCLI_GPU_SNOOP_OVERRIDE_VALUE__ENABLE__SHIFT 0x0 ++#define DAGB6_WRCLI_GPU_SNOOP_OVERRIDE_VALUE__ENABLE_MASK 0xFFFFFFFFL + //DAGB6_DAGB_DLY + #define DAGB6_DAGB_DLY__DLY__SHIFT 0x0 + #define DAGB6_DAGB_DLY__CLI__SHIFT 0x8 +@@ -32087,6 +32129,12 @@ + //DAGB7_WRCLI_DBUS_GO_PENDING + #define DAGB7_WRCLI_DBUS_GO_PENDING__BUSY__SHIFT 0x0 + #define DAGB7_WRCLI_DBUS_GO_PENDING__BUSY_MASK 0xFFFFFFFFL ++//DAGB7_WRCLI_GPU_SNOOP_OVERRIDE ++#define DAGB7_WRCLI_GPU_SNOOP_OVERRIDE__ENABLE__SHIFT 0x0 ++#define DAGB7_WRCLI_GPU_SNOOP_OVERRIDE__ENABLE_MASK 0xFFFFFFFFL ++//DAGB7_WRCLI_GPU_SNOOP_OVERRIDE_VALUE ++#define DAGB7_WRCLI_GPU_SNOOP_OVERRIDE_VALUE__ENABLE__SHIFT 0x0 ++#define DAGB7_WRCLI_GPU_SNOOP_OVERRIDE_VALUE__ENABLE_MASK 0xFFFFFFFFL + //DAGB7_DAGB_DLY + #define DAGB7_DAGB_DLY__DLY__SHIFT 0x0 + #define DAGB7_DAGB_DLY__CLI__SHIFT 0x8 +-- +2.39.5 + diff --git a/queue-6.14/drm-amdgpu-skip-err_count-sysfs-creation-on-vf-unsup.patch b/queue-6.14/drm-amdgpu-skip-err_count-sysfs-creation-on-vf-unsup.patch new file mode 100644 index 0000000000..18a385e3d4 --- /dev/null +++ b/queue-6.14/drm-amdgpu-skip-err_count-sysfs-creation-on-vf-unsup.patch @@ -0,0 +1,84 @@ +From bcbf7235d55d61a31c53cfd3de7f2fc43f340918 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 20 Jan 2025 22:00:22 -0500 +Subject: drm/amdgpu: Skip err_count sysfs creation on VF unsupported RAS + blocks + +From: Victor Skvortsov + +[ Upstream commit 04893397766a2b2f1bc7fe5c6414e4c0846ed171 ] + +VFs are not able to query error counts for all RAS blocks. Rather than +returning error for queries on these blocks, skip sysfs the creation +all together. + +Signed-off-by: Victor Skvortsov +Reviewed-by: Hawking Zhang +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 3 +++ + drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c | 17 ++++++++++++++++- + drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h | 2 ++ + 3 files changed, 21 insertions(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +index f0924aa3f4e48..0c338dcdde48a 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +@@ -1864,6 +1864,9 @@ int amdgpu_ras_sysfs_create(struct amdgpu_device *adev, + if (!obj || obj->attr_inuse) + return -EINVAL; + ++ if (amdgpu_sriov_vf(adev) && !amdgpu_virt_ras_telemetry_block_en(adev, head->block)) ++ return 0; ++ + get_obj(obj); + + snprintf(obj->fs_data.sysfs_name, sizeof(obj->fs_data.sysfs_name), +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c +index 13e5709ea1caa..e6f0152e5b087 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c +@@ -1247,7 +1247,8 @@ amdgpu_ras_block_to_sriov(struct amdgpu_device *adev, enum amdgpu_ras_block bloc + case AMDGPU_RAS_BLOCK__MPIO: + return RAS_TELEMETRY_GPU_BLOCK_MPIO; + default: +- dev_err(adev->dev, "Unsupported SRIOV RAS telemetry block 0x%x\n", block); ++ DRM_WARN_ONCE("Unsupported SRIOV RAS telemetry block 0x%x\n", ++ block); + return RAS_TELEMETRY_GPU_BLOCK_COUNT; + } + } +@@ -1332,3 +1333,17 @@ int amdgpu_virt_ras_telemetry_post_reset(struct amdgpu_device *adev) + + return 0; + } ++ ++bool amdgpu_virt_ras_telemetry_block_en(struct amdgpu_device *adev, ++ enum amdgpu_ras_block block) ++{ ++ enum amd_sriov_ras_telemetry_gpu_block sriov_block; ++ ++ sriov_block = amdgpu_ras_block_to_sriov(adev, block); ++ ++ if (sriov_block >= RAS_TELEMETRY_GPU_BLOCK_COUNT || ++ !amdgpu_sriov_ras_telemetry_block_en(adev, sriov_block)) ++ return false; ++ ++ return true; ++} +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h +index 0ca73343a7689..0f3ccae5c1ab3 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h +@@ -407,4 +407,6 @@ bool amdgpu_virt_get_ras_capability(struct amdgpu_device *adev); + int amdgpu_virt_req_ras_err_count(struct amdgpu_device *adev, enum amdgpu_ras_block block, + struct ras_err_data *err_data); + int amdgpu_virt_ras_telemetry_post_reset(struct amdgpu_device *adev); ++bool amdgpu_virt_ras_telemetry_block_en(struct amdgpu_device *adev, ++ enum amdgpu_ras_block block); + #endif +-- +2.39.5 + diff --git a/queue-6.14/drm-amdgpu-skip-pcie_replay_count-sysfs-creation-for.patch b/queue-6.14/drm-amdgpu-skip-pcie_replay_count-sysfs-creation-for.patch new file mode 100644 index 0000000000..a0f7b978e2 --- /dev/null +++ b/queue-6.14/drm-amdgpu-skip-pcie_replay_count-sysfs-creation-for.patch @@ -0,0 +1,82 @@ +From a0f26bf2a056096fe9f38e337824dc26a05577dc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Mar 2025 09:32:13 -0400 +Subject: drm/amdgpu: Skip pcie_replay_count sysfs creation for VF + +From: Victor Skvortsov + +[ Upstream commit 9c05636ca72a2dbf41bf0900380f438a0de47319 ] + +VFs cannot read the NAK_COUNTER register. This information is only +available through PMFW metrics. + +Signed-off-by: Victor Skvortsov +Reviewed-by: Lijo Lazar +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 27 ++++++++++++++++------ + 1 file changed, 20 insertions(+), 7 deletions(-) + +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +index 726c4854e6296..c00a01c62724a 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +@@ -224,6 +224,24 @@ static ssize_t amdgpu_device_get_pcie_replay_count(struct device *dev, + static DEVICE_ATTR(pcie_replay_count, 0444, + amdgpu_device_get_pcie_replay_count, NULL); + ++static int amdgpu_device_attr_sysfs_init(struct amdgpu_device *adev) ++{ ++ int ret = 0; ++ ++ if (!amdgpu_sriov_vf(adev)) ++ ret = sysfs_create_file(&adev->dev->kobj, ++ &dev_attr_pcie_replay_count.attr); ++ ++ return ret; ++} ++ ++static void amdgpu_device_attr_sysfs_fini(struct amdgpu_device *adev) ++{ ++ if (!amdgpu_sriov_vf(adev)) ++ sysfs_remove_file(&adev->dev->kobj, ++ &dev_attr_pcie_replay_count.attr); ++} ++ + static ssize_t amdgpu_sysfs_reg_state_get(struct file *f, struct kobject *kobj, + struct bin_attribute *attr, char *buf, + loff_t ppos, size_t count) +@@ -4123,11 +4141,6 @@ static bool amdgpu_device_check_iommu_remap(struct amdgpu_device *adev) + } + #endif + +-static const struct attribute *amdgpu_dev_attributes[] = { +- &dev_attr_pcie_replay_count.attr, +- NULL +-}; +- + static void amdgpu_device_set_mcbp(struct amdgpu_device *adev) + { + if (amdgpu_mcbp == 1) +@@ -4572,7 +4585,7 @@ int amdgpu_device_init(struct amdgpu_device *adev, + } else + adev->ucode_sysfs_en = true; + +- r = sysfs_create_files(&adev->dev->kobj, amdgpu_dev_attributes); ++ r = amdgpu_device_attr_sysfs_init(adev); + if (r) + dev_err(adev->dev, "Could not create amdgpu device attr\n"); + +@@ -4709,7 +4722,7 @@ void amdgpu_device_fini_hw(struct amdgpu_device *adev) + amdgpu_pm_sysfs_fini(adev); + if (adev->ucode_sysfs_en) + amdgpu_ucode_sysfs_fini(adev); +- sysfs_remove_files(&adev->dev->kobj, amdgpu_dev_attributes); ++ amdgpu_device_attr_sysfs_fini(adev); + amdgpu_fru_sysfs_fini(adev); + + amdgpu_reg_state_sysfs_fini(adev); +-- +2.39.5 + diff --git a/queue-6.14/drm-amdgpu-update-sriov-video-codec-caps.patch b/queue-6.14/drm-amdgpu-update-sriov-video-codec-caps.patch new file mode 100644 index 0000000000..1a548b2b8e --- /dev/null +++ b/queue-6.14/drm-amdgpu-update-sriov-video-codec-caps.patch @@ -0,0 +1,91 @@ +From 11e66a26597f6fd958bdfbb6ffef450b581e6e1f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 28 Feb 2025 13:44:32 +0100 +Subject: drm/amdgpu: Update SRIOV video codec caps + +From: David Rosca + +[ Upstream commit 19478f2011f8b53dee401c91423c4e0b73753e4f ] + +There have been multiple fixes to the video caps that are missing for +SRIOV. Update the SRIOV caps with correct values. + +Signed-off-by: David Rosca +Acked-by: Alex Deucher +Reviewed-by: Ruijing Dong +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/amdgpu/nv.c | 16 ++++++++-------- + drivers/gpu/drm/amd/amdgpu/soc21.c | 10 ++-------- + 2 files changed, 10 insertions(+), 16 deletions(-) + +diff --git a/drivers/gpu/drm/amd/amdgpu/nv.c b/drivers/gpu/drm/amd/amdgpu/nv.c +index 95c609317a8d7..efca7dc27d68d 100644 +--- a/drivers/gpu/drm/amd/amdgpu/nv.c ++++ b/drivers/gpu/drm/amd/amdgpu/nv.c +@@ -141,23 +141,23 @@ static struct amdgpu_video_codec_info sriov_sc_video_codecs_encode_array[] = { + }; + + static struct amdgpu_video_codec_info sriov_sc_video_codecs_decode_array_vcn0[] = { +- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG2, 4096, 4096, 3)}, +- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4, 4096, 4096, 5)}, ++ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG2, 1920, 1088, 3)}, ++ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4, 1920, 1088, 5)}, + {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4_AVC, 4096, 4096, 52)}, +- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_VC1, 4096, 4096, 4)}, ++ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_VC1, 1920, 1088, 4)}, + {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_HEVC, 8192, 4352, 186)}, +- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_JPEG, 4096, 4096, 0)}, ++ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_JPEG, 16384, 16384, 0)}, + {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_VP9, 8192, 4352, 0)}, + {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_AV1, 8192, 4352, 0)}, + }; + + static struct amdgpu_video_codec_info sriov_sc_video_codecs_decode_array_vcn1[] = { +- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG2, 4096, 4096, 3)}, +- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4, 4096, 4096, 5)}, ++ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG2, 1920, 1088, 3)}, ++ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4, 1920, 1088, 5)}, + {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4_AVC, 4096, 4096, 52)}, +- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_VC1, 4096, 4096, 4)}, ++ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_VC1, 1920, 1088, 4)}, + {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_HEVC, 8192, 4352, 186)}, +- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_JPEG, 4096, 4096, 0)}, ++ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_JPEG, 16384, 16384, 0)}, + {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_VP9, 8192, 4352, 0)}, + }; + +diff --git a/drivers/gpu/drm/amd/amdgpu/soc21.c b/drivers/gpu/drm/amd/amdgpu/soc21.c +index 62ad67d0b598f..c66cff399f63d 100644 +--- a/drivers/gpu/drm/amd/amdgpu/soc21.c ++++ b/drivers/gpu/drm/amd/amdgpu/soc21.c +@@ -117,23 +117,17 @@ static struct amdgpu_video_codecs sriov_vcn_4_0_0_video_codecs_encode_vcn1 = { + }; + + static struct amdgpu_video_codec_info sriov_vcn_4_0_0_video_codecs_decode_array_vcn0[] = { +- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG2, 4096, 4096, 3)}, +- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4, 4096, 4096, 5)}, + {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4_AVC, 4096, 4096, 52)}, +- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_VC1, 4096, 4096, 4)}, + {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_HEVC, 8192, 4352, 186)}, +- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_JPEG, 4096, 4096, 0)}, ++ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_JPEG, 16384, 16384, 0)}, + {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_VP9, 8192, 4352, 0)}, + {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_AV1, 8192, 4352, 0)}, + }; + + static struct amdgpu_video_codec_info sriov_vcn_4_0_0_video_codecs_decode_array_vcn1[] = { +- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG2, 4096, 4096, 3)}, +- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4, 4096, 4096, 5)}, + {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4_AVC, 4096, 4096, 52)}, +- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_VC1, 4096, 4096, 4)}, + {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_HEVC, 8192, 4352, 186)}, +- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_JPEG, 4096, 4096, 0)}, ++ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_JPEG, 16384, 16384, 0)}, + {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_VP9, 8192, 4352, 0)}, + }; + +-- +2.39.5 + diff --git a/queue-6.14/drm-amdgpu-use-active-umc-info-from-discovery.patch b/queue-6.14/drm-amdgpu-use-active-umc-info-from-discovery.patch new file mode 100644 index 0000000000..1f7f725ddd --- /dev/null +++ b/queue-6.14/drm-amdgpu-use-active-umc-info-from-discovery.patch @@ -0,0 +1,101 @@ +From b3e91a202c6c20b09304464738aa4e92300ab4ad Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 1 Jan 2025 14:23:31 +0530 +Subject: drm/amdgpu: Use active umc info from discovery + +From: Lijo Lazar + +[ Upstream commit f7a594e40517fa2ab25d5ca10e7b6a158f529fb5 ] + +There could be configs where some UMC instances are harvested. This +information is obtained through discovery data and populated in +umc.active_mask. Avoid reassigning this as AID mask, instead use the +mask directly while iterating through umc instances. This is to avoid +accesses to harvested UMC instances. + +v2: fix warning (Alex) + +Signed-off-by: Lijo Lazar +Reviewed-by: Hawking Zhang +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c | 42 +++++++++++++++++++++++++ + drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c | 1 - + 2 files changed, 42 insertions(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c +index eafe20d8fe0b6..0a1ef95b28668 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c +@@ -387,6 +387,45 @@ int amdgpu_umc_fill_error_record(struct ras_err_data *err_data, + return 0; + } + ++static int amdgpu_umc_loop_all_aid(struct amdgpu_device *adev, umc_func func, ++ void *data) ++{ ++ uint32_t umc_node_inst; ++ uint32_t node_inst; ++ uint32_t umc_inst; ++ uint32_t ch_inst; ++ int ret; ++ ++ /* ++ * This loop is done based on the following - ++ * umc.active mask = mask of active umc instances across all nodes ++ * umc.umc_inst_num = maximum number of umc instancess per node ++ * umc.node_inst_num = maximum number of node instances ++ * Channel instances are not assumed to be harvested. ++ */ ++ dev_dbg(adev->dev, "active umcs :%lx umc_inst per node: %d", ++ adev->umc.active_mask, adev->umc.umc_inst_num); ++ for_each_set_bit(umc_node_inst, &(adev->umc.active_mask), ++ adev->umc.node_inst_num * adev->umc.umc_inst_num) { ++ node_inst = umc_node_inst / adev->umc.umc_inst_num; ++ umc_inst = umc_node_inst % adev->umc.umc_inst_num; ++ LOOP_UMC_CH_INST(ch_inst) { ++ dev_dbg(adev->dev, ++ "node_inst :%d umc_inst: %d ch_inst: %d", ++ node_inst, umc_inst, ch_inst); ++ ret = func(adev, node_inst, umc_inst, ch_inst, data); ++ if (ret) { ++ dev_err(adev->dev, ++ "Node %d umc %d ch %d func returns %d\n", ++ node_inst, umc_inst, ch_inst, ret); ++ return ret; ++ } ++ } ++ } ++ ++ return 0; ++} ++ + int amdgpu_umc_loop_channels(struct amdgpu_device *adev, + umc_func func, void *data) + { +@@ -395,6 +434,9 @@ int amdgpu_umc_loop_channels(struct amdgpu_device *adev, + uint32_t ch_inst = 0; + int ret = 0; + ++ if (adev->aid_mask) ++ return amdgpu_umc_loop_all_aid(adev, func, data); ++ + if (adev->umc.node_inst_num) { + LOOP_UMC_EACH_NODE_INST_AND_CH(node_inst, umc_inst, ch_inst) { + ret = func(adev, node_inst, umc_inst, ch_inst, data); +diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c +index 5250b470e5ef3..f1dc9e50d67e7 100644 +--- a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c ++++ b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c +@@ -1504,7 +1504,6 @@ static void gmc_v9_0_set_umc_funcs(struct amdgpu_device *adev) + adev->umc.umc_inst_num = UMC_V12_0_UMC_INSTANCE_NUM; + adev->umc.node_inst_num /= UMC_V12_0_UMC_INSTANCE_NUM; + adev->umc.channel_offs = UMC_V12_0_PER_CHANNEL_OFFSET; +- adev->umc.active_mask = adev->aid_mask; + adev->umc.retire_unit = UMC_V12_0_BAD_PAGE_NUM_PER_CHANNEL; + if (!adev->gmc.xgmi.connected_to_cpu && !adev->gmc.is_app_apu) + adev->umc.ras = &umc_v12_0_ras; +-- +2.39.5 + diff --git a/queue-6.14/drm-amdgpu-use-gfp_nowait-for-memory-allocations.patch b/queue-6.14/drm-amdgpu-use-gfp_nowait-for-memory-allocations.patch new file mode 100644 index 0000000000..26a6fa27af --- /dev/null +++ b/queue-6.14/drm-amdgpu-use-gfp_nowait-for-memory-allocations.patch @@ -0,0 +1,274 @@ +From 0a6b0576117c0b5c18d6fbd8ad9bb761acfd4488 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 15 Jan 2025 15:10:13 +0100 +Subject: drm/amdgpu: use GFP_NOWAIT for memory allocations +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Christian König + +[ Upstream commit 16590745b571c07869ef8958e0bbe44ab6f08d1f ] + +In the critical submission path memory allocations can't wait for +reclaim since that can potentially wait for submissions to finish. + +Finally clean that up and mark most memory allocations in the critical +path with GFP_NOWAIT. The only exception left is the dma_fence_array() +used when no VMID is available, but that will be cleaned up later on. + +Signed-off-by: Christian König +Acked-by: Srinivasan Shanmugam +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + .../gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c | 8 ++++---- + drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 18 +++++++++++------- + drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c | 11 +++++++---- + drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c | 4 ++-- + drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c | 11 ++++++----- + drivers/gpu/drm/amd/amdgpu/amdgpu_sync.h | 3 ++- + 6 files changed, 32 insertions(+), 23 deletions(-) + +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c +index 1e998f972c308..70224b9f54f2f 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c +@@ -499,7 +499,7 @@ static int vm_update_pds(struct amdgpu_vm *vm, struct amdgpu_sync *sync) + if (ret) + return ret; + +- return amdgpu_sync_fence(sync, vm->last_update); ++ return amdgpu_sync_fence(sync, vm->last_update, GFP_KERNEL); + } + + static uint64_t get_pte_flags(struct amdgpu_device *adev, struct kgd_mem *mem) +@@ -1263,7 +1263,7 @@ static int unmap_bo_from_gpuvm(struct kgd_mem *mem, + + (void)amdgpu_vm_clear_freed(adev, vm, &bo_va->last_pt_update); + +- (void)amdgpu_sync_fence(sync, bo_va->last_pt_update); ++ (void)amdgpu_sync_fence(sync, bo_va->last_pt_update, GFP_KERNEL); + + return 0; + } +@@ -1287,7 +1287,7 @@ static int update_gpuvm_pte(struct kgd_mem *mem, + return ret; + } + +- return amdgpu_sync_fence(sync, bo_va->last_pt_update); ++ return amdgpu_sync_fence(sync, bo_va->last_pt_update, GFP_KERNEL); + } + + static int map_bo_to_gpuvm(struct kgd_mem *mem, +@@ -2969,7 +2969,7 @@ int amdgpu_amdkfd_gpuvm_restore_process_bos(void *info, struct dma_fence __rcu * + } + dma_resv_for_each_fence(&cursor, bo->tbo.base.resv, + DMA_RESV_USAGE_KERNEL, fence) { +- ret = amdgpu_sync_fence(&sync_obj, fence); ++ ret = amdgpu_sync_fence(&sync_obj, fence, GFP_KERNEL); + if (ret) { + pr_debug("Memory eviction: Sync BO fence failed. Try again\n"); + goto validate_map_fail; +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +index 5cc5f59e30184..4a5b406601fa2 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +@@ -428,7 +428,7 @@ static int amdgpu_cs_p2_dependencies(struct amdgpu_cs_parser *p, + dma_fence_put(old); + } + +- r = amdgpu_sync_fence(&p->sync, fence); ++ r = amdgpu_sync_fence(&p->sync, fence, GFP_KERNEL); + dma_fence_put(fence); + if (r) + return r; +@@ -450,7 +450,7 @@ static int amdgpu_syncobj_lookup_and_add(struct amdgpu_cs_parser *p, + return r; + } + +- r = amdgpu_sync_fence(&p->sync, fence); ++ r = amdgpu_sync_fence(&p->sync, fence, GFP_KERNEL); + dma_fence_put(fence); + return r; + } +@@ -1124,7 +1124,8 @@ static int amdgpu_cs_vm_handling(struct amdgpu_cs_parser *p) + if (r) + return r; + +- r = amdgpu_sync_fence(&p->sync, fpriv->prt_va->last_pt_update); ++ r = amdgpu_sync_fence(&p->sync, fpriv->prt_va->last_pt_update, ++ GFP_KERNEL); + if (r) + return r; + +@@ -1135,7 +1136,8 @@ static int amdgpu_cs_vm_handling(struct amdgpu_cs_parser *p) + if (r) + return r; + +- r = amdgpu_sync_fence(&p->sync, bo_va->last_pt_update); ++ r = amdgpu_sync_fence(&p->sync, bo_va->last_pt_update, ++ GFP_KERNEL); + if (r) + return r; + } +@@ -1154,7 +1156,8 @@ static int amdgpu_cs_vm_handling(struct amdgpu_cs_parser *p) + if (r) + return r; + +- r = amdgpu_sync_fence(&p->sync, bo_va->last_pt_update); ++ r = amdgpu_sync_fence(&p->sync, bo_va->last_pt_update, ++ GFP_KERNEL); + if (r) + return r; + } +@@ -1167,7 +1170,7 @@ static int amdgpu_cs_vm_handling(struct amdgpu_cs_parser *p) + if (r) + return r; + +- r = amdgpu_sync_fence(&p->sync, vm->last_update); ++ r = amdgpu_sync_fence(&p->sync, vm->last_update, GFP_KERNEL); + if (r) + return r; + +@@ -1248,7 +1251,8 @@ static int amdgpu_cs_sync_rings(struct amdgpu_cs_parser *p) + continue; + } + +- r = amdgpu_sync_fence(&p->gang_leader->explicit_sync, fence); ++ r = amdgpu_sync_fence(&p->gang_leader->explicit_sync, fence, ++ GFP_KERNEL); + dma_fence_put(fence); + if (r) + return r; +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c +index 9008b7388e897..92ab821afc06a 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c +@@ -209,7 +209,7 @@ static int amdgpu_vmid_grab_idle(struct amdgpu_ring *ring, + return 0; + } + +- fences = kmalloc_array(id_mgr->num_ids, sizeof(void *), GFP_KERNEL); ++ fences = kmalloc_array(id_mgr->num_ids, sizeof(void *), GFP_NOWAIT); + if (!fences) + return -ENOMEM; + +@@ -313,7 +313,8 @@ static int amdgpu_vmid_grab_reserved(struct amdgpu_vm *vm, + /* Good we can use this VMID. Remember this submission as + * user of the VMID. + */ +- r = amdgpu_sync_fence(&(*id)->active, &job->base.s_fence->finished); ++ r = amdgpu_sync_fence(&(*id)->active, &job->base.s_fence->finished, ++ GFP_NOWAIT); + if (r) + return r; + +@@ -372,7 +373,8 @@ static int amdgpu_vmid_grab_used(struct amdgpu_vm *vm, + * user of the VMID. + */ + r = amdgpu_sync_fence(&(*id)->active, +- &job->base.s_fence->finished); ++ &job->base.s_fence->finished, ++ GFP_NOWAIT); + if (r) + return r; + +@@ -424,7 +426,8 @@ int amdgpu_vmid_grab(struct amdgpu_vm *vm, struct amdgpu_ring *ring, + + /* Remember this submission as user of the VMID */ + r = amdgpu_sync_fence(&id->active, +- &job->base.s_fence->finished); ++ &job->base.s_fence->finished, ++ GFP_NOWAIT); + if (r) + goto error; + +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c +index 6fa20980a0b15..e4251d0691c9c 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c +@@ -1335,14 +1335,14 @@ int amdgpu_mes_ctx_map_meta_data(struct amdgpu_device *adev, + DRM_ERROR("failed to do vm_bo_update on meta data\n"); + goto error_del_bo_va; + } +- amdgpu_sync_fence(&sync, bo_va->last_pt_update); ++ amdgpu_sync_fence(&sync, bo_va->last_pt_update, GFP_KERNEL); + + r = amdgpu_vm_update_pdes(adev, vm, false); + if (r) { + DRM_ERROR("failed to update pdes on meta data\n"); + goto error_del_bo_va; + } +- amdgpu_sync_fence(&sync, vm->last_update); ++ amdgpu_sync_fence(&sync, vm->last_update, GFP_KERNEL); + + amdgpu_sync_wait(&sync, false); + drm_exec_fini(&exec); +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c +index d75715b3f1870..34fc742fda91d 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c +@@ -152,7 +152,8 @@ static bool amdgpu_sync_add_later(struct amdgpu_sync *sync, struct dma_fence *f) + * + * Add the fence to the sync object. + */ +-int amdgpu_sync_fence(struct amdgpu_sync *sync, struct dma_fence *f) ++int amdgpu_sync_fence(struct amdgpu_sync *sync, struct dma_fence *f, ++ gfp_t flags) + { + struct amdgpu_sync_entry *e; + +@@ -162,7 +163,7 @@ int amdgpu_sync_fence(struct amdgpu_sync *sync, struct dma_fence *f) + if (amdgpu_sync_add_later(sync, f)) + return 0; + +- e = kmem_cache_alloc(amdgpu_sync_slab, GFP_KERNEL); ++ e = kmem_cache_alloc(amdgpu_sync_slab, flags); + if (!e) + return -ENOMEM; + +@@ -249,7 +250,7 @@ int amdgpu_sync_resv(struct amdgpu_device *adev, struct amdgpu_sync *sync, + struct dma_fence *tmp = dma_fence_chain_contained(f); + + if (amdgpu_sync_test_fence(adev, mode, owner, tmp)) { +- r = amdgpu_sync_fence(sync, f); ++ r = amdgpu_sync_fence(sync, f, GFP_KERNEL); + dma_fence_put(f); + if (r) + return r; +@@ -281,7 +282,7 @@ int amdgpu_sync_kfd(struct amdgpu_sync *sync, struct dma_resv *resv) + if (fence_owner != AMDGPU_FENCE_OWNER_KFD) + continue; + +- r = amdgpu_sync_fence(sync, f); ++ r = amdgpu_sync_fence(sync, f, GFP_KERNEL); + if (r) + break; + } +@@ -388,7 +389,7 @@ int amdgpu_sync_clone(struct amdgpu_sync *source, struct amdgpu_sync *clone) + hash_for_each_safe(source->fences, i, tmp, e, node) { + f = e->fence; + if (!dma_fence_is_signaled(f)) { +- r = amdgpu_sync_fence(clone, f); ++ r = amdgpu_sync_fence(clone, f, GFP_KERNEL); + if (r) + return r; + } else { +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.h +index a91a8eaf808b1..51eb4382c91eb 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.h ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.h +@@ -47,7 +47,8 @@ struct amdgpu_sync { + }; + + void amdgpu_sync_create(struct amdgpu_sync *sync); +-int amdgpu_sync_fence(struct amdgpu_sync *sync, struct dma_fence *f); ++int amdgpu_sync_fence(struct amdgpu_sync *sync, struct dma_fence *f, ++ gfp_t flags); + int amdgpu_sync_resv(struct amdgpu_device *adev, struct amdgpu_sync *sync, + struct dma_resv *resv, enum amdgpu_sync_mode mode, + void *owner); +-- +2.39.5 + diff --git a/queue-6.14/drm-amdkfd-clear-f8_mode-for-gfx950.patch b/queue-6.14/drm-amdkfd-clear-f8_mode-for-gfx950.patch new file mode 100644 index 0000000000..72eb3de7df --- /dev/null +++ b/queue-6.14/drm-amdkfd-clear-f8_mode-for-gfx950.patch @@ -0,0 +1,37 @@ +From c1490690275925f3eea14045c9a66788a69eb4e6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 16 May 2024 17:06:48 -0500 +Subject: drm/amdkfd: clear F8_MODE for gfx950 + +From: Alex Sierra + +[ Upstream commit 59228c6631f902fa826dc61321ab377ba8aadec5 ] + +Default F8_MODE should be OCP format on gfx950. + +Signed-off-by: Alex Sierra +Reviewed-by: Harish Kasiviswanathan +Signed-off-by: Amber Lin +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v9.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v9.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v9.c +index c734eb9b505f8..3264509408bc8 100644 +--- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v9.c ++++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v9.c +@@ -98,8 +98,7 @@ static int update_qpd_v9(struct device_queue_manager *dqm, + qpd->sh_mem_config |= 1 << SH_MEM_CONFIG__RETRY_DISABLE__SHIFT; + + if (KFD_GC_VERSION(dqm->dev->kfd) == IP_VERSION(9, 4, 3) || +- KFD_GC_VERSION(dqm->dev->kfd) == IP_VERSION(9, 4, 4) || +- KFD_GC_VERSION(dqm->dev->kfd) == IP_VERSION(9, 5, 0)) ++ KFD_GC_VERSION(dqm->dev->kfd) == IP_VERSION(9, 4, 4)) + qpd->sh_mem_config |= + (1 << SH_MEM_CONFIG__F8_MODE__SHIFT); + +-- +2.39.5 + diff --git a/queue-6.14/drm-amdkfd-correct-f8_mode-for-gfx950.patch b/queue-6.14/drm-amdkfd-correct-f8_mode-for-gfx950.patch new file mode 100644 index 0000000000..051845d602 --- /dev/null +++ b/queue-6.14/drm-amdkfd-correct-f8_mode-for-gfx950.patch @@ -0,0 +1,37 @@ +From 1f5a995ba38b88f8fb8ff09b8bc75b74488c0c58 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 12 Mar 2025 21:14:43 -0400 +Subject: drm/amdkfd: Correct F8_MODE for gfx950 + +From: Amber Lin + +[ Upstream commit 0c7e053448945e5a4379dc4396c762d7422b11ca ] + +Correct F8_MODE setting for gfx950 that was removed + +Fixes: 61972cd93af7 ("drm/amdkfd: Set per-process flags only once for gfx9/10/11/12") +Signed-off-by: Amber Lin +Reviewed-by: Harish Kasiviswanathan +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v9.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v9.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v9.c +index 3264509408bc8..d85eadaa1e11b 100644 +--- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v9.c ++++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v9.c +@@ -69,8 +69,7 @@ static bool set_cache_memory_policy_v9(struct device_queue_manager *dqm, + qpd->sh_mem_config |= 1 << SH_MEM_CONFIG__RETRY_DISABLE__SHIFT; + + if (KFD_GC_VERSION(dqm->dev->kfd) == IP_VERSION(9, 4, 3) || +- KFD_GC_VERSION(dqm->dev->kfd) == IP_VERSION(9, 4, 4) || +- KFD_GC_VERSION(dqm->dev->kfd) == IP_VERSION(9, 5, 0)) ++ KFD_GC_VERSION(dqm->dev->kfd) == IP_VERSION(9, 4, 4)) + qpd->sh_mem_config |= (1 << SH_MEM_CONFIG__F8_MODE__SHIFT); + + qpd->sh_mem_ape1_limit = 0; +-- +2.39.5 + diff --git a/queue-6.14/drm-amdkfd-fix-error-handling-for-missing-pasid-in-k.patch b/queue-6.14/drm-amdkfd-fix-error-handling-for-missing-pasid-in-k.patch new file mode 100644 index 0000000000..1de5d928f6 --- /dev/null +++ b/queue-6.14/drm-amdkfd-fix-error-handling-for-missing-pasid-in-k.patch @@ -0,0 +1,71 @@ +From eb1753801e0e53dfefa4abd222be7ac509f9a651 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Feb 2025 12:07:22 +0530 +Subject: drm/amdkfd: Fix error handling for missing PASID in + 'kfd_process_device_init_vm' +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Srinivasan Shanmugam + +[ Upstream commit 2b04d04de956b44cc140d45cf8ebccfb378ce3bf ] + +In the kfd_process_device_init_vm function, a valid error code is now +returned when the associated Process Address Space ID (PASID) is not +present. + +If the address space virtual memory (avm) does not have an associated +PASID, the function sets the ret variable to -EINVAL before proceeding +to the error handling section. This ensures that the calling function, +such as kfd_ioctl_acquire_vm, can appropriately handle the error, +thereby preventing any issues during virtual memory initialization. + +Fixes the below: +drivers/gpu/drm/amd/amdgpu/../amdkfd/kfd_process.c:1694 kfd_process_device_init_vm() +warn: missing error code 'ret' + +drivers/gpu/drm/amd/amdgpu/../amdkfd/kfd_process.c + 1647 int kfd_process_device_init_vm(struct kfd_process_device *pdd, + 1648 struct file *drm_file) + 1649 { + ... + 1690 + 1691 if (unlikely(!avm->pasid)) { + 1692 dev_warn(pdd->dev->adev->dev, "WARN: vm %p has no pasid associated", + 1693 avm); +--> 1694 goto err_get_pasid; + +ret = -EINVAL? + + 1695 } + +Fixes: 8544374c0f82 ("drm/amdkfd: Have kfd driver use same PASID values from graphic driver") +Reported by: Dan Carpenter +Cc: Xiaogang Chen +Cc: Felix Kuehling +Cc: Christian König +Cc: Alex Deucher +Signed-off-by: Srinivasan Shanmugam +Reviewed-by: Felix Kuehling +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/amdkfd/kfd_process.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c +index a7e0a16dac47b..3f411922534b3 100644 +--- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c ++++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c +@@ -1711,6 +1711,7 @@ int kfd_process_device_init_vm(struct kfd_process_device *pdd, + if (unlikely(!avm->pasid)) { + dev_warn(pdd->dev->adev->dev, "WARN: vm %p has no pasid associated", + avm); ++ ret = -EINVAL; + goto err_get_pasid; + } + +-- +2.39.5 + diff --git a/queue-6.14/drm-amdkfd-fix-missing-l2-cache-info-in-topology.patch b/queue-6.14/drm-amdkfd-fix-missing-l2-cache-info-in-topology.patch new file mode 100644 index 0000000000..e991f7b7a7 --- /dev/null +++ b/queue-6.14/drm-amdkfd-fix-missing-l2-cache-info-in-topology.patch @@ -0,0 +1,67 @@ +From 85b2e4de13582675fccc0d496b3ca13b41736f97 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 28 Jan 2025 15:48:26 -0500 +Subject: drm/amdkfd: fix missing L2 cache info in topology + +From: Eric Huang + +[ Upstream commit 5ffd56822a7159917306d99f18fd15dfd7288f20 ] + +In some ASICs L2 cache info may miss in kfd topology, +because the first bitmap may be empty, that means +the first cu may be inactive, so to find the first +active cu will solve the issue. + +v2: Only find the first active cu in the first xcc + +Signed-off-by: Eric Huang +Acked-by: Alex Deucher +Acked-by: Lijo Lazar +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/amdkfd/kfd_topology.c | 19 +++++++++++++++++-- + 1 file changed, 17 insertions(+), 2 deletions(-) + +diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_topology.c b/drivers/gpu/drm/amd/amdkfd/kfd_topology.c +index 334c576a75b14..98317eda2cdb4 100644 +--- a/drivers/gpu/drm/amd/amdkfd/kfd_topology.c ++++ b/drivers/gpu/drm/amd/amdkfd/kfd_topology.c +@@ -1683,17 +1683,32 @@ static int fill_in_l2_l3_pcache(struct kfd_cache_properties **props_ext, + int cache_type, unsigned int cu_processor_id, + struct kfd_node *knode) + { +- unsigned int cu_sibling_map_mask; ++ unsigned int cu_sibling_map_mask = 0; + int first_active_cu; + int i, j, k, xcc, start, end; + int num_xcc = NUM_XCC(knode->xcc_mask); + struct kfd_cache_properties *pcache = NULL; + enum amdgpu_memory_partition mode; + struct amdgpu_device *adev = knode->adev; ++ bool found = false; + + start = ffs(knode->xcc_mask) - 1; + end = start + num_xcc; +- cu_sibling_map_mask = cu_info->bitmap[start][0][0]; ++ ++ /* To find the bitmap in the first active cu in the first ++ * xcc, it is based on the assumption that evrey xcc must ++ * have at least one active cu. ++ */ ++ for (i = 0; i < gfx_info->max_shader_engines && !found; i++) { ++ for (j = 0; j < gfx_info->max_sh_per_se && !found; j++) { ++ if (cu_info->bitmap[start][i % 4][j % 4]) { ++ cu_sibling_map_mask = ++ cu_info->bitmap[start][i % 4][j % 4]; ++ found = true; ++ } ++ } ++ } ++ + cu_sibling_map_mask &= + ((1 << pcache_info[cache_type].num_cu_shared) - 1); + first_active_cu = ffs(cu_sibling_map_mask); +-- +2.39.5 + diff --git a/queue-6.14/drm-amdkfd-fix-pasid-value-leak.patch b/queue-6.14/drm-amdkfd-fix-pasid-value-leak.patch new file mode 100644 index 0000000000..f498ab4639 --- /dev/null +++ b/queue-6.14/drm-amdkfd-fix-pasid-value-leak.patch @@ -0,0 +1,129 @@ +From 6725b91424951af96d86284df9f875d2f73353d0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 12 Feb 2025 00:24:02 -0600 +Subject: drm/amdkfd: Fix pasid value leak + +From: Xiaogang Chen + +[ Upstream commit 10e08943caedfb4b0b95933d248503a6f6b9fef6 ] + +Curret kfd does not allocate pasid values, instead uses pasid value for each +vm from graphic driver. So should not prevent graphic driver from releasing +pasid values since the values are allocated by graphic driver, not kfd driver +anymore. This patch does not stop graphic driver release pasid values. + +Fixes: 8544374c0f82 ("drm/amdkfd: Have kfd driver use same PASID values from graphic driver") +Signed-off-by: Xiaogang Chen +Reviewed-by: Felix Kuehling +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h | 2 -- + .../gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c | 21 ------------------- + drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 14 ------------- + drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h | 1 - + drivers/gpu/drm/amd/amdkfd/kfd_process.c | 5 +---- + 5 files changed, 1 insertion(+), 42 deletions(-) + +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h +index a160ffe80b3de..55d5399676951 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h +@@ -303,8 +303,6 @@ int amdgpu_amdkfd_gpuvm_acquire_process_vm(struct amdgpu_device *adev, + struct amdgpu_vm *avm, + void **process_info, + struct dma_fence **ef); +-void amdgpu_amdkfd_gpuvm_release_process_vm(struct amdgpu_device *adev, +- void *drm_priv); + uint64_t amdgpu_amdkfd_gpuvm_get_process_page_dir(void *drm_priv); + size_t amdgpu_amdkfd_get_available_memory(struct amdgpu_device *adev, + uint8_t xcp_id); +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c +index 0c8129f8d3635..b3c8eae460425 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c +@@ -1578,27 +1578,6 @@ void amdgpu_amdkfd_gpuvm_destroy_cb(struct amdgpu_device *adev, + } + } + +-void amdgpu_amdkfd_gpuvm_release_process_vm(struct amdgpu_device *adev, +- void *drm_priv) +-{ +- struct amdgpu_vm *avm; +- +- if (WARN_ON(!adev || !drm_priv)) +- return; +- +- avm = drm_priv_to_vm(drm_priv); +- +- pr_debug("Releasing process vm %p\n", avm); +- +- /* The original pasid of amdgpu vm has already been +- * released during making a amdgpu vm to a compute vm +- * The current pasid is managed by kfd and will be +- * released on kfd process destroy. Set amdgpu pasid +- * to 0 to avoid duplicate release. +- */ +- amdgpu_vm_release_compute(adev, avm); +-} +- + uint64_t amdgpu_amdkfd_gpuvm_get_process_page_dir(void *drm_priv) + { + struct amdgpu_vm *avm = drm_priv_to_vm(drm_priv); +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +index f0d675c0fc69c..21be10d46cf9c 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +@@ -2687,20 +2687,6 @@ int amdgpu_vm_make_compute(struct amdgpu_device *adev, struct amdgpu_vm *vm) + return r; + } + +-/** +- * amdgpu_vm_release_compute - release a compute vm +- * @adev: amdgpu_device pointer +- * @vm: a vm turned into compute vm by calling amdgpu_vm_make_compute +- * +- * This is a correspondant of amdgpu_vm_make_compute. It decouples compute +- * pasid from vm. Compute should stop use of vm after this call. +- */ +-void amdgpu_vm_release_compute(struct amdgpu_device *adev, struct amdgpu_vm *vm) +-{ +- amdgpu_vm_set_pasid(adev, vm, 0); +- vm->is_compute_context = false; +-} +- + static int amdgpu_vm_stats_is_zero(struct amdgpu_vm *vm) + { + for (int i = 0; i < __AMDGPU_PL_NUM; ++i) { +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h +index 5010a3107bf89..f3ad687125ad6 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h +@@ -489,7 +489,6 @@ int amdgpu_vm_set_pasid(struct amdgpu_device *adev, struct amdgpu_vm *vm, + long amdgpu_vm_wait_idle(struct amdgpu_vm *vm, long timeout); + int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm, int32_t xcp_id); + int amdgpu_vm_make_compute(struct amdgpu_device *adev, struct amdgpu_vm *vm); +-void amdgpu_vm_release_compute(struct amdgpu_device *adev, struct amdgpu_vm *vm); + void amdgpu_vm_fini(struct amdgpu_device *adev, struct amdgpu_vm *vm); + int amdgpu_vm_lock_pd(struct amdgpu_vm *vm, struct drm_exec *exec, + unsigned int num_fences); +diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c +index 3f411922534b3..7c0c24732481e 100644 +--- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c ++++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c +@@ -1059,11 +1059,8 @@ static void kfd_process_destroy_pdds(struct kfd_process *p) + kfd_process_device_destroy_cwsr_dgpu(pdd); + kfd_process_device_destroy_ib_mem(pdd); + +- if (pdd->drm_file) { +- amdgpu_amdkfd_gpuvm_release_process_vm( +- pdd->dev->adev, pdd->drm_priv); ++ if (pdd->drm_file) + fput(pdd->drm_file); +- } + + if (pdd->qpd.cwsr_kaddr && !pdd->qpd.cwsr_base) + free_pages((unsigned long)pdd->qpd.cwsr_kaddr, +-- +2.39.5 + diff --git a/queue-6.14/drm-amdkfd-have-kfd-driver-use-same-pasid-values-fro.patch b/queue-6.14/drm-amdkfd-have-kfd-driver-use-same-pasid-values-fro.patch new file mode 100644 index 0000000000..672f80b864 --- /dev/null +++ b/queue-6.14/drm-amdkfd-have-kfd-driver-use-same-pasid-values-fro.patch @@ -0,0 +1,1097 @@ +From dc7a556f00a36c1fe76aa174204c2b5bd3e1bd88 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 13 Jan 2025 17:35:59 -0600 +Subject: drm/amdkfd: Have kfd driver use same PASID values from graphic driver + +From: Xiaogang Chen + +[ Upstream commit 8544374c0f82edb285779f21b149826fe2c2977c ] + +Current kfd driver has its own PASID value for a kfd process and uses it to +locate vm at interrupt handler or mapping between kfd process and vm. That +design is not working when a physical gpu device has multiple spatial +partitions, ex: adev in CPX mode. This patch has kfd driver use same pasid +values that graphic driver generated which is per vm per pasid. + +These pasid values are passed to fw/hardware. We do not need change interrupt +handler though more pasid values are used. Also, pasid values at log are +replaced by user process pid; pasid values are not exposed to user. Users see +their process pids that have meaning in user space. + +Signed-off-by: Xiaogang Chen +Reviewed-by: Felix Kuehling +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h | 3 +- + .../gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c | 21 ---- + .../gpu/drm/amd/amdkfd/cik_event_interrupt.c | 18 ++- + drivers/gpu/drm/amd/amdkfd/kfd_chardev.c | 25 ++-- + drivers/gpu/drm/amd/amdkfd/kfd_debug.c | 14 +-- + drivers/gpu/drm/amd/amdkfd/kfd_device.c | 2 +- + .../drm/amd/amdkfd/kfd_device_queue_manager.c | 85 +++++++------ + drivers/gpu/drm/amd/amdkfd/kfd_events.c | 43 ++++--- + .../gpu/drm/amd/amdkfd/kfd_int_process_v11.c | 2 +- + .../gpu/drm/amd/amdkfd/kfd_int_process_v9.c | 2 +- + .../drm/amd/amdkfd/kfd_packet_manager_v9.c | 4 +- + .../drm/amd/amdkfd/kfd_packet_manager_vi.c | 3 +- + drivers/gpu/drm/amd/amdkfd/kfd_priv.h | 11 +- + drivers/gpu/drm/amd/amdkfd/kfd_process.c | 115 ++++++++++-------- + .../amd/amdkfd/kfd_process_queue_manager.c | 10 +- + drivers/gpu/drm/amd/amdkfd/kfd_svm.c | 19 +-- + 16 files changed, 196 insertions(+), 181 deletions(-) + +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h +index 2f48dc5747aa2..a160ffe80b3de 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h +@@ -47,6 +47,7 @@ enum TLB_FLUSH_TYPE { + }; + + struct amdgpu_device; ++struct kfd_process_device; + struct amdgpu_reset_context; + + enum kfd_mem_attachment_type { +@@ -298,8 +299,6 @@ bool amdgpu_amdkfd_compute_active(struct amdgpu_device *adev, uint32_t node_id); + (&((struct amdgpu_fpriv *) \ + ((struct drm_file *)(drm_priv))->driver_priv)->vm) + +-int amdgpu_amdkfd_gpuvm_set_vm_pasid(struct amdgpu_device *adev, +- struct amdgpu_vm *avm, u32 pasid); + int amdgpu_amdkfd_gpuvm_acquire_process_vm(struct amdgpu_device *adev, + struct amdgpu_vm *avm, + void **process_info, +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c +index c0aaa72b6c210..0c8129f8d3635 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c +@@ -1521,27 +1521,6 @@ static void amdgpu_amdkfd_gpuvm_unpin_bo(struct amdgpu_bo *bo) + amdgpu_bo_unreserve(bo); + } + +-int amdgpu_amdkfd_gpuvm_set_vm_pasid(struct amdgpu_device *adev, +- struct amdgpu_vm *avm, u32 pasid) +- +-{ +- int ret; +- +- /* Free the original amdgpu allocated pasid, +- * will be replaced with kfd allocated pasid. +- */ +- if (avm->pasid) { +- amdgpu_pasid_free(avm->pasid); +- amdgpu_vm_set_pasid(adev, avm, 0); +- } +- +- ret = amdgpu_vm_set_pasid(adev, avm, pasid); +- if (ret) +- return ret; +- +- return 0; +-} +- + int amdgpu_amdkfd_gpuvm_acquire_process_vm(struct amdgpu_device *adev, + struct amdgpu_vm *avm, + void **process_info, +diff --git a/drivers/gpu/drm/amd/amdkfd/cik_event_interrupt.c b/drivers/gpu/drm/amd/amdkfd/cik_event_interrupt.c +index 795382b55e0a9..981d9adcc5e1d 100644 +--- a/drivers/gpu/drm/amd/amdkfd/cik_event_interrupt.c ++++ b/drivers/gpu/drm/amd/amdkfd/cik_event_interrupt.c +@@ -107,20 +107,30 @@ static void cik_event_interrupt_wq(struct kfd_node *dev, + kfd_signal_hw_exception_event(pasid); + else if (ihre->source_id == CIK_INTSRC_GFX_PAGE_INV_FAULT || + ihre->source_id == CIK_INTSRC_GFX_MEM_PROT_FAULT) { ++ struct kfd_process_device *pdd = NULL; + struct kfd_vm_fault_info info; ++ struct kfd_process *p; + + kfd_smi_event_update_vmfault(dev, pasid); +- kfd_dqm_evict_pasid(dev->dqm, pasid); ++ p = kfd_lookup_process_by_pasid(pasid, &pdd); ++ if (!pdd) ++ return; ++ ++ kfd_evict_process_device(pdd); + + memset(&info, 0, sizeof(info)); + amdgpu_amdkfd_gpuvm_get_vm_fault_info(dev->adev, &info); +- if (!info.page_addr && !info.status) ++ if (!info.page_addr && !info.status) { ++ kfd_unref_process(p); + return; ++ } + + if (info.vmid == vmid) +- kfd_signal_vm_fault_event(dev, pasid, &info, NULL); ++ kfd_signal_vm_fault_event(pdd, &info, NULL); + else +- kfd_signal_vm_fault_event(dev, pasid, NULL, NULL); ++ kfd_signal_vm_fault_event(pdd, &info, NULL); ++ ++ kfd_unref_process(p); + } + } + +diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c +index 33df35cab4679..8c2e92378b491 100644 +--- a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c ++++ b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c +@@ -155,8 +155,8 @@ static int kfd_open(struct inode *inode, struct file *filep) + /* filep now owns the reference returned by kfd_create_process */ + filep->private_data = process; + +- dev_dbg(kfd_device, "process %d opened, compat mode (32 bit) - %d\n", +- process->pasid, process->is_32bit_user_mode); ++ dev_dbg(kfd_device, "process pid %d opened kfd node, compat mode (32 bit) - %d\n", ++ process->lead_thread->pid, process->is_32bit_user_mode); + + return 0; + } +@@ -366,8 +366,8 @@ static int kfd_ioctl_create_queue(struct file *filep, struct kfd_process *p, + goto err_acquire_queue_buf; + } + +- pr_debug("Creating queue for PASID 0x%x on gpu 0x%x\n", +- p->pasid, ++ pr_debug("Creating queue for process pid %d on gpu 0x%x\n", ++ p->lead_thread->pid, + dev->id); + + err = pqm_create_queue(&p->pqm, dev, &q_properties, &queue_id, +@@ -420,9 +420,9 @@ static int kfd_ioctl_destroy_queue(struct file *filp, struct kfd_process *p, + int retval; + struct kfd_ioctl_destroy_queue_args *args = data; + +- pr_debug("Destroying queue id %d for pasid 0x%x\n", ++ pr_debug("Destroying queue id %d for process pid %d\n", + args->queue_id, +- p->pasid); ++ p->lead_thread->pid); + + mutex_lock(&p->mutex); + +@@ -478,8 +478,8 @@ static int kfd_ioctl_update_queue(struct file *filp, struct kfd_process *p, + properties.pm4_target_xcc = (args->queue_percentage >> 8) & 0xFF; + properties.priority = args->queue_priority; + +- pr_debug("Updating queue id %d for pasid 0x%x\n", +- args->queue_id, p->pasid); ++ pr_debug("Updating queue id %d for process pid %d\n", ++ args->queue_id, p->lead_thread->pid); + + mutex_lock(&p->mutex); + +@@ -705,7 +705,7 @@ static int kfd_ioctl_get_process_apertures(struct file *filp, + struct kfd_process_device_apertures *pAperture; + int i; + +- dev_dbg(kfd_device, "get apertures for PASID 0x%x", p->pasid); ++ dev_dbg(kfd_device, "get apertures for process pid %d", p->lead_thread->pid); + + args->num_of_nodes = 0; + +@@ -757,7 +757,8 @@ static int kfd_ioctl_get_process_apertures_new(struct file *filp, + int ret; + int i; + +- dev_dbg(kfd_device, "get apertures for PASID 0x%x", p->pasid); ++ dev_dbg(kfd_device, "get apertures for process pid %d", ++ p->lead_thread->pid); + + if (args->num_of_nodes == 0) { + /* Return number of nodes, so that user space can alloacate +@@ -3375,12 +3376,12 @@ static int kfd_mmio_mmap(struct kfd_node *dev, struct kfd_process *process, + + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); + +- pr_debug("pasid 0x%x mapping mmio page\n" ++ pr_debug("process pid %d mapping mmio page\n" + " target user address == 0x%08llX\n" + " physical address == 0x%08llX\n" + " vm_flags == 0x%04lX\n" + " size == 0x%04lX\n", +- process->pasid, (unsigned long long) vma->vm_start, ++ process->lead_thread->pid, (unsigned long long) vma->vm_start, + address, vma->vm_flags, PAGE_SIZE); + + return io_remap_pfn_range(vma, +diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_debug.c b/drivers/gpu/drm/amd/amdkfd/kfd_debug.c +index a8abc30918013..12456c61ffa54 100644 +--- a/drivers/gpu/drm/amd/amdkfd/kfd_debug.c ++++ b/drivers/gpu/drm/amd/amdkfd/kfd_debug.c +@@ -204,11 +204,12 @@ bool kfd_set_dbg_ev_from_interrupt(struct kfd_node *dev, + size_t exception_data_size) + { + struct kfd_process *p; ++ struct kfd_process_device *pdd = NULL; + bool signaled_to_debugger_or_runtime = false; + +- p = kfd_lookup_process_by_pasid(pasid); ++ p = kfd_lookup_process_by_pasid(pasid, &pdd); + +- if (!p) ++ if (!pdd) + return false; + + if (!kfd_dbg_ev_raise(trap_mask, p, dev, doorbell_id, true, +@@ -238,9 +239,8 @@ bool kfd_set_dbg_ev_from_interrupt(struct kfd_node *dev, + + mutex_unlock(&p->mutex); + } else if (trap_mask & KFD_EC_MASK(EC_DEVICE_MEMORY_VIOLATION)) { +- kfd_dqm_evict_pasid(dev->dqm, p->pasid); +- kfd_signal_vm_fault_event(dev, p->pasid, NULL, +- exception_data); ++ kfd_evict_process_device(pdd); ++ kfd_signal_vm_fault_event(pdd, NULL, exception_data); + + signaled_to_debugger_or_runtime = true; + } +@@ -276,8 +276,8 @@ int kfd_dbg_send_exception_to_runtime(struct kfd_process *p, + data = (struct kfd_hsa_memory_exception_data *) + pdd->vm_fault_exc_data; + +- kfd_dqm_evict_pasid(pdd->dev->dqm, p->pasid); +- kfd_signal_vm_fault_event(pdd->dev, p->pasid, NULL, data); ++ kfd_evict_process_device(pdd); ++ kfd_signal_vm_fault_event(pdd, NULL, data); + error_reason &= ~KFD_EC_MASK(EC_DEVICE_MEMORY_VIOLATION); + } + +diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device.c b/drivers/gpu/drm/amd/amdkfd/kfd_device.c +index 6cefd338f23de..bf978b368f6a5 100644 +--- a/drivers/gpu/drm/amd/amdkfd/kfd_device.c ++++ b/drivers/gpu/drm/amd/amdkfd/kfd_device.c +@@ -1558,7 +1558,7 @@ bool kgd2kfd_vmfault_fast_path(struct amdgpu_device *adev, struct amdgpu_iv_entr + u32 cam_index; + + if (entry->ih == &adev->irq.ih_soft || entry->ih == &adev->irq.ih1) { +- p = kfd_lookup_process_by_pasid(entry->pasid); ++ p = kfd_lookup_process_by_pasid(entry->pasid, NULL); + if (!p) + return true; + +diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c +index 7f8ec2a152ac6..35ae3c55a97fa 100644 +--- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c ++++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c +@@ -208,7 +208,7 @@ static int add_queue_mes(struct device_queue_manager *dqm, struct queue *q, + return -EIO; + + memset(&queue_input, 0x0, sizeof(struct mes_add_queue_input)); +- queue_input.process_id = qpd->pqm->process->pasid; ++ queue_input.process_id = pdd->pasid; + queue_input.page_table_base_addr = qpd->page_table_base; + queue_input.process_va_start = 0; + queue_input.process_va_end = adev->vm_manager.max_pfn - 1; +@@ -527,6 +527,7 @@ static int allocate_vmid(struct device_queue_manager *dqm, + struct qcm_process_device *qpd, + struct queue *q) + { ++ struct kfd_process_device *pdd = qpd_to_pdd(qpd); + struct device *dev = dqm->dev->adev->dev; + int allocated_vmid = -1, i; + +@@ -545,9 +546,9 @@ static int allocate_vmid(struct device_queue_manager *dqm, + + pr_debug("vmid allocated: %d\n", allocated_vmid); + +- dqm->vmid_pasid[allocated_vmid] = q->process->pasid; ++ dqm->vmid_pasid[allocated_vmid] = pdd->pasid; + +- set_pasid_vmid_mapping(dqm, q->process->pasid, allocated_vmid); ++ set_pasid_vmid_mapping(dqm, pdd->pasid, allocated_vmid); + + qpd->vmid = allocated_vmid; + q->properties.vmid = allocated_vmid; +@@ -799,6 +800,11 @@ static int dbgdev_wave_reset_wavefronts(struct kfd_node *dev, struct kfd_process + return -EOPNOTSUPP; + } + ++ /* taking the VMID for that process on the safe way using PDD */ ++ pdd = kfd_get_process_device_data(dev, p); ++ if (!pdd) ++ return -EFAULT; ++ + /* Scan all registers in the range ATC_VMID8_PASID_MAPPING .. + * ATC_VMID15_PASID_MAPPING + * to check which VMID the current process is mapped to. +@@ -808,23 +814,19 @@ static int dbgdev_wave_reset_wavefronts(struct kfd_node *dev, struct kfd_process + status = dev->kfd2kgd->get_atc_vmid_pasid_mapping_info + (dev->adev, vmid, &queried_pasid); + +- if (status && queried_pasid == p->pasid) { +- pr_debug("Killing wave fronts of vmid %d and pasid 0x%x\n", +- vmid, p->pasid); ++ if (status && queried_pasid == pdd->pasid) { ++ pr_debug("Killing wave fronts of vmid %d and process pid %d\n", ++ vmid, p->lead_thread->pid); + break; + } + } + + if (vmid > last_vmid_to_scan) { +- dev_err(dev->adev->dev, "Didn't find vmid for pasid 0x%x\n", p->pasid); ++ dev_err(dev->adev->dev, "Didn't find vmid for process pid %d\n", ++ p->lead_thread->pid); + return -EFAULT; + } + +- /* taking the VMID for that process on the safe way using PDD */ +- pdd = kfd_get_process_device_data(dev, p); +- if (!pdd) +- return -EFAULT; +- + reg_gfx_index.bits.sh_broadcast_writes = 1; + reg_gfx_index.bits.se_broadcast_writes = 1; + reg_gfx_index.bits.instance_broadcast_writes = 1; +@@ -1060,8 +1062,8 @@ static int suspend_single_queue(struct device_queue_manager *dqm, + if (q->properties.is_suspended) + return 0; + +- pr_debug("Suspending PASID %u queue [%i]\n", +- pdd->process->pasid, ++ pr_debug("Suspending process pid %d queue [%i]\n", ++ pdd->process->lead_thread->pid, + q->properties.queue_id); + + is_new = q->properties.exception_status & KFD_EC_MASK(EC_QUEUE_NEW); +@@ -1108,8 +1110,8 @@ static int resume_single_queue(struct device_queue_manager *dqm, + + pdd = qpd_to_pdd(qpd); + +- pr_debug("Restoring from suspend PASID %u queue [%i]\n", +- pdd->process->pasid, ++ pr_debug("Restoring from suspend process pid %d queue [%i]\n", ++ pdd->process->lead_thread->pid, + q->properties.queue_id); + + q->properties.is_suspended = false; +@@ -1142,8 +1144,8 @@ static int evict_process_queues_nocpsch(struct device_queue_manager *dqm, + goto out; + + pdd = qpd_to_pdd(qpd); +- pr_debug_ratelimited("Evicting PASID 0x%x queues\n", +- pdd->process->pasid); ++ pr_debug_ratelimited("Evicting process pid %d queues\n", ++ pdd->process->lead_thread->pid); + + pdd->last_evict_timestamp = get_jiffies_64(); + /* Mark all queues as evicted. Deactivate all active queues on +@@ -1200,8 +1202,8 @@ static int evict_process_queues_cpsch(struct device_queue_manager *dqm, + if (!pdd->drm_priv) + goto out; + +- pr_debug_ratelimited("Evicting PASID 0x%x queues\n", +- pdd->process->pasid); ++ pr_debug_ratelimited("Evicting process pid %d queues\n", ++ pdd->process->lead_thread->pid); + + /* Mark all queues as evicted. Deactivate all active queues on + * the qpd. +@@ -1261,8 +1263,8 @@ static int restore_process_queues_nocpsch(struct device_queue_manager *dqm, + goto out; + } + +- pr_debug_ratelimited("Restoring PASID 0x%x queues\n", +- pdd->process->pasid); ++ pr_debug_ratelimited("Restoring process pid %d queues\n", ++ pdd->process->lead_thread->pid); + + /* Update PD Base in QPD */ + qpd->page_table_base = pd_base; +@@ -1345,8 +1347,8 @@ static int restore_process_queues_cpsch(struct device_queue_manager *dqm, + if (!pdd->drm_priv) + goto vm_not_acquired; + +- pr_debug_ratelimited("Restoring PASID 0x%x queues\n", +- pdd->process->pasid); ++ pr_debug_ratelimited("Restoring process pid %d queues\n", ++ pdd->process->lead_thread->pid); + + /* Update PD Base in QPD */ + qpd->page_table_base = amdgpu_amdkfd_gpuvm_get_process_page_dir(pdd->drm_priv); +@@ -2137,8 +2139,8 @@ static void set_queue_as_reset(struct device_queue_manager *dqm, struct queue *q + { + struct kfd_process_device *pdd = qpd_to_pdd(qpd); + +- dev_err(dqm->dev->adev->dev, "queue id 0x%0x at pasid 0x%0x is reset\n", +- q->properties.queue_id, q->process->pasid); ++ dev_err(dqm->dev->adev->dev, "queue id 0x%0x at pasid %d is reset\n", ++ q->properties.queue_id, pdd->process->lead_thread->pid); + + pdd->has_reset_queue = true; + if (q->properties.is_active) { +@@ -2941,20 +2943,19 @@ void device_queue_manager_uninit(struct device_queue_manager *dqm) + + int kfd_dqm_suspend_bad_queue_mes(struct kfd_node *knode, u32 pasid, u32 doorbell_id) + { +- struct kfd_process_device *pdd; +- struct kfd_process *p = kfd_lookup_process_by_pasid(pasid); ++ struct kfd_process_device *pdd = NULL; ++ struct kfd_process *p = kfd_lookup_process_by_pasid(pasid, &pdd); + struct device_queue_manager *dqm = knode->dqm; + struct device *dev = dqm->dev->adev->dev; + struct qcm_process_device *qpd; + struct queue *q = NULL; + int ret = 0; + +- if (!p) ++ if (!pdd) + return -EINVAL; + + dqm_lock(dqm); + +- pdd = kfd_get_process_device_data(dqm->dev, p); + if (pdd) { + qpd = &pdd->qpd; + +@@ -2987,6 +2988,7 @@ int kfd_dqm_suspend_bad_queue_mes(struct kfd_node *knode, u32 pasid, u32 doorbel + + out: + dqm_unlock(dqm); ++ kfd_unref_process(p); + return ret; + } + +@@ -3028,24 +3030,21 @@ static int kfd_dqm_evict_pasid_mes(struct device_queue_manager *dqm, + return ret; + } + +-int kfd_dqm_evict_pasid(struct device_queue_manager *dqm, u32 pasid) ++int kfd_evict_process_device(struct kfd_process_device *pdd) + { +- struct kfd_process_device *pdd; +- struct kfd_process *p = kfd_lookup_process_by_pasid(pasid); ++ struct device_queue_manager *dqm; ++ struct kfd_process *p; + int ret = 0; + +- if (!p) +- return -EINVAL; ++ p = pdd->process; ++ dqm = pdd->dev->dqm; ++ + WARN(debug_evictions, "Evicting pid %d", p->lead_thread->pid); +- pdd = kfd_get_process_device_data(dqm->dev, p); +- if (pdd) { +- if (dqm->dev->kfd->shared_resources.enable_mes) +- ret = kfd_dqm_evict_pasid_mes(dqm, &pdd->qpd); +- else +- ret = dqm->ops.evict_process_queues(dqm, &pdd->qpd); +- } + +- kfd_unref_process(p); ++ if (dqm->dev->kfd->shared_resources.enable_mes) ++ ret = kfd_dqm_evict_pasid_mes(dqm, &pdd->qpd); ++ else ++ ret = dqm->ops.evict_process_queues(dqm, &pdd->qpd); + + return ret; + } +diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_events.c b/drivers/gpu/drm/amd/amdkfd/kfd_events.c +index d075f24e5f9f3..fecdb67940750 100644 +--- a/drivers/gpu/drm/amd/amdkfd/kfd_events.c ++++ b/drivers/gpu/drm/amd/amdkfd/kfd_events.c +@@ -727,7 +727,7 @@ void kfd_signal_event_interrupt(u32 pasid, uint32_t partial_id, + * to process context, kfd_process could attempt to exit while we are + * running so the lookup function increments the process ref count. + */ +- struct kfd_process *p = kfd_lookup_process_by_pasid(pasid); ++ struct kfd_process *p = kfd_lookup_process_by_pasid(pasid, NULL); + + if (!p) + return; /* Presumably process exited. */ +@@ -1139,8 +1139,8 @@ static void lookup_events_by_type_and_signal(struct kfd_process *p, + + if (type == KFD_EVENT_TYPE_MEMORY) { + dev_warn(kfd_device, +- "Sending SIGSEGV to process %d (pasid 0x%x)", +- p->lead_thread->pid, p->pasid); ++ "Sending SIGSEGV to process pid %d", ++ p->lead_thread->pid); + send_sig(SIGSEGV, p->lead_thread, 0); + } + +@@ -1148,13 +1148,13 @@ static void lookup_events_by_type_and_signal(struct kfd_process *p, + if (send_signal) { + if (send_sigterm) { + dev_warn(kfd_device, +- "Sending SIGTERM to process %d (pasid 0x%x)", +- p->lead_thread->pid, p->pasid); ++ "Sending SIGTERM to process pid %d", ++ p->lead_thread->pid); + send_sig(SIGTERM, p->lead_thread, 0); + } else { + dev_err(kfd_device, +- "Process %d (pasid 0x%x) got unhandled exception", +- p->lead_thread->pid, p->pasid); ++ "Process pid %d got unhandled exception", ++ p->lead_thread->pid); + } + } + +@@ -1168,7 +1168,7 @@ void kfd_signal_hw_exception_event(u32 pasid) + * to process context, kfd_process could attempt to exit while we are + * running so the lookup function increments the process ref count. + */ +- struct kfd_process *p = kfd_lookup_process_by_pasid(pasid); ++ struct kfd_process *p = kfd_lookup_process_by_pasid(pasid, NULL); + + if (!p) + return; /* Presumably process exited. */ +@@ -1177,22 +1177,20 @@ void kfd_signal_hw_exception_event(u32 pasid) + kfd_unref_process(p); + } + +-void kfd_signal_vm_fault_event(struct kfd_node *dev, u32 pasid, ++void kfd_signal_vm_fault_event(struct kfd_process_device *pdd, + struct kfd_vm_fault_info *info, + struct kfd_hsa_memory_exception_data *data) + { + struct kfd_event *ev; + uint32_t id; +- struct kfd_process *p = kfd_lookup_process_by_pasid(pasid); ++ struct kfd_process *p = pdd->process; + struct kfd_hsa_memory_exception_data memory_exception_data; + int user_gpu_id; + +- if (!p) +- return; /* Presumably process exited. */ +- +- user_gpu_id = kfd_process_get_user_gpu_id(p, dev->id); ++ user_gpu_id = kfd_process_get_user_gpu_id(p, pdd->dev->id); + if (unlikely(user_gpu_id == -EINVAL)) { +- WARN_ONCE(1, "Could not get user_gpu_id from dev->id:%x\n", dev->id); ++ WARN_ONCE(1, "Could not get user_gpu_id from dev->id:%x\n", ++ pdd->dev->id); + return; + } + +@@ -1229,7 +1227,6 @@ void kfd_signal_vm_fault_event(struct kfd_node *dev, u32 pasid, + } + + rcu_read_unlock(); +- kfd_unref_process(p); + } + + void kfd_signal_reset_event(struct kfd_node *dev) +@@ -1264,7 +1261,8 @@ void kfd_signal_reset_event(struct kfd_node *dev) + } + + if (unlikely(!pdd)) { +- WARN_ONCE(1, "Could not get device data from pasid:0x%x\n", p->pasid); ++ WARN_ONCE(1, "Could not get device data from process pid:%d\n", ++ p->lead_thread->pid); + continue; + } + +@@ -1273,8 +1271,15 @@ void kfd_signal_reset_event(struct kfd_node *dev) + + if (dev->dqm->detect_hang_count) { + struct amdgpu_task_info *ti; ++ struct amdgpu_fpriv *drv_priv; ++ ++ if (unlikely(amdgpu_file_to_fpriv(pdd->drm_file, &drv_priv))) { ++ WARN_ONCE(1, "Could not get vm for device %x from pid:%d\n", ++ dev->id, p->lead_thread->pid); ++ continue; ++ } + +- ti = amdgpu_vm_get_task_info_pasid(dev->adev, p->pasid); ++ ti = amdgpu_vm_get_task_info_vm(&drv_priv->vm); + if (ti) { + dev_err(dev->adev->dev, + "Queues reset on process %s tid %d thread %s pid %d\n", +@@ -1311,7 +1316,7 @@ void kfd_signal_reset_event(struct kfd_node *dev) + + void kfd_signal_poison_consumed_event(struct kfd_node *dev, u32 pasid) + { +- struct kfd_process *p = kfd_lookup_process_by_pasid(pasid); ++ struct kfd_process *p = kfd_lookup_process_by_pasid(pasid, NULL); + struct kfd_hsa_memory_exception_data memory_exception_data; + struct kfd_hsa_hw_exception_data hw_exception_data; + struct kfd_event *ev; +diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v11.c b/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v11.c +index b3f988b275a88..c5f97e6e36ff5 100644 +--- a/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v11.c ++++ b/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v11.c +@@ -194,7 +194,7 @@ static void event_interrupt_poison_consumption_v11(struct kfd_node *dev, + enum amdgpu_ras_block block = 0; + int ret = -EINVAL; + uint32_t reset = 0; +- struct kfd_process *p = kfd_lookup_process_by_pasid(pasid); ++ struct kfd_process *p = kfd_lookup_process_by_pasid(pasid, NULL); + + if (!p) + return; +diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v9.c b/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v9.c +index 0cb5c582ce7dc..b8a91bf4ef307 100644 +--- a/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v9.c ++++ b/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v9.c +@@ -146,7 +146,7 @@ static void event_interrupt_poison_consumption_v9(struct kfd_node *dev, + { + enum amdgpu_ras_block block = 0; + uint32_t reset = 0; +- struct kfd_process *p = kfd_lookup_process_by_pasid(pasid); ++ struct kfd_process *p = kfd_lookup_process_by_pasid(pasid, NULL); + enum ras_event_type type = RAS_EVENT_TYPE_POISON_CONSUMPTION; + u64 event_id; + int old_poison, ret; +diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_packet_manager_v9.c b/drivers/gpu/drm/amd/amdkfd/kfd_packet_manager_v9.c +index 1f9f5bfeaf868..d56525201155a 100644 +--- a/drivers/gpu/drm/amd/amdkfd/kfd_packet_manager_v9.c ++++ b/drivers/gpu/drm/amd/amdkfd/kfd_packet_manager_v9.c +@@ -47,7 +47,7 @@ static int pm_map_process_v9(struct packet_manager *pm, + packet->bitfields2.exec_cleaner_shader = 1; + packet->bitfields2.diq_enable = (qpd->is_debug) ? 1 : 0; + packet->bitfields2.process_quantum = 10; +- packet->bitfields2.pasid = qpd->pqm->process->pasid; ++ packet->bitfields2.pasid = pdd->pasid; + packet->bitfields14.gds_size = qpd->gds_size & 0x3F; + packet->bitfields14.gds_size_hi = (qpd->gds_size >> 6) & 0xF; + packet->bitfields14.num_gws = (qpd->mapped_gws_queue) ? qpd->num_gws : 0; +@@ -106,7 +106,7 @@ static int pm_map_process_aldebaran(struct packet_manager *pm, + packet->bitfields2.exec_cleaner_shader = 1; + packet->bitfields2.diq_enable = (qpd->is_debug) ? 1 : 0; + packet->bitfields2.process_quantum = 10; +- packet->bitfields2.pasid = qpd->pqm->process->pasid; ++ packet->bitfields2.pasid = pdd->pasid; + packet->bitfields14.gds_size = qpd->gds_size & 0x3F; + packet->bitfields14.gds_size_hi = (qpd->gds_size >> 6) & 0xF; + packet->bitfields14.num_gws = (qpd->mapped_gws_queue) ? qpd->num_gws : 0; +diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_packet_manager_vi.c b/drivers/gpu/drm/amd/amdkfd/kfd_packet_manager_vi.c +index c1199d06d131b..347c86e1c378f 100644 +--- a/drivers/gpu/drm/amd/amdkfd/kfd_packet_manager_vi.c ++++ b/drivers/gpu/drm/amd/amdkfd/kfd_packet_manager_vi.c +@@ -42,6 +42,7 @@ unsigned int pm_build_pm4_header(unsigned int opcode, size_t packet_size) + static int pm_map_process_vi(struct packet_manager *pm, uint32_t *buffer, + struct qcm_process_device *qpd) + { ++ struct kfd_process_device *pdd = qpd_to_pdd(qpd); + struct pm4_mes_map_process *packet; + + packet = (struct pm4_mes_map_process *)buffer; +@@ -52,7 +53,7 @@ static int pm_map_process_vi(struct packet_manager *pm, uint32_t *buffer, + sizeof(struct pm4_mes_map_process)); + packet->bitfields2.diq_enable = (qpd->is_debug) ? 1 : 0; + packet->bitfields2.process_quantum = 10; +- packet->bitfields2.pasid = qpd->pqm->process->pasid; ++ packet->bitfields2.pasid = pdd->pasid; + packet->bitfields3.page_table_base = qpd->page_table_base; + packet->bitfields10.gds_size = qpd->gds_size; + packet->bitfields10.num_gws = qpd->num_gws; +diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h +index d8cd913aa772b..0a99c5c9cadc0 100644 +--- a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h ++++ b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h +@@ -851,6 +851,8 @@ struct kfd_process_device { + + /* Tracks queue reset status */ + bool has_reset_queue; ++ ++ u32 pasid; + }; + + #define qpd_to_pdd(x) container_of(x, struct kfd_process_device, qpd) +@@ -910,8 +912,6 @@ struct kfd_process { + /* We want to receive a notification when the mm_struct is destroyed */ + struct mmu_notifier mmu_notifier; + +- u32 pasid; +- + /* + * Array of kfd_process_device pointers, + * one for each device the process is using. +@@ -1039,7 +1039,8 @@ void kfd_process_destroy_wq(void); + void kfd_cleanup_processes(void); + struct kfd_process *kfd_create_process(struct task_struct *thread); + struct kfd_process *kfd_get_process(const struct task_struct *task); +-struct kfd_process *kfd_lookup_process_by_pasid(u32 pasid); ++struct kfd_process *kfd_lookup_process_by_pasid(u32 pasid, ++ struct kfd_process_device **pdd); + struct kfd_process *kfd_lookup_process_by_mm(const struct mm_struct *mm); + + int kfd_process_gpuidx_from_gpuid(struct kfd_process *p, uint32_t gpu_id); +@@ -1337,7 +1338,7 @@ void device_queue_manager_uninit(struct device_queue_manager *dqm); + struct kernel_queue *kernel_queue_init(struct kfd_node *dev, + enum kfd_queue_type type); + void kernel_queue_uninit(struct kernel_queue *kq); +-int kfd_dqm_evict_pasid(struct device_queue_manager *dqm, u32 pasid); ++int kfd_evict_process_device(struct kfd_process_device *pdd); + int kfd_dqm_suspend_bad_queue_mes(struct kfd_node *knode, u32 pasid, u32 doorbell_id); + + /* Process Queue Manager */ +@@ -1492,7 +1493,7 @@ int kfd_event_create(struct file *devkfd, struct kfd_process *p, + int kfd_get_num_events(struct kfd_process *p); + int kfd_event_destroy(struct kfd_process *p, uint32_t event_id); + +-void kfd_signal_vm_fault_event(struct kfd_node *dev, u32 pasid, ++void kfd_signal_vm_fault_event(struct kfd_process_device *pdd, + struct kfd_vm_fault_info *info, + struct kfd_hsa_memory_exception_data *data); + +diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c +index c9cbc0ecd9cb2..a7e0a16dac47b 100644 +--- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c ++++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c +@@ -283,8 +283,8 @@ static int kfd_get_cu_occupancy(struct attribute *attr, char *buffer) + cu_cnt = 0; + proc = pdd->process; + if (pdd->qpd.queue_count == 0) { +- pr_debug("Gpu-Id: %d has no active queues for process %d\n", +- dev->id, proc->pasid); ++ pr_debug("Gpu-Id: %d has no active queues for process pid %d\n", ++ dev->id, (int)proc->lead_thread->pid); + return snprintf(buffer, PAGE_SIZE, "%d\n", cu_cnt); + } + +@@ -328,12 +328,9 @@ static int kfd_get_cu_occupancy(struct attribute *attr, char *buffer) + static ssize_t kfd_procfs_show(struct kobject *kobj, struct attribute *attr, + char *buffer) + { +- if (strcmp(attr->name, "pasid") == 0) { +- struct kfd_process *p = container_of(attr, struct kfd_process, +- attr_pasid); +- +- return snprintf(buffer, PAGE_SIZE, "%d\n", p->pasid); +- } else if (strncmp(attr->name, "vram_", 5) == 0) { ++ if (strcmp(attr->name, "pasid") == 0) ++ return snprintf(buffer, PAGE_SIZE, "%d\n", 0); ++ else if (strncmp(attr->name, "vram_", 5) == 0) { + struct kfd_process_device *pdd = container_of(attr, struct kfd_process_device, + attr_vram); + return snprintf(buffer, PAGE_SIZE, "%llu\n", atomic64_read(&pdd->vram_usage)); +@@ -1057,9 +1054,8 @@ static void kfd_process_destroy_pdds(struct kfd_process *p) + for (i = 0; i < p->n_pdds; i++) { + struct kfd_process_device *pdd = p->pdds[i]; + +- pr_debug("Releasing pdd (topology id %d) for process (pasid 0x%x)\n", +- pdd->dev->id, p->pasid); +- ++ pr_debug("Releasing pdd (topology id %d, for pid %d)\n", ++ pdd->dev->id, p->lead_thread->pid); + kfd_process_device_destroy_cwsr_dgpu(pdd); + kfd_process_device_destroy_ib_mem(pdd); + +@@ -1191,7 +1187,6 @@ static void kfd_process_wq_release(struct work_struct *work) + + kfd_event_free_process(p); + +- kfd_pasid_free(p->pasid); + mutex_destroy(&p->mutex); + + put_task_struct(p->lead_thread); +@@ -1542,12 +1537,6 @@ static struct kfd_process *create_process(const struct task_struct *thread) + atomic_set(&process->debugged_process_count, 0); + sema_init(&process->runtime_enable_sema, 0); + +- process->pasid = kfd_pasid_alloc(); +- if (process->pasid == 0) { +- err = -ENOSPC; +- goto err_alloc_pasid; +- } +- + err = pqm_init(&process->pqm, process); + if (err != 0) + goto err_process_pqm_init; +@@ -1601,8 +1590,6 @@ static struct kfd_process *create_process(const struct task_struct *thread) + err_init_apertures: + pqm_uninit(&process->pqm); + err_process_pqm_init: +- kfd_pasid_free(process->pasid); +-err_alloc_pasid: + kfd_event_free_process(process); + err_event_init: + mutex_destroy(&process->mutex); +@@ -1721,15 +1708,18 @@ int kfd_process_device_init_vm(struct kfd_process_device *pdd, + if (ret) + goto err_init_cwsr; + +- ret = amdgpu_amdkfd_gpuvm_set_vm_pasid(dev->adev, avm, p->pasid); +- if (ret) +- goto err_set_pasid; ++ if (unlikely(!avm->pasid)) { ++ dev_warn(pdd->dev->adev->dev, "WARN: vm %p has no pasid associated", ++ avm); ++ goto err_get_pasid; ++ } + ++ pdd->pasid = avm->pasid; + pdd->drm_file = drm_file; + + return 0; + +-err_set_pasid: ++err_get_pasid: + kfd_process_device_destroy_cwsr_dgpu(pdd); + err_init_cwsr: + kfd_process_device_destroy_ib_mem(pdd); +@@ -1815,25 +1805,50 @@ void kfd_process_device_remove_obj_handle(struct kfd_process_device *pdd, + idr_remove(&pdd->alloc_idr, handle); + } + +-/* This increments the process->ref counter. */ +-struct kfd_process *kfd_lookup_process_by_pasid(u32 pasid) ++static struct kfd_process_device *kfd_lookup_process_device_by_pasid(u32 pasid) + { +- struct kfd_process *p, *ret_p = NULL; ++ struct kfd_process_device *ret_p = NULL; ++ struct kfd_process *p; + unsigned int temp; +- +- int idx = srcu_read_lock(&kfd_processes_srcu); ++ int i; + + hash_for_each_rcu(kfd_processes_table, temp, p, kfd_processes) { +- if (p->pasid == pasid) { +- kref_get(&p->ref); +- ret_p = p; +- break; ++ for (i = 0; i < p->n_pdds; i++) { ++ if (p->pdds[i]->pasid == pasid) { ++ ret_p = p->pdds[i]; ++ break; ++ } + } ++ if (ret_p) ++ break; ++ } ++ return ret_p; ++} ++ ++/* This increments the process->ref counter. */ ++struct kfd_process *kfd_lookup_process_by_pasid(u32 pasid, ++ struct kfd_process_device **pdd) ++{ ++ struct kfd_process_device *ret_p; ++ ++ int idx = srcu_read_lock(&kfd_processes_srcu); ++ ++ ret_p = kfd_lookup_process_device_by_pasid(pasid); ++ if (ret_p) { ++ if (pdd) ++ *pdd = ret_p; ++ kref_get(&ret_p->process->ref); ++ ++ srcu_read_unlock(&kfd_processes_srcu, idx); ++ return ret_p->process; + } + + srcu_read_unlock(&kfd_processes_srcu, idx); + +- return ret_p; ++ if (pdd) ++ *pdd = NULL; ++ ++ return NULL; + } + + /* This increments the process->ref counter. */ +@@ -1989,7 +2004,7 @@ static void evict_process_worker(struct work_struct *work) + */ + p = container_of(dwork, struct kfd_process, eviction_work); + +- pr_debug("Started evicting pasid 0x%x\n", p->pasid); ++ pr_debug("Started evicting process pid %d\n", p->lead_thread->pid); + ret = kfd_process_evict_queues(p, KFD_QUEUE_EVICTION_TRIGGER_TTM); + if (!ret) { + /* If another thread already signaled the eviction fence, +@@ -2001,9 +2016,9 @@ static void evict_process_worker(struct work_struct *work) + msecs_to_jiffies(PROCESS_RESTORE_TIME_MS))) + kfd_process_restore_queues(p); + +- pr_debug("Finished evicting pasid 0x%x\n", p->pasid); ++ pr_debug("Finished evicting process pid %d\n", p->lead_thread->pid); + } else +- pr_err("Failed to evict queues of pasid 0x%x\n", p->pasid); ++ pr_err("Failed to evict queues of process pid %d\n", p->lead_thread->pid); + } + + static int restore_process_helper(struct kfd_process *p) +@@ -2020,9 +2035,11 @@ static int restore_process_helper(struct kfd_process *p) + + ret = kfd_process_restore_queues(p); + if (!ret) +- pr_debug("Finished restoring pasid 0x%x\n", p->pasid); ++ pr_debug("Finished restoring process pid %d\n", ++ p->lead_thread->pid); + else +- pr_err("Failed to restore queues of pasid 0x%x\n", p->pasid); ++ pr_err("Failed to restore queues of process pid %d\n", ++ p->lead_thread->pid); + + return ret; + } +@@ -2039,7 +2056,7 @@ static void restore_process_worker(struct work_struct *work) + * lifetime of this thread, kfd_process p will be valid + */ + p = container_of(dwork, struct kfd_process, restore_work); +- pr_debug("Started restoring pasid 0x%x\n", p->pasid); ++ pr_debug("Started restoring process pasid %d\n", (int)p->lead_thread->pid); + + /* Setting last_restore_timestamp before successful restoration. + * Otherwise this would have to be set by KGD (restore_process_bos) +@@ -2055,8 +2072,8 @@ static void restore_process_worker(struct work_struct *work) + + ret = restore_process_helper(p); + if (ret) { +- pr_debug("Failed to restore BOs of pasid 0x%x, retry after %d ms\n", +- p->pasid, PROCESS_BACK_OFF_TIME_MS); ++ pr_debug("Failed to restore BOs of process pid %d, retry after %d ms\n", ++ p->lead_thread->pid, PROCESS_BACK_OFF_TIME_MS); + if (mod_delayed_work(kfd_restore_wq, &p->restore_work, + msecs_to_jiffies(PROCESS_RESTORE_TIME_MS))) + kfd_process_restore_queues(p); +@@ -2072,7 +2089,7 @@ void kfd_suspend_all_processes(void) + WARN(debug_evictions, "Evicting all processes"); + hash_for_each_rcu(kfd_processes_table, temp, p, kfd_processes) { + if (kfd_process_evict_queues(p, KFD_QUEUE_EVICTION_TRIGGER_SUSPEND)) +- pr_err("Failed to suspend process 0x%x\n", p->pasid); ++ pr_err("Failed to suspend process pid %d\n", p->lead_thread->pid); + signal_eviction_fence(p); + } + srcu_read_unlock(&kfd_processes_srcu, idx); +@@ -2086,8 +2103,8 @@ int kfd_resume_all_processes(void) + + hash_for_each_rcu(kfd_processes_table, temp, p, kfd_processes) { + if (restore_process_helper(p)) { +- pr_err("Restore process %d failed during resume\n", +- p->pasid); ++ pr_err("Restore process pid %d failed during resume\n", ++ p->lead_thread->pid); + ret = -EFAULT; + } + } +@@ -2142,7 +2159,7 @@ int kfd_process_drain_interrupts(struct kfd_process_device *pdd) + memset(irq_drain_fence, 0, sizeof(irq_drain_fence)); + irq_drain_fence[0] = (KFD_IRQ_FENCE_SOURCEID << 8) | + KFD_IRQ_FENCE_CLIENTID; +- irq_drain_fence[3] = pdd->process->pasid; ++ irq_drain_fence[3] = pdd->pasid; + + /* + * For GFX 9.4.3/9.5.0, send the NodeId also in IH cookie DW[3] +@@ -2173,7 +2190,7 @@ void kfd_process_close_interrupt_drain(unsigned int pasid) + { + struct kfd_process *p; + +- p = kfd_lookup_process_by_pasid(pasid); ++ p = kfd_lookup_process_by_pasid(pasid, NULL); + + if (!p) + return; +@@ -2294,8 +2311,8 @@ int kfd_debugfs_mqds_by_process(struct seq_file *m, void *data) + int idx = srcu_read_lock(&kfd_processes_srcu); + + hash_for_each_rcu(kfd_processes_table, temp, p, kfd_processes) { +- seq_printf(m, "Process %d PASID 0x%x:\n", +- p->lead_thread->tgid, p->pasid); ++ seq_printf(m, "Process %d PASID %d:\n", ++ p->lead_thread->tgid, p->lead_thread->pid); + + mutex_lock(&p->mutex); + r = pqm_debugfs_mqds(m, &p->pqm); +diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c +index d79caa1a68676..662c595ce7838 100644 +--- a/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c ++++ b/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c +@@ -69,8 +69,8 @@ static int find_available_queue_slot(struct process_queue_manager *pqm, + pr_debug("The new slot id %lu\n", found); + + if (found >= KFD_MAX_NUM_OF_QUEUES_PER_PROCESS) { +- pr_info("Cannot open more queues for process with pasid 0x%x\n", +- pqm->process->pasid); ++ pr_info("Cannot open more queues for process with pid %d\n", ++ pqm->process->lead_thread->pid); + return -ENOMEM; + } + +@@ -451,8 +451,8 @@ int pqm_create_queue(struct process_queue_manager *pqm, + } + + if (retval != 0) { +- pr_err("Pasid 0x%x DQM create queue type %d failed. ret %d\n", +- pqm->process->pasid, type, retval); ++ pr_err("process pid %d DQM create queue type %d failed. ret %d\n", ++ pqm->process->lead_thread->pid, type, retval); + goto err_create_queue; + } + +@@ -546,7 +546,7 @@ int pqm_destroy_queue(struct process_queue_manager *pqm, unsigned int qid) + retval = dqm->ops.destroy_queue(dqm, &pdd->qpd, pqn->q); + if (retval) { + pr_err("Pasid 0x%x destroy queue %d failed, ret %d\n", +- pqm->process->pasid, ++ pdd->pasid, + pqn->q->properties.queue_id, retval); + if (retval != -ETIME && retval != -EIO) + goto err_destroy_queue; +diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c +index 47189453b20c3..116116a9f5781 100644 +--- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c ++++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c +@@ -563,7 +563,8 @@ svm_range_vram_node_new(struct kfd_node *node, struct svm_range *prange, + int r; + + p = container_of(prange->svms, struct kfd_process, svms); +- pr_debug("pasid: %x svms 0x%p [0x%lx 0x%lx]\n", p->pasid, prange->svms, ++ pr_debug("process pid: %d svms 0x%p [0x%lx 0x%lx]\n", ++ p->lead_thread->pid, prange->svms, + prange->start, prange->last); + + if (svm_range_validate_svm_bo(node, prange)) +@@ -2973,7 +2974,7 @@ svm_range_restore_pages(struct amdgpu_device *adev, unsigned int pasid, + return -EFAULT; + } + +- p = kfd_lookup_process_by_pasid(pasid); ++ p = kfd_lookup_process_by_pasid(pasid, NULL); + if (!p) { + pr_debug("kfd process not founded pasid 0x%x\n", pasid); + return 0; +@@ -3239,7 +3240,8 @@ void svm_range_list_fini(struct kfd_process *p) + struct svm_range *prange; + struct svm_range *next; + +- pr_debug("pasid 0x%x svms 0x%p\n", p->pasid, &p->svms); ++ pr_debug("process pid %d svms 0x%p\n", p->lead_thread->pid, ++ &p->svms); + + cancel_delayed_work_sync(&p->svms.restore_work); + +@@ -3262,7 +3264,8 @@ void svm_range_list_fini(struct kfd_process *p) + + mutex_destroy(&p->svms.lock); + +- pr_debug("pasid 0x%x svms 0x%p done\n", p->pasid, &p->svms); ++ pr_debug("process pid %d svms 0x%p done\n", ++ p->lead_thread->pid, &p->svms); + } + + int svm_range_list_init(struct kfd_process *p) +@@ -3625,8 +3628,8 @@ svm_range_set_attr(struct kfd_process *p, struct mm_struct *mm, + bool flush_tlb; + int r, ret = 0; + +- pr_debug("pasid 0x%x svms 0x%p [0x%llx 0x%llx] pages 0x%llx\n", +- p->pasid, &p->svms, start, start + size - 1, size); ++ pr_debug("process pid %d svms 0x%p [0x%llx 0x%llx] pages 0x%llx\n", ++ p->lead_thread->pid, &p->svms, start, start + size - 1, size); + + r = svm_range_check_attr(p, nattr, attrs); + if (r) +@@ -3734,8 +3737,8 @@ svm_range_set_attr(struct kfd_process *p, struct mm_struct *mm, + out: + mutex_unlock(&process_info->lock); + +- pr_debug("pasid 0x%x svms 0x%p [0x%llx 0x%llx] done, r=%d\n", p->pasid, +- &p->svms, start, start + size - 1, r); ++ pr_debug("process pid %d svms 0x%p [0x%llx 0x%llx] done, r=%d\n", ++ p->lead_thread->pid, &p->svms, start, start + size - 1, r); + + return ret ? ret : r; + } +-- +2.39.5 + diff --git a/queue-6.14/drm-amdkfd-kfd-release_work-possible-circular-lockin.patch b/queue-6.14/drm-amdkfd-kfd-release_work-possible-circular-lockin.patch new file mode 100644 index 0000000000..96c27d2cee --- /dev/null +++ b/queue-6.14/drm-amdkfd-kfd-release_work-possible-circular-lockin.patch @@ -0,0 +1,80 @@ +From 6885273d67c22bddb4e6e30f3b4ba04a458023c7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Feb 2025 20:08:29 -0500 +Subject: drm/amdkfd: KFD release_work possible circular locking + +From: Philip Yang + +[ Upstream commit 1b9366c601039d60546794c63fbb83ce8e53b978 ] + +If waiting for gpu reset done in KFD release_work, thers is WARNING: +possible circular locking dependency detected + + #2 kfd_create_process + kfd_process_mutex + flush kfd release work + + #1 kfd release work + wait for amdgpu reset work + + #0 amdgpu_device_gpu_reset + kgd2kfd_pre_reset + kfd_process_mutex + + Possible unsafe locking scenario: + + CPU0 CPU1 + ---- ---- + lock((work_completion)(&p->release_work)); + lock((wq_completion)kfd_process_wq); + lock((work_completion)(&p->release_work)); + lock((wq_completion)amdgpu-reset-dev); + +To fix this, KFD create process move flush release work outside +kfd_process_mutex. + +Signed-off-by: Philip Yang +Reviewed-by: Felix Kuehling +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/amdkfd/kfd_process.c | 16 ++++++++-------- + 1 file changed, 8 insertions(+), 8 deletions(-) + +diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c +index c3f2c0428e013..c9cbc0ecd9cb2 100644 +--- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c ++++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c +@@ -842,6 +842,14 @@ struct kfd_process *kfd_create_process(struct task_struct *thread) + return ERR_PTR(-EINVAL); + } + ++ /* If the process just called exec(3), it is possible that the ++ * cleanup of the kfd_process (following the release of the mm ++ * of the old process image) is still in the cleanup work queue. ++ * Make sure to drain any job before trying to recreate any ++ * resource for this process. ++ */ ++ flush_workqueue(kfd_process_wq); ++ + /* + * take kfd processes mutex before starting of process creation + * so there won't be a case where two threads of the same process +@@ -862,14 +870,6 @@ struct kfd_process *kfd_create_process(struct task_struct *thread) + if (process) { + pr_debug("Process already found\n"); + } else { +- /* If the process just called exec(3), it is possible that the +- * cleanup of the kfd_process (following the release of the mm +- * of the old process image) is still in the cleanup work queue. +- * Make sure to drain any job before trying to recreate any +- * resource for this process. +- */ +- flush_workqueue(kfd_process_wq); +- + process = create_process(thread); + if (IS_ERR(process)) + goto out; +-- +2.39.5 + diff --git a/queue-6.14/drm-amdkfd-set-per-process-flags-only-once-cik-vi.patch b/queue-6.14/drm-amdkfd-set-per-process-flags-only-once-cik-vi.patch new file mode 100644 index 0000000000..23c06165c0 --- /dev/null +++ b/queue-6.14/drm-amdkfd-set-per-process-flags-only-once-cik-vi.patch @@ -0,0 +1,301 @@ +From c1e74e5dd6097dade4ca575cd47120dbe43c6cfe Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 14 Jan 2025 14:07:24 -0500 +Subject: drm/amdkfd: Set per-process flags only once cik/vi + +From: Harish Kasiviswanathan + +[ Upstream commit 289e68503a4533b014f8447e2af28ad44c92c221 ] + +Set per-process static sh_mem config only once during process +initialization. Move all static changes from update_qpd() which is +called each time a queue is created to set_cache_memory_policy() which +is called once during process initialization. + +set_cache_memory_policy() is currently defined only for cik and vi +family. So this commit only focuses on these two. A separate commit will +address other asics. + +Signed-off-by: Harish Kasiviswanathan +Reviewed-by: Amber Lin +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + .../drm/amd/amdkfd/kfd_device_queue_manager.c | 39 +--------- + .../amd/amdkfd/kfd_device_queue_manager_cik.c | 69 ++++++++++++------ + .../amd/amdkfd/kfd_device_queue_manager_vi.c | 71 ++++++++++++------- + 3 files changed, 94 insertions(+), 85 deletions(-) + +diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c +index ad9cb50a9fa38..7f8ec2a152ac6 100644 +--- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c ++++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c +@@ -2491,14 +2491,6 @@ static int destroy_queue_cpsch(struct device_queue_manager *dqm, + return retval; + } + +-/* +- * Low bits must be 0000/FFFF as required by HW, high bits must be 0 to +- * stay in user mode. +- */ +-#define APE1_FIXED_BITS_MASK 0xFFFF80000000FFFFULL +-/* APE1 limit is inclusive and 64K aligned. */ +-#define APE1_LIMIT_ALIGNMENT 0xFFFF +- + static bool set_cache_memory_policy(struct device_queue_manager *dqm, + struct qcm_process_device *qpd, + enum cache_policy default_policy, +@@ -2513,34 +2505,6 @@ static bool set_cache_memory_policy(struct device_queue_manager *dqm, + + dqm_lock(dqm); + +- if (alternate_aperture_size == 0) { +- /* base > limit disables APE1 */ +- qpd->sh_mem_ape1_base = 1; +- qpd->sh_mem_ape1_limit = 0; +- } else { +- /* +- * In FSA64, APE1_Base[63:0] = { 16{SH_MEM_APE1_BASE[31]}, +- * SH_MEM_APE1_BASE[31:0], 0x0000 } +- * APE1_Limit[63:0] = { 16{SH_MEM_APE1_LIMIT[31]}, +- * SH_MEM_APE1_LIMIT[31:0], 0xFFFF } +- * Verify that the base and size parameters can be +- * represented in this format and convert them. +- * Additionally restrict APE1 to user-mode addresses. +- */ +- +- uint64_t base = (uintptr_t)alternate_aperture_base; +- uint64_t limit = base + alternate_aperture_size - 1; +- +- if (limit <= base || (base & APE1_FIXED_BITS_MASK) != 0 || +- (limit & APE1_FIXED_BITS_MASK) != APE1_LIMIT_ALIGNMENT) { +- retval = false; +- goto out; +- } +- +- qpd->sh_mem_ape1_base = base >> 16; +- qpd->sh_mem_ape1_limit = limit >> 16; +- } +- + retval = dqm->asic_ops.set_cache_memory_policy( + dqm, + qpd, +@@ -2549,6 +2513,9 @@ static bool set_cache_memory_policy(struct device_queue_manager *dqm, + alternate_aperture_base, + alternate_aperture_size); + ++ if (retval) ++ goto out; ++ + if ((dqm->sched_policy == KFD_SCHED_POLICY_NO_HWS) && (qpd->vmid != 0)) + program_sh_mem_settings(dqm, qpd); + +diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_cik.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_cik.c +index d4d95c7f2e5d4..32bedef912b3b 100644 +--- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_cik.c ++++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_cik.c +@@ -27,6 +27,14 @@ + #include "oss/oss_2_4_sh_mask.h" + #include "gca/gfx_7_2_sh_mask.h" + ++/* ++ * Low bits must be 0000/FFFF as required by HW, high bits must be 0 to ++ * stay in user mode. ++ */ ++#define APE1_FIXED_BITS_MASK 0xFFFF80000000FFFFULL ++/* APE1 limit is inclusive and 64K aligned. */ ++#define APE1_LIMIT_ALIGNMENT 0xFFFF ++ + static bool set_cache_memory_policy_cik(struct device_queue_manager *dqm, + struct qcm_process_device *qpd, + enum cache_policy default_policy, +@@ -84,6 +92,36 @@ static bool set_cache_memory_policy_cik(struct device_queue_manager *dqm, + { + uint32_t default_mtype; + uint32_t ape1_mtype; ++ unsigned int temp; ++ bool retval = true; ++ ++ if (alternate_aperture_size == 0) { ++ /* base > limit disables APE1 */ ++ qpd->sh_mem_ape1_base = 1; ++ qpd->sh_mem_ape1_limit = 0; ++ } else { ++ /* ++ * In FSA64, APE1_Base[63:0] = { 16{SH_MEM_APE1_BASE[31]}, ++ * SH_MEM_APE1_BASE[31:0], 0x0000 } ++ * APE1_Limit[63:0] = { 16{SH_MEM_APE1_LIMIT[31]}, ++ * SH_MEM_APE1_LIMIT[31:0], 0xFFFF } ++ * Verify that the base and size parameters can be ++ * represented in this format and convert them. ++ * Additionally restrict APE1 to user-mode addresses. ++ */ ++ ++ uint64_t base = (uintptr_t)alternate_aperture_base; ++ uint64_t limit = base + alternate_aperture_size - 1; ++ ++ if (limit <= base || (base & APE1_FIXED_BITS_MASK) != 0 || ++ (limit & APE1_FIXED_BITS_MASK) != APE1_LIMIT_ALIGNMENT) { ++ retval = false; ++ goto out; ++ } ++ ++ qpd->sh_mem_ape1_base = base >> 16; ++ qpd->sh_mem_ape1_limit = limit >> 16; ++ } + + default_mtype = (default_policy == cache_policy_coherent) ? + MTYPE_NONCACHED : +@@ -97,37 +135,22 @@ static bool set_cache_memory_policy_cik(struct device_queue_manager *dqm, + | ALIGNMENT_MODE(SH_MEM_ALIGNMENT_MODE_UNALIGNED) + | DEFAULT_MTYPE(default_mtype) + | APE1_MTYPE(ape1_mtype); +- +- return true; +-} +- +-static int update_qpd_cik(struct device_queue_manager *dqm, +- struct qcm_process_device *qpd) +-{ +- struct kfd_process_device *pdd; +- unsigned int temp; +- +- pdd = qpd_to_pdd(qpd); +- +- /* check if sh_mem_config register already configured */ +- if (qpd->sh_mem_config == 0) { +- qpd->sh_mem_config = +- ALIGNMENT_MODE(SH_MEM_ALIGNMENT_MODE_UNALIGNED) | +- DEFAULT_MTYPE(MTYPE_NONCACHED) | +- APE1_MTYPE(MTYPE_NONCACHED); +- qpd->sh_mem_ape1_limit = 0; +- qpd->sh_mem_ape1_base = 0; +- } +- + /* On dGPU we're always in GPUVM64 addressing mode with 64-bit + * aperture addresses. + */ +- temp = get_sh_mem_bases_nybble_64(pdd); ++ temp = get_sh_mem_bases_nybble_64(qpd_to_pdd(qpd)); + qpd->sh_mem_bases = compute_sh_mem_bases_64bit(temp); + + pr_debug("is32bit process: %d sh_mem_bases nybble: 0x%X and register 0x%X\n", + qpd->pqm->process->is_32bit_user_mode, temp, qpd->sh_mem_bases); + ++out: ++ return retval; ++} ++ ++static int update_qpd_cik(struct device_queue_manager *dqm, ++ struct qcm_process_device *qpd) ++{ + return 0; + } + +diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_vi.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_vi.c +index b291ee0fab943..320518f418903 100644 +--- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_vi.c ++++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_vi.c +@@ -27,6 +27,14 @@ + #include "gca/gfx_8_0_sh_mask.h" + #include "oss/oss_3_0_sh_mask.h" + ++/* ++ * Low bits must be 0000/FFFF as required by HW, high bits must be 0 to ++ * stay in user mode. ++ */ ++#define APE1_FIXED_BITS_MASK 0xFFFF80000000FFFFULL ++/* APE1 limit is inclusive and 64K aligned. */ ++#define APE1_LIMIT_ALIGNMENT 0xFFFF ++ + static bool set_cache_memory_policy_vi(struct device_queue_manager *dqm, + struct qcm_process_device *qpd, + enum cache_policy default_policy, +@@ -85,6 +93,36 @@ static bool set_cache_memory_policy_vi(struct device_queue_manager *dqm, + { + uint32_t default_mtype; + uint32_t ape1_mtype; ++ unsigned int temp; ++ bool retval = true; ++ ++ if (alternate_aperture_size == 0) { ++ /* base > limit disables APE1 */ ++ qpd->sh_mem_ape1_base = 1; ++ qpd->sh_mem_ape1_limit = 0; ++ } else { ++ /* ++ * In FSA64, APE1_Base[63:0] = { 16{SH_MEM_APE1_BASE[31]}, ++ * SH_MEM_APE1_BASE[31:0], 0x0000 } ++ * APE1_Limit[63:0] = { 16{SH_MEM_APE1_LIMIT[31]}, ++ * SH_MEM_APE1_LIMIT[31:0], 0xFFFF } ++ * Verify that the base and size parameters can be ++ * represented in this format and convert them. ++ * Additionally restrict APE1 to user-mode addresses. ++ */ ++ ++ uint64_t base = (uintptr_t)alternate_aperture_base; ++ uint64_t limit = base + alternate_aperture_size - 1; ++ ++ if (limit <= base || (base & APE1_FIXED_BITS_MASK) != 0 || ++ (limit & APE1_FIXED_BITS_MASK) != APE1_LIMIT_ALIGNMENT) { ++ retval = false; ++ goto out; ++ } ++ ++ qpd->sh_mem_ape1_base = base >> 16; ++ qpd->sh_mem_ape1_limit = limit >> 16; ++ } + + default_mtype = (default_policy == cache_policy_coherent) ? + MTYPE_UC : +@@ -100,40 +138,21 @@ static bool set_cache_memory_policy_vi(struct device_queue_manager *dqm, + default_mtype << SH_MEM_CONFIG__DEFAULT_MTYPE__SHIFT | + ape1_mtype << SH_MEM_CONFIG__APE1_MTYPE__SHIFT; + +- return true; +-} +- +-static int update_qpd_vi(struct device_queue_manager *dqm, +- struct qcm_process_device *qpd) +-{ +- struct kfd_process_device *pdd; +- unsigned int temp; +- +- pdd = qpd_to_pdd(qpd); +- +- /* check if sh_mem_config register already configured */ +- if (qpd->sh_mem_config == 0) { +- qpd->sh_mem_config = +- SH_MEM_ALIGNMENT_MODE_UNALIGNED << +- SH_MEM_CONFIG__ALIGNMENT_MODE__SHIFT | +- MTYPE_UC << +- SH_MEM_CONFIG__DEFAULT_MTYPE__SHIFT | +- MTYPE_UC << +- SH_MEM_CONFIG__APE1_MTYPE__SHIFT; +- +- qpd->sh_mem_ape1_limit = 0; +- qpd->sh_mem_ape1_base = 0; +- } +- + /* On dGPU we're always in GPUVM64 addressing mode with 64-bit + * aperture addresses. + */ +- temp = get_sh_mem_bases_nybble_64(pdd); ++ temp = get_sh_mem_bases_nybble_64(qpd_to_pdd(qpd)); + qpd->sh_mem_bases = compute_sh_mem_bases_64bit(temp); + + pr_debug("sh_mem_bases nybble: 0x%X and register 0x%X\n", + temp, qpd->sh_mem_bases); ++out: ++ return retval; ++} + ++static int update_qpd_vi(struct device_queue_manager *dqm, ++ struct qcm_process_device *qpd) ++{ + return 0; + } + +-- +2.39.5 + diff --git a/queue-6.14/drm-amdkfd-set-per-process-flags-only-once-for-gfx9-.patch b/queue-6.14/drm-amdkfd-set-per-process-flags-only-once-for-gfx9-.patch new file mode 100644 index 0000000000..a4a42f3315 --- /dev/null +++ b/queue-6.14/drm-amdkfd-set-per-process-flags-only-once-for-gfx9-.patch @@ -0,0 +1,292 @@ +From 2ff1b7d41b89eda2c25989a2ab219bb1bc2442c5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 14 Jan 2025 14:13:35 -0500 +Subject: drm/amdkfd: Set per-process flags only once for gfx9/10/11/12 + +From: Harish Kasiviswanathan + +[ Upstream commit 61972cd93af70738a6ad7f93e17cc7f68a01e182 ] + +Define set_cache_memory_policy() for these asics and move all static +changes from update_qpd() which is called each time a queue is created +to set_cache_memory_policy() which is called once during process +initialization + +Signed-off-by: Harish Kasiviswanathan +Reviewed-by: Amber Lin +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + .../amd/amdkfd/kfd_device_queue_manager_v10.c | 41 +++++++++++-------- + .../amd/amdkfd/kfd_device_queue_manager_v11.c | 41 +++++++++++-------- + .../amd/amdkfd/kfd_device_queue_manager_v12.c | 41 +++++++++++-------- + .../amd/amdkfd/kfd_device_queue_manager_v9.c | 36 +++++++++++++++- + 4 files changed, 107 insertions(+), 52 deletions(-) + +diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v10.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v10.c +index 245a90dfc2f6b..b5f5f141353b5 100644 +--- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v10.c ++++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v10.c +@@ -31,10 +31,17 @@ static int update_qpd_v10(struct device_queue_manager *dqm, + struct qcm_process_device *qpd); + static void init_sdma_vm_v10(struct device_queue_manager *dqm, struct queue *q, + struct qcm_process_device *qpd); ++static bool set_cache_memory_policy_v10(struct device_queue_manager *dqm, ++ struct qcm_process_device *qpd, ++ enum cache_policy default_policy, ++ enum cache_policy alternate_policy, ++ void __user *alternate_aperture_base, ++ uint64_t alternate_aperture_size); + + void device_queue_manager_init_v10( + struct device_queue_manager_asic_ops *asic_ops) + { ++ asic_ops->set_cache_memory_policy = set_cache_memory_policy_v10; + asic_ops->update_qpd = update_qpd_v10; + asic_ops->init_sdma_vm = init_sdma_vm_v10; + asic_ops->mqd_manager_init = mqd_manager_init_v10; +@@ -49,27 +56,27 @@ static uint32_t compute_sh_mem_bases_64bit(struct kfd_process_device *pdd) + private_base; + } + +-static int update_qpd_v10(struct device_queue_manager *dqm, +- struct qcm_process_device *qpd) ++static bool set_cache_memory_policy_v10(struct device_queue_manager *dqm, ++ struct qcm_process_device *qpd, ++ enum cache_policy default_policy, ++ enum cache_policy alternate_policy, ++ void __user *alternate_aperture_base, ++ uint64_t alternate_aperture_size) + { +- struct kfd_process_device *pdd; +- +- pdd = qpd_to_pdd(qpd); +- +- /* check if sh_mem_config register already configured */ +- if (qpd->sh_mem_config == 0) { +- qpd->sh_mem_config = +- (SH_MEM_ALIGNMENT_MODE_UNALIGNED << +- SH_MEM_CONFIG__ALIGNMENT_MODE__SHIFT) | +- (3 << SH_MEM_CONFIG__INITIAL_INST_PREFETCH__SHIFT); +- qpd->sh_mem_ape1_limit = 0; +- qpd->sh_mem_ape1_base = 0; +- } +- +- qpd->sh_mem_bases = compute_sh_mem_bases_64bit(pdd); ++ qpd->sh_mem_config = (SH_MEM_ALIGNMENT_MODE_UNALIGNED << ++ SH_MEM_CONFIG__ALIGNMENT_MODE__SHIFT) | ++ (3 << SH_MEM_CONFIG__INITIAL_INST_PREFETCH__SHIFT); ++ qpd->sh_mem_ape1_limit = 0; ++ qpd->sh_mem_ape1_base = 0; ++ qpd->sh_mem_bases = compute_sh_mem_bases_64bit(qpd_to_pdd(qpd)); + + pr_debug("sh_mem_bases 0x%X\n", qpd->sh_mem_bases); ++ return true; ++} + ++static int update_qpd_v10(struct device_queue_manager *dqm, ++ struct qcm_process_device *qpd) ++{ + return 0; + } + +diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v11.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v11.c +index 2e129da7acb43..f436878d0d621 100644 +--- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v11.c ++++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v11.c +@@ -30,10 +30,17 @@ static int update_qpd_v11(struct device_queue_manager *dqm, + struct qcm_process_device *qpd); + static void init_sdma_vm_v11(struct device_queue_manager *dqm, struct queue *q, + struct qcm_process_device *qpd); ++static bool set_cache_memory_policy_v11(struct device_queue_manager *dqm, ++ struct qcm_process_device *qpd, ++ enum cache_policy default_policy, ++ enum cache_policy alternate_policy, ++ void __user *alternate_aperture_base, ++ uint64_t alternate_aperture_size); + + void device_queue_manager_init_v11( + struct device_queue_manager_asic_ops *asic_ops) + { ++ asic_ops->set_cache_memory_policy = set_cache_memory_policy_v11; + asic_ops->update_qpd = update_qpd_v11; + asic_ops->init_sdma_vm = init_sdma_vm_v11; + asic_ops->mqd_manager_init = mqd_manager_init_v11; +@@ -48,28 +55,28 @@ static uint32_t compute_sh_mem_bases_64bit(struct kfd_process_device *pdd) + private_base; + } + +-static int update_qpd_v11(struct device_queue_manager *dqm, +- struct qcm_process_device *qpd) ++static bool set_cache_memory_policy_v11(struct device_queue_manager *dqm, ++ struct qcm_process_device *qpd, ++ enum cache_policy default_policy, ++ enum cache_policy alternate_policy, ++ void __user *alternate_aperture_base, ++ uint64_t alternate_aperture_size) + { +- struct kfd_process_device *pdd; +- +- pdd = qpd_to_pdd(qpd); +- +- /* check if sh_mem_config register already configured */ +- if (qpd->sh_mem_config == 0) { +- qpd->sh_mem_config = +- (SH_MEM_ALIGNMENT_MODE_UNALIGNED << +- SH_MEM_CONFIG__ALIGNMENT_MODE__SHIFT) | +- (3 << SH_MEM_CONFIG__INITIAL_INST_PREFETCH__SHIFT); +- +- qpd->sh_mem_ape1_limit = 0; +- qpd->sh_mem_ape1_base = 0; +- } ++ qpd->sh_mem_config = (SH_MEM_ALIGNMENT_MODE_UNALIGNED << ++ SH_MEM_CONFIG__ALIGNMENT_MODE__SHIFT) | ++ (3 << SH_MEM_CONFIG__INITIAL_INST_PREFETCH__SHIFT); + +- qpd->sh_mem_bases = compute_sh_mem_bases_64bit(pdd); ++ qpd->sh_mem_ape1_limit = 0; ++ qpd->sh_mem_ape1_base = 0; ++ qpd->sh_mem_bases = compute_sh_mem_bases_64bit(qpd_to_pdd(qpd)); + + pr_debug("sh_mem_bases 0x%X\n", qpd->sh_mem_bases); ++ return true; ++} + ++static int update_qpd_v11(struct device_queue_manager *dqm, ++ struct qcm_process_device *qpd) ++{ + return 0; + } + +diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v12.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v12.c +index 4f3295b29dfb1..62ca1c8fcbaf9 100644 +--- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v12.c ++++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v12.c +@@ -30,10 +30,17 @@ static int update_qpd_v12(struct device_queue_manager *dqm, + struct qcm_process_device *qpd); + static void init_sdma_vm_v12(struct device_queue_manager *dqm, struct queue *q, + struct qcm_process_device *qpd); ++static bool set_cache_memory_policy_v12(struct device_queue_manager *dqm, ++ struct qcm_process_device *qpd, ++ enum cache_policy default_policy, ++ enum cache_policy alternate_policy, ++ void __user *alternate_aperture_base, ++ uint64_t alternate_aperture_size); + + void device_queue_manager_init_v12( + struct device_queue_manager_asic_ops *asic_ops) + { ++ asic_ops->set_cache_memory_policy = set_cache_memory_policy_v12; + asic_ops->update_qpd = update_qpd_v12; + asic_ops->init_sdma_vm = init_sdma_vm_v12; + asic_ops->mqd_manager_init = mqd_manager_init_v12; +@@ -48,28 +55,28 @@ static uint32_t compute_sh_mem_bases_64bit(struct kfd_process_device *pdd) + private_base; + } + +-static int update_qpd_v12(struct device_queue_manager *dqm, +- struct qcm_process_device *qpd) ++static bool set_cache_memory_policy_v12(struct device_queue_manager *dqm, ++ struct qcm_process_device *qpd, ++ enum cache_policy default_policy, ++ enum cache_policy alternate_policy, ++ void __user *alternate_aperture_base, ++ uint64_t alternate_aperture_size) + { +- struct kfd_process_device *pdd; +- +- pdd = qpd_to_pdd(qpd); +- +- /* check if sh_mem_config register already configured */ +- if (qpd->sh_mem_config == 0) { +- qpd->sh_mem_config = +- (SH_MEM_ALIGNMENT_MODE_UNALIGNED << +- SH_MEM_CONFIG__ALIGNMENT_MODE__SHIFT) | +- (3 << SH_MEM_CONFIG__INITIAL_INST_PREFETCH__SHIFT); +- +- qpd->sh_mem_ape1_limit = 0; +- qpd->sh_mem_ape1_base = 0; +- } ++ qpd->sh_mem_config = (SH_MEM_ALIGNMENT_MODE_UNALIGNED << ++ SH_MEM_CONFIG__ALIGNMENT_MODE__SHIFT) | ++ (3 << SH_MEM_CONFIG__INITIAL_INST_PREFETCH__SHIFT); + +- qpd->sh_mem_bases = compute_sh_mem_bases_64bit(pdd); ++ qpd->sh_mem_ape1_limit = 0; ++ qpd->sh_mem_ape1_base = 0; ++ qpd->sh_mem_bases = compute_sh_mem_bases_64bit(qpd_to_pdd(qpd)); + + pr_debug("sh_mem_bases 0x%X\n", qpd->sh_mem_bases); ++ return true; ++} + ++static int update_qpd_v12(struct device_queue_manager *dqm, ++ struct qcm_process_device *qpd) ++{ + return 0; + } + +diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v9.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v9.c +index 67137e674f1d0..c734eb9b505f8 100644 +--- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v9.c ++++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v9.c +@@ -30,10 +30,17 @@ static int update_qpd_v9(struct device_queue_manager *dqm, + struct qcm_process_device *qpd); + static void init_sdma_vm_v9(struct device_queue_manager *dqm, struct queue *q, + struct qcm_process_device *qpd); ++static bool set_cache_memory_policy_v9(struct device_queue_manager *dqm, ++ struct qcm_process_device *qpd, ++ enum cache_policy default_policy, ++ enum cache_policy alternate_policy, ++ void __user *alternate_aperture_base, ++ uint64_t alternate_aperture_size); + + void device_queue_manager_init_v9( + struct device_queue_manager_asic_ops *asic_ops) + { ++ asic_ops->set_cache_memory_policy = set_cache_memory_policy_v9; + asic_ops->update_qpd = update_qpd_v9; + asic_ops->init_sdma_vm = init_sdma_vm_v9; + asic_ops->mqd_manager_init = mqd_manager_init_v9; +@@ -48,10 +55,37 @@ static uint32_t compute_sh_mem_bases_64bit(struct kfd_process_device *pdd) + private_base; + } + ++static bool set_cache_memory_policy_v9(struct device_queue_manager *dqm, ++ struct qcm_process_device *qpd, ++ enum cache_policy default_policy, ++ enum cache_policy alternate_policy, ++ void __user *alternate_aperture_base, ++ uint64_t alternate_aperture_size) ++{ ++ qpd->sh_mem_config = SH_MEM_ALIGNMENT_MODE_UNALIGNED << ++ SH_MEM_CONFIG__ALIGNMENT_MODE__SHIFT; ++ ++ if (dqm->dev->kfd->noretry) ++ qpd->sh_mem_config |= 1 << SH_MEM_CONFIG__RETRY_DISABLE__SHIFT; ++ ++ if (KFD_GC_VERSION(dqm->dev->kfd) == IP_VERSION(9, 4, 3) || ++ KFD_GC_VERSION(dqm->dev->kfd) == IP_VERSION(9, 4, 4) || ++ KFD_GC_VERSION(dqm->dev->kfd) == IP_VERSION(9, 5, 0)) ++ qpd->sh_mem_config |= (1 << SH_MEM_CONFIG__F8_MODE__SHIFT); ++ ++ qpd->sh_mem_ape1_limit = 0; ++ qpd->sh_mem_ape1_base = 0; ++ qpd->sh_mem_bases = compute_sh_mem_bases_64bit(qpd_to_pdd(qpd)); ++ ++ pr_debug("sh_mem_bases 0x%X sh_mem_config 0x%X\n", qpd->sh_mem_bases, ++ qpd->sh_mem_config); ++ return true; ++} ++ + static int update_qpd_v9(struct device_queue_manager *dqm, + struct qcm_process_device *qpd) + { +- struct kfd_process_device *pdd; ++ struct kfd_process_device *pdd = qpd_to_pdd(qpd); + + pdd = qpd_to_pdd(qpd); + +-- +2.39.5 + diff --git a/queue-6.14/drm-amdkfd-set-precise-mem-ops-caps-to-disabled-for-.patch b/queue-6.14/drm-amdkfd-set-precise-mem-ops-caps-to-disabled-for-.patch new file mode 100644 index 0000000000..f46b6fa923 --- /dev/null +++ b/queue-6.14/drm-amdkfd-set-precise-mem-ops-caps-to-disabled-for-.patch @@ -0,0 +1,40 @@ +From 5f19b373457860f7e5e81622b80438efbfd70e4c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 14 Mar 2025 11:08:21 -0400 +Subject: drm/amdkfd: set precise mem ops caps to disabled for gfx 11 and 12 + +From: Jonathan Kim + +[ Upstream commit f82d27dcff939d3cbecbc60e1b71e2518c37e81d ] + +Clause instructions with precise memory enabled currently hang the +shader so set capabilities flag to disabled since it's unsafe to use +for debugging. + +Signed-off-by: Jonathan Kim +Tested-by: Lancelot Six +Reviewed-by: Harish Kasiviswanathan +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/amdkfd/kfd_topology.c | 4 ---- + 1 file changed, 4 deletions(-) + +diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_topology.c b/drivers/gpu/drm/amd/amdkfd/kfd_topology.c +index 62a9a9ccf9bb6..334c576a75b14 100644 +--- a/drivers/gpu/drm/amd/amdkfd/kfd_topology.c ++++ b/drivers/gpu/drm/amd/amdkfd/kfd_topology.c +@@ -2006,10 +2006,6 @@ static void kfd_topology_set_capabilities(struct kfd_topology_device *dev) + dev->node_props.debug_prop |= HSA_DBG_WATCH_ADDR_MASK_LO_BIT_GFX10 | + HSA_DBG_WATCH_ADDR_MASK_HI_BIT; + +- if (KFD_GC_VERSION(dev->gpu) >= IP_VERSION(11, 0, 0)) +- dev->node_props.capability |= +- HSA_CAP_TRAP_DEBUG_PRECISE_MEMORY_OPERATIONS_SUPPORTED; +- + if (KFD_GC_VERSION(dev->gpu) >= IP_VERSION(12, 0, 0)) + dev->node_props.capability |= + HSA_CAP_TRAP_DEBUG_PRECISE_ALU_OPERATIONS_SUPPORTED; +-- +2.39.5 + diff --git a/queue-6.14/drm-ast-find-vbios-mode-from-regular-display-size.patch b/queue-6.14/drm-ast-find-vbios-mode-from-regular-display-size.patch new file mode 100644 index 0000000000..a445bfb152 --- /dev/null +++ b/queue-6.14/drm-ast-find-vbios-mode-from-regular-display-size.patch @@ -0,0 +1,89 @@ +From 75f0b2f9250b97d8b6cf310c79a58e27831ea4ba Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 31 Jan 2025 10:21:08 +0100 +Subject: drm/ast: Find VBIOS mode from regular display size + +From: Thomas Zimmermann + +[ Upstream commit c81202906b5cd56db403e95db3d29c9dfc8c74c1 ] + +The ast driver looks up supplied display modes from an internal list of +display modes supported by the VBIOS. + +Do not use the crtc_-prefixed display values from struct drm_display_mode +for looking up the VBIOS mode. The fields contain raw values that the +driver programs to hardware. They are affected by display settings like +double-scan or interlace. + +Instead use the regular vdisplay and hdisplay fields for lookup. As the +programmed values can now differ from the values used for lookup, set +struct drm_display_mode.crtc_vdisplay and .crtc_hdisplay from the VBIOS +mode. + +Signed-off-by: Thomas Zimmermann +Reviewed-by: Jocelyn Falempe +Link: https://patchwork.freedesktop.org/patch/msgid/20250131092257.115596-9-tzimmermann@suse.de +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/ast/ast_mode.c | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c +index 9d5321c81e68d..a29fe1ae803f1 100644 +--- a/drivers/gpu/drm/ast/ast_mode.c ++++ b/drivers/gpu/drm/ast/ast_mode.c +@@ -131,7 +131,7 @@ static bool ast_get_vbios_mode_info(const struct drm_format_info *format, + return false; + } + +- switch (mode->crtc_hdisplay) { ++ switch (mode->hdisplay) { + case 640: + vbios_mode->enh_table = &res_640x480[refresh_rate_index]; + break; +@@ -145,7 +145,7 @@ static bool ast_get_vbios_mode_info(const struct drm_format_info *format, + vbios_mode->enh_table = &res_1152x864[refresh_rate_index]; + break; + case 1280: +- if (mode->crtc_vdisplay == 800) ++ if (mode->vdisplay == 800) + vbios_mode->enh_table = &res_1280x800[refresh_rate_index]; + else + vbios_mode->enh_table = &res_1280x1024[refresh_rate_index]; +@@ -157,7 +157,7 @@ static bool ast_get_vbios_mode_info(const struct drm_format_info *format, + vbios_mode->enh_table = &res_1440x900[refresh_rate_index]; + break; + case 1600: +- if (mode->crtc_vdisplay == 900) ++ if (mode->vdisplay == 900) + vbios_mode->enh_table = &res_1600x900[refresh_rate_index]; + else + vbios_mode->enh_table = &res_1600x1200[refresh_rate_index]; +@@ -166,7 +166,7 @@ static bool ast_get_vbios_mode_info(const struct drm_format_info *format, + vbios_mode->enh_table = &res_1680x1050[refresh_rate_index]; + break; + case 1920: +- if (mode->crtc_vdisplay == 1080) ++ if (mode->vdisplay == 1080) + vbios_mode->enh_table = &res_1920x1080[refresh_rate_index]; + else + vbios_mode->enh_table = &res_1920x1200[refresh_rate_index]; +@@ -210,6 +210,7 @@ static bool ast_get_vbios_mode_info(const struct drm_format_info *format, + hborder = (vbios_mode->enh_table->flags & HBorder) ? 8 : 0; + vborder = (vbios_mode->enh_table->flags & VBorder) ? 8 : 0; + ++ adjusted_mode->crtc_hdisplay = vbios_mode->enh_table->hde; + adjusted_mode->crtc_htotal = vbios_mode->enh_table->ht; + adjusted_mode->crtc_hblank_start = vbios_mode->enh_table->hde + hborder; + adjusted_mode->crtc_hblank_end = vbios_mode->enh_table->ht - hborder; +@@ -219,6 +220,7 @@ static bool ast_get_vbios_mode_info(const struct drm_format_info *format, + vbios_mode->enh_table->hfp + + vbios_mode->enh_table->hsync); + ++ adjusted_mode->crtc_vdisplay = vbios_mode->enh_table->vde; + adjusted_mode->crtc_vtotal = vbios_mode->enh_table->vt; + adjusted_mode->crtc_vblank_start = vbios_mode->enh_table->vde + vborder; + adjusted_mode->crtc_vblank_end = vbios_mode->enh_table->vt - vborder; +-- +2.39.5 + diff --git a/queue-6.14/drm-ast-hide-gens-1-to-3-tx-detection-in-branch.patch b/queue-6.14/drm-ast-hide-gens-1-to-3-tx-detection-in-branch.patch new file mode 100644 index 0000000000..71e2ad2368 --- /dev/null +++ b/queue-6.14/drm-ast-hide-gens-1-to-3-tx-detection-in-branch.patch @@ -0,0 +1,69 @@ +From 67fddc6a086ae46b2e41e9781b5ac77c6c149ecf Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 17 Jan 2025 11:29:10 +0100 +Subject: drm/ast: Hide Gens 1 to 3 TX detection in branch + +From: Thomas Zimmermann + +[ Upstream commit 87478ba50a05a1f44508316ae109622e8a85adc9 ] + +Gen7 only supports ASTDP. Gens 4 to 6 support various TX chips, +except ASTDP. These boards detect the TX chips by reading the SoC +scratch register as VGACRD1. + +Gens 1 to 3 only support SIL164. These boards read the DVO bit from +VGACRA3. Hence move this test behind a branch, so that it does not +run on later generations. + +Signed-off-by: Thomas Zimmermann +Reviewed-by: Jocelyn Falempe +Link: https://patchwork.freedesktop.org/patch/msgid/20250117103450.28692-6-tzimmermann@suse.de +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/ast/ast_main.c | 30 +++++++++++++++--------------- + 1 file changed, 15 insertions(+), 15 deletions(-) + +diff --git a/drivers/gpu/drm/ast/ast_main.c b/drivers/gpu/drm/ast/ast_main.c +index bc37c65305d48..96470fc8e6e53 100644 +--- a/drivers/gpu/drm/ast/ast_main.c ++++ b/drivers/gpu/drm/ast/ast_main.c +@@ -96,21 +96,21 @@ static void ast_detect_tx_chip(struct ast_device *ast, bool need_post) + /* Check 3rd Tx option (digital output afaik) */ + ast->tx_chip = AST_TX_NONE; + +- /* +- * VGACRA3 Enhanced Color Mode Register, check if DVO is already +- * enabled, in that case, assume we have a SIL164 TMDS transmitter +- * +- * Don't make that assumption if we the chip wasn't enabled and +- * is at power-on reset, otherwise we'll incorrectly "detect" a +- * SIL164 when there is none. +- */ +- if (!need_post) { +- jreg = ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xa3, 0xff); +- if (jreg & 0x80) +- ast->tx_chip = AST_TX_SIL164; +- } +- +- if (IS_AST_GEN4(ast) || IS_AST_GEN5(ast) || IS_AST_GEN6(ast)) { ++ if (AST_GEN(ast) <= 3) { ++ /* ++ * VGACRA3 Enhanced Color Mode Register, check if DVO is already ++ * enabled, in that case, assume we have a SIL164 TMDS transmitter ++ * ++ * Don't make that assumption if we the chip wasn't enabled and ++ * is at power-on reset, otherwise we'll incorrectly "detect" a ++ * SIL164 when there is none. ++ */ ++ if (!need_post) { ++ jreg = ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xa3, 0xff); ++ if (jreg & 0x80) ++ ast->tx_chip = AST_TX_SIL164; ++ } ++ } else if (IS_AST_GEN4(ast) || IS_AST_GEN5(ast) || IS_AST_GEN6(ast)) { + /* + * On AST GEN4+, look the configuration set by the SoC in + * the SOC scratch register #1 bits 11:8 (interestingly marked +-- +2.39.5 + diff --git a/queue-6.14/drm-atomic-clarify-the-rules-around-drm_atomic_state.patch b/queue-6.14/drm-atomic-clarify-the-rules-around-drm_atomic_state.patch new file mode 100644 index 0000000000..670ba38363 --- /dev/null +++ b/queue-6.14/drm-atomic-clarify-the-rules-around-drm_atomic_state.patch @@ -0,0 +1,90 @@ +From f12960ca80edca8d16feb03b0a730bca0e5d9fe8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 8 Jan 2025 18:24:16 +0100 +Subject: drm/atomic: clarify the rules around drm_atomic_state->allow_modeset +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Simona Vetter + +[ Upstream commit c5e3306a424b52e38ad2c28c7f3399fcd03e383d ] + +msm is automagically upgrading normal commits to full modesets, and +that's a big no-no: + +- for one this results in full on->off->on transitions on all these + crtc, at least if you're using the usual helpers. Which seems to be + the case, and is breaking uapi + +- further even if the ctm change itself would not result in flicker, + this can hide modesets for other reasons. Which again breaks the + uapi + +v2: I forgot the case of adding unrelated crtc state. Add that case +and link to the existing kerneldoc explainers. This has come up in an +irc discussion with Manasi and Ville about intel's bigjoiner mode. +Also cc everyone involved in the msm irc discussion, more people +joined after I sent out v1. + +v3: Wording polish from Pekka and Thomas + +Acked-by: Pekka Paalanen +Acked-by: Dmitry Baryshkov +Cc: Maarten Lankhorst +Cc: Maxime Ripard +Cc: Thomas Zimmermann +Cc: David Airlie +Cc: Daniel Vetter +Cc: Pekka Paalanen +Cc: Rob Clark +Cc: Simon Ser +Cc: Manasi Navare +Cc: Ville Syrjälä +Cc: Abhinav Kumar +Cc: Dmitry Baryshkov +Signed-off-by: Simona Vetter +Signed-off-by: Simona Vetter +Link: https://patchwork.freedesktop.org/patch/msgid/20250108172417.160831-1-simona.vetter@ffwll.ch +Signed-off-by: Sasha Levin +--- + include/drm/drm_atomic.h | 23 +++++++++++++++++++++-- + 1 file changed, 21 insertions(+), 2 deletions(-) + +diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h +index 31ca88deb10d2..1ded9a8d4e84d 100644 +--- a/include/drm/drm_atomic.h ++++ b/include/drm/drm_atomic.h +@@ -376,8 +376,27 @@ struct drm_atomic_state { + * + * Allow full modeset. This is used by the ATOMIC IOCTL handler to + * implement the DRM_MODE_ATOMIC_ALLOW_MODESET flag. Drivers should +- * never consult this flag, instead looking at the output of +- * drm_atomic_crtc_needs_modeset(). ++ * generally not consult this flag, but instead look at the output of ++ * drm_atomic_crtc_needs_modeset(). The detailed rules are: ++ * ++ * - Drivers must not consult @allow_modeset in the atomic commit path. ++ * Use drm_atomic_crtc_needs_modeset() instead. ++ * ++ * - Drivers must consult @allow_modeset before adding unrelated struct ++ * drm_crtc_state to this commit by calling ++ * drm_atomic_get_crtc_state(). See also the warning in the ++ * documentation for that function. ++ * ++ * - Drivers must never change this flag, it is under the exclusive ++ * control of userspace. ++ * ++ * - Drivers may consult @allow_modeset in the atomic check path, if ++ * they have the choice between an optimal hardware configuration ++ * which requires a modeset, and a less optimal configuration which ++ * can be committed without a modeset. An example would be suboptimal ++ * scanout FIFO allocation resulting in increased idle power ++ * consumption. This allows userspace to avoid flickering and delays ++ * for the normal composition loop at reasonable cost. + */ + bool allow_modeset : 1; + /** +-- +2.39.5 + diff --git a/queue-6.14/drm-bridge-adv7511-fill-stream-capabilities.patch b/queue-6.14/drm-bridge-adv7511-fill-stream-capabilities.patch new file mode 100644 index 0000000000..0556dba757 --- /dev/null +++ b/queue-6.14/drm-bridge-adv7511-fill-stream-capabilities.patch @@ -0,0 +1,39 @@ +From 67530350b444b0eaa136cb251796dca5b33b2441 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 8 Jan 2025 18:03:54 +0100 +Subject: drm: bridge: adv7511: fill stream capabilities + +From: Olivier Moysan + +[ Upstream commit c852646f12d4cd5b4f19eeec2976c5d98c0382f8 ] + +Set no_i2s_capture and no_spdif_capture flags in hdmi_codec_pdata structure +to report that the ADV7511 HDMI bridge does not support i2s or spdif audio +capture. + +Signed-off-by: Olivier Moysan +Reviewed-by: Dmitry Baryshkov +Link: https://patchwork.freedesktop.org/patch/msgid/20250108170356.413063-2-olivier.moysan@foss.st.com +Signed-off-by: Dmitry Baryshkov +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/bridge/adv7511/adv7511_audio.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511_audio.c b/drivers/gpu/drm/bridge/adv7511/adv7511_audio.c +index 657bc3dd18dff..98030500a978a 100644 +--- a/drivers/gpu/drm/bridge/adv7511/adv7511_audio.c ++++ b/drivers/gpu/drm/bridge/adv7511/adv7511_audio.c +@@ -245,7 +245,9 @@ static const struct hdmi_codec_pdata codec_data = { + .ops = &adv7511_codec_ops, + .max_i2s_channels = 2, + .i2s = 1, ++ .no_i2s_capture = 1, + .spdif = 1, ++ .no_spdif_capture = 1, + }; + + int adv7511_audio_init(struct device *dev, struct adv7511 *adv7511) +-- +2.39.5 + diff --git a/queue-6.14/drm-buddy-fix-issue-that-force_merge-cannot-free-all.patch b/queue-6.14/drm-buddy-fix-issue-that-force_merge-cannot-free-all.patch new file mode 100644 index 0000000000..736eb0ce47 --- /dev/null +++ b/queue-6.14/drm-buddy-fix-issue-that-force_merge-cannot-free-all.patch @@ -0,0 +1,54 @@ +From 9a56e6e6ee79461fa282390635ba670309395d43 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 26 Dec 2024 12:31:15 +0530 +Subject: drm/buddy: fix issue that force_merge cannot free all roots + +From: Lin.Cao + +[ Upstream commit 467dce3817bd2b62ccd6fcfd7aae76f242ac907e ] + +If buddy manager have more than one roots and each root have sub-block +need to be free. When drm_buddy_fini called, the first loop of +force_merge will merge and free all of the sub block of first root, +which offset is 0x0 and size is biggest(more than have of the mm size). +In subsequent force_merge rounds, if we use 0 as start and use remaining +mm size as end, the block of other roots will be skipped in +__force_merge function. It will cause the other roots can not be freed. + +Solution: use roots' offset as the start could fix this issue. + +Signed-off-by: Lin.Cao +Signed-off-by: Arunpravin Paneer Selvam +Reviewed-by: Matthew Auld +Link: https://patchwork.freedesktop.org/patch/msgid/20241226070116.309290-1-Arunpravin.PaneerSelvam@amd.com +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/drm_buddy.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/drivers/gpu/drm/drm_buddy.c b/drivers/gpu/drm/drm_buddy.c +index 103c185bb1c8a..ca42e6081d27c 100644 +--- a/drivers/gpu/drm/drm_buddy.c ++++ b/drivers/gpu/drm/drm_buddy.c +@@ -324,7 +324,7 @@ EXPORT_SYMBOL(drm_buddy_init); + */ + void drm_buddy_fini(struct drm_buddy *mm) + { +- u64 root_size, size; ++ u64 root_size, size, start; + unsigned int order; + int i; + +@@ -332,7 +332,8 @@ void drm_buddy_fini(struct drm_buddy *mm) + + for (i = 0; i < mm->n_roots; ++i) { + order = ilog2(size) - ilog2(mm->chunk_size); +- __force_merge(mm, 0, size, order); ++ start = drm_buddy_block_offset(mm->roots[i]); ++ __force_merge(mm, start, start + size, order); + + WARN_ON(!drm_buddy_block_is_free(mm->roots[i])); + drm_block_free(mm, mm->roots[i]); +-- +2.39.5 + diff --git a/queue-6.14/drm-gem-internally-test-import_attach-for-imported-o.patch b/queue-6.14/drm-gem-internally-test-import_attach-for-imported-o.patch new file mode 100644 index 0000000000..2f25f82893 --- /dev/null +++ b/queue-6.14/drm-gem-internally-test-import_attach-for-imported-o.patch @@ -0,0 +1,66 @@ +From 8ba4876ebde31841371db11d560790e4ebff00a9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 16 Apr 2025 08:57:45 +0200 +Subject: drm/gem: Internally test import_attach for imported objects +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Thomas Zimmermann + +[ Upstream commit 8260731ccad0451207b45844bb66eb161a209218 ] + +Test struct drm_gem_object.import_attach to detect imported objects. + +During object clenanup, the dma_buf field might be NULL. Testing it in +an object's free callback then incorrectly does a cleanup as for native +objects. Happens for calls to drm_mode_destroy_dumb_ioctl() that +clears the dma_buf field in drm_gem_object_exported_dma_buf_free(). + +v3: +- only test for import_attach (Boris) +v2: +- use import_attach.dmabuf instead of dma_buf (Christian) + +Signed-off-by: Thomas Zimmermann +Fixes: b57aa47d39e9 ("drm/gem: Test for imported GEM buffers with helper") +Reported-by: Andy Yan +Closes: https://lore.kernel.org/dri-devel/38d09d34.4354.196379aa560.Coremail.andyshrk@163.com/ +Tested-by: Andy Yan +Cc: Thomas Zimmermann +Cc: Anusha Srivatsa +Cc: Christian König +Cc: Maarten Lankhorst +Cc: Maxime Ripard +Cc: David Airlie +Cc: Simona Vetter +Cc: Sumit Semwal +Cc: "Christian König" +Cc: dri-devel@lists.freedesktop.org +Cc: linux-media@vger.kernel.org +Cc: linaro-mm-sig@lists.linaro.org +Reviewed-by: Boris Brezillon +Reviewed-by: Simona Vetter +Link: https://lore.kernel.org/r/20250416065820.26076-1-tzimmermann@suse.de +Signed-off-by: Sasha Levin +--- + include/drm/drm_gem.h | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/include/drm/drm_gem.h b/include/drm/drm_gem.h +index 2bf893eabb4b2..bcd54020d6ba5 100644 +--- a/include/drm/drm_gem.h ++++ b/include/drm/drm_gem.h +@@ -585,8 +585,7 @@ static inline bool drm_gem_object_is_shared_for_memory_stats(struct drm_gem_obje + */ + static inline bool drm_gem_is_imported(const struct drm_gem_object *obj) + { +- /* The dma-buf's priv field points to the original GEM object. */ +- return obj->dma_buf && (obj->dma_buf->priv != obj); ++ return !!obj->import_attach; + } + + #ifdef CONFIG_LOCKDEP +-- +2.39.5 + diff --git a/queue-6.14/drm-gem-test-for-imported-gem-buffers-with-helper.patch b/queue-6.14/drm-gem-test-for-imported-gem-buffers-with-helper.patch new file mode 100644 index 0000000000..e47d5ee953 --- /dev/null +++ b/queue-6.14/drm-gem-test-for-imported-gem-buffers-with-helper.patch @@ -0,0 +1,88 @@ +From 9da09a08236b463703d0fb65495027a3a1cd0c1d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 26 Feb 2025 18:03:04 +0100 +Subject: drm/gem: Test for imported GEM buffers with helper +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Thomas Zimmermann + +[ Upstream commit b57aa47d39e94dc47403a745e2024664e544078c ] + +Add drm_gem_is_imported() that tests if a GEM object's buffer has +been imported. Update the GEM code accordingly. + +GEM code usually tests for imports if import_attach has been set +in struct drm_gem_object. But attaching a dma-buf on import requires +a DMA-capable importer device, which is not the case for many serial +busses like USB or I2C. The new helper tests if a GEM object's dma-buf +has been created from the GEM object. + +Signed-off-by: Thomas Zimmermann +Reviewed-by: Anusha Srivatsa +Reviewed-by: Christian König +Link: https://patchwork.freedesktop.org/patch/msgid/20250226172457.217725-2-tzimmermann@suse.de +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/drm_gem.c | 4 ++-- + include/drm/drm_gem.h | 14 ++++++++++++++ + 2 files changed, 16 insertions(+), 2 deletions(-) + +diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c +index ee811764c3df4..c6240bab3fa55 100644 +--- a/drivers/gpu/drm/drm_gem.c ++++ b/drivers/gpu/drm/drm_gem.c +@@ -348,7 +348,7 @@ int drm_gem_dumb_map_offset(struct drm_file *file, struct drm_device *dev, + return -ENOENT; + + /* Don't allow imported objects to be mapped */ +- if (obj->import_attach) { ++ if (drm_gem_is_imported(obj)) { + ret = -EINVAL; + goto out; + } +@@ -1178,7 +1178,7 @@ void drm_gem_print_info(struct drm_printer *p, unsigned int indent, + drm_vma_node_start(&obj->vma_node)); + drm_printf_indent(p, indent, "size=%zu\n", obj->size); + drm_printf_indent(p, indent, "imported=%s\n", +- str_yes_no(obj->import_attach)); ++ str_yes_no(drm_gem_is_imported(obj))); + + if (obj->funcs->print_info) + obj->funcs->print_info(p, indent, obj); +diff --git a/include/drm/drm_gem.h b/include/drm/drm_gem.h +index fdae947682cd0..2bf893eabb4b2 100644 +--- a/include/drm/drm_gem.h ++++ b/include/drm/drm_gem.h +@@ -35,6 +35,7 @@ + */ + + #include ++#include + #include + #include + #include +@@ -575,6 +576,19 @@ static inline bool drm_gem_object_is_shared_for_memory_stats(struct drm_gem_obje + return (obj->handle_count > 1) || obj->dma_buf; + } + ++/** ++ * drm_gem_is_imported() - Tests if GEM object's buffer has been imported ++ * @obj: the GEM object ++ * ++ * Returns: ++ * True if the GEM object's buffer has been imported, false otherwise ++ */ ++static inline bool drm_gem_is_imported(const struct drm_gem_object *obj) ++{ ++ /* The dma-buf's priv field points to the original GEM object. */ ++ return obj->dma_buf && (obj->dma_buf->priv != obj); ++} ++ + #ifdef CONFIG_LOCKDEP + /** + * drm_gem_gpuva_set_lock() - Set the lock protecting accesses to the gpuva list. +-- +2.39.5 + diff --git a/queue-6.14/drm-mediatek-mtk_dpi-add-checks-for-reg_h_fre_con-ex.patch b/queue-6.14/drm-mediatek-mtk_dpi-add-checks-for-reg_h_fre_con-ex.patch new file mode 100644 index 0000000000..6424156958 --- /dev/null +++ b/queue-6.14/drm-mediatek-mtk_dpi-add-checks-for-reg_h_fre_con-ex.patch @@ -0,0 +1,51 @@ +From 1720c79de16a5102e62e58abcda52055efd73de4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Feb 2025 16:47:58 +0100 +Subject: drm/mediatek: mtk_dpi: Add checks for reg_h_fre_con existence + +From: AngeloGioacchino Del Regno + +[ Upstream commit 8c9da7cd0bbcc90ab444454fecf535320456a312 ] + +In preparation for adding support for newer DPI instances which +do support direct-pin but do not have any H_FRE_CON register, +like the one found in MT8195 and MT8188, add a branch to check +if the reg_h_fre_con variable was declared in the mtk_dpi_conf +structure for the probed SoC DPI version. + +As a note, this is useful specifically only for cases in which +the support_direct_pin variable is true, so mt8195-dpintf is +not affected by any issue. + +Reviewed-by: CK Hu +Signed-off-by: AngeloGioacchino Del Regno +Link: https://patchwork.kernel.org/project/dri-devel/patch/20250217154836.108895-6-angelogioacchino.delregno@collabora.com/ +Signed-off-by: Chun-Kuang Hu +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/mediatek/mtk_dpi.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/drivers/gpu/drm/mediatek/mtk_dpi.c b/drivers/gpu/drm/mediatek/mtk_dpi.c +index a12ef24c77423..b7d90574df9a6 100644 +--- a/drivers/gpu/drm/mediatek/mtk_dpi.c ++++ b/drivers/gpu/drm/mediatek/mtk_dpi.c +@@ -410,12 +410,13 @@ static void mtk_dpi_config_swap_input(struct mtk_dpi *dpi, bool enable) + + static void mtk_dpi_config_2n_h_fre(struct mtk_dpi *dpi) + { +- mtk_dpi_mask(dpi, dpi->conf->reg_h_fre_con, H_FRE_2N, H_FRE_2N); ++ if (dpi->conf->reg_h_fre_con) ++ mtk_dpi_mask(dpi, dpi->conf->reg_h_fre_con, H_FRE_2N, H_FRE_2N); + } + + static void mtk_dpi_config_disable_edge(struct mtk_dpi *dpi) + { +- if (dpi->conf->edge_sel_en) ++ if (dpi->conf->edge_sel_en && dpi->conf->reg_h_fre_con) + mtk_dpi_mask(dpi, dpi->conf->reg_h_fre_con, 0, EDGE_SEL_EN); + } + +-- +2.39.5 + diff --git a/queue-6.14/drm-msm-dpu-set-possible-clones-for-all-encoders.patch b/queue-6.14/drm-msm-dpu-set-possible-clones-for-all-encoders.patch new file mode 100644 index 0000000000..b26da35949 --- /dev/null +++ b/queue-6.14/drm-msm-dpu-set-possible-clones-for-all-encoders.patch @@ -0,0 +1,110 @@ +From e3e634883e3792b22e08a9993c3dc792120ac468 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 14 Feb 2025 16:14:37 -0800 +Subject: drm/msm/dpu: Set possible clones for all encoders + +From: Jessica Zhang + +[ Upstream commit e8cd8224a30798b65e05b26de284e1702b22ba5e ] + +Set writeback encoders as possible clones for DSI encoders and vice +versa. + +Reviewed-by: Dmitry Baryshkov +Reviewed-by: Abhinav Kumar +Signed-off-by: Jessica Zhang +Patchwork: https://patchwork.freedesktop.org/patch/637498/ +Link: https://lore.kernel.org/r/20250214-concurrent-wb-v6-14-a44c293cf422@quicinc.com +Signed-off-by: Dmitry Baryshkov +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 32 +++++++++++++++++++++ + drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h | 2 ++ + drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 7 +++-- + 3 files changed, 39 insertions(+), 2 deletions(-) + +diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +index 7b56da24711e4..eca9c7d4ec6f5 100644 +--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c ++++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +@@ -2539,6 +2539,38 @@ static int dpu_encoder_virt_add_phys_encs( + return 0; + } + ++/** ++ * dpu_encoder_get_clones - Calculate the possible_clones for DPU encoder ++ * @drm_enc: DRM encoder pointer ++ * Returns: possible_clones mask ++ */ ++uint32_t dpu_encoder_get_clones(struct drm_encoder *drm_enc) ++{ ++ struct drm_encoder *curr; ++ int type = drm_enc->encoder_type; ++ uint32_t clone_mask = drm_encoder_mask(drm_enc); ++ ++ /* ++ * Set writeback as possible clones of real-time DSI encoders and vice ++ * versa ++ * ++ * Writeback encoders can't be clones of each other and DSI ++ * encoders can't be clones of each other. ++ * ++ * TODO: Add DP encoders as valid possible clones for writeback encoders ++ * (and vice versa) once concurrent writeback has been validated for DP ++ */ ++ drm_for_each_encoder(curr, drm_enc->dev) { ++ if ((type == DRM_MODE_ENCODER_VIRTUAL && ++ curr->encoder_type == DRM_MODE_ENCODER_DSI) || ++ (type == DRM_MODE_ENCODER_DSI && ++ curr->encoder_type == DRM_MODE_ENCODER_VIRTUAL)) ++ clone_mask |= drm_encoder_mask(curr); ++ } ++ ++ return clone_mask; ++} ++ + static int dpu_encoder_setup_display(struct dpu_encoder_virt *dpu_enc, + struct dpu_kms *dpu_kms, + struct msm_display_info *disp_info) +diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h +index da133ee4701a3..751be231ee7b1 100644 +--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h ++++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h +@@ -60,6 +60,8 @@ enum dpu_intf_mode dpu_encoder_get_intf_mode(struct drm_encoder *encoder); + + void dpu_encoder_virt_runtime_resume(struct drm_encoder *encoder); + ++uint32_t dpu_encoder_get_clones(struct drm_encoder *drm_enc); ++ + struct drm_encoder *dpu_encoder_init(struct drm_device *dev, + int drm_enc_mode, + struct msm_display_info *disp_info); +diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c +index 8741dc6fc8ddc..b8f4ebba8ac28 100644 +--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c ++++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c +@@ -2,7 +2,7 @@ + /* + * Copyright (C) 2013 Red Hat + * Copyright (c) 2014-2018, The Linux Foundation. All rights reserved. +- * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. ++ * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. + * + * Author: Rob Clark + */ +@@ -834,8 +834,11 @@ static int _dpu_kms_drm_obj_init(struct dpu_kms *dpu_kms) + return ret; + + num_encoders = 0; +- drm_for_each_encoder(encoder, dev) ++ drm_for_each_encoder(encoder, dev) { + num_encoders++; ++ if (catalog->cwb_count > 0) ++ encoder->possible_clones = dpu_encoder_get_clones(encoder); ++ } + + max_crtc_count = min(catalog->mixer_count, num_encoders); + +-- +2.39.5 + diff --git a/queue-6.14/drm-nouveau-fix-the-broken-marco-gsp_msg_max_size.patch b/queue-6.14/drm-nouveau-fix-the-broken-marco-gsp_msg_max_size.patch new file mode 100644 index 0000000000..693b65ff71 --- /dev/null +++ b/queue-6.14/drm-nouveau-fix-the-broken-marco-gsp_msg_max_size.patch @@ -0,0 +1,39 @@ +From f6d17b34fb6686e339e324ccc0c5844cdf8473ed Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 24 Jan 2025 10:29:50 -0800 +Subject: drm/nouveau: fix the broken marco GSP_MSG_MAX_SIZE + +From: Zhi Wang + +[ Upstream commit bbae6680cfe38b033250b483722e60ccd865976f ] + +The macro GSP_MSG_MAX_SIZE refers to another macro that doesn't exist. +It represents the max GSP message element size. + +Fix the broken marco so it can be used to replace some magic numbers in +the code. + +Signed-off-by: Zhi Wang +Signed-off-by: Danilo Krummrich +Link: https://patchwork.freedesktop.org/patch/msgid/20250124182958.2040494-8-zhiw@nvidia.com +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c +index 58502102926b6..bb86b6d4ca49e 100644 +--- a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c ++++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c +@@ -61,7 +61,7 @@ + extern struct dentry *nouveau_debugfs_root; + + #define GSP_MSG_MIN_SIZE GSP_PAGE_SIZE +-#define GSP_MSG_MAX_SIZE GSP_PAGE_MIN_SIZE * 16 ++#define GSP_MSG_MAX_SIZE (GSP_MSG_MIN_SIZE * 16) + + struct r535_gsp_msg { + u8 auth_tag_buffer[16]; +-- +2.39.5 + diff --git a/queue-6.14/drm-panel-edp-add-starry-116khd024006.patch b/queue-6.14/drm-panel-edp-add-starry-116khd024006.patch new file mode 100644 index 0000000000..07bd1d8581 --- /dev/null +++ b/queue-6.14/drm-panel-edp-add-starry-116khd024006.patch @@ -0,0 +1,57 @@ +From e8c0ec13f899244b88ce77b10dc71b3d156c056d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 9 Jan 2025 14:28:53 -0800 +Subject: drm/panel-edp: Add Starry 116KHD024006 + +From: Douglas Anderson + +[ Upstream commit 749b5b279e5636cdcef51e15d67b77162cca6caa ] + +We have a few reports of sc7180-trogdor-pompom devices that have a +panel in them that IDs as STA 0x0004 and has the following raw EDID: + + 00 ff ff ff ff ff ff 00 4e 81 04 00 00 00 00 00 + 10 20 01 04 a5 1a 0e 78 0a dc dd 96 5b 5b 91 28 + 1f 52 54 00 00 00 01 01 01 01 01 01 01 01 01 01 + 01 01 01 01 01 01 8e 1c 56 a0 50 00 1e 30 28 20 + 55 00 00 90 10 00 00 18 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 fe + 00 31 31 36 4b 48 44 30 32 34 30 30 36 0a 00 e6 + +We've been unable to locate a datasheet for this panel and our partner +has not been responsive, but all Starry eDP datasheets that we can +find agree on the same timing (delay_100_500_e200) so it should be +safe to use that here instead of the super conservative timings. We'll +still go a little extra conservative and allow `hpd_absent` of 200 +instead of 100 because that won't add any real-world delay in most +cases. + +We'll associate the string from the EDID ("116KHD024006") with this +panel. Given that the ID is the suspicious value of 0x0004 it seems +likely that Starry doesn't always update their IDs but the string will +still work to differentiate if we ever need to in the future. + +Reviewed-by: Neil Armstrong +Signed-off-by: Douglas Anderson +Link: https://patchwork.freedesktop.org/patch/msgid/20250109142853.1.Ibcc3009933fd19507cc9c713ad0c99c7a9e4fe17@changeid +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/panel/panel-edp.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/gpu/drm/panel/panel-edp.c b/drivers/gpu/drm/panel/panel-edp.c +index f8511fe5fb0d6..b0315d3ba00a5 100644 +--- a/drivers/gpu/drm/panel/panel-edp.c ++++ b/drivers/gpu/drm/panel/panel-edp.c +@@ -1993,6 +1993,7 @@ static const struct edp_panel_entry edp_panels[] = { + EDP_PANEL_ENTRY('S', 'H', 'P', 0x154c, &delay_200_500_p2e100, "LQ116M1JW10"), + EDP_PANEL_ENTRY('S', 'H', 'P', 0x1593, &delay_200_500_p2e100, "LQ134N1"), + ++ EDP_PANEL_ENTRY('S', 'T', 'A', 0x0004, &delay_200_500_e200, "116KHD024006"), + EDP_PANEL_ENTRY('S', 'T', 'A', 0x0100, &delay_100_500_e200, "2081116HHD028001-51D"), + + { /* sentinal */ } +-- +2.39.5 + diff --git a/queue-6.14/drm-rockchip-vop2-add-uv-swap-for-cluster-window.patch b/queue-6.14/drm-rockchip-vop2-add-uv-swap-for-cluster-window.patch new file mode 100644 index 0000000000..aa65f7c373 --- /dev/null +++ b/queue-6.14/drm-rockchip-vop2-add-uv-swap-for-cluster-window.patch @@ -0,0 +1,46 @@ +From 1c4e2757ae99c766e44295d146bef560546025c5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 3 Mar 2025 11:44:17 +0800 +Subject: drm/rockchip: vop2: Add uv swap for cluster window + +From: Andy Yan + +[ Upstream commit e7aae9f6d762139f8d2b86db03793ae0ab3dd802 ] + +The Cluster windows of upcoming VOP on rk3576 also support +linear YUV support, we need to set uv swap bit for it. + +As the VOP2_WIN_UV_SWA register defined on rk3568/rk3588 is +0xffffffff, so this register will not be touched on these +two platforms. + +Signed-off-by: Andy Yan +Tested-by: Michael Riesch # on RK3568 +Tested-by: Detlev Casanova +Signed-off-by: Heiko Stuebner +Link: https://patchwork.freedesktop.org/patch/msgid/20250303034436.192400-4-andyshrk@163.com +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/rockchip/rockchip_drm_vop2.c | 6 ++---- + 1 file changed, 2 insertions(+), 4 deletions(-) + +diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c +index 17a98845fd31b..64029237358d8 100644 +--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c ++++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c +@@ -1547,10 +1547,8 @@ static void vop2_plane_atomic_update(struct drm_plane *plane, + + rb_swap = vop2_win_rb_swap(fb->format->format); + vop2_win_write(win, VOP2_WIN_RB_SWAP, rb_swap); +- if (!vop2_cluster_window(win)) { +- uv_swap = vop2_win_uv_swap(fb->format->format); +- vop2_win_write(win, VOP2_WIN_UV_SWAP, uv_swap); +- } ++ uv_swap = vop2_win_uv_swap(fb->format->format); ++ vop2_win_write(win, VOP2_WIN_UV_SWAP, uv_swap); + + if (fb->format->is_yuv) { + vop2_win_write(win, VOP2_WIN_UV_VIR, DIV_ROUND_UP(fb->pitches[1], 4)); +-- +2.39.5 + diff --git a/queue-6.14/drm-rockchip-vop2-improve-display-modes-handling-on-.patch b/queue-6.14/drm-rockchip-vop2-improve-display-modes-handling-on-.patch new file mode 100644 index 0000000000..1c94ec104a --- /dev/null +++ b/queue-6.14/drm-rockchip-vop2-improve-display-modes-handling-on-.patch @@ -0,0 +1,112 @@ +From d73375026d9619615d48de66bb5f59de5a4ab50b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 4 Feb 2025 14:40:06 +0200 +Subject: drm/rockchip: vop2: Improve display modes handling on RK3588 HDMI0 + +From: Cristian Ciocaltea + +[ Upstream commit 2c1268e7aad0819f38e56134bbc2095fd95fde1b ] + +The RK3588 specific implementation is currently quite limited in terms +of handling the full range of display modes supported by the connected +screens, e.g. 2560x1440@75Hz, 2048x1152@60Hz, 1024x768@60Hz are just a +few of them. + +Additionally, it doesn't cope well with non-integer refresh rates like +59.94, 29.97, 23.98, etc. + +Make use of HDMI0 PHY PLL as a more accurate DCLK source to handle +all display modes up to 4K@60Hz. + +Tested-by: FUKAUMI Naoki +Signed-off-by: Cristian Ciocaltea +Signed-off-by: Heiko Stuebner +Link: https://patchwork.freedesktop.org/patch/msgid/20250204-vop2-hdmi0-disp-modes-v3-3-d71c6a196e58@collabora.com +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/rockchip/rockchip_drm_vop2.c | 34 ++++++++++++++++++++ + 1 file changed, 34 insertions(+) + +diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c +index 64029237358d8..bcbd498823928 100644 +--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c ++++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c +@@ -159,6 +159,7 @@ struct vop2_video_port { + struct drm_crtc crtc; + struct vop2 *vop2; + struct clk *dclk; ++ struct clk *dclk_src; + unsigned int id; + const struct vop2_video_port_data *data; + +@@ -214,6 +215,7 @@ struct vop2 { + struct clk *hclk; + struct clk *aclk; + struct clk *pclk; ++ struct clk *pll_hdmiphy0; + + /* optional internal rgb encoder */ + struct rockchip_rgb *rgb; +@@ -222,6 +224,8 @@ struct vop2 { + struct vop2_win win[]; + }; + ++#define VOP2_MAX_DCLK_RATE 600000000 ++ + #define vop2_output_if_is_hdmi(x) ((x) == ROCKCHIP_VOP2_EP_HDMI0 || \ + (x) == ROCKCHIP_VOP2_EP_HDMI1) + +@@ -1155,6 +1159,9 @@ static void vop2_crtc_atomic_disable(struct drm_crtc *crtc, + + vop2_crtc_disable_irq(vp, VP_INT_DSP_HOLD_VALID); + ++ if (vp->dclk_src) ++ clk_set_parent(vp->dclk, vp->dclk_src); ++ + clk_disable_unprepare(vp->dclk); + + vop2->enable_count--; +@@ -2257,6 +2264,27 @@ static void vop2_crtc_atomic_enable(struct drm_crtc *crtc, + + vop2_vp_write(vp, RK3568_VP_MIPI_CTRL, 0); + ++ /* ++ * Switch to HDMI PHY PLL as DCLK source for display modes up ++ * to 4K@60Hz, if available, otherwise keep using the system CRU. ++ */ ++ if (vop2->pll_hdmiphy0 && clock <= VOP2_MAX_DCLK_RATE) { ++ drm_for_each_encoder_mask(encoder, crtc->dev, crtc_state->encoder_mask) { ++ struct rockchip_encoder *rkencoder = to_rockchip_encoder(encoder); ++ ++ if (rkencoder->crtc_endpoint_id == ROCKCHIP_VOP2_EP_HDMI0) { ++ if (!vp->dclk_src) ++ vp->dclk_src = clk_get_parent(vp->dclk); ++ ++ ret = clk_set_parent(vp->dclk, vop2->pll_hdmiphy0); ++ if (ret < 0) ++ drm_warn(vop2->drm, ++ "Could not switch to HDMI0 PHY PLL: %d\n", ret); ++ break; ++ } ++ } ++ } ++ + clk_set_rate(vp->dclk, clock); + + vop2_post_config(crtc); +@@ -3697,6 +3725,12 @@ static int vop2_bind(struct device *dev, struct device *master, void *data) + return PTR_ERR(vop2->pclk); + } + ++ vop2->pll_hdmiphy0 = devm_clk_get_optional(vop2->dev, "pll_hdmiphy0"); ++ if (IS_ERR(vop2->pll_hdmiphy0)) { ++ drm_err(vop2->drm, "failed to get pll_hdmiphy0\n"); ++ return PTR_ERR(vop2->pll_hdmiphy0); ++ } ++ + vop2->irq = platform_get_irq(pdev, 0); + if (vop2->irq < 0) { + drm_err(vop2->drm, "cannot find irq for vop2\n"); +-- +2.39.5 + diff --git a/queue-6.14/drm-ttm-fix-the-warning-for-hit_low-and-evict_low.patch b/queue-6.14/drm-ttm-fix-the-warning-for-hit_low-and-evict_low.patch new file mode 100644 index 0000000000..684a64e63e --- /dev/null +++ b/queue-6.14/drm-ttm-fix-the-warning-for-hit_low-and-evict_low.patch @@ -0,0 +1,44 @@ +From d1b8526cf72128528457136dcc023c653ff6727a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 23 Apr 2025 09:54:42 +0530 +Subject: drm/ttm: fix the warning for hit_low and evict_low +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Sunil Khatri + +[ Upstream commit 76047483fe94414edf409dc498498abf346e22f1 ] + +fix the below warning messages: +ttm/ttm_bo.c:1098: warning: Function parameter or struct member 'hit_low' not described in 'ttm_bo_swapout_walk' +ttm/ttm_bo.c:1098: warning: Function parameter or struct member 'evict_low' not described in 'ttm_bo_swapout_walk' + +Cc: Maarten Lankhorst +Cc: Tvrtko Ursulin +Signed-off-by: Sunil Khatri +Reviewed-by: Maarten Lankhorst +Signed-off-by: Christian König +Link: https://lore.kernel.org/r/20250423042442.762108-1-sunil.khatri@amd.com +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/ttm/ttm_bo.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c +index ea5e498588573..72c675191a022 100644 +--- a/drivers/gpu/drm/ttm/ttm_bo.c ++++ b/drivers/gpu/drm/ttm/ttm_bo.c +@@ -1092,7 +1092,8 @@ struct ttm_bo_swapout_walk { + struct ttm_lru_walk walk; + /** @gfp_flags: The gfp flags to use for ttm_tt_swapout() */ + gfp_t gfp_flags; +- ++ /** @hit_low: Whether we should attempt to swap BO's with low watermark threshold */ ++ /** @evict_low: If we cannot swap a bo when @try_low is false (first pass) */ + bool hit_low, evict_low; + }; + +-- +2.39.5 + diff --git a/queue-6.14/drm-v3d-add-clock-handling.patch b/queue-6.14/drm-v3d-add-clock-handling.patch new file mode 100644 index 0000000000..ba4a0eacb2 --- /dev/null +++ b/queue-6.14/drm-v3d-add-clock-handling.patch @@ -0,0 +1,108 @@ +From 984dc4d11e5b7edb44b1b7677fb20d0552df9137 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 1 Feb 2025 13:50:46 +0100 +Subject: drm/v3d: Add clock handling +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Stefan Wahren + +[ Upstream commit 4dd40b5f9c3d89b67af0dbe059cf4a51aac6bf06 ] + +Since the initial commit 57692c94dcbe ("drm/v3d: Introduce a new DRM driver +for Broadcom V3D V3.x+") the struct v3d_dev reserved a pointer for +an optional V3D clock. But there wasn't any code, which fetched it. +So add the missing clock handling before accessing any V3D registers. + +Signed-off-by: Stefan Wahren +Reviewed-by: Maíra Canal +Signed-off-by: Maíra Canal +Link: https://patchwork.freedesktop.org/patch/msgid/20250201125046.33030-1-wahrenst@gmx.net +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/v3d/v3d_drv.c | 25 ++++++++++++++++++++----- + 1 file changed, 20 insertions(+), 5 deletions(-) + +diff --git a/drivers/gpu/drm/v3d/v3d_drv.c b/drivers/gpu/drm/v3d/v3d_drv.c +index 930737a9347b6..852015214e971 100644 +--- a/drivers/gpu/drm/v3d/v3d_drv.c ++++ b/drivers/gpu/drm/v3d/v3d_drv.c +@@ -295,11 +295,21 @@ static int v3d_platform_drm_probe(struct platform_device *pdev) + if (ret) + return ret; + ++ v3d->clk = devm_clk_get_optional(dev, NULL); ++ if (IS_ERR(v3d->clk)) ++ return dev_err_probe(dev, PTR_ERR(v3d->clk), "Failed to get V3D clock\n"); ++ ++ ret = clk_prepare_enable(v3d->clk); ++ if (ret) { ++ dev_err(&pdev->dev, "Couldn't enable the V3D clock\n"); ++ return ret; ++ } ++ + mmu_debug = V3D_READ(V3D_MMU_DEBUG_INFO); + mask = DMA_BIT_MASK(30 + V3D_GET_FIELD(mmu_debug, V3D_MMU_PA_WIDTH)); + ret = dma_set_mask_and_coherent(dev, mask); + if (ret) +- return ret; ++ goto clk_disable; + + v3d->va_width = 30 + V3D_GET_FIELD(mmu_debug, V3D_MMU_VA_WIDTH); + +@@ -319,28 +329,29 @@ static int v3d_platform_drm_probe(struct platform_device *pdev) + ret = PTR_ERR(v3d->reset); + + if (ret == -EPROBE_DEFER) +- return ret; ++ goto clk_disable; + + v3d->reset = NULL; + ret = map_regs(v3d, &v3d->bridge_regs, "bridge"); + if (ret) { + dev_err(dev, + "Failed to get reset control or bridge regs\n"); +- return ret; ++ goto clk_disable; + } + } + + if (v3d->ver < 41) { + ret = map_regs(v3d, &v3d->gca_regs, "gca"); + if (ret) +- return ret; ++ goto clk_disable; + } + + v3d->mmu_scratch = dma_alloc_wc(dev, 4096, &v3d->mmu_scratch_paddr, + GFP_KERNEL | __GFP_NOWARN | __GFP_ZERO); + if (!v3d->mmu_scratch) { + dev_err(dev, "Failed to allocate MMU scratch page\n"); +- return -ENOMEM; ++ ret = -ENOMEM; ++ goto clk_disable; + } + + ret = v3d_gem_init(drm); +@@ -369,6 +380,8 @@ static int v3d_platform_drm_probe(struct platform_device *pdev) + v3d_gem_destroy(drm); + dma_free: + dma_free_wc(dev, 4096, v3d->mmu_scratch, v3d->mmu_scratch_paddr); ++clk_disable: ++ clk_disable_unprepare(v3d->clk); + return ret; + } + +@@ -386,6 +399,8 @@ static void v3d_platform_drm_remove(struct platform_device *pdev) + + dma_free_wc(v3d->drm.dev, 4096, v3d->mmu_scratch, + v3d->mmu_scratch_paddr); ++ ++ clk_disable_unprepare(v3d->clk); + } + + static struct platform_driver v3d_platform_driver = { +-- +2.39.5 + diff --git a/queue-6.14/drm-xe-add-locks-in-gtidle-code.patch b/queue-6.14/drm-xe-add-locks-in-gtidle-code.patch new file mode 100644 index 0000000000..ef6fd5204c --- /dev/null +++ b/queue-6.14/drm-xe-add-locks-in-gtidle-code.patch @@ -0,0 +1,123 @@ +From 3019c98b6332023de349e0f0e0a3debfe78ceb7a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 10 Jan 2025 09:33:09 -0800 +Subject: drm/xe: Add locks in gtidle code + +From: Vinay Belgaumkar + +[ Upstream commit d160dc6f53914d729be7fcb7afbd0e9e6a3725b2 ] + +The update of the residency values needs to be protected by a lock to +avoid multiple entrypoints, for example when multiple userspace clients +read the sysfs file. Other in-kernel clients are going to be added to +sample these values, making the problem worse. Protect those updates +with a raw_spinlock so it can be called by future integration with perf +pmu. + +Suggested-by: Lucas De Marchi +Cc: Rodrigo Vivi +Cc: Lucas De Marchi +Signed-off-by: Vinay Belgaumkar +Reviewed-by: Lucas De Marchi +Link: https://patchwork.freedesktop.org/patch/msgid/20250110173308.2412232-2-lucas.demarchi@intel.com +Signed-off-by: Lucas De Marchi +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/xe/xe_gt_idle.c | 23 ++++++++++++++++++++--- + drivers/gpu/drm/xe/xe_gt_idle.h | 1 + + drivers/gpu/drm/xe/xe_gt_idle_types.h | 3 +++ + 3 files changed, 24 insertions(+), 3 deletions(-) + +diff --git a/drivers/gpu/drm/xe/xe_gt_idle.c b/drivers/gpu/drm/xe/xe_gt_idle.c +index ffd3ba7f66561..fbbace7b0b12a 100644 +--- a/drivers/gpu/drm/xe/xe_gt_idle.c ++++ b/drivers/gpu/drm/xe/xe_gt_idle.c +@@ -69,6 +69,8 @@ static u64 get_residency_ms(struct xe_gt_idle *gtidle, u64 cur_residency) + { + u64 delta, overflow_residency, prev_residency; + ++ lockdep_assert_held(>idle->lock); ++ + overflow_residency = BIT_ULL(32); + + /* +@@ -275,8 +277,21 @@ static ssize_t idle_status_show(struct device *dev, + + return sysfs_emit(buff, "%s\n", gt_idle_state_to_string(state)); + } +-static DEVICE_ATTR_RO(idle_status); + ++u64 xe_gt_idle_residency_msec(struct xe_gt_idle *gtidle) ++{ ++ struct xe_guc_pc *pc = gtidle_to_pc(gtidle); ++ u64 residency; ++ unsigned long flags; ++ ++ raw_spin_lock_irqsave(>idle->lock, flags); ++ residency = get_residency_ms(gtidle, gtidle->idle_residency(pc)); ++ raw_spin_unlock_irqrestore(>idle->lock, flags); ++ ++ return residency; ++} ++ ++static DEVICE_ATTR_RO(idle_status); + static ssize_t idle_residency_ms_show(struct device *dev, + struct device_attribute *attr, char *buff) + { +@@ -285,10 +300,10 @@ static ssize_t idle_residency_ms_show(struct device *dev, + u64 residency; + + xe_pm_runtime_get(pc_to_xe(pc)); +- residency = gtidle->idle_residency(pc); ++ residency = xe_gt_idle_residency_msec(gtidle); + xe_pm_runtime_put(pc_to_xe(pc)); + +- return sysfs_emit(buff, "%llu\n", get_residency_ms(gtidle, residency)); ++ return sysfs_emit(buff, "%llu\n", residency); + } + static DEVICE_ATTR_RO(idle_residency_ms); + +@@ -331,6 +346,8 @@ int xe_gt_idle_init(struct xe_gt_idle *gtidle) + if (!kobj) + return -ENOMEM; + ++ raw_spin_lock_init(>idle->lock); ++ + if (xe_gt_is_media_type(gt)) { + snprintf(gtidle->name, sizeof(gtidle->name), "gt%d-mc", gt->info.id); + gtidle->idle_residency = xe_guc_pc_mc6_residency; +diff --git a/drivers/gpu/drm/xe/xe_gt_idle.h b/drivers/gpu/drm/xe/xe_gt_idle.h +index 4455a6501cb07..591a01e181bcc 100644 +--- a/drivers/gpu/drm/xe/xe_gt_idle.h ++++ b/drivers/gpu/drm/xe/xe_gt_idle.h +@@ -17,5 +17,6 @@ void xe_gt_idle_disable_c6(struct xe_gt *gt); + void xe_gt_idle_enable_pg(struct xe_gt *gt); + void xe_gt_idle_disable_pg(struct xe_gt *gt); + int xe_gt_idle_pg_print(struct xe_gt *gt, struct drm_printer *p); ++u64 xe_gt_idle_residency_msec(struct xe_gt_idle *gtidle); + + #endif /* _XE_GT_IDLE_H_ */ +diff --git a/drivers/gpu/drm/xe/xe_gt_idle_types.h b/drivers/gpu/drm/xe/xe_gt_idle_types.h +index b8b297a3f8848..a3667c567f8a7 100644 +--- a/drivers/gpu/drm/xe/xe_gt_idle_types.h ++++ b/drivers/gpu/drm/xe/xe_gt_idle_types.h +@@ -6,6 +6,7 @@ + #ifndef _XE_GT_IDLE_SYSFS_TYPES_H_ + #define _XE_GT_IDLE_SYSFS_TYPES_H_ + ++#include + #include + + struct xe_guc_pc; +@@ -31,6 +32,8 @@ struct xe_gt_idle { + u64 cur_residency; + /** @prev_residency: previous residency counter */ + u64 prev_residency; ++ /** @lock: Lock protecting idle residency counters */ ++ raw_spinlock_t lock; + /** @idle_status: get the current idle state */ + enum xe_gt_idle_state (*idle_status)(struct xe_guc_pc *pc); + /** @idle_residency: get idle residency counter */ +-- +2.39.5 + diff --git a/queue-6.14/drm-xe-always-setup-gt-mmio-adjustment-data.patch b/queue-6.14/drm-xe-always-setup-gt-mmio-adjustment-data.patch new file mode 100644 index 0000000000..928ada7bdc --- /dev/null +++ b/queue-6.14/drm-xe-always-setup-gt-mmio-adjustment-data.patch @@ -0,0 +1,41 @@ +From be6f7a4ad38eef99c3969c840dc867a0eb90ecee Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 14 Nov 2024 18:59:54 +0100 +Subject: drm/xe: Always setup GT MMIO adjustment data + +From: Michal Wajdeczko + +[ Upstream commit bbd8429264baf8bc3c40cefda048560ae0eb7890 ] + +While we believed that xe_gt_mmio_init() will be called just once +per GT, this might not be a case due to some tweaks that need to +performed by the VF driver during early probe. To avoid leaving +any stale data in case of the re-run, reset the GT MMIO adjustment +data for the non-media GT case. + +Signed-off-by: Michal Wajdeczko +Cc: Matt Roper +Reviewed-by: Lucas De Marchi +Link: https://patchwork.freedesktop.org/patch/msgid/20241114175955.2299-2-michal.wajdeczko@intel.com +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/xe/xe_gt.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/gpu/drm/xe/xe_gt.c b/drivers/gpu/drm/xe/xe_gt.c +index 150dca2f91033..6b4b9eca2c384 100644 +--- a/drivers/gpu/drm/xe/xe_gt.c ++++ b/drivers/gpu/drm/xe/xe_gt.c +@@ -650,6 +650,9 @@ void xe_gt_mmio_init(struct xe_gt *gt) + if (gt->info.type == XE_GT_TYPE_MEDIA) { + gt->mmio.adj_offset = MEDIA_GT_GSI_OFFSET; + gt->mmio.adj_limit = MEDIA_GT_GSI_LENGTH; ++ } else { ++ gt->mmio.adj_offset = 0; ++ gt->mmio.adj_limit = 0; + } + + if (IS_SRIOV_VF(gt_to_xe(gt))) +-- +2.39.5 + diff --git a/queue-6.14/drm-xe-client-skip-show_run_ticks-if-unable-to-read-.patch b/queue-6.14/drm-xe-client-skip-show_run_ticks-if-unable-to-read-.patch new file mode 100644 index 0000000000..e70dc56c0e --- /dev/null +++ b/queue-6.14/drm-xe-client-skip-show_run_ticks-if-unable-to-read-.patch @@ -0,0 +1,51 @@ +From 9f679234267233be694e219459a04ed1fc5e6d0a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Feb 2025 20:16:44 +0100 +Subject: drm/xe/client: Skip show_run_ticks if unable to read timestamp +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Marcin Bernatowicz + +[ Upstream commit 94030a1d3283251778411cf74553607a65260f78 ] + +RING_TIMESTAMP registers are inaccessible in VF mode. +Without drm-total-cycles-*, other keys provide little value. +Skip all optional "run_ticks" keys in this case. + +Signed-off-by: Marcin Bernatowicz +Cc: Lucas De Marchi +Cc: Michal Wajdeczko +Cc: Michał Winiarski +Cc: Umesh Nerlige Ramappa +Reviewed-by: Satyanarayana K V P +Signed-off-by: Michal Wajdeczko +Link: https://patchwork.freedesktop.org/patch/msgid/20250205191644.2550879-3-marcin.bernatowicz@linux.intel.com +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/xe/xe_drm_client.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/drivers/gpu/drm/xe/xe_drm_client.c b/drivers/gpu/drm/xe/xe_drm_client.c +index 2d4874d2b9225..31f688e953d7b 100644 +--- a/drivers/gpu/drm/xe/xe_drm_client.c ++++ b/drivers/gpu/drm/xe/xe_drm_client.c +@@ -324,6 +324,14 @@ static void show_run_ticks(struct drm_printer *p, struct drm_file *file) + u64 gpu_timestamp; + unsigned int fw_ref; + ++ /* ++ * RING_TIMESTAMP registers are inaccessible in VF mode. ++ * Without drm-total-cycles-*, other keys provide little value. ++ * Show all or none of the optional "run_ticks" keys in this case. ++ */ ++ if (IS_SRIOV_VF(xe)) ++ return; ++ + /* + * Wait for any exec queue going away: their cycles will get updated on + * context switch out, so wait for that to happen +-- +2.39.5 + diff --git a/queue-6.14/drm-xe-debugfs-add-missing-xe_pm_runtime_put-in-wedg.patch b/queue-6.14/drm-xe-debugfs-add-missing-xe_pm_runtime_put-in-wedg.patch new file mode 100644 index 0000000000..4724bc6afb --- /dev/null +++ b/queue-6.14/drm-xe-debugfs-add-missing-xe_pm_runtime_put-in-wedg.patch @@ -0,0 +1,36 @@ +From 43c161088ef291ab95dcfaf9fbc46c4abd57b5a7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 13 Feb 2025 23:03:22 +0000 +Subject: drm/xe/debugfs: Add missing xe_pm_runtime_put in wedge_mode_set + +From: Shuicheng Lin + +[ Upstream commit b31e668d3111b100d16fd7db8db335328ce8c6d5 ] + +xe_pm_runtime_put is missed in the failure path. + +Cc: Rodrigo Vivi +Signed-off-by: Shuicheng Lin +Reviewed-by: Rodrigo Vivi +Link: https://patchwork.freedesktop.org/patch/msgid/20250213230322.1180621-1-shuicheng.lin@intel.com +Signed-off-by: Rodrigo Vivi +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/xe/xe_debugfs.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/gpu/drm/xe/xe_debugfs.c b/drivers/gpu/drm/xe/xe_debugfs.c +index 6bfdd3a9913fd..92e6fa8fe3a17 100644 +--- a/drivers/gpu/drm/xe/xe_debugfs.c ++++ b/drivers/gpu/drm/xe/xe_debugfs.c +@@ -175,6 +175,7 @@ static ssize_t wedged_mode_set(struct file *f, const char __user *ubuf, + ret = xe_guc_ads_scheduler_policy_toggle_reset(>->uc.guc.ads); + if (ret) { + xe_gt_err(gt, "Failed to update GuC ADS scheduler policy. GuC may still cause engine reset even with wedged_mode=2\n"); ++ xe_pm_runtime_put(xe); + return -EIO; + } + } +-- +2.39.5 + diff --git a/queue-6.14/drm-xe-debugfs-fixed-the-return-value-of-wedged_mode.patch b/queue-6.14/drm-xe-debugfs-fixed-the-return-value-of-wedged_mode.patch new file mode 100644 index 0000000000..543e91a38d --- /dev/null +++ b/queue-6.14/drm-xe-debugfs-fixed-the-return-value-of-wedged_mode.patch @@ -0,0 +1,51 @@ +From 556c72b0aab2eda53b0459c3920c8de92f3d9274 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 14 Feb 2025 06:36:15 +0800 +Subject: drm/xe/debugfs: fixed the return value of wedged_mode_set + +From: Xin Wang + +[ Upstream commit 6884d2051011f4db9e2f0b85709c79a8ced13bd6 ] + +It is generally expected that the write() function should return a +positive value indicating the number of bytes written or a negative +error code if an error occurs. Returning 0 is unusual and can lead +to unexpected behavior. + +When the user program writes the same value to wedged_mode twice in +a row, a lockup will occur, because the value expected to be +returned by the write() function inside the program should be equal +to the actual written value instead of 0. + +To reproduce the issue: +echo 1 > /sys/kernel/debug/dri/0/wedged_mode +echo 1 > /sys/kernel/debug/dri/0/wedged_mode <- lockup here + +Signed-off-by: Xin Wang +Cc: Rodrigo Vivi +Cc: Fei Yang +Cc: Shuicheng Lin +Reviewed-by: Rodrigo Vivi +Link: https://patchwork.freedesktop.org/patch/msgid/20250213223615.2327367-1-x.wang@intel.com +Signed-off-by: Rodrigo Vivi +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/xe/xe_debugfs.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/xe/xe_debugfs.c b/drivers/gpu/drm/xe/xe_debugfs.c +index 492b4877433f1..6bfdd3a9913fd 100644 +--- a/drivers/gpu/drm/xe/xe_debugfs.c ++++ b/drivers/gpu/drm/xe/xe_debugfs.c +@@ -166,7 +166,7 @@ static ssize_t wedged_mode_set(struct file *f, const char __user *ubuf, + return -EINVAL; + + if (xe->wedged.mode == wedged_mode) +- return 0; ++ return size; + + xe->wedged.mode = wedged_mode; + +-- +2.39.5 + diff --git a/queue-6.14/drm-xe-disambiguate-gmdid-based-ip-names.patch b/queue-6.14/drm-xe-disambiguate-gmdid-based-ip-names.patch new file mode 100644 index 0000000000..1f2eeea495 --- /dev/null +++ b/queue-6.14/drm-xe-disambiguate-gmdid-based-ip-names.patch @@ -0,0 +1,150 @@ +From c1e924ce8f93779c740a9b5e3ecaf04934048d06 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 21 Feb 2025 15:51:41 -0300 +Subject: drm/xe: Disambiguate GMDID-based IP names + +From: Gustavo Sousa + +[ Upstream commit 0695c746f55c875f4cf20bab92533a800a0fe4d6 ] + +The name of an IP is a function of its version. As such, given an IP +version, it should be clear to identify the name of that IP release. + +With the current code, we keep that mapping clear for pre-GMDID IPs, but +ambiguous for GMDID-based ones. That causes two types of inconveniences: + + 1. The end user, who might not have all the necessary mapping at hand, + might be confused when seeing different possible IP names in the + dmesg log. + + 2. It makes a developer who is not familiar with the "IP version" to + "Release name" need to resort to looking at the specs to understand + see what version maps to what. While the specs should be the + authority on the mapping, we should make our lives easier by + reflecting that mapping in the source code. + +Thus, since the IP name is tied to the version, let's remove the +ambiguity by using a "name" field in struct gmdid_map instead of +accumulating names in the descriptor instances. + +This does result in the code having IP name being defined in +different structs (gmdid_map, xe_graphics_desc, xe_media_desc), but that +will be resolved in upcoming changes. + +A side-effect of this change is that media_xe2 exactly matches +media_xelpmp now, so we just re-use the latter. + +v2: + - Drop media_xe2 and re-use media_xelpmp. (Matt) + +Reviewed-by: Matt Roper +Signed-off-by: Gustavo Sousa +Link: https://patchwork.freedesktop.org/patch/msgid/20250221-xe-unify-ip-descriptors-v2-2-5bc0c6d0c13f@intel.com +Signed-off-by: Matt Roper +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/xe/xe_pci.c | 36 +++++++++++-------------------- + drivers/gpu/drm/xe/xe_pci_types.h | 1 + + 2 files changed, 14 insertions(+), 23 deletions(-) + +diff --git a/drivers/gpu/drm/xe/xe_pci.c b/drivers/gpu/drm/xe/xe_pci.c +index 39be74848e447..9b8813a518d72 100644 +--- a/drivers/gpu/drm/xe/xe_pci.c ++++ b/drivers/gpu/drm/xe/xe_pci.c +@@ -150,7 +150,6 @@ static const struct xe_graphics_desc graphics_xehpc = { + }; + + static const struct xe_graphics_desc graphics_xelpg = { +- .name = "Xe_LPG", + .hw_engine_mask = + BIT(XE_HW_ENGINE_RCS0) | BIT(XE_HW_ENGINE_BCS0) | + BIT(XE_HW_ENGINE_CCS0), +@@ -174,8 +173,6 @@ static const struct xe_graphics_desc graphics_xelpg = { + GENMASK(XE_HW_ENGINE_CCS3, XE_HW_ENGINE_CCS0) + + static const struct xe_graphics_desc graphics_xe2 = { +- .name = "Xe2_LPG / Xe2_HPG / Xe3_LPG", +- + XE2_GFX_FEATURES, + }; + +@@ -200,15 +197,6 @@ static const struct xe_media_desc media_xehpm = { + }; + + static const struct xe_media_desc media_xelpmp = { +- .name = "Xe_LPM+", +- .hw_engine_mask = +- GENMASK(XE_HW_ENGINE_VCS7, XE_HW_ENGINE_VCS0) | +- GENMASK(XE_HW_ENGINE_VECS3, XE_HW_ENGINE_VECS0) | +- BIT(XE_HW_ENGINE_GSCCS0) +-}; +- +-static const struct xe_media_desc media_xe2 = { +- .name = "Xe2_LPM / Xe2_HPM / Xe3_LPM", + .hw_engine_mask = + GENMASK(XE_HW_ENGINE_VCS7, XE_HW_ENGINE_VCS0) | + GENMASK(XE_HW_ENGINE_VECS3, XE_HW_ENGINE_VECS0) | +@@ -357,21 +345,21 @@ __diag_pop(); + + /* Map of GMD_ID values to graphics IP */ + static const struct gmdid_map graphics_ip_map[] = { +- { 1270, &graphics_xelpg }, +- { 1271, &graphics_xelpg }, +- { 1274, &graphics_xelpg }, /* Xe_LPG+ */ +- { 2001, &graphics_xe2 }, +- { 2004, &graphics_xe2 }, +- { 3000, &graphics_xe2 }, +- { 3001, &graphics_xe2 }, ++ { 1270, "Xe_LPG", &graphics_xelpg }, ++ { 1271, "Xe_LPG", &graphics_xelpg }, ++ { 1274, "Xe_LPG+", &graphics_xelpg }, ++ { 2001, "Xe2_HPG", &graphics_xe2 }, ++ { 2004, "Xe2_LPG", &graphics_xe2 }, ++ { 3000, "Xe3_LPG", &graphics_xe2 }, ++ { 3001, "Xe3_LPG", &graphics_xe2 }, + }; + + /* Map of GMD_ID values to media IP */ + static const struct gmdid_map media_ip_map[] = { +- { 1300, &media_xelpmp }, +- { 1301, &media_xe2 }, +- { 2000, &media_xe2 }, +- { 3000, &media_xe2 }, ++ { 1300, "Xe_LPM+", &media_xelpmp }, ++ { 1301, "Xe2_HPM", &media_xelpmp }, ++ { 2000, "Xe2_LPM", &media_xelpmp }, ++ { 3000, "Xe3_LPM", &media_xelpmp }, + }; + + /* +@@ -566,6 +554,7 @@ static void handle_gmdid(struct xe_device *xe, + for (int i = 0; i < ARRAY_SIZE(graphics_ip_map); i++) { + if (ver == graphics_ip_map[i].ver) { + xe->info.graphics_verx100 = ver; ++ xe->info.graphics_name = graphics_ip_map[i].name; + *graphics = graphics_ip_map[i].ip; + + break; +@@ -586,6 +575,7 @@ static void handle_gmdid(struct xe_device *xe, + for (int i = 0; i < ARRAY_SIZE(media_ip_map); i++) { + if (ver == media_ip_map[i].ver) { + xe->info.media_verx100 = ver; ++ xe->info.media_name = media_ip_map[i].name; + *media = media_ip_map[i].ip; + + break; +diff --git a/drivers/gpu/drm/xe/xe_pci_types.h b/drivers/gpu/drm/xe/xe_pci_types.h +index 79b0f80376a4d..665b4447b2ebc 100644 +--- a/drivers/gpu/drm/xe/xe_pci_types.h ++++ b/drivers/gpu/drm/xe/xe_pci_types.h +@@ -44,6 +44,7 @@ struct xe_media_desc { + + struct gmdid_map { + unsigned int ver; ++ const char *name; + const void *ip; + }; + +-- +2.39.5 + diff --git a/queue-6.14/drm-xe-display-remove-hpd-cancel-work-sync-from-runt.patch b/queue-6.14/drm-xe-display-remove-hpd-cancel-work-sync-from-runt.patch new file mode 100644 index 0000000000..179e1e7e2f --- /dev/null +++ b/queue-6.14/drm-xe-display-remove-hpd-cancel-work-sync-from-runt.patch @@ -0,0 +1,39 @@ +From e736f29ea8d5e7a8b59f1b282fc42f3fbf7b45a8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 12 Feb 2025 14:24:47 -0500 +Subject: drm/xe/display: Remove hpd cancel work sync from runtime pm path + +From: Rodrigo Vivi + +[ Upstream commit 1ed591582b7b894d2f7e7ab5cef2e9b0b6fef12b ] + +This function will synchronously cancel and wait for many display +work queue items, which might try to take the runtime pm reference +causing a bad deadlock. So, remove it from the runtime_pm suspend patch. + +Reported-by: Imre Deak +Reviewed-by: Imre Deak +Link: https://patchwork.freedesktop.org/patch/msgid/20250212192447.402715-1-rodrigo.vivi@intel.com +Signed-off-by: Rodrigo Vivi +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/xe/display/xe_display.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/xe/display/xe_display.c b/drivers/gpu/drm/xe/display/xe_display.c +index b3921dbc52ff6..b735e30953cee 100644 +--- a/drivers/gpu/drm/xe/display/xe_display.c ++++ b/drivers/gpu/drm/xe/display/xe_display.c +@@ -346,7 +346,8 @@ static void __xe_display_pm_suspend(struct xe_device *xe, bool runtime) + + xe_display_flush_cleanup_work(xe); + +- intel_hpd_cancel_work(xe); ++ if (!runtime) ++ intel_hpd_cancel_work(xe); + + if (!runtime && has_display(xe)) { + intel_display_driver_suspend_access(display); +-- +2.39.5 + diff --git a/queue-6.14/drm-xe-do-not-attempt-to-bootstrap-vf-in-execlists-m.patch b/queue-6.14/drm-xe-do-not-attempt-to-bootstrap-vf-in-execlists-m.patch new file mode 100644 index 0000000000..1ed83499a2 --- /dev/null +++ b/queue-6.14/drm-xe-do-not-attempt-to-bootstrap-vf-in-execlists-m.patch @@ -0,0 +1,39 @@ +From 2b1d02d71533738f976b1903f9cec492672e17d9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 10 Dec 2024 09:31:11 +0100 +Subject: drm/xe: Do not attempt to bootstrap VF in execlists mode + +From: Maarten Lankhorst + +[ Upstream commit f3b59457808f61d88178b0afa67cbd017d7ce79e ] + +It was mentioned in a review that there is a possibility of choosing +to load the module with VF in execlists mode. + +Of course this doesn't work, just bomb out as hard as possible. + +Reviewed-by: Lucas De Marchi +Link: https://patchwork.freedesktop.org/patch/msgid/20241210083111.230484-12-dev@lankhorst.se +Signed-off-by: Maarten Lankhorst +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/xe/xe_gt_sriov_vf.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_vf.c b/drivers/gpu/drm/xe/xe_gt_sriov_vf.c +index 1c764f200b2a5..a439261bf4d72 100644 +--- a/drivers/gpu/drm/xe/xe_gt_sriov_vf.c ++++ b/drivers/gpu/drm/xe/xe_gt_sriov_vf.c +@@ -236,6 +236,9 @@ int xe_gt_sriov_vf_bootstrap(struct xe_gt *gt) + { + int err; + ++ if (!xe_device_uc_enabled(gt_to_xe(gt))) ++ return -ENODEV; ++ + err = vf_reset_guc_state(gt); + if (unlikely(err)) + return err; +-- +2.39.5 + diff --git a/queue-6.14/drm-xe-fix-pvc-rpe-and-rpa-information.patch b/queue-6.14/drm-xe-fix-pvc-rpe-and-rpa-information.patch new file mode 100644 index 0000000000..1139783204 --- /dev/null +++ b/queue-6.14/drm-xe-fix-pvc-rpe-and-rpa-information.patch @@ -0,0 +1,72 @@ +From 22987f7201f6aca444d016e314ea3705b31936a1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 9 Jan 2025 14:52:19 -0500 +Subject: drm/xe: Fix PVC RPe and RPa information + +From: Rodrigo Vivi + +[ Upstream commit 8a734b9359cfa1bdb805f5ca23e20bd99dd18a0a ] + +A simple lazy buggy copy and paste of the PVC comment has brought +the attention to the incorrect masks of the PVC register for RPa +and RPe. So, let's fix them all. + +Cc: Lucas De Marchi +Cc: Vinay Belgaumkar +Reviewed-by: Vinay Belgaumkar +Link: https://patchwork.freedesktop.org/patch/msgid/20250109195219.658557-1-rodrigo.vivi@intel.com +Signed-off-by: Rodrigo Vivi +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/xe/xe_guc_pc.c | 22 ++++++++++++---------- + 1 file changed, 12 insertions(+), 10 deletions(-) + +diff --git a/drivers/gpu/drm/xe/xe_guc_pc.c b/drivers/gpu/drm/xe/xe_guc_pc.c +index f382f5d53ca8b..2276d85926fcb 100644 +--- a/drivers/gpu/drm/xe/xe_guc_pc.c ++++ b/drivers/gpu/drm/xe/xe_guc_pc.c +@@ -371,16 +371,17 @@ static void tgl_update_rpa_value(struct xe_guc_pc *pc) + u32 reg; + + /* +- * For PVC we still need to use fused RP1 as the approximation for RPe +- * For other platforms than PVC we get the resolved RPe directly from ++ * For PVC we still need to use fused RP0 as the approximation for RPa ++ * For other platforms than PVC we get the resolved RPa directly from + * PCODE at a different register + */ +- if (xe->info.platform == XE_PVC) ++ if (xe->info.platform == XE_PVC) { + reg = xe_mmio_read32(>->mmio, PVC_RP_STATE_CAP); +- else ++ pc->rpa_freq = REG_FIELD_GET(RP0_MASK, reg) * GT_FREQUENCY_MULTIPLIER; ++ } else { + reg = xe_mmio_read32(>->mmio, FREQ_INFO_REC); +- +- pc->rpa_freq = REG_FIELD_GET(RPA_MASK, reg) * GT_FREQUENCY_MULTIPLIER; ++ pc->rpa_freq = REG_FIELD_GET(RPA_MASK, reg) * GT_FREQUENCY_MULTIPLIER; ++ } + } + + static void tgl_update_rpe_value(struct xe_guc_pc *pc) +@@ -394,12 +395,13 @@ static void tgl_update_rpe_value(struct xe_guc_pc *pc) + * For other platforms than PVC we get the resolved RPe directly from + * PCODE at a different register + */ +- if (xe->info.platform == XE_PVC) ++ if (xe->info.platform == XE_PVC) { + reg = xe_mmio_read32(>->mmio, PVC_RP_STATE_CAP); +- else ++ pc->rpe_freq = REG_FIELD_GET(RP1_MASK, reg) * GT_FREQUENCY_MULTIPLIER; ++ } else { + reg = xe_mmio_read32(>->mmio, FREQ_INFO_REC); +- +- pc->rpe_freq = REG_FIELD_GET(RPE_MASK, reg) * GT_FREQUENCY_MULTIPLIER; ++ pc->rpe_freq = REG_FIELD_GET(RPE_MASK, reg) * GT_FREQUENCY_MULTIPLIER; ++ } + } + + static void pc_update_rp_values(struct xe_guc_pc *pc) +-- +2.39.5 + diff --git a/queue-6.14/drm-xe-fix-xe_tile_init_noalloc-error-propagation.patch b/queue-6.14/drm-xe-fix-xe_tile_init_noalloc-error-propagation.patch new file mode 100644 index 0000000000..a14075a401 --- /dev/null +++ b/queue-6.14/drm-xe-fix-xe_tile_init_noalloc-error-propagation.patch @@ -0,0 +1,39 @@ +From a7c6159f19ee5abb01035592fe7c28bbde8e576a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 13 Feb 2025 11:29:00 -0800 +Subject: drm/xe: Fix xe_tile_init_noalloc() error propagation + +From: Lucas De Marchi + +[ Upstream commit 0bcf41171c64234e79eb3552d00f0aad8a47e8d3 ] + +Propagate the error to the caller so initialization properly stops if +sysfs creation fails. + +Reviewed-by: Francois Dugast +Reviewed-by: Himal Prasad Ghimiray +Link: https://patchwork.freedesktop.org/patch/msgid/20250213192909.996148-4-lucas.demarchi@intel.com +Signed-off-by: Lucas De Marchi +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/xe/xe_tile.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +diff --git a/drivers/gpu/drm/xe/xe_tile.c b/drivers/gpu/drm/xe/xe_tile.c +index 07cf7cfe4abd5..37f170effcd67 100644 +--- a/drivers/gpu/drm/xe/xe_tile.c ++++ b/drivers/gpu/drm/xe/xe_tile.c +@@ -176,9 +176,7 @@ int xe_tile_init_noalloc(struct xe_tile *tile) + + xe_wa_apply_tile_workarounds(tile); + +- err = xe_tile_sysfs_init(tile); +- +- return 0; ++ return xe_tile_sysfs_init(tile); + } + + void xe_tile_migrate_wait(struct xe_tile *tile) +-- +2.39.5 + diff --git a/queue-6.14/drm-xe-guc-drop-error-messages-about-missing-guc-log.patch b/queue-6.14/drm-xe-guc-drop-error-messages-about-missing-guc-log.patch new file mode 100644 index 0000000000..9320993c00 --- /dev/null +++ b/queue-6.14/drm-xe-guc-drop-error-messages-about-missing-guc-log.patch @@ -0,0 +1,57 @@ +From 3ccce22a43e408c352e137f8b82e213d1b9d9e16 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 13 Jan 2025 11:44:04 -0800 +Subject: drm/xe/guc: Drop error messages about missing GuC logs + +From: John Harrison + +[ Upstream commit 174e9ce0daf6af791386e96e76e743eb59e8a401 ] + +The GuC log snapshot code would complain loudly if there was no GuC +log to take a snapshot of or if the snapshot alloc failed. Originally, +this code was only called on demand when a user (or developer) +explicitly requested a dump of the log. Hence an error message was +useful. + +However, it is now part of the general devcoredump file and is called +for any GPU hang. Most people don't care about GuC logs and GPU hangs +do not generally mean a kernel/GuC bug. More importantly, there are +valid situations where there is no GuC log, e.g. SRIOV VFs. + +So drop the error message. + +Closes: https://gitlab.freedesktop.org/drm/xe/kernel/-/issues/3958 +Signed-off-by: John Harrison +Reviewed-by: Rodrigo Vivi +Link: https://patchwork.freedesktop.org/patch/msgid/20250113194405.2033085-1-John.C.Harrison@Intel.com +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/xe/xe_guc_log.c | 8 ++------ + 1 file changed, 2 insertions(+), 6 deletions(-) + +diff --git a/drivers/gpu/drm/xe/xe_guc_log.c b/drivers/gpu/drm/xe/xe_guc_log.c +index 0ca3056d8bd3f..80514a446ba28 100644 +--- a/drivers/gpu/drm/xe/xe_guc_log.c ++++ b/drivers/gpu/drm/xe/xe_guc_log.c +@@ -149,16 +149,12 @@ struct xe_guc_log_snapshot *xe_guc_log_snapshot_capture(struct xe_guc_log *log, + size_t remain; + int i; + +- if (!log->bo) { +- xe_gt_err(gt, "GuC log buffer not allocated\n"); ++ if (!log->bo) + return NULL; +- } + + snapshot = xe_guc_log_snapshot_alloc(log, atomic); +- if (!snapshot) { +- xe_gt_err(gt, "GuC log snapshot not allocated\n"); ++ if (!snapshot) + return NULL; +- } + + remain = snapshot->size; + for (i = 0; i < snapshot->num_chunks; i++) { +-- +2.39.5 + diff --git a/queue-6.14/drm-xe-move-suballocator-init-to-after-display-init.patch b/queue-6.14/drm-xe-move-suballocator-init-to-after-display-init.patch new file mode 100644 index 0000000000..9b0dd7d2cd --- /dev/null +++ b/queue-6.14/drm-xe-move-suballocator-init-to-after-display-init.patch @@ -0,0 +1,82 @@ +From ad19b7951a55413ff7513b43ff48e78b34bfed62 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 10 Dec 2024 09:31:03 +0100 +Subject: drm/xe: Move suballocator init to after display init + +From: Maarten Lankhorst + +[ Upstream commit 380b0cdaa76bc8f5c16db16eaf48751e792ff041 ] + +No allocations should be done before we have had a chance to preserve +the display fb. + +Reviewed-by: Rodrigo Vivi +Link: https://patchwork.freedesktop.org/patch/msgid/20241210083111.230484-4-dev@lankhorst.se +Signed-off-by: Maarten Lankhorst +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/xe/xe_device.c | 6 ++++++ + drivers/gpu/drm/xe/xe_tile.c | 12 ++++++++---- + drivers/gpu/drm/xe/xe_tile.h | 1 + + 3 files changed, 15 insertions(+), 4 deletions(-) + +diff --git a/drivers/gpu/drm/xe/xe_device.c b/drivers/gpu/drm/xe/xe_device.c +index e22f29ac96631..74516e73ba4e5 100644 +--- a/drivers/gpu/drm/xe/xe_device.c ++++ b/drivers/gpu/drm/xe/xe_device.c +@@ -736,6 +736,12 @@ int xe_device_probe(struct xe_device *xe) + if (err) + goto err; + ++ for_each_tile(tile, xe, id) { ++ err = xe_tile_init(tile); ++ if (err) ++ goto err; ++ } ++ + for_each_gt(gt, xe, id) { + last_gt = id; + +diff --git a/drivers/gpu/drm/xe/xe_tile.c b/drivers/gpu/drm/xe/xe_tile.c +index 37f170effcd67..377438ea6b838 100644 +--- a/drivers/gpu/drm/xe/xe_tile.c ++++ b/drivers/gpu/drm/xe/xe_tile.c +@@ -170,15 +170,19 @@ int xe_tile_init_noalloc(struct xe_tile *tile) + if (err) + return err; + +- tile->mem.kernel_bb_pool = xe_sa_bo_manager_init(tile, SZ_1M, 16); +- if (IS_ERR(tile->mem.kernel_bb_pool)) +- return PTR_ERR(tile->mem.kernel_bb_pool); +- + xe_wa_apply_tile_workarounds(tile); + + return xe_tile_sysfs_init(tile); + } + ++int xe_tile_init(struct xe_tile *tile) ++{ ++ tile->mem.kernel_bb_pool = xe_sa_bo_manager_init(tile, SZ_1M, 16); ++ if (IS_ERR(tile->mem.kernel_bb_pool)) ++ return PTR_ERR(tile->mem.kernel_bb_pool); ++ ++ return 0; ++} + void xe_tile_migrate_wait(struct xe_tile *tile) + { + xe_migrate_wait(tile->migrate); +diff --git a/drivers/gpu/drm/xe/xe_tile.h b/drivers/gpu/drm/xe/xe_tile.h +index 1c9e42ade6b05..eb939316d55b0 100644 +--- a/drivers/gpu/drm/xe/xe_tile.h ++++ b/drivers/gpu/drm/xe/xe_tile.h +@@ -12,6 +12,7 @@ struct xe_tile; + + int xe_tile_init_early(struct xe_tile *tile, struct xe_device *xe, u8 id); + int xe_tile_init_noalloc(struct xe_tile *tile); ++int xe_tile_init(struct xe_tile *tile); + + void xe_tile_migrate_wait(struct xe_tile *tile); + +-- +2.39.5 + diff --git a/queue-6.14/drm-xe-nuke-vm-s-mapping-upon-close.patch b/queue-6.14/drm-xe-nuke-vm-s-mapping-upon-close.patch new file mode 100644 index 0000000000..65b88ca6d4 --- /dev/null +++ b/queue-6.14/drm-xe-nuke-vm-s-mapping-upon-close.patch @@ -0,0 +1,195 @@ +From 9ad70d195ae7be3c52f42a2830325c9839dacdc6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Mar 2025 17:26:36 -0800 +Subject: drm/xe: Nuke VM's mapping upon close +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Matthew Brost + +[ Upstream commit 074e40d9c2a84939fe28d7121d3469db50f34a3d ] + +Clear root PT entry and invalidate entire VM's address space when +closing the VM. Will prevent the GPU from accessing any of the VM's +memory after closing. + +v2: + - s/vma/vm in kernel doc (CI) + - Don't nuke migration VM as this occur at driver unload (CI) +v3: + - Rebase and pull into SVM series (Thomas) + - Wait for pending binds (Thomas) +v5: + - Remove xe_gt_tlb_invalidation_fence_fini in error case (Matt Auld) + - Drop local migration bool (Thomas) +v7: + - Add drm_dev_enter/exit protecting invalidation (CI, Matt Auld) + +Signed-off-by: Matthew Brost +Reviewed-by: Thomas Hellström +Link: https://patchwork.freedesktop.org/patch/msgid/20250306012657.3505757-12-matthew.brost@intel.com +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/xe/xe_gt_tlb_invalidation.c | 22 ++++++++++++++ + drivers/gpu/drm/xe/xe_gt_tlb_invalidation.h | 2 ++ + drivers/gpu/drm/xe/xe_pt.c | 14 +++++++++ + drivers/gpu/drm/xe/xe_pt.h | 3 ++ + drivers/gpu/drm/xe/xe_vm.c | 32 +++++++++++++++++++++ + 5 files changed, 73 insertions(+) + +diff --git a/drivers/gpu/drm/xe/xe_gt_tlb_invalidation.c b/drivers/gpu/drm/xe/xe_gt_tlb_invalidation.c +index 9405d83d4db2a..084cbdeba8eaa 100644 +--- a/drivers/gpu/drm/xe/xe_gt_tlb_invalidation.c ++++ b/drivers/gpu/drm/xe/xe_gt_tlb_invalidation.c +@@ -418,6 +418,28 @@ int xe_gt_tlb_invalidation_range(struct xe_gt *gt, + return send_tlb_invalidation(>->uc.guc, fence, action, len); + } + ++/** ++ * xe_gt_tlb_invalidation_vm - Issue a TLB invalidation on this GT for a VM ++ * @gt: graphics tile ++ * @vm: VM to invalidate ++ * ++ * Invalidate entire VM's address space ++ */ ++void xe_gt_tlb_invalidation_vm(struct xe_gt *gt, struct xe_vm *vm) ++{ ++ struct xe_gt_tlb_invalidation_fence fence; ++ u64 range = 1ull << vm->xe->info.va_bits; ++ int ret; ++ ++ xe_gt_tlb_invalidation_fence_init(gt, &fence, true); ++ ++ ret = xe_gt_tlb_invalidation_range(gt, &fence, 0, range, vm->usm.asid); ++ if (ret < 0) ++ return; ++ ++ xe_gt_tlb_invalidation_fence_wait(&fence); ++} ++ + /** + * xe_gt_tlb_invalidation_vma - Issue a TLB invalidation on this GT for a VMA + * @gt: GT structure +diff --git a/drivers/gpu/drm/xe/xe_gt_tlb_invalidation.h b/drivers/gpu/drm/xe/xe_gt_tlb_invalidation.h +index 672acfcdf0d70..abe9b03d543e6 100644 +--- a/drivers/gpu/drm/xe/xe_gt_tlb_invalidation.h ++++ b/drivers/gpu/drm/xe/xe_gt_tlb_invalidation.h +@@ -12,6 +12,7 @@ + + struct xe_gt; + struct xe_guc; ++struct xe_vm; + struct xe_vma; + + int xe_gt_tlb_invalidation_init_early(struct xe_gt *gt); +@@ -21,6 +22,7 @@ int xe_gt_tlb_invalidation_ggtt(struct xe_gt *gt); + int xe_gt_tlb_invalidation_vma(struct xe_gt *gt, + struct xe_gt_tlb_invalidation_fence *fence, + struct xe_vma *vma); ++void xe_gt_tlb_invalidation_vm(struct xe_gt *gt, struct xe_vm *vm); + int xe_gt_tlb_invalidation_range(struct xe_gt *gt, + struct xe_gt_tlb_invalidation_fence *fence, + u64 start, u64 end, u32 asid); +diff --git a/drivers/gpu/drm/xe/xe_pt.c b/drivers/gpu/drm/xe/xe_pt.c +index dc24baa840924..148d90611eebf 100644 +--- a/drivers/gpu/drm/xe/xe_pt.c ++++ b/drivers/gpu/drm/xe/xe_pt.c +@@ -218,6 +218,20 @@ void xe_pt_destroy(struct xe_pt *pt, u32 flags, struct llist_head *deferred) + xe_pt_free(pt); + } + ++/** ++ * xe_pt_clear() - Clear a page-table. ++ * @xe: xe device. ++ * @pt: The page-table. ++ * ++ * Clears page-table by setting to zero. ++ */ ++void xe_pt_clear(struct xe_device *xe, struct xe_pt *pt) ++{ ++ struct iosys_map *map = &pt->bo->vmap; ++ ++ xe_map_memset(xe, map, 0, 0, SZ_4K); ++} ++ + /** + * DOC: Pagetable building + * +diff --git a/drivers/gpu/drm/xe/xe_pt.h b/drivers/gpu/drm/xe/xe_pt.h +index 9ab386431cadd..8e43912ae8e94 100644 +--- a/drivers/gpu/drm/xe/xe_pt.h ++++ b/drivers/gpu/drm/xe/xe_pt.h +@@ -13,6 +13,7 @@ struct dma_fence; + struct xe_bo; + struct xe_device; + struct xe_exec_queue; ++struct xe_svm_range; + struct xe_sync_entry; + struct xe_tile; + struct xe_vm; +@@ -35,6 +36,8 @@ void xe_pt_populate_empty(struct xe_tile *tile, struct xe_vm *vm, + + void xe_pt_destroy(struct xe_pt *pt, u32 flags, struct llist_head *deferred); + ++void xe_pt_clear(struct xe_device *xe, struct xe_pt *pt); ++ + int xe_pt_update_ops_prepare(struct xe_tile *tile, struct xe_vma_ops *vops); + struct dma_fence *xe_pt_update_ops_run(struct xe_tile *tile, + struct xe_vma_ops *vops); +diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c +index 5956631c0d40a..785b8960050bd 100644 +--- a/drivers/gpu/drm/xe/xe_vm.c ++++ b/drivers/gpu/drm/xe/xe_vm.c +@@ -8,6 +8,7 @@ + #include + #include + ++#include + #include + #include + #include +@@ -1582,9 +1583,40 @@ struct xe_vm *xe_vm_create(struct xe_device *xe, u32 flags) + + static void xe_vm_close(struct xe_vm *vm) + { ++ struct xe_device *xe = vm->xe; ++ bool bound; ++ int idx; ++ ++ bound = drm_dev_enter(&xe->drm, &idx); ++ + down_write(&vm->lock); ++ + vm->size = 0; ++ ++ if (!((vm->flags & XE_VM_FLAG_MIGRATION))) { ++ struct xe_tile *tile; ++ struct xe_gt *gt; ++ u8 id; ++ ++ /* Wait for pending binds */ ++ dma_resv_wait_timeout(xe_vm_resv(vm), ++ DMA_RESV_USAGE_BOOKKEEP, ++ false, MAX_SCHEDULE_TIMEOUT); ++ ++ if (bound) { ++ for_each_tile(tile, xe, id) ++ if (vm->pt_root[id]) ++ xe_pt_clear(xe, vm->pt_root[id]); ++ ++ for_each_gt(gt, xe, id) ++ xe_gt_tlb_invalidation_vm(gt, vm); ++ } ++ } ++ + up_write(&vm->lock); ++ ++ if (bound) ++ drm_dev_exit(idx); + } + + void xe_vm_close_and_put(struct xe_vm *vm) +-- +2.39.5 + diff --git a/queue-6.14/drm-xe-oa-ensure-that-polled-read-returns-latest-dat.patch b/queue-6.14/drm-xe-oa-ensure-that-polled-read-returns-latest-dat.patch new file mode 100644 index 0000000000..3790a46a0b --- /dev/null +++ b/queue-6.14/drm-xe-oa-ensure-that-polled-read-returns-latest-dat.patch @@ -0,0 +1,37 @@ +From 5a3e69febd14d6dba17375c62fe6bb1ce3cee418 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 11 Feb 2025 17:02:55 -0800 +Subject: drm/xe/oa: Ensure that polled read returns latest data + +From: Umesh Nerlige Ramappa + +[ Upstream commit 98c9d27ab30aa9c6451d3a34e6e297171f273e51 ] + +In polled mode, user calls poll() for read data to be available before +performing a read(). In the duration between these 2 calls, there may be +new data available in the OA buffer. To ensure user reads all available +data, check for latest data in the OA buffer in polled read. + +Signed-off-by: Umesh Nerlige Ramappa +Reviewed-by: Ashutosh Dixit +Link: https://patchwork.freedesktop.org/patch/msgid/20250212010255.1423343-1-umesh.nerlige.ramappa@intel.com +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/xe/xe_oa.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/gpu/drm/xe/xe_oa.c b/drivers/gpu/drm/xe/xe_oa.c +index eb6cd91e1e226..abf37d9ab2212 100644 +--- a/drivers/gpu/drm/xe/xe_oa.c ++++ b/drivers/gpu/drm/xe/xe_oa.c +@@ -548,6 +548,7 @@ static ssize_t xe_oa_read(struct file *file, char __user *buf, + mutex_unlock(&stream->stream_lock); + } while (!offset && !ret); + } else { ++ xe_oa_buffer_check_unlocked(stream); + mutex_lock(&stream->stream_lock); + ret = __xe_oa_read(stream, buf, count, &offset); + mutex_unlock(&stream->stream_lock); +-- +2.39.5 + diff --git a/queue-6.14/drm-xe-pf-create-a-link-between-pf-and-vf-devices.patch b/queue-6.14/drm-xe-pf-create-a-link-between-pf-and-vf-devices.patch new file mode 100644 index 0000000000..08483f94a3 --- /dev/null +++ b/queue-6.14/drm-xe-pf-create-a-link-between-pf-and-vf-devices.patch @@ -0,0 +1,120 @@ +From 50a29a8692e12200b2ac7f88fa3bdd29093f10a3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 24 Feb 2025 15:58:06 +0530 +Subject: drm/xe/pf: Create a link between PF and VF devices +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Satyanarayana K V P + +[ Upstream commit 8c0aff7d92e2be25717669eb65a81a89740a24f2 ] + +When both PF and VF devices are enabled on the host, they +resume simultaneously during system resume. + +However, the PF must finish provisioning the VF before any +VFs can successfully resume. + +Establish a parent-child device link between the PF and VF +devices to ensure the correct order of resumption. + +V4 -> V5: +- Added missing break in the error condition. +V3 -> V4: +- Made xe_pci_pf_get_vf_dev() as a static function and updated + input parameter types. +- Updated xe_sriov_warn() to xe_sriov_abort() when VF device + cannot be found. +V2 -> V3: +- Added function documentation for xe_pci_pf_get_vf_dev(). +- Added assertion if not called from PF. +V1 -> V2: +- Added a helper function to get VF pci_dev. +- Updated xe_sriov_notice() to xe_sriov_warn() if vf pci_dev + is not found. + +Signed-off-by: Satyanarayana K V P +Cc: Michał Wajdeczko +Cc: Michał Winiarski +Cc: Piotr Piórkowski +Reviewed-by: Piotr Piorkowski +Signed-off-by: Michal Wajdeczko +Link: https://patchwork.freedesktop.org/patch/msgid/20250224102807.11065-2-satyanarayana.k.v.p@intel.com +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/xe/xe_pci_sriov.c | 51 +++++++++++++++++++++++++++++++ + 1 file changed, 51 insertions(+) + +diff --git a/drivers/gpu/drm/xe/xe_pci_sriov.c b/drivers/gpu/drm/xe/xe_pci_sriov.c +index aaceee748287e..09ee8a06fe2ed 100644 +--- a/drivers/gpu/drm/xe/xe_pci_sriov.c ++++ b/drivers/gpu/drm/xe/xe_pci_sriov.c +@@ -62,6 +62,55 @@ static void pf_reset_vfs(struct xe_device *xe, unsigned int num_vfs) + xe_gt_sriov_pf_control_trigger_flr(gt, n); + } + ++static struct pci_dev *xe_pci_pf_get_vf_dev(struct xe_device *xe, unsigned int vf_id) ++{ ++ struct pci_dev *pdev = to_pci_dev(xe->drm.dev); ++ ++ xe_assert(xe, IS_SRIOV_PF(xe)); ++ ++ /* caller must use pci_dev_put() */ ++ return pci_get_domain_bus_and_slot(pci_domain_nr(pdev->bus), ++ pdev->bus->number, ++ pci_iov_virtfn_devfn(pdev, vf_id)); ++} ++ ++static void pf_link_vfs(struct xe_device *xe, int num_vfs) ++{ ++ struct pci_dev *pdev_pf = to_pci_dev(xe->drm.dev); ++ struct device_link *link; ++ struct pci_dev *pdev_vf; ++ unsigned int n; ++ ++ /* ++ * When both PF and VF devices are enabled on the host, during system ++ * resume they are resuming in parallel. ++ * ++ * But PF has to complete the provision of VF first to allow any VFs to ++ * successfully resume. ++ * ++ * Create a parent-child device link between PF and VF devices that will ++ * enforce correct resume order. ++ */ ++ for (n = 1; n <= num_vfs; n++) { ++ pdev_vf = xe_pci_pf_get_vf_dev(xe, n - 1); ++ ++ /* unlikely, something weird is happening, abort */ ++ if (!pdev_vf) { ++ xe_sriov_err(xe, "Cannot find VF%u device, aborting link%s creation!\n", ++ n, str_plural(num_vfs)); ++ break; ++ } ++ ++ link = device_link_add(&pdev_vf->dev, &pdev_pf->dev, ++ DL_FLAG_AUTOREMOVE_CONSUMER); ++ /* unlikely and harmless, continue with other VFs */ ++ if (!link) ++ xe_sriov_notice(xe, "Failed linking VF%u\n", n); ++ ++ pci_dev_put(pdev_vf); ++ } ++} ++ + static int pf_enable_vfs(struct xe_device *xe, int num_vfs) + { + struct pci_dev *pdev = to_pci_dev(xe->drm.dev); +@@ -92,6 +141,8 @@ static int pf_enable_vfs(struct xe_device *xe, int num_vfs) + if (err < 0) + goto failed; + ++ pf_link_vfs(xe, num_vfs); ++ + xe_sriov_info(xe, "Enabled %u of %u VF%s\n", + num_vfs, total_vfs, str_plural(total_vfs)); + return num_vfs; +-- +2.39.5 + diff --git a/queue-6.14/drm-xe-pf-move-vfs-reprovisioning-to-worker.patch b/queue-6.14/drm-xe-pf-move-vfs-reprovisioning-to-worker.patch new file mode 100644 index 0000000000..e55674b2b9 --- /dev/null +++ b/queue-6.14/drm-xe-pf-move-vfs-reprovisioning-to-worker.patch @@ -0,0 +1,147 @@ +From d09443dcd1dcb2ac89b9ae0910875a1d44174575 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 25 Jan 2025 22:55:05 +0100 +Subject: drm/xe/pf: Move VFs reprovisioning to worker +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Michal Wajdeczko + +[ Upstream commit a4d1c5d0b99b75263a5626d2e52d569db3844b33 ] + +Since the GuC is reset during GT reset, we need to re-send the +entire SR-IOV provisioning configuration to the GuC. But since +this whole configuration is protected by the PF master mutex and +we can't avoid making allocations under this mutex (like during +LMEM provisioning), we can't do this reprovisioning from gt-reset +path if we want to be reclaim-safe. Move VFs reprovisioning to a +async worker that we will start from the gt-reset path. + +Signed-off-by: Michal Wajdeczko +Cc: Thomas Hellström +Cc: Matthew Brost +Reviewed-by: Michał Winiarski +Reviewed-by: Stuart Summers +Reviewed-by: Matthew Brost +Link: https://patchwork.freedesktop.org/patch/msgid/20250125215505.720-1-michal.wajdeczko@intel.com +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/xe/xe_gt_sriov_pf.c | 43 +++++++++++++++++++++-- + drivers/gpu/drm/xe/xe_gt_sriov_pf_types.h | 10 ++++++ + 2 files changed, 51 insertions(+), 2 deletions(-) + +diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_pf.c b/drivers/gpu/drm/xe/xe_gt_sriov_pf.c +index b80930a6bc1a2..c08efca6420e7 100644 +--- a/drivers/gpu/drm/xe/xe_gt_sriov_pf.c ++++ b/drivers/gpu/drm/xe/xe_gt_sriov_pf.c +@@ -15,7 +15,11 @@ + #include "xe_gt_sriov_pf_helpers.h" + #include "xe_gt_sriov_pf_migration.h" + #include "xe_gt_sriov_pf_service.h" ++#include "xe_gt_sriov_printk.h" + #include "xe_mmio.h" ++#include "xe_pm.h" ++ ++static void pf_worker_restart_func(struct work_struct *w); + + /* + * VF's metadata is maintained in the flexible array where: +@@ -41,6 +45,11 @@ static int pf_alloc_metadata(struct xe_gt *gt) + return 0; + } + ++static void pf_init_workers(struct xe_gt *gt) ++{ ++ INIT_WORK(>->sriov.pf.workers.restart, pf_worker_restart_func); ++} ++ + /** + * xe_gt_sriov_pf_init_early - Prepare SR-IOV PF data structures on PF. + * @gt: the &xe_gt to initialize +@@ -65,6 +74,8 @@ int xe_gt_sriov_pf_init_early(struct xe_gt *gt) + if (err) + return err; + ++ pf_init_workers(gt); ++ + return 0; + } + +@@ -161,6 +172,35 @@ void xe_gt_sriov_pf_sanitize_hw(struct xe_gt *gt, unsigned int vfid) + pf_clear_vf_scratch_regs(gt, vfid); + } + ++static void pf_restart(struct xe_gt *gt) ++{ ++ struct xe_device *xe = gt_to_xe(gt); ++ ++ xe_pm_runtime_get(xe); ++ xe_gt_sriov_pf_config_restart(gt); ++ xe_gt_sriov_pf_control_restart(gt); ++ xe_pm_runtime_put(xe); ++ ++ xe_gt_sriov_dbg(gt, "restart completed\n"); ++} ++ ++static void pf_worker_restart_func(struct work_struct *w) ++{ ++ struct xe_gt *gt = container_of(w, typeof(*gt), sriov.pf.workers.restart); ++ ++ pf_restart(gt); ++} ++ ++static void pf_queue_restart(struct xe_gt *gt) ++{ ++ struct xe_device *xe = gt_to_xe(gt); ++ ++ xe_gt_assert(gt, IS_SRIOV_PF(xe)); ++ ++ if (!queue_work(xe->sriov.wq, >->sriov.pf.workers.restart)) ++ xe_gt_sriov_dbg(gt, "restart already in queue!\n"); ++} ++ + /** + * xe_gt_sriov_pf_restart - Restart SR-IOV support after a GT reset. + * @gt: the &xe_gt +@@ -169,6 +209,5 @@ void xe_gt_sriov_pf_sanitize_hw(struct xe_gt *gt, unsigned int vfid) + */ + void xe_gt_sriov_pf_restart(struct xe_gt *gt) + { +- xe_gt_sriov_pf_config_restart(gt); +- xe_gt_sriov_pf_control_restart(gt); ++ pf_queue_restart(gt); + } +diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_pf_types.h b/drivers/gpu/drm/xe/xe_gt_sriov_pf_types.h +index 0426b1a77069a..a64a6835ad656 100644 +--- a/drivers/gpu/drm/xe/xe_gt_sriov_pf_types.h ++++ b/drivers/gpu/drm/xe/xe_gt_sriov_pf_types.h +@@ -35,8 +35,17 @@ struct xe_gt_sriov_metadata { + struct xe_gt_sriov_state_snapshot snapshot; + }; + ++/** ++ * struct xe_gt_sriov_pf_workers - GT level workers used by the PF. ++ */ ++struct xe_gt_sriov_pf_workers { ++ /** @restart: worker that executes actions post GT reset */ ++ struct work_struct restart; ++}; ++ + /** + * struct xe_gt_sriov_pf - GT level PF virtualization data. ++ * @workers: workers data. + * @service: service data. + * @control: control data. + * @policy: policy data. +@@ -45,6 +54,7 @@ struct xe_gt_sriov_metadata { + * @vfs: metadata for all VFs. + */ + struct xe_gt_sriov_pf { ++ struct xe_gt_sriov_pf_workers workers; + struct xe_gt_sriov_pf_service service; + struct xe_gt_sriov_pf_control control; + struct xe_gt_sriov_pf_policy policy; +-- +2.39.5 + diff --git a/queue-6.14/drm-xe-pf-release-all-vfs-configs-on-device-removal.patch b/queue-6.14/drm-xe-pf-release-all-vfs-configs-on-device-removal.patch new file mode 100644 index 0000000000..6edfcc9c2a --- /dev/null +++ b/queue-6.14/drm-xe-pf-release-all-vfs-configs-on-device-removal.patch @@ -0,0 +1,124 @@ +From 92a348b3db75e258d99bdb6cf2421c31fa16134e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 11 Feb 2025 16:50:34 +0100 +Subject: drm/xe/pf: Release all VFs configs on device removal +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Michal Wajdeczko + +[ Upstream commit 611160b02a40ce3f60ab94eea85b394dca1cafd2 ] + +If we try to manually provision VFs using debugfs and then we +try to unload the driver, we will see complains like: + + [ ] Memory manager not clean during takedown. + [ ] RIP: 0010:drm_mm_takedown+0x3f/0x100 + [ ] [drm:drm_mm_takedown] *ERROR* node [fedff000 + 00001000]: inserted at + drm_mm_insert_node_in_range+0x2bd/0x520 + xe_ggtt_node_insert+0x52/0x90 [xe] + pf_provision_vf_ggtt+0x1fa/0xac0 [xe] + xe_gt_sriov_pf_config_set_ggtt+0x79/0x7a0 [xe] + ggtt_set+0x53/0x80 [xe] + simple_attr_write_xsigned.isra.0+0xd2/0x150 + simple_attr_write+0x14/0x30 + debugfs_attr_write+0x4e/0x80 + + [ ] xe 0000:00:02.0: [drm] *ERROR* GT0: GUC ID manager unclean (1/65535) + [ ] xe 0000:00:02.0: [drm] GT0: total 65535 + [ ] xe 0000:00:02.0: [drm] GT0: used 1 + [ ] xe 0000:00:02.0: [drm] GT0: range 65534..65534 (1) + + [ ] xe 0000:00:02.0: [drm] *ERROR* GT0: GuC doorbells manager unclean (1/256) + [ ] xe 0000:00:02.0: [drm] GT0: count: 256 + [ ] xe 0000:00:02.0: [drm] GT0: available range: 1..255 (255) + [ ] xe 0000:00:02.0: [drm] GT0: available total: 255 + [ ] xe 0000:00:02.0: [drm] GT0: reserved range: 0..0 (1) + [ ] xe 0000:00:02.0: [drm] GT0: reserved total: 1 + +This could be easily fixed by adding config release action. + +Signed-off-by: Michal Wajdeczko +Cc: Piotr Piórkowski +Reviewed-by: Piotr Piórkowski +Link: https://patchwork.freedesktop.org/patch/msgid/20250211155034.1028-1-michal.wajdeczko@intel.com +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/xe/xe_gt_sriov_pf.c | 6 +++++ + drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c | 29 ++++++++++++++++++++++ + drivers/gpu/drm/xe/xe_gt_sriov_pf_config.h | 1 + + 3 files changed, 36 insertions(+) + +diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_pf.c b/drivers/gpu/drm/xe/xe_gt_sriov_pf.c +index 6f906c8e8108b..b80930a6bc1a2 100644 +--- a/drivers/gpu/drm/xe/xe_gt_sriov_pf.c ++++ b/drivers/gpu/drm/xe/xe_gt_sriov_pf.c +@@ -78,6 +78,12 @@ int xe_gt_sriov_pf_init_early(struct xe_gt *gt) + */ + int xe_gt_sriov_pf_init(struct xe_gt *gt) + { ++ int err; ++ ++ err = xe_gt_sriov_pf_config_init(gt); ++ if (err) ++ return err; ++ + return xe_gt_sriov_pf_migration_init(gt); + } + +diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c b/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c +index 4bd255adfb401..aaca54b40091f 100644 +--- a/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c ++++ b/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c +@@ -2320,6 +2320,35 @@ int xe_gt_sriov_pf_config_restore(struct xe_gt *gt, unsigned int vfid, + return err; + } + ++static void fini_config(void *arg) ++{ ++ struct xe_gt *gt = arg; ++ struct xe_device *xe = gt_to_xe(gt); ++ unsigned int n, total_vfs = xe_sriov_pf_get_totalvfs(xe); ++ ++ mutex_lock(xe_gt_sriov_pf_master_mutex(gt)); ++ for (n = 1; n <= total_vfs; n++) ++ pf_release_vf_config(gt, n); ++ mutex_unlock(xe_gt_sriov_pf_master_mutex(gt)); ++} ++ ++/** ++ * xe_gt_sriov_pf_config_init - Initialize SR-IOV configuration data. ++ * @gt: the &xe_gt ++ * ++ * This function can only be called on PF. ++ * ++ * Return: 0 on success or a negative error code on failure. ++ */ ++int xe_gt_sriov_pf_config_init(struct xe_gt *gt) ++{ ++ struct xe_device *xe = gt_to_xe(gt); ++ ++ xe_gt_assert(gt, IS_SRIOV_PF(xe)); ++ ++ return devm_add_action_or_reset(xe->drm.dev, fini_config, gt); ++} ++ + /** + * xe_gt_sriov_pf_config_restart - Restart SR-IOV configurations after a GT reset. + * @gt: the &xe_gt +diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.h b/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.h +index f894e9d4abba2..513e6512a575b 100644 +--- a/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.h ++++ b/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.h +@@ -63,6 +63,7 @@ int xe_gt_sriov_pf_config_restore(struct xe_gt *gt, unsigned int vfid, + + bool xe_gt_sriov_pf_config_is_empty(struct xe_gt *gt, unsigned int vfid); + ++int xe_gt_sriov_pf_config_init(struct xe_gt *gt); + void xe_gt_sriov_pf_config_restart(struct xe_gt *gt); + + int xe_gt_sriov_pf_config_print_ggtt(struct xe_gt *gt, struct drm_printer *p); +-- +2.39.5 + diff --git a/queue-6.14/drm-xe-pf-reset-guc-vf-config-when-unprovisioning-cr.patch b/queue-6.14/drm-xe-pf-reset-guc-vf-config-when-unprovisioning-cr.patch new file mode 100644 index 0000000000..48e376eba2 --- /dev/null +++ b/queue-6.14/drm-xe-pf-reset-guc-vf-config-when-unprovisioning-cr.patch @@ -0,0 +1,114 @@ +From e8a49c2490f5523645df9e30f0c99bec2fc0f427 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 29 Jan 2025 20:59:47 +0100 +Subject: drm/xe/pf: Reset GuC VF config when unprovisioning critical resource +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Michal Wajdeczko + +[ Upstream commit 33f17e2cbd930a2a00eb007d9b241b6db010a880 ] + +GuC firmware counts received VF configuration KLVs and may start +validation of the complete VF config even if some resources where +unprovisioned in the meantime, leading to unexpected errors like: + + $ echo 1 | sudo tee /sys/kernel/debug/dri/0000:00:02.0/gt0/vf1/contexts_quota + $ echo 0 | sudo tee /sys/kernel/debug/dri/0000:00:02.0/gt0/vf1/contexts_quota + $ echo 1 | sudo tee /sys/kernel/debug/dri/0000:00:02.0/gt0/vf1/doorbells_quota + $ echo 0 | sudo tee /sys/kernel/debug/dri/0000:00:02.0/gt0/vf1/doorbells_quota + $ echo 1 | sudo tee /sys/kernel/debug/dri/0000:00:02.0/gt0/vf1/ggtt_quota + tee: '/sys/kernel/debug/dri/0000:00:02.0/gt0/vf1/ggtt_quota': Input/output error + +To mitigate this problem trigger explicit VF config reset after +unprovisioning any of the critical resources (GGTT, context or +doorbell IDs) that GuC is monitoring. + +Signed-off-by: Michal Wajdeczko +Reviewed-by: Michał Winiarski +Link: https://patchwork.freedesktop.org/patch/msgid/20250129195947.764-3-michal.wajdeczko@intel.com +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c | 37 +++++++++++++++++++--- + 1 file changed, 33 insertions(+), 4 deletions(-) + +diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c b/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c +index aaca54b40091f..27f309e3a76e6 100644 +--- a/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c ++++ b/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c +@@ -336,6 +336,26 @@ static int pf_push_full_vf_config(struct xe_gt *gt, unsigned int vfid) + return err; + } + ++static int pf_push_vf_cfg(struct xe_gt *gt, unsigned int vfid, bool reset) ++{ ++ int err = 0; ++ ++ xe_gt_assert(gt, vfid); ++ lockdep_assert_held(xe_gt_sriov_pf_master_mutex(gt)); ++ ++ if (reset) ++ err = pf_send_vf_cfg_reset(gt, vfid); ++ if (!err) ++ err = pf_push_full_vf_config(gt, vfid); ++ ++ return err; ++} ++ ++static int pf_refresh_vf_cfg(struct xe_gt *gt, unsigned int vfid) ++{ ++ return pf_push_vf_cfg(gt, vfid, true); ++} ++ + static u64 pf_get_ggtt_alignment(struct xe_gt *gt) + { + struct xe_device *xe = gt_to_xe(gt); +@@ -432,6 +452,10 @@ static int pf_provision_vf_ggtt(struct xe_gt *gt, unsigned int vfid, u64 size) + return err; + + pf_release_vf_config_ggtt(gt, config); ++ ++ err = pf_refresh_vf_cfg(gt, vfid); ++ if (unlikely(err)) ++ return err; + } + xe_gt_assert(gt, !xe_ggtt_node_allocated(config->ggtt_region)); + +@@ -757,6 +781,10 @@ static int pf_provision_vf_ctxs(struct xe_gt *gt, unsigned int vfid, u32 num_ctx + return ret; + + pf_release_config_ctxs(gt, config); ++ ++ ret = pf_refresh_vf_cfg(gt, vfid); ++ if (unlikely(ret)) ++ return ret; + } + + if (!num_ctxs) +@@ -1054,6 +1082,10 @@ static int pf_provision_vf_dbs(struct xe_gt *gt, unsigned int vfid, u32 num_dbs) + return ret; + + pf_release_config_dbs(gt, config); ++ ++ ret = pf_refresh_vf_cfg(gt, vfid); ++ if (unlikely(ret)) ++ return ret; + } + + if (!num_dbs) +@@ -2085,10 +2117,7 @@ int xe_gt_sriov_pf_config_push(struct xe_gt *gt, unsigned int vfid, bool refresh + xe_gt_assert(gt, vfid); + + mutex_lock(xe_gt_sriov_pf_master_mutex(gt)); +- if (refresh) +- err = pf_send_vf_cfg_reset(gt, vfid); +- if (!err) +- err = pf_push_full_vf_config(gt, vfid); ++ err = pf_push_vf_cfg(gt, vfid, refresh); + mutex_unlock(xe_gt_sriov_pf_master_mutex(gt)); + + if (unlikely(err)) { +-- +2.39.5 + diff --git a/queue-6.14/drm-xe-reject-bo-eviction-if-bo-is-bound-to-current-.patch b/queue-6.14/drm-xe-reject-bo-eviction-if-bo-is-bound-to-current-.patch new file mode 100644 index 0000000000..82c15cabac --- /dev/null +++ b/queue-6.14/drm-xe-reject-bo-eviction-if-bo-is-bound-to-current-.patch @@ -0,0 +1,68 @@ +From 41485a1ec895d7f1b60e3f166300e673cf3d5906 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 10 Jan 2025 16:01:37 -0500 +Subject: drm/xe: Reject BO eviction if BO is bound to current VM +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Oak Zeng + +[ Upstream commit 0af944f0e3082ff517958b1cea76fb9b8cb379dd ] + +This is a follow up fix for +https://patchwork.freedesktop.org/patch/msgid/20241203021929.1919730-1-oak.zeng@intel.com +The overall goal is to fail vm_bind when there is memory pressure. See more +details in the commit message of above patch. Abbove patch fixes the issue +when user pass in a vm_id parameter during gem_create. If user doesn't pass +in a vm_id during gem_create, above patch doesn't help. + +This patch further reject BO eviction (which could be triggered by bo validation) +if BO is bound to the current VM. vm_bind could fail due to the eviction failure. +The BO to VM reverse mapping structure is used to determine whether BO is bound +to VM. + +v2: +Move vm_bo definition from function scope to if(evict) clause (Thomas) +Further constraint the condition by adding ctx->resv (Thomas) +Add a short comment describe the change. + +Suggested-by: Thomas Hellström +Signed-off-by: Oak Zeng +Reviewed-by: Thomas Hellström +Signed-off-by: Thomas Hellström +Link: https://patchwork.freedesktop.org/patch/msgid/20250110210137.3181576-1-oak.zeng@intel.com +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/xe/xe_bo.c | 15 +++++++++++++++ + 1 file changed, 15 insertions(+) + +diff --git a/drivers/gpu/drm/xe/xe_bo.c b/drivers/gpu/drm/xe/xe_bo.c +index d1eb87cb178bd..2070aa12059ce 100644 +--- a/drivers/gpu/drm/xe/xe_bo.c ++++ b/drivers/gpu/drm/xe/xe_bo.c +@@ -713,6 +713,21 @@ static int xe_bo_move(struct ttm_buffer_object *ttm_bo, bool evict, + goto out; + } + ++ /* Reject BO eviction if BO is bound to current VM. */ ++ if (evict && ctx->resv) { ++ struct drm_gpuvm_bo *vm_bo; ++ ++ drm_gem_for_each_gpuvm_bo(vm_bo, &bo->ttm.base) { ++ struct xe_vm *vm = gpuvm_to_vm(vm_bo->vm); ++ ++ if (xe_vm_resv(vm) == ctx->resv && ++ xe_vm_in_preempt_fence_mode(vm)) { ++ ret = -EBUSY; ++ goto out; ++ } ++ } ++ } ++ + /* + * Failed multi-hop where the old_mem is still marked as + * TTM_PL_FLAG_TEMPORARY, should just be a dummy move. +-- +2.39.5 + diff --git a/queue-6.14/drm-xe-relay-don-t-use-gfp_kernel-for-new-transactio.patch b/queue-6.14/drm-xe-relay-don-t-use-gfp_kernel-for-new-transactio.patch new file mode 100644 index 0000000000..1c86c31fa4 --- /dev/null +++ b/queue-6.14/drm-xe-relay-don-t-use-gfp_kernel-for-new-transactio.patch @@ -0,0 +1,62 @@ +From 6c2a81d91f3b8827778ca792bd98ec31afb2bf55 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 31 Jan 2025 16:37:13 +0100 +Subject: drm/xe/relay: Don't use GFP_KERNEL for new transactions + +From: Michal Wajdeczko + +[ Upstream commit 78d5d1e20d1de9422f013338a0f2311448588ba7 ] + +VFs use a relay transaction during the resume/reset flow and use +of the GFP_KERNEL flag may conflict with the reclaim: + + -> #0 (fs_reclaim){+.+.}-{0:0}: + [ ] __lock_acquire+0x1874/0x2bc0 + [ ] lock_acquire+0xd2/0x310 + [ ] fs_reclaim_acquire+0xc5/0x100 + [ ] mempool_alloc_noprof+0x5c/0x1b0 + [ ] __relay_get_transaction+0xdc/0xa10 [xe] + [ ] relay_send_to+0x251/0xe50 [xe] + [ ] xe_guc_relay_send_to_pf+0x79/0x3a0 [xe] + [ ] xe_gt_sriov_vf_connect+0x90/0x4d0 [xe] + [ ] xe_uc_init_hw+0x157/0x3b0 [xe] + [ ] do_gt_restart+0x1ae/0x650 [xe] + [ ] xe_gt_resume+0xb6/0x120 [xe] + [ ] xe_pm_runtime_resume+0x15b/0x370 [xe] + [ ] xe_pci_runtime_resume+0x73/0x90 [xe] + [ ] pci_pm_runtime_resume+0xa0/0x100 + [ ] __rpm_callback+0x4d/0x170 + [ ] rpm_callback+0x64/0x70 + [ ] rpm_resume+0x594/0x790 + [ ] __pm_runtime_resume+0x4e/0x90 + [ ] xe_pm_runtime_get_ioctl+0x9c/0x160 [xe] + +Since we have a preallocated pool of relay transactions, which +should cover all our normal relay use cases, we may use the +GFP_NOWAIT flag when allocating new outgoing transactions. + +Signed-off-by: Michal Wajdeczko +Tested-by: Marcin Bernatowicz +Reviewed-by: Marcin Bernatowicz +Link: https://patchwork.freedesktop.org/patch/msgid/20250131153713.808-1-michal.wajdeczko@intel.com +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/xe/xe_guc_relay.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/xe/xe_guc_relay.c b/drivers/gpu/drm/xe/xe_guc_relay.c +index 8f62de026724c..e5dc94f3e6181 100644 +--- a/drivers/gpu/drm/xe/xe_guc_relay.c ++++ b/drivers/gpu/drm/xe/xe_guc_relay.c +@@ -225,7 +225,7 @@ __relay_get_transaction(struct xe_guc_relay *relay, bool incoming, u32 remote, u + * with CTB lock held which is marked as used in the reclaim path. + * Btw, that's one of the reason why we use mempool here! + */ +- txn = mempool_alloc(&relay->pool, incoming ? GFP_ATOMIC : GFP_KERNEL); ++ txn = mempool_alloc(&relay->pool, incoming ? GFP_ATOMIC : GFP_NOWAIT); + if (!txn) + return ERR_PTR(-ENOMEM); + +-- +2.39.5 + diff --git a/queue-6.14/drm-xe-retry-bo-allocation.patch b/queue-6.14/drm-xe-retry-bo-allocation.patch new file mode 100644 index 0000000000..d6e5b7738b --- /dev/null +++ b/queue-6.14/drm-xe-retry-bo-allocation.patch @@ -0,0 +1,61 @@ +From 6aed486a81c20855106f1f93eabf04b610a23f63 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Mar 2025 17:26:26 -0800 +Subject: drm/xe: Retry BO allocation + +From: Matthew Brost + +[ Upstream commit 1d724a2f1b2c3f0cba4975784a808482e0631adf ] + +TTM doesn't support fair eviction via WW locking, this mitigated in by +using retry loops in exec and preempt rebind worker. Extend this retry +loop to BO allocation. Once TTM supports fair eviction this patch can be +reverted. + +v4: + - Keep line break (Stuart) + +Signed-off-by: Matthew Brost +Reviewed-by: Gwan-gyeong Mun +Reviewed-by: Stuart Summers +Link: https://patchwork.freedesktop.org/patch/msgid/20250306012657.3505757-2-matthew.brost@intel.com +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/xe/xe_bo.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/drivers/gpu/drm/xe/xe_bo.c b/drivers/gpu/drm/xe/xe_bo.c +index 3f5391d416d46..d1eb87cb178bd 100644 +--- a/drivers/gpu/drm/xe/xe_bo.c ++++ b/drivers/gpu/drm/xe/xe_bo.c +@@ -2142,6 +2142,7 @@ int xe_gem_create_ioctl(struct drm_device *dev, void *data, + struct xe_file *xef = to_xe_file(file); + struct drm_xe_gem_create *args = data; + struct xe_vm *vm = NULL; ++ ktime_t end = 0; + struct xe_bo *bo; + unsigned int bo_flags; + u32 handle; +@@ -2214,6 +2215,10 @@ int xe_gem_create_ioctl(struct drm_device *dev, void *data, + vm = xe_vm_lookup(xef, args->vm_id); + if (XE_IOCTL_DBG(xe, !vm)) + return -ENOENT; ++ } ++ ++retry: ++ if (vm) { + err = xe_vm_lock(vm, true); + if (err) + goto out_vm; +@@ -2227,6 +2232,8 @@ int xe_gem_create_ioctl(struct drm_device *dev, void *data, + + if (IS_ERR(bo)) { + err = PTR_ERR(bo); ++ if (xe_vm_validate_should_retry(NULL, err, &end)) ++ goto retry; + goto out_vm; + } + +-- +2.39.5 + diff --git a/queue-6.14/drm-xe-sa-always-call-drm_suballoc_manager_fini.patch b/queue-6.14/drm-xe-sa-always-call-drm_suballoc_manager_fini.patch new file mode 100644 index 0000000000..01fdfa8f9f --- /dev/null +++ b/queue-6.14/drm-xe-sa-always-call-drm_suballoc_manager_fini.patch @@ -0,0 +1,51 @@ +From 6b10d835d233cc7310b4514c8e11938fa2d3387e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 20 Dec 2024 20:41:54 +0100 +Subject: drm/xe/sa: Always call drm_suballoc_manager_fini() + +From: Michal Wajdeczko + +[ Upstream commit 9cd3f4efc870463f17f6c29114c61fb6bfcaa291 ] + +After successful call to drm_suballoc_manager_init() we should +make sure to call drm_suballoc_manager_fini() as it may include +some cleanup code even if we didn't start using it for real. + +As we can abort init() early due to kvzalloc() failure, we should +either explicitly call drm_suballoc_manager_fini() or, even better, +postpone drm_suballoc_manager_init() once we finish all other +preparation steps, so we can rely on fini() that will do cleanup. + +Signed-off-by: Michal Wajdeczko +Cc: Matthew Brost +Reviewed-by: Matthew Brost +Link: https://patchwork.freedesktop.org/patch/msgid/20241220194205.995-2-michal.wajdeczko@intel.com +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/xe/xe_sa.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/drivers/gpu/drm/xe/xe_sa.c b/drivers/gpu/drm/xe/xe_sa.c +index e055bed7ae555..4e7aba445ebc8 100644 +--- a/drivers/gpu/drm/xe/xe_sa.c ++++ b/drivers/gpu/drm/xe/xe_sa.c +@@ -57,8 +57,6 @@ struct xe_sa_manager *xe_sa_bo_manager_init(struct xe_tile *tile, u32 size, u32 + } + sa_manager->bo = bo; + sa_manager->is_iomem = bo->vmap.is_iomem; +- +- drm_suballoc_manager_init(&sa_manager->base, managed_size, align); + sa_manager->gpu_addr = xe_bo_ggtt_addr(bo); + + if (bo->vmap.is_iomem) { +@@ -72,6 +70,7 @@ struct xe_sa_manager *xe_sa_bo_manager_init(struct xe_tile *tile, u32 size, u32 + memset(sa_manager->cpu_ptr, 0, bo->ttm.base.size); + } + ++ drm_suballoc_manager_init(&sa_manager->base, managed_size, align); + ret = drmm_add_action_or_reset(&xe->drm, xe_sa_bo_manager_fini, + sa_manager); + if (ret) +-- +2.39.5 + diff --git a/queue-6.14/drm-xe-stop-ignoring-errors-from-xe_ttm_stolen_mgr_i.patch b/queue-6.14/drm-xe-stop-ignoring-errors-from-xe_ttm_stolen_mgr_i.patch new file mode 100644 index 0000000000..802741a7c6 --- /dev/null +++ b/queue-6.14/drm-xe-stop-ignoring-errors-from-xe_ttm_stolen_mgr_i.patch @@ -0,0 +1,108 @@ +From b746540489d60b19c998113ff8867db61ff0e3bb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 13 Feb 2025 11:29:01 -0800 +Subject: drm/xe: Stop ignoring errors from xe_ttm_stolen_mgr_init() + +From: Lucas De Marchi + +[ Upstream commit ff57025c358603555f1e0ae0d50282a460433594 ] + +Make sure to differentiate normal behavior, e.g. there's no stolen, from +allocation errors or failure to initialize lower layers. + +Reviewed-by: Francois Dugast +Reviewed-by: Himal Prasad Ghimiray +Link: https://patchwork.freedesktop.org/patch/msgid/20250213192909.996148-5-lucas.demarchi@intel.com +Signed-off-by: Lucas De Marchi +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/xe/xe_device.c | 4 +++- + drivers/gpu/drm/xe/xe_ttm_stolen_mgr.c | 17 +++++++++-------- + drivers/gpu/drm/xe/xe_ttm_stolen_mgr.h | 2 +- + 3 files changed, 13 insertions(+), 10 deletions(-) + +diff --git a/drivers/gpu/drm/xe/xe_device.c b/drivers/gpu/drm/xe/xe_device.c +index 4e1839b483a00..e22f29ac96631 100644 +--- a/drivers/gpu/drm/xe/xe_device.c ++++ b/drivers/gpu/drm/xe/xe_device.c +@@ -722,7 +722,9 @@ int xe_device_probe(struct xe_device *xe) + } + + /* Allocate and map stolen after potential VRAM resize */ +- xe_ttm_stolen_mgr_init(xe); ++ err = xe_ttm_stolen_mgr_init(xe); ++ if (err) ++ return err; + + /* + * Now that GT is initialized (TTM in particular), +diff --git a/drivers/gpu/drm/xe/xe_ttm_stolen_mgr.c b/drivers/gpu/drm/xe/xe_ttm_stolen_mgr.c +index d414421f8c131..d9c9d2547aadf 100644 +--- a/drivers/gpu/drm/xe/xe_ttm_stolen_mgr.c ++++ b/drivers/gpu/drm/xe/xe_ttm_stolen_mgr.c +@@ -207,17 +207,16 @@ static u64 detect_stolen(struct xe_device *xe, struct xe_ttm_stolen_mgr *mgr) + #endif + } + +-void xe_ttm_stolen_mgr_init(struct xe_device *xe) ++int xe_ttm_stolen_mgr_init(struct xe_device *xe) + { +- struct xe_ttm_stolen_mgr *mgr = drmm_kzalloc(&xe->drm, sizeof(*mgr), GFP_KERNEL); + struct pci_dev *pdev = to_pci_dev(xe->drm.dev); ++ struct xe_ttm_stolen_mgr *mgr; + u64 stolen_size, io_size; + int err; + +- if (!mgr) { +- drm_dbg_kms(&xe->drm, "Stolen mgr init failed\n"); +- return; +- } ++ mgr = drmm_kzalloc(&xe->drm, sizeof(*mgr), GFP_KERNEL); ++ if (!mgr) ++ return -ENOMEM; + + if (IS_SRIOV_VF(xe)) + stolen_size = 0; +@@ -230,7 +229,7 @@ void xe_ttm_stolen_mgr_init(struct xe_device *xe) + + if (!stolen_size) { + drm_dbg_kms(&xe->drm, "No stolen memory support\n"); +- return; ++ return 0; + } + + /* +@@ -246,7 +245,7 @@ void xe_ttm_stolen_mgr_init(struct xe_device *xe) + io_size, PAGE_SIZE); + if (err) { + drm_dbg_kms(&xe->drm, "Stolen mgr init failed: %i\n", err); +- return; ++ return err; + } + + drm_dbg_kms(&xe->drm, "Initialized stolen memory support with %llu bytes\n", +@@ -254,6 +253,8 @@ void xe_ttm_stolen_mgr_init(struct xe_device *xe) + + if (io_size) + mgr->mapping = devm_ioremap_wc(&pdev->dev, mgr->io_base, io_size); ++ ++ return 0; + } + + u64 xe_ttm_stolen_io_offset(struct xe_bo *bo, u32 offset) +diff --git a/drivers/gpu/drm/xe/xe_ttm_stolen_mgr.h b/drivers/gpu/drm/xe/xe_ttm_stolen_mgr.h +index 1777245ff8101..8e877d1e839bd 100644 +--- a/drivers/gpu/drm/xe/xe_ttm_stolen_mgr.h ++++ b/drivers/gpu/drm/xe/xe_ttm_stolen_mgr.h +@@ -12,7 +12,7 @@ struct ttm_resource; + struct xe_bo; + struct xe_device; + +-void xe_ttm_stolen_mgr_init(struct xe_device *xe); ++int xe_ttm_stolen_mgr_init(struct xe_device *xe); + int xe_ttm_stolen_io_mem_reserve(struct xe_device *xe, struct ttm_resource *mem); + bool xe_ttm_stolen_cpu_access_needs_ggtt(struct xe_device *xe); + u64 xe_ttm_stolen_io_offset(struct xe_bo *bo, u32 offset); +-- +2.39.5 + diff --git a/queue-6.14/drm-xe-vf-perform-early-gt-mmio-initialization-to-re.patch b/queue-6.14/drm-xe-vf-perform-early-gt-mmio-initialization-to-re.patch new file mode 100644 index 0000000000..090df54e82 --- /dev/null +++ b/queue-6.14/drm-xe-vf-perform-early-gt-mmio-initialization-to-re.patch @@ -0,0 +1,53 @@ +From e19a89aafc30e1f1fa633b9da4d0ca620f496ce9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 14 Jan 2025 22:13:47 +0100 +Subject: drm/xe/vf: Perform early GT MMIO initialization to read GMDID +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Michal Wajdeczko + +[ Upstream commit 13265fe7426ec9ba5aa86baab913417ca361e8a4 ] + +VFs need to communicate with the GuC to obtain the GMDID value +and existing GuC functions used for that assume that the GT has +it's MMIO members already setup. However, due to recent refactoring +the gt->mmio is initialized later, and any attempt by the VF to use +xe_mmio_read|write() from GuC functions will lead to NPD crash due +to unset MMIO register address: + +[] xe 0000:00:02.1: [drm] Running in SR-IOV VF mode +[] xe 0000:00:02.1: [drm] GT0: sending H2G MMIO 0x5507 +[] BUG: unable to handle page fault for address: 0000000000190240 + +Since we are already tweaking the id and type of the primary GT to +mimic it's a Media GT before initializing the GuC communication, +we can also call xe_gt_mmio_init() to perform early setup of the +gt->mmio which will make those GuC functions work again. + +Signed-off-by: Michal Wajdeczko +Cc: Matt Roper +Cc: Piotr Piórkowski +Reviewed-by: Piotr Piórkowski +Link: https://patchwork.freedesktop.org/patch/msgid/20250114211347.1083-1-michal.wajdeczko@intel.com +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/xe/xe_pci.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/gpu/drm/xe/xe_pci.c b/drivers/gpu/drm/xe/xe_pci.c +index 9b8813a518d72..d92b2e5885b98 100644 +--- a/drivers/gpu/drm/xe/xe_pci.c ++++ b/drivers/gpu/drm/xe/xe_pci.c +@@ -490,6 +490,7 @@ static void read_gmdid(struct xe_device *xe, enum xe_gmdid_type type, u32 *ver, + gt->info.type = XE_GT_TYPE_MAIN; + } + ++ xe_gt_mmio_init(gt); + xe_guc_comm_init_early(>->uc.guc); + + /* Don't bother with GMDID if failed to negotiate the GuC ABI */ +-- +2.39.5 + diff --git a/queue-6.14/drm-xe-vf-retry-sending-mmio-request-to-guc-on-timeo.patch b/queue-6.14/drm-xe-vf-retry-sending-mmio-request-to-guc-on-timeo.patch new file mode 100644 index 0000000000..8b84400a9b --- /dev/null +++ b/queue-6.14/drm-xe-vf-retry-sending-mmio-request-to-guc-on-timeo.patch @@ -0,0 +1,64 @@ +From 19a2af81605a205be86b6238991ec83658e70630 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 24 Feb 2025 15:58:07 +0530 +Subject: drm/xe/vf: Retry sending MMIO request to GUC on timeout error +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Satyanarayana K V P + +[ Upstream commit ba757a65d2a28d46a8ccf50538f4f05036983f1b ] + +Add support to allow retrying the sending of MMIO requests +from the VF to the GUC in the event of an error. During the +suspend/resume process, VFs begin resuming only after the PF has +resumed. Although the PF resumes, the GUC reset and provisioning +occur later in a separate worker process. + +When there are a large number of VFs, some may attempt to resume +before the PF has completed its provisioning. Therefore, if a +MMIO request from a VF fails during this period, we will retry +sending the request up to GUC_RESET_VF_STATE_RETRY_MAX times, +which is set to a maximum of 10 attempts. + +Signed-off-by: Satyanarayana K V P +Cc: Michał Wajdeczko +Cc: Michał Winiarski +Cc: Piotr Piórkowski +Reviewed-by: Piotr Piorkowski +Signed-off-by: Michal Wajdeczko +Link: https://patchwork.freedesktop.org/patch/msgid/20250224102807.11065-3-satyanarayana.k.v.p@intel.com +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/xe/xe_gt_sriov_vf.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_vf.c b/drivers/gpu/drm/xe/xe_gt_sriov_vf.c +index 9c30cbd9af6e1..1c764f200b2a5 100644 +--- a/drivers/gpu/drm/xe/xe_gt_sriov_vf.c ++++ b/drivers/gpu/drm/xe/xe_gt_sriov_vf.c +@@ -47,12 +47,19 @@ static int guc_action_vf_reset(struct xe_guc *guc) + return ret > 0 ? -EPROTO : ret; + } + ++#define GUC_RESET_VF_STATE_RETRY_MAX 10 + static int vf_reset_guc_state(struct xe_gt *gt) + { ++ unsigned int retry = GUC_RESET_VF_STATE_RETRY_MAX; + struct xe_guc *guc = >->uc.guc; + int err; + +- err = guc_action_vf_reset(guc); ++ do { ++ err = guc_action_vf_reset(guc); ++ if (!err || err != -ETIMEDOUT) ++ break; ++ } while (--retry); ++ + if (unlikely(err)) + xe_gt_sriov_err(gt, "Failed to reset GuC state (%pe)\n", ERR_PTR(err)); + return err; +-- +2.39.5 + diff --git a/queue-6.14/drm-xe-xe_gen_wa_oob-replace-program_invocation_shor.patch b/queue-6.14/drm-xe-xe_gen_wa_oob-replace-program_invocation_shor.patch new file mode 100644 index 0000000000..24f6f09dd2 --- /dev/null +++ b/queue-6.14/drm-xe-xe_gen_wa_oob-replace-program_invocation_shor.patch @@ -0,0 +1,58 @@ +From 19921603bb28385398066b66b2c20fda44780624 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 24 Feb 2025 07:23:13 +0100 +Subject: drm/xe: xe_gen_wa_oob: replace program_invocation_short_name + +From: Daniel Gomez + +[ Upstream commit 89eb42b5539f6ae6a0cabcb39e5b6fcc83c106a1 ] + +program_invocation_short_name may not be available in other systems. +Instead, replace it with the argv[0] to pass the executable name. + +Fixes build error when program_invocation_short_name is not available: + +drivers/gpu/drm/xe/xe_gen_wa_oob.c:34:3: error: use of +undeclared identifier 'program_invocation_short_name' 34 | +program_invocation_short_name); | ^ 1 error +generated. + +Suggested-by: Masahiro Yamada +Signed-off-by: Daniel Gomez +Reviewed-by: Lucas De Marchi +Link: https://patchwork.freedesktop.org/patch/msgid/20250224-macos-build-support-xe-v3-1-d2c9ed3a27cc@samsung.com +Signed-off-by: Lucas De Marchi +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/xe/xe_gen_wa_oob.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/gpu/drm/xe/xe_gen_wa_oob.c b/drivers/gpu/drm/xe/xe_gen_wa_oob.c +index 904cf47925aa1..ed9183599e31c 100644 +--- a/drivers/gpu/drm/xe/xe_gen_wa_oob.c ++++ b/drivers/gpu/drm/xe/xe_gen_wa_oob.c +@@ -28,10 +28,10 @@ + "\n" \ + "#endif\n" + +-static void print_usage(FILE *f) ++static void print_usage(FILE *f, const char *progname) + { + fprintf(f, "usage: %s \n", +- program_invocation_short_name); ++ progname); + } + + static void print_parse_error(const char *err_msg, const char *line, +@@ -144,7 +144,7 @@ int main(int argc, const char *argv[]) + + if (argc < 3) { + fprintf(stderr, "ERROR: wrong arguments\n"); +- print_usage(stderr); ++ print_usage(stderr, argv[0]); + return 1; + } + +-- +2.39.5 + diff --git a/queue-6.14/edac-ie31200-work-around-false-positive-build-warnin.patch b/queue-6.14/edac-ie31200-work-around-false-positive-build-warnin.patch new file mode 100644 index 0000000000..31c82609b0 --- /dev/null +++ b/queue-6.14/edac-ie31200-work-around-false-positive-build-warnin.patch @@ -0,0 +1,105 @@ +From f0e7dc7ec7eab1400ac7d1506c58cdd9a199ecbf Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 22 Jan 2025 07:50:26 +0100 +Subject: EDAC/ie31200: work around false positive build warning + +From: Arnd Bergmann + +[ Upstream commit c29dfd661fe2f8d1b48c7f00590929c04b25bf40 ] + +gcc-14 produces a bogus warning in some configurations: + +drivers/edac/ie31200_edac.c: In function 'ie31200_probe1.isra': +drivers/edac/ie31200_edac.c:412:26: error: 'dimm_info' is used uninitialized [-Werror=uninitialized] + 412 | struct dimm_data dimm_info[IE31200_CHANNELS][IE31200_DIMMS_PER_CHANNEL]; + | ^~~~~~~~~ +drivers/edac/ie31200_edac.c:412:26: note: 'dimm_info' declared here + 412 | struct dimm_data dimm_info[IE31200_CHANNELS][IE31200_DIMMS_PER_CHANNEL]; + | ^~~~~~~~~ + +I don't see any way the unintialized access could really happen here, +but I can see why the compiler gets confused by the two loops. + +Instead, rework the two nested loops to only read the addr_decode +registers and then keep only one instance of the dimm info structure. + +[Tony: Qiuxu pointed out that the "populate DIMM info" comment was left +behind in the refactor and suggested moving it. I deleted the comment +as unnecessry in front os a call to populate_dimm_info(). That seems +pretty self-describing.] + +Signed-off-by: Arnd Bergmann +Acked-by: Jason Baron +Signed-off-by: Tony Luck +Link: https://lore.kernel.org/all/20250122065031.1321015-1-arnd@kernel.org +Signed-off-by: Sasha Levin +--- + drivers/edac/ie31200_edac.c | 28 +++++++++++++--------------- + 1 file changed, 13 insertions(+), 15 deletions(-) + +diff --git a/drivers/edac/ie31200_edac.c b/drivers/edac/ie31200_edac.c +index 9b02a6b43ab58..a8dd55ec52cea 100644 +--- a/drivers/edac/ie31200_edac.c ++++ b/drivers/edac/ie31200_edac.c +@@ -408,10 +408,9 @@ static int ie31200_probe1(struct pci_dev *pdev, int dev_idx) + int i, j, ret; + struct mem_ctl_info *mci = NULL; + struct edac_mc_layer layers[2]; +- struct dimm_data dimm_info[IE31200_CHANNELS][IE31200_DIMMS_PER_CHANNEL]; + void __iomem *window; + struct ie31200_priv *priv; +- u32 addr_decode, mad_offset; ++ u32 addr_decode[IE31200_CHANNELS], mad_offset; + + /* + * Kaby Lake, Coffee Lake seem to work like Skylake. Please re-visit +@@ -469,19 +468,10 @@ static int ie31200_probe1(struct pci_dev *pdev, int dev_idx) + mad_offset = IE31200_MAD_DIMM_0_OFFSET; + } + +- /* populate DIMM info */ + for (i = 0; i < IE31200_CHANNELS; i++) { +- addr_decode = readl(window + mad_offset + ++ addr_decode[i] = readl(window + mad_offset + + (i * 4)); +- edac_dbg(0, "addr_decode: 0x%x\n", addr_decode); +- for (j = 0; j < IE31200_DIMMS_PER_CHANNEL; j++) { +- populate_dimm_info(&dimm_info[i][j], addr_decode, j, +- skl); +- edac_dbg(0, "size: 0x%x, rank: %d, width: %d\n", +- dimm_info[i][j].size, +- dimm_info[i][j].dual_rank, +- dimm_info[i][j].x16_width); +- } ++ edac_dbg(0, "addr_decode: 0x%x\n", addr_decode[i]); + } + + /* +@@ -492,14 +482,22 @@ static int ie31200_probe1(struct pci_dev *pdev, int dev_idx) + */ + for (i = 0; i < IE31200_DIMMS_PER_CHANNEL; i++) { + for (j = 0; j < IE31200_CHANNELS; j++) { ++ struct dimm_data dimm_info; + struct dimm_info *dimm; + unsigned long nr_pages; + +- nr_pages = IE31200_PAGES(dimm_info[j][i].size, skl); ++ populate_dimm_info(&dimm_info, addr_decode[j], i, ++ skl); ++ edac_dbg(0, "size: 0x%x, rank: %d, width: %d\n", ++ dimm_info.size, ++ dimm_info.dual_rank, ++ dimm_info.x16_width); ++ ++ nr_pages = IE31200_PAGES(dimm_info.size, skl); + if (nr_pages == 0) + continue; + +- if (dimm_info[j][i].dual_rank) { ++ if (dimm_info.dual_rank) { + nr_pages = nr_pages / 2; + dimm = edac_get_dimm(mci, (i * 2) + 1, j, 0); + dimm->nr_pages = nr_pages; +-- +2.39.5 + diff --git a/queue-6.14/eeprom-ee1004-check-chip-before-probing.patch b/queue-6.14/eeprom-ee1004-check-chip-before-probing.patch new file mode 100644 index 0000000000..714a79dfd5 --- /dev/null +++ b/queue-6.14/eeprom-ee1004-check-chip-before-probing.patch @@ -0,0 +1,38 @@ +From 97885b6a7468c514970a96ff7d37043664854ccd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 18 Feb 2025 16:09:59 -0600 +Subject: eeprom: ee1004: Check chip before probing + +From: Eddie James + +[ Upstream commit d9406677428e9234ea62bb2d2f5e996d1b777760 ] + +Like other eeprom drivers, check if the device is really there and +functional before probing. + +Signed-off-by: Eddie James +Link: https://lore.kernel.org/r/20250218220959.721698-1-eajames@linux.ibm.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/misc/eeprom/ee1004.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/drivers/misc/eeprom/ee1004.c b/drivers/misc/eeprom/ee1004.c +index 89224d4af4a20..e13f9fdd9d7b1 100644 +--- a/drivers/misc/eeprom/ee1004.c ++++ b/drivers/misc/eeprom/ee1004.c +@@ -304,6 +304,10 @@ static int ee1004_probe(struct i2c_client *client) + I2C_FUNC_SMBUS_BYTE | I2C_FUNC_SMBUS_READ_BYTE_DATA)) + return -EPFNOSUPPORT; + ++ err = i2c_smbus_read_byte(client); ++ if (err < 0) ++ return -ENODEV; ++ + mutex_lock(&ee1004_bus_lock); + + err = ee1004_init_bus_data(client); +-- +2.39.5 + diff --git a/queue-6.14/erofs-initialize-decompression-early.patch b/queue-6.14/erofs-initialize-decompression-early.patch new file mode 100644 index 0000000000..9e26e14e5b --- /dev/null +++ b/queue-6.14/erofs-initialize-decompression-early.patch @@ -0,0 +1,176 @@ +From 7259d62c9be0f64eebe0ded4a4de6c27353f2b23 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Mar 2025 13:48:40 +0800 +Subject: erofs: initialize decompression early + +From: Gao Xiang + +[ Upstream commit fe1e57d44d7f106df9048e815e4862cf63921220 ] + + - Rename erofs_init_managed_cache() to z_erofs_init_super(); + - Move the initialization of managed_pslots into z_erofs_init_super() too; + - Move z_erofs_init_super() and packed inode preparation upwards, before + the root inode initialization. + +Therefore, the root directory can also be compressible. + +Signed-off-by: Gao Xiang +Acked-by: Chao Yu +Link: https://lore.kernel.org/r/20250317054840.3483000-1-hsiangkao@linux.alibaba.com +Signed-off-by: Sasha Levin +--- + fs/erofs/internal.h | 4 ++-- + fs/erofs/super.c | 46 ++++++++++++++++++++++----------------------- + fs/erofs/zdata.c | 4 ++-- + 3 files changed, 26 insertions(+), 28 deletions(-) + +diff --git a/fs/erofs/internal.h b/fs/erofs/internal.h +index efd25f3101f1f..2b8d9a10f0026 100644 +--- a/fs/erofs/internal.h ++++ b/fs/erofs/internal.h +@@ -446,6 +446,7 @@ int __init erofs_init_shrinker(void); + void erofs_exit_shrinker(void); + int __init z_erofs_init_subsystem(void); + void z_erofs_exit_subsystem(void); ++int z_erofs_init_super(struct super_block *sb); + unsigned long z_erofs_shrink_scan(struct erofs_sb_info *sbi, + unsigned long nr_shrink); + int z_erofs_map_blocks_iter(struct inode *inode, struct erofs_map_blocks *map, +@@ -455,7 +456,6 @@ void z_erofs_put_gbuf(void *ptr); + int z_erofs_gbuf_growsize(unsigned int nrpages); + int __init z_erofs_gbuf_init(void); + void z_erofs_gbuf_exit(void); +-int erofs_init_managed_cache(struct super_block *sb); + int z_erofs_parse_cfgs(struct super_block *sb, struct erofs_super_block *dsb); + #else + static inline void erofs_shrinker_register(struct super_block *sb) {} +@@ -464,7 +464,7 @@ static inline int erofs_init_shrinker(void) { return 0; } + static inline void erofs_exit_shrinker(void) {} + static inline int z_erofs_init_subsystem(void) { return 0; } + static inline void z_erofs_exit_subsystem(void) {} +-static inline int erofs_init_managed_cache(struct super_block *sb) { return 0; } ++static inline int z_erofs_init_super(struct super_block *sb) { return 0; } + #endif /* !CONFIG_EROFS_FS_ZIP */ + + #ifdef CONFIG_EROFS_FS_BACKED_BY_FILE +diff --git a/fs/erofs/super.c b/fs/erofs/super.c +index 9f2bce5af9c83..b30125a2a5011 100644 +--- a/fs/erofs/super.c ++++ b/fs/erofs/super.c +@@ -631,9 +631,16 @@ static int erofs_fc_fill_super(struct super_block *sb, struct fs_context *fc) + else + sb->s_flags &= ~SB_POSIXACL; + +-#ifdef CONFIG_EROFS_FS_ZIP +- xa_init(&sbi->managed_pslots); +-#endif ++ err = z_erofs_init_super(sb); ++ if (err) ++ return err; ++ ++ if (erofs_sb_has_fragments(sbi) && sbi->packed_nid) { ++ inode = erofs_iget(sb, sbi->packed_nid); ++ if (IS_ERR(inode)) ++ return PTR_ERR(inode); ++ sbi->packed_inode = inode; ++ } + + inode = erofs_iget(sb, sbi->root_nid); + if (IS_ERR(inode)) +@@ -645,24 +652,11 @@ static int erofs_fc_fill_super(struct super_block *sb, struct fs_context *fc) + iput(inode); + return -EINVAL; + } +- + sb->s_root = d_make_root(inode); + if (!sb->s_root) + return -ENOMEM; + + erofs_shrinker_register(sb); +- if (erofs_sb_has_fragments(sbi) && sbi->packed_nid) { +- sbi->packed_inode = erofs_iget(sb, sbi->packed_nid); +- if (IS_ERR(sbi->packed_inode)) { +- err = PTR_ERR(sbi->packed_inode); +- sbi->packed_inode = NULL; +- return err; +- } +- } +- err = erofs_init_managed_cache(sb); +- if (err) +- return err; +- + err = erofs_xattr_prefixes_init(sb); + if (err) + return err; +@@ -798,6 +792,16 @@ static int erofs_init_fs_context(struct fs_context *fc) + return 0; + } + ++static void erofs_drop_internal_inodes(struct erofs_sb_info *sbi) ++{ ++ iput(sbi->packed_inode); ++ sbi->packed_inode = NULL; ++#ifdef CONFIG_EROFS_FS_ZIP ++ iput(sbi->managed_cache); ++ sbi->managed_cache = NULL; ++#endif ++} ++ + static void erofs_kill_sb(struct super_block *sb) + { + struct erofs_sb_info *sbi = EROFS_SB(sb); +@@ -807,6 +811,7 @@ static void erofs_kill_sb(struct super_block *sb) + kill_anon_super(sb); + else + kill_block_super(sb); ++ erofs_drop_internal_inodes(sbi); + fs_put_dax(sbi->dif0.dax_dev, NULL); + erofs_fscache_unregister_fs(sb); + erofs_sb_free(sbi); +@@ -817,17 +822,10 @@ static void erofs_put_super(struct super_block *sb) + { + struct erofs_sb_info *const sbi = EROFS_SB(sb); + +- DBG_BUGON(!sbi); +- + erofs_unregister_sysfs(sb); + erofs_shrinker_unregister(sb); + erofs_xattr_prefixes_cleanup(sb); +-#ifdef CONFIG_EROFS_FS_ZIP +- iput(sbi->managed_cache); +- sbi->managed_cache = NULL; +-#endif +- iput(sbi->packed_inode); +- sbi->packed_inode = NULL; ++ erofs_drop_internal_inodes(sbi); + erofs_free_dev_context(sbi->devs); + sbi->devs = NULL; + erofs_fscache_unregister_fs(sb); +diff --git a/fs/erofs/zdata.c b/fs/erofs/zdata.c +index 67acef591646c..87192635b2d20 100644 +--- a/fs/erofs/zdata.c ++++ b/fs/erofs/zdata.c +@@ -641,18 +641,18 @@ static const struct address_space_operations z_erofs_cache_aops = { + .invalidate_folio = z_erofs_cache_invalidate_folio, + }; + +-int erofs_init_managed_cache(struct super_block *sb) ++int z_erofs_init_super(struct super_block *sb) + { + struct inode *const inode = new_inode(sb); + + if (!inode) + return -ENOMEM; +- + set_nlink(inode, 1); + inode->i_size = OFFSET_MAX; + inode->i_mapping->a_ops = &z_erofs_cache_aops; + mapping_set_gfp_mask(inode->i_mapping, GFP_KERNEL); + EROFS_SB(sb)->managed_cache = inode; ++ xa_init(&EROFS_SB(sb)->managed_pslots); + return 0; + } + +-- +2.39.5 + diff --git a/queue-6.14/eth-fbnic-prepend-tsene-fw-fields-with-fbnic_fw.patch b/queue-6.14/eth-fbnic-prepend-tsene-fw-fields-with-fbnic_fw.patch new file mode 100644 index 0000000000..1b96be2054 --- /dev/null +++ b/queue-6.14/eth-fbnic-prepend-tsene-fw-fields-with-fbnic_fw.patch @@ -0,0 +1,87 @@ +From 291f1627c127c88531be87370456fcd9a509cc6d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 28 Feb 2025 11:15:26 -0800 +Subject: eth: fbnic: Prepend TSENE FW fields with FBNIC_FW + +From: Lee Trager + +[ Upstream commit 56bcc6ecff8fdc06258c637226986ed522027ca5 ] + +All other firmware fields are prepended with FBNIC_FW. Update TSENE fields +to follow the same format. + +Signed-off-by: Lee Trager +Link: https://patch.msgid.link/20250228191935.3953712-2-lee@trager.us +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/meta/fbnic/fbnic_fw.c | 16 ++++++++-------- + drivers/net/ethernet/meta/fbnic/fbnic_fw.h | 8 ++++---- + 2 files changed, 12 insertions(+), 12 deletions(-) + +diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_fw.c b/drivers/net/ethernet/meta/fbnic/fbnic_fw.c +index 9351a874689f8..cdd6c3a210944 100644 +--- a/drivers/net/ethernet/meta/fbnic/fbnic_fw.c ++++ b/drivers/net/ethernet/meta/fbnic/fbnic_fw.c +@@ -747,9 +747,9 @@ int fbnic_fw_xmit_tsene_read_msg(struct fbnic_dev *fbd, + } + + static const struct fbnic_tlv_index fbnic_tsene_read_resp_index[] = { +- FBNIC_TLV_ATTR_S32(FBNIC_TSENE_THERM), +- FBNIC_TLV_ATTR_S32(FBNIC_TSENE_VOLT), +- FBNIC_TLV_ATTR_S32(FBNIC_TSENE_ERROR), ++ FBNIC_TLV_ATTR_S32(FBNIC_FW_TSENE_THERM), ++ FBNIC_TLV_ATTR_S32(FBNIC_FW_TSENE_VOLT), ++ FBNIC_TLV_ATTR_S32(FBNIC_FW_TSENE_ERROR), + FBNIC_TLV_ATTR_LAST + }; + +@@ -766,21 +766,21 @@ static int fbnic_fw_parse_tsene_read_resp(void *opaque, + if (!cmpl_data) + return -EINVAL; + +- if (results[FBNIC_TSENE_ERROR]) { +- err = fbnic_tlv_attr_get_unsigned(results[FBNIC_TSENE_ERROR]); ++ if (results[FBNIC_FW_TSENE_ERROR]) { ++ err = fbnic_tlv_attr_get_unsigned(results[FBNIC_FW_TSENE_ERROR]); + if (err) + goto exit_complete; + } + +- if (!results[FBNIC_TSENE_THERM] || !results[FBNIC_TSENE_VOLT]) { ++ if (!results[FBNIC_FW_TSENE_THERM] || !results[FBNIC_FW_TSENE_VOLT]) { + err = -EINVAL; + goto exit_complete; + } + + cmpl_data->u.tsene.millidegrees = +- fbnic_tlv_attr_get_signed(results[FBNIC_TSENE_THERM]); ++ fbnic_tlv_attr_get_signed(results[FBNIC_FW_TSENE_THERM]); + cmpl_data->u.tsene.millivolts = +- fbnic_tlv_attr_get_signed(results[FBNIC_TSENE_VOLT]); ++ fbnic_tlv_attr_get_signed(results[FBNIC_FW_TSENE_VOLT]); + + exit_complete: + cmpl_data->result = err; +diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_fw.h b/drivers/net/ethernet/meta/fbnic/fbnic_fw.h +index fe68333d51b18..a3618e7826c25 100644 +--- a/drivers/net/ethernet/meta/fbnic/fbnic_fw.h ++++ b/drivers/net/ethernet/meta/fbnic/fbnic_fw.h +@@ -139,10 +139,10 @@ enum { + }; + + enum { +- FBNIC_TSENE_THERM = 0x0, +- FBNIC_TSENE_VOLT = 0x1, +- FBNIC_TSENE_ERROR = 0x2, +- FBNIC_TSENE_MSG_MAX ++ FBNIC_FW_TSENE_THERM = 0x0, ++ FBNIC_FW_TSENE_VOLT = 0x1, ++ FBNIC_FW_TSENE_ERROR = 0x2, ++ FBNIC_FW_TSENE_MSG_MAX + }; + + enum { +-- +2.39.5 + diff --git a/queue-6.14/eth-fbnic-set-iff_unicast_flt-to-avoid-enabling-prom.patch b/queue-6.14/eth-fbnic-set-iff_unicast_flt-to-avoid-enabling-prom.patch new file mode 100644 index 0000000000..9c516de5a4 --- /dev/null +++ b/queue-6.14/eth-fbnic-set-iff_unicast_flt-to-avoid-enabling-prom.patch @@ -0,0 +1,73 @@ +From 52853c978fa8eb9b9fea744ce3e6097fe6fbf110 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 3 Feb 2025 17:00:38 -0800 +Subject: eth: fbnic: set IFF_UNICAST_FLT to avoid enabling promiscuous mode + when adding unicast addrs + +From: Alexander Duyck + +[ Upstream commit 09717c28b76c30b1dc8c261c855ffb2406abab2e ] + +I realized when we were adding unicast addresses we were enabling +promiscuous mode. I did a bit of digging and realized we had overlooked +setting the driver private flag to indicate we supported unicast filtering. + +Example below shows the table with 00deadbeef01 as the main NIC address, +and 5 additional addresses in the 00deadbeefX0 format. + + # cat $dbgfs/mac_addr + Idx S TCAM Bitmap Addr/Mask + ---------------------------------- + 00 0 00000000,00000000 000000000000 + 000000000000 + 01 0 00000000,00000000 000000000000 + 000000000000 + 02 0 00000000,00000000 000000000000 + 000000000000 + ... + 24 0 00000000,00000000 000000000000 + 000000000000 + 25 1 00100000,00000000 00deadbeef50 + 000000000000 + 26 1 00100000,00000000 00deadbeef40 + 000000000000 + 27 1 00100000,00000000 00deadbeef30 + 000000000000 + 28 1 00100000,00000000 00deadbeef20 + 000000000000 + 29 1 00100000,00000000 00deadbeef10 + 000000000000 + 30 1 00100000,00000000 00deadbeef01 + 000000000000 + 31 0 00000000,00000000 000000000000 + 000000000000 + +Before rule 31 would be active. With this change it correctly sticks +to just the unicast filters. + +Signed-off-by: Alexander Duyck +Signed-off-by: Jakub Kicinski +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20250204010038.1404268-2-kuba@kernel.org +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/meta/fbnic/fbnic_netdev.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_netdev.c b/drivers/net/ethernet/meta/fbnic/fbnic_netdev.c +index 7a96b6ee773f3..1db57c42333ef 100644 +--- a/drivers/net/ethernet/meta/fbnic/fbnic_netdev.c ++++ b/drivers/net/ethernet/meta/fbnic/fbnic_netdev.c +@@ -628,6 +628,8 @@ struct net_device *fbnic_netdev_alloc(struct fbnic_dev *fbd) + fbnic_rss_key_fill(fbn->rss_key); + fbnic_rss_init_en_mask(fbn); + ++ netdev->priv_flags |= IFF_UNICAST_FLT; ++ + netdev->features |= + NETIF_F_RXHASH | + NETIF_F_SG | +-- +2.39.5 + diff --git a/queue-6.14/eth-mlx4-don-t-try-to-complete-xdp-frames-in-netpoll.patch b/queue-6.14/eth-mlx4-don-t-try-to-complete-xdp-frames-in-netpoll.patch new file mode 100644 index 0000000000..49577ffde5 --- /dev/null +++ b/queue-6.14/eth-mlx4-don-t-try-to-complete-xdp-frames-in-netpoll.patch @@ -0,0 +1,39 @@ +From f1e4ba993b2b455f55cab90f6a297ab6ae9baa28 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 12 Feb 2025 17:06:33 -0800 +Subject: eth: mlx4: don't try to complete XDP frames in netpoll + +From: Jakub Kicinski + +[ Upstream commit 8fdeafd66edaf420ea0063a1f13442fe3470fe70 ] + +mlx4 doesn't support ndo_xdp_xmit / XDP_REDIRECT and wasn't +using page pool until now, so it could run XDP completions +in netpoll (NAPI budget == 0) just fine. Page pool has calling +context requirements, make sure we don't try to call it from +what is potentially HW IRQ context. + +Reviewed-by: Tariq Toukan +Link: https://patch.msgid.link/20250213010635.1354034-3-kuba@kernel.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx4/en_tx.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/net/ethernet/mellanox/mlx4/en_tx.c b/drivers/net/ethernet/mellanox/mlx4/en_tx.c +index 1ddb11cb25f91..6e077d202827a 100644 +--- a/drivers/net/ethernet/mellanox/mlx4/en_tx.c ++++ b/drivers/net/ethernet/mellanox/mlx4/en_tx.c +@@ -450,6 +450,8 @@ int mlx4_en_process_tx_cq(struct net_device *dev, + + if (unlikely(!priv->port_up)) + return 0; ++ if (unlikely(!napi_budget) && cq->type == TX_XDP) ++ return 0; + + netdev_txq_bql_complete_prefetchw(ring->tx_queue); + +-- +2.39.5 + diff --git a/queue-6.14/exfat-call-bh_read-in-get_block-only-when-necessary.patch b/queue-6.14/exfat-call-bh_read-in-get_block-only-when-necessary.patch new file mode 100644 index 0000000000..d467024872 --- /dev/null +++ b/queue-6.14/exfat-call-bh_read-in-get_block-only-when-necessary.patch @@ -0,0 +1,222 @@ +From 663b648c046ac206bbfe2de4bf71ac4faff5b33f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 27 Mar 2025 00:01:16 +0900 +Subject: exfat: call bh_read in get_block only when necessary + +From: Sungjong Seo + +[ Upstream commit c73e680d1f84059e1b1ea82a537f6ccc1c563eb4 ] + +With commit 11a347fb6cef ("exfat: change to get file size from DataLength"), +exfat_get_block() can now handle valid_size. However, most partial +unwritten blocks that could be mapped with other blocks are being +inefficiently processed separately as individual blocks. + +Except for partial unwritten blocks that require independent processing, +let's handle them simply as before. + +Signed-off-by: Sungjong Seo +Reviewed-by: Yuezhang Mo +Signed-off-by: Namjae Jeon +Signed-off-by: Sasha Levin +--- + fs/exfat/inode.c | 159 +++++++++++++++++++++++------------------------ + 1 file changed, 77 insertions(+), 82 deletions(-) + +diff --git a/fs/exfat/inode.c b/fs/exfat/inode.c +index a23677de4544f..b22c02d6000f7 100644 +--- a/fs/exfat/inode.c ++++ b/fs/exfat/inode.c +@@ -274,9 +274,11 @@ static int exfat_get_block(struct inode *inode, sector_t iblock, + sector_t last_block; + sector_t phys = 0; + sector_t valid_blks; ++ loff_t i_size; + + mutex_lock(&sbi->s_lock); +- last_block = EXFAT_B_TO_BLK_ROUND_UP(i_size_read(inode), sb); ++ i_size = i_size_read(inode); ++ last_block = EXFAT_B_TO_BLK_ROUND_UP(i_size, sb); + if (iblock >= last_block && !create) + goto done; + +@@ -305,102 +307,95 @@ static int exfat_get_block(struct inode *inode, sector_t iblock, + if (buffer_delay(bh_result)) + clear_buffer_delay(bh_result); + +- if (create) { ++ /* ++ * In most cases, we just need to set bh_result to mapped, unmapped ++ * or new status as follows: ++ * 1. i_size == valid_size ++ * 2. write case (create == 1) ++ * 3. direct_read (!bh_result->b_folio) ++ * -> the unwritten part will be zeroed in exfat_direct_IO() ++ * ++ * Otherwise, in the case of buffered read, it is necessary to take ++ * care the last nested block if valid_size is not equal to i_size. ++ */ ++ if (i_size == ei->valid_size || create || !bh_result->b_folio) + valid_blks = EXFAT_B_TO_BLK_ROUND_UP(ei->valid_size, sb); ++ else ++ valid_blks = EXFAT_B_TO_BLK(ei->valid_size, sb); + +- if (iblock + max_blocks < valid_blks) { +- /* The range has been written, map it */ +- goto done; +- } else if (iblock < valid_blks) { +- /* +- * The range has been partially written, +- * map the written part. +- */ +- max_blocks = valid_blks - iblock; +- goto done; +- } ++ /* The range has been fully written, map it */ ++ if (iblock + max_blocks < valid_blks) ++ goto done; + +- /* The area has not been written, map and mark as new. */ +- set_buffer_new(bh_result); ++ /* The range has been partially written, map the written part */ ++ if (iblock < valid_blks) { ++ max_blocks = valid_blks - iblock; ++ goto done; ++ } + ++ /* The area has not been written, map and mark as new for create case */ ++ if (create) { ++ set_buffer_new(bh_result); + ei->valid_size = EXFAT_BLK_TO_B(iblock + max_blocks, sb); + mark_inode_dirty(inode); +- } else { +- valid_blks = EXFAT_B_TO_BLK(ei->valid_size, sb); ++ goto done; ++ } + +- if (iblock + max_blocks < valid_blks) { +- /* The range has been written, map it */ +- goto done; +- } else if (iblock < valid_blks) { +- /* +- * The area has been partially written, +- * map the written part. +- */ +- max_blocks = valid_blks - iblock; ++ /* ++ * The area has just one block partially written. ++ * In that case, we should read and fill the unwritten part of ++ * a block with zero. ++ */ ++ if (bh_result->b_folio && iblock == valid_blks && ++ (ei->valid_size & (sb->s_blocksize - 1))) { ++ loff_t size, pos; ++ void *addr; ++ ++ max_blocks = 1; ++ ++ /* ++ * No buffer_head is allocated. ++ * (1) bmap: It's enough to set blocknr without I/O. ++ * (2) read: The unwritten part should be filled with zero. ++ * If a folio does not have any buffers, ++ * let's returns -EAGAIN to fallback to ++ * block_read_full_folio() for per-bh IO. ++ */ ++ if (!folio_buffers(bh_result->b_folio)) { ++ err = -EAGAIN; + goto done; +- } else if (iblock == valid_blks && +- (ei->valid_size & (sb->s_blocksize - 1))) { +- /* +- * The block has been partially written, +- * zero the unwritten part and map the block. +- */ +- loff_t size, pos; +- void *addr; +- +- max_blocks = 1; +- +- /* +- * For direct read, the unwritten part will be zeroed in +- * exfat_direct_IO() +- */ +- if (!bh_result->b_folio) +- goto done; +- +- /* +- * No buffer_head is allocated. +- * (1) bmap: It's enough to fill bh_result without I/O. +- * (2) read: The unwritten part should be filled with 0 +- * If a folio does not have any buffers, +- * let's returns -EAGAIN to fallback to +- * per-bh IO like block_read_full_folio(). +- */ +- if (!folio_buffers(bh_result->b_folio)) { +- err = -EAGAIN; +- goto done; +- } ++ } + +- pos = EXFAT_BLK_TO_B(iblock, sb); +- size = ei->valid_size - pos; +- addr = folio_address(bh_result->b_folio) + +- offset_in_folio(bh_result->b_folio, pos); ++ pos = EXFAT_BLK_TO_B(iblock, sb); ++ size = ei->valid_size - pos; ++ addr = folio_address(bh_result->b_folio) + ++ offset_in_folio(bh_result->b_folio, pos); + +- /* Check if bh->b_data points to proper addr in folio */ +- if (bh_result->b_data != addr) { +- exfat_fs_error_ratelimit(sb, ++ /* Check if bh->b_data points to proper addr in folio */ ++ if (bh_result->b_data != addr) { ++ exfat_fs_error_ratelimit(sb, + "b_data(%p) != folio_addr(%p)", + bh_result->b_data, addr); +- err = -EINVAL; +- goto done; +- } +- +- /* Read a block */ +- err = bh_read(bh_result, 0); +- if (err < 0) +- goto done; ++ err = -EINVAL; ++ goto done; ++ } + +- /* Zero unwritten part of a block */ +- memset(bh_result->b_data + size, 0, +- bh_result->b_size - size); ++ /* Read a block */ ++ err = bh_read(bh_result, 0); ++ if (err < 0) ++ goto done; + +- err = 0; +- } else { +- /* +- * The range has not been written, clear the mapped flag +- * to only zero the cache and do not read from disk. +- */ +- clear_buffer_mapped(bh_result); +- } ++ /* Zero unwritten part of a block */ ++ memset(bh_result->b_data + size, 0, bh_result->b_size - size); ++ err = 0; ++ goto done; + } ++ ++ /* ++ * The area has not been written, clear mapped for read/bmap cases. ++ * If so, it will be filled with zero without reading from disk. ++ */ ++ clear_buffer_mapped(bh_result); + done: + bh_result->b_size = EXFAT_BLK_TO_B(max_blocks, sb); + if (err < 0) +-- +2.39.5 + diff --git a/queue-6.14/exit-fix-the-usage-of-delay_group_leader-exit_code-i.patch b/queue-6.14/exit-fix-the-usage-of-delay_group_leader-exit_code-i.patch new file mode 100644 index 0000000000..ae6aac555a --- /dev/null +++ b/queue-6.14/exit-fix-the-usage-of-delay_group_leader-exit_code-i.patch @@ -0,0 +1,52 @@ +From 909fe6c95cb78648e9b6398dbb8c3bba92459c46 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 24 Mar 2025 18:19:41 +0100 +Subject: exit: fix the usage of delay_group_leader->exit_code in + do_notify_parent() and pidfs_exit() + +From: Oleg Nesterov + +[ Upstream commit 9133607de37a4887c6f89ed937176a0a0c1ebb17 ] + +Consider a process with a group leader L and a sub-thread T. +L does sys_exit(1), then T does sys_exit_group(2). + +In this case wait_task_zombie(L) will notice SIGNAL_GROUP_EXIT and use +L->signal->group_exit_code, this is correct. + +But, before that, do_notify_parent(L) called by release_task(T) will use +L->exit_code != L->signal->group_exit_code, and this is not consistent. +We don't really care, I think that nobody relies on the info which comes +with SIGCHLD, if nothing else SIGCHLD < SIGRTMIN can be queued only once. + +But pidfs_exit() is more problematic, I think pidfs_exit_info->exit_code +should report ->group_exit_code in this case, just like wait_task_zombie(). + +TODO: with this change we can hopefully cleanup (or may be even kill) the +similar SIGNAL_GROUP_EXIT checks, at least in wait_task_zombie(). + +Signed-off-by: Oleg Nesterov +Link: https://lore.kernel.org/r/20250324171941.GA13114@redhat.com +Signed-off-by: Christian Brauner +Signed-off-by: Sasha Levin +--- + kernel/exit.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/kernel/exit.c b/kernel/exit.c +index 3485e5fc499e4..6bb59b16e33e1 100644 +--- a/kernel/exit.c ++++ b/kernel/exit.c +@@ -265,6 +265,9 @@ void release_task(struct task_struct *p) + leader = p->group_leader; + if (leader != p && thread_group_empty(leader) + && leader->exit_state == EXIT_ZOMBIE) { ++ /* for pidfs_exit() and do_notify_parent() */ ++ if (leader->signal->flags & SIGNAL_GROUP_EXIT) ++ leader->exit_code = leader->signal->group_exit_code; + /* + * If we were the last child thread and the leader has + * exited already, and the leader's parent ignores SIGCHLD, +-- +2.39.5 + diff --git a/queue-6.14/ext4-do-not-convert-the-unwritten-extents-if-data-wr.patch b/queue-6.14/ext4-do-not-convert-the-unwritten-extents-if-data-wr.patch new file mode 100644 index 0000000000..3dce0caa00 --- /dev/null +++ b/queue-6.14/ext4-do-not-convert-the-unwritten-extents-if-data-wr.patch @@ -0,0 +1,90 @@ +From 4e2defa15845ab8406b3214e4c1ffb2a5a7a4aff Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 22 Jan 2025 19:05:26 +0800 +Subject: ext4: do not convert the unwritten extents if data writeback fails + +From: Baokun Li + +[ Upstream commit e856f93e0fb249955f7d5efb18fe20500a9ccc6d ] + +When dioread_nolock is turned on (the default), it will convert unwritten +extents to written at ext4_end_io_end(), even if the data writeback fails. + +It leads to the possibility that stale data may be exposed when the +physical block corresponding to the file data is read-only (i.e., writes +return -EIO, but reads are normal). + +Therefore a new ext4_io_end->flags EXT4_IO_END_FAILED is added, which +indicates that some bio write-back failed in the current ext4_io_end. +When this flag is set, the unwritten to written conversion is no longer +performed. Users can read the data normally until the caches are dropped, +after that, the failed extents can only be read to all 0. + +Signed-off-by: Baokun Li +Reviewed-by: Jan Kara +Reviewed-by: Zhang Yi +Link: https://patch.msgid.link/20250122110533.4116662-3-libaokun@huaweicloud.com +Signed-off-by: Theodore Ts'o +Signed-off-by: Sasha Levin +--- + fs/ext4/ext4.h | 3 ++- + fs/ext4/page-io.c | 16 ++++++++++++++-- + 2 files changed, 16 insertions(+), 3 deletions(-) + +diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h +index df30d9f235123..d4d285d999311 100644 +--- a/fs/ext4/ext4.h ++++ b/fs/ext4/ext4.h +@@ -278,7 +278,8 @@ struct ext4_system_blocks { + /* + * Flags for ext4_io_end->flags + */ +-#define EXT4_IO_END_UNWRITTEN 0x0001 ++#define EXT4_IO_END_UNWRITTEN 0x0001 ++#define EXT4_IO_END_FAILED 0x0002 + + struct ext4_io_end_vec { + struct list_head list; /* list of io_end_vec */ +diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c +index 69b8a7221a2b1..f041a5d93716f 100644 +--- a/fs/ext4/page-io.c ++++ b/fs/ext4/page-io.c +@@ -181,14 +181,25 @@ static int ext4_end_io_end(ext4_io_end_t *io_end) + "list->prev 0x%p\n", + io_end, inode->i_ino, io_end->list.next, io_end->list.prev); + +- io_end->handle = NULL; /* Following call will use up the handle */ +- ret = ext4_convert_unwritten_io_end_vec(handle, io_end); ++ /* ++ * Do not convert the unwritten extents if data writeback fails, ++ * or stale data may be exposed. ++ */ ++ io_end->handle = NULL; /* Following call will use up the handle */ ++ if (unlikely(io_end->flag & EXT4_IO_END_FAILED)) { ++ ret = -EIO; ++ if (handle) ++ jbd2_journal_free_reserved(handle); ++ } else { ++ ret = ext4_convert_unwritten_io_end_vec(handle, io_end); ++ } + if (ret < 0 && !ext4_forced_shutdown(inode->i_sb)) { + ext4_msg(inode->i_sb, KERN_EMERG, + "failed to convert unwritten extents to written " + "extents -- potential data loss! " + "(inode %lu, error %d)", inode->i_ino, ret); + } ++ + ext4_clear_io_unwritten_flag(io_end); + ext4_release_io_end(io_end); + return ret; +@@ -344,6 +355,7 @@ static void ext4_end_bio(struct bio *bio) + bio->bi_status, inode->i_ino, + (unsigned long long) + bi_sector >> (inode->i_blkbits - 9)); ++ io_end->flag |= EXT4_IO_END_FAILED; + mapping_set_error(inode->i_mapping, + blk_status_to_errno(bio->bi_status)); + } +-- +2.39.5 + diff --git a/queue-6.14/ext4-don-t-write-back-data-before-punch-hole-in-nojo.patch b/queue-6.14/ext4-don-t-write-back-data-before-punch-hole-in-nojo.patch new file mode 100644 index 0000000000..588731e09a --- /dev/null +++ b/queue-6.14/ext4-don-t-write-back-data-before-punch-hole-in-nojo.patch @@ -0,0 +1,71 @@ +From db753dabca4329d99109850965c2b3a1e207cce5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 20 Dec 2024 09:16:30 +0800 +Subject: ext4: don't write back data before punch hole in nojournal mode + +From: Zhang Yi + +[ Upstream commit 43d0105e2c7523cc6b14cad65e2044e829c0a07a ] + +There is no need to write back all data before punching a hole in +non-journaled mode since it will be dropped soon after removing space. +Therefore, the call to filemap_write_and_wait_range() can be eliminated. +Besides, similar to ext4_zero_range(), we must address the case of +partially punched folios when block size < page size. It is essential to +remove writable userspace mappings to ensure that the folio can be +faulted again during subsequent mmap write access. + +In journaled mode, we need to write dirty pages out before discarding +page cache in case of crash before committing the freeing data +transaction, which could expose old, stale data, even if synchronization +has been performed. + +Signed-off-by: Zhang Yi +Reviewed-by: Jan Kara +Reviewed-by: Ojaswin Mujoo +Link: https://patch.msgid.link/20241220011637.1157197-4-yi.zhang@huaweicloud.com +Signed-off-by: Theodore Ts'o +Signed-off-by: Sasha Levin +--- + fs/ext4/inode.c | 18 +++++------------- + 1 file changed, 5 insertions(+), 13 deletions(-) + +diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c +index 74c5e2a381a6b..377fec39b24be 100644 +--- a/fs/ext4/inode.c ++++ b/fs/ext4/inode.c +@@ -3957,17 +3957,6 @@ int ext4_punch_hole(struct file *file, loff_t offset, loff_t length) + + trace_ext4_punch_hole(inode, offset, length, 0); + +- /* +- * Write out all dirty pages to avoid race conditions +- * Then release them. +- */ +- if (mapping_tagged(mapping, PAGECACHE_TAG_DIRTY)) { +- ret = filemap_write_and_wait_range(mapping, offset, +- offset + length - 1); +- if (ret) +- return ret; +- } +- + inode_lock(inode); + + /* No need to punch hole beyond i_size */ +@@ -4029,8 +4018,11 @@ int ext4_punch_hole(struct file *file, loff_t offset, loff_t length) + ret = ext4_update_disksize_before_punch(inode, offset, length); + if (ret) + goto out_dio; +- truncate_pagecache_range(inode, first_block_offset, +- last_block_offset); ++ ++ ret = ext4_truncate_page_cache_block_range(inode, ++ first_block_offset, last_block_offset + 1); ++ if (ret) ++ goto out_dio; + } + + if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)) +-- +2.39.5 + diff --git a/queue-6.14/ext4-on-a-remount-only-log-the-ro-or-r-w-state-when-.patch b/queue-6.14/ext4-on-a-remount-only-log-the-ro-or-r-w-state-when-.patch new file mode 100644 index 0000000000..23581a4b47 --- /dev/null +++ b/queue-6.14/ext4-on-a-remount-only-log-the-ro-or-r-w-state-when-.patch @@ -0,0 +1,56 @@ +From b62f7d64d57f729188d8b4e99f57be318d0bed5c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 19 Mar 2025 11:10:11 -0600 +Subject: ext4: on a remount, only log the ro or r/w state when it has changed + +From: Nicolas Bretz + +[ Upstream commit d7b0befd09320e3356a75cb96541c030515e7f5f ] + +A user complained that a message such as: + +EXT4-fs (nvme0n1p3): re-mounted UUID ro. Quota mode: none. + +implied that the file system was previously mounted read/write and was +now remounted read-only, when it could have been some other mount +state that had changed by the "mount -o remount" operation. Fix this +by only logging "ro"or "r/w" when it has changed. + +https://bugzilla.kernel.org/show_bug.cgi?id=219132 + +Signed-off-by: Nicolas Bretz +Link: https://patch.msgid.link/20250319171011.8372-1-bretznic@gmail.com +Signed-off-by: Theodore Ts'o +Signed-off-by: Sasha Levin +--- + fs/ext4/super.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/fs/ext4/super.c b/fs/ext4/super.c +index 528979de0f7c1..b4a02be2eacf6 100644 +--- a/fs/ext4/super.c ++++ b/fs/ext4/super.c +@@ -6776,6 +6776,7 @@ static int ext4_reconfigure(struct fs_context *fc) + { + struct super_block *sb = fc->root->d_sb; + int ret; ++ bool old_ro = sb_rdonly(sb); + + fc->s_fs_info = EXT4_SB(sb); + +@@ -6787,9 +6788,9 @@ static int ext4_reconfigure(struct fs_context *fc) + if (ret < 0) + return ret; + +- ext4_msg(sb, KERN_INFO, "re-mounted %pU %s. Quota mode: %s.", +- &sb->s_uuid, sb_rdonly(sb) ? "ro" : "r/w", +- ext4_quota_mode(sb)); ++ ext4_msg(sb, KERN_INFO, "re-mounted %pU%s.", ++ &sb->s_uuid, ++ (old_ro != sb_rdonly(sb)) ? (sb_rdonly(sb) ? " ro" : " r/w") : ""); + + return 0; + } +-- +2.39.5 + diff --git a/queue-6.14/ext4-reject-the-data_err-abort-option-in-nojournal-m.patch b/queue-6.14/ext4-reject-the-data_err-abort-option-in-nojournal-m.patch new file mode 100644 index 0000000000..089d458a4c --- /dev/null +++ b/queue-6.14/ext4-reject-the-data_err-abort-option-in-nojournal-m.patch @@ -0,0 +1,56 @@ +From 8936a5df34cb3db706ccd0f8d997faed5d7ba9f9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 22 Jan 2025 19:05:27 +0800 +Subject: ext4: reject the 'data_err=abort' option in nojournal mode + +From: Baokun Li + +[ Upstream commit 26343ca0df715097065b02a6cddb4a029d5b9327 ] + +data_err=abort aborts the journal on I/O errors. However, this option is +meaningless if journal is disabled, so it is rejected in nojournal mode +to reduce unnecessary checks. Also, this option is ignored upon remount. + +Signed-off-by: Baokun Li +Reviewed-by: Zhang Yi +Reviewed-by: Jan Kara +Link: https://patch.msgid.link/20250122110533.4116662-4-libaokun@huaweicloud.com +Signed-off-by: Theodore Ts'o +Signed-off-by: Sasha Levin +--- + fs/ext4/super.c | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/fs/ext4/super.c b/fs/ext4/super.c +index b4a02be2eacf6..b956e1ee98290 100644 +--- a/fs/ext4/super.c ++++ b/fs/ext4/super.c +@@ -2785,6 +2785,13 @@ static int ext4_check_opt_consistency(struct fs_context *fc, + } + + if (is_remount) { ++ if (!sbi->s_journal && ++ ctx_test_mount_opt(ctx, EXT4_MOUNT_DATA_ERR_ABORT)) { ++ ext4_msg(NULL, KERN_WARNING, ++ "Remounting fs w/o journal so ignoring data_err option"); ++ ctx_clear_mount_opt(ctx, EXT4_MOUNT_DATA_ERR_ABORT); ++ } ++ + if (ctx_test_mount_opt(ctx, EXT4_MOUNT_DAX_ALWAYS) && + (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA)) { + ext4_msg(NULL, KERN_ERR, "can't mount with " +@@ -5428,6 +5435,11 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb) + "data=, fs mounted w/o journal"); + goto failed_mount3a; + } ++ if (test_opt(sb, DATA_ERR_ABORT)) { ++ ext4_msg(sb, KERN_ERR, ++ "can't mount with data_err=abort, fs mounted w/o journal"); ++ goto failed_mount3a; ++ } + sbi->s_def_mount_opt &= ~EXT4_MOUNT_JOURNAL_CHECKSUM; + clear_opt(sb, JOURNAL_CHECKSUM); + clear_opt(sb, DATA_FLAGS); +-- +2.39.5 + diff --git a/queue-6.14/ext4-remove-writable-userspace-mappings-before-trunc.patch b/queue-6.14/ext4-remove-writable-userspace-mappings-before-trunc.patch new file mode 100644 index 0000000000..a1a754a75a --- /dev/null +++ b/queue-6.14/ext4-remove-writable-userspace-mappings-before-trunc.patch @@ -0,0 +1,185 @@ +From 8cabec0d6bc2b2903e87472cd4992cc6f864c592 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 20 Dec 2024 09:16:28 +0800 +Subject: ext4: remove writable userspace mappings before truncating page cache + +From: Zhang Yi + +[ Upstream commit 17207d0bb209e8b40f27d7f3f96e82a78af0bf2c ] + +When zeroing a range of folios on the filesystem which block size is +less than the page size, the file's mapped blocks within one page will +be marked as unwritten, we should remove writable userspace mappings to +ensure that ext4_page_mkwrite() can be called during subsequent write +access to these partial folios. Otherwise, data written by subsequent +mmap writes may not be saved to disk. + + $mkfs.ext4 -b 1024 /dev/vdb + $mount /dev/vdb /mnt + $xfs_io -t -f -c "pwrite -S 0x58 0 4096" -c "mmap -rw 0 4096" \ + -c "mwrite -S 0x5a 2048 2048" -c "fzero 2048 2048" \ + -c "mwrite -S 0x59 2048 2048" -c "close" /mnt/foo + + $od -Ax -t x1z /mnt/foo + 000000 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 + * + 000800 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 + * + 001000 + + $umount /mnt && mount /dev/vdb /mnt + $od -Ax -t x1z /mnt/foo + 000000 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 + * + 000800 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + * + 001000 + +Fix this by introducing ext4_truncate_page_cache_block_range() to remove +writable userspace mappings when truncating a partial folio range. +Additionally, move the journal data mode-specific handlers and +truncate_pagecache_range() into this function, allowing it to serve as a +common helper that correctly manages the page cache in preparation for +block range manipulations. + +Signed-off-by: Zhang Yi +Reviewed-by: Jan Kara +Reviewed-by: Ojaswin Mujoo +Link: https://patch.msgid.link/20241220011637.1157197-2-yi.zhang@huaweicloud.com +Signed-off-by: Theodore Ts'o +Signed-off-by: Sasha Levin +--- + fs/ext4/ext4.h | 2 ++ + fs/ext4/extents.c | 19 ++++---------- + fs/ext4/inode.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 70 insertions(+), 14 deletions(-) + +diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h +index d4d285d999311..4f81983b79186 100644 +--- a/fs/ext4/ext4.h ++++ b/fs/ext4/ext4.h +@@ -3011,6 +3011,8 @@ extern int ext4_inode_attach_jinode(struct inode *inode); + extern int ext4_can_truncate(struct inode *inode); + extern int ext4_truncate(struct inode *); + extern int ext4_break_layouts(struct inode *); ++extern int ext4_truncate_page_cache_block_range(struct inode *inode, ++ loff_t start, loff_t end); + extern int ext4_punch_hole(struct file *file, loff_t offset, loff_t length); + extern void ext4_set_inode_flags(struct inode *, bool init); + extern int ext4_alloc_da_blocks(struct inode *inode); +diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c +index a07a98a4b97a5..8dc6b4271b15d 100644 +--- a/fs/ext4/extents.c ++++ b/fs/ext4/extents.c +@@ -4667,22 +4667,13 @@ static long ext4_zero_range(struct file *file, loff_t offset, + goto out_mutex; + } + +- /* +- * For journalled data we need to write (and checkpoint) pages +- * before discarding page cache to avoid inconsitent data on +- * disk in case of crash before zeroing trans is committed. +- */ +- if (ext4_should_journal_data(inode)) { +- ret = filemap_write_and_wait_range(mapping, start, +- end - 1); +- if (ret) { +- filemap_invalidate_unlock(mapping); +- goto out_mutex; +- } ++ /* Now release the pages and zero block aligned part of pages */ ++ ret = ext4_truncate_page_cache_block_range(inode, start, end); ++ if (ret) { ++ filemap_invalidate_unlock(mapping); ++ goto out_mutex; + } + +- /* Now release the pages and zero block aligned part of pages */ +- truncate_pagecache_range(inode, start, end - 1); + inode_set_mtime_to_ts(inode, inode_set_ctime_current(inode)); + + ret = ext4_alloc_file_blocks(file, lblk, max_blocks, new_size, +diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c +index 377fec39b24be..44780bb537f95 100644 +--- a/fs/ext4/inode.c ++++ b/fs/ext4/inode.c +@@ -31,6 +31,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -3903,6 +3904,68 @@ int ext4_update_disksize_before_punch(struct inode *inode, loff_t offset, + return ret; + } + ++static inline void ext4_truncate_folio(struct inode *inode, ++ loff_t start, loff_t end) ++{ ++ unsigned long blocksize = i_blocksize(inode); ++ struct folio *folio; ++ ++ /* Nothing to be done if no complete block needs to be truncated. */ ++ if (round_up(start, blocksize) >= round_down(end, blocksize)) ++ return; ++ ++ folio = filemap_lock_folio(inode->i_mapping, start >> PAGE_SHIFT); ++ if (IS_ERR(folio)) ++ return; ++ ++ if (folio_mkclean(folio)) ++ folio_mark_dirty(folio); ++ folio_unlock(folio); ++ folio_put(folio); ++} ++ ++int ext4_truncate_page_cache_block_range(struct inode *inode, ++ loff_t start, loff_t end) ++{ ++ unsigned long blocksize = i_blocksize(inode); ++ int ret; ++ ++ /* ++ * For journalled data we need to write (and checkpoint) pages ++ * before discarding page cache to avoid inconsitent data on disk ++ * in case of crash before freeing or unwritten converting trans ++ * is committed. ++ */ ++ if (ext4_should_journal_data(inode)) { ++ ret = filemap_write_and_wait_range(inode->i_mapping, start, ++ end - 1); ++ if (ret) ++ return ret; ++ goto truncate_pagecache; ++ } ++ ++ /* ++ * If the block size is less than the page size, the file's mapped ++ * blocks within one page could be freed or converted to unwritten. ++ * So it's necessary to remove writable userspace mappings, and then ++ * ext4_page_mkwrite() can be called during subsequent write access ++ * to these partial folios. ++ */ ++ if (!IS_ALIGNED(start | end, PAGE_SIZE) && ++ blocksize < PAGE_SIZE && start < inode->i_size) { ++ loff_t page_boundary = round_up(start, PAGE_SIZE); ++ ++ ext4_truncate_folio(inode, start, min(page_boundary, end)); ++ if (end > page_boundary) ++ ext4_truncate_folio(inode, ++ round_down(end, PAGE_SIZE), end); ++ } ++ ++truncate_pagecache: ++ truncate_pagecache_range(inode, start, end - 1); ++ return 0; ++} ++ + static void ext4_wait_dax_page(struct inode *inode) + { + filemap_invalidate_unlock(inode->i_mapping); +-- +2.39.5 + diff --git a/queue-6.14/ext4-reorder-capability-check-last.patch b/queue-6.14/ext4-reorder-capability-check-last.patch new file mode 100644 index 0000000000..a14e26d5cc --- /dev/null +++ b/queue-6.14/ext4-reorder-capability-check-last.patch @@ -0,0 +1,55 @@ +From 344dee38f237f5bbd8d74857a9f59cf10df01ee4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 2 Mar 2025 17:06:39 +0100 +Subject: ext4: reorder capability check last +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Christian Göttsche + +[ Upstream commit 1b419c889c0767a5b66d0a6c566cae491f1cb0f7 ] + +capable() calls refer to enabled LSMs whether to permit or deny the +request. This is relevant in connection with SELinux, where a +capability check results in a policy decision and by default a denial +message on insufficient permission is issued. +It can lead to three undesired cases: + 1. A denial message is generated, even in case the operation was an + unprivileged one and thus the syscall succeeded, creating noise. + 2. To avoid the noise from 1. the policy writer adds a rule to ignore + those denial messages, hiding future syscalls, where the task + performs an actual privileged operation, leading to hidden limited + functionality of that task. + 3. To avoid the noise from 1. the policy writer adds a rule to permit + the task the requested capability, while it does not need it, + violating the principle of least privilege. + +Signed-off-by: Christian Göttsche +Reviewed-by: Serge Hallyn +Reviewed-by: Jan Kara +Link: https://patch.msgid.link/20250302160657.127253-2-cgoettsche@seltendoof.de +Signed-off-by: Theodore Ts'o +Signed-off-by: Sasha Levin +--- + fs/ext4/balloc.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c +index 8042ad8738089..c48fd36b2d74c 100644 +--- a/fs/ext4/balloc.c ++++ b/fs/ext4/balloc.c +@@ -649,8 +649,8 @@ static int ext4_has_free_clusters(struct ext4_sb_info *sbi, + /* Hm, nope. Are (enough) root reserved clusters available? */ + if (uid_eq(sbi->s_resuid, current_fsuid()) || + (!gid_eq(sbi->s_resgid, GLOBAL_ROOT_GID) && in_group_p(sbi->s_resgid)) || +- capable(CAP_SYS_RESOURCE) || +- (flags & EXT4_MB_USE_ROOT_BLOCKS)) { ++ (flags & EXT4_MB_USE_ROOT_BLOCKS) || ++ capable(CAP_SYS_RESOURCE)) { + + if (free_clusters >= (nclusters + dirty_clusters + + resv_clusters)) +-- +2.39.5 + diff --git a/queue-6.14/f2fs-defer-readonly-check-vs-norecovery.patch b/queue-6.14/f2fs-defer-readonly-check-vs-norecovery.patch new file mode 100644 index 0000000000..b4d6907ad1 --- /dev/null +++ b/queue-6.14/f2fs-defer-readonly-check-vs-norecovery.patch @@ -0,0 +1,56 @@ +From 442e4090bb78d5dce4506a591214ce2447d6ea50 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 3 Mar 2025 11:12:17 -0600 +Subject: f2fs: defer readonly check vs norecovery + +From: Eric Sandeen + +[ Upstream commit 9cca49875997a1a7e92800a828a62bacb0f577b9 ] + +Defer the readonly-vs-norecovery check until after option parsing is done +so that option parsing does not require an active superblock for the test. +Add a helpful message, while we're at it. + +(I think could be moved back into parsing after we switch to the new mount +API if desired, as the fs context will have RO state available.) + +Signed-off-by: Eric Sandeen +Reviewed-by: Chao Yu +Signed-off-by: Jaegeuk Kim +Signed-off-by: Sasha Levin +--- + fs/f2fs/super.c | 10 +++++++--- + 1 file changed, 7 insertions(+), 3 deletions(-) + +diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c +index b8a0e925a4011..d3b04a589b525 100644 +--- a/fs/f2fs/super.c ++++ b/fs/f2fs/super.c +@@ -728,10 +728,8 @@ static int parse_options(struct super_block *sb, char *options, bool is_remount) + set_opt(sbi, DISABLE_ROLL_FORWARD); + break; + case Opt_norecovery: +- /* this option mounts f2fs with ro */ ++ /* requires ro mount, checked in f2fs_default_check */ + set_opt(sbi, NORECOVERY); +- if (!f2fs_readonly(sb)) +- return -EINVAL; + break; + case Opt_discard: + if (!f2fs_hw_support_discard(sbi)) { +@@ -1418,6 +1416,12 @@ static int parse_options(struct super_block *sb, char *options, bool is_remount) + f2fs_err(sbi, "Allow to mount readonly mode only"); + return -EROFS; + } ++ ++ if (test_opt(sbi, NORECOVERY) && !f2fs_readonly(sbi->sb)) { ++ f2fs_err(sbi, "norecovery requires readonly mount"); ++ return -EINVAL; ++ } ++ + return 0; + } + +-- +2.39.5 + diff --git a/queue-6.14/f2fs-introduce-f2fs_base_attr-for-global-sysfs-entri.patch b/queue-6.14/f2fs-introduce-f2fs_base_attr-for-global-sysfs-entri.patch new file mode 100644 index 0000000000..b87ef78542 --- /dev/null +++ b/queue-6.14/f2fs-introduce-f2fs_base_attr-for-global-sysfs-entri.patch @@ -0,0 +1,155 @@ +From 14ce4b28aacc75f397cf8d1265effffec7dfd861 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 30 Jan 2025 05:06:07 +0000 +Subject: f2fs: introduce f2fs_base_attr for global sysfs entries + +From: Jaegeuk Kim + +[ Upstream commit 21925ede449e038ed6f9efdfe0e79f15bddc34bc ] + +In /sys/fs/f2fs/features, there's no f2fs_sb_info, so let's avoid to get +the pointer. + +Reviewed-by: Chao Yu +Signed-off-by: Jaegeuk Kim +Signed-off-by: Sasha Levin +--- + fs/f2fs/sysfs.c | 74 ++++++++++++++++++++++++++++++++++--------------- + 1 file changed, 52 insertions(+), 22 deletions(-) + +diff --git a/fs/f2fs/sysfs.c b/fs/f2fs/sysfs.c +index d15c68b28952b..b419555e1ea7f 100644 +--- a/fs/f2fs/sysfs.c ++++ b/fs/f2fs/sysfs.c +@@ -61,6 +61,12 @@ struct f2fs_attr { + int id; + }; + ++struct f2fs_base_attr { ++ struct attribute attr; ++ ssize_t (*show)(struct f2fs_base_attr *a, char *buf); ++ ssize_t (*store)(struct f2fs_base_attr *a, const char *buf, size_t len); ++}; ++ + static ssize_t f2fs_sbi_show(struct f2fs_attr *a, + struct f2fs_sb_info *sbi, char *buf); + +@@ -862,6 +868,25 @@ static void f2fs_sb_release(struct kobject *kobj) + complete(&sbi->s_kobj_unregister); + } + ++static ssize_t f2fs_base_attr_show(struct kobject *kobj, ++ struct attribute *attr, char *buf) ++{ ++ struct f2fs_base_attr *a = container_of(attr, ++ struct f2fs_base_attr, attr); ++ ++ return a->show ? a->show(a, buf) : 0; ++} ++ ++static ssize_t f2fs_base_attr_store(struct kobject *kobj, ++ struct attribute *attr, ++ const char *buf, size_t len) ++{ ++ struct f2fs_base_attr *a = container_of(attr, ++ struct f2fs_base_attr, attr); ++ ++ return a->store ? a->store(a, buf, len) : 0; ++} ++ + /* + * Note that there are three feature list entries: + * 1) /sys/fs/f2fs/features +@@ -880,14 +905,13 @@ static void f2fs_sb_release(struct kobject *kobj) + * please add new on-disk feature in this list only. + * - ref. F2FS_SB_FEATURE_RO_ATTR() + */ +-static ssize_t f2fs_feature_show(struct f2fs_attr *a, +- struct f2fs_sb_info *sbi, char *buf) ++static ssize_t f2fs_feature_show(struct f2fs_base_attr *a, char *buf) + { + return sysfs_emit(buf, "supported\n"); + } + + #define F2FS_FEATURE_RO_ATTR(_name) \ +-static struct f2fs_attr f2fs_attr_##_name = { \ ++static struct f2fs_base_attr f2fs_base_attr_##_name = { \ + .attr = {.name = __stringify(_name), .mode = 0444 }, \ + .show = f2fs_feature_show, \ + } +@@ -1256,37 +1280,38 @@ static struct attribute *f2fs_attrs[] = { + }; + ATTRIBUTE_GROUPS(f2fs); + ++#define BASE_ATTR_LIST(name) (&f2fs_base_attr_##name.attr) + static struct attribute *f2fs_feat_attrs[] = { + #ifdef CONFIG_FS_ENCRYPTION +- ATTR_LIST(encryption), +- ATTR_LIST(test_dummy_encryption_v2), ++ BASE_ATTR_LIST(encryption), ++ BASE_ATTR_LIST(test_dummy_encryption_v2), + #if IS_ENABLED(CONFIG_UNICODE) +- ATTR_LIST(encrypted_casefold), ++ BASE_ATTR_LIST(encrypted_casefold), + #endif + #endif /* CONFIG_FS_ENCRYPTION */ + #ifdef CONFIG_BLK_DEV_ZONED +- ATTR_LIST(block_zoned), ++ BASE_ATTR_LIST(block_zoned), + #endif +- ATTR_LIST(atomic_write), +- ATTR_LIST(extra_attr), +- ATTR_LIST(project_quota), +- ATTR_LIST(inode_checksum), +- ATTR_LIST(flexible_inline_xattr), +- ATTR_LIST(quota_ino), +- ATTR_LIST(inode_crtime), +- ATTR_LIST(lost_found), ++ BASE_ATTR_LIST(atomic_write), ++ BASE_ATTR_LIST(extra_attr), ++ BASE_ATTR_LIST(project_quota), ++ BASE_ATTR_LIST(inode_checksum), ++ BASE_ATTR_LIST(flexible_inline_xattr), ++ BASE_ATTR_LIST(quota_ino), ++ BASE_ATTR_LIST(inode_crtime), ++ BASE_ATTR_LIST(lost_found), + #ifdef CONFIG_FS_VERITY +- ATTR_LIST(verity), ++ BASE_ATTR_LIST(verity), + #endif +- ATTR_LIST(sb_checksum), ++ BASE_ATTR_LIST(sb_checksum), + #if IS_ENABLED(CONFIG_UNICODE) +- ATTR_LIST(casefold), ++ BASE_ATTR_LIST(casefold), + #endif +- ATTR_LIST(readonly), ++ BASE_ATTR_LIST(readonly), + #ifdef CONFIG_F2FS_FS_COMPRESSION +- ATTR_LIST(compression), ++ BASE_ATTR_LIST(compression), + #endif +- ATTR_LIST(pin_file), ++ BASE_ATTR_LIST(pin_file), + NULL, + }; + ATTRIBUTE_GROUPS(f2fs_feat); +@@ -1362,9 +1387,14 @@ static struct kset f2fs_kset = { + .kobj = {.ktype = &f2fs_ktype}, + }; + ++static const struct sysfs_ops f2fs_feat_attr_ops = { ++ .show = f2fs_base_attr_show, ++ .store = f2fs_base_attr_store, ++}; ++ + static const struct kobj_type f2fs_feat_ktype = { + .default_groups = f2fs_feat_groups, +- .sysfs_ops = &f2fs_attr_ops, ++ .sysfs_ops = &f2fs_feat_attr_ops, + }; + + static struct kobject f2fs_feat = { +-- +2.39.5 + diff --git a/queue-6.14/fbcon-use-correct-erase-colour-for-clearing-in-fbcon.patch b/queue-6.14/fbcon-use-correct-erase-colour-for-clearing-in-fbcon.patch new file mode 100644 index 0000000000..35a41a888f --- /dev/null +++ b/queue-6.14/fbcon-use-correct-erase-colour-for-clearing-in-fbcon.patch @@ -0,0 +1,242 @@ +From b2d40f00da6ed825af69cded987c1a79c70b0a04 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 2 Feb 2025 21:33:46 +0100 +Subject: fbcon: Use correct erase colour for clearing in fbcon + +From: Zsolt Kajtar + +[ Upstream commit 892c788d73fe4a94337ed092cb998c49fa8ecaf4 ] + +The erase colour calculation for fbcon clearing should use get_color instead +of attr_col_ec, like everything else. The latter is similar but is not correct. +For example it's missing the depth dependent remapping and doesn't care about +blanking. + +The problem can be reproduced by setting up the background colour to grey +(vt.color=0x70) and having an fbcon console set to 2bpp (4 shades of gray). +Now the background attribute should be 1 (dark gray) on the console. + +If the screen is scrolled when pressing enter in a shell prompt at the bottom +line then the new line is cleared using colour 7 instead of 1. That's not +something fillrect likes (at 2bbp it expect 0-3) so the result is interesting. + +This patch switches to get_color with vc_video_erase_char to determine the +erase colour from attr_col_ec. That makes the latter function redundant as +no other users were left. + +Use correct erase colour for clearing in fbcon + +Signed-off-by: Zsolt Kajtar +Signed-off-by: Helge Deller +Signed-off-by: Sasha Levin +--- + drivers/video/fbdev/core/bitblit.c | 5 ++-- + drivers/video/fbdev/core/fbcon.c | 10 +++++--- + drivers/video/fbdev/core/fbcon.h | 38 +--------------------------- + drivers/video/fbdev/core/fbcon_ccw.c | 5 ++-- + drivers/video/fbdev/core/fbcon_cw.c | 5 ++-- + drivers/video/fbdev/core/fbcon_ud.c | 5 ++-- + drivers/video/fbdev/core/tileblit.c | 8 +++--- + 7 files changed, 18 insertions(+), 58 deletions(-) + +diff --git a/drivers/video/fbdev/core/bitblit.c b/drivers/video/fbdev/core/bitblit.c +index 3ff1b2a8659e8..f9475c14f7339 100644 +--- a/drivers/video/fbdev/core/bitblit.c ++++ b/drivers/video/fbdev/core/bitblit.c +@@ -59,12 +59,11 @@ static void bit_bmove(struct vc_data *vc, struct fb_info *info, int sy, + } + + static void bit_clear(struct vc_data *vc, struct fb_info *info, int sy, +- int sx, int height, int width) ++ int sx, int height, int width, int fg, int bg) + { +- int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; + struct fb_fillrect region; + +- region.color = attr_bgcol_ec(bgshift, vc, info); ++ region.color = bg; + region.dx = sx * vc->vc_font.width; + region.dy = sy * vc->vc_font.height; + region.width = width * vc->vc_font.width; +diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c +index e8b4e8c119b5c..07d127110ca4c 100644 +--- a/drivers/video/fbdev/core/fbcon.c ++++ b/drivers/video/fbdev/core/fbcon.c +@@ -1258,7 +1258,7 @@ static void __fbcon_clear(struct vc_data *vc, unsigned int sy, unsigned int sx, + { + struct fb_info *info = fbcon_info_from_console(vc->vc_num); + struct fbcon_ops *ops = info->fbcon_par; +- ++ int fg, bg; + struct fbcon_display *p = &fb_display[vc->vc_num]; + u_int y_break; + +@@ -1279,16 +1279,18 @@ static void __fbcon_clear(struct vc_data *vc, unsigned int sy, unsigned int sx, + fbcon_clear_margins(vc, 0); + } + ++ fg = get_color(vc, info, vc->vc_video_erase_char, 1); ++ bg = get_color(vc, info, vc->vc_video_erase_char, 0); + /* Split blits that cross physical y_wrap boundary */ + + y_break = p->vrows - p->yscroll; + if (sy < y_break && sy + height - 1 >= y_break) { + u_int b = y_break - sy; +- ops->clear(vc, info, real_y(p, sy), sx, b, width); ++ ops->clear(vc, info, real_y(p, sy), sx, b, width, fg, bg); + ops->clear(vc, info, real_y(p, sy + b), sx, height - b, +- width); ++ width, fg, bg); + } else +- ops->clear(vc, info, real_y(p, sy), sx, height, width); ++ ops->clear(vc, info, real_y(p, sy), sx, height, width, fg, bg); + } + + static void fbcon_clear(struct vc_data *vc, unsigned int sy, unsigned int sx, +diff --git a/drivers/video/fbdev/core/fbcon.h b/drivers/video/fbdev/core/fbcon.h +index df70ea5ec5b37..4d97e6d8a16a2 100644 +--- a/drivers/video/fbdev/core/fbcon.h ++++ b/drivers/video/fbdev/core/fbcon.h +@@ -55,7 +55,7 @@ struct fbcon_ops { + void (*bmove)(struct vc_data *vc, struct fb_info *info, int sy, + int sx, int dy, int dx, int height, int width); + void (*clear)(struct vc_data *vc, struct fb_info *info, int sy, +- int sx, int height, int width); ++ int sx, int height, int width, int fb, int bg); + void (*putcs)(struct vc_data *vc, struct fb_info *info, + const unsigned short *s, int count, int yy, int xx, + int fg, int bg); +@@ -116,42 +116,6 @@ static inline int mono_col(const struct fb_info *info) + return (~(0xfff << max_len)) & 0xff; + } + +-static inline int attr_col_ec(int shift, struct vc_data *vc, +- struct fb_info *info, int is_fg) +-{ +- int is_mono01; +- int col; +- int fg; +- int bg; +- +- if (!vc) +- return 0; +- +- if (vc->vc_can_do_color) +- return is_fg ? attr_fgcol(shift,vc->vc_video_erase_char) +- : attr_bgcol(shift,vc->vc_video_erase_char); +- +- if (!info) +- return 0; +- +- col = mono_col(info); +- is_mono01 = info->fix.visual == FB_VISUAL_MONO01; +- +- if (attr_reverse(vc->vc_video_erase_char)) { +- fg = is_mono01 ? col : 0; +- bg = is_mono01 ? 0 : col; +- } +- else { +- fg = is_mono01 ? 0 : col; +- bg = is_mono01 ? col : 0; +- } +- +- return is_fg ? fg : bg; +-} +- +-#define attr_bgcol_ec(bgshift, vc, info) attr_col_ec(bgshift, vc, info, 0) +-#define attr_fgcol_ec(fgshift, vc, info) attr_col_ec(fgshift, vc, info, 1) +- + /* + * Scroll Method + */ +diff --git a/drivers/video/fbdev/core/fbcon_ccw.c b/drivers/video/fbdev/core/fbcon_ccw.c +index f9b794ff7d396..89ef4ba7e8672 100644 +--- a/drivers/video/fbdev/core/fbcon_ccw.c ++++ b/drivers/video/fbdev/core/fbcon_ccw.c +@@ -78,14 +78,13 @@ static void ccw_bmove(struct vc_data *vc, struct fb_info *info, int sy, + } + + static void ccw_clear(struct vc_data *vc, struct fb_info *info, int sy, +- int sx, int height, int width) ++ int sx, int height, int width, int fg, int bg) + { + struct fbcon_ops *ops = info->fbcon_par; + struct fb_fillrect region; +- int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; + u32 vyres = GETVYRES(ops->p, info); + +- region.color = attr_bgcol_ec(bgshift,vc,info); ++ region.color = bg; + region.dx = sy * vc->vc_font.height; + region.dy = vyres - ((sx + width) * vc->vc_font.width); + region.height = width * vc->vc_font.width; +diff --git a/drivers/video/fbdev/core/fbcon_cw.c b/drivers/video/fbdev/core/fbcon_cw.c +index 903f6fc174e14..b9dac7940fb77 100644 +--- a/drivers/video/fbdev/core/fbcon_cw.c ++++ b/drivers/video/fbdev/core/fbcon_cw.c +@@ -63,14 +63,13 @@ static void cw_bmove(struct vc_data *vc, struct fb_info *info, int sy, + } + + static void cw_clear(struct vc_data *vc, struct fb_info *info, int sy, +- int sx, int height, int width) ++ int sx, int height, int width, int fg, int bg) + { + struct fbcon_ops *ops = info->fbcon_par; + struct fb_fillrect region; +- int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; + u32 vxres = GETVXRES(ops->p, info); + +- region.color = attr_bgcol_ec(bgshift,vc,info); ++ region.color = bg; + region.dx = vxres - ((sy + height) * vc->vc_font.height); + region.dy = sx * vc->vc_font.width; + region.height = width * vc->vc_font.width; +diff --git a/drivers/video/fbdev/core/fbcon_ud.c b/drivers/video/fbdev/core/fbcon_ud.c +index 594331936fd3c..0af7913a2abdc 100644 +--- a/drivers/video/fbdev/core/fbcon_ud.c ++++ b/drivers/video/fbdev/core/fbcon_ud.c +@@ -64,15 +64,14 @@ static void ud_bmove(struct vc_data *vc, struct fb_info *info, int sy, + } + + static void ud_clear(struct vc_data *vc, struct fb_info *info, int sy, +- int sx, int height, int width) ++ int sx, int height, int width, int fg, int bg) + { + struct fbcon_ops *ops = info->fbcon_par; + struct fb_fillrect region; +- int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; + u32 vyres = GETVYRES(ops->p, info); + u32 vxres = GETVXRES(ops->p, info); + +- region.color = attr_bgcol_ec(bgshift,vc,info); ++ region.color = bg; + region.dy = vyres - ((sy + height) * vc->vc_font.height); + region.dx = vxres - ((sx + width) * vc->vc_font.width); + region.width = width * vc->vc_font.width; +diff --git a/drivers/video/fbdev/core/tileblit.c b/drivers/video/fbdev/core/tileblit.c +index eff7ec4da1671..45b0828fad1cf 100644 +--- a/drivers/video/fbdev/core/tileblit.c ++++ b/drivers/video/fbdev/core/tileblit.c +@@ -32,16 +32,14 @@ static void tile_bmove(struct vc_data *vc, struct fb_info *info, int sy, + } + + static void tile_clear(struct vc_data *vc, struct fb_info *info, int sy, +- int sx, int height, int width) ++ int sx, int height, int width, int fg, int bg) + { + struct fb_tilerect rect; +- int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; +- int fgshift = (vc->vc_hi_font_mask) ? 9 : 8; + + rect.index = vc->vc_video_erase_char & + ((vc->vc_hi_font_mask) ? 0x1ff : 0xff); +- rect.fg = attr_fgcol_ec(fgshift, vc, info); +- rect.bg = attr_bgcol_ec(bgshift, vc, info); ++ rect.fg = fg; ++ rect.bg = bg; + rect.sx = sx; + rect.sy = sy; + rect.width = width; +-- +2.39.5 + diff --git a/queue-6.14/fbdev-core-tileblit-implement-missing-margin-clearin.patch b/queue-6.14/fbdev-core-tileblit-implement-missing-margin-clearin.patch new file mode 100644 index 0000000000..10717db8f5 --- /dev/null +++ b/queue-6.14/fbdev-core-tileblit-implement-missing-margin-clearin.patch @@ -0,0 +1,95 @@ +From ef156cbb38f984b547082e4877e007dda2384fe1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 1 Feb 2025 09:18:09 +0100 +Subject: fbdev: core: tileblit: Implement missing margin clearing for tileblit + +From: Zsolt Kajtar + +[ Upstream commit 76d3ca89981354e1f85a3e0ad9ac4217d351cc72 ] + +I was wondering why there's garbage at the bottom of the screen when +tile blitting is used with an odd mode like 1080, 600 or 200. Sure there's +only space for half a tile but the same area is clean when the buffer +is bitmap. + +Then later I found that it's supposed to be cleaned but that's not +implemented. So I took what's in bitblit and adapted it for tileblit. + +This implementation was tested for both the horizontal and vertical case, +and now does the same as what's done for bitmap buffers. + +If anyone is interested to reproduce the problem then I could bet that'd +be on a S3 or Ark. Just set up a mode with an odd line count and make +sure that the virtual size covers the complete tile at the bottom. E.g. +for 600 lines that's 608 virtual lines for a 16 tall tile. Then the +bottom area should be cleaned. + +For the right side it's more difficult as there the drivers won't let an +odd size happen, unless the code is modified. But once it reports back a +few pixel columns short then fbcon won't use the last column. With the +patch that column is now clean. + +Btw. the virtual size should be rounded up by the driver for both axes +(not only the horizontal) so that it's dividable by the tile size. +That's a driver bug but correcting it is not in scope for this patch. + +Implement missing margin clearing for tileblit + +Signed-off-by: Zsolt Kajtar +Signed-off-by: Helge Deller +Signed-off-by: Sasha Levin +--- + drivers/video/fbdev/core/tileblit.c | 37 ++++++++++++++++++++++++++++- + 1 file changed, 36 insertions(+), 1 deletion(-) + +diff --git a/drivers/video/fbdev/core/tileblit.c b/drivers/video/fbdev/core/tileblit.c +index 45b0828fad1cf..d342b90c42b7f 100644 +--- a/drivers/video/fbdev/core/tileblit.c ++++ b/drivers/video/fbdev/core/tileblit.c +@@ -74,7 +74,42 @@ static void tile_putcs(struct vc_data *vc, struct fb_info *info, + static void tile_clear_margins(struct vc_data *vc, struct fb_info *info, + int color, int bottom_only) + { +- return; ++ unsigned int cw = vc->vc_font.width; ++ unsigned int ch = vc->vc_font.height; ++ unsigned int rw = info->var.xres - (vc->vc_cols*cw); ++ unsigned int bh = info->var.yres - (vc->vc_rows*ch); ++ unsigned int rs = info->var.xres - rw; ++ unsigned int bs = info->var.yres - bh; ++ unsigned int vwt = info->var.xres_virtual / cw; ++ unsigned int vht = info->var.yres_virtual / ch; ++ struct fb_tilerect rect; ++ ++ rect.index = vc->vc_video_erase_char & ++ ((vc->vc_hi_font_mask) ? 0x1ff : 0xff); ++ rect.fg = color; ++ rect.bg = color; ++ ++ if ((int) rw > 0 && !bottom_only) { ++ rect.sx = (info->var.xoffset + rs + cw - 1) / cw; ++ rect.sy = 0; ++ rect.width = (rw + cw - 1) / cw; ++ rect.height = vht; ++ if (rect.width + rect.sx > vwt) ++ rect.width = vwt - rect.sx; ++ if (rect.sx < vwt) ++ info->tileops->fb_tilefill(info, &rect); ++ } ++ ++ if ((int) bh > 0) { ++ rect.sx = info->var.xoffset / cw; ++ rect.sy = (info->var.yoffset + bs) / ch; ++ rect.width = rs / cw; ++ rect.height = (bh + ch - 1) / ch; ++ if (rect.height + rect.sy > vht) ++ rect.height = vht - rect.sy; ++ if (rect.sy < vht) ++ info->tileops->fb_tilefill(info, &rect); ++ } + } + + static void tile_cursor(struct vc_data *vc, struct fb_info *info, bool enable, +-- +2.39.5 + diff --git a/queue-6.14/fbdev-fsl-diu-fb-add-missing-device_remove_file.patch b/queue-6.14/fbdev-fsl-diu-fb-add-missing-device_remove_file.patch new file mode 100644 index 0000000000..4e1982101d --- /dev/null +++ b/queue-6.14/fbdev-fsl-diu-fb-add-missing-device_remove_file.patch @@ -0,0 +1,33 @@ +From 8d014cc14a7390a7e9f2d1a001ef26f46e3cc778 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 10 Mar 2025 09:54:31 +0800 +Subject: fbdev: fsl-diu-fb: add missing device_remove_file() + +From: Shixiong Ou + +[ Upstream commit 86d16cd12efa547ed43d16ba7a782c1251c80ea8 ] + +Call device_remove_file() when driver remove. + +Signed-off-by: Shixiong Ou +Signed-off-by: Helge Deller +Signed-off-by: Sasha Levin +--- + drivers/video/fbdev/fsl-diu-fb.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/video/fbdev/fsl-diu-fb.c b/drivers/video/fbdev/fsl-diu-fb.c +index 5ac8201c35337..b71d15794ce8b 100644 +--- a/drivers/video/fbdev/fsl-diu-fb.c ++++ b/drivers/video/fbdev/fsl-diu-fb.c +@@ -1827,6 +1827,7 @@ static void fsl_diu_remove(struct platform_device *pdev) + int i; + + data = dev_get_drvdata(&pdev->dev); ++ device_remove_file(&pdev->dev, &data->dev_attr); + disable_lcdc(&data->fsl_diu_info[0]); + + free_irq(data->irq, data->diu_reg); +-- +2.39.5 + diff --git a/queue-6.14/firmware-arm_ffa-handle-the-presence-of-host-partiti.patch b/queue-6.14/firmware-arm_ffa-handle-the-presence-of-host-partiti.patch new file mode 100644 index 0000000000..5eb35cdff3 --- /dev/null +++ b/queue-6.14/firmware-arm_ffa-handle-the-presence-of-host-partiti.patch @@ -0,0 +1,46 @@ +From e65e4401b43e9eaaa0f528b8b3615ff93f4e1f79 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Feb 2025 15:38:48 +0000 +Subject: firmware: arm_ffa: Handle the presence of host partition in the + partition info + +From: Sudeep Holla + +[ Upstream commit 2f622a8b0722d332a2a149794a3add47bc9bdcf3 ] + +Currently it is assumed that the firmware doesn't present the host +partition in the list of partitions presented as part of the response +to PARTITION_INFO_GET from the firmware. However, there are few +platforms that prefer to present the same in the list of partitions. +It is not manadatory but not restricted as well. + +So handle the same by making sure to check the presence of the host +VM ID in the XArray partition information maintained/managed in the +driver before attempting to add it. + +Tested-by: Viresh Kumar +Message-Id: <20250217-ffa_updates-v3-7-bd1d9de615e7@arm.com> +Signed-off-by: Sudeep Holla +Signed-off-by: Sasha Levin +--- + drivers/firmware/arm_ffa/driver.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c +index ca9a27fceb1fd..d545d25132051 100644 +--- a/drivers/firmware/arm_ffa/driver.c ++++ b/drivers/firmware/arm_ffa/driver.c +@@ -1458,6 +1458,10 @@ static int ffa_setup_partitions(void) + + kfree(pbuf); + ++ /* Check if the host is already added as part of partition info */ ++ if (xa_load(&drv_info->partition_info, drv_info->vm_id)) ++ return 0; ++ + /* Allocate for the host */ + ret = ffa_xa_add_partition_info(drv_info->vm_id); + if (ret) +-- +2.39.5 + diff --git a/queue-6.14/firmware-arm_ffa-reject-higher-major-version-as-inco.patch b/queue-6.14/firmware-arm_ffa-reject-higher-major-version-as-inco.patch new file mode 100644 index 0000000000..036d8b2d90 --- /dev/null +++ b/queue-6.14/firmware-arm_ffa-reject-higher-major-version-as-inco.patch @@ -0,0 +1,50 @@ +From 68ecbc3b3d270f5c18dd95c85ba5dc31d382f6fe Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Feb 2025 15:38:53 +0000 +Subject: firmware: arm_ffa: Reject higher major version as incompatible + +From: Sudeep Holla + +[ Upstream commit efff6a7f16b34fd902f342b58bd8bafc2d6f2fd1 ] + +When the firmware compatibility was handled previously in the commit +8e3f9da608f1 ("firmware: arm_ffa: Handle compatibility with different firmware versions"), +we only addressed firmware versions that have higher minor versions +compared to the driver version which is should be considered compatible +unless the firmware returns NOT_SUPPORTED. + +However, if the firmware reports higher major version than the driver +supported, we need to reject it. If the firmware can work in a compatible +mode with the driver requested version, it must return the same major +version as requested. + +Tested-by: Viresh Kumar +Message-Id: <20250217-ffa_updates-v3-12-bd1d9de615e7@arm.com> +Signed-off-by: Sudeep Holla +Signed-off-by: Sasha Levin +--- + drivers/firmware/arm_ffa/driver.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c +index 03d22cbb2ad47..ca9a27fceb1fd 100644 +--- a/drivers/firmware/arm_ffa/driver.c ++++ b/drivers/firmware/arm_ffa/driver.c +@@ -150,6 +150,14 @@ static int ffa_version_check(u32 *version) + return -EOPNOTSUPP; + } + ++ if (FFA_MAJOR_VERSION(ver.a0) > FFA_MAJOR_VERSION(FFA_DRIVER_VERSION)) { ++ pr_err("Incompatible v%d.%d! Latest supported v%d.%d\n", ++ FFA_MAJOR_VERSION(ver.a0), FFA_MINOR_VERSION(ver.a0), ++ FFA_MAJOR_VERSION(FFA_DRIVER_VERSION), ++ FFA_MINOR_VERSION(FFA_DRIVER_VERSION)); ++ return -EINVAL; ++ } ++ + if (ver.a0 < FFA_MIN_VERSION) { + pr_err("Incompatible v%d.%d! Earliest supported v%d.%d\n", + FFA_MAJOR_VERSION(ver.a0), FFA_MINOR_VERSION(ver.a0), +-- +2.39.5 + diff --git a/queue-6.14/firmware-arm_ffa-set-dma_mask-for-ffa-devices.patch b/queue-6.14/firmware-arm_ffa-set-dma_mask-for-ffa-devices.patch new file mode 100644 index 0000000000..80eb993c3a --- /dev/null +++ b/queue-6.14/firmware-arm_ffa-set-dma_mask-for-ffa-devices.patch @@ -0,0 +1,37 @@ +From f5cd34d540dc56cea06664b6a2259cd4b60ef0a4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 17 Jan 2025 15:35:52 +0530 +Subject: firmware: arm_ffa: Set dma_mask for ffa devices + +From: Viresh Kumar + +[ Upstream commit cc0aac7ca17e0ea3ca84b552fc79f3e86fd07f53 ] + +Set dma_mask for FFA devices, otherwise DMA allocation using the device pointer +lead to following warning: + +WARNING: CPU: 1 PID: 1 at kernel/dma/mapping.c:597 dma_alloc_attrs+0xe0/0x124 + +Signed-off-by: Viresh Kumar +Message-Id: +Signed-off-by: Sudeep Holla +Signed-off-by: Sasha Levin +--- + drivers/firmware/arm_ffa/bus.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/firmware/arm_ffa/bus.c b/drivers/firmware/arm_ffa/bus.c +index fa09a82b44921..eacde92802f58 100644 +--- a/drivers/firmware/arm_ffa/bus.c ++++ b/drivers/firmware/arm_ffa/bus.c +@@ -213,6 +213,7 @@ ffa_device_register(const struct ffa_partition_info *part_info, + dev = &ffa_dev->dev; + dev->bus = &ffa_bus_type; + dev->release = ffa_release_device; ++ dev->dma_mask = &dev->coherent_dma_mask; + dev_set_name(&ffa_dev->dev, "arm-ffa-%d", id); + + ffa_dev->id = id; +-- +2.39.5 + diff --git a/queue-6.14/firmware-arm_scmi-relax-duplicate-name-constraint-ac.patch b/queue-6.14/firmware-arm_scmi-relax-duplicate-name-constraint-ac.patch new file mode 100644 index 0000000000..41d2ae5a3b --- /dev/null +++ b/queue-6.14/firmware-arm_scmi-relax-duplicate-name-constraint-ac.patch @@ -0,0 +1,76 @@ +From 70565a16bac0fca6661a7ba97fe312f986a98ed8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 31 Jan 2025 14:18:20 +0000 +Subject: firmware: arm_scmi: Relax duplicate name constraint across protocol + ids + +From: Sudeep Holla + +[ Upstream commit 21ee965267bcbdd733be0f35344fa0f0226d7861 ] + +Currently in scmi_protocol_device_request(), no duplicate scmi device +name is allowed across any protocol. However scmi_dev_match_id() first +matches the protocol id and then the name. So, there is no strict +requirement to keep this scmi device name unique across all the protocols. + +Relax the constraint on the duplicate name across the protocols and +inhibit only within the same protocol id. + +Message-Id: <20250131141822.514342-1-sudeep.holla@arm.com> +Reviewed-by: Dhruva Gole +Reviewed-by: Peng Fan +Signed-off-by: Sudeep Holla +Signed-off-by: Sasha Levin +--- + drivers/firmware/arm_scmi/bus.c | 19 ++++++------------- + 1 file changed, 6 insertions(+), 13 deletions(-) + +diff --git a/drivers/firmware/arm_scmi/bus.c b/drivers/firmware/arm_scmi/bus.c +index 7d7af2262c013..5d799f6626963 100644 +--- a/drivers/firmware/arm_scmi/bus.c ++++ b/drivers/firmware/arm_scmi/bus.c +@@ -42,7 +42,7 @@ static atomic_t scmi_syspower_registered = ATOMIC_INIT(0); + * This helper let an SCMI driver request specific devices identified by the + * @id_table to be created for each active SCMI instance. + * +- * The requested device name MUST NOT be already existent for any protocol; ++ * The requested device name MUST NOT be already existent for this protocol; + * at first the freshly requested @id_table is annotated in the IDR table + * @scmi_requested_devices and then the requested device is advertised to any + * registered party via the @scmi_requested_devices_nh notification chain. +@@ -52,7 +52,6 @@ static atomic_t scmi_syspower_registered = ATOMIC_INIT(0); + static int scmi_protocol_device_request(const struct scmi_device_id *id_table) + { + int ret = 0; +- unsigned int id = 0; + struct list_head *head, *phead = NULL; + struct scmi_requested_dev *rdev; + +@@ -67,19 +66,13 @@ static int scmi_protocol_device_request(const struct scmi_device_id *id_table) + } + + /* +- * Search for the matching protocol rdev list and then search +- * of any existent equally named device...fails if any duplicate found. ++ * Find the matching protocol rdev list and then search of any ++ * existent equally named device...fails if any duplicate found. + */ + mutex_lock(&scmi_requested_devices_mtx); +- idr_for_each_entry(&scmi_requested_devices, head, id) { +- if (!phead) { +- /* A list found registered in the IDR is never empty */ +- rdev = list_first_entry(head, struct scmi_requested_dev, +- node); +- if (rdev->id_table->protocol_id == +- id_table->protocol_id) +- phead = head; +- } ++ phead = idr_find(&scmi_requested_devices, id_table->protocol_id); ++ if (phead) { ++ head = phead; + list_for_each_entry(rdev, head, node) { + if (!strcmp(rdev->id_table->name, id_table->name)) { + pr_err("Ignoring duplicate request [%d] %s\n", +-- +2.39.5 + diff --git a/queue-6.14/firmware-xilinx-dont-send-linux-address-to-get-fpga-.patch b/queue-6.14/firmware-xilinx-dont-send-linux-address-to-get-fpga-.patch new file mode 100644 index 0000000000..d4359e5050 --- /dev/null +++ b/queue-6.14/firmware-xilinx-dont-send-linux-address-to-get-fpga-.patch @@ -0,0 +1,52 @@ +From 4c207afab71ea04998a6332dbd781963a5e2b84c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 7 Feb 2025 11:19:51 +0530 +Subject: firmware: xilinx: Dont send linux address to get fpga config get + status + +From: Siva Durga Prasad Paladugu + +[ Upstream commit 5abc174016052caff1bcf4cedb159bd388411e98 ] + +Fpga get config status just returns status through ret_payload and there +is no need to allocate local buf and send its address through SMC args. +Moreover, the address that is being passed till now is linux virtual +address and is incorrect. +Corresponding modification has been done in the firmware to avoid using the +address sent by linux. + +Signed-off-by: Siva Durga Prasad Paladugu +Signed-off-by: Nava kishore Manne +Link: https://lore.kernel.org/r/20250207054951.1650534-1-nava.kishore.manne@amd.com +Signed-off-by: Michal Simek +Signed-off-by: Sasha Levin +--- + drivers/firmware/xilinx/zynqmp.c | 6 +----- + 1 file changed, 1 insertion(+), 5 deletions(-) + +diff --git a/drivers/firmware/xilinx/zynqmp.c b/drivers/firmware/xilinx/zynqmp.c +index 720fa8b5d8e95..7356e860e65ce 100644 +--- a/drivers/firmware/xilinx/zynqmp.c ++++ b/drivers/firmware/xilinx/zynqmp.c +@@ -1139,17 +1139,13 @@ EXPORT_SYMBOL_GPL(zynqmp_pm_fpga_get_status); + int zynqmp_pm_fpga_get_config_status(u32 *value) + { + u32 ret_payload[PAYLOAD_ARG_CNT]; +- u32 buf, lower_addr, upper_addr; + int ret; + + if (!value) + return -EINVAL; + +- lower_addr = lower_32_bits((u64)&buf); +- upper_addr = upper_32_bits((u64)&buf); +- + ret = zynqmp_pm_invoke_fn(PM_FPGA_READ, ret_payload, 4, +- XILINX_ZYNQMP_PM_FPGA_CONFIG_STAT_OFFSET, lower_addr, upper_addr, ++ XILINX_ZYNQMP_PM_FPGA_CONFIG_STAT_OFFSET, 0, 0, + XILINX_ZYNQMP_PM_FPGA_READ_CONFIG_REG); + + *value = ret_payload[1]; +-- +2.39.5 + diff --git a/queue-6.14/fpga-altera-cvp-increase-credit-timeout.patch b/queue-6.14/fpga-altera-cvp-increase-credit-timeout.patch new file mode 100644 index 0000000000..865c3eee78 --- /dev/null +++ b/queue-6.14/fpga-altera-cvp-increase-credit-timeout.patch @@ -0,0 +1,43 @@ +From 849b5ce250695189443c7c028584537794fec6af Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 13 Feb 2025 06:12:49 +0800 +Subject: fpga: altera-cvp: Increase credit timeout + +From: Kuhanh Murugasen Krishnan + +[ Upstream commit 0f05886a40fdc55016ba4d9ae0a9c41f8312f15b ] + +Increase the timeout for SDM (Secure device manager) data credits from +20ms to 40ms. Internal stress tests running at 500 loops failed with the +current timeout of 20ms. At the start of a FPGA configuration, the CVP +host driver reads the transmit credits from SDM. It then sends bitstream +FPGA data to SDM based on the total credits. Each credit allows the +CVP host driver to send 4kBytes of data. There are situations whereby, +the SDM did not respond in time during testing. + +Signed-off-by: Ang Tien Sung +Signed-off-by: Kuhanh Murugasen Krishnan +Acked-by: Xu Yilun +Link: https://lore.kernel.org/r/20250212221249.2715929-1-tien.sung.ang@intel.com +Signed-off-by: Xu Yilun +Signed-off-by: Sasha Levin +--- + drivers/fpga/altera-cvp.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/fpga/altera-cvp.c b/drivers/fpga/altera-cvp.c +index 6b09144324453..5af0bd33890c0 100644 +--- a/drivers/fpga/altera-cvp.c ++++ b/drivers/fpga/altera-cvp.c +@@ -52,7 +52,7 @@ + /* V2 Defines */ + #define VSE_CVP_TX_CREDITS 0x49 /* 8bit */ + +-#define V2_CREDIT_TIMEOUT_US 20000 ++#define V2_CREDIT_TIMEOUT_US 40000 + #define V2_CHECK_CREDIT_US 10 + #define V2_POLL_TIMEOUT_US 1000000 + #define V2_USER_TIMEOUT_US 500000 +-- +2.39.5 + diff --git a/queue-6.14/fs-buffer-introduce-sleeping-flavors-for-pagecache-l.patch b/queue-6.14/fs-buffer-introduce-sleeping-flavors-for-pagecache-l.patch new file mode 100644 index 0000000000..eb96c717f3 --- /dev/null +++ b/queue-6.14/fs-buffer-introduce-sleeping-flavors-for-pagecache-l.patch @@ -0,0 +1,76 @@ +From dd2741b79e22a0234b43815164f349e22e10047d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 17 Apr 2025 18:59:16 -0700 +Subject: fs/buffer: introduce sleeping flavors for pagecache lookups + +From: Davidlohr Bueso + +[ Upstream commit 2814a7d3d2ff5d2cdd22936f641f758fdb971fa0 ] + +Add __find_get_block_nonatomic() and sb_find_get_block_nonatomic() +calls for which users will be converted where safe. These versions +will take the folio lock instead of the mapping's private_lock. + +Reviewed-by: Jan Kara +Signed-off-by: Davidlohr Bueso +Link: https://kdevops.org/ext4/v6.15-rc2.html # [0] +Link: https://lore.kernel.org/all/aAAEvcrmREWa1SKF@bombadil.infradead.org/ # [1] +Link: https://lore.kernel.org/20250418015921.132400-3-dave@stgolabs.net +Tested-by: kdevops@lists.linux.dev +Reviewed-by: Luis Chamberlain +Signed-off-by: Christian Brauner +Signed-off-by: Sasha Levin +--- + fs/buffer.c | 9 +++++++++ + include/linux/buffer_head.h | 8 ++++++++ + 2 files changed, 17 insertions(+) + +diff --git a/fs/buffer.c b/fs/buffer.c +index a03c245022dcf..7981097c846d4 100644 +--- a/fs/buffer.c ++++ b/fs/buffer.c +@@ -1414,6 +1414,15 @@ __find_get_block(struct block_device *bdev, sector_t block, unsigned size) + } + EXPORT_SYMBOL(__find_get_block); + ++/* same as __find_get_block() but allows sleeping contexts */ ++struct buffer_head * ++__find_get_block_nonatomic(struct block_device *bdev, sector_t block, ++ unsigned size) ++{ ++ return find_get_block_common(bdev, block, size, false); ++} ++EXPORT_SYMBOL(__find_get_block_nonatomic); ++ + /** + * bdev_getblk - Get a buffer_head in a block device's buffer cache. + * @bdev: The block device. +diff --git a/include/linux/buffer_head.h b/include/linux/buffer_head.h +index 932139c5d46f5..ffcd76d977703 100644 +--- a/include/linux/buffer_head.h ++++ b/include/linux/buffer_head.h +@@ -223,6 +223,8 @@ void __wait_on_buffer(struct buffer_head *); + wait_queue_head_t *bh_waitq_head(struct buffer_head *bh); + struct buffer_head *__find_get_block(struct block_device *bdev, sector_t block, + unsigned size); ++struct buffer_head *__find_get_block_nonatomic(struct block_device *bdev, ++ sector_t block, unsigned size); + struct buffer_head *bdev_getblk(struct block_device *bdev, sector_t block, + unsigned size, gfp_t gfp); + void __brelse(struct buffer_head *); +@@ -398,6 +400,12 @@ sb_find_get_block(struct super_block *sb, sector_t block) + return __find_get_block(sb->s_bdev, block, sb->s_blocksize); + } + ++static inline struct buffer_head * ++sb_find_get_block_nonatomic(struct super_block *sb, sector_t block) ++{ ++ return __find_get_block_nonatomic(sb->s_bdev, block, sb->s_blocksize); ++} ++ + static inline void + map_bh(struct buffer_head *bh, struct super_block *sb, sector_t block) + { +-- +2.39.5 + diff --git a/queue-6.14/fs-buffer-split-locking-for-pagecache-lookups.patch b/queue-6.14/fs-buffer-split-locking-for-pagecache-lookups.patch new file mode 100644 index 0000000000..6090b847a0 --- /dev/null +++ b/queue-6.14/fs-buffer-split-locking-for-pagecache-lookups.patch @@ -0,0 +1,125 @@ +From 40d9fb45714023c40abd52504abdde92504efafc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 17 Apr 2025 18:59:15 -0700 +Subject: fs/buffer: split locking for pagecache lookups + +From: Davidlohr Bueso + +[ Upstream commit 7ffe3de53a885dbb5836541c2178bd07d1bad7df ] + +Callers of __find_get_block() may or may not allow for blocking +semantics, and is currently assumed that it will not. Layout +two paths based on this. The the private_lock scheme will +continued to be used for atomic contexts. Otherwise take the +folio lock instead, which protects the buffers, such as +vs migration and try_to_free_buffers(). + +Per the "hack idea", the latter can alleviate contention on +the private_lock for bdev mappings. For reasons of determinism +and avoid making bugs hard to reproduce, the trylocking is not +attempted. + +No change in semantics. All lookup users still take the spinlock. + +Reviewed-by: Jan Kara +Signed-off-by: Davidlohr Bueso +Link: https://kdevops.org/ext4/v6.15-rc2.html # [0] +Link: https://lore.kernel.org/all/aAAEvcrmREWa1SKF@bombadil.infradead.org/ # [1] +Link: https://lore.kernel.org/20250418015921.132400-2-dave@stgolabs.net +Tested-by: kdevops@lists.linux.dev +Reviewed-by: Luis Chamberlain +Signed-off-by: Christian Brauner +Signed-off-by: Sasha Levin +--- + fs/buffer.c | 41 +++++++++++++++++++++++++---------------- + 1 file changed, 25 insertions(+), 16 deletions(-) + +diff --git a/fs/buffer.c b/fs/buffer.c +index cc8452f602516..a03c245022dcf 100644 +--- a/fs/buffer.c ++++ b/fs/buffer.c +@@ -176,18 +176,8 @@ void end_buffer_write_sync(struct buffer_head *bh, int uptodate) + } + EXPORT_SYMBOL(end_buffer_write_sync); + +-/* +- * Various filesystems appear to want __find_get_block to be non-blocking. +- * But it's the page lock which protects the buffers. To get around this, +- * we get exclusion from try_to_free_buffers with the blockdev mapping's +- * i_private_lock. +- * +- * Hack idea: for the blockdev mapping, i_private_lock contention +- * may be quite high. This code could TryLock the page, and if that +- * succeeds, there is no need to take i_private_lock. +- */ + static struct buffer_head * +-__find_get_block_slow(struct block_device *bdev, sector_t block) ++__find_get_block_slow(struct block_device *bdev, sector_t block, bool atomic) + { + struct address_space *bd_mapping = bdev->bd_mapping; + const int blkbits = bd_mapping->host->i_blkbits; +@@ -204,7 +194,16 @@ __find_get_block_slow(struct block_device *bdev, sector_t block) + if (IS_ERR(folio)) + goto out; + +- spin_lock(&bd_mapping->i_private_lock); ++ /* ++ * Folio lock protects the buffers. Callers that cannot block ++ * will fallback to serializing vs try_to_free_buffers() via ++ * the i_private_lock. ++ */ ++ if (atomic) ++ spin_lock(&bd_mapping->i_private_lock); ++ else ++ folio_lock(folio); ++ + head = folio_buffers(folio); + if (!head) + goto out_unlock; +@@ -236,7 +235,10 @@ __find_get_block_slow(struct block_device *bdev, sector_t block) + 1 << blkbits); + } + out_unlock: +- spin_unlock(&bd_mapping->i_private_lock); ++ if (atomic) ++ spin_unlock(&bd_mapping->i_private_lock); ++ else ++ folio_unlock(folio); + folio_put(folio); + out: + return ret; +@@ -1388,14 +1390,15 @@ lookup_bh_lru(struct block_device *bdev, sector_t block, unsigned size) + * it in the LRU and mark it as accessed. If it is not present then return + * NULL + */ +-struct buffer_head * +-__find_get_block(struct block_device *bdev, sector_t block, unsigned size) ++static struct buffer_head * ++find_get_block_common(struct block_device *bdev, sector_t block, ++ unsigned size, bool atomic) + { + struct buffer_head *bh = lookup_bh_lru(bdev, block, size); + + if (bh == NULL) { + /* __find_get_block_slow will mark the page accessed */ +- bh = __find_get_block_slow(bdev, block); ++ bh = __find_get_block_slow(bdev, block, atomic); + if (bh) + bh_lru_install(bh); + } else +@@ -1403,6 +1406,12 @@ __find_get_block(struct block_device *bdev, sector_t block, unsigned size) + + return bh; + } ++ ++struct buffer_head * ++__find_get_block(struct block_device *bdev, sector_t block, unsigned size) ++{ ++ return find_get_block_common(bdev, block, size, true); ++} + EXPORT_SYMBOL(__find_get_block); + + /** +-- +2.39.5 + diff --git a/queue-6.14/fs-buffer-use-sleeping-version-of-__find_get_block.patch b/queue-6.14/fs-buffer-use-sleeping-version-of-__find_get_block.patch new file mode 100644 index 0000000000..7a045b9f63 --- /dev/null +++ b/queue-6.14/fs-buffer-use-sleeping-version-of-__find_get_block.patch @@ -0,0 +1,63 @@ +From 37f9964fde8f8071d4c5cd7d0e7012eb5c3f75a7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 17 Apr 2025 18:59:17 -0700 +Subject: fs/buffer: use sleeping version of __find_get_block() + +From: Davidlohr Bueso + +[ Upstream commit 5b67d43976828dea2394eae2556b369bb7a61f64 ] + +Convert to the new nonatomic flavor to benefit from potential performance +benefits and adapt in the future vs migration such that semantics +are kept. + +Convert write_boundary_block() which already takes the buffer +lock as well as bdev_getblk() depending on the respective gpf flags. +There are no changes in semantics. + +Suggested-by: Jan Kara +Reviewed-by: Jan Kara +Signed-off-by: Davidlohr Bueso +Link: https://kdevops.org/ext4/v6.15-rc2.html # [0] +Link: https://lore.kernel.org/all/aAAEvcrmREWa1SKF@bombadil.infradead.org/ # [1] +Link: https://lore.kernel.org/20250418015921.132400-4-dave@stgolabs.net +Tested-by: kdevops@lists.linux.dev # [0] [1] +Reviewed-by: Luis Chamberlain +Signed-off-by: Christian Brauner +Signed-off-by: Sasha Levin +--- + fs/buffer.c | 11 +++++++++-- + 1 file changed, 9 insertions(+), 2 deletions(-) + +diff --git a/fs/buffer.c b/fs/buffer.c +index 7981097c846d4..2494fe3a5e69e 100644 +--- a/fs/buffer.c ++++ b/fs/buffer.c +@@ -658,7 +658,9 @@ EXPORT_SYMBOL(generic_buffers_fsync); + void write_boundary_block(struct block_device *bdev, + sector_t bblock, unsigned blocksize) + { +- struct buffer_head *bh = __find_get_block(bdev, bblock + 1, blocksize); ++ struct buffer_head *bh; ++ ++ bh = __find_get_block_nonatomic(bdev, bblock + 1, blocksize); + if (bh) { + if (buffer_dirty(bh)) + write_dirty_buffer(bh, 0); +@@ -1440,7 +1442,12 @@ EXPORT_SYMBOL(__find_get_block_nonatomic); + struct buffer_head *bdev_getblk(struct block_device *bdev, sector_t block, + unsigned size, gfp_t gfp) + { +- struct buffer_head *bh = __find_get_block(bdev, block, size); ++ struct buffer_head *bh; ++ ++ if (gfpflags_allow_blocking(gfp)) ++ bh = __find_get_block_nonatomic(bdev, block, size); ++ else ++ bh = __find_get_block(bdev, block, size); + + might_alloc(gfp); + if (bh) +-- +2.39.5 + diff --git a/queue-6.14/fs-ext4-use-sleeping-version-of-sb_find_get_block.patch b/queue-6.14/fs-ext4-use-sleeping-version-of-sb_find_get_block.patch new file mode 100644 index 0000000000..8e3e10916f --- /dev/null +++ b/queue-6.14/fs-ext4-use-sleeping-version-of-sb_find_get_block.patch @@ -0,0 +1,45 @@ +From 67d1eaa9309f8392416edb8cb6029df7d45a7112 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 17 Apr 2025 18:59:20 -0700 +Subject: fs/ext4: use sleeping version of sb_find_get_block() + +From: Davidlohr Bueso + +[ Upstream commit 6e8f57fd09c9fb569d10b2ccc3878155b702591a ] + +Enable ext4_free_blocks() to use it, which has a cond_resched to begin +with. Convert to the new nonatomic flavor to benefit from potential +performance benefits and adapt in the future vs migration such that +semantics are kept. + +Suggested-by: Jan Kara +Reviewed-by: Jan Kara +Signed-off-by: Davidlohr Bueso +Link: https://kdevops.org/ext4/v6.15-rc2.html # [0] +Link: https://lore.kernel.org/all/aAAEvcrmREWa1SKF@bombadil.infradead.org/ # [1] +Link: https://lore.kernel.org/20250418015921.132400-7-dave@stgolabs.net +Tested-by: kdevops@lists.linux.dev +Reviewed-by: Luis Chamberlain +Signed-off-by: Christian Brauner +Signed-off-by: Sasha Levin +--- + fs/ext4/mballoc.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c +index b25a27c866969..d6f1e61c6dc82 100644 +--- a/fs/ext4/mballoc.c ++++ b/fs/ext4/mballoc.c +@@ -6644,7 +6644,8 @@ void ext4_free_blocks(handle_t *handle, struct inode *inode, + for (i = 0; i < count; i++) { + cond_resched(); + if (is_metadata) +- bh = sb_find_get_block(inode->i_sb, block + i); ++ bh = sb_find_get_block_nonatomic(inode->i_sb, ++ block + i); + ext4_forget(handle, is_metadata, inode, bh, block + i); + } + } +-- +2.39.5 + diff --git a/queue-6.14/fs-jbd2-use-sleeping-version-of-__find_get_block.patch b/queue-6.14/fs-jbd2-use-sleeping-version-of-__find_get_block.patch new file mode 100644 index 0000000000..f2e856d85c --- /dev/null +++ b/queue-6.14/fs-jbd2-use-sleeping-version-of-__find_get_block.patch @@ -0,0 +1,85 @@ +From a4061c347536738f97a53ba0227fb0c2cb193e3c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 17 Apr 2025 18:59:19 -0700 +Subject: fs/jbd2: use sleeping version of __find_get_block() + +From: Davidlohr Bueso + +[ Upstream commit f76d4c28a46a9260d85e00dafc8f46d369365d33 ] + +Convert to the new nonatomic flavor to benefit from potential +performance benefits and adapt in the future vs migration such +that semantics are kept. + +- jbd2_journal_revoke(): can sleep (has might_sleep() in the beginning) + +- jbd2_journal_cancel_revoke(): only used from do_get_write_access() and + do_get_create_access() which do sleep. So can sleep. + +- jbd2_clear_buffer_revoked_flags() - only called from journal commit code + which sleeps. So can sleep. + +Suggested-by: Jan Kara +Reviewed-by: Jan Kara +Signed-off-by: Davidlohr Bueso +Link: https://kdevops.org/ext4/v6.15-rc2.html # [0] +Link: https://lore.kernel.org/all/aAAEvcrmREWa1SKF@bombadil.infradead.org/ # [1] +Link: https://lore.kernel.org/20250418015921.132400-6-dave@stgolabs.net +Tested-by: kdevops@lists.linux.dev +Reviewed-by: Luis Chamberlain +Signed-off-by: Christian Brauner +Signed-off-by: Sasha Levin +--- + fs/jbd2/revoke.c | 15 +++++++++------ + 1 file changed, 9 insertions(+), 6 deletions(-) + +diff --git a/fs/jbd2/revoke.c b/fs/jbd2/revoke.c +index ce63d5fde9c3a..f68fc8c255f00 100644 +--- a/fs/jbd2/revoke.c ++++ b/fs/jbd2/revoke.c +@@ -345,7 +345,8 @@ int jbd2_journal_revoke(handle_t *handle, unsigned long long blocknr, + bh = bh_in; + + if (!bh) { +- bh = __find_get_block(bdev, blocknr, journal->j_blocksize); ++ bh = __find_get_block_nonatomic(bdev, blocknr, ++ journal->j_blocksize); + if (bh) + BUFFER_TRACE(bh, "found on hash"); + } +@@ -355,7 +356,8 @@ int jbd2_journal_revoke(handle_t *handle, unsigned long long blocknr, + + /* If there is a different buffer_head lying around in + * memory anywhere... */ +- bh2 = __find_get_block(bdev, blocknr, journal->j_blocksize); ++ bh2 = __find_get_block_nonatomic(bdev, blocknr, ++ journal->j_blocksize); + if (bh2) { + /* ... and it has RevokeValid status... */ + if (bh2 != bh && buffer_revokevalid(bh2)) +@@ -466,7 +468,8 @@ int jbd2_journal_cancel_revoke(handle_t *handle, struct journal_head *jh) + * state machine will get very upset later on. */ + if (need_cancel) { + struct buffer_head *bh2; +- bh2 = __find_get_block(bh->b_bdev, bh->b_blocknr, bh->b_size); ++ bh2 = __find_get_block_nonatomic(bh->b_bdev, bh->b_blocknr, ++ bh->b_size); + if (bh2) { + if (bh2 != bh) + clear_buffer_revoked(bh2); +@@ -495,9 +498,9 @@ void jbd2_clear_buffer_revoked_flags(journal_t *journal) + struct jbd2_revoke_record_s *record; + struct buffer_head *bh; + record = (struct jbd2_revoke_record_s *)list_entry; +- bh = __find_get_block(journal->j_fs_dev, +- record->blocknr, +- journal->j_blocksize); ++ bh = __find_get_block_nonatomic(journal->j_fs_dev, ++ record->blocknr, ++ journal->j_blocksize); + if (bh) { + clear_buffer_revoked(bh); + __brelse(bh); +-- +2.39.5 + diff --git a/queue-6.14/fs-mpage-avoid-negative-shift-for-large-blocksize.patch b/queue-6.14/fs-mpage-avoid-negative-shift-for-large-blocksize.patch new file mode 100644 index 0000000000..763959be08 --- /dev/null +++ b/queue-6.14/fs-mpage-avoid-negative-shift-for-large-blocksize.patch @@ -0,0 +1,49 @@ +From 937e1cfc23766b242d46fb08e8b736ddd499d0a6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 21 Feb 2025 14:38:18 -0800 +Subject: fs/mpage: avoid negative shift for large blocksize + +From: Hannes Reinecke + +[ Upstream commit 86c60efd7c0ede43bd677f2eee1d84200528df1e ] + +For large blocksizes the number of block bits is larger than PAGE_SHIFT, +so calculate the sector number from the byte offset instead. This is +required to enable large folios with buffer-heads. + +Reviewed-by: "Matthew Wilcox (Oracle)" +Signed-off-by: Luis Chamberlain +Signed-off-by: Hannes Reinecke +Link: https://lore.kernel.org/r/20250221223823.1680616-4-mcgrof@kernel.org +Reviewed-by: Hannes Reinecke +Signed-off-by: Christian Brauner +Signed-off-by: Sasha Levin +--- + fs/mpage.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/fs/mpage.c b/fs/mpage.c +index 82aecf3727437..a3c82206977f6 100644 +--- a/fs/mpage.c ++++ b/fs/mpage.c +@@ -181,7 +181,7 @@ static struct bio *do_mpage_readpage(struct mpage_readpage_args *args) + if (folio_buffers(folio)) + goto confused; + +- block_in_file = (sector_t)folio->index << (PAGE_SHIFT - blkbits); ++ block_in_file = folio_pos(folio) >> blkbits; + last_block = block_in_file + args->nr_pages * blocks_per_page; + last_block_in_file = (i_size_read(inode) + blocksize - 1) >> blkbits; + if (last_block > last_block_in_file) +@@ -527,7 +527,7 @@ static int __mpage_writepage(struct folio *folio, struct writeback_control *wbc, + * The page has no buffers: map it to disk + */ + BUG_ON(!folio_test_uptodate(folio)); +- block_in_file = (sector_t)folio->index << (PAGE_SHIFT - blkbits); ++ block_in_file = folio_pos(folio) >> blkbits; + /* + * Whole page beyond EOF? Skip allocating blocks to avoid leaking + * space. +-- +2.39.5 + diff --git a/queue-6.14/fs-ocfs2-use-sleeping-version-of-__find_get_block.patch b/queue-6.14/fs-ocfs2-use-sleeping-version-of-__find_get_block.patch new file mode 100644 index 0000000000..7a9331caf6 --- /dev/null +++ b/queue-6.14/fs-ocfs2-use-sleeping-version-of-__find_get_block.patch @@ -0,0 +1,44 @@ +From a3852ebdb8e968832e9aeb479865bb5869600cff Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 17 Apr 2025 18:59:18 -0700 +Subject: fs/ocfs2: use sleeping version of __find_get_block() + +From: Davidlohr Bueso + +[ Upstream commit a0b5ff07491010789fcb012bc8f9dad9d26f9a8b ] + +This is a path that allows for blocking as it does IO. Convert +to the new nonatomic flavor to benefit from potential performance +benefits and adapt in the future vs migration such that semantics +are kept. + +Suggested-by: Jan Kara +Reviewed-by: Jan Kara +Signed-off-by: Davidlohr Bueso +Link: https://kdevops.org/ext4/v6.15-rc2.html # [0] +Link: https://lore.kernel.org/all/aAAEvcrmREWa1SKF@bombadil.infradead.org/ # [1] +Link: https://lore.kernel.org/20250418015921.132400-5-dave@stgolabs.net +Tested-by: kdevops@lists.linux.dev +Reviewed-by: Luis Chamberlain +Signed-off-by: Christian Brauner +Signed-off-by: Sasha Levin +--- + fs/ocfs2/journal.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/fs/ocfs2/journal.c b/fs/ocfs2/journal.c +index f37831d5f95a1..e5f58ff2175f4 100644 +--- a/fs/ocfs2/journal.c ++++ b/fs/ocfs2/journal.c +@@ -1271,7 +1271,7 @@ static int ocfs2_force_read_journal(struct inode *inode) + } + + for (i = 0; i < p_blocks; i++, p_blkno++) { +- bh = __find_get_block(osb->sb->s_bdev, p_blkno, ++ bh = __find_get_block_nonatomic(osb->sb->s_bdev, p_blkno, + osb->sb->s_blocksize); + /* block not cached. */ + if (!bh) +-- +2.39.5 + diff --git a/queue-6.14/fs-pipe-limit-the-slots-in-pipe_resize_ring.patch b/queue-6.14/fs-pipe-limit-the-slots-in-pipe_resize_ring.patch new file mode 100644 index 0000000000..a6acbc70c7 --- /dev/null +++ b/queue-6.14/fs-pipe-limit-the-slots-in-pipe_resize_ring.patch @@ -0,0 +1,42 @@ +From 291eda3996e7006d851c35c2ec71d5ef2fba5239 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 7 Mar 2025 05:29:16 +0000 +Subject: fs/pipe: Limit the slots in pipe_resize_ring() + +From: K Prateek Nayak + +[ Upstream commit cf3d0c54b21c4a351d4f94cf188e9715dbd1ef5b ] + +Limit the number of slots in pipe_resize_ring() to the maximum value +representable by pipe->{head,tail}. Values beyond the max limit can +lead to incorrect pipe occupancy related calculations where the pipe +will never appear full. + +Suggested-by: Linus Torvalds +Signed-off-by: K Prateek Nayak +Link: https://lore.kernel.org/r/20250307052919.34542-2-kprateek.nayak@amd.com +Reviewed-by: Oleg Nesterov +Signed-off-by: Christian Brauner +Signed-off-by: Sasha Levin +--- + fs/pipe.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/fs/pipe.c b/fs/pipe.c +index 4d0799e4e7196..88e81f84e3eaf 100644 +--- a/fs/pipe.c ++++ b/fs/pipe.c +@@ -1271,6 +1271,10 @@ int pipe_resize_ring(struct pipe_inode_info *pipe, unsigned int nr_slots) + struct pipe_buffer *bufs; + unsigned int head, tail, mask, n; + ++ /* nr_slots larger than limits of pipe->{head,tail} */ ++ if (unlikely(nr_slots > (pipe_index_t)-1u)) ++ return -EINVAL; ++ + bufs = kcalloc(nr_slots, sizeof(*bufs), + GFP_KERNEL_ACCOUNT | __GFP_NOWARN); + if (unlikely(!bufs)) +-- +2.39.5 + diff --git a/queue-6.14/fuse-return-eperm-rather-than-enosys-from-link.patch b/queue-6.14/fuse-return-eperm-rather-than-enosys-from-link.patch new file mode 100644 index 0000000000..c944fa1d85 --- /dev/null +++ b/queue-6.14/fuse-return-eperm-rather-than-enosys-from-link.patch @@ -0,0 +1,36 @@ +From 6c17944fdf2d4e756ff2d38c94df7400ed7f5b65 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 14 Feb 2025 09:17:53 +0800 +Subject: fuse: Return EPERM rather than ENOSYS from link() + +From: Matt Johnston + +[ Upstream commit 8344213571b2ac8caf013cfd3b37bc3467c3a893 ] + +link() is documented to return EPERM when a filesystem doesn't support +the operation, return that instead. + +Link: https://github.com/libfuse/libfuse/issues/925 +Signed-off-by: Matt Johnston +Signed-off-by: Miklos Szeredi +Signed-off-by: Sasha Levin +--- + fs/fuse/dir.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c +index 3b031d24d3691..8f699c67561fa 100644 +--- a/fs/fuse/dir.c ++++ b/fs/fuse/dir.c +@@ -1137,6 +1137,8 @@ static int fuse_link(struct dentry *entry, struct inode *newdir, + else if (err == -EINTR) + fuse_invalidate_attr(inode); + ++ if (err == -ENOSYS) ++ err = -EPERM; + return err; + } + +-- +2.39.5 + diff --git a/queue-6.14/genirq-msi-store-the-iommu-iova-directly-in-msi_desc.patch b/queue-6.14/genirq-msi-store-the-iommu-iova-directly-in-msi_desc.patch new file mode 100644 index 0000000000..be72d7009f --- /dev/null +++ b/queue-6.14/genirq-msi-store-the-iommu-iova-directly-in-msi_desc.patch @@ -0,0 +1,175 @@ +From d26e9c8a5bcc241f84ce588eed332fa6059425f3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 19 Feb 2025 17:31:36 -0800 +Subject: genirq/msi: Store the IOMMU IOVA directly in msi_desc instead of + iommu_cookie + +From: Jason Gunthorpe + +[ Upstream commit 1f7df3a691740a7736bbc99dc4ed536120eb4746 ] + +The IOMMU translation for MSI message addresses has been a 2-step process, +separated in time: + + 1) iommu_dma_prepare_msi(): A cookie pointer containing the IOVA address + is stored in the MSI descriptor when an MSI interrupt is allocated. + + 2) iommu_dma_compose_msi_msg(): this cookie pointer is used to compute a + translated message address. + +This has an inherent lifetime problem for the pointer stored in the cookie +that must remain valid between the two steps. However, there is no locking +at the irq layer that helps protect the lifetime. Today, this works under +the assumption that the iommu domain is not changed while MSI interrupts +being programmed. This is true for normal DMA API users within the kernel, +as the iommu domain is attached before the driver is probed and cannot be +changed while a driver is attached. + +Classic VFIO type1 also prevented changing the iommu domain while VFIO was +running as it does not support changing the "container" after starting up. + +However, iommufd has improved this so that the iommu domain can be changed +during VFIO operation. This potentially allows userspace to directly race +VFIO_DEVICE_ATTACH_IOMMUFD_PT (which calls iommu_attach_group()) and +VFIO_DEVICE_SET_IRQS (which calls into iommu_dma_compose_msi_msg()). + +This potentially causes both the cookie pointer and the unlocked call to +iommu_get_domain_for_dev() on the MSI translation path to become UAFs. + +Fix the MSI cookie UAF by removing the cookie pointer. The translated IOVA +address is already known during iommu_dma_prepare_msi() and cannot change. +Thus, it can simply be stored as an integer in the MSI descriptor. + +The other UAF related to iommu_get_domain_for_dev() will be addressed in +patch "iommu: Make iommu_dma_prepare_msi() into a generic operation" by +using the IOMMU group mutex. + +Link: https://patch.msgid.link/r/a4f2cd76b9dc1833ee6c1cf325cba57def22231c.1740014950.git.nicolinc@nvidia.com +Signed-off-by: Nicolin Chen +Reviewed-by: Thomas Gleixner +Signed-off-by: Jason Gunthorpe +Signed-off-by: Sasha Levin +--- + drivers/iommu/dma-iommu.c | 28 +++++++++++++--------------- + include/linux/msi.h | 33 ++++++++++++--------------------- + 2 files changed, 25 insertions(+), 36 deletions(-) + +diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c +index 2a9fa0c8cc00f..0f0caf59023c7 100644 +--- a/drivers/iommu/dma-iommu.c ++++ b/drivers/iommu/dma-iommu.c +@@ -1815,7 +1815,7 @@ int iommu_dma_prepare_msi(struct msi_desc *desc, phys_addr_t msi_addr) + static DEFINE_MUTEX(msi_prepare_lock); /* see below */ + + if (!domain || !domain->iova_cookie) { +- desc->iommu_cookie = NULL; ++ msi_desc_set_iommu_msi_iova(desc, 0, 0); + return 0; + } + +@@ -1827,11 +1827,12 @@ int iommu_dma_prepare_msi(struct msi_desc *desc, phys_addr_t msi_addr) + mutex_lock(&msi_prepare_lock); + msi_page = iommu_dma_get_msi_page(dev, msi_addr, domain); + mutex_unlock(&msi_prepare_lock); +- +- msi_desc_set_iommu_cookie(desc, msi_page); +- + if (!msi_page) + return -ENOMEM; ++ ++ msi_desc_set_iommu_msi_iova( ++ desc, msi_page->iova, ++ ilog2(cookie_msi_granule(domain->iova_cookie))); + return 0; + } + +@@ -1842,18 +1843,15 @@ int iommu_dma_prepare_msi(struct msi_desc *desc, phys_addr_t msi_addr) + */ + void iommu_dma_compose_msi_msg(struct msi_desc *desc, struct msi_msg *msg) + { +- struct device *dev = msi_desc_to_dev(desc); +- const struct iommu_domain *domain = iommu_get_domain_for_dev(dev); +- const struct iommu_dma_msi_page *msi_page; ++#ifdef CONFIG_IRQ_MSI_IOMMU ++ if (desc->iommu_msi_shift) { ++ u64 msi_iova = desc->iommu_msi_iova << desc->iommu_msi_shift; + +- msi_page = msi_desc_get_iommu_cookie(desc); +- +- if (!domain || !domain->iova_cookie || WARN_ON(!msi_page)) +- return; +- +- msg->address_hi = upper_32_bits(msi_page->iova); +- msg->address_lo &= cookie_msi_granule(domain->iova_cookie) - 1; +- msg->address_lo += lower_32_bits(msi_page->iova); ++ msg->address_hi = upper_32_bits(msi_iova); ++ msg->address_lo = lower_32_bits(msi_iova) | ++ (msg->address_lo & ((1 << desc->iommu_msi_shift) - 1)); ++ } ++#endif + } + + static int iommu_dma_init(void) +diff --git a/include/linux/msi.h b/include/linux/msi.h +index 59a421fc42bf0..63d0e51f7a801 100644 +--- a/include/linux/msi.h ++++ b/include/linux/msi.h +@@ -165,6 +165,10 @@ struct msi_desc_data { + * @dev: Pointer to the device which uses this descriptor + * @msg: The last set MSI message cached for reuse + * @affinity: Optional pointer to a cpu affinity mask for this descriptor ++ * @iommu_msi_iova: Optional shifted IOVA from the IOMMU to override the msi_addr. ++ * Only used if iommu_msi_shift != 0 ++ * @iommu_msi_shift: Indicates how many bits of the original address should be ++ * preserved when using iommu_msi_iova. + * @sysfs_attr: Pointer to sysfs device attribute + * + * @write_msi_msg: Callback that may be called when the MSI message +@@ -183,7 +187,8 @@ struct msi_desc { + struct msi_msg msg; + struct irq_affinity_desc *affinity; + #ifdef CONFIG_IRQ_MSI_IOMMU +- const void *iommu_cookie; ++ u64 iommu_msi_iova : 58; ++ u64 iommu_msi_shift : 6; + #endif + #ifdef CONFIG_SYSFS + struct device_attribute *sysfs_attrs; +@@ -284,28 +289,14 @@ struct msi_desc *msi_next_desc(struct device *dev, unsigned int domid, + + #define msi_desc_to_dev(desc) ((desc)->dev) + +-#ifdef CONFIG_IRQ_MSI_IOMMU +-static inline const void *msi_desc_get_iommu_cookie(struct msi_desc *desc) +-{ +- return desc->iommu_cookie; +-} +- +-static inline void msi_desc_set_iommu_cookie(struct msi_desc *desc, +- const void *iommu_cookie) +-{ +- desc->iommu_cookie = iommu_cookie; +-} +-#else +-static inline const void *msi_desc_get_iommu_cookie(struct msi_desc *desc) ++static inline void msi_desc_set_iommu_msi_iova(struct msi_desc *desc, u64 msi_iova, ++ unsigned int msi_shift) + { +- return NULL; +-} +- +-static inline void msi_desc_set_iommu_cookie(struct msi_desc *desc, +- const void *iommu_cookie) +-{ +-} ++#ifdef CONFIG_IRQ_MSI_IOMMU ++ desc->iommu_msi_iova = msi_iova >> msi_shift; ++ desc->iommu_msi_shift = msi_shift; + #endif ++} + + int msi_domain_insert_msi_desc(struct device *dev, unsigned int domid, + struct msi_desc *init_desc); +-- +2.39.5 + diff --git a/queue-6.14/gfs2-check-for-empty-queue-in-run_queue.patch b/queue-6.14/gfs2-check-for-empty-queue-in-run_queue.patch new file mode 100644 index 0000000000..d030a34baf --- /dev/null +++ b/queue-6.14/gfs2-check-for-empty-queue-in-run_queue.patch @@ -0,0 +1,65 @@ +From c491e26fc1178764776e620ddf7355104eedda75 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Feb 2025 14:58:39 +0100 +Subject: gfs2: Check for empty queue in run_queue + +From: Andreas Gruenbacher + +[ Upstream commit d838605fea6eabae3746a276fd448f6719eb3926 ] + +In run_queue(), check if the queue of pending requests is empty instead +of blindly assuming that it won't be. + +Signed-off-by: Andreas Gruenbacher +Signed-off-by: Sasha Levin +--- + fs/gfs2/glock.c | 11 ++++++++--- + 1 file changed, 8 insertions(+), 3 deletions(-) + +diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c +index 65c07aa957184..7f9cc7872214e 100644 +--- a/fs/gfs2/glock.c ++++ b/fs/gfs2/glock.c +@@ -843,12 +843,13 @@ static void run_queue(struct gfs2_glock *gl, const int nonblock) + __releases(&gl->gl_lockref.lock) + __acquires(&gl->gl_lockref.lock) + { +- struct gfs2_holder *gh = NULL; ++ struct gfs2_holder *gh; + + if (test_bit(GLF_LOCK, &gl->gl_flags)) + return; + set_bit(GLF_LOCK, &gl->gl_flags); + ++ /* While a demote is in progress, the GLF_LOCK flag must be set. */ + GLOCK_BUG_ON(gl, test_bit(GLF_DEMOTE_IN_PROGRESS, &gl->gl_flags)); + + if (test_bit(GLF_DEMOTE, &gl->gl_flags) && +@@ -860,18 +861,22 @@ __acquires(&gl->gl_lockref.lock) + set_bit(GLF_DEMOTE_IN_PROGRESS, &gl->gl_flags); + GLOCK_BUG_ON(gl, gl->gl_demote_state == LM_ST_EXCLUSIVE); + gl->gl_target = gl->gl_demote_state; ++ do_xmote(gl, NULL, gl->gl_target); ++ return; + } else { + if (test_bit(GLF_DEMOTE, &gl->gl_flags)) + gfs2_demote_wake(gl); + if (do_promote(gl)) + goto out_unlock; + gh = find_first_waiter(gl); ++ if (!gh) ++ goto out_unlock; + gl->gl_target = gh->gh_state; + if (!(gh->gh_flags & (LM_FLAG_TRY | LM_FLAG_TRY_1CB))) + do_error(gl, 0); /* Fail queued try locks */ ++ do_xmote(gl, gh, gl->gl_target); ++ return; + } +- do_xmote(gl, gh, gl->gl_target); +- return; + + out_sched: + clear_bit(GLF_LOCK, &gl->gl_flags); +-- +2.39.5 + diff --git a/queue-6.14/gpiolib-sanitize-the-return-value-of-gpio_chip-set_c.patch b/queue-6.14/gpiolib-sanitize-the-return-value-of-gpio_chip-set_c.patch new file mode 100644 index 0000000000..7fae52584d --- /dev/null +++ b/queue-6.14/gpiolib-sanitize-the-return-value-of-gpio_chip-set_c.patch @@ -0,0 +1,54 @@ +From af03790585ce16bcf4f8c4e7526ee8fd935042e2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 10 Feb 2025 11:51:57 +0100 +Subject: gpiolib: sanitize the return value of gpio_chip::set_config() + +From: Bartosz Golaszewski + +[ Upstream commit dcf8f3bffa2de2c7f3b5771b63605194ccd2286f ] + +The return value of the set_config() callback may be propagated to +user-space. If a bad driver returns a positive number, it may confuse +user programs. Tighten the API contract and check for positive numbers +returned by GPIO controllers. + +Reviewed-by: Linus Walleij +Link: https://lore.kernel.org/r/20250210-gpio-sanitize-retvals-v1-3-12ea88506cb2@linaro.org +Signed-off-by: Bartosz Golaszewski +Signed-off-by: Sasha Levin +--- + drivers/gpio/gpiolib.c | 3 +++ + include/linux/gpio/driver.h | 3 ++- + 2 files changed, 5 insertions(+), 1 deletion(-) + +diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c +index 0c00ed2ab4315..960ca0ad45fc8 100644 +--- a/drivers/gpio/gpiolib.c ++++ b/drivers/gpio/gpiolib.c +@@ -2577,6 +2577,9 @@ int gpio_do_set_config(struct gpio_desc *desc, unsigned long config) + return -ENOTSUPP; + + ret = guard.gc->set_config(guard.gc, gpio_chip_hwgpio(desc), config); ++ if (ret > 0) ++ ret = -EBADE; ++ + #ifdef CONFIG_GPIO_CDEV + /* + * Special case - if we're setting debounce period, we need to store +diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h +index 2dd7cb9cc270a..5ce6b2167f808 100644 +--- a/include/linux/gpio/driver.h ++++ b/include/linux/gpio/driver.h +@@ -347,7 +347,8 @@ struct gpio_irq_chip { + * @set: assigns output value for signal "offset" + * @set_multiple: assigns output values for multiple signals defined by "mask" + * @set_config: optional hook for all kinds of settings. Uses the same +- * packed config format as generic pinconf. ++ * packed config format as generic pinconf. Must return 0 on success and ++ * a negative error number on failure. + * @to_irq: optional hook supporting non-static gpiod_to_irq() mappings; + * implementation may not sleep + * @dbg_show: optional routine to show contents in debugfs; default code +-- +2.39.5 + diff --git a/queue-6.14/hid-kconfig-add-leds_class_multicolor-dependency-to-.patch b/queue-6.14/hid-kconfig-add-leds_class_multicolor-dependency-to-.patch new file mode 100644 index 0000000000..1a3a79ad8b --- /dev/null +++ b/queue-6.14/hid-kconfig-add-leds_class_multicolor-dependency-to-.patch @@ -0,0 +1,47 @@ +From 501a0f03d5711376812ce0312fd50e73c82d8b23 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 11 Feb 2025 13:02:40 +0800 +Subject: HID: Kconfig: Add LEDS_CLASS_MULTICOLOR dependency to HID_LOGITECH + +From: Kate Hsuan + +[ Upstream commit 4465f4fa21e0e54c10896db3ed49dbd5a9aad3fd ] + +The test bot found an issue with building hid-lg-g15. + +All errors (new ones prefixed by >>): + + powerpc-linux-ld: drivers/hid/hid-lg-g15.o: in function `lg_g510_kbd_led_write': +>> drivers/hid/hid-lg-g15.c:241:(.text+0x768): undefined reference to `led_mc_calc_color_components' + powerpc-linux-ld: drivers/hid/hid-lg-g15.o: in function `lg_g15_register_led': +>> drivers/hid/hid-lg-g15.c:686:(.text+0xa9c): undefined reference to `devm_led_classdev_multicolor_register_ext' + +Since multicolor LED APIs manage the keyboard backlight settings of +hid-lg-g15, the LEDS_CLASS_MULTICOLOR dependency was added to +HID_LOGITECH. + +Reported-by: kernel test robot +Closes: https://lore.kernel.org/oe-kbuild-all/202502110032.VZ0J024X-lkp@intel.com/ +Fixes: a3a064146c50 ("HID: hid-lg-g15: Use standard multicolor LED API") +Signed-off-by: Kate Hsuan +Signed-off-by: Jiri Kosina +Signed-off-by: Sasha Levin +--- + drivers/hid/Kconfig | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig +index 4cfea399ebab2..76be97c5fc2ff 100644 +--- a/drivers/hid/Kconfig ++++ b/drivers/hid/Kconfig +@@ -603,6 +603,7 @@ config HID_LOGITECH + tristate "Logitech devices" + depends on USB_HID + depends on LEDS_CLASS ++ depends on LEDS_CLASS_MULTICOLOR + default !EXPERT + help + Support for Logitech devices that are not fully compliant with HID standard. +-- +2.39.5 + diff --git a/queue-6.14/hid-usbkbd-fix-the-bit-shift-number-for-led_kana.patch b/queue-6.14/hid-usbkbd-fix-the-bit-shift-number-for-led_kana.patch new file mode 100644 index 0000000000..628f1ff552 --- /dev/null +++ b/queue-6.14/hid-usbkbd-fix-the-bit-shift-number-for-led_kana.patch @@ -0,0 +1,34 @@ +From 72164a0dc90f927fdaf693703fea47a3758b2f76 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 28 Nov 2024 10:35:18 +0800 +Subject: HID: usbkbd: Fix the bit shift number for LED_KANA + +From: junan + +[ Upstream commit d73a4bfa2881a6859b384b75a414c33d4898b055 ] + +Since "LED_KANA" was defined as "0x04", the shift number should be "4". + +Signed-off-by: junan +Signed-off-by: Jiri Kosina +Signed-off-by: Sasha Levin +--- + drivers/hid/usbhid/usbkbd.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/hid/usbhid/usbkbd.c b/drivers/hid/usbhid/usbkbd.c +index c439ed2f16dbc..af6bc76dbf649 100644 +--- a/drivers/hid/usbhid/usbkbd.c ++++ b/drivers/hid/usbhid/usbkbd.c +@@ -160,7 +160,7 @@ static int usb_kbd_event(struct input_dev *dev, unsigned int type, + return -1; + + spin_lock_irqsave(&kbd->leds_lock, flags); +- kbd->newleds = (!!test_bit(LED_KANA, dev->led) << 3) | (!!test_bit(LED_COMPOSE, dev->led) << 3) | ++ kbd->newleds = (!!test_bit(LED_KANA, dev->led) << 4) | (!!test_bit(LED_COMPOSE, dev->led) << 3) | + (!!test_bit(LED_SCROLLL, dev->led) << 2) | (!!test_bit(LED_CAPSL, dev->led) << 1) | + (!!test_bit(LED_NUML, dev->led)); + +-- +2.39.5 + diff --git a/queue-6.14/hrtimers-replace-hrtimer_clock_to_base_table-with-sw.patch b/queue-6.14/hrtimers-replace-hrtimer_clock_to_base_table-with-sw.patch new file mode 100644 index 0000000000..d41a4351c2 --- /dev/null +++ b/queue-6.14/hrtimers-replace-hrtimer_clock_to_base_table-with-sw.patch @@ -0,0 +1,87 @@ +From 0fd65f3a3f2676a3714497a7ffad1dd6dcbd3c2a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 14 Feb 2025 15:43:33 +0200 +Subject: hrtimers: Replace hrtimer_clock_to_base_table with switch-case + +From: Andy Shevchenko + +[ Upstream commit 4441b976dfeff0d3579e8da3c0283300c618a553 ] + +Clang and GCC complain about overlapped initialisers in the +hrtimer_clock_to_base_table definition. With `make W=1` and CONFIG_WERROR=y +(which is default nowadays) this breaks the build: + + CC kernel/time/hrtimer.o +kernel/time/hrtimer.c:124:21: error: initializer overrides prior initialization of this subobject [-Werror,-Winitializer-overrides] + 124 | [CLOCK_REALTIME] = HRTIMER_BASE_REALTIME, + +kernel/time/hrtimer.c:122:27: note: previous initialization is here + 122 | [0 ... MAX_CLOCKS - 1] = HRTIMER_MAX_CLOCK_BASES, + +(and similar for CLOCK_MONOTONIC, CLOCK_BOOTTIME, and CLOCK_TAI). + +hrtimer_clockid_to_base(), which uses the table, is only used in +__hrtimer_init(), which is not a hotpath. + +Therefore replace the table lookup with a switch case in +hrtimer_clockid_to_base() to avoid this warning. + +Signed-off-by: Andy Shevchenko +Signed-off-by: Thomas Gleixner +Link: https://lore.kernel.org/all/20250214134424.3367619-1-andriy.shevchenko@linux.intel.com +Signed-off-by: Sasha Levin +--- + kernel/time/hrtimer.c | 29 ++++++++++++----------------- + 1 file changed, 12 insertions(+), 17 deletions(-) + +diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c +index deb1aa32814e3..453dc76c93484 100644 +--- a/kernel/time/hrtimer.c ++++ b/kernel/time/hrtimer.c +@@ -117,16 +117,6 @@ DEFINE_PER_CPU(struct hrtimer_cpu_base, hrtimer_bases) = + .csd = CSD_INIT(retrigger_next_event, NULL) + }; + +-static const int hrtimer_clock_to_base_table[MAX_CLOCKS] = { +- /* Make sure we catch unsupported clockids */ +- [0 ... MAX_CLOCKS - 1] = HRTIMER_MAX_CLOCK_BASES, +- +- [CLOCK_REALTIME] = HRTIMER_BASE_REALTIME, +- [CLOCK_MONOTONIC] = HRTIMER_BASE_MONOTONIC, +- [CLOCK_BOOTTIME] = HRTIMER_BASE_BOOTTIME, +- [CLOCK_TAI] = HRTIMER_BASE_TAI, +-}; +- + static inline bool hrtimer_base_is_online(struct hrtimer_cpu_base *base) + { + if (!IS_ENABLED(CONFIG_HOTPLUG_CPU)) +@@ -1587,14 +1577,19 @@ u64 hrtimer_next_event_without(const struct hrtimer *exclude) + + static inline int hrtimer_clockid_to_base(clockid_t clock_id) + { +- if (likely(clock_id < MAX_CLOCKS)) { +- int base = hrtimer_clock_to_base_table[clock_id]; +- +- if (likely(base != HRTIMER_MAX_CLOCK_BASES)) +- return base; ++ switch (clock_id) { ++ case CLOCK_REALTIME: ++ return HRTIMER_BASE_REALTIME; ++ case CLOCK_MONOTONIC: ++ return HRTIMER_BASE_MONOTONIC; ++ case CLOCK_BOOTTIME: ++ return HRTIMER_BASE_BOOTTIME; ++ case CLOCK_TAI: ++ return HRTIMER_BASE_TAI; ++ default: ++ WARN(1, "Invalid clockid %d. Using MONOTONIC\n", clock_id); ++ return HRTIMER_BASE_MONOTONIC; + } +- WARN(1, "Invalid clockid %d. Using MONOTONIC\n", clock_id); +- return HRTIMER_BASE_MONOTONIC; + } + + static enum hrtimer_restart hrtimer_dummy_timeout(struct hrtimer *unused) +-- +2.39.5 + diff --git a/queue-6.14/hwmon-acpi_power_meter-fix-the-fake-power-alarm-repo.patch b/queue-6.14/hwmon-acpi_power_meter-fix-the-fake-power-alarm-repo.patch new file mode 100644 index 0000000000..eddfeb2520 --- /dev/null +++ b/queue-6.14/hwmon-acpi_power_meter-fix-the-fake-power-alarm-repo.patch @@ -0,0 +1,51 @@ +From 850a3519bd043a4d8ace6e69901955941212e680 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 20 Feb 2025 11:08:32 +0800 +Subject: hwmon: (acpi_power_meter) Fix the fake power alarm reporting + +From: Huisong Li + +[ Upstream commit 0ea627381eb527a0ebd262c690c3992085b87ff4 ] + +We encountered a problem that a fake power alarm is reported to +user on the platform unsupported notifications at the second step +below: +1> Query 'power1_alarm' attribute when the power capping occurs. +2> Query 'power1_alarm' attribute when the power capping is over + and the current average power is less then power cap value. + +The root cause is that the resource->power_alarm is set to true +at the first step. And power meter use this old value to show +the power alarm state instead of the current the comparison value. + +Signed-off-by: Huisong Li +Link: https://lore.kernel.org/r/20250220030832.2976-1-lihuisong@huawei.com +Signed-off-by: Guenter Roeck +Signed-off-by: Sasha Levin +--- + drivers/hwmon/acpi_power_meter.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/drivers/hwmon/acpi_power_meter.c b/drivers/hwmon/acpi_power_meter.c +index 44afb07409a46..f05986e4f3792 100644 +--- a/drivers/hwmon/acpi_power_meter.c ++++ b/drivers/hwmon/acpi_power_meter.c +@@ -437,9 +437,13 @@ static ssize_t show_val(struct device *dev, + ret = update_cap(resource); + if (ret) + return ret; ++ resource->power_alarm = resource->power > resource->cap; ++ val = resource->power_alarm; ++ } else { ++ val = resource->power_alarm || ++ resource->power > resource->cap; ++ resource->power_alarm = resource->power > resource->cap; + } +- val = resource->power_alarm || resource->power > resource->cap; +- resource->power_alarm = resource->power > resource->cap; + break; + case 7: + case 8: +-- +2.39.5 + diff --git a/queue-6.14/hwmon-dell-smm-increment-the-number-of-fans.patch b/queue-6.14/hwmon-dell-smm-increment-the-number-of-fans.patch new file mode 100644 index 0000000000..b3f9a2d4dd --- /dev/null +++ b/queue-6.14/hwmon-dell-smm-increment-the-number-of-fans.patch @@ -0,0 +1,86 @@ +From 808bf9be5bf2abd483c7fda1aacfd43866cc3891 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 4 Mar 2025 00:52:50 -0500 +Subject: hwmon: (dell-smm) Increment the number of fans + +From: Kurt Borja + +[ Upstream commit dbcfcb239b3b452ef8782842c36fb17dd1b9092f ] + +Some Alienware laptops that support the SMM interface, may have up to 4 +fans. + +Tested on an Alienware x15 r1. + +Signed-off-by: Kurt Borja +Link: https://lore.kernel.org/r/20250304055249.51940-2-kuurtb@gmail.com +Signed-off-by: Guenter Roeck +Signed-off-by: Sasha Levin +--- + Documentation/hwmon/dell-smm-hwmon.rst | 14 +++++++------- + drivers/hwmon/dell-smm-hwmon.c | 5 ++++- + 2 files changed, 11 insertions(+), 8 deletions(-) + +diff --git a/Documentation/hwmon/dell-smm-hwmon.rst b/Documentation/hwmon/dell-smm-hwmon.rst +index 74905675d71f9..5a4edb6565cf9 100644 +--- a/Documentation/hwmon/dell-smm-hwmon.rst ++++ b/Documentation/hwmon/dell-smm-hwmon.rst +@@ -32,12 +32,12 @@ Temperature sensors and fans can be queried and set via the standard + =============================== ======= ======================================= + Name Perm Description + =============================== ======= ======================================= +-fan[1-3]_input RO Fan speed in RPM. +-fan[1-3]_label RO Fan label. +-fan[1-3]_min RO Minimal Fan speed in RPM +-fan[1-3]_max RO Maximal Fan speed in RPM +-fan[1-3]_target RO Expected Fan speed in RPM +-pwm[1-3] RW Control the fan PWM duty-cycle. ++fan[1-4]_input RO Fan speed in RPM. ++fan[1-4]_label RO Fan label. ++fan[1-4]_min RO Minimal Fan speed in RPM ++fan[1-4]_max RO Maximal Fan speed in RPM ++fan[1-4]_target RO Expected Fan speed in RPM ++pwm[1-4] RW Control the fan PWM duty-cycle. + pwm1_enable WO Enable or disable automatic BIOS fan + control (not supported on all laptops, + see below for details). +@@ -93,7 +93,7 @@ Again, when you find new codes, we'd be happy to have your patches! + --------------------------- + + The driver also exports the fans as thermal cooling devices with +-``type`` set to ``dell-smm-fan[1-3]``. This allows for easy fan control ++``type`` set to ``dell-smm-fan[1-4]``. This allows for easy fan control + using one of the thermal governors. + + Module parameters +diff --git a/drivers/hwmon/dell-smm-hwmon.c b/drivers/hwmon/dell-smm-hwmon.c +index cd00adaad1b41..79e5606e6d2f8 100644 +--- a/drivers/hwmon/dell-smm-hwmon.c ++++ b/drivers/hwmon/dell-smm-hwmon.c +@@ -73,7 +73,7 @@ + #define DELL_SMM_LEGACY_EXECUTE 0x1 + + #define DELL_SMM_NO_TEMP 10 +-#define DELL_SMM_NO_FANS 3 ++#define DELL_SMM_NO_FANS 4 + + struct smm_regs { + unsigned int eax; +@@ -1074,11 +1074,14 @@ static const struct hwmon_channel_info * const dell_smm_info[] = { + HWMON_F_INPUT | HWMON_F_LABEL | HWMON_F_MIN | HWMON_F_MAX | + HWMON_F_TARGET, + HWMON_F_INPUT | HWMON_F_LABEL | HWMON_F_MIN | HWMON_F_MAX | ++ HWMON_F_TARGET, ++ HWMON_F_INPUT | HWMON_F_LABEL | HWMON_F_MIN | HWMON_F_MAX | + HWMON_F_TARGET + ), + HWMON_CHANNEL_INFO(pwm, + HWMON_PWM_INPUT | HWMON_PWM_ENABLE, + HWMON_PWM_INPUT, ++ HWMON_PWM_INPUT, + HWMON_PWM_INPUT + ), + NULL +-- +2.39.5 + diff --git a/queue-6.14/hwmon-gpio-fan-add-missing-mutex-locks.patch b/queue-6.14/hwmon-gpio-fan-add-missing-mutex-locks.patch new file mode 100644 index 0000000000..947338c194 --- /dev/null +++ b/queue-6.14/hwmon-gpio-fan-add-missing-mutex-locks.patch @@ -0,0 +1,75 @@ +From 9a9a19893cb7a9921d8292a2f8ece75d809b9ce7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 10 Feb 2025 15:59:30 +0100 +Subject: hwmon: (gpio-fan) Add missing mutex locks + +From: Alexander Stein + +[ Upstream commit 9fee7d19bab635f89223cc40dfd2c8797fdc4988 ] + +set_fan_speed() is expected to be called with fan_data->lock being locked. +Add locking for proper synchronization. + +Signed-off-by: Alexander Stein +Link: https://lore.kernel.org/r/20250210145934.761280-3-alexander.stein@ew.tq-group.com +Signed-off-by: Guenter Roeck +Signed-off-by: Sasha Levin +--- + drivers/hwmon/gpio-fan.c | 16 +++++++++++++++- + 1 file changed, 15 insertions(+), 1 deletion(-) + +diff --git a/drivers/hwmon/gpio-fan.c b/drivers/hwmon/gpio-fan.c +index d92c536be9af7..b779240328d59 100644 +--- a/drivers/hwmon/gpio-fan.c ++++ b/drivers/hwmon/gpio-fan.c +@@ -393,7 +393,12 @@ static int gpio_fan_set_cur_state(struct thermal_cooling_device *cdev, + if (state >= fan_data->num_speed) + return -EINVAL; + ++ mutex_lock(&fan_data->lock); ++ + set_fan_speed(fan_data, state); ++ ++ mutex_unlock(&fan_data->lock); ++ + return 0; + } + +@@ -489,7 +494,11 @@ MODULE_DEVICE_TABLE(of, of_gpio_fan_match); + + static void gpio_fan_stop(void *data) + { ++ struct gpio_fan_data *fan_data = data; ++ ++ mutex_lock(&fan_data->lock); + set_fan_speed(data, 0); ++ mutex_unlock(&fan_data->lock); + } + + static int gpio_fan_probe(struct platform_device *pdev) +@@ -562,7 +571,9 @@ static int gpio_fan_suspend(struct device *dev) + + if (fan_data->gpios) { + fan_data->resume_speed = fan_data->speed_index; ++ mutex_lock(&fan_data->lock); + set_fan_speed(fan_data, 0); ++ mutex_unlock(&fan_data->lock); + } + + return 0; +@@ -572,8 +583,11 @@ static int gpio_fan_resume(struct device *dev) + { + struct gpio_fan_data *fan_data = dev_get_drvdata(dev); + +- if (fan_data->gpios) ++ if (fan_data->gpios) { ++ mutex_lock(&fan_data->lock); + set_fan_speed(fan_data, fan_data->resume_speed); ++ mutex_unlock(&fan_data->lock); ++ } + + return 0; + } +-- +2.39.5 + diff --git a/queue-6.14/hwmon-xgene-hwmon-use-appropriate-type-for-the-laten.patch b/queue-6.14/hwmon-xgene-hwmon-use-appropriate-type-for-the-laten.patch new file mode 100644 index 0000000000..2127f8752b --- /dev/null +++ b/queue-6.14/hwmon-xgene-hwmon-use-appropriate-type-for-the-laten.patch @@ -0,0 +1,45 @@ +From 9ba25745c1d8571e570d5395c96e0e998afc88e6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 4 Feb 2025 09:54:08 +0000 +Subject: hwmon: (xgene-hwmon) use appropriate type for the latency value + +From: Andrey Vatoropin + +[ Upstream commit 8df0f002827e18632dcd986f7546c1abf1953a6f ] + +The expression PCC_NUM_RETRIES * pcc_chan->latency is currently being +evaluated using 32-bit arithmetic. + +Since a value of type 'u64' is used to store the eventual result, +and this result is later sent to the function usecs_to_jiffies with +input parameter unsigned int, the current data type is too wide to +store the value of ctx->usecs_lat. + +Change the data type of "usecs_lat" to a more suitable (narrower) type. + +Found by Linux Verification Center (linuxtesting.org) with SVACE. + +Signed-off-by: Andrey Vatoropin +Link: https://lore.kernel.org/r/20250204095400.95013-1-a.vatoropin@crpt.ru +Signed-off-by: Guenter Roeck +Signed-off-by: Sasha Levin +--- + drivers/hwmon/xgene-hwmon.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/hwmon/xgene-hwmon.c b/drivers/hwmon/xgene-hwmon.c +index 7087197383c96..2cdbd5f107a2c 100644 +--- a/drivers/hwmon/xgene-hwmon.c ++++ b/drivers/hwmon/xgene-hwmon.c +@@ -105,7 +105,7 @@ struct xgene_hwmon_dev { + + phys_addr_t comm_base_addr; + void *pcc_comm_addr; +- u64 usecs_lat; ++ unsigned int usecs_lat; + }; + + /* +-- +2.39.5 + diff --git a/queue-6.14/hypfs_create_cpu_files-add-missing-check-for-hypfs_m.patch b/queue-6.14/hypfs_create_cpu_files-add-missing-check-for-hypfs_m.patch new file mode 100644 index 0000000000..d16cafbaf9 --- /dev/null +++ b/queue-6.14/hypfs_create_cpu_files-add-missing-check-for-hypfs_m.patch @@ -0,0 +1,31 @@ +From 62eddd9f0a2c82e0ecb718438c6b89029767955c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Mar 2025 22:06:04 -0400 +Subject: hypfs_create_cpu_files(): add missing check for hypfs_mkdir() failure + +From: Al Viro + +[ Upstream commit 00cdfdcfa0806202aea56b02cedbf87ef1e75df8 ] + +Signed-off-by: Al Viro +Signed-off-by: Sasha Levin +--- + arch/s390/hypfs/hypfs_diag_fs.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/arch/s390/hypfs/hypfs_diag_fs.c b/arch/s390/hypfs/hypfs_diag_fs.c +index 00a6d370a2803..280266a74f378 100644 +--- a/arch/s390/hypfs/hypfs_diag_fs.c ++++ b/arch/s390/hypfs/hypfs_diag_fs.c +@@ -208,6 +208,8 @@ static int hypfs_create_cpu_files(struct dentry *cpus_dir, void *cpu_info) + snprintf(buffer, TMP_SIZE, "%d", cpu_info__cpu_addr(diag204_get_info_type(), + cpu_info)); + cpu_dir = hypfs_mkdir(cpus_dir, buffer); ++ if (IS_ERR(cpu_dir)) ++ return PTR_ERR(cpu_dir); + rc = hypfs_create_u64(cpu_dir, "mgmtime", + cpu_info__acc_time(diag204_get_info_type(), cpu_info) - + cpu_info__lp_time(diag204_get_info_type(), cpu_info)); +-- +2.39.5 + diff --git a/queue-6.14/i2c-amd-asf-set-cmd-variable-when-encountering-an-er.patch b/queue-6.14/i2c-amd-asf-set-cmd-variable-when-encountering-an-er.patch new file mode 100644 index 0000000000..8be5af639a --- /dev/null +++ b/queue-6.14/i2c-amd-asf-set-cmd-variable-when-encountering-an-er.patch @@ -0,0 +1,38 @@ +From 0fb89140e764eb7fdde3584e5274958693b370f3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Feb 2025 14:32:57 +0530 +Subject: i2c: amd-asf: Set cmd variable when encountering an error + +From: Shyam Sundar S K + +[ Upstream commit b719afaa1e5d88a1b51d76adf344ff4a48efdb45 ] + +In the event of ASF error during the transfer, update the cmd and exit +the process, as data processing is not performed when a command fails. + +Co-developed-by: Sanket Goswami +Signed-off-by: Sanket Goswami +Signed-off-by: Shyam Sundar S K +Signed-off-by: Andi Shyti +Link: https://lore.kernel.org/r/20250217090258.398540-2-Shyam-sundar.S-k@amd.com +Signed-off-by: Sasha Levin +--- + drivers/i2c/busses/i2c-amd-asf-plat.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/i2c/busses/i2c-amd-asf-plat.c b/drivers/i2c/busses/i2c-amd-asf-plat.c +index 93ebec162c6dd..61bc714c28d70 100644 +--- a/drivers/i2c/busses/i2c-amd-asf-plat.c ++++ b/drivers/i2c/busses/i2c-amd-asf-plat.c +@@ -69,7 +69,7 @@ static void amd_asf_process_target(struct work_struct *work) + /* Check if no error bits are set in target status register */ + if (reg & ASF_ERROR_STATUS) { + /* Set bank as full */ +- cmd = 0; ++ cmd = 1; + reg |= GENMASK(3, 2); + outb_p(reg, ASFDATABNKSEL); + } else { +-- +2.39.5 + diff --git a/queue-6.14/i2c-pxa-fix-call-balance-of-i2c-clk-handling-routine.patch b/queue-6.14/i2c-pxa-fix-call-balance-of-i2c-clk-handling-routine.patch new file mode 100644 index 0000000000..5f01e55b21 --- /dev/null +++ b/queue-6.14/i2c-pxa-fix-call-balance-of-i2c-clk-handling-routine.patch @@ -0,0 +1,41 @@ +From e708d12e9eb63ed204f014e6d76668e400cd409b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 12 Feb 2025 20:28:03 +0300 +Subject: i2c: pxa: fix call balance of i2c->clk handling routines + +From: Vitalii Mordan + +[ Upstream commit be7113d2e2a6f20cbee99c98d261a1fd6fd7b549 ] + +If the clock i2c->clk was not enabled in i2c_pxa_probe(), it should not be +disabled in any path. + +Found by Linux Verification Center (linuxtesting.org) with Klever. + +Signed-off-by: Vitalii Mordan +Signed-off-by: Andi Shyti +Link: https://lore.kernel.org/r/20250212172803.1422136-1-mordan@ispras.ru +Signed-off-by: Sasha Levin +--- + drivers/i2c/busses/i2c-pxa.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c +index cb69884826739..4415a29f749b9 100644 +--- a/drivers/i2c/busses/i2c-pxa.c ++++ b/drivers/i2c/busses/i2c-pxa.c +@@ -1503,7 +1503,10 @@ static int i2c_pxa_probe(struct platform_device *dev) + i2c->adap.name); + } + +- clk_prepare_enable(i2c->clk); ++ ret = clk_prepare_enable(i2c->clk); ++ if (ret) ++ return dev_err_probe(&dev->dev, ret, ++ "failed to enable clock\n"); + + if (i2c->use_pio) { + i2c->adap.algo = &i2c_pxa_pio_algorithm; +-- +2.39.5 + diff --git a/queue-6.14/i2c-qcom-geni-update-i2c-frequency-table-to-match-ha.patch b/queue-6.14/i2c-qcom-geni-update-i2c-frequency-table-to-match-ha.patch new file mode 100644 index 0000000000..f3ab94476d --- /dev/null +++ b/queue-6.14/i2c-qcom-geni-update-i2c-frequency-table-to-match-ha.patch @@ -0,0 +1,50 @@ +From ce11ee0a0670ba6bdd498ca59a79bb5e8462b96e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 22 Jan 2025 12:16:34 +0530 +Subject: i2c: qcom-geni: Update i2c frequency table to match hardware guidance +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Mukesh Kumar Savaliya + +[ Upstream commit a815975cbaeb4ab29f45312ef23be2871b2e8b82 ] + +With the current settings, the I2C buses are achieving around 370KHz +instead of the expected 400KHz. For 100KHz and 1MHz, the settings are +now more compliant and adhere to the Qualcomm’s internal programming +guide. + +Update the I2C frequency table to align with the recommended values +outlined in the I2C hardware programming guide, ensuring proper +communication and performance. + +Signed-off-by: Mukesh Kumar Savaliya +Reviewed-by: Vladimir Zapolskiy +Link: https://lore.kernel.org/r/20250122064634.2864432-1-quic_msavaliy@quicinc.com +Signed-off-by: Andi Shyti +Signed-off-by: Sasha Levin +--- + drivers/i2c/busses/i2c-qcom-geni.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/i2c/busses/i2c-qcom-geni.c b/drivers/i2c/busses/i2c-qcom-geni.c +index 7bbd478171e02..515a784c951ca 100644 +--- a/drivers/i2c/busses/i2c-qcom-geni.c ++++ b/drivers/i2c/busses/i2c-qcom-geni.c +@@ -148,9 +148,9 @@ struct geni_i2c_clk_fld { + * source_clock = 19.2 MHz + */ + static const struct geni_i2c_clk_fld geni_i2c_clk_map_19p2mhz[] = { +- {KHZ(100), 7, 10, 11, 26}, +- {KHZ(400), 2, 5, 12, 24}, +- {KHZ(1000), 1, 3, 9, 18}, ++ {KHZ(100), 7, 10, 12, 26}, ++ {KHZ(400), 2, 5, 11, 22}, ++ {KHZ(1000), 1, 2, 8, 18}, + {}, + }; + +-- +2.39.5 + diff --git a/queue-6.14/i2c-qup-vote-for-interconnect-bandwidth-to-dram.patch b/queue-6.14/i2c-qup-vote-for-interconnect-bandwidth-to-dram.patch new file mode 100644 index 0000000000..6042303f62 --- /dev/null +++ b/queue-6.14/i2c-qup-vote-for-interconnect-bandwidth-to-dram.patch @@ -0,0 +1,139 @@ +From 35ae2ae7dc117137a347be96cc8685285d98301b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 28 Nov 2023 10:48:37 +0100 +Subject: i2c: qup: Vote for interconnect bandwidth to DRAM + +From: Stephan Gerhold + +[ Upstream commit d4f35233a6345f62637463ef6e0708f44ffaa583 ] + +When the I2C QUP controller is used together with a DMA engine it needs +to vote for the interconnect path to the DRAM. Otherwise it may be +unable to access the memory quickly enough. + +The requested peak bandwidth is dependent on the I2C core clock. + +To avoid sending votes too often the bandwidth is always requested when +a DMA transfer starts, but dropped only on runtime suspend. Runtime +suspend should only happen if no transfer is active. After resumption we +can defer the next vote until the first DMA transfer actually happens. + +The implementation is largely identical to the one introduced for +spi-qup in commit ecdaa9473019 ("spi: qup: Vote for interconnect +bandwidth to DRAM") since both drivers represent the same hardware +block. + +Signed-off-by: Stephan Gerhold +Signed-off-by: Andi Shyti +Link: https://lore.kernel.org/r/20231128-i2c-qup-dvfs-v1-3-59a0e3039111@kernkonzept.com +Signed-off-by: Sasha Levin +--- + drivers/i2c/busses/i2c-qup.c | 36 ++++++++++++++++++++++++++++++++++++ + 1 file changed, 36 insertions(+) + +diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c +index da20b4487c9a5..3a36d682ed572 100644 +--- a/drivers/i2c/busses/i2c-qup.c ++++ b/drivers/i2c/busses/i2c-qup.c +@@ -14,6 +14,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -150,6 +151,8 @@ + /* TAG length for DATA READ in RX FIFO */ + #define READ_RX_TAGS_LEN 2 + ++#define QUP_BUS_WIDTH 8 ++ + static unsigned int scl_freq; + module_param_named(scl_freq, scl_freq, uint, 0444); + MODULE_PARM_DESC(scl_freq, "SCL frequency override"); +@@ -227,6 +230,7 @@ struct qup_i2c_dev { + int irq; + struct clk *clk; + struct clk *pclk; ++ struct icc_path *icc_path; + struct i2c_adapter adap; + + int clk_ctl; +@@ -255,6 +259,10 @@ struct qup_i2c_dev { + /* To configure when bus is in run state */ + u32 config_run; + ++ /* bandwidth votes */ ++ u32 src_clk_freq; ++ u32 cur_bw_clk_freq; ++ + /* dma parameters */ + bool is_dma; + /* To check if the current transfer is using DMA */ +@@ -453,6 +461,23 @@ static int qup_i2c_bus_active(struct qup_i2c_dev *qup, int len) + return ret; + } + ++static int qup_i2c_vote_bw(struct qup_i2c_dev *qup, u32 clk_freq) ++{ ++ u32 needed_peak_bw; ++ int ret; ++ ++ if (qup->cur_bw_clk_freq == clk_freq) ++ return 0; ++ ++ needed_peak_bw = Bps_to_icc(clk_freq * QUP_BUS_WIDTH); ++ ret = icc_set_bw(qup->icc_path, 0, needed_peak_bw); ++ if (ret) ++ return ret; ++ ++ qup->cur_bw_clk_freq = clk_freq; ++ return 0; ++} ++ + static void qup_i2c_write_tx_fifo_v1(struct qup_i2c_dev *qup) + { + struct qup_i2c_block *blk = &qup->blk; +@@ -838,6 +863,10 @@ static int qup_i2c_bam_xfer(struct i2c_adapter *adap, struct i2c_msg *msg, + int ret = 0; + int idx = 0; + ++ ret = qup_i2c_vote_bw(qup, qup->src_clk_freq); ++ if (ret) ++ return ret; ++ + enable_irq(qup->irq); + ret = qup_i2c_req_dma(qup); + +@@ -1643,6 +1672,7 @@ static void qup_i2c_disable_clocks(struct qup_i2c_dev *qup) + config = readl(qup->base + QUP_CONFIG); + config |= QUP_CLOCK_AUTO_GATE; + writel(config, qup->base + QUP_CONFIG); ++ qup_i2c_vote_bw(qup, 0); + clk_disable_unprepare(qup->pclk); + } + +@@ -1743,6 +1773,11 @@ static int qup_i2c_probe(struct platform_device *pdev) + goto fail_dma; + } + qup->is_dma = true; ++ ++ qup->icc_path = devm_of_icc_get(&pdev->dev, NULL); ++ if (IS_ERR(qup->icc_path)) ++ return dev_err_probe(&pdev->dev, PTR_ERR(qup->icc_path), ++ "failed to get interconnect path\n"); + } + + nodma: +@@ -1791,6 +1826,7 @@ static int qup_i2c_probe(struct platform_device *pdev) + qup_i2c_enable_clocks(qup); + src_clk_freq = clk_get_rate(qup->clk); + } ++ qup->src_clk_freq = src_clk_freq; + + /* + * Bootloaders might leave a pending interrupt on certain QUP's, +-- +2.39.5 + diff --git a/queue-6.14/i3c-master-svc-fix-implicit-fallthrough-in-svc_i3c_m.patch b/queue-6.14/i3c-master-svc-fix-implicit-fallthrough-in-svc_i3c_m.patch new file mode 100644 index 0000000000..c926f2b7af --- /dev/null +++ b/queue-6.14/i3c-master-svc-fix-implicit-fallthrough-in-svc_i3c_m.patch @@ -0,0 +1,52 @@ +From dd36322433813f734aeac301b3fd122d9c7a8e9c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 19 Mar 2025 09:08:01 -0700 +Subject: i3c: master: svc: Fix implicit fallthrough in + svc_i3c_master_ibi_work() + +From: Nathan Chancellor + +[ Upstream commit e8d2d287e26d9bd9114cf258a123a6b70812442e ] + +Clang warns (or errors with CONFIG_WERROR=y): + + drivers/i3c/master/svc-i3c-master.c:596:2: error: unannotated fall-through between switch labels [-Werror,-Wimplicit-fallthrough] + 596 | default: + | ^ + drivers/i3c/master/svc-i3c-master.c:596:2: note: insert 'break;' to avoid fall-through + 596 | default: + | ^ + | break; + 1 error generated. + +Clang is a little more pedantic than GCC, which does not warn when +falling through to a case that is just break or return. Clang's version +is more in line with the kernel's own stance in deprecated.rst, which +states that all switch/case blocks must end in either break, +fallthrough, continue, goto, or return. Add the missing break to silence +the warning. + +Fixes: 0430bf9bc1ac ("i3c: master: svc: Fix missing STOP for master request") +Signed-off-by: Nathan Chancellor +Link: https://lore.kernel.org/r/20250319-i3c-fix-clang-fallthrough-v1-1-d8e02be1ef5c@kernel.org +Signed-off-by: Alexandre Belloni +Signed-off-by: Sasha Levin +--- + drivers/i3c/master/svc-i3c-master.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/i3c/master/svc-i3c-master.c b/drivers/i3c/master/svc-i3c-master.c +index 2cf2c567f8931..75127b6c161f0 100644 +--- a/drivers/i3c/master/svc-i3c-master.c ++++ b/drivers/i3c/master/svc-i3c-master.c +@@ -552,6 +552,7 @@ static void svc_i3c_master_ibi_work(struct work_struct *work) + break; + case SVC_I3C_MSTATUS_IBITYPE_MASTER_REQUEST: + svc_i3c_master_emit_stop(master); ++ break; + default: + break; + } +-- +2.39.5 + diff --git a/queue-6.14/i3c-master-svc-fix-missing-stop-for-master-request.patch b/queue-6.14/i3c-master-svc-fix-missing-stop-for-master-request.patch new file mode 100644 index 0000000000..f496685f58 --- /dev/null +++ b/queue-6.14/i3c-master-svc-fix-missing-stop-for-master-request.patch @@ -0,0 +1,37 @@ +From 88e82d9963cbcadd297ace4e540115f2de30d874 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 18 Mar 2025 13:36:06 +0800 +Subject: i3c: master: svc: Fix missing STOP for master request + +From: Stanley Chu + +[ Upstream commit 0430bf9bc1ac068c8b8c540eb93e5751872efc51 ] + +The controller driver nacked the master request but didn't emit a +STOP to end the transaction. The driver shall refuse the unsupported +requests and return the controller state to IDLE by emitting a STOP. + +Signed-off-by: Stanley Chu +Reviewed-by: Frank Li +Link: https://lore.kernel.org/r/20250318053606.3087121-4-yschu@nuvoton.com +Signed-off-by: Alexandre Belloni +Signed-off-by: Sasha Levin +--- + drivers/i3c/master/svc-i3c-master.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/i3c/master/svc-i3c-master.c b/drivers/i3c/master/svc-i3c-master.c +index 0fc03bb5d0a6e..a18fe62962b0c 100644 +--- a/drivers/i3c/master/svc-i3c-master.c ++++ b/drivers/i3c/master/svc-i3c-master.c +@@ -551,6 +551,7 @@ static void svc_i3c_master_ibi_work(struct work_struct *work) + queue_work(master->base.wq, &master->hj_work); + break; + case SVC_I3C_MSTATUS_IBITYPE_MASTER_REQUEST: ++ svc_i3c_master_emit_stop(master); + default: + break; + } +-- +2.39.5 + diff --git a/queue-6.14/i3c-master-svc-flush-fifo-before-sending-dynamic-add.patch b/queue-6.14/i3c-master-svc-flush-fifo-before-sending-dynamic-add.patch new file mode 100644 index 0000000000..c2d03677fb --- /dev/null +++ b/queue-6.14/i3c-master-svc-flush-fifo-before-sending-dynamic-add.patch @@ -0,0 +1,40 @@ +From 4de38cc5cdeead059cb8cf1e4113af22143cc851 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 29 Jan 2025 11:22:50 -0500 +Subject: i3c: master: svc: Flush FIFO before sending Dynamic Address + Assignment(DAA) + +From: Frank Li + +[ Upstream commit a892ee4cf22a50e1d6988d0464a9a421f3e5db2f ] + +Ensure the FIFO is empty before issuing the DAA command to prevent +incorrect command data from being sent. Align with other data transfers, +such as svc_i3c_master_start_xfer_locked(), which flushes the FIFO before +sending a command. + +Signed-off-by: Frank Li +Reviewed-by: Miquel Raynal +Link: https://lore.kernel.org/r/20250129162250.3629189-1-Frank.Li@nxp.com +Signed-off-by: Alexandre Belloni +Signed-off-by: Sasha Levin +--- + drivers/i3c/master/svc-i3c-master.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/i3c/master/svc-i3c-master.c b/drivers/i3c/master/svc-i3c-master.c +index a18fe62962b0c..2cf2c567f8931 100644 +--- a/drivers/i3c/master/svc-i3c-master.c ++++ b/drivers/i3c/master/svc-i3c-master.c +@@ -899,6 +899,8 @@ static int svc_i3c_master_do_daa_locked(struct svc_i3c_master *master, + u32 reg; + int ret, i; + ++ svc_i3c_master_flush_fifo(master); ++ + while (true) { + /* clean SVC_I3C_MINT_IBIWON w1c bits */ + writel(SVC_I3C_MINT_IBIWON, master->regs + SVC_I3C_MSTATUS); +-- +2.39.5 + diff --git a/queue-6.14/ice-count-combined-queues-using-rx-tx-count.patch b/queue-6.14/ice-count-combined-queues-using-rx-tx-count.patch new file mode 100644 index 0000000000..7ea098972a --- /dev/null +++ b/queue-6.14/ice-count-combined-queues-using-rx-tx-count.patch @@ -0,0 +1,40 @@ +From 48d0ae0535e344e5acb5453ec428ec5871d36d9f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 3 Dec 2024 07:58:09 +0100 +Subject: ice: count combined queues using Rx/Tx count + +From: Michal Swiatkowski + +[ Upstream commit c3a392bdd31adc474f1009ee85c13fdd01fe800d ] + +Previous implementation assumes that there is 1:1 matching between +vectors and queues. It isn't always true. + +Get minimum value from Rx/Tx queues to determine combined queues number. + +Reviewed-by: Jacob Keller +Tested-by: Pucha Himasekhar Reddy +Signed-off-by: Michal Swiatkowski +Signed-off-by: Tony Nguyen +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/intel/ice/ice_ethtool.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/intel/ice/ice_ethtool.c b/drivers/net/ethernet/intel/ice/ice_ethtool.c +index f241493a6ac88..6bbb304ad9ab7 100644 +--- a/drivers/net/ethernet/intel/ice/ice_ethtool.c ++++ b/drivers/net/ethernet/intel/ice/ice_ethtool.c +@@ -3817,8 +3817,7 @@ static u32 ice_get_combined_cnt(struct ice_vsi *vsi) + ice_for_each_q_vector(vsi, q_idx) { + struct ice_q_vector *q_vector = vsi->q_vectors[q_idx]; + +- if (q_vector->rx.rx_ring && q_vector->tx.tx_ring) +- combined++; ++ combined += min(q_vector->num_ring_tx, q_vector->num_ring_rx); + } + + return combined; +-- +2.39.5 + diff --git a/queue-6.14/ice-init-flow-director-before-rdma.patch b/queue-6.14/ice-init-flow-director-before-rdma.patch new file mode 100644 index 0000000000..8fe0c9d728 --- /dev/null +++ b/queue-6.14/ice-init-flow-director-before-rdma.patch @@ -0,0 +1,60 @@ +From 0c9110861c24e6c1488c42c21006fe6dccaf926b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 3 Dec 2024 07:58:17 +0100 +Subject: ice: init flow director before RDMA + +From: Michal Swiatkowski + +[ Upstream commit d67627e7b53203ca150e54723abbed81a0716286 ] + +Flow director needs only one MSI-X. Load it before RDMA to save MSI-X +for it. + +Reviewed-by: Jacob Keller +Tested-by: Pucha Himasekhar Reddy +Signed-off-by: Michal Swiatkowski +Signed-off-by: Tony Nguyen +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/intel/ice/ice_main.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c +index e13bd5a6cb6c4..d24d46b24e371 100644 +--- a/drivers/net/ethernet/intel/ice/ice_main.c ++++ b/drivers/net/ethernet/intel/ice/ice_main.c +@@ -5186,11 +5186,12 @@ int ice_load(struct ice_pf *pf) + + ice_napi_add(vsi); + ++ ice_init_features(pf); ++ + err = ice_init_rdma(pf); + if (err) + goto err_init_rdma; + +- ice_init_features(pf); + ice_service_task_restart(pf); + + clear_bit(ICE_DOWN, pf->state); +@@ -5198,6 +5199,7 @@ int ice_load(struct ice_pf *pf) + return 0; + + err_init_rdma: ++ ice_deinit_features(pf); + ice_tc_indir_block_unregister(vsi); + err_tc_indir_block_register: + ice_unregister_netdev(vsi); +@@ -5221,8 +5223,8 @@ void ice_unload(struct ice_pf *pf) + + devl_assert_locked(priv_to_devlink(pf)); + +- ice_deinit_features(pf); + ice_deinit_rdma(pf); ++ ice_deinit_features(pf); + ice_tc_indir_block_unregister(vsi); + ice_unregister_netdev(vsi); + ice_devlink_destroy_pf_port(pf); +-- +2.39.5 + diff --git a/queue-6.14/ice-treat-dyn_allowed-only-as-suggestion.patch b/queue-6.14/ice-treat-dyn_allowed-only-as-suggestion.patch new file mode 100644 index 0000000000..2815dd6281 --- /dev/null +++ b/queue-6.14/ice-treat-dyn_allowed-only-as-suggestion.patch @@ -0,0 +1,133 @@ +From 80dd118b04fa3f6752ec77106942c9b78cfc7b70 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 3 Dec 2024 07:58:14 +0100 +Subject: ice: treat dyn_allowed only as suggestion + +From: Michal Swiatkowski + +[ Upstream commit a8c2d3932c1106af2764cc6869b29bcf3cb5bc47 ] + +It can be needed to have some MSI-X allocated as static and rest as +dynamic. For example on PF VSI. We want to always have minimum one MSI-X +on it, because of that it is allocated as a static one, rest can be +dynamic if it is supported. + +Change the ice_get_irq_res() to allow using static entries if they are +free even if caller wants dynamic one. + +Adjust limit values to the new approach. Min and max in limit means the +values that are valid, so decrease max and num_static by one. + +Set vsi::irq_dyn_alloc if dynamic allocation is supported. + +Reviewed-by: Jacob Keller +Reviewed-by: Wojciech Drewek +Tested-by: Pucha Himasekhar Reddy +Signed-off-by: Michal Swiatkowski +Signed-off-by: Tony Nguyen +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/intel/ice/ice_irq.c | 25 ++++++++++++------------ + drivers/net/ethernet/intel/ice/ice_lib.c | 2 ++ + 2 files changed, 15 insertions(+), 12 deletions(-) + +diff --git a/drivers/net/ethernet/intel/ice/ice_irq.c b/drivers/net/ethernet/intel/ice/ice_irq.c +index ad82ff7d19957..09f9c7ba52795 100644 +--- a/drivers/net/ethernet/intel/ice/ice_irq.c ++++ b/drivers/net/ethernet/intel/ice/ice_irq.c +@@ -45,7 +45,7 @@ static void ice_free_irq_res(struct ice_pf *pf, u16 index) + /** + * ice_get_irq_res - get an interrupt resource + * @pf: board private structure +- * @dyn_only: force entry to be dynamically allocated ++ * @dyn_allowed: allow entry to be dynamically allocated + * + * Allocate new irq entry in the free slot of the tracker. Since xarray + * is used, always allocate new entry at the lowest possible index. Set +@@ -53,11 +53,12 @@ static void ice_free_irq_res(struct ice_pf *pf, u16 index) + * + * Returns allocated irq entry or NULL on failure. + */ +-static struct ice_irq_entry *ice_get_irq_res(struct ice_pf *pf, bool dyn_only) ++static struct ice_irq_entry *ice_get_irq_res(struct ice_pf *pf, ++ bool dyn_allowed) + { +- struct xa_limit limit = { .max = pf->irq_tracker.num_entries, ++ struct xa_limit limit = { .max = pf->irq_tracker.num_entries - 1, + .min = 0 }; +- unsigned int num_static = pf->irq_tracker.num_static; ++ unsigned int num_static = pf->irq_tracker.num_static - 1; + struct ice_irq_entry *entry; + unsigned int index; + int ret; +@@ -66,9 +67,9 @@ static struct ice_irq_entry *ice_get_irq_res(struct ice_pf *pf, bool dyn_only) + if (!entry) + return NULL; + +- /* skip preallocated entries if the caller says so */ +- if (dyn_only) +- limit.min = num_static; ++ /* only already allocated if the caller says so */ ++ if (!dyn_allowed) ++ limit.max = num_static; + + ret = xa_alloc(&pf->irq_tracker.entries, &index, entry, limit, + GFP_KERNEL); +@@ -78,7 +79,7 @@ static struct ice_irq_entry *ice_get_irq_res(struct ice_pf *pf, bool dyn_only) + entry = NULL; + } else { + entry->index = index; +- entry->dynamic = index >= num_static; ++ entry->dynamic = index > num_static; + } + + return entry; +@@ -272,7 +273,7 @@ int ice_init_interrupt_scheme(struct ice_pf *pf) + /** + * ice_alloc_irq - Allocate new interrupt vector + * @pf: board private structure +- * @dyn_only: force dynamic allocation of the interrupt ++ * @dyn_allowed: allow dynamic allocation of the interrupt + * + * Allocate new interrupt vector for a given owner id. + * return struct msi_map with interrupt details and track +@@ -285,20 +286,20 @@ int ice_init_interrupt_scheme(struct ice_pf *pf) + * interrupt will be allocated with pci_msix_alloc_irq_at. + * + * Some callers may only support dynamically allocated interrupts. +- * This is indicated with dyn_only flag. ++ * This is indicated with dyn_allowed flag. + * + * On failure, return map with negative .index. The caller + * is expected to check returned map index. + * + */ +-struct msi_map ice_alloc_irq(struct ice_pf *pf, bool dyn_only) ++struct msi_map ice_alloc_irq(struct ice_pf *pf, bool dyn_allowed) + { + int sriov_base_vector = pf->sriov_base_vector; + struct msi_map map = { .index = -ENOENT }; + struct device *dev = ice_pf_to_dev(pf); + struct ice_irq_entry *entry; + +- entry = ice_get_irq_res(pf, dyn_only); ++ entry = ice_get_irq_res(pf, dyn_allowed); + if (!entry) + return map; + +diff --git a/drivers/net/ethernet/intel/ice/ice_lib.c b/drivers/net/ethernet/intel/ice/ice_lib.c +index e0785e820d601..021ed7451bb9f 100644 +--- a/drivers/net/ethernet/intel/ice/ice_lib.c ++++ b/drivers/net/ethernet/intel/ice/ice_lib.c +@@ -567,6 +567,8 @@ ice_vsi_alloc_def(struct ice_vsi *vsi, struct ice_channel *ch) + return -ENOMEM; + } + ++ vsi->irq_dyn_alloc = pci_msix_can_alloc_dyn(vsi->back->pdev); ++ + switch (vsi->type) { + case ICE_VSI_PF: + case ICE_VSI_SF: +-- +2.39.5 + diff --git a/queue-6.14/ieee802154-ca8210-use-proper-setters-and-getters-for.patch b/queue-6.14/ieee802154-ca8210-use-proper-setters-and-getters-for.patch new file mode 100644 index 0000000000..a159f77dd1 --- /dev/null +++ b/queue-6.14/ieee802154-ca8210-use-proper-setters-and-getters-for.patch @@ -0,0 +1,77 @@ +From 473395e621aa116566f6b499c2cf7d31b6317490 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Mar 2025 12:55:34 +0200 +Subject: ieee802154: ca8210: Use proper setters and getters for bitwise types + +From: Andy Shevchenko + +[ Upstream commit 169b2262205836a5d1213ff44dca2962276bece1 ] + +Sparse complains that the driver doesn't respect the bitwise types: + +drivers/net/ieee802154/ca8210.c:1796:27: warning: incorrect type in assignment (different base types) +drivers/net/ieee802154/ca8210.c:1796:27: expected restricted __le16 [addressable] [assigned] [usertype] pan_id +drivers/net/ieee802154/ca8210.c:1796:27: got unsigned short [usertype] +drivers/net/ieee802154/ca8210.c:1801:25: warning: incorrect type in assignment (different base types) +drivers/net/ieee802154/ca8210.c:1801:25: expected restricted __le16 [addressable] [assigned] [usertype] pan_id +drivers/net/ieee802154/ca8210.c:1801:25: got unsigned short [usertype] +drivers/net/ieee802154/ca8210.c:1928:28: warning: incorrect type in argument 3 (different base types) +drivers/net/ieee802154/ca8210.c:1928:28: expected unsigned short [usertype] dst_pan_id +drivers/net/ieee802154/ca8210.c:1928:28: got restricted __le16 [addressable] [usertype] pan_id + +Use proper setters and getters for bitwise types. + +Note, in accordance with [1] the protocol is little endian. + +Link: https://www.cascoda.com/wp-content/uploads/2018/11/CA-8210_datasheet_0418.pdf [1] +Reviewed-by: Miquel Raynal +Reviewed-by: Linus Walleij +Signed-off-by: Andy Shevchenko +Link: https://lore.kernel.org/20250305105656.2133487-2-andriy.shevchenko@linux.intel.com +Signed-off-by: Stefan Schmidt +Signed-off-by: Sasha Levin +--- + drivers/net/ieee802154/ca8210.c | 9 ++++----- + 1 file changed, 4 insertions(+), 5 deletions(-) + +diff --git a/drivers/net/ieee802154/ca8210.c b/drivers/net/ieee802154/ca8210.c +index 753215ebc67c7..a036910f60828 100644 +--- a/drivers/net/ieee802154/ca8210.c ++++ b/drivers/net/ieee802154/ca8210.c +@@ -1446,8 +1446,7 @@ static u8 mcps_data_request( + command.pdata.data_req.src_addr_mode = src_addr_mode; + command.pdata.data_req.dst.mode = dst_address_mode; + if (dst_address_mode != MAC_MODE_NO_ADDR) { +- command.pdata.data_req.dst.pan_id[0] = LS_BYTE(dst_pan_id); +- command.pdata.data_req.dst.pan_id[1] = MS_BYTE(dst_pan_id); ++ put_unaligned_le16(dst_pan_id, command.pdata.data_req.dst.pan_id); + if (dst_address_mode == MAC_MODE_SHORT_ADDR) { + command.pdata.data_req.dst.address[0] = LS_BYTE( + dst_addr->short_address +@@ -1795,12 +1794,12 @@ static int ca8210_skb_rx( + } + hdr.source.mode = data_ind[0]; + dev_dbg(&priv->spi->dev, "srcAddrMode: %#03x\n", hdr.source.mode); +- hdr.source.pan_id = *(u16 *)&data_ind[1]; ++ hdr.source.pan_id = cpu_to_le16(get_unaligned_le16(&data_ind[1])); + dev_dbg(&priv->spi->dev, "srcPanId: %#06x\n", hdr.source.pan_id); + memcpy(&hdr.source.extended_addr, &data_ind[3], 8); + hdr.dest.mode = data_ind[11]; + dev_dbg(&priv->spi->dev, "dstAddrMode: %#03x\n", hdr.dest.mode); +- hdr.dest.pan_id = *(u16 *)&data_ind[12]; ++ hdr.dest.pan_id = cpu_to_le16(get_unaligned_le16(&data_ind[12])); + dev_dbg(&priv->spi->dev, "dstPanId: %#06x\n", hdr.dest.pan_id); + memcpy(&hdr.dest.extended_addr, &data_ind[14], 8); + +@@ -1927,7 +1926,7 @@ static int ca8210_skb_tx( + status = mcps_data_request( + header.source.mode, + header.dest.mode, +- header.dest.pan_id, ++ le16_to_cpu(header.dest.pan_id), + (union macaddr *)&header.dest.extended_addr, + skb->len - mac_len, + &skb->data[mac_len], +-- +2.39.5 + diff --git a/queue-6.14/igc-avoid-unnecessary-link-down-event-in-xdp_setup_p.patch b/queue-6.14/igc-avoid-unnecessary-link-down-event-in-xdp_setup_p.patch new file mode 100644 index 0000000000..4b5cc4386b --- /dev/null +++ b/queue-6.14/igc-avoid-unnecessary-link-down-event-in-xdp_setup_p.patch @@ -0,0 +1,136 @@ +From 7e73b3d356fea2e75bf5bd79b3a59c788e551137 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 16 Dec 2024 15:38:49 +0800 +Subject: igc: Avoid unnecessary link down event in XDP_SETUP_PROG process + +From: Song Yoong Siang + +[ Upstream commit be324b790368c1522f07c6bb5654122e07b5e588 ] + +The igc_close()/igc_open() functions are too drastic for installing a new +XDP prog because they cause undesirable link down event and device reset. + +To avoid delays in Ethernet traffic, improve the XDP_SETUP_PROG process by +using the same sequence as igc_xdp_setup_pool(), which performs only the +necessary steps, as follows: + 1. stop the traffic and clean buffer + 2. stop NAPI + 3. install the XDP program + 4. resume NAPI + 5. allocate buffer and resume the traffic + +This patch has been tested using the 'ip link set xdpdrv' command to attach +a simple XDP prog that always returns XDP_PASS. + +Before this patch, attaching xdp program will cause ptp4l to lose sync for +few seconds, as shown in ptp4l log below: + ptp4l[198.082]: rms 4 max 8 freq +906 +/- 2 delay 12 +/- 0 + ptp4l[199.082]: rms 3 max 4 freq +906 +/- 3 delay 12 +/- 0 + ptp4l[199.536]: port 1 (enp2s0): link down + ptp4l[199.536]: port 1 (enp2s0): SLAVE to FAULTY on FAULT_DETECTED (FT_UNSPECIFIED) + ptp4l[199.600]: selected local clock 22abbc.fffe.bb1234 as best master + ptp4l[199.600]: port 1 (enp2s0): assuming the grand master role + ptp4l[199.600]: port 1 (enp2s0): master state recommended in slave only mode + ptp4l[199.600]: port 1 (enp2s0): defaultDS.priority1 probably misconfigured + ptp4l[202.266]: port 1 (enp2s0): link up + ptp4l[202.300]: port 1 (enp2s0): FAULTY to LISTENING on INIT_COMPLETE + ptp4l[205.558]: port 1 (enp2s0): new foreign master 44abbc.fffe.bb2144-1 + ptp4l[207.558]: selected best master clock 44abbc.fffe.bb2144 + ptp4l[207.559]: port 1 (enp2s0): LISTENING to UNCALIBRATED on RS_SLAVE + ptp4l[208.308]: port 1 (enp2s0): UNCALIBRATED to SLAVE on MASTER_CLOCK_SELECTED + ptp4l[208.933]: rms 742 max 1303 freq -195 +/- 682 delay 12 +/- 0 + ptp4l[209.933]: rms 178 max 274 freq +387 +/- 243 delay 12 +/- 0 + +After this patch, attaching xdp program no longer cause ptp4l to lose sync, +as shown in ptp4l log below: + ptp4l[201.183]: rms 1 max 3 freq +959 +/- 1 delay 8 +/- 0 + ptp4l[202.183]: rms 1 max 3 freq +961 +/- 2 delay 8 +/- 0 + ptp4l[203.183]: rms 2 max 3 freq +958 +/- 2 delay 8 +/- 0 + ptp4l[204.183]: rms 3 max 5 freq +961 +/- 3 delay 8 +/- 0 + ptp4l[205.183]: rms 2 max 4 freq +964 +/- 3 delay 8 +/- 0 + +Besides, before this patch, attaching xdp program will causes flood ping to +lose 10 packets, as shown in ping statistics below: + --- 169.254.1.2 ping statistics --- + 100000 packets transmitted, 99990 received, +6 errors, 0.01% packet loss, time 34001ms + rtt min/avg/max/mdev = 0.028/0.301/3104.360/13.838 ms, pipe 10, ipg/ewma 0.340/0.243 ms + +After this patch, attaching xdp program no longer cause flood ping to loss +any packets, as shown in ping statistics below: + --- 169.254.1.2 ping statistics --- + 100000 packets transmitted, 100000 received, 0% packet loss, time 32326ms + rtt min/avg/max/mdev = 0.027/0.231/19.589/0.155 ms, pipe 2, ipg/ewma 0.323/0.322 ms + +On the other hand, this patch has been tested with tools/testing/selftests/ +bpf/xdp_hw_metadata app to make sure AF_XDP zero-copy is working fine with +XDP Tx and Rx metadata. Below is the result of last packet after received +10000 UDP packets with interval 1 ms: + poll: 1 (0) skip=0 fail=0 redir=10000 + xsk_ring_cons__peek: 1 + 0x55881c7ef7a8: rx_desc[9999]->addr=8f110 addr=8f110 comp_addr=8f110 EoP + rx_hash: 0xFB9BB6A3 with RSS type:0x1 + HW RX-time: 1733923136269470866 (sec:1733923136.2695) delta to User RX-time sec:0.0000 (43.280 usec) + XDP RX-time: 1733923136269482482 (sec:1733923136.2695) delta to User RX-time sec:0.0000 (31.664 usec) + No rx_vlan_tci or rx_vlan_proto, err=-95 + 0x55881c7ef7a8: ping-pong with csum=ab19 (want 315b) csum_start=34 csum_offset=6 + 0x55881c7ef7a8: complete tx idx=9999 addr=f010 + HW TX-complete-time: 1733923136269591637 (sec:1733923136.2696) delta to User TX-complete-time sec:0.0001 (108.571 usec) + XDP RX-time: 1733923136269482482 (sec:1733923136.2695) delta to User TX-complete-time sec:0.0002 (217.726 usec) + HW RX-time: 1733923136269470866 (sec:1733923136.2695) delta to HW TX-complete-time sec:0.0001 (120.771 usec) + 0x55881c7ef7a8: complete rx idx=10127 addr=8f110 + +Signed-off-by: Song Yoong Siang +Tested-by: Avigail Dahan +Signed-off-by: Tony Nguyen +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/intel/igc/igc_xdp.c | 19 +++++++++++++++---- + 1 file changed, 15 insertions(+), 4 deletions(-) + +diff --git a/drivers/net/ethernet/intel/igc/igc_xdp.c b/drivers/net/ethernet/intel/igc/igc_xdp.c +index 869815f48ac1d..9eb47b4beb062 100644 +--- a/drivers/net/ethernet/intel/igc/igc_xdp.c ++++ b/drivers/net/ethernet/intel/igc/igc_xdp.c +@@ -14,6 +14,7 @@ int igc_xdp_set_prog(struct igc_adapter *adapter, struct bpf_prog *prog, + bool if_running = netif_running(dev); + struct bpf_prog *old_prog; + bool need_update; ++ unsigned int i; + + if (dev->mtu > ETH_DATA_LEN) { + /* For now, the driver doesn't support XDP functionality with +@@ -24,8 +25,13 @@ int igc_xdp_set_prog(struct igc_adapter *adapter, struct bpf_prog *prog, + } + + need_update = !!adapter->xdp_prog != !!prog; +- if (if_running && need_update) +- igc_close(dev); ++ if (if_running && need_update) { ++ for (i = 0; i < adapter->num_rx_queues; i++) { ++ igc_disable_rx_ring(adapter->rx_ring[i]); ++ igc_disable_tx_ring(adapter->tx_ring[i]); ++ napi_disable(&adapter->rx_ring[i]->q_vector->napi); ++ } ++ } + + old_prog = xchg(&adapter->xdp_prog, prog); + if (old_prog) +@@ -36,8 +42,13 @@ int igc_xdp_set_prog(struct igc_adapter *adapter, struct bpf_prog *prog, + else + xdp_features_clear_redirect_target(dev); + +- if (if_running && need_update) +- igc_open(dev); ++ if (if_running && need_update) { ++ for (i = 0; i < adapter->num_rx_queues; i++) { ++ napi_enable(&adapter->rx_ring[i]->q_vector->napi); ++ igc_enable_tx_ring(adapter->tx_ring[i]); ++ igc_enable_rx_ring(adapter->rx_ring[i]); ++ } ++ } + + return 0; + } +-- +2.39.5 + diff --git a/queue-6.14/iio-accel-fxls8962af-fix-wakeup-source-leaks-on-devi.patch b/queue-6.14/iio-accel-fxls8962af-fix-wakeup-source-leaks-on-devi.patch new file mode 100644 index 0000000000..46013a9be1 --- /dev/null +++ b/queue-6.14/iio-accel-fxls8962af-fix-wakeup-source-leaks-on-devi.patch @@ -0,0 +1,41 @@ +From 546c915b2d8a13f8fd17079552c0e5480dd05b99 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 6 Apr 2025 22:01:42 +0200 +Subject: iio: accel: fxls8962af: Fix wakeup source leaks on device unbind + +From: Krzysztof Kozlowski + +[ Upstream commit 0cd34d98dfd4f2b596415b8f12faf7b946613458 ] + +Device can be unbound, so driver must also release memory for the wakeup +source. + +Signed-off-by: Krzysztof Kozlowski +Link: https://patch.msgid.link/20250406-b4-device-wakeup-leak-iio-v1-1-2d7d322a4a93@linaro.org +Signed-off-by: Jonathan Cameron +Signed-off-by: Sasha Levin +--- + drivers/iio/accel/fxls8962af-core.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/drivers/iio/accel/fxls8962af-core.c b/drivers/iio/accel/fxls8962af-core.c +index 987212a7c038e..a0ae30c86687a 100644 +--- a/drivers/iio/accel/fxls8962af-core.c ++++ b/drivers/iio/accel/fxls8962af-core.c +@@ -1229,8 +1229,11 @@ int fxls8962af_core_probe(struct device *dev, struct regmap *regmap, int irq) + if (ret) + return ret; + +- if (device_property_read_bool(dev, "wakeup-source")) +- device_init_wakeup(dev, true); ++ if (device_property_read_bool(dev, "wakeup-source")) { ++ ret = devm_device_init_wakeup(dev); ++ if (ret) ++ return dev_err_probe(dev, ret, "Failed to init wakeup\n"); ++ } + + return devm_iio_device_register(dev, indio_dev); + } +-- +2.39.5 + diff --git a/queue-6.14/iio-adc-ad7606-protect-register-access.patch b/queue-6.14/iio-adc-ad7606-protect-register-access.patch new file mode 100644 index 0000000000..b3e57c555b --- /dev/null +++ b/queue-6.14/iio-adc-ad7606-protect-register-access.patch @@ -0,0 +1,53 @@ +From 36672aa9f3a4f7d1b64110974b22b78dffcbfc41 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 10 Feb 2025 17:10:57 +0100 +Subject: iio: adc: ad7606: protect register access + +From: Angelo Dureghello + +[ Upstream commit 0f65f59e632d942cccffd12c36036c24eb7037eb ] + +Protect register (and bus) access from concurrent +read / write. Needed in the backend operating mode. + +Signed-off-by: Angelo Dureghello +Link: https://patch.msgid.link/20250210-wip-bl-ad7606_add_backend_sw_mode-v4-7-160df18b1da7@baylibre.com +Signed-off-by: Jonathan Cameron +Signed-off-by: Sasha Levin +--- + drivers/iio/adc/ad7606.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/drivers/iio/adc/ad7606.c b/drivers/iio/adc/ad7606.c +index 0339e27f92c32..1c547e8d52ac0 100644 +--- a/drivers/iio/adc/ad7606.c ++++ b/drivers/iio/adc/ad7606.c +@@ -862,7 +862,12 @@ static int ad7606_write_raw(struct iio_dev *indio_dev, + } + val = (val * MICRO) + val2; + i = find_closest(val, scale_avail_uv, cs->num_scales); ++ ++ ret = iio_device_claim_direct_mode(indio_dev); ++ if (ret < 0) ++ return ret; + ret = st->write_scale(indio_dev, ch, i + cs->reg_offset); ++ iio_device_release_direct_mode(indio_dev); + if (ret < 0) + return ret; + cs->range = i; +@@ -873,7 +878,12 @@ static int ad7606_write_raw(struct iio_dev *indio_dev, + return -EINVAL; + i = find_closest(val, st->oversampling_avail, + st->num_os_ratios); ++ ++ ret = iio_device_claim_direct_mode(indio_dev); ++ if (ret < 0) ++ return ret; + ret = st->write_os(indio_dev, i); ++ iio_device_release_direct_mode(indio_dev); + if (ret < 0) + return ret; + st->oversampling = st->oversampling_avail[i]; +-- +2.39.5 + diff --git a/queue-6.14/iio-adc-ad7944-don-t-use-storagebits-for-sizing.patch b/queue-6.14/iio-adc-ad7944-don-t-use-storagebits-for-sizing.patch new file mode 100644 index 0000000000..f230c8a327 --- /dev/null +++ b/queue-6.14/iio-adc-ad7944-don-t-use-storagebits-for-sizing.patch @@ -0,0 +1,98 @@ +From 8b7f684ac437bf98fe437ac6ba387c4fc1f7b3bf Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 7 Feb 2025 14:09:07 -0600 +Subject: iio: adc: ad7944: don't use storagebits for sizing + +From: David Lechner + +[ Upstream commit 503d20ed8cf7c7b40ec0bd94f53c490c1d91c31b ] + +Replace use of storagebits with realbits for determining the number of +bytes needed for SPI transfers. + +When adding SPI offload support, storagebits will always be 32 rather +than 16 for 16-bit 16-bit chips so we can no longer rely on storagebits +being the correct size expected by the SPI framework (it always uses +4 bytes for > 16-bit xfers and 2 bytes for > 8-bit xfers). Instead, +derive the correct size from realbits since it will always be correct +even when SPI offloading is used. + +Reviewed-by: Jonathan Cameron +Reviewed-vy: Nuno Sa +Signed-off-by: David Lechner +Link: https://patch.msgid.link/20250207-dlech-mainline-spi-engine-offload-2-v8-10-e48a489be48c@baylibre.com +Signed-off-by: Jonathan Cameron +Signed-off-by: Sasha Levin +--- + drivers/iio/adc/ad7944.c | 16 +++++++++------- + 1 file changed, 9 insertions(+), 7 deletions(-) + +diff --git a/drivers/iio/adc/ad7944.c b/drivers/iio/adc/ad7944.c +index 0ec9cda10f5f8..abfababcea101 100644 +--- a/drivers/iio/adc/ad7944.c ++++ b/drivers/iio/adc/ad7944.c +@@ -98,6 +98,9 @@ struct ad7944_chip_info { + const struct iio_chan_spec channels[2]; + }; + ++/* get number of bytes for SPI xfer */ ++#define AD7944_SPI_BYTES(scan_type) ((scan_type).realbits > 16 ? 4 : 2) ++ + /* + * AD7944_DEFINE_CHIP_INFO - Define a chip info structure for a specific chip + * @_name: The name of the chip +@@ -164,7 +167,7 @@ static int ad7944_3wire_cs_mode_init_msg(struct device *dev, struct ad7944_adc * + + /* Then we can read the data during the acquisition phase */ + xfers[2].rx_buf = &adc->sample.raw; +- xfers[2].len = BITS_TO_BYTES(chan->scan_type.storagebits); ++ xfers[2].len = AD7944_SPI_BYTES(chan->scan_type); + xfers[2].bits_per_word = chan->scan_type.realbits; + + spi_message_init_with_transfers(&adc->msg, xfers, 3); +@@ -193,7 +196,7 @@ static int ad7944_4wire_mode_init_msg(struct device *dev, struct ad7944_adc *adc + xfers[0].delay.unit = SPI_DELAY_UNIT_NSECS; + + xfers[1].rx_buf = &adc->sample.raw; +- xfers[1].len = BITS_TO_BYTES(chan->scan_type.storagebits); ++ xfers[1].len = AD7944_SPI_BYTES(chan->scan_type); + xfers[1].bits_per_word = chan->scan_type.realbits; + + spi_message_init_with_transfers(&adc->msg, xfers, 2); +@@ -228,7 +231,7 @@ static int ad7944_chain_mode_init_msg(struct device *dev, struct ad7944_adc *adc + xfers[0].delay.unit = SPI_DELAY_UNIT_NSECS; + + xfers[1].rx_buf = adc->chain_mode_buf; +- xfers[1].len = BITS_TO_BYTES(chan->scan_type.storagebits) * n_chain_dev; ++ xfers[1].len = AD7944_SPI_BYTES(chan->scan_type) * n_chain_dev; + xfers[1].bits_per_word = chan->scan_type.realbits; + + spi_message_init_with_transfers(&adc->msg, xfers, 2); +@@ -274,12 +277,12 @@ static int ad7944_single_conversion(struct ad7944_adc *adc, + return ret; + + if (adc->spi_mode == AD7944_SPI_MODE_CHAIN) { +- if (chan->scan_type.storagebits > 16) ++ if (chan->scan_type.realbits > 16) + *val = ((u32 *)adc->chain_mode_buf)[chan->scan_index]; + else + *val = ((u16 *)adc->chain_mode_buf)[chan->scan_index]; + } else { +- if (chan->scan_type.storagebits > 16) ++ if (chan->scan_type.realbits > 16) + *val = adc->sample.raw.u32; + else + *val = adc->sample.raw.u16; +@@ -409,8 +412,7 @@ static int ad7944_chain_mode_alloc(struct device *dev, + /* 1 word for each voltage channel + aligned u64 for timestamp */ + + chain_mode_buf_size = ALIGN(n_chain_dev * +- BITS_TO_BYTES(chan[0].scan_type.storagebits), sizeof(u64)) +- + sizeof(u64); ++ AD7944_SPI_BYTES(chan[0].scan_type), sizeof(u64)) + sizeof(u64); + buf = devm_kzalloc(dev, chain_mode_buf_size, GFP_KERNEL); + if (!buf) + return -ENOMEM; +-- +2.39.5 + diff --git a/queue-6.14/iio-adc-qcom-spmi-iadc-fix-wakeup-source-leaks-on-de.patch b/queue-6.14/iio-adc-qcom-spmi-iadc-fix-wakeup-source-leaks-on-de.patch new file mode 100644 index 0000000000..002f190fb0 --- /dev/null +++ b/queue-6.14/iio-adc-qcom-spmi-iadc-fix-wakeup-source-leaks-on-de.patch @@ -0,0 +1,38 @@ +From eb9fee854d85c10126a9b82ba59ca0a1567cf274 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 6 Apr 2025 22:01:43 +0200 +Subject: iio: adc: qcom-spmi-iadc: Fix wakeup source leaks on device unbind + +From: Krzysztof Kozlowski + +[ Upstream commit ad3764b45c1524872b621d5667a56f6a574501bd ] + +Device can be unbound, so driver must also release memory for the wakeup +source. + +Signed-off-by: Krzysztof Kozlowski +Link: https://patch.msgid.link/20250406-b4-device-wakeup-leak-iio-v1-2-2d7d322a4a93@linaro.org +Signed-off-by: Jonathan Cameron +Signed-off-by: Sasha Levin +--- + drivers/iio/adc/qcom-spmi-iadc.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/iio/adc/qcom-spmi-iadc.c b/drivers/iio/adc/qcom-spmi-iadc.c +index 7fb8b2499a1d0..b64a8a407168b 100644 +--- a/drivers/iio/adc/qcom-spmi-iadc.c ++++ b/drivers/iio/adc/qcom-spmi-iadc.c +@@ -543,7 +543,9 @@ static int iadc_probe(struct platform_device *pdev) + else + return ret; + } else { +- device_init_wakeup(iadc->dev, 1); ++ ret = devm_device_init_wakeup(iadc->dev); ++ if (ret) ++ return dev_err_probe(iadc->dev, ret, "Failed to init wakeup\n"); + } + + ret = iadc_update_offset(iadc); +-- +2.39.5 + diff --git a/queue-6.14/iio-dac-ad3552r-hs-use-instruction-mode-for-configur.patch b/queue-6.14/iio-dac-ad3552r-hs-use-instruction-mode-for-configur.patch new file mode 100644 index 0000000000..94562299ab --- /dev/null +++ b/queue-6.14/iio-dac-ad3552r-hs-use-instruction-mode-for-configur.patch @@ -0,0 +1,100 @@ +From ccf0494eb91ba1e31fae5cc3538f3d89ae78dc3b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 14 Jan 2025 16:30:15 +0100 +Subject: iio: dac: ad3552r-hs: use instruction mode for configuration + +From: Angelo Dureghello + +[ Upstream commit 21889245fb538123ac9968eea0018f878b44c8c8 ] + +Use "instruction" mode over initial configuration and all other +non-streaming operations. + +DAC boots in streaming mode as default, and the driver is not +changing this mode. + +Instruction r/w is still working because instruction is processed +from the DAC after chip select is deasserted, this works until +loop mode is 0 or greater than the instruction size. + +All initial operations should be more safely done in instruction +mode, a mode provided for this. + +Signed-off-by: Angelo Dureghello +Link: https://patch.msgid.link/20250114-wip-bl-ad3552r-axi-v0-iio-testing-carlos-v4-6-979402e33545@baylibre.com +Signed-off-by: Jonathan Cameron +Signed-off-by: Sasha Levin +--- + drivers/iio/dac/ad3552r-hs.c | 29 ++++++++++++++++++++++++++++- + 1 file changed, 28 insertions(+), 1 deletion(-) + +diff --git a/drivers/iio/dac/ad3552r-hs.c b/drivers/iio/dac/ad3552r-hs.c +index 8974df6256708..67957fc21696a 100644 +--- a/drivers/iio/dac/ad3552r-hs.c ++++ b/drivers/iio/dac/ad3552r-hs.c +@@ -137,13 +137,20 @@ static int ad3552r_hs_buffer_postenable(struct iio_dev *indio_dev) + if (ret) + return ret; + ++ /* Primary region access, set streaming mode (now in SPI + SDR). */ ++ ret = ad3552r_qspi_update_reg_bits(st, ++ AD3552R_REG_ADDR_INTERFACE_CONFIG_B, ++ AD3552R_MASK_SINGLE_INST, 0, 1); ++ if (ret) ++ return ret; ++ + /* Inform DAC chip to switch into DDR mode */ + ret = ad3552r_qspi_update_reg_bits(st, + AD3552R_REG_ADDR_INTERFACE_CONFIG_D, + AD3552R_MASK_SPI_CONFIG_DDR, + AD3552R_MASK_SPI_CONFIG_DDR, 1); + if (ret) +- return ret; ++ goto exit_err_ddr; + + /* Inform DAC IP to go for DDR mode from now on */ + ret = iio_backend_ddr_enable(st->back); +@@ -174,6 +181,11 @@ static int ad3552r_hs_buffer_postenable(struct iio_dev *indio_dev) + + iio_backend_ddr_disable(st->back); + ++exit_err_ddr: ++ ad3552r_qspi_update_reg_bits(st, AD3552R_REG_ADDR_INTERFACE_CONFIG_B, ++ AD3552R_MASK_SINGLE_INST, ++ AD3552R_MASK_SINGLE_INST, 1); ++ + return ret; + } + +@@ -198,6 +210,14 @@ static int ad3552r_hs_buffer_predisable(struct iio_dev *indio_dev) + if (ret) + return ret; + ++ /* Back to single instruction mode, disabling loop. */ ++ ret = ad3552r_qspi_update_reg_bits(st, ++ AD3552R_REG_ADDR_INTERFACE_CONFIG_B, ++ AD3552R_MASK_SINGLE_INST, ++ AD3552R_MASK_SINGLE_INST, 1); ++ if (ret) ++ return ret; ++ + return 0; + } + +@@ -308,6 +328,13 @@ static int ad3552r_hs_setup(struct ad3552r_hs_state *st) + if (ret) + return ret; + ++ ret = st->data->bus_reg_write(st->back, ++ AD3552R_REG_ADDR_INTERFACE_CONFIG_B, ++ AD3552R_MASK_SINGLE_INST | ++ AD3552R_MASK_SHORT_INSTRUCTION, 1); ++ if (ret) ++ return ret; ++ + ret = ad3552r_hs_scratch_pad_test(st); + if (ret) + return ret; +-- +2.39.5 + diff --git a/queue-6.14/iio-dac-adi-axi-dac-add-bus-mode-setup.patch b/queue-6.14/iio-dac-adi-axi-dac-add-bus-mode-setup.patch new file mode 100644 index 0000000000..2786e98aad --- /dev/null +++ b/queue-6.14/iio-dac-adi-axi-dac-add-bus-mode-setup.patch @@ -0,0 +1,109 @@ +From efe6d7110da8b3a7d436dca5b3c58020b0812cc1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 14 Jan 2025 16:30:13 +0100 +Subject: iio: dac: adi-axi-dac: add bus mode setup + +From: Angelo Dureghello + +[ Upstream commit 8ab67b37b81dfaa00a25e95a5f5a020f374848bb ] + +The ad354xr requires DSPI mode (2 data lanes) to work in buffering +mode, so, depending on the DAC type, target TRANSFER_REGISTER +"MULTI_IO_MODE" bitfield can be set between: + SPI (configuration, entire ad35xxr family), + DSPI (ad354xr), + QSPI (ad355xr). +Also bus IO_MODE must be set accordingly. + +About removal of AXI_DAC_CUSTOM_CTRL_SYNCED_TRANSFER, according to +the HDL history the flag has never been used. So looks like the driver +was including it by mistake or in anticipation for something that was +never implemented on HDL side. + +Current HDL updated documentation confirm it is actually not in use +anymore and replaced by the IO_MODE bits. + +Reviewed-by: Nuno Sa +Signed-off-by: Angelo Dureghello +Link: https://patch.msgid.link/20250114-wip-bl-ad3552r-axi-v0-iio-testing-carlos-v4-4-979402e33545@baylibre.com +Signed-off-by: Jonathan Cameron +Signed-off-by: Sasha Levin +--- + drivers/iio/dac/ad3552r-hs.h | 8 ++++++++ + drivers/iio/dac/adi-axi-dac.c | 22 +++++++++++++++++++++- + 2 files changed, 29 insertions(+), 1 deletion(-) + +diff --git a/drivers/iio/dac/ad3552r-hs.h b/drivers/iio/dac/ad3552r-hs.h +index 724261d38dea3..4a9e352341244 100644 +--- a/drivers/iio/dac/ad3552r-hs.h ++++ b/drivers/iio/dac/ad3552r-hs.h +@@ -8,11 +8,19 @@ + + struct iio_backend; + ++enum ad3552r_io_mode { ++ AD3552R_IO_MODE_SPI, ++ AD3552R_IO_MODE_DSPI, ++ AD3552R_IO_MODE_QSPI, ++}; ++ + struct ad3552r_hs_platform_data { + int (*bus_reg_read)(struct iio_backend *back, u32 reg, u32 *val, + size_t data_size); + int (*bus_reg_write)(struct iio_backend *back, u32 reg, u32 val, + size_t data_size); ++ int (*bus_set_io_mode)(struct iio_backend *back, ++ enum ad3552r_io_mode mode); + u32 bus_sample_data_clock_hz; + }; + +diff --git a/drivers/iio/dac/adi-axi-dac.c b/drivers/iio/dac/adi-axi-dac.c +index ac871deb8063c..bcaf365feef42 100644 +--- a/drivers/iio/dac/adi-axi-dac.c ++++ b/drivers/iio/dac/adi-axi-dac.c +@@ -64,7 +64,7 @@ + #define AXI_DAC_UI_STATUS_IF_BUSY BIT(4) + #define AXI_DAC_CUSTOM_CTRL_REG 0x008C + #define AXI_DAC_CUSTOM_CTRL_ADDRESS GENMASK(31, 24) +-#define AXI_DAC_CUSTOM_CTRL_SYNCED_TRANSFER BIT(2) ++#define AXI_DAC_CUSTOM_CTRL_MULTI_IO_MODE GENMASK(3, 2) + #define AXI_DAC_CUSTOM_CTRL_STREAM BIT(1) + #define AXI_DAC_CUSTOM_CTRL_TRANSFER_DATA BIT(0) + +@@ -722,6 +722,25 @@ static int axi_dac_bus_reg_read(struct iio_backend *back, u32 reg, u32 *val, + return regmap_read(st->regmap, AXI_DAC_CUSTOM_RD_REG, val); + } + ++static int axi_dac_bus_set_io_mode(struct iio_backend *back, ++ enum ad3552r_io_mode mode) ++{ ++ struct axi_dac_state *st = iio_backend_get_priv(back); ++ int ival, ret; ++ ++ guard(mutex)(&st->lock); ++ ++ ret = regmap_update_bits(st->regmap, AXI_DAC_CUSTOM_CTRL_REG, ++ AXI_DAC_CUSTOM_CTRL_MULTI_IO_MODE, ++ FIELD_PREP(AXI_DAC_CUSTOM_CTRL_MULTI_IO_MODE, mode)); ++ if (ret) ++ return ret; ++ ++ return regmap_read_poll_timeout(st->regmap, AXI_DAC_UI_STATUS_REG, ival, ++ FIELD_GET(AXI_DAC_UI_STATUS_IF_BUSY, ival) == 0, 10, ++ 100 * KILO); ++} ++ + static void axi_dac_child_remove(void *data) + { + platform_device_unregister(data); +@@ -733,6 +752,7 @@ static int axi_dac_create_platform_device(struct axi_dac_state *st, + struct ad3552r_hs_platform_data pdata = { + .bus_reg_read = axi_dac_bus_reg_read, + .bus_reg_write = axi_dac_bus_reg_write, ++ .bus_set_io_mode = axi_dac_bus_set_io_mode, + .bus_sample_data_clock_hz = st->dac_clk_rate, + }; + struct platform_device_info pi = { +-- +2.39.5 + diff --git a/queue-6.14/iio-imu-st_lsm6dsx-fix-wakeup-source-leaks-on-device.patch b/queue-6.14/iio-imu-st_lsm6dsx-fix-wakeup-source-leaks-on-device.patch new file mode 100644 index 0000000000..c64d2bb98f --- /dev/null +++ b/queue-6.14/iio-imu-st_lsm6dsx-fix-wakeup-source-leaks-on-device.patch @@ -0,0 +1,42 @@ +From deae26664c4513427f1b49498292946c879f0cbb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 6 Apr 2025 22:01:44 +0200 +Subject: iio: imu: st_lsm6dsx: Fix wakeup source leaks on device unbind + +From: Krzysztof Kozlowski + +[ Upstream commit 4551383e78d59b34eea3f4ed28ad22df99e25d59 ] + +Device can be unbound, so driver must also release memory for the wakeup +source. + +Signed-off-by: Krzysztof Kozlowski +Acked-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20250406-b4-device-wakeup-leak-iio-v1-3-2d7d322a4a93@linaro.org +Signed-off-by: Jonathan Cameron +Signed-off-by: Sasha Levin +--- + drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c +index 4fdcc2acc94ed..96c6106b95eef 100644 +--- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c ++++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c +@@ -2719,8 +2719,11 @@ int st_lsm6dsx_probe(struct device *dev, int irq, int hw_id, + } + + if (device_property_read_bool(dev, "wakeup-source") || +- (pdata && pdata->wakeup_source)) +- device_init_wakeup(dev, true); ++ (pdata && pdata->wakeup_source)) { ++ err = devm_device_init_wakeup(dev); ++ if (err) ++ return dev_err_probe(dev, err, "Failed to init wakeup\n"); ++ } + + return 0; + } +-- +2.39.5 + diff --git a/queue-6.14/ima-process_measurement-needlessly-takes-inode_lock-.patch b/queue-6.14/ima-process_measurement-needlessly-takes-inode_lock-.patch new file mode 100644 index 0000000000..c9a9172cb1 --- /dev/null +++ b/queue-6.14/ima-process_measurement-needlessly-takes-inode_lock-.patch @@ -0,0 +1,43 @@ +From ddb28b4a931fda69cb118d64a04906e00607f394 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 27 Mar 2025 11:09:11 -0500 +Subject: ima: process_measurement() needlessly takes inode_lock() on MAY_READ + +From: Frederick Lawler + +[ Upstream commit 30d68cb0c37ebe2dc63aa1d46a28b9163e61caa2 ] + +On IMA policy update, if a measure rule exists in the policy, +IMA_MEASURE is set for ima_policy_flags which makes the violation_check +variable always true. Coupled with a no-action on MAY_READ for a +FILE_CHECK call, we're always taking the inode_lock(). + +This becomes a performance problem for extremely heavy read-only workloads. +Therefore, prevent this only in the case there's no action to be taken. + +Signed-off-by: Frederick Lawler +Acked-by: Roberto Sassu +Signed-off-by: Mimi Zohar +Signed-off-by: Sasha Levin +--- + security/integrity/ima/ima_main.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c +index f3e7ac513db3f..f99ab1a3b0f09 100644 +--- a/security/integrity/ima/ima_main.c ++++ b/security/integrity/ima/ima_main.c +@@ -245,7 +245,9 @@ static int process_measurement(struct file *file, const struct cred *cred, + &allowed_algos); + violation_check = ((func == FILE_CHECK || func == MMAP_CHECK || + func == MMAP_CHECK_REQPROT) && +- (ima_policy_flag & IMA_MEASURE)); ++ (ima_policy_flag & IMA_MEASURE) && ++ ((action & IMA_MEASURE) || ++ (file->f_mode & FMODE_WRITE))); + if (!action && !violation_check) + return 0; + +-- +2.39.5 + diff --git a/queue-6.14/intel_th-avoid-using-deprecated-page-mapping-index-f.patch b/queue-6.14/intel_th-avoid-using-deprecated-page-mapping-index-f.patch new file mode 100644 index 0000000000..bc243d84ad --- /dev/null +++ b/queue-6.14/intel_th-avoid-using-deprecated-page-mapping-index-f.patch @@ -0,0 +1,145 @@ +From e676d0fbc28bcbf9345cc2861dba49d9b421f6b0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 31 Mar 2025 13:56:08 +0100 +Subject: intel_th: avoid using deprecated page->mapping, index fields + +From: Lorenzo Stoakes + +[ Upstream commit 8e553520596bbd5ce832e26e9d721e6a0c797b8b ] + +The struct page->mapping, index fields are deprecated and soon to be only +available as part of a folio. + +It is likely the intel_th code which sets page->mapping, index is was +implemented out of concern that some aspect of the page fault logic may +encounter unexpected problems should they not. + +However, the appropriate interface for inserting kernel-allocated memory is +vm_insert_page() in a VM_MIXEDMAP. By using the helper function +vmf_insert_mixed() we can do this with minimal churn in the existing fault +handler. + +By doing so, we bypass the remainder of the faulting logic. The pages are +still pinned so there is no possibility of anything unexpected being done +with the pages once established. + +It would also be reasonable to pre-map everything on fault, however to +minimise churn we retain the fault handler. + +We also eliminate all code which clears page->mapping on teardown as this +has now become unnecessary. + +The MSU code relies on faulting to function correctly, so is by definition +dependent on CONFIG_MMU. We avoid spurious reports about compilation +failure for unsupported platforms by making this requirement explicit in +Kconfig as part of this change too. + +Signed-off-by: Lorenzo Stoakes +Acked-by: Alexander Shishkin +Link: https://lore.kernel.org/r/20250331125608.60300-1-lorenzo.stoakes@oracle.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/hwtracing/intel_th/Kconfig | 1 + + drivers/hwtracing/intel_th/msu.c | 31 +++++++----------------------- + 2 files changed, 8 insertions(+), 24 deletions(-) + +diff --git a/drivers/hwtracing/intel_th/Kconfig b/drivers/hwtracing/intel_th/Kconfig +index 4b6359326ede9..4f7d2b6d79e29 100644 +--- a/drivers/hwtracing/intel_th/Kconfig ++++ b/drivers/hwtracing/intel_th/Kconfig +@@ -60,6 +60,7 @@ config INTEL_TH_STH + + config INTEL_TH_MSU + tristate "Intel(R) Trace Hub Memory Storage Unit" ++ depends on MMU + help + Memory Storage Unit (MSU) trace output device enables + storing STP traces to system memory. It supports single +diff --git a/drivers/hwtracing/intel_th/msu.c b/drivers/hwtracing/intel_th/msu.c +index bf99d79a41920..7163950eb3719 100644 +--- a/drivers/hwtracing/intel_th/msu.c ++++ b/drivers/hwtracing/intel_th/msu.c +@@ -19,6 +19,7 @@ + #include + #include + #include ++#include + + #ifdef CONFIG_X86 + #include +@@ -976,7 +977,6 @@ static void msc_buffer_contig_free(struct msc *msc) + for (off = 0; off < msc->nr_pages << PAGE_SHIFT; off += PAGE_SIZE) { + struct page *page = virt_to_page(msc->base + off); + +- page->mapping = NULL; + __free_page(page); + } + +@@ -1158,9 +1158,6 @@ static void __msc_buffer_win_free(struct msc *msc, struct msc_window *win) + int i; + + for_each_sg(win->sgt->sgl, sg, win->nr_segs, i) { +- struct page *page = msc_sg_page(sg); +- +- page->mapping = NULL; + dma_free_coherent(msc_dev(win->msc)->parent->parent, PAGE_SIZE, + sg_virt(sg), sg_dma_address(sg)); + } +@@ -1601,22 +1598,10 @@ static void msc_mmap_close(struct vm_area_struct *vma) + { + struct msc_iter *iter = vma->vm_file->private_data; + struct msc *msc = iter->msc; +- unsigned long pg; + + if (!atomic_dec_and_mutex_lock(&msc->mmap_count, &msc->buf_mutex)) + return; + +- /* drop page _refcounts */ +- for (pg = 0; pg < msc->nr_pages; pg++) { +- struct page *page = msc_buffer_get_page(msc, pg); +- +- if (WARN_ON_ONCE(!page)) +- continue; +- +- if (page->mapping) +- page->mapping = NULL; +- } +- + /* last mapping -- drop user_count */ + atomic_dec(&msc->user_count); + mutex_unlock(&msc->buf_mutex); +@@ -1626,16 +1611,14 @@ static vm_fault_t msc_mmap_fault(struct vm_fault *vmf) + { + struct msc_iter *iter = vmf->vma->vm_file->private_data; + struct msc *msc = iter->msc; ++ struct page *page; + +- vmf->page = msc_buffer_get_page(msc, vmf->pgoff); +- if (!vmf->page) ++ page = msc_buffer_get_page(msc, vmf->pgoff); ++ if (!page) + return VM_FAULT_SIGBUS; + +- get_page(vmf->page); +- vmf->page->mapping = vmf->vma->vm_file->f_mapping; +- vmf->page->index = vmf->pgoff; +- +- return 0; ++ get_page(page); ++ return vmf_insert_mixed(vmf->vma, vmf->address, page_to_pfn_t(page)); + } + + static const struct vm_operations_struct msc_mmap_ops = { +@@ -1676,7 +1659,7 @@ static int intel_th_msc_mmap(struct file *file, struct vm_area_struct *vma) + atomic_dec(&msc->user_count); + + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); +- vm_flags_set(vma, VM_DONTEXPAND | VM_DONTCOPY); ++ vm_flags_set(vma, VM_DONTEXPAND | VM_DONTCOPY | VM_MIXEDMAP); + vma->vm_ops = &msc_mmap_ops; + return ret; + } +-- +2.39.5 + diff --git a/queue-6.14/io_uring-don-t-duplicate-flushing-in-io_req_post_cqe.patch b/queue-6.14/io_uring-don-t-duplicate-flushing-in-io_req_post_cqe.patch new file mode 100644 index 0000000000..e72b43ed2c --- /dev/null +++ b/queue-6.14/io_uring-don-t-duplicate-flushing-in-io_req_post_cqe.patch @@ -0,0 +1,47 @@ +From 90d0369ec220ea01b91615470def997e9bd7365d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 24 Apr 2025 12:28:39 +0100 +Subject: io_uring: don't duplicate flushing in io_req_post_cqe + +From: Pavel Begunkov + +[ Upstream commit 5e16f1a68d28965c12b6fa227a306fef8a680f84 ] + +io_req_post_cqe() sets submit_state.cq_flush so that +*flush_completions() can take care of batch commiting CQEs. Don't commit +it twice by using __io_cq_unlock_post(). + +Signed-off-by: Pavel Begunkov +Link: https://lore.kernel.org/r/41c416660c509cee676b6cad96081274bcb459f3.1745493861.git.asml.silence@gmail.com +Signed-off-by: Jens Axboe +Signed-off-by: Sasha Levin +--- + io_uring/io_uring.c | 11 ++++++++--- + 1 file changed, 8 insertions(+), 3 deletions(-) + +diff --git a/io_uring/io_uring.c b/io_uring/io_uring.c +index a60cb9d30cc0d..f1c09e2b53022 100644 +--- a/io_uring/io_uring.c ++++ b/io_uring/io_uring.c +@@ -864,10 +864,15 @@ bool io_req_post_cqe(struct io_kiocb *req, s32 res, u32 cflags) + lockdep_assert(!io_wq_current_is_worker()); + lockdep_assert_held(&ctx->uring_lock); + +- __io_cq_lock(ctx); +- posted = io_fill_cqe_aux(ctx, req->cqe.user_data, res, cflags); ++ if (!ctx->lockless_cq) { ++ spin_lock(&ctx->completion_lock); ++ posted = io_fill_cqe_aux(ctx, req->cqe.user_data, res, cflags); ++ spin_unlock(&ctx->completion_lock); ++ } else { ++ posted = io_fill_cqe_aux(ctx, req->cqe.user_data, res, cflags); ++ } ++ + ctx->submit_state.cq_flush = true; +- __io_cq_unlock_post(ctx); + return posted; + } + +-- +2.39.5 + diff --git a/queue-6.14/io_uring-fdinfo-annotate-racy-sq-cq-head-tail-reads.patch b/queue-6.14/io_uring-fdinfo-annotate-racy-sq-cq-head-tail-reads.patch new file mode 100644 index 0000000000..b56709c2a2 --- /dev/null +++ b/queue-6.14/io_uring-fdinfo-annotate-racy-sq-cq-head-tail-reads.patch @@ -0,0 +1,47 @@ +From a75e5e6e30dd8aedd05fceab66537f8f61188c27 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 30 Apr 2025 07:17:17 -0600 +Subject: io_uring/fdinfo: annotate racy sq/cq head/tail reads + +From: Jens Axboe + +[ Upstream commit f024d3a8ded0d8d2129ae123d7a5305c29ca44ce ] + +syzbot complains about the cached sq head read, and it's totally right. +But we don't need to care, it's just reading fdinfo, and reading the +CQ or SQ tail/head entries are known racy in that they are just a view +into that very instant and may of course be outdated by the time they +are reported. + +Annotate both the SQ head and CQ tail read with data_race() to avoid +this syzbot complaint. + +Link: https://lore.kernel.org/io-uring/6811f6dc.050a0220.39e3a1.0d0e.GAE@google.com/ +Reported-by: syzbot+3e77fd302e99f5af9394@syzkaller.appspotmail.com +Signed-off-by: Jens Axboe +Signed-off-by: Sasha Levin +--- + io_uring/fdinfo.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/io_uring/fdinfo.c b/io_uring/fdinfo.c +index 336aec7ea8c29..e0d6a59a89fa1 100644 +--- a/io_uring/fdinfo.c ++++ b/io_uring/fdinfo.c +@@ -117,11 +117,11 @@ static void __io_uring_show_fdinfo(struct io_ring_ctx *ctx, struct seq_file *m) + seq_printf(m, "SqMask:\t0x%x\n", sq_mask); + seq_printf(m, "SqHead:\t%u\n", sq_head); + seq_printf(m, "SqTail:\t%u\n", sq_tail); +- seq_printf(m, "CachedSqHead:\t%u\n", ctx->cached_sq_head); ++ seq_printf(m, "CachedSqHead:\t%u\n", data_race(ctx->cached_sq_head)); + seq_printf(m, "CqMask:\t0x%x\n", cq_mask); + seq_printf(m, "CqHead:\t%u\n", cq_head); + seq_printf(m, "CqTail:\t%u\n", cq_tail); +- seq_printf(m, "CachedCqTail:\t%u\n", ctx->cached_cq_tail); ++ seq_printf(m, "CachedCqTail:\t%u\n", data_race(ctx->cached_cq_tail)); + seq_printf(m, "SQEs:\t%u\n", sq_tail - sq_head); + sq_entries = min(sq_tail - sq_head, ctx->sq_entries); + for (i = 0; i < sq_entries; i++) { +-- +2.39.5 + diff --git a/queue-6.14/io_uring-msg-initialise-msg-request-opcode.patch b/queue-6.14/io_uring-msg-initialise-msg-request-opcode.patch new file mode 100644 index 0000000000..7cdf234e66 --- /dev/null +++ b/queue-6.14/io_uring-msg-initialise-msg-request-opcode.patch @@ -0,0 +1,36 @@ +From 036b5f25ab2930091c39768a5c19dda0cbc63a50 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 28 Mar 2025 23:11:50 +0000 +Subject: io_uring/msg: initialise msg request opcode + +From: Pavel Begunkov + +[ Upstream commit 9cc0bbdaba2a66ad90bc6ce45163b7745baffe98 ] + +It's risky to have msg request opcode set to garbage, so at least +initialise it to nop. Later we might want to add a user inaccessible +opcode for such cases. + +Signed-off-by: Pavel Begunkov +Link: https://lore.kernel.org/r/9afe650fcb348414a4529d89f52eb8969ba06efd.1743190078.git.asml.silence@gmail.com +Signed-off-by: Jens Axboe +Signed-off-by: Sasha Levin +--- + io_uring/msg_ring.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/io_uring/msg_ring.c b/io_uring/msg_ring.c +index 7e6f68e911f10..f844ab24cda42 100644 +--- a/io_uring/msg_ring.c ++++ b/io_uring/msg_ring.c +@@ -93,6 +93,7 @@ static int io_msg_remote_post(struct io_ring_ctx *ctx, struct io_kiocb *req, + kmem_cache_free(req_cachep, req); + return -EOWNERDEAD; + } ++ req->opcode = IORING_OP_NOP; + req->cqe.user_data = user_data; + io_req_set_res(req, res, cflags); + percpu_ref_get(&ctx->refs); +-- +2.39.5 + diff --git a/queue-6.14/io_uring-sanitise-ring-params-earlier.patch b/queue-6.14/io_uring-sanitise-ring-params-earlier.patch new file mode 100644 index 0000000000..7ec13134b8 --- /dev/null +++ b/queue-6.14/io_uring-sanitise-ring-params-earlier.patch @@ -0,0 +1,135 @@ +From cf671bbaae9d5538cbc2ec16637900218e31bf46 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 31 Jan 2025 17:31:03 +0000 +Subject: io_uring: sanitise ring params earlier + +From: Pavel Begunkov + +[ Upstream commit 92a3bac9a57c39728226ab191859c85f5e2829c0 ] + +Do all struct io_uring_params validation early on before allocating the +context. That makes initialisation easier, especially by having fewer +places where we need to care about partial de-initialisation. + +Signed-off-by: Pavel Begunkov +Link: https://lore.kernel.org/r/363ba90b83ff78eefdc88b60e1b2c4a39d182247.1738344646.git.asml.silence@gmail.com +Signed-off-by: Jens Axboe +Signed-off-by: Sasha Levin +--- + io_uring/io_uring.c | 77 ++++++++++++++++++++++++++------------------- + 1 file changed, 44 insertions(+), 33 deletions(-) + +diff --git a/io_uring/io_uring.c b/io_uring/io_uring.c +index 56f10cce8f009..52c9fa6c06450 100644 +--- a/io_uring/io_uring.c ++++ b/io_uring/io_uring.c +@@ -3532,6 +3532,44 @@ static struct file *io_uring_get_file(struct io_ring_ctx *ctx) + O_RDWR | O_CLOEXEC, NULL); + } + ++static int io_uring_sanitise_params(struct io_uring_params *p) ++{ ++ unsigned flags = p->flags; ++ ++ /* There is no way to mmap rings without a real fd */ ++ if ((flags & IORING_SETUP_REGISTERED_FD_ONLY) && ++ !(flags & IORING_SETUP_NO_MMAP)) ++ return -EINVAL; ++ ++ if (flags & IORING_SETUP_SQPOLL) { ++ /* IPI related flags don't make sense with SQPOLL */ ++ if (flags & (IORING_SETUP_COOP_TASKRUN | ++ IORING_SETUP_TASKRUN_FLAG | ++ IORING_SETUP_DEFER_TASKRUN)) ++ return -EINVAL; ++ } ++ ++ if (flags & IORING_SETUP_TASKRUN_FLAG) { ++ if (!(flags & (IORING_SETUP_COOP_TASKRUN | ++ IORING_SETUP_DEFER_TASKRUN))) ++ return -EINVAL; ++ } ++ ++ /* HYBRID_IOPOLL only valid with IOPOLL */ ++ if ((flags & IORING_SETUP_HYBRID_IOPOLL) && !(flags & IORING_SETUP_IOPOLL)) ++ return -EINVAL; ++ ++ /* ++ * For DEFER_TASKRUN we require the completion task to be the same as ++ * the submission task. This implies that there is only one submitter. ++ */ ++ if ((flags & IORING_SETUP_DEFER_TASKRUN) && ++ !(flags & IORING_SETUP_SINGLE_ISSUER)) ++ return -EINVAL; ++ ++ return 0; ++} ++ + int io_uring_fill_params(unsigned entries, struct io_uring_params *p) + { + if (!entries) +@@ -3542,10 +3580,6 @@ int io_uring_fill_params(unsigned entries, struct io_uring_params *p) + entries = IORING_MAX_ENTRIES; + } + +- if ((p->flags & IORING_SETUP_REGISTERED_FD_ONLY) +- && !(p->flags & IORING_SETUP_NO_MMAP)) +- return -EINVAL; +- + /* + * Use twice as many entries for the CQ ring. It's possible for the + * application to drive a higher depth than the size of the SQ ring, +@@ -3607,6 +3641,10 @@ static __cold int io_uring_create(unsigned entries, struct io_uring_params *p, + struct file *file; + int ret; + ++ ret = io_uring_sanitise_params(p); ++ if (ret) ++ return ret; ++ + ret = io_uring_fill_params(entries, p); + if (unlikely(ret)) + return ret; +@@ -3654,37 +3692,10 @@ static __cold int io_uring_create(unsigned entries, struct io_uring_params *p, + * For SQPOLL, we just need a wakeup, always. For !SQPOLL, if + * COOP_TASKRUN is set, then IPIs are never needed by the app. + */ +- ret = -EINVAL; +- if (ctx->flags & IORING_SETUP_SQPOLL) { +- /* IPI related flags don't make sense with SQPOLL */ +- if (ctx->flags & (IORING_SETUP_COOP_TASKRUN | +- IORING_SETUP_TASKRUN_FLAG | +- IORING_SETUP_DEFER_TASKRUN)) +- goto err; ++ if (ctx->flags & (IORING_SETUP_SQPOLL|IORING_SETUP_COOP_TASKRUN)) + ctx->notify_method = TWA_SIGNAL_NO_IPI; +- } else if (ctx->flags & IORING_SETUP_COOP_TASKRUN) { +- ctx->notify_method = TWA_SIGNAL_NO_IPI; +- } else { +- if (ctx->flags & IORING_SETUP_TASKRUN_FLAG && +- !(ctx->flags & IORING_SETUP_DEFER_TASKRUN)) +- goto err; ++ else + ctx->notify_method = TWA_SIGNAL; +- } +- +- /* HYBRID_IOPOLL only valid with IOPOLL */ +- if ((ctx->flags & (IORING_SETUP_IOPOLL|IORING_SETUP_HYBRID_IOPOLL)) == +- IORING_SETUP_HYBRID_IOPOLL) +- goto err; +- +- /* +- * For DEFER_TASKRUN we require the completion task to be the same as the +- * submission task. This implies that there is only one submitter, so enforce +- * that. +- */ +- if (ctx->flags & IORING_SETUP_DEFER_TASKRUN && +- !(ctx->flags & IORING_SETUP_SINGLE_ISSUER)) { +- goto err; +- } + + /* + * This is just grabbed for accounting purposes. When a process exits, +-- +2.39.5 + diff --git a/queue-6.14/io_uring-use-io_req_link_flags-more.patch b/queue-6.14/io_uring-use-io_req_link_flags-more.patch new file mode 100644 index 0000000000..ef7ce51ecd --- /dev/null +++ b/queue-6.14/io_uring-use-io_req_link_flags-more.patch @@ -0,0 +1,59 @@ +From 6b3a204289e84403d44c8f401cd97522f6f18040 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 11 Feb 2025 13:19:56 -0700 +Subject: io_uring: use IO_REQ_LINK_FLAGS more + +From: Caleb Sander Mateos + +[ Upstream commit 0e8934724f78602635d6e11c97ef48caa693cb65 ] + +Replace the 2 instances of REQ_F_LINK | REQ_F_HARDLINK with +the more commonly used IO_REQ_LINK_FLAGS. + +Signed-off-by: Caleb Sander Mateos +Link: https://lore.kernel.org/r/20250211202002.3316324-1-csander@purestorage.com +Signed-off-by: Jens Axboe +Signed-off-by: Sasha Levin +--- + io_uring/io_uring.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/io_uring/io_uring.c b/io_uring/io_uring.c +index f1c09e2b53022..56f10cce8f009 100644 +--- a/io_uring/io_uring.c ++++ b/io_uring/io_uring.c +@@ -110,11 +110,13 @@ + #define SQE_VALID_FLAGS (SQE_COMMON_FLAGS | IOSQE_BUFFER_SELECT | \ + IOSQE_IO_DRAIN | IOSQE_CQE_SKIP_SUCCESS) + ++#define IO_REQ_LINK_FLAGS (REQ_F_LINK | REQ_F_HARDLINK) ++ + #define IO_REQ_CLEAN_FLAGS (REQ_F_BUFFER_SELECTED | REQ_F_NEED_CLEANUP | \ + REQ_F_POLLED | REQ_F_INFLIGHT | REQ_F_CREDS | \ + REQ_F_ASYNC_DATA) + +-#define IO_REQ_CLEAN_SLOW_FLAGS (REQ_F_REFCOUNT | REQ_F_LINK | REQ_F_HARDLINK |\ ++#define IO_REQ_CLEAN_SLOW_FLAGS (REQ_F_REFCOUNT | IO_REQ_LINK_FLAGS | \ + REQ_F_REISSUE | IO_REQ_CLEAN_FLAGS) + + #define IO_TCTX_REFS_CACHE_NR (1U << 10) +@@ -131,7 +133,6 @@ struct io_defer_entry { + + /* requests with any of those set should undergo io_disarm_next() */ + #define IO_DISARM_MASK (REQ_F_ARM_LTIMEOUT | REQ_F_LINK_TIMEOUT | REQ_F_FAIL) +-#define IO_REQ_LINK_FLAGS (REQ_F_LINK | REQ_F_HARDLINK) + + /* + * No waiters. It's larger than any valid value of the tw counter +@@ -1150,7 +1151,7 @@ static inline void io_req_local_work_add(struct io_kiocb *req, + * We don't know how many reuqests is there in the link and whether + * they can even be queued lazily, fall back to non-lazy. + */ +- if (req->flags & (REQ_F_LINK | REQ_F_HARDLINK)) ++ if (req->flags & IO_REQ_LINK_FLAGS) + flags &= ~IOU_F_TWQ_LAZY_WAKE; + + guard(rcu)(); +-- +2.39.5 + diff --git a/queue-6.14/iommu-amd-pgtbl_v2-improve-error-handling.patch b/queue-6.14/iommu-amd-pgtbl_v2-improve-error-handling.patch new file mode 100644 index 0000000000..ae01f33ab6 --- /dev/null +++ b/queue-6.14/iommu-amd-pgtbl_v2-improve-error-handling.patch @@ -0,0 +1,36 @@ +From ebbd348df2c360fc757dc11d03001105666baa73 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 27 Feb 2025 16:23:16 +0000 +Subject: iommu/amd/pgtbl_v2: Improve error handling + +From: Vasant Hegde + +[ Upstream commit 36a1cfd497435ba5e37572fe9463bb62a7b1b984 ] + +Return -ENOMEM if v2_alloc_pte() fails to allocate memory. + +Signed-off-by: Vasant Hegde +Reviewed-by: Jason Gunthorpe +Link: https://lore.kernel.org/r/20250227162320.5805-4-vasant.hegde@amd.com +Signed-off-by: Joerg Roedel +Signed-off-by: Sasha Levin +--- + drivers/iommu/amd/io_pgtable_v2.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/iommu/amd/io_pgtable_v2.c b/drivers/iommu/amd/io_pgtable_v2.c +index c616de2c5926e..a56a273963059 100644 +--- a/drivers/iommu/amd/io_pgtable_v2.c ++++ b/drivers/iommu/amd/io_pgtable_v2.c +@@ -254,7 +254,7 @@ static int iommu_v2_map_pages(struct io_pgtable_ops *ops, unsigned long iova, + pte = v2_alloc_pte(cfg->amd.nid, pgtable->pgd, + iova, map_size, gfp, &updated); + if (!pte) { +- ret = -EINVAL; ++ ret = -ENOMEM; + goto out; + } + +-- +2.39.5 + diff --git a/queue-6.14/iommu-keep-dev-iommu-state-consistent.patch b/queue-6.14/iommu-keep-dev-iommu-state-consistent.patch new file mode 100644 index 0000000000..f47e4bce6d --- /dev/null +++ b/queue-6.14/iommu-keep-dev-iommu-state-consistent.patch @@ -0,0 +1,88 @@ +From 20596372b0be4b954fd3c272d0575b84e588ad52 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 28 Feb 2025 15:46:32 +0000 +Subject: iommu: Keep dev->iommu state consistent + +From: Robin Murphy + +[ Upstream commit 3832862eb9c4dfa0e80b2522bfaedbc8a43de97d ] + +At the moment, if of_iommu_configure() allocates dev->iommu itself via +iommu_fwspec_init(), then suffers a DT parsing failure, it cleans up the +fwspec but leaves the empty dev_iommu hanging around. So far this is +benign (if a tiny bit wasteful), but we'd like to be able to reason +about dev->iommu having a consistent and unambiguous lifecycle. Thus +make sure that the of_iommu cleanup undoes precisely whatever it did. + +Signed-off-by: Robin Murphy +Reviewed-by: Jason Gunthorpe +Link: https://lore.kernel.org/r/d219663a3f23001f23d520a883ac622d70b4e642.1740753261.git.robin.murphy@arm.com +Signed-off-by: Joerg Roedel +Signed-off-by: Sasha Levin +--- + drivers/iommu/iommu-priv.h | 2 ++ + drivers/iommu/iommu.c | 2 +- + drivers/iommu/of_iommu.c | 6 +++++- + 3 files changed, 8 insertions(+), 2 deletions(-) + +diff --git a/drivers/iommu/iommu-priv.h b/drivers/iommu/iommu-priv.h +index de5b54eaa8bf1..a5913c0b02a0a 100644 +--- a/drivers/iommu/iommu-priv.h ++++ b/drivers/iommu/iommu-priv.h +@@ -17,6 +17,8 @@ static inline const struct iommu_ops *dev_iommu_ops(struct device *dev) + return dev->iommu->iommu_dev->ops; + } + ++void dev_iommu_free(struct device *dev); ++ + const struct iommu_ops *iommu_ops_from_fwnode(const struct fwnode_handle *fwnode); + + static inline const struct iommu_ops *iommu_fwspec_ops(struct iommu_fwspec *fwspec) +diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c +index 1efe7cddb4fe3..3a2804a98203b 100644 +--- a/drivers/iommu/iommu.c ++++ b/drivers/iommu/iommu.c +@@ -352,7 +352,7 @@ static struct dev_iommu *dev_iommu_get(struct device *dev) + return param; + } + +-static void dev_iommu_free(struct device *dev) ++void dev_iommu_free(struct device *dev) + { + struct dev_iommu *param = dev->iommu; + +diff --git a/drivers/iommu/of_iommu.c b/drivers/iommu/of_iommu.c +index 97987cd78da93..e10a68b5ffde1 100644 +--- a/drivers/iommu/of_iommu.c ++++ b/drivers/iommu/of_iommu.c +@@ -116,6 +116,7 @@ static void of_pci_check_device_ats(struct device *dev, struct device_node *np) + int of_iommu_configure(struct device *dev, struct device_node *master_np, + const u32 *id) + { ++ bool dev_iommu_present; + int err; + + if (!master_np) +@@ -127,6 +128,7 @@ int of_iommu_configure(struct device *dev, struct device_node *master_np, + mutex_unlock(&iommu_probe_device_lock); + return 0; + } ++ dev_iommu_present = dev->iommu; + + /* + * We don't currently walk up the tree looking for a parent IOMMU. +@@ -147,8 +149,10 @@ int of_iommu_configure(struct device *dev, struct device_node *master_np, + err = of_iommu_configure_device(master_np, dev, id); + } + +- if (err) ++ if (err && dev_iommu_present) + iommu_fwspec_free(dev); ++ else if (err && dev->iommu) ++ dev_iommu_free(dev); + mutex_unlock(&iommu_probe_device_lock); + + if (!err && dev->bus) +-- +2.39.5 + diff --git a/queue-6.14/iommu-vt-d-check-if-sva-is-supported-when-attaching-.patch b/queue-6.14/iommu-vt-d-check-if-sva-is-supported-when-attaching-.patch new file mode 100644 index 0000000000..12bc9d6357 --- /dev/null +++ b/queue-6.14/iommu-vt-d-check-if-sva-is-supported-when-attaching-.patch @@ -0,0 +1,153 @@ +From 5004c54191c5fa7cae8938d9e8b04e18c32c22b5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 10 Mar 2025 10:47:46 +0800 +Subject: iommu/vt-d: Check if SVA is supported when attaching the SVA domain + +From: Jason Gunthorpe + +[ Upstream commit 607ba1bb096110751f6aa4b46666e0ba024ab3c2 ] + +Attach of a SVA domain should fail if SVA is not supported, move the check +for SVA support out of IOMMU_DEV_FEAT_SVA and into attach. + +Also check when allocating a SVA domain to match other drivers. + +Signed-off-by: Jason Gunthorpe +Signed-off-by: Lu Baolu +Reviewed-by: Kevin Tian +Reviewed-by: Yi Liu +Tested-by: Zhangfei Gao +Link: https://lore.kernel.org/r/20250228092631.3425464-3-baolu.lu@linux.intel.com +Signed-off-by: Joerg Roedel +Signed-off-by: Sasha Levin +--- + drivers/iommu/intel/iommu.c | 37 +------------------------------ + drivers/iommu/intel/svm.c | 43 +++++++++++++++++++++++++++++++++++++ + 2 files changed, 44 insertions(+), 36 deletions(-) + +diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c +index 7c863c41c8645..6da09345398d9 100644 +--- a/drivers/iommu/intel/iommu.c ++++ b/drivers/iommu/intel/iommu.c +@@ -3869,41 +3869,6 @@ static struct iommu_group *intel_iommu_device_group(struct device *dev) + return generic_device_group(dev); + } + +-static int intel_iommu_enable_sva(struct device *dev) +-{ +- struct device_domain_info *info = dev_iommu_priv_get(dev); +- struct intel_iommu *iommu; +- +- if (!info || dmar_disabled) +- return -EINVAL; +- +- iommu = info->iommu; +- if (!iommu) +- return -EINVAL; +- +- if (!(iommu->flags & VTD_FLAG_SVM_CAPABLE)) +- return -ENODEV; +- +- if (!info->pasid_enabled || !info->ats_enabled) +- return -EINVAL; +- +- /* +- * Devices having device-specific I/O fault handling should not +- * support PCI/PRI. The IOMMU side has no means to check the +- * capability of device-specific IOPF. Therefore, IOMMU can only +- * default that if the device driver enables SVA on a non-PRI +- * device, it will handle IOPF in its own way. +- */ +- if (!info->pri_supported) +- return 0; +- +- /* Devices supporting PRI should have it enabled. */ +- if (!info->pri_enabled) +- return -EINVAL; +- +- return 0; +-} +- + static int context_flip_pri(struct device_domain_info *info, bool enable) + { + struct intel_iommu *iommu = info->iommu; +@@ -4024,7 +3989,7 @@ intel_iommu_dev_enable_feat(struct device *dev, enum iommu_dev_features feat) + return intel_iommu_enable_iopf(dev); + + case IOMMU_DEV_FEAT_SVA: +- return intel_iommu_enable_sva(dev); ++ return 0; + + default: + return -ENODEV; +diff --git a/drivers/iommu/intel/svm.c b/drivers/iommu/intel/svm.c +index f5569347591f2..ba93123cb4eba 100644 +--- a/drivers/iommu/intel/svm.c ++++ b/drivers/iommu/intel/svm.c +@@ -110,6 +110,41 @@ static const struct mmu_notifier_ops intel_mmuops = { + .free_notifier = intel_mm_free_notifier, + }; + ++static int intel_iommu_sva_supported(struct device *dev) ++{ ++ struct device_domain_info *info = dev_iommu_priv_get(dev); ++ struct intel_iommu *iommu; ++ ++ if (!info || dmar_disabled) ++ return -EINVAL; ++ ++ iommu = info->iommu; ++ if (!iommu) ++ return -EINVAL; ++ ++ if (!(iommu->flags & VTD_FLAG_SVM_CAPABLE)) ++ return -ENODEV; ++ ++ if (!info->pasid_enabled || !info->ats_enabled) ++ return -EINVAL; ++ ++ /* ++ * Devices having device-specific I/O fault handling should not ++ * support PCI/PRI. The IOMMU side has no means to check the ++ * capability of device-specific IOPF. Therefore, IOMMU can only ++ * default that if the device driver enables SVA on a non-PRI ++ * device, it will handle IOPF in its own way. ++ */ ++ if (!info->pri_supported) ++ return 0; ++ ++ /* Devices supporting PRI should have it enabled. */ ++ if (!info->pri_enabled) ++ return -EINVAL; ++ ++ return 0; ++} ++ + static int intel_svm_set_dev_pasid(struct iommu_domain *domain, + struct device *dev, ioasid_t pasid, + struct iommu_domain *old) +@@ -121,6 +156,10 @@ static int intel_svm_set_dev_pasid(struct iommu_domain *domain, + unsigned long sflags; + int ret = 0; + ++ ret = intel_iommu_sva_supported(dev); ++ if (ret) ++ return ret; ++ + dev_pasid = domain_add_dev_pasid(domain, dev, pasid); + if (IS_ERR(dev_pasid)) + return PTR_ERR(dev_pasid); +@@ -161,6 +200,10 @@ struct iommu_domain *intel_svm_domain_alloc(struct device *dev, + struct dmar_domain *domain; + int ret; + ++ ret = intel_iommu_sva_supported(dev); ++ if (ret) ++ return ERR_PTR(ret); ++ + domain = kzalloc(sizeof(*domain), GFP_KERNEL); + if (!domain) + return ERR_PTR(-ENOMEM); +-- +2.39.5 + diff --git a/queue-6.14/iommu-vt-d-move-scalable-mode-ats-enablement-to-prob.patch b/queue-6.14/iommu-vt-d-move-scalable-mode-ats-enablement-to-prob.patch new file mode 100644 index 0000000000..f409117d6b --- /dev/null +++ b/queue-6.14/iommu-vt-d-move-scalable-mode-ats-enablement-to-prob.patch @@ -0,0 +1,165 @@ +From d228a5cb0c72d3ffbf8da4fe02b063992afa0f54 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 10 Mar 2025 10:47:47 +0800 +Subject: iommu/vt-d: Move scalable mode ATS enablement to probe path + +From: Lu Baolu + +[ Upstream commit 5518f239aff1baf772c5748da3add7243c5fb5df ] + +Device ATS is currently enabled when a domain is attached to the device +and disabled when the domain is detached. This creates a limitation: +when the IOMMU is operating in scalable mode and IOPF is enabled, the +device's domain cannot be changed. + +The previous code enables ATS when a domain is set to a device's RID and +disables it during RID domain switch. So, if a PASID is set with a +domain requiring PRI, ATS should remain enabled until the domain is +removed. During the PASID domain's lifecycle, if the RID's domain +changes, PRI will be disrupted because it depends on ATS, which is +disabled when the blocking domain is set for the device's RID. + +Remove this limitation by moving ATS enablement to the device probe path. + +Signed-off-by: Lu Baolu +Reviewed-by: Kevin Tian +Tested-by: Zhangfei Gao +Link: https://lore.kernel.org/r/20250228092631.3425464-5-baolu.lu@linux.intel.com +Signed-off-by: Joerg Roedel +Signed-off-by: Sasha Levin +--- + drivers/iommu/intel/iommu.c | 51 ++++++++++++++++++++----------------- + 1 file changed, 27 insertions(+), 24 deletions(-) + +diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c +index 07adf4ceeea06..7c863c41c8645 100644 +--- a/drivers/iommu/intel/iommu.c ++++ b/drivers/iommu/intel/iommu.c +@@ -1172,32 +1172,28 @@ static bool dev_needs_extra_dtlb_flush(struct pci_dev *pdev) + return true; + } + +-static void iommu_enable_pci_caps(struct device_domain_info *info) ++static void iommu_enable_pci_ats(struct device_domain_info *info) + { + struct pci_dev *pdev; + +- if (!dev_is_pci(info->dev)) ++ if (!info->ats_supported) + return; + + pdev = to_pci_dev(info->dev); +- if (info->ats_supported && pci_ats_page_aligned(pdev) && +- !pci_enable_ats(pdev, VTD_PAGE_SHIFT)) ++ if (!pci_ats_page_aligned(pdev)) ++ return; ++ ++ if (!pci_enable_ats(pdev, VTD_PAGE_SHIFT)) + info->ats_enabled = 1; + } + +-static void iommu_disable_pci_caps(struct device_domain_info *info) ++static void iommu_disable_pci_ats(struct device_domain_info *info) + { +- struct pci_dev *pdev; +- +- if (!dev_is_pci(info->dev)) ++ if (!info->ats_enabled) + return; + +- pdev = to_pci_dev(info->dev); +- +- if (info->ats_enabled) { +- pci_disable_ats(pdev); +- info->ats_enabled = 0; +- } ++ pci_disable_ats(to_pci_dev(info->dev)); ++ info->ats_enabled = 0; + } + + static void intel_flush_iotlb_all(struct iommu_domain *domain) +@@ -1556,12 +1552,19 @@ domain_context_mapping(struct dmar_domain *domain, struct device *dev) + struct device_domain_info *info = dev_iommu_priv_get(dev); + struct intel_iommu *iommu = info->iommu; + u8 bus = info->bus, devfn = info->devfn; ++ int ret; + + if (!dev_is_pci(dev)) + return domain_context_mapping_one(domain, iommu, bus, devfn); + +- return pci_for_each_dma_alias(to_pci_dev(dev), +- domain_context_mapping_cb, domain); ++ ret = pci_for_each_dma_alias(to_pci_dev(dev), ++ domain_context_mapping_cb, domain); ++ if (ret) ++ return ret; ++ ++ iommu_enable_pci_ats(info); ++ ++ return 0; + } + + /* Return largest possible superpage level for a given mapping */ +@@ -1843,8 +1846,6 @@ static int dmar_domain_attach_device(struct dmar_domain *domain, + if (ret) + goto out_block_translation; + +- iommu_enable_pci_caps(info); +- + ret = cache_tag_assign_domain(domain, dev, IOMMU_NO_PASID); + if (ret) + goto out_block_translation; +@@ -3210,6 +3211,7 @@ static void domain_context_clear(struct device_domain_info *info) + + pci_for_each_dma_alias(to_pci_dev(info->dev), + &domain_context_clear_one_cb, info); ++ iommu_disable_pci_ats(info); + } + + /* +@@ -3226,7 +3228,6 @@ void device_block_translation(struct device *dev) + if (info->domain) + cache_tag_unassign_domain(info->domain, dev, IOMMU_NO_PASID); + +- iommu_disable_pci_caps(info); + if (!dev_is_real_dma_subdevice(dev)) { + if (sm_supported(iommu)) + intel_pasid_tear_down_entry(iommu, dev, +@@ -3761,6 +3762,9 @@ static struct iommu_device *intel_iommu_probe_device(struct device *dev) + !pci_enable_pasid(pdev, info->pasid_supported & ~1)) + info->pasid_enabled = 1; + ++ if (sm_supported(iommu)) ++ iommu_enable_pci_ats(info); ++ + return &iommu->iommu; + free_table: + intel_pasid_free_table(dev); +@@ -3777,6 +3781,8 @@ static void intel_iommu_release_device(struct device *dev) + struct device_domain_info *info = dev_iommu_priv_get(dev); + struct intel_iommu *iommu = info->iommu; + ++ iommu_disable_pci_ats(info); ++ + if (info->pasid_enabled) { + pci_disable_pasid(to_pci_dev(dev)); + info->pasid_enabled = 0; +@@ -4415,13 +4421,10 @@ static int identity_domain_attach_dev(struct iommu_domain *domain, struct device + if (dev_is_real_dma_subdevice(dev)) + return 0; + +- if (sm_supported(iommu)) { ++ if (sm_supported(iommu)) + ret = intel_pasid_setup_pass_through(iommu, dev, IOMMU_NO_PASID); +- if (!ret) +- iommu_enable_pci_caps(info); +- } else { ++ else + ret = device_setup_pass_through(dev); +- } + + return ret; + } +-- +2.39.5 + diff --git a/queue-6.14/iommufd-disallow-allocating-nested-parent-domain-wit.patch b/queue-6.14/iommufd-disallow-allocating-nested-parent-domain-wit.patch new file mode 100644 index 0000000000..3d9b909708 --- /dev/null +++ b/queue-6.14/iommufd-disallow-allocating-nested-parent-domain-wit.patch @@ -0,0 +1,63 @@ +From bc57a57f7b1053209ddd682e4344ce097b892890 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 26 Feb 2025 02:40:12 -0800 +Subject: iommufd: Disallow allocating nested parent domain with fault ID + +From: Yi Liu + +[ Upstream commit 1062d81086156e42878d701b816d2f368b53a77c ] + +Allocating a domain with a fault ID indicates that the domain is faultable. +However, there is a gap for the nested parent domain to support PRI. Some +hardware lacks the capability to distinguish whether PRI occurs at stage 1 +or stage 2. This limitation may require software-based page table walking +to resolve. Since no in-tree IOMMU driver currently supports this +functionality, it is disallowed. For more details, refer to the related +discussion at [1]. + +[1] https://lore.kernel.org/linux-iommu/bd1655c6-8b2f-4cfa-adb1-badc00d01811@intel.com/ + +Link: https://patch.msgid.link/r/20250226104012.82079-1-yi.l.liu@intel.com +Suggested-by: Lu Baolu +Signed-off-by: Yi Liu +Reviewed-by: Kevin Tian +Reviewed-by: Lu Baolu +Signed-off-by: Jason Gunthorpe +Signed-off-by: Sasha Levin +--- + drivers/iommu/iommufd/hw_pagetable.c | 3 +++ + tools/testing/selftests/iommu/iommufd.c | 4 ++++ + 2 files changed, 7 insertions(+) + +diff --git a/drivers/iommu/iommufd/hw_pagetable.c b/drivers/iommu/iommufd/hw_pagetable.c +index 598be26a14e28..9b5b0b8522299 100644 +--- a/drivers/iommu/iommufd/hw_pagetable.c ++++ b/drivers/iommu/iommufd/hw_pagetable.c +@@ -126,6 +126,9 @@ iommufd_hwpt_paging_alloc(struct iommufd_ctx *ictx, struct iommufd_ioas *ioas, + if ((flags & IOMMU_HWPT_ALLOC_DIRTY_TRACKING) && + !device_iommu_capable(idev->dev, IOMMU_CAP_DIRTY_TRACKING)) + return ERR_PTR(-EOPNOTSUPP); ++ if ((flags & IOMMU_HWPT_FAULT_ID_VALID) && ++ (flags & IOMMU_HWPT_ALLOC_NEST_PARENT)) ++ return ERR_PTR(-EOPNOTSUPP); + + hwpt_paging = __iommufd_object_alloc( + ictx, hwpt_paging, IOMMUFD_OBJ_HWPT_PAGING, common.obj); +diff --git a/tools/testing/selftests/iommu/iommufd.c b/tools/testing/selftests/iommu/iommufd.c +index a1b2b657999dc..618c03bb6509b 100644 +--- a/tools/testing/selftests/iommu/iommufd.c ++++ b/tools/testing/selftests/iommu/iommufd.c +@@ -439,6 +439,10 @@ TEST_F(iommufd_ioas, alloc_hwpt_nested) + &test_hwpt_id); + test_err_hwpt_alloc(EINVAL, self->device_id, self->device_id, 0, + &test_hwpt_id); ++ test_err_hwpt_alloc(EOPNOTSUPP, self->device_id, self->ioas_id, ++ IOMMU_HWPT_ALLOC_NEST_PARENT | ++ IOMMU_HWPT_FAULT_ID_VALID, ++ &test_hwpt_id); + + test_cmd_hwpt_alloc(self->device_id, self->ioas_id, + IOMMU_HWPT_ALLOC_NEST_PARENT, +-- +2.39.5 + diff --git a/queue-6.14/iommufd-extend-iommu_get_hw_info-to-report-pasid-cap.patch b/queue-6.14/iommufd-extend-iommu_get_hw_info-to-report-pasid-cap.patch new file mode 100644 index 0000000000..17d350a43c --- /dev/null +++ b/queue-6.14/iommufd-extend-iommu_get_hw_info-to-report-pasid-cap.patch @@ -0,0 +1,197 @@ +From b0629628aed174d8232bdcbec57bf441f9cdaf81 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 21 Mar 2025 11:01:42 -0700 +Subject: iommufd: Extend IOMMU_GET_HW_INFO to report PASID capability + +From: Yi Liu + +[ Upstream commit 803f97298e7de9242eb677a1351dcafbbcc9117e ] + +PASID usage requires PASID support in both device and IOMMU. Since the +iommu drivers always enable the PASID capability for the device if it +is supported, this extends the IOMMU_GET_HW_INFO to report the PASID +capability to userspace. Also, enhances the selftest accordingly. + +Link: https://patch.msgid.link/r/20250321180143.8468-5-yi.l.liu@intel.com +Cc: Bjorn Helgaas +Reviewed-by: Kevin Tian +Reviewed-by: Jason Gunthorpe +Tested-by: Zhangfei Gao #aarch64 platform +Tested-by: Nicolin Chen +Signed-off-by: Yi Liu +Signed-off-by: Jason Gunthorpe +Signed-off-by: Sasha Levin +--- + drivers/iommu/iommufd/device.c | 34 +++++++++++++++++++++++++++++++++- + drivers/pci/ats.c | 33 +++++++++++++++++++++++++++++++++ + include/linux/pci-ats.h | 3 +++ + include/uapi/linux/iommufd.h | 14 +++++++++++++- + 4 files changed, 82 insertions(+), 2 deletions(-) + +diff --git a/drivers/iommu/iommufd/device.c b/drivers/iommu/iommufd/device.c +index 3c7800d4ab622..66a6b7466820d 100644 +--- a/drivers/iommu/iommufd/device.c ++++ b/drivers/iommu/iommufd/device.c +@@ -3,6 +3,7 @@ + */ + #include + #include ++#include + #include + #include + +@@ -1304,7 +1305,8 @@ int iommufd_get_hw_info(struct iommufd_ucmd *ucmd) + void *data; + int rc; + +- if (cmd->flags || cmd->__reserved) ++ if (cmd->flags || cmd->__reserved[0] || cmd->__reserved[1] || ++ cmd->__reserved[2]) + return -EOPNOTSUPP; + + idev = iommufd_get_device(ucmd, cmd->dev_id); +@@ -1361,6 +1363,36 @@ int iommufd_get_hw_info(struct iommufd_ucmd *ucmd) + if (device_iommu_capable(idev->dev, IOMMU_CAP_DIRTY_TRACKING)) + cmd->out_capabilities |= IOMMU_HW_CAP_DIRTY_TRACKING; + ++ cmd->out_max_pasid_log2 = 0; ++ /* ++ * Currently, all iommu drivers enable PASID in the probe_device() ++ * op if iommu and device supports it. So the max_pasids stored in ++ * dev->iommu indicates both PASID support and enable status. A ++ * non-zero dev->iommu->max_pasids means PASID is supported and ++ * enabled. The iommufd only reports PASID capability to userspace ++ * if it's enabled. ++ */ ++ if (idev->dev->iommu->max_pasids) { ++ cmd->out_max_pasid_log2 = ilog2(idev->dev->iommu->max_pasids); ++ ++ if (dev_is_pci(idev->dev)) { ++ struct pci_dev *pdev = to_pci_dev(idev->dev); ++ int ctrl; ++ ++ ctrl = pci_pasid_status(pdev); ++ ++ WARN_ON_ONCE(ctrl < 0 || ++ !(ctrl & PCI_PASID_CTRL_ENABLE)); ++ ++ if (ctrl & PCI_PASID_CTRL_EXEC) ++ cmd->out_capabilities |= ++ IOMMU_HW_CAP_PCI_PASID_EXEC; ++ if (ctrl & PCI_PASID_CTRL_PRIV) ++ cmd->out_capabilities |= ++ IOMMU_HW_CAP_PCI_PASID_PRIV; ++ } ++ } ++ + rc = iommufd_ucmd_respond(ucmd, sizeof(*cmd)); + out_free: + kfree(data); +diff --git a/drivers/pci/ats.c b/drivers/pci/ats.c +index c6b266c772c81..ec6c8dbdc5e9c 100644 +--- a/drivers/pci/ats.c ++++ b/drivers/pci/ats.c +@@ -538,4 +538,37 @@ int pci_max_pasids(struct pci_dev *pdev) + return (1 << FIELD_GET(PCI_PASID_CAP_WIDTH, supported)); + } + EXPORT_SYMBOL_GPL(pci_max_pasids); ++ ++/** ++ * pci_pasid_status - Check the PASID status ++ * @pdev: PCI device structure ++ * ++ * Returns a negative value when no PASID capability is present. ++ * Otherwise the value of the control register is returned. ++ * Status reported are: ++ * ++ * PCI_PASID_CTRL_ENABLE - PASID enabled ++ * PCI_PASID_CTRL_EXEC - Execute permission enabled ++ * PCI_PASID_CTRL_PRIV - Privileged mode enabled ++ */ ++int pci_pasid_status(struct pci_dev *pdev) ++{ ++ int pasid; ++ u16 ctrl; ++ ++ if (pdev->is_virtfn) ++ pdev = pci_physfn(pdev); ++ ++ pasid = pdev->pasid_cap; ++ if (!pasid) ++ return -EINVAL; ++ ++ pci_read_config_word(pdev, pasid + PCI_PASID_CTRL, &ctrl); ++ ++ ctrl &= PCI_PASID_CTRL_ENABLE | PCI_PASID_CTRL_EXEC | ++ PCI_PASID_CTRL_PRIV; ++ ++ return ctrl; ++} ++EXPORT_SYMBOL_GPL(pci_pasid_status); + #endif /* CONFIG_PCI_PASID */ +diff --git a/include/linux/pci-ats.h b/include/linux/pci-ats.h +index 0e8b74e63767a..75c6c86cf09dc 100644 +--- a/include/linux/pci-ats.h ++++ b/include/linux/pci-ats.h +@@ -42,6 +42,7 @@ int pci_enable_pasid(struct pci_dev *pdev, int features); + void pci_disable_pasid(struct pci_dev *pdev); + int pci_pasid_features(struct pci_dev *pdev); + int pci_max_pasids(struct pci_dev *pdev); ++int pci_pasid_status(struct pci_dev *pdev); + #else /* CONFIG_PCI_PASID */ + static inline int pci_enable_pasid(struct pci_dev *pdev, int features) + { return -EINVAL; } +@@ -50,6 +51,8 @@ static inline int pci_pasid_features(struct pci_dev *pdev) + { return -EINVAL; } + static inline int pci_max_pasids(struct pci_dev *pdev) + { return -EINVAL; } ++static inline int pci_pasid_status(struct pci_dev *pdev) ++{ return -EINVAL; } + #endif /* CONFIG_PCI_PASID */ + + #endif /* LINUX_PCI_ATS_H */ +diff --git a/include/uapi/linux/iommufd.h b/include/uapi/linux/iommufd.h +index 78747b24bd0fb..9495604e40b06 100644 +--- a/include/uapi/linux/iommufd.h ++++ b/include/uapi/linux/iommufd.h +@@ -608,9 +608,17 @@ enum iommu_hw_info_type { + * IOMMU_HWPT_GET_DIRTY_BITMAP + * IOMMU_HWPT_SET_DIRTY_TRACKING + * ++ * @IOMMU_HW_CAP_PCI_PASID_EXEC: Execute Permission Supported, user ignores it ++ * when the struct ++ * iommu_hw_info::out_max_pasid_log2 is zero. ++ * @IOMMU_HW_CAP_PCI_PASID_PRIV: Privileged Mode Supported, user ignores it ++ * when the struct ++ * iommu_hw_info::out_max_pasid_log2 is zero. + */ + enum iommufd_hw_capabilities { + IOMMU_HW_CAP_DIRTY_TRACKING = 1 << 0, ++ IOMMU_HW_CAP_PCI_PASID_EXEC = 1 << 1, ++ IOMMU_HW_CAP_PCI_PASID_PRIV = 1 << 2, + }; + + /** +@@ -626,6 +634,9 @@ enum iommufd_hw_capabilities { + * iommu_hw_info_type. + * @out_capabilities: Output the generic iommu capability info type as defined + * in the enum iommu_hw_capabilities. ++ * @out_max_pasid_log2: Output the width of PASIDs. 0 means no PASID support. ++ * PCI devices turn to out_capabilities to check if the ++ * specific capabilities is supported or not. + * @__reserved: Must be 0 + * + * Query an iommu type specific hardware information data from an iommu behind +@@ -649,7 +660,8 @@ struct iommu_hw_info { + __u32 data_len; + __aligned_u64 data_uptr; + __u32 out_data_type; +- __u32 __reserved; ++ __u8 out_max_pasid_log2; ++ __u8 __reserved[3]; + __aligned_u64 out_capabilities; + }; + #define IOMMU_GET_HW_INFO _IO(IOMMUFD_TYPE, IOMMUFD_CMD_GET_HW_INFO) +-- +2.39.5 + diff --git a/queue-6.14/ip-fib_rules-fetch-net-from-fib_rule-in-fib-46-_rule.patch b/queue-6.14/ip-fib_rules-fetch-net-from-fib_rule-in-fib-46-_rule.patch new file mode 100644 index 0000000000..b1a3d14a6f --- /dev/null +++ b/queue-6.14/ip-fib_rules-fetch-net-from-fib_rule-in-fib-46-_rule.patch @@ -0,0 +1,61 @@ +From d4af8df9b242204431211af615aebda8ab5450ec Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 7 Feb 2025 16:24:58 +0900 +Subject: ip: fib_rules: Fetch net from fib_rule in fib[46]_rule_configure(). + +From: Kuniyuki Iwashima + +[ Upstream commit 5a1ccffd30a08f5a2428cd5fbb3ab03e8eb6c66d ] + +The following patch will not set skb->sk from VRF path. + +Let's fetch net from fib_rule->fr_net instead of sock_net(skb->sk) +in fib[46]_rule_configure(). + +Signed-off-by: Kuniyuki Iwashima +Reviewed-by: Eric Dumazet +Reviewed-by: Ido Schimmel +Tested-by: Ido Schimmel +Link: https://patch.msgid.link/20250207072502.87775-5-kuniyu@amazon.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/ipv4/fib_rules.c | 4 ++-- + net/ipv6/fib6_rules.c | 4 ++-- + 2 files changed, 4 insertions(+), 4 deletions(-) + +diff --git a/net/ipv4/fib_rules.c b/net/ipv4/fib_rules.c +index 9517b8667e000..041c46787d941 100644 +--- a/net/ipv4/fib_rules.c ++++ b/net/ipv4/fib_rules.c +@@ -245,9 +245,9 @@ static int fib4_rule_configure(struct fib_rule *rule, struct sk_buff *skb, + struct nlattr **tb, + struct netlink_ext_ack *extack) + { +- struct net *net = sock_net(skb->sk); ++ struct fib4_rule *rule4 = (struct fib4_rule *)rule; ++ struct net *net = rule->fr_net; + int err = -EINVAL; +- struct fib4_rule *rule4 = (struct fib4_rule *) rule; + + if (tb[FRA_FLOWLABEL] || tb[FRA_FLOWLABEL_MASK]) { + NL_SET_ERR_MSG(extack, +diff --git a/net/ipv6/fib6_rules.c b/net/ipv6/fib6_rules.c +index 67d39114d9a63..40af8fd6efa70 100644 +--- a/net/ipv6/fib6_rules.c ++++ b/net/ipv6/fib6_rules.c +@@ -399,9 +399,9 @@ static int fib6_rule_configure(struct fib_rule *rule, struct sk_buff *skb, + struct nlattr **tb, + struct netlink_ext_ack *extack) + { ++ struct fib6_rule *rule6 = (struct fib6_rule *)rule; ++ struct net *net = rule->fr_net; + int err = -EINVAL; +- struct net *net = sock_net(skb->sk); +- struct fib6_rule *rule6 = (struct fib6_rule *) rule; + + if (!inet_validate_dscp(frh->tos)) { + NL_SET_ERR_MSG(extack, +-- +2.39.5 + diff --git a/queue-6.14/ipv4-fib-hold-rtnl_net_lock-in-ip_rt_ioctl.patch b/queue-6.14/ipv4-fib-hold-rtnl_net_lock-in-ip_rt_ioctl.patch new file mode 100644 index 0000000000..99a41f4888 --- /dev/null +++ b/queue-6.14/ipv4-fib-hold-rtnl_net_lock-in-ip_rt_ioctl.patch @@ -0,0 +1,73 @@ +From 3e98d8a7e4eee3cc9824525b9ee8490e42a80a47 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 27 Feb 2025 20:23:26 -0800 +Subject: ipv4: fib: Hold rtnl_net_lock() in ip_rt_ioctl(). + +From: Kuniyuki Iwashima + +[ Upstream commit c0ebe1cdc2cff0dee092a67f2c50377bb5fcf43d ] + +ioctl(SIOCADDRT/SIOCDELRT) calls ip_rt_ioctl() to add/remove a route in +the netns of the specified socket. + +Let's hold rtnl_net_lock() there. + +Note that rtentry_to_fib_config() can be called without rtnl_net_lock() +if we convert rtentry.dev handling to RCU later. + +Signed-off-by: Kuniyuki Iwashima +Reviewed-by: Eric Dumazet +Reviewed-by: David Ahern +Link: https://patch.msgid.link/20250228042328.96624-11-kuniyu@amazon.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/ipv4/fib_frontend.c | 10 ++++------ + 1 file changed, 4 insertions(+), 6 deletions(-) + +diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c +index 493c37ce232d3..8470e259d8fd8 100644 +--- a/net/ipv4/fib_frontend.c ++++ b/net/ipv4/fib_frontend.c +@@ -553,18 +553,16 @@ static int rtentry_to_fib_config(struct net *net, int cmd, struct rtentry *rt, + const struct in_ifaddr *ifa; + struct in_device *in_dev; + +- in_dev = __in_dev_get_rtnl(dev); ++ in_dev = __in_dev_get_rtnl_net(dev); + if (!in_dev) + return -ENODEV; + + *colon = ':'; + +- rcu_read_lock(); +- in_dev_for_each_ifa_rcu(ifa, in_dev) { ++ in_dev_for_each_ifa_rtnl_net(net, ifa, in_dev) { + if (strcmp(ifa->ifa_label, devname) == 0) + break; + } +- rcu_read_unlock(); + + if (!ifa) + return -ENODEV; +@@ -635,7 +633,7 @@ int ip_rt_ioctl(struct net *net, unsigned int cmd, struct rtentry *rt) + if (!ns_capable(net->user_ns, CAP_NET_ADMIN)) + return -EPERM; + +- rtnl_lock(); ++ rtnl_net_lock(net); + err = rtentry_to_fib_config(net, cmd, rt, &cfg); + if (err == 0) { + struct fib_table *tb; +@@ -659,7 +657,7 @@ int ip_rt_ioctl(struct net *net, unsigned int cmd, struct rtentry *rt) + /* allocated by rtentry_to_fib_config() */ + kfree(cfg.fc_mx); + } +- rtnl_unlock(); ++ rtnl_net_unlock(net); + return err; + } + return -EINVAL; +-- +2.39.5 + diff --git a/queue-6.14/ipv4-fib-move-fib_valid_key_len-to-rtm_to_fib_config.patch b/queue-6.14/ipv4-fib-move-fib_valid_key_len-to-rtm_to_fib_config.patch new file mode 100644 index 0000000000..8f2481223f --- /dev/null +++ b/queue-6.14/ipv4-fib-move-fib_valid_key_len-to-rtm_to_fib_config.patch @@ -0,0 +1,128 @@ +From 0a17ed66f8136f4fcac8e6150df4e3d68770b91d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 27 Feb 2025 20:23:27 -0800 +Subject: ipv4: fib: Move fib_valid_key_len() to rtm_to_fib_config(). + +From: Kuniyuki Iwashima + +[ Upstream commit 254ba7e6032d3fc738050d500b0c1d8197af90ca ] + +fib_valid_key_len() is called in the beginning of fib_table_insert() +or fib_table_delete() to check if the prefix length is valid. + +fib_table_insert() and fib_table_delete() are called from 3 paths + + - ip_rt_ioctl() + - inet_rtm_newroute() / inet_rtm_delroute() + - fib_magic() + +In the first ioctl() path, rtentry_to_fib_config() checks the prefix +length with bad_mask(). Also, fib_magic() always passes the correct +prefix: 32 or ifa->ifa_prefixlen, which is already validated. + +Let's move fib_valid_key_len() to the rtnetlink path, rtm_to_fib_config(). + +While at it, 2 direct returns in rtm_to_fib_config() are changed to +goto to match other places in the same function + +Signed-off-by: Kuniyuki Iwashima +Reviewed-by: Eric Dumazet +Reviewed-by: David Ahern +Link: https://patch.msgid.link/20250228042328.96624-12-kuniyu@amazon.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/ipv4/fib_frontend.c | 18 ++++++++++++++++-- + net/ipv4/fib_trie.c | 22 ---------------------- + 2 files changed, 16 insertions(+), 24 deletions(-) + +diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c +index 272e42d813230..493c37ce232d3 100644 +--- a/net/ipv4/fib_frontend.c ++++ b/net/ipv4/fib_frontend.c +@@ -837,19 +837,33 @@ static int rtm_to_fib_config(struct net *net, struct sk_buff *skb, + } + } + ++ if (cfg->fc_dst_len > 32) { ++ NL_SET_ERR_MSG(extack, "Invalid prefix length"); ++ err = -EINVAL; ++ goto errout; ++ } ++ ++ if (cfg->fc_dst_len < 32 && (ntohl(cfg->fc_dst) << cfg->fc_dst_len)) { ++ NL_SET_ERR_MSG(extack, "Invalid prefix for given prefix length"); ++ err = -EINVAL; ++ goto errout; ++ } ++ + if (cfg->fc_nh_id) { + if (cfg->fc_oif || cfg->fc_gw_family || + cfg->fc_encap || cfg->fc_mp) { + NL_SET_ERR_MSG(extack, + "Nexthop specification and nexthop id are mutually exclusive"); +- return -EINVAL; ++ err = -EINVAL; ++ goto errout; + } + } + + if (has_gw && has_via) { + NL_SET_ERR_MSG(extack, + "Nexthop configuration can not contain both GATEWAY and VIA"); +- return -EINVAL; ++ err = -EINVAL; ++ goto errout; + } + + if (!cfg->fc_table) +diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c +index d6411ac810961..59a6f0a9638f9 100644 +--- a/net/ipv4/fib_trie.c ++++ b/net/ipv4/fib_trie.c +@@ -1187,22 +1187,6 @@ static int fib_insert_alias(struct trie *t, struct key_vector *tp, + return 0; + } + +-static bool fib_valid_key_len(u32 key, u8 plen, struct netlink_ext_ack *extack) +-{ +- if (plen > KEYLENGTH) { +- NL_SET_ERR_MSG(extack, "Invalid prefix length"); +- return false; +- } +- +- if ((plen < KEYLENGTH) && (key << plen)) { +- NL_SET_ERR_MSG(extack, +- "Invalid prefix for given prefix length"); +- return false; +- } +- +- return true; +-} +- + static void fib_remove_alias(struct trie *t, struct key_vector *tp, + struct key_vector *l, struct fib_alias *old); + +@@ -1223,9 +1207,6 @@ int fib_table_insert(struct net *net, struct fib_table *tb, + + key = ntohl(cfg->fc_dst); + +- if (!fib_valid_key_len(key, plen, extack)) +- return -EINVAL; +- + pr_debug("Insert table=%u %08x/%d\n", tb->tb_id, key, plen); + + fi = fib_create_info(cfg, extack); +@@ -1717,9 +1698,6 @@ int fib_table_delete(struct net *net, struct fib_table *tb, + + key = ntohl(cfg->fc_dst); + +- if (!fib_valid_key_len(key, plen, extack)) +- return -EINVAL; +- + l = fib_find_node(t, &tp, key); + if (!l) + return -ESRCH; +-- +2.39.5 + diff --git a/queue-6.14/ipv4-ip_gre-fix-set-but-not-used-warning-in-ipgre_er.patch b/queue-6.14/ipv4-ip_gre-fix-set-but-not-used-warning-in-ipgre_er.patch new file mode 100644 index 0000000000..098769dd86 --- /dev/null +++ b/queue-6.14/ipv4-ip_gre-fix-set-but-not-used-warning-in-ipgre_er.patch @@ -0,0 +1,78 @@ +From 7baabcffdfa33f60bf704b06e3b91bf3accf1607 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 4 Feb 2025 22:36:54 +0100 +Subject: ipv4: ip_gre: Fix set but not used warning in ipgre_err() if + IPv4-only +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Geert Uytterhoeven + +[ Upstream commit 50f37fc2a39c4a8cc4813629b4cf239b71c6097d ] + +if CONFIG_NET_IPGRE is enabled, but CONFIG_IPV6 is disabled: + + net/ipv4/ip_gre.c: In function ‘ipgre_err’: + net/ipv4/ip_gre.c:144:22: error: variable ‘data_len’ set but not used [-Werror=unused-but-set-variable] + 144 | unsigned int data_len = 0; + | ^~~~~~~~ + +Fix this by moving all data_len processing inside the IPV6-only section +that uses its result. + +Reported-by: kernel test robot +Closes: https://lore.kernel.org/oe-kbuild-all/202501121007.2GofXmh5-lkp@intel.com/ +Signed-off-by: Geert Uytterhoeven +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/d09113cfe2bfaca02f3dddf832fb5f48dd20958b.1738704881.git.geert@linux-m68k.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/ipv4/ip_gre.c | 16 ++++++++++------ + 1 file changed, 10 insertions(+), 6 deletions(-) + +diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c +index ed1b6b44faf80..c9f11a046c263 100644 +--- a/net/ipv4/ip_gre.c ++++ b/net/ipv4/ip_gre.c +@@ -141,7 +141,6 @@ static int ipgre_err(struct sk_buff *skb, u32 info, + const struct iphdr *iph; + const int type = icmp_hdr(skb)->type; + const int code = icmp_hdr(skb)->code; +- unsigned int data_len = 0; + struct ip_tunnel *t; + + if (tpi->proto == htons(ETH_P_TEB)) +@@ -182,7 +181,6 @@ static int ipgre_err(struct sk_buff *skb, u32 info, + case ICMP_TIME_EXCEEDED: + if (code != ICMP_EXC_TTL) + return 0; +- data_len = icmp_hdr(skb)->un.reserved[1] * 4; /* RFC 4884 4.1 */ + break; + + case ICMP_REDIRECT: +@@ -190,10 +188,16 @@ static int ipgre_err(struct sk_buff *skb, u32 info, + } + + #if IS_ENABLED(CONFIG_IPV6) +- if (tpi->proto == htons(ETH_P_IPV6) && +- !ip6_err_gen_icmpv6_unreach(skb, iph->ihl * 4 + tpi->hdr_len, +- type, data_len)) +- return 0; ++ if (tpi->proto == htons(ETH_P_IPV6)) { ++ unsigned int data_len = 0; ++ ++ if (type == ICMP_TIME_EXCEEDED) ++ data_len = icmp_hdr(skb)->un.reserved[1] * 4; /* RFC 4884 4.1 */ ++ ++ if (!ip6_err_gen_icmpv6_unreach(skb, iph->ihl * 4 + tpi->hdr_len, ++ type, data_len)) ++ return 0; ++ } + #endif + + if (t->parms.iph.daddr == 0 || +-- +2.39.5 + diff --git a/queue-6.14/ipv6-remove-leftover-ip6-cookie-initializer.patch b/queue-6.14/ipv6-remove-leftover-ip6-cookie-initializer.patch new file mode 100644 index 0000000000..0934f5becc --- /dev/null +++ b/queue-6.14/ipv6-remove-leftover-ip6-cookie-initializer.patch @@ -0,0 +1,47 @@ +From 67bbdde4eb0ff6badabf3d992f97565315d89d6e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Mar 2025 22:34:08 -0500 +Subject: ipv6: remove leftover ip6 cookie initializer + +From: Willem de Bruijn + +[ Upstream commit 54580ccdd8a9c6821fd6f72171d435480867e4c3 ] + +As of the blamed commit ipc6.dontfrag is always initialized at the +start of udpv6_sendmsg, by ipcm6_init_sk, to either 0 or 1. + +Later checks against -1 are no longer needed and the branches are now +dead code. + +The blamed commit had removed those branches. But I had overlooked +this one case. + +UDP has both a lockless fast path and a slower path for corked +requests. This branch remained in the fast path. + +Fixes: 096208592b09 ("ipv6: replace ipcm6_init calls with ipcm6_init_sk") +Signed-off-by: Willem de Bruijn +Reviewed-by: Eric Dumazet +Link: https://patch.msgid.link/20250307033620.411611-2-willemdebruijn.kernel@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/ipv6/ip6_output.c | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c +index eb636bec89796..581bc62890818 100644 +--- a/net/ipv6/ip6_output.c ++++ b/net/ipv6/ip6_output.c +@@ -2055,8 +2055,6 @@ struct sk_buff *ip6_make_skb(struct sock *sk, + ip6_cork_release(cork, &v6_cork); + return ERR_PTR(err); + } +- if (ipc6->dontfrag < 0) +- ipc6->dontfrag = inet6_test_bit(DONTFRAG, sk); + + err = __ip6_append_data(sk, &queue, cork, &v6_cork, + ¤t->task_frag, getfrag, from, +-- +2.39.5 + diff --git a/queue-6.14/ipv6-save-dontfrag-in-cork.patch b/queue-6.14/ipv6-save-dontfrag-in-cork.patch new file mode 100644 index 0000000000..313e05568d --- /dev/null +++ b/queue-6.14/ipv6-save-dontfrag-in-cork.patch @@ -0,0 +1,103 @@ +From 17a855ee87d2b7a42081f85bcffc1556cb46ad7c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Mar 2025 22:34:09 -0500 +Subject: ipv6: save dontfrag in cork + +From: Willem de Bruijn + +[ Upstream commit a18dfa9925b9ef6107ea3aa5814ca3c704d34a8a ] + +When spanning datagram construction over multiple send calls using +MSG_MORE, per datagram settings are configured on the first send. + +That is when ip(6)_setup_cork stores these settings for subsequent use +in __ip(6)_append_data and others. + +The only flag that escaped this was dontfrag. As a result, a datagram +could be constructed with df=0 on the first sendmsg, but df=1 on a +next. Which is what cmsg_ip.sh does in an upcoming MSG_MORE test in +the "diff" scenario. + +Changing datagram conditions in the middle of constructing an skb +makes this already complex code path even more convoluted. It is here +unintentional. Bring this flag in line with expected sockopt/cmsg +behavior. + +And stop passing ipc6 to __ip6_append_data, to avoid such issues +in the future. This is already the case for __ip_append_data. + +inet6_cork had a 6 byte hole, so the 1B flag has no impact. + +Signed-off-by: Willem de Bruijn +Reviewed-by: Eric Dumazet +Link: https://patch.msgid.link/20250307033620.411611-3-willemdebruijn.kernel@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + include/linux/ipv6.h | 1 + + net/ipv6/ip6_output.c | 9 +++++---- + 2 files changed, 6 insertions(+), 4 deletions(-) + +diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h +index a6e2aadbb91bd..5aeeed22f35bf 100644 +--- a/include/linux/ipv6.h ++++ b/include/linux/ipv6.h +@@ -207,6 +207,7 @@ struct inet6_cork { + struct ipv6_txoptions *opt; + u8 hop_limit; + u8 tclass; ++ u8 dontfrag:1; + }; + + /* struct ipv6_pinfo - ipv6 private area */ +diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c +index d577bf2f30538..eb636bec89796 100644 +--- a/net/ipv6/ip6_output.c ++++ b/net/ipv6/ip6_output.c +@@ -1386,6 +1386,7 @@ static int ip6_setup_cork(struct sock *sk, struct inet_cork_full *cork, + } + v6_cork->hop_limit = ipc6->hlimit; + v6_cork->tclass = ipc6->tclass; ++ v6_cork->dontfrag = ipc6->dontfrag; + if (rt->dst.flags & DST_XFRM_TUNNEL) + mtu = READ_ONCE(np->pmtudisc) >= IPV6_PMTUDISC_PROBE ? + READ_ONCE(rt->dst.dev->mtu) : dst_mtu(&rt->dst); +@@ -1421,7 +1422,7 @@ static int __ip6_append_data(struct sock *sk, + int getfrag(void *from, char *to, int offset, + int len, int odd, struct sk_buff *skb), + void *from, size_t length, int transhdrlen, +- unsigned int flags, struct ipcm6_cookie *ipc6) ++ unsigned int flags) + { + struct sk_buff *skb, *skb_prev = NULL; + struct inet_cork *cork = &cork_full->base; +@@ -1475,7 +1476,7 @@ static int __ip6_append_data(struct sock *sk, + if (headersize + transhdrlen > mtu) + goto emsgsize; + +- if (cork->length + length > mtu - headersize && ipc6->dontfrag && ++ if (cork->length + length > mtu - headersize && v6_cork->dontfrag && + (sk->sk_protocol == IPPROTO_UDP || + sk->sk_protocol == IPPROTO_ICMPV6 || + sk->sk_protocol == IPPROTO_RAW)) { +@@ -1855,7 +1856,7 @@ int ip6_append_data(struct sock *sk, + + return __ip6_append_data(sk, &sk->sk_write_queue, &inet->cork, + &np->cork, sk_page_frag(sk), getfrag, +- from, length, transhdrlen, flags, ipc6); ++ from, length, transhdrlen, flags); + } + EXPORT_SYMBOL_GPL(ip6_append_data); + +@@ -2060,7 +2061,7 @@ struct sk_buff *ip6_make_skb(struct sock *sk, + err = __ip6_append_data(sk, &queue, cork, &v6_cork, + ¤t->task_frag, getfrag, from, + length + exthdrlen, transhdrlen + exthdrlen, +- flags, ipc6); ++ flags); + if (err) { + __ip6_flush_pending_frames(sk, &queue, cork, &v6_cork); + return ERR_PTR(err); +-- +2.39.5 + diff --git a/queue-6.14/irqchip-riscv-aplic-add-support-for-hart-indexes.patch b/queue-6.14/irqchip-riscv-aplic-add-support-for-hart-indexes.patch new file mode 100644 index 0000000000..e0ab0969bb --- /dev/null +++ b/queue-6.14/irqchip-riscv-aplic-add-support-for-hart-indexes.patch @@ -0,0 +1,97 @@ +From f34f6310a5ebc7a8b67a709cccb8e8005fd0781d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 29 Jan 2025 11:16:37 +0200 +Subject: irqchip/riscv-aplic: Add support for hart indexes +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Vladimir Kondratiev + +[ Upstream commit b93afe8a3ac53ae52296d65acfaa9c5f582a48cc ] + +RISC-V APLIC specification defines "hart index" in: + + https://github.com/riscv/riscv-aia + +Within a given interrupt domain, each of the domain’s harts has a unique +index number in the range 0 to 2^14 − 1 (= 16,383). The index number a +domain associates with a hart may or may not have any relationship to the +unique hart identifier (“hart ID”) that the RISC-V Privileged Architecture +assigns to the hart. Two different interrupt domains may employ entirely +different index numbers for the same set of harts. + +Further, this document says in "4.5 Memory-mapped control region for an +interrupt domain": + +The array of IDC structures may include some for potential hart index +numbers that are not actual hart index numbers in the domain. For example, +the first IDC structure is always for hart index 0, but 0 is not +necessarily a valid index number for any hart in the domain. + +Support arbitrary hart indices specified in an optional APLIC property +"riscv,hart-indexes" which is specified as an array of u32 elements, one +per interrupt target. If this property is not specified, fallback to use +logical hart indices within the domain. + +Signed-off-by: Vladimir Kondratiev +Signed-off-by: Thomas Gleixner +Reviewed-by: Anup Patel +Link: https://lore.kernel.org/all/20250129091637.1667279-3-vladimir.kondratiev@mobileye.com +Signed-off-by: Sasha Levin +--- + drivers/irqchip/irq-riscv-aplic-direct.c | 24 +++++++++++++++++++++--- + 1 file changed, 21 insertions(+), 3 deletions(-) + +diff --git a/drivers/irqchip/irq-riscv-aplic-direct.c b/drivers/irqchip/irq-riscv-aplic-direct.c +index 7cd6b646774b9..205ad61d15e49 100644 +--- a/drivers/irqchip/irq-riscv-aplic-direct.c ++++ b/drivers/irqchip/irq-riscv-aplic-direct.c +@@ -31,7 +31,7 @@ struct aplic_direct { + }; + + struct aplic_idc { +- unsigned int hart_index; ++ u32 hart_index; + void __iomem *regs; + struct aplic_direct *direct; + }; +@@ -219,6 +219,20 @@ static int aplic_direct_parse_parent_hwirq(struct device *dev, u32 index, + return 0; + } + ++static int aplic_direct_get_hart_index(struct device *dev, u32 logical_index, ++ u32 *hart_index) ++{ ++ const char *prop_hart_index = "riscv,hart-indexes"; ++ struct device_node *np = to_of_node(dev->fwnode); ++ ++ if (!np || !of_property_present(np, prop_hart_index)) { ++ *hart_index = logical_index; ++ return 0; ++ } ++ ++ return of_property_read_u32_index(np, prop_hart_index, logical_index, hart_index); ++} ++ + int aplic_direct_setup(struct device *dev, void __iomem *regs) + { + int i, j, rc, cpu, current_cpu, setup_count = 0; +@@ -265,8 +279,12 @@ int aplic_direct_setup(struct device *dev, void __iomem *regs) + cpumask_set_cpu(cpu, &direct->lmask); + + idc = per_cpu_ptr(&aplic_idcs, cpu); +- idc->hart_index = i; +- idc->regs = priv->regs + APLIC_IDC_BASE + i * APLIC_IDC_SIZE; ++ rc = aplic_direct_get_hart_index(dev, i, &idc->hart_index); ++ if (rc) { ++ dev_warn(dev, "hart index not found for IDC%d\n", i); ++ continue; ++ } ++ idc->regs = priv->regs + APLIC_IDC_BASE + idc->hart_index * APLIC_IDC_SIZE; + idc->direct = direct; + + aplic_idc_set_delivery(idc, true); +-- +2.39.5 + diff --git a/queue-6.14/irqchip-riscv-imsic-separate-next-and-previous-point.patch b/queue-6.14/irqchip-riscv-imsic-separate-next-and-previous-point.patch new file mode 100644 index 0000000000..e061df6eb9 --- /dev/null +++ b/queue-6.14/irqchip-riscv-imsic-separate-next-and-previous-point.patch @@ -0,0 +1,274 @@ +From 0fb6dd7ef17a4990048cd2a5460a99d6eeaf521d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Feb 2025 14:26:53 +0530 +Subject: irqchip/riscv-imsic: Separate next and previous pointers in IMSIC + vector + +From: Anup Patel + +[ Upstream commit 0f67911e821c67ecfccc365a2103ce276a9a56fe ] + +Currently, there is only one "move" pointer in struct imsic_vector so +during vector movement the old vector points to the new vector and new +vector points to itself. + +To support forced cleanup of the old vector, add separate "move_next" and +"move_prev" pointers to struct imsic_vector, where during vector movement +the "move_next" pointer of the old vector points to the new vector and the +"move_prev" pointer of the new vector points to the old vector. + +Both "move_next" and "move_prev" pointers are cleared separately by +__imsic_local_sync() with a restriction that "move_prev" on the new +CPU is cleared only after the old CPU has cleared "move_next". + +Signed-off-by: Anup Patel +Signed-off-by: Thomas Gleixner +Link: https://lore.kernel.org/all/20250217085657.789309-8-apatel@ventanamicro.com +Signed-off-by: Sasha Levin +--- + drivers/irqchip/irq-riscv-imsic-early.c | 8 ++- + drivers/irqchip/irq-riscv-imsic-state.c | 96 +++++++++++++++++-------- + drivers/irqchip/irq-riscv-imsic-state.h | 7 +- + 3 files changed, 78 insertions(+), 33 deletions(-) + +diff --git a/drivers/irqchip/irq-riscv-imsic-early.c b/drivers/irqchip/irq-riscv-imsic-early.c +index 275df50057057..553650932c75f 100644 +--- a/drivers/irqchip/irq-riscv-imsic-early.c ++++ b/drivers/irqchip/irq-riscv-imsic-early.c +@@ -77,6 +77,12 @@ static void imsic_handle_irq(struct irq_desc *desc) + struct imsic_vector *vec; + unsigned long local_id; + ++ /* ++ * Process pending local synchronization instead of waiting ++ * for per-CPU local timer to expire. ++ */ ++ imsic_local_sync_all(false); ++ + chained_irq_enter(chip, desc); + + while ((local_id = csr_swap(CSR_TOPEI, 0))) { +@@ -120,7 +126,7 @@ static int imsic_starting_cpu(unsigned int cpu) + * Interrupts identities might have been enabled/disabled while + * this CPU was not running so sync-up local enable/disable state. + */ +- imsic_local_sync_all(); ++ imsic_local_sync_all(true); + + /* Enable local interrupt delivery */ + imsic_local_delivery(true); +diff --git a/drivers/irqchip/irq-riscv-imsic-state.c b/drivers/irqchip/irq-riscv-imsic-state.c +index b97e6cd89ed74..1aeba76d72795 100644 +--- a/drivers/irqchip/irq-riscv-imsic-state.c ++++ b/drivers/irqchip/irq-riscv-imsic-state.c +@@ -124,10 +124,11 @@ void __imsic_eix_update(unsigned long base_id, unsigned long num_id, bool pend, + } + } + +-static void __imsic_local_sync(struct imsic_local_priv *lpriv) ++static bool __imsic_local_sync(struct imsic_local_priv *lpriv) + { + struct imsic_local_config *mlocal; + struct imsic_vector *vec, *mvec; ++ bool ret = true; + int i; + + lockdep_assert_held(&lpriv->lock); +@@ -143,35 +144,75 @@ static void __imsic_local_sync(struct imsic_local_priv *lpriv) + __imsic_id_clear_enable(i); + + /* +- * If the ID was being moved to a new ID on some other CPU +- * then we can get a MSI during the movement so check the +- * ID pending bit and re-trigger the new ID on other CPU +- * using MMIO write. ++ * Clear the previous vector pointer of the new vector only ++ * after the movement is complete on the old CPU. + */ +- mvec = READ_ONCE(vec->move); +- WRITE_ONCE(vec->move, NULL); +- if (mvec && mvec != vec) { ++ mvec = READ_ONCE(vec->move_prev); ++ if (mvec) { ++ /* ++ * If the old vector has not been updated then ++ * try again in the next sync-up call. ++ */ ++ if (READ_ONCE(mvec->move_next)) { ++ ret = false; ++ continue; ++ } ++ ++ WRITE_ONCE(vec->move_prev, NULL); ++ } ++ ++ /* ++ * If a vector was being moved to a new vector on some other ++ * CPU then we can get a MSI during the movement so check the ++ * ID pending bit and re-trigger the new ID on other CPU using ++ * MMIO write. ++ */ ++ mvec = READ_ONCE(vec->move_next); ++ if (mvec) { + if (__imsic_id_read_clear_pending(i)) { + mlocal = per_cpu_ptr(imsic->global.local, mvec->cpu); + writel_relaxed(mvec->local_id, mlocal->msi_va); + } + ++ WRITE_ONCE(vec->move_next, NULL); + imsic_vector_free(&lpriv->vectors[i]); + } + + skip: + bitmap_clear(lpriv->dirty_bitmap, i, 1); + } ++ ++ return ret; + } + +-void imsic_local_sync_all(void) ++#ifdef CONFIG_SMP ++static void __imsic_local_timer_start(struct imsic_local_priv *lpriv) ++{ ++ lockdep_assert_held(&lpriv->lock); ++ ++ if (!timer_pending(&lpriv->timer)) { ++ lpriv->timer.expires = jiffies + 1; ++ add_timer_on(&lpriv->timer, smp_processor_id()); ++ } ++} ++#else ++static inline void __imsic_local_timer_start(struct imsic_local_priv *lpriv) ++{ ++} ++#endif ++ ++void imsic_local_sync_all(bool force_all) + { + struct imsic_local_priv *lpriv = this_cpu_ptr(imsic->lpriv); + unsigned long flags; + + raw_spin_lock_irqsave(&lpriv->lock, flags); +- bitmap_fill(lpriv->dirty_bitmap, imsic->global.nr_ids + 1); +- __imsic_local_sync(lpriv); ++ ++ if (force_all) ++ bitmap_fill(lpriv->dirty_bitmap, imsic->global.nr_ids + 1); ++ if (!__imsic_local_sync(lpriv)) ++ __imsic_local_timer_start(lpriv); ++ + raw_spin_unlock_irqrestore(&lpriv->lock, flags); + } + +@@ -190,12 +231,7 @@ void imsic_local_delivery(bool enable) + #ifdef CONFIG_SMP + static void imsic_local_timer_callback(struct timer_list *timer) + { +- struct imsic_local_priv *lpriv = this_cpu_ptr(imsic->lpriv); +- unsigned long flags; +- +- raw_spin_lock_irqsave(&lpriv->lock, flags); +- __imsic_local_sync(lpriv); +- raw_spin_unlock_irqrestore(&lpriv->lock, flags); ++ imsic_local_sync_all(false); + } + + static void __imsic_remote_sync(struct imsic_local_priv *lpriv, unsigned int cpu) +@@ -216,14 +252,11 @@ static void __imsic_remote_sync(struct imsic_local_priv *lpriv, unsigned int cpu + */ + if (cpu_online(cpu)) { + if (cpu == smp_processor_id()) { +- __imsic_local_sync(lpriv); +- return; ++ if (__imsic_local_sync(lpriv)) ++ return; + } + +- if (!timer_pending(&lpriv->timer)) { +- lpriv->timer.expires = jiffies + 1; +- add_timer_on(&lpriv->timer, cpu); +- } ++ __imsic_local_timer_start(lpriv); + } + } + #else +@@ -278,8 +311,9 @@ void imsic_vector_unmask(struct imsic_vector *vec) + raw_spin_unlock(&lpriv->lock); + } + +-static bool imsic_vector_move_update(struct imsic_local_priv *lpriv, struct imsic_vector *vec, +- bool new_enable, struct imsic_vector *new_move) ++static bool imsic_vector_move_update(struct imsic_local_priv *lpriv, ++ struct imsic_vector *vec, bool is_old_vec, ++ bool new_enable, struct imsic_vector *move_vec) + { + unsigned long flags; + bool enabled; +@@ -289,7 +323,10 @@ static bool imsic_vector_move_update(struct imsic_local_priv *lpriv, struct imsi + /* Update enable and move details */ + enabled = READ_ONCE(vec->enable); + WRITE_ONCE(vec->enable, new_enable); +- WRITE_ONCE(vec->move, new_move); ++ if (is_old_vec) ++ WRITE_ONCE(vec->move_next, move_vec); ++ else ++ WRITE_ONCE(vec->move_prev, move_vec); + + /* Mark the vector as dirty and synchronize */ + bitmap_set(lpriv->dirty_bitmap, vec->local_id, 1); +@@ -322,8 +359,8 @@ void imsic_vector_move(struct imsic_vector *old_vec, struct imsic_vector *new_ve + * interrupt on the old vector while device was being moved + * to the new vector. + */ +- enabled = imsic_vector_move_update(old_lpriv, old_vec, false, new_vec); +- imsic_vector_move_update(new_lpriv, new_vec, enabled, new_vec); ++ enabled = imsic_vector_move_update(old_lpriv, old_vec, true, false, new_vec); ++ imsic_vector_move_update(new_lpriv, new_vec, false, enabled, old_vec); + } + + #ifdef CONFIG_GENERIC_IRQ_DEBUGFS +@@ -386,7 +423,8 @@ struct imsic_vector *imsic_vector_alloc(unsigned int hwirq, const struct cpumask + vec = &lpriv->vectors[local_id]; + vec->hwirq = hwirq; + vec->enable = false; +- vec->move = NULL; ++ vec->move_next = NULL; ++ vec->move_prev = NULL; + + return vec; + } +diff --git a/drivers/irqchip/irq-riscv-imsic-state.h b/drivers/irqchip/irq-riscv-imsic-state.h +index 391e442808275..f02842b84ed58 100644 +--- a/drivers/irqchip/irq-riscv-imsic-state.h ++++ b/drivers/irqchip/irq-riscv-imsic-state.h +@@ -23,7 +23,8 @@ struct imsic_vector { + unsigned int hwirq; + /* Details accessed using local lock held */ + bool enable; +- struct imsic_vector *move; ++ struct imsic_vector *move_next; ++ struct imsic_vector *move_prev; + }; + + struct imsic_local_priv { +@@ -74,7 +75,7 @@ static inline void __imsic_id_clear_enable(unsigned long id) + __imsic_eix_update(id, 1, false, false); + } + +-void imsic_local_sync_all(void); ++void imsic_local_sync_all(bool force_all); + void imsic_local_delivery(bool enable); + + void imsic_vector_mask(struct imsic_vector *vec); +@@ -87,7 +88,7 @@ static inline bool imsic_vector_isenabled(struct imsic_vector *vec) + + static inline struct imsic_vector *imsic_vector_get_move(struct imsic_vector *vec) + { +- return READ_ONCE(vec->move); ++ return READ_ONCE(vec->move_prev); + } + + void imsic_vector_move(struct imsic_vector *old_vec, struct imsic_vector *new_vec); +-- +2.39.5 + diff --git a/queue-6.14/irqchip-riscv-imsic-set-irq_set_affinity-for-imsic-b.patch b/queue-6.14/irqchip-riscv-imsic-set-irq_set_affinity-for-imsic-b.patch new file mode 100644 index 0000000000..2bc675aedf --- /dev/null +++ b/queue-6.14/irqchip-riscv-imsic-set-irq_set_affinity-for-imsic-b.patch @@ -0,0 +1,85 @@ +From 57249338fd4bd79b07bbe7d17ae4e6ba3a0ea60d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Feb 2025 14:26:47 +0530 +Subject: irqchip/riscv-imsic: Set irq_set_affinity() for IMSIC base + +From: Andrew Jones + +[ Upstream commit 999f458c1771354371ba367dd84f55f9a62a4233 ] + +The IMSIC driver assigns the IMSIC domain specific imsic_irq_set_affinity() +callback to the per device leaf MSI domain. That's a layering violation as +it is called with the leaf domain data and not with the IMSIC domain +data. This prevents moving the IMSIC driver to the common MSI library which +uses the generic msi_domain_set_affinity() callback for device MSI domains. + +Instead of using imsic_irq_set_affinity() for leaf MSI domains, use +imsic_irq_set_affinity() for the non-leaf IMSIC base domain and use +irq_chip_set_affinity_parent() for leaf MSI domains. + +[ tglx: Massaged change log ] + +Signed-off-by: Andrew Jones +Signed-off-by: Anup Patel +Signed-off-by: Thomas Gleixner +Link: https://lore.kernel.org/all/20250217085657.789309-2-apatel@ventanamicro.com +Signed-off-by: Sasha Levin +--- + drivers/irqchip/irq-riscv-imsic-platform.c | 16 +++++++++------- + 1 file changed, 9 insertions(+), 7 deletions(-) + +diff --git a/drivers/irqchip/irq-riscv-imsic-platform.c b/drivers/irqchip/irq-riscv-imsic-platform.c +index c708780e8760f..5d7c30ad8855b 100644 +--- a/drivers/irqchip/irq-riscv-imsic-platform.c ++++ b/drivers/irqchip/irq-riscv-imsic-platform.c +@@ -96,9 +96,8 @@ static int imsic_irq_set_affinity(struct irq_data *d, const struct cpumask *mask + bool force) + { + struct imsic_vector *old_vec, *new_vec; +- struct irq_data *pd = d->parent_data; + +- old_vec = irq_data_get_irq_chip_data(pd); ++ old_vec = irq_data_get_irq_chip_data(d); + if (WARN_ON(!old_vec)) + return -ENOENT; + +@@ -116,13 +115,13 @@ static int imsic_irq_set_affinity(struct irq_data *d, const struct cpumask *mask + return -ENOSPC; + + /* Point device to the new vector */ +- imsic_msi_update_msg(d, new_vec); ++ imsic_msi_update_msg(irq_get_irq_data(d->irq), new_vec); + + /* Update irq descriptors with the new vector */ +- pd->chip_data = new_vec; ++ d->chip_data = new_vec; + +- /* Update effective affinity of parent irq data */ +- irq_data_update_effective_affinity(pd, cpumask_of(new_vec->cpu)); ++ /* Update effective affinity */ ++ irq_data_update_effective_affinity(d, cpumask_of(new_vec->cpu)); + + /* Move state of the old vector to the new vector */ + imsic_vector_move(old_vec, new_vec); +@@ -135,6 +134,9 @@ static struct irq_chip imsic_irq_base_chip = { + .name = "IMSIC", + .irq_mask = imsic_irq_mask, + .irq_unmask = imsic_irq_unmask, ++#ifdef CONFIG_SMP ++ .irq_set_affinity = imsic_irq_set_affinity, ++#endif + .irq_retrigger = imsic_irq_retrigger, + .irq_compose_msi_msg = imsic_irq_compose_msg, + .flags = IRQCHIP_SKIP_SET_WAKE | +@@ -245,7 +247,7 @@ static bool imsic_init_dev_msi_info(struct device *dev, + if (WARN_ON_ONCE(domain != real_parent)) + return false; + #ifdef CONFIG_SMP +- info->chip->irq_set_affinity = imsic_irq_set_affinity; ++ info->chip->irq_set_affinity = irq_chip_set_affinity_parent; + #endif + break; + default: +-- +2.39.5 + diff --git a/queue-6.14/ixgbe-add-support-for-thermal-sensor-event-reception.patch b/queue-6.14/ixgbe-add-support-for-thermal-sensor-event-reception.patch new file mode 100644 index 0000000000..3db929554f --- /dev/null +++ b/queue-6.14/ixgbe-add-support-for-thermal-sensor-event-reception.patch @@ -0,0 +1,69 @@ +From 1d2d5c81d591948eecc99a2e1ae0320b7324f5e8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 10 Mar 2025 10:44:59 -0700 +Subject: ixgbe: add support for thermal sensor event reception + +From: Jedrzej Jagielski + +[ Upstream commit affead2d904e8f82c0b89e23b3835242eb8c3e1a ] + +E610 NICs unlike the previous devices utilising ixgbe driver +are notified in the case of overheating by the FW ACI event. + +In event of overheat when threshold is exceeded, FW suspends all +traffic and sends overtemp event to the driver. Then driver +logs appropriate message and disables the adapter instance. +The card remains in that state until the platform is rebooted. + +This approach is a solution to the fact current version of the +E610 FW doesn't support reading thermal sensor data by the +SW. So give to user at least any info that overtemp event +has occurred, without interface disappearing from the OS +without any note. + +Reviewed-by: Przemek Kitszel +Reviewed-by: Mateusz Polchlopek +Reviewed-by: Simon Horman +Signed-off-by: Jedrzej Jagielski +Tested-by: Jeremiah Lokan (A Contingent worker at Intel) +Signed-off-by: Tony Nguyen +Link: https://patch.msgid.link/20250310174502.3708121-7-anthony.l.nguyen@intel.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 4 ++++ + drivers/net/ethernet/intel/ixgbe/ixgbe_type_e610.h | 3 +++ + 2 files changed, 7 insertions(+) + +diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +index 467f81239e12f..481f917f7ed28 100644 +--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c ++++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +@@ -3185,6 +3185,10 @@ static void ixgbe_handle_fw_event(struct ixgbe_adapter *adapter) + case ixgbe_aci_opc_get_link_status: + ixgbe_handle_link_status_event(adapter, &event); + break; ++ case ixgbe_aci_opc_temp_tca_event: ++ e_crit(drv, "%s\n", ixgbe_overheat_msg); ++ ixgbe_down(adapter); ++ break; + default: + e_warn(hw, "unknown FW async event captured\n"); + break; +diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_type_e610.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_type_e610.h +index 8d06ade3c7cd9..617e07878e4f7 100644 +--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_type_e610.h ++++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_type_e610.h +@@ -171,6 +171,9 @@ enum ixgbe_aci_opc { + ixgbe_aci_opc_done_alt_write = 0x0904, + ixgbe_aci_opc_clear_port_alt_write = 0x0906, + ++ /* TCA Events */ ++ ixgbe_aci_opc_temp_tca_event = 0x0C94, ++ + /* debug commands */ + ixgbe_aci_opc_debug_dump_internals = 0xFF08, + +-- +2.39.5 + diff --git a/queue-6.14/jbd2-avoid-long-replay-times-due-to-high-number-or-r.patch b/queue-6.14/jbd2-avoid-long-replay-times-due-to-high-number-or-r.patch new file mode 100644 index 0000000000..57201553d0 --- /dev/null +++ b/queue-6.14/jbd2-avoid-long-replay-times-due-to-high-number-or-r.patch @@ -0,0 +1,211 @@ +From 994b5f9d200376a4b992f0620e3ca4185f81e7f4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Jan 2025 15:09:26 +0100 +Subject: jbd2: Avoid long replay times due to high number or revoke blocks + +From: Jan Kara + +[ Upstream commit a399af4e3b1ab2c5d83292d4487c4d18de551659 ] + +Some users are reporting journal replay takes a long time when there is +excessive number of revoke blocks in the journal. Reported times are +like: + +1048576 records - 95 seconds +2097152 records - 580 seconds + +The problem is that hash chains in the revoke table gets excessively +long in these cases. Fix the problem by sizing the revoke table +appropriately before the revoke pass. + +Thanks to Alexey Zhuravlev for benchmarking the +patch with large numbers of revoke blocks [1]. + +[1] https://lore.kernel.org/all/20250113183107.7bfef7b6@x390.bzzz77.ru + +Signed-off-by: Jan Kara +Reviewed-by: Andreas Dilger +Reviewed-by: Zhang Yi +Link: https://patch.msgid.link/20250121140925.17231-2-jack@suse.cz +Signed-off-by: Theodore Ts'o +Signed-off-by: Sasha Levin +--- + fs/jbd2/recovery.c | 58 ++++++++++++++++++++++++++++++++++++-------- + fs/jbd2/revoke.c | 8 +++--- + include/linux/jbd2.h | 2 ++ + 3 files changed, 54 insertions(+), 14 deletions(-) + +diff --git a/fs/jbd2/recovery.c b/fs/jbd2/recovery.c +index 23502f1a67c1e..a3c39a71c4ad3 100644 +--- a/fs/jbd2/recovery.c ++++ b/fs/jbd2/recovery.c +@@ -39,7 +39,7 @@ struct recovery_info + + static int do_one_pass(journal_t *journal, + struct recovery_info *info, enum passtype pass); +-static int scan_revoke_records(journal_t *, struct buffer_head *, ++static int scan_revoke_records(journal_t *, enum passtype, struct buffer_head *, + tid_t, struct recovery_info *); + + #ifdef __KERNEL__ +@@ -328,6 +328,12 @@ int jbd2_journal_recover(journal_t *journal) + journal->j_transaction_sequence, journal->j_head); + + jbd2_journal_clear_revoke(journal); ++ /* Free revoke table allocated for replay */ ++ if (journal->j_revoke != journal->j_revoke_table[0] && ++ journal->j_revoke != journal->j_revoke_table[1]) { ++ jbd2_journal_destroy_revoke_table(journal->j_revoke); ++ journal->j_revoke = journal->j_revoke_table[1]; ++ } + err2 = sync_blockdev(journal->j_fs_dev); + if (!err) + err = err2; +@@ -613,6 +619,31 @@ static int do_one_pass(journal_t *journal, + first_commit_ID = next_commit_ID; + if (pass == PASS_SCAN) + info->start_transaction = first_commit_ID; ++ else if (pass == PASS_REVOKE) { ++ /* ++ * Would the default revoke table have too long hash chains ++ * during replay? ++ */ ++ if (info->nr_revokes > JOURNAL_REVOKE_DEFAULT_HASH * 16) { ++ unsigned int hash_size; ++ ++ /* ++ * Aim for average chain length of 8, limit at 1M ++ * entries to avoid problems with malicious ++ * filesystems. ++ */ ++ hash_size = min(roundup_pow_of_two(info->nr_revokes / 8), ++ 1U << 20); ++ journal->j_revoke = ++ jbd2_journal_init_revoke_table(hash_size); ++ if (!journal->j_revoke) { ++ printk(KERN_ERR ++ "JBD2: failed to allocate revoke table for replay with %u entries. " ++ "Journal replay may be slow.\n", hash_size); ++ journal->j_revoke = journal->j_revoke_table[1]; ++ } ++ } ++ } + + jbd2_debug(1, "Starting recovery pass %d\n", pass); + +@@ -852,6 +883,13 @@ static int do_one_pass(journal_t *journal, + continue; + + case JBD2_REVOKE_BLOCK: ++ /* ++ * If we aren't in the SCAN or REVOKE pass, then we can ++ * just skip over this block. ++ */ ++ if (pass != PASS_REVOKE && pass != PASS_SCAN) ++ continue; ++ + /* + * Check revoke block crc in pass_scan, if csum verify + * failed, check commit block time later. +@@ -864,12 +902,7 @@ static int do_one_pass(journal_t *journal, + need_check_commit_time = true; + } + +- /* If we aren't in the REVOKE pass, then we can +- * just skip over this block. */ +- if (pass != PASS_REVOKE) +- continue; +- +- err = scan_revoke_records(journal, bh, ++ err = scan_revoke_records(journal, pass, bh, + next_commit_ID, info); + if (err) + goto failed; +@@ -923,8 +956,9 @@ static int do_one_pass(journal_t *journal, + + /* Scan a revoke record, marking all blocks mentioned as revoked. */ + +-static int scan_revoke_records(journal_t *journal, struct buffer_head *bh, +- tid_t sequence, struct recovery_info *info) ++static int scan_revoke_records(journal_t *journal, enum passtype pass, ++ struct buffer_head *bh, tid_t sequence, ++ struct recovery_info *info) + { + jbd2_journal_revoke_header_t *header; + int offset, max; +@@ -945,6 +979,11 @@ static int scan_revoke_records(journal_t *journal, struct buffer_head *bh, + if (jbd2_has_feature_64bit(journal)) + record_len = 8; + ++ if (pass == PASS_SCAN) { ++ info->nr_revokes += (max - offset) / record_len; ++ return 0; ++ } ++ + while (offset + record_len <= max) { + unsigned long long blocknr; + int err; +@@ -957,7 +996,6 @@ static int scan_revoke_records(journal_t *journal, struct buffer_head *bh, + err = jbd2_journal_set_revoke(journal, blocknr, sequence); + if (err) + return err; +- ++info->nr_revokes; + } + return 0; + } +diff --git a/fs/jbd2/revoke.c b/fs/jbd2/revoke.c +index f68fc8c255f00..bc328c39028a2 100644 +--- a/fs/jbd2/revoke.c ++++ b/fs/jbd2/revoke.c +@@ -215,7 +215,7 @@ int __init jbd2_journal_init_revoke_table_cache(void) + return 0; + } + +-static struct jbd2_revoke_table_s *jbd2_journal_init_revoke_table(int hash_size) ++struct jbd2_revoke_table_s *jbd2_journal_init_revoke_table(int hash_size) + { + int shift = 0; + int tmp = hash_size; +@@ -231,7 +231,7 @@ static struct jbd2_revoke_table_s *jbd2_journal_init_revoke_table(int hash_size) + table->hash_size = hash_size; + table->hash_shift = shift; + table->hash_table = +- kmalloc_array(hash_size, sizeof(struct list_head), GFP_KERNEL); ++ kvmalloc_array(hash_size, sizeof(struct list_head), GFP_KERNEL); + if (!table->hash_table) { + kmem_cache_free(jbd2_revoke_table_cache, table); + table = NULL; +@@ -245,7 +245,7 @@ static struct jbd2_revoke_table_s *jbd2_journal_init_revoke_table(int hash_size) + return table; + } + +-static void jbd2_journal_destroy_revoke_table(struct jbd2_revoke_table_s *table) ++void jbd2_journal_destroy_revoke_table(struct jbd2_revoke_table_s *table) + { + int i; + struct list_head *hash_list; +@@ -255,7 +255,7 @@ static void jbd2_journal_destroy_revoke_table(struct jbd2_revoke_table_s *table) + J_ASSERT(list_empty(hash_list)); + } + +- kfree(table->hash_table); ++ kvfree(table->hash_table); + kmem_cache_free(jbd2_revoke_table_cache, table); + } + +diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h +index 561025b4f3d91..469c4a191ced4 100644 +--- a/include/linux/jbd2.h ++++ b/include/linux/jbd2.h +@@ -1627,6 +1627,8 @@ extern void jbd2_journal_destroy_revoke_record_cache(void); + extern void jbd2_journal_destroy_revoke_table_cache(void); + extern int __init jbd2_journal_init_revoke_record_cache(void); + extern int __init jbd2_journal_init_revoke_table_cache(void); ++struct jbd2_revoke_table_s *jbd2_journal_init_revoke_table(int hash_size); ++void jbd2_journal_destroy_revoke_table(struct jbd2_revoke_table_s *table); + + extern void jbd2_journal_destroy_revoke(journal_t *); + extern int jbd2_journal_revoke (handle_t *, unsigned long long, struct buffer_head *); +-- +2.39.5 + diff --git a/queue-6.14/jbd2-do-not-try-to-recover-wiped-journal.patch b/queue-6.14/jbd2-do-not-try-to-recover-wiped-journal.patch new file mode 100644 index 0000000000..eb92b3b1c1 --- /dev/null +++ b/queue-6.14/jbd2-do-not-try-to-recover-wiped-journal.patch @@ -0,0 +1,58 @@ +From fb48a39902a8435ed8f6c8b25cf9a908eeedaf68 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Feb 2025 10:46:59 +0100 +Subject: jbd2: do not try to recover wiped journal + +From: Jan Kara + +[ Upstream commit a662f3c03b754e1f97a2781fa242e95bdb139798 ] + +If a journal is wiped, we will set journal->j_tail to 0. However if +'write' argument is not set (as it happens for read-only device or for +ocfs2), the on-disk superblock is not updated accordingly and thus +jbd2_journal_recover() cat try to recover the wiped journal. Fix the +check in jbd2_journal_recover() to use journal->j_tail for checking +empty journal instead. + +Signed-off-by: Jan Kara +Reviewed-by: Zhang Yi +Link: https://patch.msgid.link/20250206094657.20865-4-jack@suse.cz +Signed-off-by: Theodore Ts'o +Signed-off-by: Sasha Levin +--- + fs/jbd2/recovery.c | 11 ++++++----- + 1 file changed, 6 insertions(+), 5 deletions(-) + +diff --git a/fs/jbd2/recovery.c b/fs/jbd2/recovery.c +index 9192be7c19d83..23502f1a67c1e 100644 +--- a/fs/jbd2/recovery.c ++++ b/fs/jbd2/recovery.c +@@ -287,19 +287,20 @@ static int fc_do_one_pass(journal_t *journal, + int jbd2_journal_recover(journal_t *journal) + { + int err, err2; +- journal_superblock_t * sb; +- + struct recovery_info info; + + memset(&info, 0, sizeof(info)); +- sb = journal->j_superblock; + + /* + * The journal superblock's s_start field (the current log head) + * is always zero if, and only if, the journal was cleanly +- * unmounted. ++ * unmounted. We use its in-memory version j_tail here because ++ * jbd2_journal_wipe() could have updated it without updating journal ++ * superblock. + */ +- if (!sb->s_start) { ++ if (!journal->j_tail) { ++ journal_superblock_t *sb = journal->j_superblock; ++ + jbd2_debug(1, "No recovery required, last transaction %d, head block %u\n", + be32_to_cpu(sb->s_sequence), be32_to_cpu(sb->s_head)); + journal->j_transaction_sequence = be32_to_cpu(sb->s_sequence) + 1; +-- +2.39.5 + diff --git a/queue-6.14/kbuild-fix-argument-parsing-in-scripts-config.patch b/queue-6.14/kbuild-fix-argument-parsing-in-scripts-config.patch new file mode 100644 index 0000000000..4cffa740fc --- /dev/null +++ b/queue-6.14/kbuild-fix-argument-parsing-in-scripts-config.patch @@ -0,0 +1,82 @@ +From 263e13e92e5055130e16ab28f467361a77bfd428 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 1 Mar 2025 17:21:37 -0500 +Subject: kbuild: fix argument parsing in scripts/config + +From: Seyediman Seyedarab + +[ Upstream commit f757f6011c92b5a01db742c39149bed9e526478f ] + +The script previously assumed --file was always the first argument, +which caused issues when it appeared later. This patch updates the +parsing logic to scan all arguments to find --file, sets the config +file correctly, and resets the argument list with the remaining +commands. + +It also fixes --refresh to respect --file by passing KCONFIG_CONFIG=$FN +to make oldconfig. + +Signed-off-by: Seyediman Seyedarab +Signed-off-by: Masahiro Yamada +Signed-off-by: Sasha Levin +--- + scripts/config | 26 ++++++++++++++++---------- + 1 file changed, 16 insertions(+), 10 deletions(-) + +diff --git a/scripts/config b/scripts/config +index ff88e2faefd35..ea475c07de283 100755 +--- a/scripts/config ++++ b/scripts/config +@@ -32,6 +32,7 @@ commands: + Disable option directly after other option + --module-after|-M beforeopt option + Turn option into module directly after other option ++ --refresh Refresh the config using old settings + + commands can be repeated multiple times + +@@ -124,16 +125,22 @@ undef_var() { + txt_delete "^# $name is not set" "$FN" + } + +-if [ "$1" = "--file" ]; then +- FN="$2" +- if [ "$FN" = "" ] ; then +- usage ++FN=.config ++CMDS=() ++while [[ $# -gt 0 ]]; do ++ if [ "$1" = "--file" ]; then ++ if [ "$2" = "" ]; then ++ usage ++ fi ++ FN="$2" ++ shift 2 ++ else ++ CMDS+=("$1") ++ shift + fi +- shift 2 +-else +- FN=.config +-fi ++done + ++set -- "${CMDS[@]}" + if [ "$1" = "" ] ; then + usage + fi +@@ -217,9 +224,8 @@ while [ "$1" != "" ] ; do + set_var "${CONFIG_}$B" "${CONFIG_}$B=m" "${CONFIG_}$A" + ;; + +- # undocumented because it ignores --file (fixme) + --refresh) +- yes "" | make oldconfig ++ yes "" | make oldconfig KCONFIG_CONFIG=$FN + ;; + + *) +-- +2.39.5 + diff --git a/queue-6.14/kconfig-do-not-clear-symbol_valid-when-reading-inclu.patch b/queue-6.14/kconfig-do-not-clear-symbol_valid-when-reading-inclu.patch new file mode 100644 index 0000000000..2467416e03 --- /dev/null +++ b/queue-6.14/kconfig-do-not-clear-symbol_valid-when-reading-inclu.patch @@ -0,0 +1,90 @@ +From 5c7426336e9a3df6682ed3ded767f16d3ea49c92 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 8 Feb 2025 03:41:55 +0900 +Subject: kconfig: do not clear SYMBOL_VALID when reading + include/config/auto.conf + +From: Masahiro Yamada + +[ Upstream commit 226ac19c217f24f0927d0a73cf9ee613971a188d ] + +When conf_read_simple() is called with S_DEF_AUTO, it is meant to read +previous symbol values from include/config/auto.conf to determine which +include/config/* files should be touched. + +This process should not modify the current symbol status in any way. +However, conf_touch_deps() currently invalidates all symbol values and +recalculates them, which is totally unneeded. + +Signed-off-by: Masahiro Yamada +Signed-off-by: Sasha Levin +--- + scripts/kconfig/confdata.c | 19 ++++++++++++------- + 1 file changed, 12 insertions(+), 7 deletions(-) + +diff --git a/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c +index 3b55e7a4131d9..ac95661a1c9dd 100644 +--- a/scripts/kconfig/confdata.c ++++ b/scripts/kconfig/confdata.c +@@ -385,7 +385,7 @@ int conf_read_simple(const char *name, int def) + + def_flags = SYMBOL_DEF << def; + for_all_symbols(sym) { +- sym->flags &= ~(def_flags|SYMBOL_VALID); ++ sym->flags &= ~def_flags; + switch (sym->type) { + case S_INT: + case S_HEX: +@@ -398,7 +398,11 @@ int conf_read_simple(const char *name, int def) + } + } + +- expr_invalidate_all(); ++ if (def == S_DEF_USER) { ++ for_all_symbols(sym) ++ sym->flags &= ~SYMBOL_VALID; ++ expr_invalidate_all(); ++ } + + while (getline_stripped(&line, &line_asize, in) != -1) { + struct menu *choice; +@@ -464,6 +468,9 @@ int conf_read_simple(const char *name, int def) + if (conf_set_sym_val(sym, def, def_flags, val)) + continue; + ++ if (def != S_DEF_USER) ++ continue; ++ + /* + * If this is a choice member, give it the highest priority. + * If conflicting CONFIG options are given from an input file, +@@ -967,10 +974,8 @@ static int conf_touch_deps(void) + depfile_path[depfile_prefix_len] = 0; + + conf_read_simple(name, S_DEF_AUTO); +- sym_calc_value(modules_sym); + + for_all_symbols(sym) { +- sym_calc_value(sym); + if (sym_is_choice(sym)) + continue; + if (sym->flags & SYMBOL_WRITE) { +@@ -1084,12 +1089,12 @@ int conf_write_autoconf(int overwrite) + if (ret) + return -1; + +- if (conf_touch_deps()) +- return 1; +- + for_all_symbols(sym) + sym_calc_value(sym); + ++ if (conf_touch_deps()) ++ return 1; ++ + ret = __conf_write_autoconf(conf_get_autoheader_name(), + print_symbol_for_c, + &comment_style_c); +-- +2.39.5 + diff --git a/queue-6.14/kconfig-merge_config-use-an-empty-file-as-initfile.patch b/queue-6.14/kconfig-merge_config-use-an-empty-file-as-initfile.patch new file mode 100644 index 0000000000..48c0f07242 --- /dev/null +++ b/queue-6.14/kconfig-merge_config-use-an-empty-file-as-initfile.patch @@ -0,0 +1,48 @@ +From 21609391f804ae146dc39b5a6bf57a982fba933a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 28 Mar 2025 14:28:37 +0000 +Subject: kconfig: merge_config: use an empty file as initfile + +From: Daniel Gomez + +[ Upstream commit a26fe287eed112b4e21e854f173c8918a6a8596d ] + +The scripts/kconfig/merge_config.sh script requires an existing +$INITFILE (or the $1 argument) as a base file for merging Kconfig +fragments. However, an empty $INITFILE can serve as an initial starting +point, later referenced by the KCONFIG_ALLCONFIG Makefile variable +if -m is not used. This variable can point to any configuration file +containing preset config symbols (the merged output) as stated in +Documentation/kbuild/kconfig.rst. When -m is used $INITFILE will +contain just the merge output requiring the user to run make (i.e. +KCONFIG_ALLCONFIG=<$INITFILE> make or make +olddefconfig). + +Instead of failing when `$INITFILE` is missing, create an empty file and +use it as the starting point for merges. + +Signed-off-by: Daniel Gomez +Signed-off-by: Masahiro Yamada +Signed-off-by: Sasha Levin +--- + scripts/kconfig/merge_config.sh | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/scripts/kconfig/merge_config.sh b/scripts/kconfig/merge_config.sh +index 0b7952471c18f..79c09b378be81 100755 +--- a/scripts/kconfig/merge_config.sh ++++ b/scripts/kconfig/merge_config.sh +@@ -112,8 +112,8 @@ INITFILE=$1 + shift; + + if [ ! -r "$INITFILE" ]; then +- echo "The base file '$INITFILE' does not exist. Exit." >&2 +- exit 1 ++ echo "The base file '$INITFILE' does not exist. Creating one..." >&2 ++ touch "$INITFILE" + fi + + MERGE_LIST=$* +-- +2.39.5 + diff --git a/queue-6.14/kernfs-acquire-kernfs_rwsem-in-kernfs_get_parent_den.patch b/queue-6.14/kernfs-acquire-kernfs_rwsem-in-kernfs_get_parent_den.patch new file mode 100644 index 0000000000..aa0face48b --- /dev/null +++ b/queue-6.14/kernfs-acquire-kernfs_rwsem-in-kernfs_get_parent_den.patch @@ -0,0 +1,41 @@ +From 25a717297c69bf728ca7ef85fdfae89a520d5f2d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 13 Feb 2025 15:50:19 +0100 +Subject: kernfs: Acquire kernfs_rwsem in kernfs_get_parent_dentry(). + +From: Sebastian Andrzej Siewior + +[ Upstream commit 122ab92dee80582c39740609a627198dd5b6b595 ] + +kernfs_get_parent_dentry() passes kernfs_node::parent to +kernfs_get_inode(). + +Acquire kernfs_root::kernfs_rwsem to ensure kernfs_node::parent isn't +replaced during the operation. + +Acked-by: Tejun Heo +Signed-off-by: Sebastian Andrzej Siewior +Link: https://lore.kernel.org/r/20250213145023.2820193-3-bigeasy@linutronix.de +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + fs/kernfs/mount.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/fs/kernfs/mount.c b/fs/kernfs/mount.c +index 0f6379ae258d1..4a0ff08d589ca 100644 +--- a/fs/kernfs/mount.c ++++ b/fs/kernfs/mount.c +@@ -145,7 +145,9 @@ static struct dentry *kernfs_fh_to_parent(struct super_block *sb, + static struct dentry *kernfs_get_parent_dentry(struct dentry *child) + { + struct kernfs_node *kn = kernfs_dentry_node(child); ++ struct kernfs_root *root = kernfs_root(kn); + ++ guard(rwsem_read)(&root->kernfs_rwsem); + return d_obtain_alias(kernfs_get_inode(child->d_sb, kn->parent)); + } + +-- +2.39.5 + diff --git a/queue-6.14/kernfs-acquire-kernfs_rwsem-in-kernfs_node_dentry.patch b/queue-6.14/kernfs-acquire-kernfs_rwsem-in-kernfs_node_dentry.patch new file mode 100644 index 0000000000..83781407fa --- /dev/null +++ b/queue-6.14/kernfs-acquire-kernfs_rwsem-in-kernfs_node_dentry.patch @@ -0,0 +1,49 @@ +From f6f132bdcac41f2b42619efd69a1112b6a5a2dde Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 13 Feb 2025 15:50:20 +0100 +Subject: kernfs: Acquire kernfs_rwsem in kernfs_node_dentry(). + +From: Sebastian Andrzej Siewior + +[ Upstream commit 5b2fabf7fe8f745ff214ff003e6067b64f172271 ] + +kernfs_node_dentry() passes kernfs_node::name to +lookup_positive_unlocked(). + +Acquire kernfs_root::kernfs_rwsem to ensure the node is not renamed +during the operation. + +Acked-by: Tejun Heo +Signed-off-by: Sebastian Andrzej Siewior +Link: https://lore.kernel.org/r/20250213145023.2820193-4-bigeasy@linutronix.de +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + fs/kernfs/mount.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/fs/kernfs/mount.c b/fs/kernfs/mount.c +index 1358c21837f1a..0f6379ae258d1 100644 +--- a/fs/kernfs/mount.c ++++ b/fs/kernfs/mount.c +@@ -207,6 +207,7 @@ struct dentry *kernfs_node_dentry(struct kernfs_node *kn, + { + struct dentry *dentry; + struct kernfs_node *knparent; ++ struct kernfs_root *root; + + BUG_ON(sb->s_op != &kernfs_sops); + +@@ -216,6 +217,9 @@ struct dentry *kernfs_node_dentry(struct kernfs_node *kn, + if (!kn->parent) + return dentry; + ++ root = kernfs_root(kn); ++ guard(rwsem_read)(&root->kernfs_rwsem); ++ + knparent = find_next_ancestor(kn, NULL); + if (WARN_ON(!knparent)) { + dput(dentry); +-- +2.39.5 + diff --git a/queue-6.14/kernfs-acquire-kernfs_rwsem-in-kernfs_notify_workfn.patch b/queue-6.14/kernfs-acquire-kernfs_rwsem-in-kernfs_notify_workfn.patch new file mode 100644 index 0000000000..f1899c860e --- /dev/null +++ b/queue-6.14/kernfs-acquire-kernfs_rwsem-in-kernfs_notify_workfn.patch @@ -0,0 +1,47 @@ +From c004b9f6c4df78b795678226de60856ef13ca3ca Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 13 Feb 2025 15:50:18 +0100 +Subject: kernfs: Acquire kernfs_rwsem in kernfs_notify_workfn(). + +From: Sebastian Andrzej Siewior + +[ Upstream commit 400188ae361a9d9a72a47a6cedaf2d2efcc84aa8 ] + +kernfs_notify_workfn() dereferences kernfs_node::name and passes it +later to fsnotify(). If the node is renamed then the previously observed +name pointer becomes invalid. + +Acquire kernfs_root::kernfs_rwsem to block renames of the node. + +Acked-by: Tejun Heo +Signed-off-by: Sebastian Andrzej Siewior +Link: https://lore.kernel.org/r/20250213145023.2820193-2-bigeasy@linutronix.de +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + fs/kernfs/file.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/fs/kernfs/file.c b/fs/kernfs/file.c +index 0eb320617d7b1..c4ffa8dc89ebc 100644 +--- a/fs/kernfs/file.c ++++ b/fs/kernfs/file.c +@@ -911,6 +911,7 @@ static void kernfs_notify_workfn(struct work_struct *work) + /* kick fsnotify */ + + down_read(&root->kernfs_supers_rwsem); ++ down_read(&root->kernfs_rwsem); + list_for_each_entry(info, &kernfs_root(kn)->supers, node) { + struct kernfs_node *parent; + struct inode *p_inode = NULL; +@@ -947,6 +948,7 @@ static void kernfs_notify_workfn(struct work_struct *work) + iput(inode); + } + ++ up_read(&root->kernfs_rwsem); + up_read(&root->kernfs_supers_rwsem); + kernfs_put(kn); + goto repeat; +-- +2.39.5 + diff --git a/queue-6.14/kernfs-don-t-re-lock-kernfs_root-kernfs_rwsem-in-ker.patch b/queue-6.14/kernfs-don-t-re-lock-kernfs_root-kernfs_rwsem-in-ker.patch new file mode 100644 index 0000000000..c1cc4d9585 --- /dev/null +++ b/queue-6.14/kernfs-don-t-re-lock-kernfs_root-kernfs_rwsem-in-ker.patch @@ -0,0 +1,56 @@ +From d207a5442668cab762f65cae33b30cc749ede28e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 13 Feb 2025 15:50:21 +0100 +Subject: kernfs: Don't re-lock kernfs_root::kernfs_rwsem in + kernfs_fop_readdir(). + +From: Sebastian Andrzej Siewior + +[ Upstream commit 9aab10a0249eab4ec77c6a5e4f66442610c12a09 ] + +The readdir operation iterates over all entries and invokes dir_emit() +for every entry passing kernfs_node::name as argument. +Since the name argument can change, and become invalid, the +kernfs_root::kernfs_rwsem lock should not be dropped to prevent renames +during the operation. + +The lock drop around dir_emit() has been initially introduced in commit + 1e5289c97bba2 ("sysfs: Cache the last sysfs_dirent to improve readdir scalability v2") + +to avoid holding a global lock during a page fault. The lock drop is +wrong since the support of renames and not a big burden since the lock +is no longer global. + +Don't re-acquire kernfs_root::kernfs_rwsem while copying the name to the +userpace buffer. + +Acked-by: Tejun Heo +Signed-off-by: Sebastian Andrzej Siewior +Link: https://lore.kernel.org/r/20250213145023.2820193-5-bigeasy@linutronix.de +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + fs/kernfs/dir.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/fs/kernfs/dir.c b/fs/kernfs/dir.c +index 5f0f8b95f44c0..43fbada678381 100644 +--- a/fs/kernfs/dir.c ++++ b/fs/kernfs/dir.c +@@ -1869,10 +1869,10 @@ static int kernfs_fop_readdir(struct file *file, struct dir_context *ctx) + file->private_data = pos; + kernfs_get(pos); + +- up_read(&root->kernfs_rwsem); +- if (!dir_emit(ctx, name, len, ino, type)) ++ if (!dir_emit(ctx, name, len, ino, type)) { ++ up_read(&root->kernfs_rwsem); + return 0; +- down_read(&root->kernfs_rwsem); ++ } + } + up_read(&root->kernfs_rwsem); + file->private_data = NULL; +-- +2.39.5 + diff --git a/queue-6.14/kernfs-drop-kernfs_rwsem-while-invoking-lookup_posit.patch b/queue-6.14/kernfs-drop-kernfs_rwsem-while-invoking-lookup_posit.patch new file mode 100644 index 0000000000..1d6567e21b --- /dev/null +++ b/queue-6.14/kernfs-drop-kernfs_rwsem-while-invoking-lookup_posit.patch @@ -0,0 +1,98 @@ +From a19c98bbfce95b52ef574173a1be3cbe45aa0ad0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 18 Feb 2025 17:39:38 +0100 +Subject: kernfs: Drop kernfs_rwsem while invoking lookup_positive_unlocked(). + +From: Sebastian Andrzej Siewior + +[ Upstream commit 6ef5b6fae304091593956be59065c0c8633ad9e8 ] + +syzbot reported two warnings: +- kernfs_node::name was accessed outside of a RCU section so it created + warning. The kernfs_rwsem was held so it was okay but it wasn't seen. + +- While kernfs_rwsem was held invoked lookup_positive_unlocked()-> + kernfs_dop_revalidate() which acquired kernfs_rwsem. + +kernfs_rwsem was both acquired as a read lock so it can be acquired +twice. However if a writer acquires the lock after the first reader then +neither the writer nor the second reader can obtain the lock so it +deadlocks. + +The reason for the lock is to ensure that kernfs_node::name remain +stable during lookup_positive_unlocked()'s invocation. The function can +not be invoked within a RCU section because it may sleep. + +Make a temporary copy of the kernfs_node::name under the lock so +GFP_KERNEL can be used and use this instead. + +Reported-by: syzbot+ecccecbc636b455f9084@syzkaller.appspotmail.com +Fixes: 5b2fabf7fe8f ("kernfs: Acquire kernfs_rwsem in kernfs_node_dentry().") +Signed-off-by: Sebastian Andrzej Siewior +Acked-by: Tejun Heo +Link: https://lore.kernel.org/r/20250218163938.xmvjlJ0K@linutronix.de +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + fs/kernfs/mount.c | 33 ++++++++++++++++++++++++--------- + 1 file changed, 24 insertions(+), 9 deletions(-) + +diff --git a/fs/kernfs/mount.c b/fs/kernfs/mount.c +index d1f512b7bf867..f1cea282aae32 100644 +--- a/fs/kernfs/mount.c ++++ b/fs/kernfs/mount.c +@@ -220,12 +220,19 @@ struct dentry *kernfs_node_dentry(struct kernfs_node *kn, + return dentry; + + root = kernfs_root(kn); +- guard(rwsem_read)(&root->kernfs_rwsem); +- +- knparent = find_next_ancestor(kn, NULL); +- if (WARN_ON(!knparent)) { +- dput(dentry); ++ /* ++ * As long as kn is valid, its parent can not vanish. This is cgroup's ++ * kn so it not have its parent replaced. Therefore it is safe to use ++ * the ancestor node outside of the RCU or locked section. ++ */ ++ if (WARN_ON_ONCE(!(root->flags & KERNFS_ROOT_INVARIANT_PARENT))) + return ERR_PTR(-EINVAL); ++ scoped_guard(rcu) { ++ knparent = find_next_ancestor(kn, NULL); ++ if (WARN_ON(!knparent)) { ++ dput(dentry); ++ return ERR_PTR(-EINVAL); ++ } + } + + do { +@@ -235,14 +242,22 @@ struct dentry *kernfs_node_dentry(struct kernfs_node *kn, + + if (kn == knparent) + return dentry; +- kntmp = find_next_ancestor(kn, knparent); +- if (WARN_ON(!kntmp)) { ++ ++ scoped_guard(rwsem_read, &root->kernfs_rwsem) { ++ kntmp = find_next_ancestor(kn, knparent); ++ if (WARN_ON(!kntmp)) { ++ dput(dentry); ++ return ERR_PTR(-EINVAL); ++ } ++ name = kstrdup(kernfs_rcu_name(kntmp), GFP_KERNEL); ++ } ++ if (!name) { + dput(dentry); +- return ERR_PTR(-EINVAL); ++ return ERR_PTR(-ENOMEM); + } +- name = rcu_dereference(kntmp->name); + dtmp = lookup_positive_unlocked(name, dentry, strlen(name)); + dput(dentry); ++ kfree(name); + if (IS_ERR(dtmp)) + return dtmp; + knparent = kntmp; +-- +2.39.5 + diff --git a/queue-6.14/kernfs-use-rcu-to-access-kernfs_node-name.patch b/queue-6.14/kernfs-use-rcu-to-access-kernfs_node-name.patch new file mode 100644 index 0000000000..f7110a2aac --- /dev/null +++ b/queue-6.14/kernfs-use-rcu-to-access-kernfs_node-name.patch @@ -0,0 +1,596 @@ +From 8e1b2461023eba183fce8c2b3ef54a3e6b6eb056 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 13 Feb 2025 15:50:23 +0100 +Subject: kernfs: Use RCU to access kernfs_node::name. + +From: Sebastian Andrzej Siewior + +[ Upstream commit 741c10b096bc4dd79cd9f215b6ef173bb953e75c ] + +Using RCU lifetime rules to access kernfs_node::name can avoid the +trouble with kernfs_rename_lock in kernfs_name() and kernfs_path_from_node() +if the fs was created with KERNFS_ROOT_INVARIANT_PARENT. This is usefull +as it allows to implement kernfs_path_from_node() only with RCU +protection and avoiding kernfs_rename_lock. The lock is only required if +the __parent node can be changed and the function requires an unchanged +hierarchy while it iterates from the node to its parent. +The change is needed to allow the lookup of the node's path +(kernfs_path_from_node()) from context which runs always with disabled +preemption and or interrutps even on PREEMPT_RT. The problem is that +kernfs_rename_lock becomes a sleeping lock on PREEMPT_RT. + +I went through all ::name users and added the required access for the lookup +with a few extensions: +- rdtgroup_pseudo_lock_create() drops all locks and then uses the name + later on. resctrl supports rename with different parents. Here I made + a temporal copy of the name while it is used outside of the lock. + +- kernfs_rename_ns() accepts NULL as new_parent. This simplifies + sysfs_move_dir_ns() where it can set NULL in order to reuse the current + name. + +- kernfs_rename_ns() is only using kernfs_rename_lock if the parents are + different. All users use either kernfs_rwsem (for stable path view) or + just RCU for the lookup. The ::name uses always RCU free. + +Use RCU lifetime guarantees to access kernfs_node::name. + +Suggested-by: Tejun Heo +Acked-by: Tejun Heo +Reported-by: syzbot+6ea37e2e6ffccf41a7e6@syzkaller.appspotmail.com +Closes: https://lore.kernel.org/lkml/67251dc6.050a0220.529b6.015e.GAE@google.com/ +Reported-by: Hillf Danton +Closes: https://lore.kernel.org/20241102001224.2789-1-hdanton@sina.com +Signed-off-by: Sebastian Andrzej Siewior +Link: https://lore.kernel.org/r/20250213145023.2820193-7-bigeasy@linutronix.de +Signed-off-by: Greg Kroah-Hartman +Stable-dep-of: 6ef5b6fae304 ("kernfs: Drop kernfs_rwsem while invoking lookup_positive_unlocked().") +Signed-off-by: Sasha Levin +--- + arch/x86/kernel/cpu/resctrl/internal.h | 5 + + arch/x86/kernel/cpu/resctrl/pseudo_lock.c | 14 ++- + arch/x86/kernel/cpu/resctrl/rdtgroup.c | 10 +- + fs/kernfs/dir.c | 113 ++++++++++++---------- + fs/kernfs/file.c | 4 +- + fs/kernfs/kernfs-internal.h | 5 + + fs/kernfs/mount.c | 5 +- + fs/kernfs/symlink.c | 7 +- + fs/sysfs/dir.c | 2 +- + include/linux/kernfs.h | 4 +- + security/selinux/hooks.c | 7 +- + 11 files changed, 105 insertions(+), 71 deletions(-) + +diff --git a/arch/x86/kernel/cpu/resctrl/internal.h b/arch/x86/kernel/cpu/resctrl/internal.h +index 20c898f09b7e7..dd5d6b4bfcc22 100644 +--- a/arch/x86/kernel/cpu/resctrl/internal.h ++++ b/arch/x86/kernel/cpu/resctrl/internal.h +@@ -507,6 +507,11 @@ int parse_bw(struct rdt_parse_data *data, struct resctrl_schema *s, + + extern struct mutex rdtgroup_mutex; + ++static inline const char *rdt_kn_name(const struct kernfs_node *kn) ++{ ++ return rcu_dereference_check(kn->name, lockdep_is_held(&rdtgroup_mutex)); ++} ++ + extern struct rdt_hw_resource rdt_resources_all[]; + extern struct rdtgroup rdtgroup_default; + extern struct dentry *debugfs_resctrl; +diff --git a/arch/x86/kernel/cpu/resctrl/pseudo_lock.c b/arch/x86/kernel/cpu/resctrl/pseudo_lock.c +index 42cc162f7fc91..7a2db7fa41083 100644 +--- a/arch/x86/kernel/cpu/resctrl/pseudo_lock.c ++++ b/arch/x86/kernel/cpu/resctrl/pseudo_lock.c +@@ -52,7 +52,8 @@ static char *pseudo_lock_devnode(const struct device *dev, umode_t *mode) + rdtgrp = dev_get_drvdata(dev); + if (mode) + *mode = 0600; +- return kasprintf(GFP_KERNEL, "pseudo_lock/%s", rdtgrp->kn->name); ++ guard(mutex)(&rdtgroup_mutex); ++ return kasprintf(GFP_KERNEL, "pseudo_lock/%s", rdt_kn_name(rdtgrp->kn)); + } + + static const struct class pseudo_lock_class = { +@@ -1293,6 +1294,7 @@ int rdtgroup_pseudo_lock_create(struct rdtgroup *rdtgrp) + struct task_struct *thread; + unsigned int new_minor; + struct device *dev; ++ char *kn_name __free(kfree) = NULL; + int ret; + + ret = pseudo_lock_region_alloc(plr); +@@ -1304,6 +1306,11 @@ int rdtgroup_pseudo_lock_create(struct rdtgroup *rdtgrp) + ret = -EINVAL; + goto out_region; + } ++ kn_name = kstrdup(rdt_kn_name(rdtgrp->kn), GFP_KERNEL); ++ if (!kn_name) { ++ ret = -ENOMEM; ++ goto out_cstates; ++ } + + plr->thread_done = 0; + +@@ -1348,8 +1355,7 @@ int rdtgroup_pseudo_lock_create(struct rdtgroup *rdtgrp) + mutex_unlock(&rdtgroup_mutex); + + if (!IS_ERR_OR_NULL(debugfs_resctrl)) { +- plr->debugfs_dir = debugfs_create_dir(rdtgrp->kn->name, +- debugfs_resctrl); ++ plr->debugfs_dir = debugfs_create_dir(kn_name, debugfs_resctrl); + if (!IS_ERR_OR_NULL(plr->debugfs_dir)) + debugfs_create_file("pseudo_lock_measure", 0200, + plr->debugfs_dir, rdtgrp, +@@ -1358,7 +1364,7 @@ int rdtgroup_pseudo_lock_create(struct rdtgroup *rdtgrp) + + dev = device_create(&pseudo_lock_class, NULL, + MKDEV(pseudo_lock_major, new_minor), +- rdtgrp, "%s", rdtgrp->kn->name); ++ rdtgrp, "%s", kn_name); + + mutex_lock(&rdtgroup_mutex); + +diff --git a/arch/x86/kernel/cpu/resctrl/rdtgroup.c b/arch/x86/kernel/cpu/resctrl/rdtgroup.c +index 3d2a850ea737d..1f769d819a864 100644 +--- a/arch/x86/kernel/cpu/resctrl/rdtgroup.c ++++ b/arch/x86/kernel/cpu/resctrl/rdtgroup.c +@@ -917,14 +917,14 @@ int proc_resctrl_show(struct seq_file *s, struct pid_namespace *ns, + continue; + + seq_printf(s, "res:%s%s\n", (rdtg == &rdtgroup_default) ? "/" : "", +- rdtg->kn->name); ++ rdt_kn_name(rdtg->kn)); + seq_puts(s, "mon:"); + list_for_each_entry(crg, &rdtg->mon.crdtgrp_list, + mon.crdtgrp_list) { + if (!resctrl_arch_match_rmid(tsk, crg->mon.parent->closid, + crg->mon.rmid)) + continue; +- seq_printf(s, "%s", crg->kn->name); ++ seq_printf(s, "%s", rdt_kn_name(crg->kn)); + break; + } + seq_putc(s, '\n'); +@@ -3676,7 +3676,7 @@ static int rdtgroup_mkdir_ctrl_mon(struct kernfs_node *parent_kn, + */ + static bool is_mon_groups(struct kernfs_node *kn, const char *name) + { +- return (!strcmp(kn->name, "mon_groups") && ++ return (!strcmp(rdt_kn_name(kn), "mon_groups") && + strcmp(name, "mon_groups")); + } + +@@ -3825,7 +3825,7 @@ static int rdtgroup_rmdir(struct kernfs_node *kn) + ret = rdtgroup_rmdir_ctrl(rdtgrp, tmpmask); + } + } else if (rdtgrp->type == RDTMON_GROUP && +- is_mon_groups(parent_kn, kn->name)) { ++ is_mon_groups(parent_kn, rdt_kn_name(kn))) { + ret = rdtgroup_rmdir_mon(rdtgrp, tmpmask); + } else { + ret = -EPERM; +@@ -3913,7 +3913,7 @@ static int rdtgroup_rename(struct kernfs_node *kn, + + kn_parent = rdt_kn_parent(kn); + if (rdtgrp->type != RDTMON_GROUP || !kn_parent || +- !is_mon_groups(kn_parent, kn->name)) { ++ !is_mon_groups(kn_parent, rdt_kn_name(kn))) { + rdt_last_cmd_puts("Source must be a MON group\n"); + ret = -EPERM; + goto out; +diff --git a/fs/kernfs/dir.c b/fs/kernfs/dir.c +index 1d370c497e8a3..c5a578c46759a 100644 +--- a/fs/kernfs/dir.c ++++ b/fs/kernfs/dir.c +@@ -51,14 +51,6 @@ static bool kernfs_lockdep(struct kernfs_node *kn) + #endif + } + +-static int kernfs_name_locked(struct kernfs_node *kn, char *buf, size_t buflen) +-{ +- if (!kn) +- return strscpy(buf, "(null)", buflen); +- +- return strscpy(buf, rcu_access_pointer(kn->__parent) ? kn->name : "/", buflen); +-} +- + /* kernfs_node_depth - compute depth from @from to @to */ + static size_t kernfs_depth(struct kernfs_node *from, struct kernfs_node *to) + { +@@ -168,11 +160,13 @@ static int kernfs_path_from_node_locked(struct kernfs_node *kn_to, + + /* Calculate how many bytes we need for the rest */ + for (i = depth_to - 1; i >= 0; i--) { ++ const char *name; + + for (kn = kn_to, j = 0; j < i; j++) + kn = rcu_dereference(kn->__parent); + +- len += scnprintf(buf + len, buflen - len, "/%s", kn->name); ++ name = rcu_dereference(kn->name); ++ len += scnprintf(buf + len, buflen - len, "/%s", name); + } + + return len; +@@ -196,13 +190,18 @@ static int kernfs_path_from_node_locked(struct kernfs_node *kn_to, + */ + int kernfs_name(struct kernfs_node *kn, char *buf, size_t buflen) + { +- unsigned long flags; +- int ret; ++ struct kernfs_node *kn_parent; + +- read_lock_irqsave(&kernfs_rename_lock, flags); +- ret = kernfs_name_locked(kn, buf, buflen); +- read_unlock_irqrestore(&kernfs_rename_lock, flags); +- return ret; ++ if (!kn) ++ return strscpy(buf, "(null)", buflen); ++ ++ guard(rcu)(); ++ /* ++ * KERNFS_ROOT_INVARIANT_PARENT is ignored here. The name is RCU freed and ++ * the parent is either existing or not. ++ */ ++ kn_parent = rcu_dereference(kn->__parent); ++ return strscpy(buf, kn_parent ? rcu_dereference(kn->name) : "/", buflen); + } + + /** +@@ -224,14 +223,17 @@ int kernfs_name(struct kernfs_node *kn, char *buf, size_t buflen) + int kernfs_path_from_node(struct kernfs_node *to, struct kernfs_node *from, + char *buf, size_t buflen) + { +- unsigned long flags; +- int ret; ++ struct kernfs_root *root; + + guard(rcu)(); +- read_lock_irqsave(&kernfs_rename_lock, flags); +- ret = kernfs_path_from_node_locked(to, from, buf, buflen); +- read_unlock_irqrestore(&kernfs_rename_lock, flags); +- return ret; ++ if (to) { ++ root = kernfs_root(to); ++ if (!(root->flags & KERNFS_ROOT_INVARIANT_PARENT)) { ++ guard(read_lock_irqsave)(&kernfs_rename_lock); ++ return kernfs_path_from_node_locked(to, from, buf, buflen); ++ } ++ } ++ return kernfs_path_from_node_locked(to, from, buf, buflen); + } + EXPORT_SYMBOL_GPL(kernfs_path_from_node); + +@@ -338,13 +340,13 @@ static int kernfs_name_compare(unsigned int hash, const char *name, + return -1; + if (ns > kn->ns) + return 1; +- return strcmp(name, kn->name); ++ return strcmp(name, kernfs_rcu_name(kn)); + } + + static int kernfs_sd_compare(const struct kernfs_node *left, + const struct kernfs_node *right) + { +- return kernfs_name_compare(left->hash, left->name, left->ns, right); ++ return kernfs_name_compare(left->hash, kernfs_rcu_name(left), left->ns, right); + } + + /** +@@ -542,7 +544,8 @@ static void kernfs_free_rcu(struct rcu_head *rcu) + { + struct kernfs_node *kn = container_of(rcu, struct kernfs_node, rcu); + +- kfree_const(kn->name); ++ /* If the whole node goes away, then name can't be used outside */ ++ kfree_const(rcu_access_pointer(kn->name)); + + if (kn->iattr) { + simple_xattrs_free(&kn->iattr->xattrs, NULL); +@@ -575,7 +578,8 @@ void kernfs_put(struct kernfs_node *kn) + + WARN_ONCE(atomic_read(&kn->active) != KN_DEACTIVATED_BIAS, + "kernfs_put: %s/%s: released with incorrect active_ref %d\n", +- parent ? parent->name : "", kn->name, atomic_read(&kn->active)); ++ parent ? rcu_dereference(parent->name) : "", ++ rcu_dereference(kn->name), atomic_read(&kn->active)); + + if (kernfs_type(kn) == KERNFS_LINK) + kernfs_put(kn->symlink.target_kn); +@@ -652,7 +656,7 @@ static struct kernfs_node *__kernfs_new_node(struct kernfs_root *root, + atomic_set(&kn->active, KN_DEACTIVATED_BIAS); + RB_CLEAR_NODE(&kn->rb); + +- kn->name = name; ++ rcu_assign_pointer(kn->name, name); + kn->mode = mode; + kn->flags = flags; + +@@ -790,7 +794,8 @@ int kernfs_add_one(struct kernfs_node *kn) + ret = -EINVAL; + has_ns = kernfs_ns_enabled(parent); + if (WARN(has_ns != (bool)kn->ns, KERN_WARNING "kernfs: ns %s in '%s' for '%s'\n", +- has_ns ? "required" : "invalid", parent->name, kn->name)) ++ has_ns ? "required" : "invalid", ++ kernfs_rcu_name(parent), kernfs_rcu_name(kn))) + goto out_unlock; + + if (kernfs_type(parent) != KERNFS_DIR) +@@ -800,7 +805,7 @@ int kernfs_add_one(struct kernfs_node *kn) + if (parent->flags & (KERNFS_REMOVING | KERNFS_EMPTY_DIR)) + goto out_unlock; + +- kn->hash = kernfs_name_hash(kn->name, kn->ns); ++ kn->hash = kernfs_name_hash(kernfs_rcu_name(kn), kn->ns); + + ret = kernfs_link_sibling(kn); + if (ret) +@@ -856,7 +861,7 @@ static struct kernfs_node *kernfs_find_ns(struct kernfs_node *parent, + + if (has_ns != (bool)ns) { + WARN(1, KERN_WARNING "kernfs: ns %s in '%s' for '%s'\n", +- has_ns ? "required" : "invalid", parent->name, name); ++ has_ns ? "required" : "invalid", kernfs_rcu_name(parent), name); + return NULL; + } + +@@ -1135,8 +1140,6 @@ static int kernfs_dop_revalidate(struct inode *dir, const struct qstr *name, + + /* Negative hashed dentry? */ + if (d_really_is_negative(dentry)) { +- struct kernfs_node *parent; +- + /* If the kernfs parent node has changed discard and + * proceed to ->lookup. + * +@@ -1184,7 +1187,7 @@ static int kernfs_dop_revalidate(struct inode *dir, const struct qstr *name, + goto out_bad; + + /* The kernfs node has been renamed */ +- if (strcmp(dentry->d_name.name, kn->name) != 0) ++ if (strcmp(dentry->d_name.name, kernfs_rcu_name(kn)) != 0) + goto out_bad; + + /* The kernfs node has been moved to a different namespace */ +@@ -1478,7 +1481,7 @@ static void __kernfs_remove(struct kernfs_node *kn) + if (kernfs_parent(kn) && RB_EMPTY_NODE(&kn->rb)) + return; + +- pr_debug("kernfs %s: removing\n", kn->name); ++ pr_debug("kernfs %s: removing\n", kernfs_rcu_name(kn)); + + /* prevent new usage by marking all nodes removing and deactivating */ + pos = NULL; +@@ -1734,7 +1737,7 @@ int kernfs_rename_ns(struct kernfs_node *kn, struct kernfs_node *new_parent, + { + struct kernfs_node *old_parent; + struct kernfs_root *root; +- const char *old_name = NULL; ++ const char *old_name; + int error; + + /* can't move or rename root */ +@@ -1757,8 +1760,11 @@ int kernfs_rename_ns(struct kernfs_node *kn, struct kernfs_node *new_parent, + } + + error = 0; ++ old_name = kernfs_rcu_name(kn); ++ if (!new_name) ++ new_name = old_name; + if ((old_parent == new_parent) && (kn->ns == new_ns) && +- (strcmp(kn->name, new_name) == 0)) ++ (strcmp(old_name, new_name) == 0)) + goto out; /* nothing to rename */ + + error = -EEXIST; +@@ -1766,7 +1772,7 @@ int kernfs_rename_ns(struct kernfs_node *kn, struct kernfs_node *new_parent, + goto out; + + /* rename kernfs_node */ +- if (strcmp(kn->name, new_name) != 0) { ++ if (strcmp(old_name, new_name) != 0) { + error = -ENOMEM; + new_name = kstrdup_const(new_name, GFP_KERNEL); + if (!new_name) +@@ -1779,27 +1785,32 @@ int kernfs_rename_ns(struct kernfs_node *kn, struct kernfs_node *new_parent, + * Move to the appropriate place in the appropriate directories rbtree. + */ + kernfs_unlink_sibling(kn); +- kernfs_get(new_parent); + +- /* rename_lock protects ->parent and ->name accessors */ +- write_lock_irq(&kernfs_rename_lock); ++ /* rename_lock protects ->parent accessors */ ++ if (old_parent != new_parent) { ++ kernfs_get(new_parent); ++ write_lock_irq(&kernfs_rename_lock); + +- old_parent = kernfs_parent(kn); +- rcu_assign_pointer(kn->__parent, new_parent); ++ rcu_assign_pointer(kn->__parent, new_parent); + +- kn->ns = new_ns; +- if (new_name) { +- old_name = kn->name; +- kn->name = new_name; +- } ++ kn->ns = new_ns; ++ if (new_name) ++ rcu_assign_pointer(kn->name, new_name); + +- write_unlock_irq(&kernfs_rename_lock); ++ write_unlock_irq(&kernfs_rename_lock); ++ kernfs_put(old_parent); ++ } else { ++ /* name assignment is RCU protected, parent is the same */ ++ kn->ns = new_ns; ++ if (new_name) ++ rcu_assign_pointer(kn->name, new_name); ++ } + +- kn->hash = kernfs_name_hash(kn->name, kn->ns); ++ kn->hash = kernfs_name_hash(new_name ?: old_name, kn->ns); + kernfs_link_sibling(kn); + +- kernfs_put(old_parent); +- kfree_const(old_name); ++ if (new_name && !is_kernel_rodata((unsigned long)old_name)) ++ kfree_rcu_mightsleep(old_name); + + error = 0; + out: +@@ -1884,7 +1895,7 @@ static int kernfs_fop_readdir(struct file *file, struct dir_context *ctx) + for (pos = kernfs_dir_pos(ns, parent, ctx->pos, pos); + pos; + pos = kernfs_dir_next_pos(ns, parent, ctx->pos, pos)) { +- const char *name = pos->name; ++ const char *name = kernfs_rcu_name(pos); + unsigned int type = fs_umode_to_dtype(pos->mode); + int len = strlen(name); + ino_t ino = kernfs_ino(pos); +diff --git a/fs/kernfs/file.c b/fs/kernfs/file.c +index c4ffa8dc89ebc..66fe8fe41f060 100644 +--- a/fs/kernfs/file.c ++++ b/fs/kernfs/file.c +@@ -915,6 +915,7 @@ static void kernfs_notify_workfn(struct work_struct *work) + list_for_each_entry(info, &kernfs_root(kn)->supers, node) { + struct kernfs_node *parent; + struct inode *p_inode = NULL; ++ const char *kn_name; + struct inode *inode; + struct qstr name; + +@@ -928,7 +929,8 @@ static void kernfs_notify_workfn(struct work_struct *work) + if (!inode) + continue; + +- name = QSTR(kn->name); ++ kn_name = kernfs_rcu_name(kn); ++ name = QSTR(kn_name); + parent = kernfs_get_parent(kn); + if (parent) { + p_inode = ilookup(info->sb, kernfs_ino(parent)); +diff --git a/fs/kernfs/kernfs-internal.h b/fs/kernfs/kernfs-internal.h +index c43bee18b79f7..40a2a9cd819d0 100644 +--- a/fs/kernfs/kernfs-internal.h ++++ b/fs/kernfs/kernfs-internal.h +@@ -107,6 +107,11 @@ static inline bool kernfs_root_is_locked(const struct kernfs_node *kn) + return lockdep_is_held(&kernfs_root(kn)->kernfs_rwsem); + } + ++static inline const char *kernfs_rcu_name(const struct kernfs_node *kn) ++{ ++ return rcu_dereference_check(kn->name, kernfs_root_is_locked(kn)); ++} ++ + static inline struct kernfs_node *kernfs_parent(const struct kernfs_node *kn) + { + /* +diff --git a/fs/kernfs/mount.c b/fs/kernfs/mount.c +index 2252b16e6ef0b..d1f512b7bf867 100644 +--- a/fs/kernfs/mount.c ++++ b/fs/kernfs/mount.c +@@ -231,6 +231,7 @@ struct dentry *kernfs_node_dentry(struct kernfs_node *kn, + do { + struct dentry *dtmp; + struct kernfs_node *kntmp; ++ const char *name; + + if (kn == knparent) + return dentry; +@@ -239,8 +240,8 @@ struct dentry *kernfs_node_dentry(struct kernfs_node *kn, + dput(dentry); + return ERR_PTR(-EINVAL); + } +- dtmp = lookup_positive_unlocked(kntmp->name, dentry, +- strlen(kntmp->name)); ++ name = rcu_dereference(kntmp->name); ++ dtmp = lookup_positive_unlocked(name, dentry, strlen(name)); + dput(dentry); + if (IS_ERR(dtmp)) + return dtmp; +diff --git a/fs/kernfs/symlink.c b/fs/kernfs/symlink.c +index 05c62ca93c53d..0bd8a2143723d 100644 +--- a/fs/kernfs/symlink.c ++++ b/fs/kernfs/symlink.c +@@ -81,7 +81,7 @@ static int kernfs_get_target_path(struct kernfs_node *parent, + /* determine end of target string for reverse fillup */ + kn = target; + while (kernfs_parent(kn) && kn != base) { +- len += strlen(kn->name) + 1; ++ len += strlen(kernfs_rcu_name(kn)) + 1; + kn = kernfs_parent(kn); + } + +@@ -95,10 +95,11 @@ static int kernfs_get_target_path(struct kernfs_node *parent, + /* reverse fillup of target string from target to base */ + kn = target; + while (kernfs_parent(kn) && kn != base) { +- int slen = strlen(kn->name); ++ const char *name = kernfs_rcu_name(kn); ++ int slen = strlen(name); + + len -= slen; +- memcpy(s + len, kn->name, slen); ++ memcpy(s + len, name, slen); + if (len) + s[--len] = '/'; + +diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c +index 4df2afa551dc6..94e12efd92f21 100644 +--- a/fs/sysfs/dir.c ++++ b/fs/sysfs/dir.c +@@ -123,7 +123,7 @@ int sysfs_move_dir_ns(struct kobject *kobj, struct kobject *new_parent_kobj, + new_parent = new_parent_kobj && new_parent_kobj->sd ? + new_parent_kobj->sd : sysfs_root_kn; + +- return kernfs_rename_ns(kn, new_parent, kn->name, new_ns); ++ return kernfs_rename_ns(kn, new_parent, NULL, new_ns); + } + + /** +diff --git a/include/linux/kernfs.h b/include/linux/kernfs.h +index 5dda9a268e44c..b5a5f32fdfd1a 100644 +--- a/include/linux/kernfs.h ++++ b/include/linux/kernfs.h +@@ -204,8 +204,8 @@ struct kernfs_node { + * never moved to a different parent, it is safe to access the + * parent directly. + */ +- const char *name; + struct kernfs_node __rcu *__parent; ++ const char __rcu *name; + + struct rb_node rb; + +@@ -400,7 +400,7 @@ static inline bool kernfs_ns_enabled(struct kernfs_node *kn) + } + + int kernfs_name(struct kernfs_node *kn, char *buf, size_t buflen); +-int kernfs_path_from_node(struct kernfs_node *root_kn, struct kernfs_node *kn, ++int kernfs_path_from_node(struct kernfs_node *kn_to, struct kernfs_node *kn_from, + char *buf, size_t buflen); + void pr_cont_kernfs_name(struct kernfs_node *kn); + void pr_cont_kernfs_path(struct kernfs_node *kn); +diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c +index 7b867dfec88ba..7dee9616147d2 100644 +--- a/security/selinux/hooks.c ++++ b/security/selinux/hooks.c +@@ -3584,10 +3584,13 @@ static int selinux_kernfs_init_security(struct kernfs_node *kn_dir, + newsid = tsec->create_sid; + } else { + u16 secclass = inode_mode_to_security_class(kn->mode); ++ const char *kn_name; + struct qstr q; + +- q.name = kn->name; +- q.hash_len = hashlen_string(kn_dir, kn->name); ++ /* kn is fresh, can't be renamed, name goes not away */ ++ kn_name = rcu_dereference_check(kn->name, true); ++ q.name = kn_name; ++ q.hash_len = hashlen_string(kn_dir, kn_name); + + rc = security_transition_sid(tsec->sid, + parent_sid, secclass, &q, +-- +2.39.5 + diff --git a/queue-6.14/kernfs-use-rcu-to-access-kernfs_node-parent.patch b/queue-6.14/kernfs-use-rcu-to-access-kernfs_node-parent.patch new file mode 100644 index 0000000000..2a6d928b79 --- /dev/null +++ b/queue-6.14/kernfs-use-rcu-to-access-kernfs_node-parent.patch @@ -0,0 +1,989 @@ +From d00673680b5c872e774bcf1edfc01462fd88bb55 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 13 Feb 2025 15:50:22 +0100 +Subject: kernfs: Use RCU to access kernfs_node::parent. + +From: Sebastian Andrzej Siewior + +[ Upstream commit 633488947ef66b194377411322dc9e12aab79b65 ] + +kernfs_rename_lock is used to obtain stable kernfs_node::{name|parent} +pointer. This is a preparation to access kernfs_node::parent under RCU +and ensure that the pointer remains stable under the RCU lifetime +guarantees. + +For a complete path, as it is done in kernfs_path_from_node(), the +kernfs_rename_lock is still required in order to obtain a stable parent +relationship while computing the relevant node depth. This must not +change while the nodes are inspected in order to build the path. +If the kernfs user never moves the nodes (changes the parent) then the +kernfs_rename_lock is not required and the RCU guarantees are +sufficient. This "restriction" can be set with +KERNFS_ROOT_INVARIANT_PARENT. Otherwise the lock is required. + +Rename kernfs_node::parent to kernfs_node::__parent to denote the RCU +access and use RCU accessor while accessing the node. +Make cgroup use KERNFS_ROOT_INVARIANT_PARENT since the parent here can +not change. + +Acked-by: Tejun Heo +Cc: Yonghong Song +Signed-off-by: Sebastian Andrzej Siewior +Link: https://lore.kernel.org/r/20250213145023.2820193-6-bigeasy@linutronix.de +Signed-off-by: Greg Kroah-Hartman +Stable-dep-of: 6ef5b6fae304 ("kernfs: Drop kernfs_rwsem while invoking lookup_positive_unlocked().") +Signed-off-by: Sasha Levin +--- + arch/x86/kernel/cpu/resctrl/rdtgroup.c | 65 +++++++++---- + fs/kernfs/dir.c | 96 ++++++++++++------- + fs/kernfs/kernfs-internal.h | 32 ++++++- + fs/kernfs/mount.c | 10 +- + fs/kernfs/symlink.c | 23 ++--- + fs/sysfs/file.c | 24 +++-- + include/linux/kernfs.h | 10 +- + kernel/cgroup/cgroup-v1.c | 2 +- + kernel/cgroup/cgroup.c | 24 ++++- + .../selftests/bpf/progs/profiler.inc.h | 2 +- + 10 files changed, 195 insertions(+), 93 deletions(-) + +diff --git a/arch/x86/kernel/cpu/resctrl/rdtgroup.c b/arch/x86/kernel/cpu/resctrl/rdtgroup.c +index 04b653d613e88..3d2a850ea737d 100644 +--- a/arch/x86/kernel/cpu/resctrl/rdtgroup.c ++++ b/arch/x86/kernel/cpu/resctrl/rdtgroup.c +@@ -957,10 +957,20 @@ static int rdt_last_cmd_status_show(struct kernfs_open_file *of, + return 0; + } + ++static void *rdt_kn_parent_priv(struct kernfs_node *kn) ++{ ++ /* ++ * The parent pointer is only valid within RCU section since it can be ++ * replaced. ++ */ ++ guard(rcu)(); ++ return rcu_dereference(kn->__parent)->priv; ++} ++ + static int rdt_num_closids_show(struct kernfs_open_file *of, + struct seq_file *seq, void *v) + { +- struct resctrl_schema *s = of->kn->parent->priv; ++ struct resctrl_schema *s = rdt_kn_parent_priv(of->kn); + + seq_printf(seq, "%u\n", s->num_closid); + return 0; +@@ -969,7 +979,7 @@ static int rdt_num_closids_show(struct kernfs_open_file *of, + static int rdt_default_ctrl_show(struct kernfs_open_file *of, + struct seq_file *seq, void *v) + { +- struct resctrl_schema *s = of->kn->parent->priv; ++ struct resctrl_schema *s = rdt_kn_parent_priv(of->kn); + struct rdt_resource *r = s->res; + + seq_printf(seq, "%x\n", r->default_ctrl); +@@ -979,7 +989,7 @@ static int rdt_default_ctrl_show(struct kernfs_open_file *of, + static int rdt_min_cbm_bits_show(struct kernfs_open_file *of, + struct seq_file *seq, void *v) + { +- struct resctrl_schema *s = of->kn->parent->priv; ++ struct resctrl_schema *s = rdt_kn_parent_priv(of->kn); + struct rdt_resource *r = s->res; + + seq_printf(seq, "%u\n", r->cache.min_cbm_bits); +@@ -989,7 +999,7 @@ static int rdt_min_cbm_bits_show(struct kernfs_open_file *of, + static int rdt_shareable_bits_show(struct kernfs_open_file *of, + struct seq_file *seq, void *v) + { +- struct resctrl_schema *s = of->kn->parent->priv; ++ struct resctrl_schema *s = rdt_kn_parent_priv(of->kn); + struct rdt_resource *r = s->res; + + seq_printf(seq, "%x\n", r->cache.shareable_bits); +@@ -1013,7 +1023,7 @@ static int rdt_shareable_bits_show(struct kernfs_open_file *of, + static int rdt_bit_usage_show(struct kernfs_open_file *of, + struct seq_file *seq, void *v) + { +- struct resctrl_schema *s = of->kn->parent->priv; ++ struct resctrl_schema *s = rdt_kn_parent_priv(of->kn); + /* + * Use unsigned long even though only 32 bits are used to ensure + * test_bit() is used safely. +@@ -1095,7 +1105,7 @@ static int rdt_bit_usage_show(struct kernfs_open_file *of, + static int rdt_min_bw_show(struct kernfs_open_file *of, + struct seq_file *seq, void *v) + { +- struct resctrl_schema *s = of->kn->parent->priv; ++ struct resctrl_schema *s = rdt_kn_parent_priv(of->kn); + struct rdt_resource *r = s->res; + + seq_printf(seq, "%u\n", r->membw.min_bw); +@@ -1105,7 +1115,7 @@ static int rdt_min_bw_show(struct kernfs_open_file *of, + static int rdt_num_rmids_show(struct kernfs_open_file *of, + struct seq_file *seq, void *v) + { +- struct rdt_resource *r = of->kn->parent->priv; ++ struct rdt_resource *r = rdt_kn_parent_priv(of->kn); + + seq_printf(seq, "%d\n", r->num_rmid); + +@@ -1115,7 +1125,7 @@ static int rdt_num_rmids_show(struct kernfs_open_file *of, + static int rdt_mon_features_show(struct kernfs_open_file *of, + struct seq_file *seq, void *v) + { +- struct rdt_resource *r = of->kn->parent->priv; ++ struct rdt_resource *r = rdt_kn_parent_priv(of->kn); + struct mon_evt *mevt; + + list_for_each_entry(mevt, &r->evt_list, list) { +@@ -1130,7 +1140,7 @@ static int rdt_mon_features_show(struct kernfs_open_file *of, + static int rdt_bw_gran_show(struct kernfs_open_file *of, + struct seq_file *seq, void *v) + { +- struct resctrl_schema *s = of->kn->parent->priv; ++ struct resctrl_schema *s = rdt_kn_parent_priv(of->kn); + struct rdt_resource *r = s->res; + + seq_printf(seq, "%u\n", r->membw.bw_gran); +@@ -1140,7 +1150,7 @@ static int rdt_bw_gran_show(struct kernfs_open_file *of, + static int rdt_delay_linear_show(struct kernfs_open_file *of, + struct seq_file *seq, void *v) + { +- struct resctrl_schema *s = of->kn->parent->priv; ++ struct resctrl_schema *s = rdt_kn_parent_priv(of->kn); + struct rdt_resource *r = s->res; + + seq_printf(seq, "%u\n", r->membw.delay_linear); +@@ -1158,7 +1168,7 @@ static int max_threshold_occ_show(struct kernfs_open_file *of, + static int rdt_thread_throttle_mode_show(struct kernfs_open_file *of, + struct seq_file *seq, void *v) + { +- struct resctrl_schema *s = of->kn->parent->priv; ++ struct resctrl_schema *s = rdt_kn_parent_priv(of->kn); + struct rdt_resource *r = s->res; + + if (r->membw.throttle_mode == THREAD_THROTTLE_PER_THREAD) +@@ -1223,7 +1233,7 @@ static enum resctrl_conf_type resctrl_peer_type(enum resctrl_conf_type my_type) + static int rdt_has_sparse_bitmasks_show(struct kernfs_open_file *of, + struct seq_file *seq, void *v) + { +- struct resctrl_schema *s = of->kn->parent->priv; ++ struct resctrl_schema *s = rdt_kn_parent_priv(of->kn); + struct rdt_resource *r = s->res; + + seq_printf(seq, "%u\n", r->cache.arch_has_sparse_bitmasks); +@@ -1635,7 +1645,7 @@ static int mbm_config_show(struct seq_file *s, struct rdt_resource *r, u32 evtid + static int mbm_total_bytes_config_show(struct kernfs_open_file *of, + struct seq_file *seq, void *v) + { +- struct rdt_resource *r = of->kn->parent->priv; ++ struct rdt_resource *r = rdt_kn_parent_priv(of->kn); + + mbm_config_show(seq, r, QOS_L3_MBM_TOTAL_EVENT_ID); + +@@ -1645,7 +1655,7 @@ static int mbm_total_bytes_config_show(struct kernfs_open_file *of, + static int mbm_local_bytes_config_show(struct kernfs_open_file *of, + struct seq_file *seq, void *v) + { +- struct rdt_resource *r = of->kn->parent->priv; ++ struct rdt_resource *r = rdt_kn_parent_priv(of->kn); + + mbm_config_show(seq, r, QOS_L3_MBM_LOCAL_EVENT_ID); + +@@ -1751,7 +1761,7 @@ static ssize_t mbm_total_bytes_config_write(struct kernfs_open_file *of, + char *buf, size_t nbytes, + loff_t off) + { +- struct rdt_resource *r = of->kn->parent->priv; ++ struct rdt_resource *r = rdt_kn_parent_priv(of->kn); + int ret; + + /* Valid input requires a trailing newline */ +@@ -1777,7 +1787,7 @@ static ssize_t mbm_local_bytes_config_write(struct kernfs_open_file *of, + char *buf, size_t nbytes, + loff_t off) + { +- struct rdt_resource *r = of->kn->parent->priv; ++ struct rdt_resource *r = rdt_kn_parent_priv(of->kn); + int ret; + + /* Valid input requires a trailing newline */ +@@ -2441,12 +2451,13 @@ static struct rdtgroup *kernfs_to_rdtgroup(struct kernfs_node *kn) + * resource. "info" and its subdirectories don't + * have rdtgroup structures, so return NULL here. + */ +- if (kn == kn_info || kn->parent == kn_info) ++ if (kn == kn_info || ++ rcu_access_pointer(kn->__parent) == kn_info) + return NULL; + else + return kn->priv; + } else { +- return kn->parent->priv; ++ return rdt_kn_parent_priv(kn); + } + } + +@@ -3772,9 +3783,18 @@ static int rdtgroup_rmdir_ctrl(struct rdtgroup *rdtgrp, cpumask_var_t tmpmask) + return 0; + } + ++static struct kernfs_node *rdt_kn_parent(struct kernfs_node *kn) ++{ ++ /* ++ * Valid within the RCU section it was obtained or while rdtgroup_mutex ++ * is held. ++ */ ++ return rcu_dereference_check(kn->__parent, lockdep_is_held(&rdtgroup_mutex)); ++} ++ + static int rdtgroup_rmdir(struct kernfs_node *kn) + { +- struct kernfs_node *parent_kn = kn->parent; ++ struct kernfs_node *parent_kn; + struct rdtgroup *rdtgrp; + cpumask_var_t tmpmask; + int ret = 0; +@@ -3787,6 +3807,7 @@ static int rdtgroup_rmdir(struct kernfs_node *kn) + ret = -EPERM; + goto out; + } ++ parent_kn = rdt_kn_parent(kn); + + /* + * If the rdtgroup is a ctrl_mon group and parent directory +@@ -3855,6 +3876,7 @@ static void mongrp_reparent(struct rdtgroup *rdtgrp, + static int rdtgroup_rename(struct kernfs_node *kn, + struct kernfs_node *new_parent, const char *new_name) + { ++ struct kernfs_node *kn_parent; + struct rdtgroup *new_prdtgrp; + struct rdtgroup *rdtgrp; + cpumask_var_t tmpmask; +@@ -3889,8 +3911,9 @@ static int rdtgroup_rename(struct kernfs_node *kn, + goto out; + } + +- if (rdtgrp->type != RDTMON_GROUP || !kn->parent || +- !is_mon_groups(kn->parent, kn->name)) { ++ kn_parent = rdt_kn_parent(kn); ++ if (rdtgrp->type != RDTMON_GROUP || !kn_parent || ++ !is_mon_groups(kn_parent, kn->name)) { + rdt_last_cmd_puts("Source must be a MON group\n"); + ret = -EPERM; + goto out; +diff --git a/fs/kernfs/dir.c b/fs/kernfs/dir.c +index 43fbada678381..1d370c497e8a3 100644 +--- a/fs/kernfs/dir.c ++++ b/fs/kernfs/dir.c +@@ -17,7 +17,7 @@ + + #include "kernfs-internal.h" + +-static DEFINE_RWLOCK(kernfs_rename_lock); /* kn->parent and ->name */ ++DEFINE_RWLOCK(kernfs_rename_lock); /* kn->parent and ->name */ + /* + * Don't use rename_lock to piggy back on pr_cont_buf. We don't want to + * call pr_cont() while holding rename_lock. Because sometimes pr_cont() +@@ -56,7 +56,7 @@ static int kernfs_name_locked(struct kernfs_node *kn, char *buf, size_t buflen) + if (!kn) + return strscpy(buf, "(null)", buflen); + +- return strscpy(buf, kn->parent ? kn->name : "/", buflen); ++ return strscpy(buf, rcu_access_pointer(kn->__parent) ? kn->name : "/", buflen); + } + + /* kernfs_node_depth - compute depth from @from to @to */ +@@ -64,9 +64,9 @@ static size_t kernfs_depth(struct kernfs_node *from, struct kernfs_node *to) + { + size_t depth = 0; + +- while (to->parent && to != from) { ++ while (rcu_dereference(to->__parent) && to != from) { + depth++; +- to = to->parent; ++ to = rcu_dereference(to->__parent); + } + return depth; + } +@@ -84,18 +84,18 @@ static struct kernfs_node *kernfs_common_ancestor(struct kernfs_node *a, + db = kernfs_depth(rb->kn, b); + + while (da > db) { +- a = a->parent; ++ a = rcu_dereference(a->__parent); + da--; + } + while (db > da) { +- b = b->parent; ++ b = rcu_dereference(b->__parent); + db--; + } + + /* worst case b and a will be the same at root */ + while (b != a) { +- b = b->parent; +- a = a->parent; ++ b = rcu_dereference(b->__parent); ++ a = rcu_dereference(a->__parent); + } + + return a; +@@ -168,8 +168,9 @@ static int kernfs_path_from_node_locked(struct kernfs_node *kn_to, + + /* Calculate how many bytes we need for the rest */ + for (i = depth_to - 1; i >= 0; i--) { ++ + for (kn = kn_to, j = 0; j < i; j++) +- kn = kn->parent; ++ kn = rcu_dereference(kn->__parent); + + len += scnprintf(buf + len, buflen - len, "/%s", kn->name); + } +@@ -226,6 +227,7 @@ int kernfs_path_from_node(struct kernfs_node *to, struct kernfs_node *from, + unsigned long flags; + int ret; + ++ guard(rcu)(); + read_lock_irqsave(&kernfs_rename_lock, flags); + ret = kernfs_path_from_node_locked(to, from, buf, buflen); + read_unlock_irqrestore(&kernfs_rename_lock, flags); +@@ -295,7 +297,7 @@ struct kernfs_node *kernfs_get_parent(struct kernfs_node *kn) + unsigned long flags; + + read_lock_irqsave(&kernfs_rename_lock, flags); +- parent = kn->parent; ++ parent = kernfs_parent(kn); + kernfs_get(parent); + read_unlock_irqrestore(&kernfs_rename_lock, flags); + +@@ -360,8 +362,12 @@ static int kernfs_sd_compare(const struct kernfs_node *left, + */ + static int kernfs_link_sibling(struct kernfs_node *kn) + { +- struct rb_node **node = &kn->parent->dir.children.rb_node; + struct rb_node *parent = NULL; ++ struct kernfs_node *kn_parent; ++ struct rb_node **node; ++ ++ kn_parent = kernfs_parent(kn); ++ node = &kn_parent->dir.children.rb_node; + + while (*node) { + struct kernfs_node *pos; +@@ -380,13 +386,13 @@ static int kernfs_link_sibling(struct kernfs_node *kn) + + /* add new node and rebalance the tree */ + rb_link_node(&kn->rb, parent, node); +- rb_insert_color(&kn->rb, &kn->parent->dir.children); ++ rb_insert_color(&kn->rb, &kn_parent->dir.children); + + /* successfully added, account subdir number */ + down_write(&kernfs_root(kn)->kernfs_iattr_rwsem); + if (kernfs_type(kn) == KERNFS_DIR) +- kn->parent->dir.subdirs++; +- kernfs_inc_rev(kn->parent); ++ kn_parent->dir.subdirs++; ++ kernfs_inc_rev(kn_parent); + up_write(&kernfs_root(kn)->kernfs_iattr_rwsem); + + return 0; +@@ -407,16 +413,19 @@ static int kernfs_link_sibling(struct kernfs_node *kn) + */ + static bool kernfs_unlink_sibling(struct kernfs_node *kn) + { ++ struct kernfs_node *kn_parent; ++ + if (RB_EMPTY_NODE(&kn->rb)) + return false; + ++ kn_parent = kernfs_parent(kn); + down_write(&kernfs_root(kn)->kernfs_iattr_rwsem); + if (kernfs_type(kn) == KERNFS_DIR) +- kn->parent->dir.subdirs--; +- kernfs_inc_rev(kn->parent); ++ kn_parent->dir.subdirs--; ++ kernfs_inc_rev(kn_parent); + up_write(&kernfs_root(kn)->kernfs_iattr_rwsem); + +- rb_erase(&kn->rb, &kn->parent->dir.children); ++ rb_erase(&kn->rb, &kn_parent->dir.children); + RB_CLEAR_NODE(&kn->rb); + return true; + } +@@ -562,7 +571,7 @@ void kernfs_put(struct kernfs_node *kn) + * Moving/renaming is always done while holding reference. + * kn->parent won't change beneath us. + */ +- parent = kn->parent; ++ parent = kernfs_parent(kn); + + WARN_ONCE(atomic_read(&kn->active) != KN_DEACTIVATED_BIAS, + "kernfs_put: %s/%s: released with incorrect active_ref %d\n", +@@ -701,7 +710,7 @@ struct kernfs_node *kernfs_new_node(struct kernfs_node *parent, + name, mode, uid, gid, flags); + if (kn) { + kernfs_get(parent); +- kn->parent = parent; ++ rcu_assign_pointer(kn->__parent, parent); + } + return kn; + } +@@ -769,13 +778,14 @@ struct kernfs_node *kernfs_find_and_get_node_by_id(struct kernfs_root *root, + */ + int kernfs_add_one(struct kernfs_node *kn) + { +- struct kernfs_node *parent = kn->parent; +- struct kernfs_root *root = kernfs_root(parent); ++ struct kernfs_root *root = kernfs_root(kn); + struct kernfs_iattrs *ps_iattr; ++ struct kernfs_node *parent; + bool has_ns; + int ret; + + down_write(&root->kernfs_rwsem); ++ parent = kernfs_parent(kn); + + ret = -EINVAL; + has_ns = kernfs_ns_enabled(parent); +@@ -949,6 +959,11 @@ struct kernfs_node *kernfs_walk_and_get_ns(struct kernfs_node *parent, + return kn; + } + ++unsigned int kernfs_root_flags(struct kernfs_node *kn) ++{ ++ return kernfs_root(kn)->flags; ++} ++ + /** + * kernfs_create_root - create a new kernfs hierarchy + * @scops: optional syscall operations for the hierarchy +@@ -1112,7 +1127,7 @@ struct kernfs_node *kernfs_create_empty_dir(struct kernfs_node *parent, + static int kernfs_dop_revalidate(struct inode *dir, const struct qstr *name, + struct dentry *dentry, unsigned int flags) + { +- struct kernfs_node *kn; ++ struct kernfs_node *kn, *parent; + struct kernfs_root *root; + + if (flags & LOOKUP_RCU) +@@ -1163,8 +1178,9 @@ static int kernfs_dop_revalidate(struct inode *dir, const struct qstr *name, + if (!kernfs_active(kn)) + goto out_bad; + ++ parent = kernfs_parent(kn); + /* The kernfs node has been moved? */ +- if (kernfs_dentry_node(dentry->d_parent) != kn->parent) ++ if (kernfs_dentry_node(dentry->d_parent) != parent) + goto out_bad; + + /* The kernfs node has been renamed */ +@@ -1172,7 +1188,7 @@ static int kernfs_dop_revalidate(struct inode *dir, const struct qstr *name, + goto out_bad; + + /* The kernfs node has been moved to a different namespace */ +- if (kn->parent && kernfs_ns_enabled(kn->parent) && ++ if (parent && kernfs_ns_enabled(parent) && + kernfs_info(dentry->d_sb)->ns != kn->ns) + goto out_bad; + +@@ -1365,7 +1381,7 @@ static struct kernfs_node *kernfs_next_descendant_post(struct kernfs_node *pos, + return kernfs_leftmost_descendant(rb_to_kn(rbn)); + + /* no sibling left, visit parent */ +- return pos->parent; ++ return kernfs_parent(pos); + } + + static void kernfs_activate_one(struct kernfs_node *kn) +@@ -1377,7 +1393,7 @@ static void kernfs_activate_one(struct kernfs_node *kn) + if (kernfs_active(kn) || (kn->flags & (KERNFS_HIDDEN | KERNFS_REMOVING))) + return; + +- WARN_ON_ONCE(kn->parent && RB_EMPTY_NODE(&kn->rb)); ++ WARN_ON_ONCE(rcu_access_pointer(kn->__parent) && RB_EMPTY_NODE(&kn->rb)); + WARN_ON_ONCE(atomic_read(&kn->active) != KN_DEACTIVATED_BIAS); + + atomic_sub(KN_DEACTIVATED_BIAS, &kn->active); +@@ -1447,7 +1463,7 @@ void kernfs_show(struct kernfs_node *kn, bool show) + + static void __kernfs_remove(struct kernfs_node *kn) + { +- struct kernfs_node *pos; ++ struct kernfs_node *pos, *parent; + + /* Short-circuit if non-root @kn has already finished removal. */ + if (!kn) +@@ -1459,7 +1475,7 @@ static void __kernfs_remove(struct kernfs_node *kn) + * This is for kernfs_remove_self() which plays with active ref + * after removal. + */ +- if (kn->parent && RB_EMPTY_NODE(&kn->rb)) ++ if (kernfs_parent(kn) && RB_EMPTY_NODE(&kn->rb)) + return; + + pr_debug("kernfs %s: removing\n", kn->name); +@@ -1485,14 +1501,14 @@ static void __kernfs_remove(struct kernfs_node *kn) + kernfs_get(pos); + + kernfs_drain(pos); +- ++ parent = kernfs_parent(pos); + /* + * kernfs_unlink_sibling() succeeds once per node. Use it + * to decide who's responsible for cleanups. + */ +- if (!pos->parent || kernfs_unlink_sibling(pos)) { ++ if (!parent || kernfs_unlink_sibling(pos)) { + struct kernfs_iattrs *ps_iattr = +- pos->parent ? pos->parent->iattr : NULL; ++ parent ? parent->iattr : NULL; + + /* update timestamps on the parent */ + down_write(&kernfs_root(kn)->kernfs_iattr_rwsem); +@@ -1722,7 +1738,7 @@ int kernfs_rename_ns(struct kernfs_node *kn, struct kernfs_node *new_parent, + int error; + + /* can't move or rename root */ +- if (!kn->parent) ++ if (!rcu_access_pointer(kn->__parent)) + return -EINVAL; + + root = kernfs_root(kn); +@@ -1733,8 +1749,15 @@ int kernfs_rename_ns(struct kernfs_node *kn, struct kernfs_node *new_parent, + (new_parent->flags & KERNFS_EMPTY_DIR)) + goto out; + ++ old_parent = kernfs_parent(kn); ++ if (root->flags & KERNFS_ROOT_INVARIANT_PARENT) { ++ error = -EINVAL; ++ if (WARN_ON_ONCE(old_parent != new_parent)) ++ goto out; ++ } ++ + error = 0; +- if ((kn->parent == new_parent) && (kn->ns == new_ns) && ++ if ((old_parent == new_parent) && (kn->ns == new_ns) && + (strcmp(kn->name, new_name) == 0)) + goto out; /* nothing to rename */ + +@@ -1761,8 +1784,8 @@ int kernfs_rename_ns(struct kernfs_node *kn, struct kernfs_node *new_parent, + /* rename_lock protects ->parent and ->name accessors */ + write_lock_irq(&kernfs_rename_lock); + +- old_parent = kn->parent; +- kn->parent = new_parent; ++ old_parent = kernfs_parent(kn); ++ rcu_assign_pointer(kn->__parent, new_parent); + + kn->ns = new_ns; + if (new_name) { +@@ -1795,7 +1818,8 @@ static struct kernfs_node *kernfs_dir_pos(const void *ns, + { + if (pos) { + int valid = kernfs_active(pos) && +- pos->parent == parent && hash == pos->hash; ++ rcu_access_pointer(pos->__parent) == parent && ++ hash == pos->hash; + kernfs_put(pos); + if (!valid) + pos = NULL; +diff --git a/fs/kernfs/kernfs-internal.h b/fs/kernfs/kernfs-internal.h +index b42ee6547cdc1..c43bee18b79f7 100644 +--- a/fs/kernfs/kernfs-internal.h ++++ b/fs/kernfs/kernfs-internal.h +@@ -19,6 +19,8 @@ + #include + #include + ++extern rwlock_t kernfs_rename_lock; ++ + struct kernfs_iattrs { + kuid_t ia_uid; + kgid_t ia_gid; +@@ -64,11 +66,14 @@ struct kernfs_root { + * + * Return: the kernfs_root @kn belongs to. + */ +-static inline struct kernfs_root *kernfs_root(struct kernfs_node *kn) ++static inline struct kernfs_root *kernfs_root(const struct kernfs_node *kn) + { ++ const struct kernfs_node *knp; + /* if parent exists, it's always a dir; otherwise, @sd is a dir */ +- if (kn->parent) +- kn = kn->parent; ++ guard(rcu)(); ++ knp = rcu_dereference(kn->__parent); ++ if (knp) ++ kn = knp; + return kn->dir.root; + } + +@@ -97,6 +102,27 @@ struct kernfs_super_info { + }; + #define kernfs_info(SB) ((struct kernfs_super_info *)(SB->s_fs_info)) + ++static inline bool kernfs_root_is_locked(const struct kernfs_node *kn) ++{ ++ return lockdep_is_held(&kernfs_root(kn)->kernfs_rwsem); ++} ++ ++static inline struct kernfs_node *kernfs_parent(const struct kernfs_node *kn) ++{ ++ /* ++ * The kernfs_node::__parent remains valid within a RCU section. The kn ++ * can be reparented (and renamed) which changes the entry. This can be ++ * avoided by locking kernfs_root::kernfs_rwsem or kernfs_rename_lock. ++ * Both locks can be used to obtain a reference on __parent. Once the ++ * reference count reaches 0 then the node is about to be freed ++ * and can not be renamed (or become a different parent) anymore. ++ */ ++ return rcu_dereference_check(kn->__parent, ++ kernfs_root_is_locked(kn) || ++ lockdep_is_held(&kernfs_rename_lock) || ++ !atomic_read(&kn->count)); ++} ++ + static inline struct kernfs_node *kernfs_dentry_node(struct dentry *dentry) + { + if (d_really_is_negative(dentry)) +diff --git a/fs/kernfs/mount.c b/fs/kernfs/mount.c +index 4a0ff08d589ca..2252b16e6ef0b 100644 +--- a/fs/kernfs/mount.c ++++ b/fs/kernfs/mount.c +@@ -148,7 +148,7 @@ static struct dentry *kernfs_get_parent_dentry(struct dentry *child) + struct kernfs_root *root = kernfs_root(kn); + + guard(rwsem_read)(&root->kernfs_rwsem); +- return d_obtain_alias(kernfs_get_inode(child->d_sb, kn->parent)); ++ return d_obtain_alias(kernfs_get_inode(child->d_sb, kernfs_parent(kn))); + } + + static const struct export_operations kernfs_export_ops = { +@@ -188,10 +188,10 @@ static struct kernfs_node *find_next_ancestor(struct kernfs_node *child, + return NULL; + } + +- while (child->parent != parent) { +- if (!child->parent) ++ while (kernfs_parent(child) != parent) { ++ child = kernfs_parent(child); ++ if (!child) + return NULL; +- child = child->parent; + } + + return child; +@@ -216,7 +216,7 @@ struct dentry *kernfs_node_dentry(struct kernfs_node *kn, + dentry = dget(sb->s_root); + + /* Check if this is the root kernfs_node */ +- if (!kn->parent) ++ if (!rcu_access_pointer(kn->__parent)) + return dentry; + + root = kernfs_root(kn); +diff --git a/fs/kernfs/symlink.c b/fs/kernfs/symlink.c +index 45371a70caa71..05c62ca93c53d 100644 +--- a/fs/kernfs/symlink.c ++++ b/fs/kernfs/symlink.c +@@ -62,10 +62,10 @@ static int kernfs_get_target_path(struct kernfs_node *parent, + + /* go up to the root, stop at the base */ + base = parent; +- while (base->parent) { +- kn = target->parent; +- while (kn->parent && base != kn) +- kn = kn->parent; ++ while (kernfs_parent(base)) { ++ kn = kernfs_parent(target); ++ while (kernfs_parent(kn) && base != kn) ++ kn = kernfs_parent(kn); + + if (base == kn) + break; +@@ -75,14 +75,14 @@ static int kernfs_get_target_path(struct kernfs_node *parent, + + strcpy(s, "../"); + s += 3; +- base = base->parent; ++ base = kernfs_parent(base); + } + + /* determine end of target string for reverse fillup */ + kn = target; +- while (kn->parent && kn != base) { ++ while (kernfs_parent(kn) && kn != base) { + len += strlen(kn->name) + 1; +- kn = kn->parent; ++ kn = kernfs_parent(kn); + } + + /* check limits */ +@@ -94,7 +94,7 @@ static int kernfs_get_target_path(struct kernfs_node *parent, + + /* reverse fillup of target string from target to base */ + kn = target; +- while (kn->parent && kn != base) { ++ while (kernfs_parent(kn) && kn != base) { + int slen = strlen(kn->name); + + len -= slen; +@@ -102,7 +102,7 @@ static int kernfs_get_target_path(struct kernfs_node *parent, + if (len) + s[--len] = '/'; + +- kn = kn->parent; ++ kn = kernfs_parent(kn); + } + + return 0; +@@ -111,12 +111,13 @@ static int kernfs_get_target_path(struct kernfs_node *parent, + static int kernfs_getlink(struct inode *inode, char *path) + { + struct kernfs_node *kn = inode->i_private; +- struct kernfs_node *parent = kn->parent; ++ struct kernfs_node *parent; + struct kernfs_node *target = kn->symlink.target_kn; +- struct kernfs_root *root = kernfs_root(parent); ++ struct kernfs_root *root = kernfs_root(kn); + int error; + + down_read(&root->kernfs_rwsem); ++ parent = kernfs_parent(kn); + error = kernfs_get_target_path(parent, target, path); + up_read(&root->kernfs_rwsem); + +diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c +index 6931308876c4a..c3d3b079aedde 100644 +--- a/fs/sysfs/file.c ++++ b/fs/sysfs/file.c +@@ -19,13 +19,19 @@ + + #include "sysfs.h" + ++static struct kobject *sysfs_file_kobj(struct kernfs_node *kn) ++{ ++ guard(rcu)(); ++ return rcu_dereference(kn->__parent)->priv; ++} ++ + /* + * Determine ktype->sysfs_ops for the given kernfs_node. This function + * must be called while holding an active reference. + */ + static const struct sysfs_ops *sysfs_file_ops(struct kernfs_node *kn) + { +- struct kobject *kobj = kn->parent->priv; ++ struct kobject *kobj = sysfs_file_kobj(kn); + + if (kn->flags & KERNFS_LOCKDEP) + lockdep_assert_held(kn); +@@ -40,7 +46,7 @@ static const struct sysfs_ops *sysfs_file_ops(struct kernfs_node *kn) + static int sysfs_kf_seq_show(struct seq_file *sf, void *v) + { + struct kernfs_open_file *of = sf->private; +- struct kobject *kobj = of->kn->parent->priv; ++ struct kobject *kobj = sysfs_file_kobj(of->kn); + const struct sysfs_ops *ops = sysfs_file_ops(of->kn); + ssize_t count; + char *buf; +@@ -78,7 +84,7 @@ static ssize_t sysfs_kf_bin_read(struct kernfs_open_file *of, char *buf, + size_t count, loff_t pos) + { + struct bin_attribute *battr = of->kn->priv; +- struct kobject *kobj = of->kn->parent->priv; ++ struct kobject *kobj = sysfs_file_kobj(of->kn); + loff_t size = file_inode(of->file)->i_size; + + if (!count) +@@ -105,7 +111,7 @@ static ssize_t sysfs_kf_read(struct kernfs_open_file *of, char *buf, + size_t count, loff_t pos) + { + const struct sysfs_ops *ops = sysfs_file_ops(of->kn); +- struct kobject *kobj = of->kn->parent->priv; ++ struct kobject *kobj = sysfs_file_kobj(of->kn); + ssize_t len; + + /* +@@ -131,7 +137,7 @@ static ssize_t sysfs_kf_write(struct kernfs_open_file *of, char *buf, + size_t count, loff_t pos) + { + const struct sysfs_ops *ops = sysfs_file_ops(of->kn); +- struct kobject *kobj = of->kn->parent->priv; ++ struct kobject *kobj = sysfs_file_kobj(of->kn); + + if (!count) + return 0; +@@ -144,7 +150,7 @@ static ssize_t sysfs_kf_bin_write(struct kernfs_open_file *of, char *buf, + size_t count, loff_t pos) + { + struct bin_attribute *battr = of->kn->priv; +- struct kobject *kobj = of->kn->parent->priv; ++ struct kobject *kobj = sysfs_file_kobj(of->kn); + loff_t size = file_inode(of->file)->i_size; + + if (size) { +@@ -168,7 +174,7 @@ static int sysfs_kf_bin_mmap(struct kernfs_open_file *of, + struct vm_area_struct *vma) + { + struct bin_attribute *battr = of->kn->priv; +- struct kobject *kobj = of->kn->parent->priv; ++ struct kobject *kobj = sysfs_file_kobj(of->kn); + + return battr->mmap(of->file, kobj, battr, vma); + } +@@ -177,7 +183,7 @@ static loff_t sysfs_kf_bin_llseek(struct kernfs_open_file *of, loff_t offset, + int whence) + { + struct bin_attribute *battr = of->kn->priv; +- struct kobject *kobj = of->kn->parent->priv; ++ struct kobject *kobj = sysfs_file_kobj(of->kn); + + if (battr->llseek) + return battr->llseek(of->file, kobj, battr, offset, whence); +@@ -494,7 +500,7 @@ EXPORT_SYMBOL_GPL(sysfs_break_active_protection); + */ + void sysfs_unbreak_active_protection(struct kernfs_node *kn) + { +- struct kobject *kobj = kn->parent->priv; ++ struct kobject *kobj = sysfs_file_kobj(kn); + + kernfs_unbreak_active_protection(kn); + kernfs_put(kn); +diff --git a/include/linux/kernfs.h b/include/linux/kernfs.h +index 87c79d076d6d7..5dda9a268e44c 100644 +--- a/include/linux/kernfs.h ++++ b/include/linux/kernfs.h +@@ -147,6 +147,11 @@ enum kernfs_root_flag { + * Support user xattrs to be written to nodes rooted at this root. + */ + KERNFS_ROOT_SUPPORT_USER_XATTR = 0x0008, ++ ++ /* ++ * Renames must not change the parent node. ++ */ ++ KERNFS_ROOT_INVARIANT_PARENT = 0x0010, + }; + + /* type-specific structures for kernfs_node union members */ +@@ -199,8 +204,8 @@ struct kernfs_node { + * never moved to a different parent, it is safe to access the + * parent directly. + */ +- struct kernfs_node *parent; + const char *name; ++ struct kernfs_node __rcu *__parent; + + struct rb_node rb; + +@@ -416,6 +421,7 @@ struct dentry *kernfs_node_dentry(struct kernfs_node *kn, + struct kernfs_root *kernfs_create_root(struct kernfs_syscall_ops *scops, + unsigned int flags, void *priv); + void kernfs_destroy_root(struct kernfs_root *root); ++unsigned int kernfs_root_flags(struct kernfs_node *kn); + + struct kernfs_node *kernfs_create_dir_ns(struct kernfs_node *parent, + const char *name, umode_t mode, +@@ -514,6 +520,8 @@ kernfs_create_root(struct kernfs_syscall_ops *scops, unsigned int flags, + { return ERR_PTR(-ENOSYS); } + + static inline void kernfs_destroy_root(struct kernfs_root *root) { } ++static inline unsigned int kernfs_root_flags(struct kernfs_node *kn) ++{ return 0; } + + static inline struct kernfs_node * + kernfs_create_dir_ns(struct kernfs_node *parent, const char *name, +diff --git a/kernel/cgroup/cgroup-v1.c b/kernel/cgroup/cgroup-v1.c +index e28d5f0d20ed0..c9752eb607ec9 100644 +--- a/kernel/cgroup/cgroup-v1.c ++++ b/kernel/cgroup/cgroup-v1.c +@@ -844,7 +844,7 @@ static int cgroup1_rename(struct kernfs_node *kn, struct kernfs_node *new_parent + + if (kernfs_type(kn) != KERNFS_DIR) + return -ENOTDIR; +- if (kn->parent != new_parent) ++ if (rcu_access_pointer(kn->__parent) != new_parent) + return -EIO; + + /* +diff --git a/kernel/cgroup/cgroup.c b/kernel/cgroup/cgroup.c +index 660d27a0cb3d4..1e2bc9f74fe29 100644 +--- a/kernel/cgroup/cgroup.c ++++ b/kernel/cgroup/cgroup.c +@@ -633,9 +633,22 @@ int cgroup_task_count(const struct cgroup *cgrp) + return count; + } + ++static struct cgroup *kn_priv(struct kernfs_node *kn) ++{ ++ struct kernfs_node *parent; ++ /* ++ * The parent can not be replaced due to KERNFS_ROOT_INVARIANT_PARENT. ++ * Therefore it is always safe to dereference this pointer outside of a ++ * RCU section. ++ */ ++ parent = rcu_dereference_check(kn->__parent, ++ kernfs_root_flags(kn) & KERNFS_ROOT_INVARIANT_PARENT); ++ return parent->priv; ++} ++ + struct cgroup_subsys_state *of_css(struct kernfs_open_file *of) + { +- struct cgroup *cgrp = of->kn->parent->priv; ++ struct cgroup *cgrp = kn_priv(of->kn); + struct cftype *cft = of_cft(of); + + /* +@@ -1612,7 +1625,7 @@ void cgroup_kn_unlock(struct kernfs_node *kn) + if (kernfs_type(kn) == KERNFS_DIR) + cgrp = kn->priv; + else +- cgrp = kn->parent->priv; ++ cgrp = kn_priv(kn); + + cgroup_unlock(); + +@@ -1644,7 +1657,7 @@ struct cgroup *cgroup_kn_lock_live(struct kernfs_node *kn, bool drain_offline) + if (kernfs_type(kn) == KERNFS_DIR) + cgrp = kn->priv; + else +- cgrp = kn->parent->priv; ++ cgrp = kn_priv(kn); + + /* + * We're gonna grab cgroup_mutex which nests outside kernfs +@@ -2118,7 +2131,8 @@ int cgroup_setup_root(struct cgroup_root *root, u16 ss_mask) + root->kf_root = kernfs_create_root(kf_sops, + KERNFS_ROOT_CREATE_DEACTIVATED | + KERNFS_ROOT_SUPPORT_EXPORTOP | +- KERNFS_ROOT_SUPPORT_USER_XATTR, ++ KERNFS_ROOT_SUPPORT_USER_XATTR | ++ KERNFS_ROOT_INVARIANT_PARENT, + root_cgrp); + if (IS_ERR(root->kf_root)) { + ret = PTR_ERR(root->kf_root); +@@ -4144,7 +4158,7 @@ static ssize_t cgroup_file_write(struct kernfs_open_file *of, char *buf, + size_t nbytes, loff_t off) + { + struct cgroup_file_ctx *ctx = of->priv; +- struct cgroup *cgrp = of->kn->parent->priv; ++ struct cgroup *cgrp = kn_priv(of->kn); + struct cftype *cft = of_cft(of); + struct cgroup_subsys_state *css; + int ret; +diff --git a/tools/testing/selftests/bpf/progs/profiler.inc.h b/tools/testing/selftests/bpf/progs/profiler.inc.h +index 8bd1ebd7d6afd..813143b4985dc 100644 +--- a/tools/testing/selftests/bpf/progs/profiler.inc.h ++++ b/tools/testing/selftests/bpf/progs/profiler.inc.h +@@ -223,7 +223,7 @@ static INLINE void* read_full_cgroup_path(struct kernfs_node* cgroup_node, + if (bpf_cmp_likely(filepart_length, <=, MAX_PATH)) { + payload += filepart_length; + } +- cgroup_node = BPF_CORE_READ(cgroup_node, parent); ++ cgroup_node = BPF_CORE_READ(cgroup_node, __parent); + } + return payload; + } +-- +2.39.5 + diff --git a/queue-6.14/kunit-tool-fix-bug-in-parsing-test-plan.patch b/queue-6.14/kunit-tool-fix-bug-in-parsing-test-plan.patch new file mode 100644 index 0000000000..3c05cd5067 --- /dev/null +++ b/queue-6.14/kunit-tool-fix-bug-in-parsing-test-plan.patch @@ -0,0 +1,62 @@ +From 1aeee13f00992342bd96176b6fcd3728c7ce23ab Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 13 Mar 2025 19:27:13 +0000 +Subject: kunit: tool: Fix bug in parsing test plan + +From: Rae Moar + +[ Upstream commit 1d4c06d51963f89f67c7b75d5c0c34e9d1bb2ae6 ] + +A bug was identified where the KTAP below caused an infinite loop: + + TAP version 13 + ok 4 test_case + 1..4 + +The infinite loop was caused by the parser not parsing a test plan +if following a test result line. + +Fix this bug by parsing test plan line to avoid the infinite loop. + +Link: https://lore.kernel.org/r/20250313192714.1380005-1-rmoar@google.com +Signed-off-by: Rae Moar +Reviewed-by: David Gow +Signed-off-by: Shuah Khan +Signed-off-by: Sasha Levin +--- + tools/testing/kunit/kunit_parser.py | 9 ++++----- + 1 file changed, 4 insertions(+), 5 deletions(-) + +diff --git a/tools/testing/kunit/kunit_parser.py b/tools/testing/kunit/kunit_parser.py +index 29fc27e8949bd..da53a709773a2 100644 +--- a/tools/testing/kunit/kunit_parser.py ++++ b/tools/testing/kunit/kunit_parser.py +@@ -759,7 +759,7 @@ def parse_test(lines: LineStream, expected_num: int, log: List[str], is_subtest: + # If parsing the main/top-level test, parse KTAP version line and + # test plan + test.name = "main" +- ktap_line = parse_ktap_header(lines, test, printer) ++ parse_ktap_header(lines, test, printer) + test.log.extend(parse_diagnostic(lines)) + parse_test_plan(lines, test) + parent_test = True +@@ -768,13 +768,12 @@ def parse_test(lines: LineStream, expected_num: int, log: List[str], is_subtest: + # the KTAP version line and/or subtest header line + ktap_line = parse_ktap_header(lines, test, printer) + subtest_line = parse_test_header(lines, test) ++ test.log.extend(parse_diagnostic(lines)) ++ parse_test_plan(lines, test) + parent_test = (ktap_line or subtest_line) + if parent_test: +- # If KTAP version line and/or subtest header is found, attempt +- # to parse test plan and print test header +- test.log.extend(parse_diagnostic(lines)) +- parse_test_plan(lines, test) + print_test_header(test, printer) ++ + expected_count = test.expected_count + subtests = [] + test_num = 1 +-- +2.39.5 + diff --git a/queue-6.14/kunit-tool-use-qboot-on-qemu-x86_64.patch b/queue-6.14/kunit-tool-use-qboot-on-qemu-x86_64.patch new file mode 100644 index 0000000000..8401486435 --- /dev/null +++ b/queue-6.14/kunit-tool-use-qboot-on-qemu-x86_64.patch @@ -0,0 +1,46 @@ +From a95d9511a99ff5e66f65491232afeedcc6a1d827 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 24 Jan 2025 11:01:42 +0000 +Subject: kunit: tool: Use qboot on QEMU x86_64 + +From: Brendan Jackman + +[ Upstream commit 08fafac4c9f289a9d9a22d838921e4b3eb22c664 ] + +As noted in [0], SeaBIOS (QEMU default) makes a mess of the terminal, +qboot does not. + +It turns out this is actually useful with kunit.py, since the user is +exposed to this issue if they set --raw_output=all. + +qboot is also faster than SeaBIOS, but it's is marginal for this +usecase. + +[0] https://lore.kernel.org/all/CA+i-1C0wYb-gZ8Mwh3WSVpbk-LF-Uo+njVbASJPe1WXDURoV7A@mail.gmail.com/ + +Both SeaBIOS and qboot are x86-specific. + +Link: https://lore.kernel.org/r/20250124-kunit-qboot-v1-1-815e4d4c6f7c@google.com +Signed-off-by: Brendan Jackman +Reviewed-by: David Gow +Signed-off-by: Shuah Khan +Signed-off-by: Sasha Levin +--- + tools/testing/kunit/qemu_configs/x86_64.py | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/tools/testing/kunit/qemu_configs/x86_64.py b/tools/testing/kunit/qemu_configs/x86_64.py +index dc79490768630..4a6bf4e048f5b 100644 +--- a/tools/testing/kunit/qemu_configs/x86_64.py ++++ b/tools/testing/kunit/qemu_configs/x86_64.py +@@ -7,4 +7,6 @@ CONFIG_SERIAL_8250_CONSOLE=y''', + qemu_arch='x86_64', + kernel_path='arch/x86/boot/bzImage', + kernel_command_line='console=ttyS0', +- extra_qemu_params=[]) ++ # qboot is faster than SeaBIOS and doesn't mess up ++ # the terminal. ++ extra_qemu_params=['-bios', 'qboot.rom']) +-- +2.39.5 + diff --git a/queue-6.14/leds-kconfig-leds-st1202-add-select-for-required-led.patch b/queue-6.14/leds-kconfig-leds-st1202-add-select-for-required-led.patch new file mode 100644 index 0000000000..2fb1086cfc --- /dev/null +++ b/queue-6.14/leds-kconfig-leds-st1202-add-select-for-required-led.patch @@ -0,0 +1,52 @@ +From de40986e4d227334420ed2852ca69982f374d3ad Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 26 Feb 2025 17:12:50 +0000 +Subject: leds: Kconfig: leds-st1202: Add select for required + LEDS_TRIGGER_PATTERN + +From: Manuel Fombuena + +[ Upstream commit be2f92844d0f8cb059cb6958c6d9582d381ca68e ] + +leds-st1202 requires the LED Pattern Trigger (LEDS_TRIGGER_PATTERN), which +is not selected when LED Trigger support is (LEDS_TRIGGERS). + +To reproduce this: + +- make menuconfig KCONFIG_CONFIG= +- select LEDS_ST1202 dependencies OF, I2C and LEDS_CLASS. +- select LEDS_ST1202 +- LEDS_TRIGGERS is selected but LEDS_TRIGGER_PATTERN isn't. + +The absence of LEDS_TRIGGER_PATTERN explicitly required can lead to builds +in which LEDS_ST1202 is selected while LEDS_TRIGGER_PATTERN isn't. The direct +result of that would be that /sys/class/leds//hw_pattern wouldn't be +available and there would be no way of interacting with the driver and +hardware from user space. + +Add select LEDS_TRIGGER_PATTERN to Kconfig to meet the requirement and +indirectly document it as well. + +Signed-off-by: Manuel Fombuena +Link: https://lore.kernel.org/r/CWLP123MB5473F4DF3A668F7DD057A280C5C22@CWLP123MB5473.GBRP123.PROD.OUTLOOK.COM +Signed-off-by: Lee Jones +Signed-off-by: Sasha Levin +--- + drivers/leds/Kconfig | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig +index 2b27d043921ce..8859e8fe292a9 100644 +--- a/drivers/leds/Kconfig ++++ b/drivers/leds/Kconfig +@@ -971,6 +971,7 @@ config LEDS_ST1202 + depends on I2C + depends on OF + select LEDS_TRIGGERS ++ select LEDS_TRIGGER_PATTERN + help + Say Y to enable support for LEDs connected to LED1202 + LED driver chips accessed via the I2C bus. +-- +2.39.5 + diff --git a/queue-6.14/leds-leds-st1202-initialize-hardware-before-dt-node-.patch b/queue-6.14/leds-leds-st1202-initialize-hardware-before-dt-node-.patch new file mode 100644 index 0000000000..a76aaf0523 --- /dev/null +++ b/queue-6.14/leds-leds-st1202-initialize-hardware-before-dt-node-.patch @@ -0,0 +1,57 @@ +From 8c75dcdf583bcd389d4398eb3ab9e3ff87e4bedb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 26 Feb 2025 17:06:40 +0000 +Subject: leds: leds-st1202: Initialize hardware before DT node child + operations + +From: Manuel Fombuena + +[ Upstream commit a17d9e736ddd78323e77d3066c1e86371a99023c ] + +Arguably, there are more chances of errors occurring during the +initialization of the hardware, so this should complete successfully +before the devicetree node's children are initialized. + +st1202_dt_init() fills the led_classdev struct. + +st1202_setup() initializes the hardware. Specifically, resets the chip, +enables its phase-shift delay feature, enables the device and disables all +the LEDs channels. All that writing to registers, with no input from +st1202_dt_init(). + +Real-world testing corroborates that calling st1202_setup() before +st1202_dt_init() doesn't cause any issue during initialization. + +Switch the order of st1202_dt_init() and st1202_setup() to ensure the +hardware is correctly initialized before the led_classdev struct is +filled. + +Signed-off-by: Manuel Fombuena +Link: https://lore.kernel.org/r/CWLP123MB54731877A8DC54EDD33F0229C5C22@CWLP123MB5473.GBRP123.PROD.OUTLOOK.COM +Signed-off-by: Lee Jones +Signed-off-by: Sasha Levin +--- + drivers/leds/leds-st1202.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/leds/leds-st1202.c b/drivers/leds/leds-st1202.c +index 4cebc0203c227..ccea216c11f9b 100644 +--- a/drivers/leds/leds-st1202.c ++++ b/drivers/leds/leds-st1202.c +@@ -350,11 +350,11 @@ static int st1202_probe(struct i2c_client *client) + return ret; + chip->client = client; + +- ret = st1202_dt_init(chip); ++ ret = st1202_setup(chip); + if (ret < 0) + return ret; + +- ret = st1202_setup(chip); ++ ret = st1202_dt_init(chip); + if (ret < 0) + return ret; + +-- +2.39.5 + diff --git a/queue-6.14/leds-pwm-multicolor-add-check-for-fwnode_property_re.patch b/queue-6.14/leds-pwm-multicolor-add-check-for-fwnode_property_re.patch new file mode 100644 index 0000000000..0bd1cf1761 --- /dev/null +++ b/queue-6.14/leds-pwm-multicolor-add-check-for-fwnode_property_re.patch @@ -0,0 +1,40 @@ +From d87288cdf9580e775d65ab21d9e00589fbb8da43 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 23 Feb 2025 20:14:59 +0800 +Subject: leds: pwm-multicolor: Add check for fwnode_property_read_u32 + +From: Yuanjun Gong + +[ Upstream commit 6d91124e7edc109f114b1afe6d00d85d0d0ac174 ] + +Add a check to the return value of fwnode_property_read_u32() +in case it fails. + +Signed-off-by: Yuanjun Gong +Link: https://lore.kernel.org/r/20250223121459.2889484-1-ruc_gongyuanjun@163.com +Signed-off-by: Lee Jones +Signed-off-by: Sasha Levin +--- + drivers/leds/rgb/leds-pwm-multicolor.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/drivers/leds/rgb/leds-pwm-multicolor.c b/drivers/leds/rgb/leds-pwm-multicolor.c +index f80a06cc31f8a..1c7705bafdfc7 100644 +--- a/drivers/leds/rgb/leds-pwm-multicolor.c ++++ b/drivers/leds/rgb/leds-pwm-multicolor.c +@@ -141,8 +141,11 @@ static int led_pwm_mc_probe(struct platform_device *pdev) + + /* init the multicolor's LED class device */ + cdev = &priv->mc_cdev.led_cdev; +- fwnode_property_read_u32(mcnode, "max-brightness", ++ ret = fwnode_property_read_u32(mcnode, "max-brightness", + &cdev->max_brightness); ++ if (ret) ++ goto release_mcnode; ++ + cdev->flags = LED_CORE_SUSPENDRESUME; + cdev->brightness_set_blocking = led_pwm_mc_set; + +-- +2.39.5 + diff --git a/queue-6.14/leds-trigger-netdev-configure-led-blink-interval-for.patch b/queue-6.14/leds-trigger-netdev-configure-led-blink-interval-for.patch new file mode 100644 index 0000000000..741a4b2b88 --- /dev/null +++ b/queue-6.14/leds-trigger-netdev-configure-led-blink-interval-for.patch @@ -0,0 +1,84 @@ +From fd6258d20e37b52572d9668850bf6ae07f065b7f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 20 Jan 2025 12:36:53 +0100 +Subject: leds: trigger: netdev: Configure LED blink interval for HW offload + +From: Marek Vasut + +[ Upstream commit c629c972b310af41e9e072febb6dae9a299edde6 ] + +In case a PHY LED implements .blink_set callback to set LED blink +interval, call it even if .hw_control is already set, as that LED +blink interval likely controls the blink rate of that HW offloaded +LED. For PHY LEDs, that can be their activity blinking interval. + +The software blinking is not affected by this change. + +With this change, the LED interval setting looks something like this: +$ echo netdev > /sys/class/leds/led:green:lan/trigger +$ echo 1 > /sys/class/leds/led:green:lan/brightness +$ echo 250 > /sys/class/leds/led:green:lan/interval + +Signed-off-by: Marek Vasut +Link: https://lore.kernel.org/r/20250120113740.91807-1-marex@denx.de +Signed-off-by: Lee Jones +Signed-off-by: Sasha Levin +--- + drivers/leds/trigger/ledtrig-netdev.c | 16 +++++++++++++--- + 1 file changed, 13 insertions(+), 3 deletions(-) + +diff --git a/drivers/leds/trigger/ledtrig-netdev.c b/drivers/leds/trigger/ledtrig-netdev.c +index c15efe3e50780..4e048e08c4fde 100644 +--- a/drivers/leds/trigger/ledtrig-netdev.c ++++ b/drivers/leds/trigger/ledtrig-netdev.c +@@ -68,6 +68,7 @@ struct led_netdev_data { + unsigned int last_activity; + + unsigned long mode; ++ unsigned long blink_delay; + int link_speed; + __ETHTOOL_DECLARE_LINK_MODE_MASK(supported_link_modes); + u8 duplex; +@@ -86,6 +87,10 @@ static void set_baseline_state(struct led_netdev_data *trigger_data) + /* Already validated, hw control is possible with the requested mode */ + if (trigger_data->hw_control) { + led_cdev->hw_control_set(led_cdev, trigger_data->mode); ++ if (led_cdev->blink_set) { ++ led_cdev->blink_set(led_cdev, &trigger_data->blink_delay, ++ &trigger_data->blink_delay); ++ } + + return; + } +@@ -454,10 +459,11 @@ static ssize_t interval_store(struct device *dev, + size_t size) + { + struct led_netdev_data *trigger_data = led_trigger_get_drvdata(dev); ++ struct led_classdev *led_cdev = trigger_data->led_cdev; + unsigned long value; + int ret; + +- if (trigger_data->hw_control) ++ if (trigger_data->hw_control && !led_cdev->blink_set) + return -EINVAL; + + ret = kstrtoul(buf, 0, &value); +@@ -466,9 +472,13 @@ static ssize_t interval_store(struct device *dev, + + /* impose some basic bounds on the timer interval */ + if (value >= 5 && value <= 10000) { +- cancel_delayed_work_sync(&trigger_data->work); ++ if (trigger_data->hw_control) { ++ trigger_data->blink_delay = value; ++ } else { ++ cancel_delayed_work_sync(&trigger_data->work); + +- atomic_set(&trigger_data->interval, msecs_to_jiffies(value)); ++ atomic_set(&trigger_data->interval, msecs_to_jiffies(value)); ++ } + set_baseline_state(trigger_data); /* resets timer */ + } + +-- +2.39.5 + diff --git a/queue-6.14/libbpf-fix-ldx-stx-st-co-re-relocation-size-adjustme.patch b/queue-6.14/libbpf-fix-ldx-stx-st-co-re-relocation-size-adjustme.patch new file mode 100644 index 0000000000..714c6cab0d --- /dev/null +++ b/queue-6.14/libbpf-fix-ldx-stx-st-co-re-relocation-size-adjustme.patch @@ -0,0 +1,92 @@ +From e2547548c76d0c0e4aea2a3ba6a418d18ac58cd5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Feb 2025 17:48:08 -0800 +Subject: libbpf: fix LDX/STX/ST CO-RE relocation size adjustment logic + +From: Andrii Nakryiko + +[ Upstream commit 06096d19ee3897a7e70922580159607fe315da7a ] + +Libbpf has a somewhat obscure feature of automatically adjusting the +"size" of LDX/STX/ST instruction (memory store and load instructions), +based on originally recorded access size (u8, u16, u32, or u64) and the +actual size of the field on target kernel. This is meant to facilitate +using BPF CO-RE on 32-bit architectures (pointers are always 64-bit in +BPF, but host kernel's BTF will have it as 32-bit type), as well as +generally supporting safe type changes (unsigned integer type changes +can be transparently "relocated"). + +One issue that surfaced only now, 5 years after this logic was +implemented, is how this all works when dealing with fields that are +arrays. This isn't all that easy and straightforward to hit (see +selftests that reproduce this condition), but one of sched_ext BPF +programs did hit it with innocent looking loop. + +Long story short, libbpf used to calculate entire array size, instead of +making sure to only calculate array's element size. But it's the element +that is loaded by LDX/STX/ST instructions (1, 2, 4, or 8 bytes), so +that's what libbpf should check. This patch adjusts the logic for +arrays and fixed the issue. + +Reported-by: Emil Tsalapatis +Signed-off-by: Andrii Nakryiko +Acked-by: Eduard Zingerman +Link: https://lore.kernel.org/r/20250207014809.1573841-1-andrii@kernel.org +Signed-off-by: Alexei Starovoitov +Signed-off-by: Sasha Levin +--- + tools/lib/bpf/relo_core.c | 24 ++++++++++++++++++++---- + 1 file changed, 20 insertions(+), 4 deletions(-) + +diff --git a/tools/lib/bpf/relo_core.c b/tools/lib/bpf/relo_core.c +index 7632e9d418271..2b83c98a11372 100644 +--- a/tools/lib/bpf/relo_core.c ++++ b/tools/lib/bpf/relo_core.c +@@ -683,7 +683,7 @@ static int bpf_core_calc_field_relo(const char *prog_name, + { + const struct bpf_core_accessor *acc; + const struct btf_type *t; +- __u32 byte_off, byte_sz, bit_off, bit_sz, field_type_id; ++ __u32 byte_off, byte_sz, bit_off, bit_sz, field_type_id, elem_id; + const struct btf_member *m; + const struct btf_type *mt; + bool bitfield; +@@ -706,8 +706,14 @@ static int bpf_core_calc_field_relo(const char *prog_name, + if (!acc->name) { + if (relo->kind == BPF_CORE_FIELD_BYTE_OFFSET) { + *val = spec->bit_offset / 8; +- /* remember field size for load/store mem size */ +- sz = btf__resolve_size(spec->btf, acc->type_id); ++ /* remember field size for load/store mem size; ++ * note, for arrays we care about individual element ++ * sizes, not the overall array size ++ */ ++ t = skip_mods_and_typedefs(spec->btf, acc->type_id, &elem_id); ++ while (btf_is_array(t)) ++ t = skip_mods_and_typedefs(spec->btf, btf_array(t)->type, &elem_id); ++ sz = btf__resolve_size(spec->btf, elem_id); + if (sz < 0) + return -EINVAL; + *field_sz = sz; +@@ -767,7 +773,17 @@ static int bpf_core_calc_field_relo(const char *prog_name, + case BPF_CORE_FIELD_BYTE_OFFSET: + *val = byte_off; + if (!bitfield) { +- *field_sz = byte_sz; ++ /* remember field size for load/store mem size; ++ * note, for arrays we care about individual element ++ * sizes, not the overall array size ++ */ ++ t = skip_mods_and_typedefs(spec->btf, field_type_id, &elem_id); ++ while (btf_is_array(t)) ++ t = skip_mods_and_typedefs(spec->btf, btf_array(t)->type, &elem_id); ++ sz = btf__resolve_size(spec->btf, elem_id); ++ if (sz < 0) ++ return -EINVAL; ++ *field_sz = sz; + *type_id = field_type_id; + } + break; +-- +2.39.5 + diff --git a/queue-6.14/libbpf-fix-out-of-bound-read.patch b/queue-6.14/libbpf-fix-out-of-bound-read.patch new file mode 100644 index 0000000000..62f46a7fc5 --- /dev/null +++ b/queue-6.14/libbpf-fix-out-of-bound-read.patch @@ -0,0 +1,43 @@ +From a72f65f82e39f3f8ec5f6fe3ad13e189fced1870 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 22 Feb 2025 02:31:11 +0530 +Subject: libbpf: Fix out-of-bound read + +From: Nandakumar Edamana + +[ Upstream commit 236d3910117e9f97ebf75e511d8bcc950f1a4e5f ] + +In `set_kcfg_value_str`, an untrusted string is accessed with the assumption +that it will be at least two characters long due to the presence of checks for +opening and closing quotes. But the check for the closing quote +(value[len - 1] != '"') misses the fact that it could be checking the opening +quote itself in case of an invalid input that consists of just the opening +quote. + +This commit adds an explicit check to make sure the string is at least two +characters long. + +Signed-off-by: Nandakumar Edamana +Signed-off-by: Andrii Nakryiko +Link: https://lore.kernel.org/bpf/20250221210110.3182084-1-nandakumar@nandakumar.co.in +Signed-off-by: Sasha Levin +--- + tools/lib/bpf/libbpf.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c +index 6b436ec872b0f..1791a12b1aac5 100644 +--- a/tools/lib/bpf/libbpf.c ++++ b/tools/lib/bpf/libbpf.c +@@ -2106,7 +2106,7 @@ static int set_kcfg_value_str(struct extern_desc *ext, char *ext_val, + } + + len = strlen(value); +- if (value[len - 1] != '"') { ++ if (len < 2 || value[len - 1] != '"') { + pr_warn("extern (kcfg) '%s': invalid string config '%s'\n", + ext->name, value); + return -EINVAL; +-- +2.39.5 + diff --git a/queue-6.14/libbpf-pass-bpf-token-from-find_prog_btf_id-to-bpf_b.patch b/queue-6.14/libbpf-pass-bpf-token-from-find_prog_btf_id-to-bpf_b.patch new file mode 100644 index 0000000000..59485a418a --- /dev/null +++ b/queue-6.14/libbpf-pass-bpf-token-from-find_prog_btf_id-to-bpf_b.patch @@ -0,0 +1,166 @@ +From 7a8beec7026564efe57ebf9c4c568ed0071f2e39 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Mar 2025 17:40:38 +0000 +Subject: libbpf: Pass BPF token from find_prog_btf_id to BPF_BTF_GET_FD_BY_ID + +From: Mykyta Yatsenko + +[ Upstream commit 974ef9f0d23edc1a802691c585b84514b414a96d ] + +Pass BPF token from bpf_program__set_attach_target to +BPF_BTF_GET_FD_BY_ID bpf command. +When freplace program attaches to target program, it needs to look up +for BTF of the target, this may require BPF token, if, for example, +running from user namespace. + +Signed-off-by: Mykyta Yatsenko +Signed-off-by: Andrii Nakryiko +Acked-by: Yonghong Song +Link: https://lore.kernel.org/bpf/20250317174039.161275-4-mykyta.yatsenko5@gmail.com +Signed-off-by: Sasha Levin +--- + tools/lib/bpf/bpf.c | 3 ++- + tools/lib/bpf/bpf.h | 3 ++- + tools/lib/bpf/btf.c | 15 +++++++++++++-- + tools/lib/bpf/libbpf.c | 10 +++++----- + tools/lib/bpf/libbpf_internal.h | 1 + + 5 files changed, 23 insertions(+), 9 deletions(-) + +diff --git a/tools/lib/bpf/bpf.c b/tools/lib/bpf/bpf.c +index 359f73ead6137..a9c3e33d0f8a9 100644 +--- a/tools/lib/bpf/bpf.c ++++ b/tools/lib/bpf/bpf.c +@@ -1097,7 +1097,7 @@ int bpf_map_get_fd_by_id(__u32 id) + int bpf_btf_get_fd_by_id_opts(__u32 id, + const struct bpf_get_fd_by_id_opts *opts) + { +- const size_t attr_sz = offsetofend(union bpf_attr, open_flags); ++ const size_t attr_sz = offsetofend(union bpf_attr, fd_by_id_token_fd); + union bpf_attr attr; + int fd; + +@@ -1107,6 +1107,7 @@ int bpf_btf_get_fd_by_id_opts(__u32 id, + memset(&attr, 0, attr_sz); + attr.btf_id = id; + attr.open_flags = OPTS_GET(opts, open_flags, 0); ++ attr.fd_by_id_token_fd = OPTS_GET(opts, token_fd, 0); + + fd = sys_bpf_fd(BPF_BTF_GET_FD_BY_ID, &attr, attr_sz); + return libbpf_err_errno(fd); +diff --git a/tools/lib/bpf/bpf.h b/tools/lib/bpf/bpf.h +index 435da95d20589..777627d33d257 100644 +--- a/tools/lib/bpf/bpf.h ++++ b/tools/lib/bpf/bpf.h +@@ -487,9 +487,10 @@ LIBBPF_API int bpf_link_get_next_id(__u32 start_id, __u32 *next_id); + struct bpf_get_fd_by_id_opts { + size_t sz; /* size of this struct for forward/backward compatibility */ + __u32 open_flags; /* permissions requested for the operation on fd */ ++ __u32 token_fd; + size_t :0; + }; +-#define bpf_get_fd_by_id_opts__last_field open_flags ++#define bpf_get_fd_by_id_opts__last_field token_fd + + LIBBPF_API int bpf_prog_get_fd_by_id(__u32 id); + LIBBPF_API int bpf_prog_get_fd_by_id_opts(__u32 id, +diff --git a/tools/lib/bpf/btf.c b/tools/lib/bpf/btf.c +index 560b519f820e2..03cc7c46c16b5 100644 +--- a/tools/lib/bpf/btf.c ++++ b/tools/lib/bpf/btf.c +@@ -1619,12 +1619,18 @@ struct btf *btf_get_from_fd(int btf_fd, struct btf *base_btf) + return btf; + } + +-struct btf *btf__load_from_kernel_by_id_split(__u32 id, struct btf *base_btf) ++struct btf *btf_load_from_kernel(__u32 id, struct btf *base_btf, int token_fd) + { + struct btf *btf; + int btf_fd; ++ LIBBPF_OPTS(bpf_get_fd_by_id_opts, opts); ++ ++ if (token_fd) { ++ opts.open_flags |= BPF_F_TOKEN_FD; ++ opts.token_fd = token_fd; ++ } + +- btf_fd = bpf_btf_get_fd_by_id(id); ++ btf_fd = bpf_btf_get_fd_by_id_opts(id, &opts); + if (btf_fd < 0) + return libbpf_err_ptr(-errno); + +@@ -1634,6 +1640,11 @@ struct btf *btf__load_from_kernel_by_id_split(__u32 id, struct btf *base_btf) + return libbpf_ptr(btf); + } + ++struct btf *btf__load_from_kernel_by_id_split(__u32 id, struct btf *base_btf) ++{ ++ return btf_load_from_kernel(id, base_btf, 0); ++} ++ + struct btf *btf__load_from_kernel_by_id(__u32 id) + { + return btf__load_from_kernel_by_id_split(id, NULL); +diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c +index 194809da51725..6b436ec872b0f 100644 +--- a/tools/lib/bpf/libbpf.c ++++ b/tools/lib/bpf/libbpf.c +@@ -9959,7 +9959,7 @@ int libbpf_find_vmlinux_btf_id(const char *name, + return libbpf_err(err); + } + +-static int libbpf_find_prog_btf_id(const char *name, __u32 attach_prog_fd) ++static int libbpf_find_prog_btf_id(const char *name, __u32 attach_prog_fd, int token_fd) + { + struct bpf_prog_info info; + __u32 info_len = sizeof(info); +@@ -9979,7 +9979,7 @@ static int libbpf_find_prog_btf_id(const char *name, __u32 attach_prog_fd) + pr_warn("The target program doesn't have BTF\n"); + goto out; + } +- btf = btf__load_from_kernel_by_id(info.btf_id); ++ btf = btf_load_from_kernel(info.btf_id, NULL, token_fd); + err = libbpf_get_error(btf); + if (err) { + pr_warn("Failed to get BTF %d of the program: %s\n", info.btf_id, errstr(err)); +@@ -10062,7 +10062,7 @@ static int libbpf_find_attach_btf_id(struct bpf_program *prog, const char *attac + pr_warn("prog '%s': attach program FD is not set\n", prog->name); + return -EINVAL; + } +- err = libbpf_find_prog_btf_id(attach_name, attach_prog_fd); ++ err = libbpf_find_prog_btf_id(attach_name, attach_prog_fd, prog->obj->token_fd); + if (err < 0) { + pr_warn("prog '%s': failed to find BPF program (FD %d) BTF ID for '%s': %s\n", + prog->name, attach_prog_fd, attach_name, errstr(err)); +@@ -12858,7 +12858,7 @@ struct bpf_link *bpf_program__attach_freplace(const struct bpf_program *prog, + if (target_fd) { + LIBBPF_OPTS(bpf_link_create_opts, target_opts); + +- btf_id = libbpf_find_prog_btf_id(attach_func_name, target_fd); ++ btf_id = libbpf_find_prog_btf_id(attach_func_name, target_fd, prog->obj->token_fd); + if (btf_id < 0) + return libbpf_err_ptr(btf_id); + +@@ -13679,7 +13679,7 @@ int bpf_program__set_attach_target(struct bpf_program *prog, + + if (attach_prog_fd) { + btf_id = libbpf_find_prog_btf_id(attach_func_name, +- attach_prog_fd); ++ attach_prog_fd, prog->obj->token_fd); + if (btf_id < 0) + return libbpf_err(btf_id); + } else { +diff --git a/tools/lib/bpf/libbpf_internal.h b/tools/lib/bpf/libbpf_internal.h +index de498e2dd6b0b..76669c73dcd16 100644 +--- a/tools/lib/bpf/libbpf_internal.h ++++ b/tools/lib/bpf/libbpf_internal.h +@@ -409,6 +409,7 @@ int libbpf__load_raw_btf(const char *raw_types, size_t types_len, + int btf_load_into_kernel(struct btf *btf, + char *log_buf, size_t log_sz, __u32 log_level, + int token_fd); ++struct btf *btf_load_from_kernel(__u32 id, struct btf *base_btf, int token_fd); + + struct btf *btf_get_from_fd(int btf_fd, struct btf *base_btf); + void btf_get_kernel_prefix_kind(enum bpf_attach_type attach_type, +-- +2.39.5 + diff --git a/queue-6.14/libnvdimm-labels-fix-divide-error-in-nd_label_data_i.patch b/queue-6.14/libnvdimm-labels-fix-divide-error-in-nd_label_data_i.patch new file mode 100644 index 0000000000..57ccb17b22 --- /dev/null +++ b/queue-6.14/libnvdimm-labels-fix-divide-error-in-nd_label_data_i.patch @@ -0,0 +1,64 @@ +From 040ac72b937fe02c207a0544d48d1f4654d437b8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 20 Mar 2025 12:22:22 +0100 +Subject: libnvdimm/labels: Fix divide error in nd_label_data_init() + +From: Robert Richter + +[ Upstream commit ef1d3455bbc1922f94a91ed58d3d7db440652959 ] + +If a faulty CXL memory device returns a broken zero LSA size in its +memory device information (Identify Memory Device (Opcode 4000h), CXL +spec. 3.1, 8.2.9.9.1.1), a divide error occurs in the libnvdimm +driver: + + Oops: divide error: 0000 [#1] PREEMPT SMP NOPTI + RIP: 0010:nd_label_data_init+0x10e/0x800 [libnvdimm] + +Code and flow: + +1) CXL Command 4000h returns LSA size = 0 +2) config_size is assigned to zero LSA size (CXL pmem driver): + +drivers/cxl/pmem.c: .config_size = mds->lsa_size, + +3) max_xfer is set to zero (nvdimm driver): + +drivers/nvdimm/label.c: max_xfer = min_t(size_t, ndd->nsarea.max_xfer, config_size); + +4) A subsequent DIV_ROUND_UP() causes a division by zero: + +drivers/nvdimm/label.c: /* Make our initial read size a multiple of max_xfer size */ +drivers/nvdimm/label.c: read_size = min(DIV_ROUND_UP(read_size, max_xfer) * max_xfer, +drivers/nvdimm/label.c- config_size); + +Fix this by checking the config size parameter by extending an +existing check. + +Signed-off-by: Robert Richter +Reviewed-by: Pankaj Gupta +Reviewed-by: Ira Weiny +Link: https://patch.msgid.link/20250320112223.608320-1-rrichter@amd.com +Signed-off-by: Ira Weiny +Signed-off-by: Sasha Levin +--- + drivers/nvdimm/label.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/nvdimm/label.c b/drivers/nvdimm/label.c +index 082253a3a9560..04f4a049599a1 100644 +--- a/drivers/nvdimm/label.c ++++ b/drivers/nvdimm/label.c +@@ -442,7 +442,8 @@ int nd_label_data_init(struct nvdimm_drvdata *ndd) + if (ndd->data) + return 0; + +- if (ndd->nsarea.status || ndd->nsarea.max_xfer == 0) { ++ if (ndd->nsarea.status || ndd->nsarea.max_xfer == 0 || ++ ndd->nsarea.config_size == 0) { + dev_dbg(ndd->dev, "failed to init config data area: (%u:%u)\n", + ndd->nsarea.max_xfer, ndd->nsarea.config_size); + return -ENXIO; +-- +2.39.5 + diff --git a/queue-6.14/lockdep-fix-wait-context-check-on-softirq-for-preemp.patch b/queue-6.14/lockdep-fix-wait-context-check-on-softirq-for-preemp.patch new file mode 100644 index 0000000000..fa49a959d5 --- /dev/null +++ b/queue-6.14/lockdep-fix-wait-context-check-on-softirq-for-preemp.patch @@ -0,0 +1,99 @@ +From 2dfb8b75b57370d50db318243a05a7d0b0d2304e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 21 Mar 2025 07:33:22 -0700 +Subject: lockdep: Fix wait context check on softirq for PREEMPT_RT + +From: Ryo Takakura + +[ Upstream commit 61c39d8c83e2077f33e0a2c8980a76a7f323f0ce ] + +Since: + + 0c1d7a2c2d32 ("lockdep: Remove softirq accounting on PREEMPT_RT.") + +the wait context test for mutex usage within "in softirq context" fails +as it references @softirq_context: + + | wait context tests | + -------------------------------------------------------------------------- + | rcu | raw | spin |mutex | + -------------------------------------------------------------------------- + in hardirq context: ok | ok | ok | ok | + in hardirq context (not threaded): ok | ok | ok | ok | + in softirq context: ok | ok | ok |FAILED| + +As a fix, add lockdep map for BH disabled section. This fixes the +issue by letting us catch cases when local_bh_disable() gets called +with preemption disabled where local_lock doesn't get acquired. +In the case of "in softirq context" selftest, local_bh_disable() was +being called with preemption disable as it's early in the boot. + +[ boqun: Move the lockdep annotations into __local_bh_*() to avoid false + positives because of unpaired local_bh_disable() reported by + Borislav Petkov and Peter Zijlstra, and make bh_lock_map + only exist for PREEMPT_RT. ] + +[ mingo: Restored authorship and improved the bh_lock_map definition. ] + +Signed-off-by: Ryo Takakura +Signed-off-by: Boqun Feng +Signed-off-by: Ingo Molnar +Link: https://lore.kernel.org/r/20250321143322.79651-1-boqun.feng@gmail.com +Signed-off-by: Sasha Levin +--- + kernel/softirq.c | 18 ++++++++++++++++++ + 1 file changed, 18 insertions(+) + +diff --git a/kernel/softirq.c b/kernel/softirq.c +index 4dae6ac2e83fb..513b1945987cc 100644 +--- a/kernel/softirq.c ++++ b/kernel/softirq.c +@@ -126,6 +126,18 @@ static DEFINE_PER_CPU(struct softirq_ctrl, softirq_ctrl) = { + .lock = INIT_LOCAL_LOCK(softirq_ctrl.lock), + }; + ++#ifdef CONFIG_DEBUG_LOCK_ALLOC ++static struct lock_class_key bh_lock_key; ++struct lockdep_map bh_lock_map = { ++ .name = "local_bh", ++ .key = &bh_lock_key, ++ .wait_type_outer = LD_WAIT_FREE, ++ .wait_type_inner = LD_WAIT_CONFIG, /* PREEMPT_RT makes BH preemptible. */ ++ .lock_type = LD_LOCK_PERCPU, ++}; ++EXPORT_SYMBOL_GPL(bh_lock_map); ++#endif ++ + /** + * local_bh_blocked() - Check for idle whether BH processing is blocked + * +@@ -148,6 +160,8 @@ void __local_bh_disable_ip(unsigned long ip, unsigned int cnt) + + WARN_ON_ONCE(in_hardirq()); + ++ lock_map_acquire_read(&bh_lock_map); ++ + /* First entry of a task into a BH disabled section? */ + if (!current->softirq_disable_cnt) { + if (preemptible()) { +@@ -211,6 +225,8 @@ void __local_bh_enable_ip(unsigned long ip, unsigned int cnt) + WARN_ON_ONCE(in_hardirq()); + lockdep_assert_irqs_enabled(); + ++ lock_map_release(&bh_lock_map); ++ + local_irq_save(flags); + curcnt = __this_cpu_read(softirq_ctrl.cnt); + +@@ -261,6 +277,8 @@ static inline void ksoftirqd_run_begin(void) + /* Counterpart to ksoftirqd_run_begin() */ + static inline void ksoftirqd_run_end(void) + { ++ /* pairs with the lock_map_acquire_read() in ksoftirqd_run_begin() */ ++ lock_map_release(&bh_lock_map); + __local_bh_enable(SOFTIRQ_OFFSET, true); + WARN_ON_ONCE(in_interrupt()); + local_irq_enable(); +-- +2.39.5 + diff --git a/queue-6.14/loop-check-in-lo_flags_direct_io-in-loop_default_blo.patch b/queue-6.14/loop-check-in-lo_flags_direct_io-in-loop_default_blo.patch new file mode 100644 index 0000000000..27f8f70505 --- /dev/null +++ b/queue-6.14/loop-check-in-lo_flags_direct_io-in-loop_default_blo.patch @@ -0,0 +1,40 @@ +From 741688b17cc8abdddbdbae15e8a51dfb139ce5cf Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 31 Jan 2025 13:00:40 +0100 +Subject: loop: check in LO_FLAGS_DIRECT_IO in loop_default_blocksize + +From: Christoph Hellwig + +[ Upstream commit f6f9e32fe1e454ae8ac0190b2c2bd6074914beec ] + +We can't go below the minimum direct I/O size no matter if direct I/O is +enabled by passing in an O_DIRECT file descriptor or due to the explicit +flag. Now that LO_FLAGS_DIRECT_IO is set earlier after assigning a +backing file, loop_default_blocksize can check it instead of the +O_DIRECT flag to handle both conditions. + +Signed-off-by: Christoph Hellwig +Reviewed-by: Damien Le Moal +Link: https://lore.kernel.org/r/20250131120120.1315125-4-hch@lst.de +Signed-off-by: Jens Axboe +Signed-off-by: Sasha Levin +--- + drivers/block/loop.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/block/loop.c b/drivers/block/loop.c +index 1e5ef09cdde68..f68f86e9cb716 100644 +--- a/drivers/block/loop.c ++++ b/drivers/block/loop.c +@@ -920,7 +920,7 @@ static unsigned int loop_default_blocksize(struct loop_device *lo, + struct block_device *backing_bdev) + { + /* In case of direct I/O, match underlying block size */ +- if ((lo->lo_backing_file->f_flags & O_DIRECT) && backing_bdev) ++ if ((lo->lo_flags & LO_FLAGS_DIRECT_IO) && backing_bdev) + return bdev_logical_block_size(backing_bdev); + return SECTOR_SIZE; + } +-- +2.39.5 + diff --git a/queue-6.14/loop-move-vfs_fsync-out-of-loop_update_dio.patch b/queue-6.14/loop-move-vfs_fsync-out-of-loop_update_dio.patch new file mode 100644 index 0000000000..48f8b4c1fc --- /dev/null +++ b/queue-6.14/loop-move-vfs_fsync-out-of-loop_update_dio.patch @@ -0,0 +1,93 @@ +From b2e23c6b7d6d2934c1cb6f0788143ab7e19cd1ea Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 18 Mar 2025 15:29:55 +0800 +Subject: loop: move vfs_fsync() out of loop_update_dio() + +From: Ming Lei + +[ Upstream commit 86947bdc28894520ed5aab0cf21b99ff0b659e07 ] + +If vfs_flush() is called with queue frozen, the queue freeze lock may be +connected with FS internal lock, and lockdep warning can be triggered +because the queue freeze lock is connected with too many global or +sub-system locks. + +Fix the warning by moving vfs_fsync() out of loop_update_dio(): + +- vfs_fsync() is only needed when switching to dio + +- only loop_change_fd() and loop_configure() may switch from buffered +IO to direct IO, so call vfs_fsync() directly here. This way is safe +because either loop is in unbound, or new file isn't attached + +- for the other two cases of set_status and set_block_size, direct IO +can only become off, so no need to call vfs_fsync() + +Cc: Christoph Hellwig +Reported-by: Kun Hu +Reported-by: Jiaji Qin +Closes: https://lore.kernel.org/linux-block/359BC288-B0B1-4815-9F01-3A349B12E816@m.fudan.edu.cn/T/#u +Signed-off-by: Ming Lei +Reviewed-by: Christoph Hellwig +Link: https://lore.kernel.org/r/20250318072955.3893805-1-ming.lei@redhat.com +Signed-off-by: Jens Axboe +Signed-off-by: Sasha Levin +--- + drivers/block/loop.c | 20 ++++++++++++++------ + 1 file changed, 14 insertions(+), 6 deletions(-) + +diff --git a/drivers/block/loop.c b/drivers/block/loop.c +index b378d2aa49f06..1e5ef09cdde68 100644 +--- a/drivers/block/loop.c ++++ b/drivers/block/loop.c +@@ -205,8 +205,6 @@ static bool lo_can_use_dio(struct loop_device *lo) + */ + static inline void loop_update_dio(struct loop_device *lo) + { +- bool dio_in_use = lo->lo_flags & LO_FLAGS_DIRECT_IO; +- + lockdep_assert_held(&lo->lo_mutex); + WARN_ON_ONCE(lo->lo_state == Lo_bound && + lo->lo_queue->mq_freeze_depth == 0); +@@ -215,10 +213,6 @@ static inline void loop_update_dio(struct loop_device *lo) + lo->lo_flags |= LO_FLAGS_DIRECT_IO; + if ((lo->lo_flags & LO_FLAGS_DIRECT_IO) && !lo_can_use_dio(lo)) + lo->lo_flags &= ~LO_FLAGS_DIRECT_IO; +- +- /* flush dirty pages before starting to issue direct I/O */ +- if ((lo->lo_flags & LO_FLAGS_DIRECT_IO) && !dio_in_use) +- vfs_fsync(lo->lo_backing_file, 0); + } + + /** +@@ -568,6 +562,13 @@ static int loop_change_fd(struct loop_device *lo, struct block_device *bdev, + if (get_loop_size(lo, file) != get_loop_size(lo, old_file)) + goto out_err; + ++ /* ++ * We might switch to direct I/O mode for the loop device, write back ++ * all dirty data the page cache now that so that the individual I/O ++ * operations don't have to do that. ++ */ ++ vfs_fsync(file, 0); ++ + /* and ... switch */ + disk_force_media_change(lo->lo_disk); + memflags = blk_mq_freeze_queue(lo->lo_queue); +@@ -1046,6 +1047,13 @@ static int loop_configure(struct loop_device *lo, blk_mode_t mode, + if (error) + goto out_unlock; + ++ /* ++ * We might switch to direct I/O mode for the loop device, write back ++ * all dirty data the page cache now that so that the individual I/O ++ * operations don't have to do that. ++ */ ++ vfs_fsync(file, 0); ++ + loop_update_dio(lo); + loop_sysfs_init(lo); + +-- +2.39.5 + diff --git a/queue-6.14/mailbox-pcc-use-acpi_os_ioremap-instead-of-ioremap.patch b/queue-6.14/mailbox-pcc-use-acpi_os_ioremap-instead-of-ioremap.patch new file mode 100644 index 0000000000..5bf78f9081 --- /dev/null +++ b/queue-6.14/mailbox-pcc-use-acpi_os_ioremap-instead-of-ioremap.patch @@ -0,0 +1,49 @@ +From 215648eacbcb644a682a773d15b096a4a8d9175d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 13 Mar 2025 15:28:51 +0000 +Subject: mailbox: pcc: Use acpi_os_ioremap() instead of ioremap() + +From: Sudeep Holla + +[ Upstream commit d181acea5b864e91f38f5771b8961215ce5017ae ] + +The Platform Communication Channel (PCC) mailbox driver currently uses +ioremap() to map channel shared memory regions. However it is preferred +to use acpi_os_ioremap(), which is mapping function specific to EFI/ACPI +defined memory regions. It ensures that the correct memory attributes +are applied when mapping ACPI-provided regions. + +While at it, also add checks for handling any errors with the mapping. + +Acked-by: Huisong Li +Tested-by: Huisong Li +Tested-by: Adam Young +Signed-off-by: Sudeep Holla +Signed-off-by: Jassi Brar +Signed-off-by: Sasha Levin +--- + drivers/mailbox/pcc.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/drivers/mailbox/pcc.c b/drivers/mailbox/pcc.c +index f8215a8f656a4..49254d99a8ad6 100644 +--- a/drivers/mailbox/pcc.c ++++ b/drivers/mailbox/pcc.c +@@ -419,8 +419,12 @@ int pcc_mbox_ioremap(struct mbox_chan *chan) + return -1; + pchan_info = chan->con_priv; + pcc_mbox_chan = &pchan_info->chan; +- pcc_mbox_chan->shmem = ioremap(pcc_mbox_chan->shmem_base_addr, +- pcc_mbox_chan->shmem_size); ++ ++ pcc_mbox_chan->shmem = acpi_os_ioremap(pcc_mbox_chan->shmem_base_addr, ++ pcc_mbox_chan->shmem_size); ++ if (!pcc_mbox_chan->shmem) ++ return -ENXIO; ++ + return 0; + } + EXPORT_SYMBOL_GPL(pcc_mbox_ioremap); +-- +2.39.5 + diff --git a/queue-6.14/mailbox-use-error-ret-code-of-of_parse_phandle_with_.patch b/queue-6.14/mailbox-use-error-ret-code-of-of_parse_phandle_with_.patch new file mode 100644 index 0000000000..15f06ca87b --- /dev/null +++ b/queue-6.14/mailbox-use-error-ret-code-of-of_parse_phandle_with_.patch @@ -0,0 +1,45 @@ +From 427b10c24024b6a9d1e1e0c5e0fe0fa5e9cb8581 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 24 Feb 2025 08:27:13 +0000 +Subject: mailbox: use error ret code of of_parse_phandle_with_args() + +From: Tudor Ambarus + +[ Upstream commit 24fdd5074b205cfb0ef4cd0751a2d03031455929 ] + +In case of error, of_parse_phandle_with_args() returns -EINVAL when the +passed index is negative, or -ENOENT when the index is for an empty +phandle. The mailbox core overwrote the error return code with a less +precise -ENODEV. Use the error returned code from +of_parse_phandle_with_args(). + +Signed-off-by: Tudor Ambarus +Signed-off-by: Jassi Brar +Signed-off-by: Sasha Levin +--- + drivers/mailbox/mailbox.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/drivers/mailbox/mailbox.c b/drivers/mailbox/mailbox.c +index d3d26a2c98956..cb174e788a96c 100644 +--- a/drivers/mailbox/mailbox.c ++++ b/drivers/mailbox/mailbox.c +@@ -415,11 +415,12 @@ struct mbox_chan *mbox_request_channel(struct mbox_client *cl, int index) + + mutex_lock(&con_mutex); + +- if (of_parse_phandle_with_args(dev->of_node, "mboxes", +- "#mbox-cells", index, &spec)) { ++ ret = of_parse_phandle_with_args(dev->of_node, "mboxes", "#mbox-cells", ++ index, &spec); ++ if (ret) { + dev_dbg(dev, "%s: can't parse \"mboxes\" property\n", __func__); + mutex_unlock(&con_mutex); +- return ERR_PTR(-ENODEV); ++ return ERR_PTR(ret); + } + + chan = ERR_PTR(-EPROBE_DEFER); +-- +2.39.5 + diff --git a/queue-6.14/mctp-fix-incorrect-tx-flow-invalidation-condition-in.patch b/queue-6.14/mctp-fix-incorrect-tx-flow-invalidation-condition-in.patch new file mode 100644 index 0000000000..805c565d12 --- /dev/null +++ b/queue-6.14/mctp-fix-incorrect-tx-flow-invalidation-condition-in.patch @@ -0,0 +1,41 @@ +From 3a61d633539b05e672d327fb208d2d815ca9e2fc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 25 Mar 2025 16:10:08 +0800 +Subject: mctp: Fix incorrect tx flow invalidation condition in mctp-i2c + +From: Daniel Hsu + +[ Upstream commit 70facbf978ac90c6da17a3de2a8dd111b06f1bac ] + +Previously, the condition for invalidating the tx flow in +mctp_i2c_invalidate_tx_flow() checked if `rc` was nonzero. +However, this could incorrectly trigger the invalidation +even when `rc > 0` was returned as a success status. + +This patch updates the condition to explicitly check for `rc < 0`, +ensuring that only error cases trigger the invalidation. + +Signed-off-by: Daniel Hsu +Reviewed-by: Jeremy Kerr +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + drivers/net/mctp/mctp-i2c.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/mctp/mctp-i2c.c b/drivers/net/mctp/mctp-i2c.c +index d74d47dd6e04d..f782d93f826ef 100644 +--- a/drivers/net/mctp/mctp-i2c.c ++++ b/drivers/net/mctp/mctp-i2c.c +@@ -537,7 +537,7 @@ static void mctp_i2c_xmit(struct mctp_i2c_dev *midev, struct sk_buff *skb) + rc = __i2c_transfer(midev->adapter, &msg, 1); + + /* on tx errors, the flow can no longer be considered valid */ +- if (rc) ++ if (rc < 0) + mctp_i2c_invalidate_tx_flow(midev, skb); + + break; +-- +2.39.5 + diff --git a/queue-6.14/media-adv7180-disable-test-pattern-control-on-adv718.patch b/queue-6.14/media-adv7180-disable-test-pattern-control-on-adv718.patch new file mode 100644 index 0000000000..7e51c29cb3 --- /dev/null +++ b/queue-6.14/media-adv7180-disable-test-pattern-control-on-adv718.patch @@ -0,0 +1,131 @@ +From 0fbfaa268f45a5b33d3d12dc12c1caee57ea4e33 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 22 Feb 2025 00:09:07 +0100 +Subject: media: adv7180: Disable test-pattern control on adv7180 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Niklas Söderlund + +[ Upstream commit a980bc5f56b0292336e408f657f79e574e8067c0 ] + +The register that enables selecting a test-pattern to be outputted in +free-run mode (FREE_RUN_PAT_SEL[2:0]) is only available on adv7280 based +devices, not the adv7180 based ones. + +Add a flag to mark devices that are capable of generating test-patterns, +and those that are not. And only register the control on supported +devices. + +Signed-off-by: Niklas Söderlund +Signed-off-by: Hans Verkuil +Signed-off-by: Sasha Levin +--- + drivers/media/i2c/adv7180.c | 34 ++++++++++++++++++++++------------ + 1 file changed, 22 insertions(+), 12 deletions(-) + +diff --git a/drivers/media/i2c/adv7180.c b/drivers/media/i2c/adv7180.c +index ff7dfa0278a7a..6e50b14f888f1 100644 +--- a/drivers/media/i2c/adv7180.c ++++ b/drivers/media/i2c/adv7180.c +@@ -195,6 +195,7 @@ struct adv7180_state; + #define ADV7180_FLAG_V2 BIT(1) + #define ADV7180_FLAG_MIPI_CSI2 BIT(2) + #define ADV7180_FLAG_I2P BIT(3) ++#define ADV7180_FLAG_TEST_PATTERN BIT(4) + + struct adv7180_chip_info { + unsigned int flags; +@@ -682,11 +683,15 @@ static int adv7180_init_controls(struct adv7180_state *state) + ADV7180_HUE_MAX, 1, ADV7180_HUE_DEF); + v4l2_ctrl_new_custom(&state->ctrl_hdl, &adv7180_ctrl_fast_switch, NULL); + +- v4l2_ctrl_new_std_menu_items(&state->ctrl_hdl, &adv7180_ctrl_ops, +- V4L2_CID_TEST_PATTERN, +- ARRAY_SIZE(test_pattern_menu) - 1, +- 0, ARRAY_SIZE(test_pattern_menu) - 1, +- test_pattern_menu); ++ if (state->chip_info->flags & ADV7180_FLAG_TEST_PATTERN) { ++ v4l2_ctrl_new_std_menu_items(&state->ctrl_hdl, ++ &adv7180_ctrl_ops, ++ V4L2_CID_TEST_PATTERN, ++ ARRAY_SIZE(test_pattern_menu) - 1, ++ 0, ++ ARRAY_SIZE(test_pattern_menu) - 1, ++ test_pattern_menu); ++ } + + state->sd.ctrl_handler = &state->ctrl_hdl; + if (state->ctrl_hdl.error) { +@@ -1221,7 +1226,7 @@ static const struct adv7180_chip_info adv7182_info = { + }; + + static const struct adv7180_chip_info adv7280_info = { +- .flags = ADV7180_FLAG_V2 | ADV7180_FLAG_I2P, ++ .flags = ADV7180_FLAG_V2 | ADV7180_FLAG_I2P | ADV7180_FLAG_TEST_PATTERN, + .valid_input_mask = BIT(ADV7182_INPUT_CVBS_AIN1) | + BIT(ADV7182_INPUT_CVBS_AIN2) | + BIT(ADV7182_INPUT_CVBS_AIN3) | +@@ -1235,7 +1240,8 @@ static const struct adv7180_chip_info adv7280_info = { + }; + + static const struct adv7180_chip_info adv7280_m_info = { +- .flags = ADV7180_FLAG_V2 | ADV7180_FLAG_MIPI_CSI2 | ADV7180_FLAG_I2P, ++ .flags = ADV7180_FLAG_V2 | ADV7180_FLAG_MIPI_CSI2 | ADV7180_FLAG_I2P | ++ ADV7180_FLAG_TEST_PATTERN, + .valid_input_mask = BIT(ADV7182_INPUT_CVBS_AIN1) | + BIT(ADV7182_INPUT_CVBS_AIN2) | + BIT(ADV7182_INPUT_CVBS_AIN3) | +@@ -1256,7 +1262,8 @@ static const struct adv7180_chip_info adv7280_m_info = { + }; + + static const struct adv7180_chip_info adv7281_info = { +- .flags = ADV7180_FLAG_V2 | ADV7180_FLAG_MIPI_CSI2, ++ .flags = ADV7180_FLAG_V2 | ADV7180_FLAG_MIPI_CSI2 | ++ ADV7180_FLAG_TEST_PATTERN, + .valid_input_mask = BIT(ADV7182_INPUT_CVBS_AIN1) | + BIT(ADV7182_INPUT_CVBS_AIN2) | + BIT(ADV7182_INPUT_CVBS_AIN7) | +@@ -1271,7 +1278,8 @@ static const struct adv7180_chip_info adv7281_info = { + }; + + static const struct adv7180_chip_info adv7281_m_info = { +- .flags = ADV7180_FLAG_V2 | ADV7180_FLAG_MIPI_CSI2, ++ .flags = ADV7180_FLAG_V2 | ADV7180_FLAG_MIPI_CSI2 | ++ ADV7180_FLAG_TEST_PATTERN, + .valid_input_mask = BIT(ADV7182_INPUT_CVBS_AIN1) | + BIT(ADV7182_INPUT_CVBS_AIN2) | + BIT(ADV7182_INPUT_CVBS_AIN3) | +@@ -1291,7 +1299,8 @@ static const struct adv7180_chip_info adv7281_m_info = { + }; + + static const struct adv7180_chip_info adv7281_ma_info = { +- .flags = ADV7180_FLAG_V2 | ADV7180_FLAG_MIPI_CSI2, ++ .flags = ADV7180_FLAG_V2 | ADV7180_FLAG_MIPI_CSI2 | ++ ADV7180_FLAG_TEST_PATTERN, + .valid_input_mask = BIT(ADV7182_INPUT_CVBS_AIN1) | + BIT(ADV7182_INPUT_CVBS_AIN2) | + BIT(ADV7182_INPUT_CVBS_AIN3) | +@@ -1316,7 +1325,7 @@ static const struct adv7180_chip_info adv7281_ma_info = { + }; + + static const struct adv7180_chip_info adv7282_info = { +- .flags = ADV7180_FLAG_V2 | ADV7180_FLAG_I2P, ++ .flags = ADV7180_FLAG_V2 | ADV7180_FLAG_I2P | ADV7180_FLAG_TEST_PATTERN, + .valid_input_mask = BIT(ADV7182_INPUT_CVBS_AIN1) | + BIT(ADV7182_INPUT_CVBS_AIN2) | + BIT(ADV7182_INPUT_CVBS_AIN7) | +@@ -1331,7 +1340,8 @@ static const struct adv7180_chip_info adv7282_info = { + }; + + static const struct adv7180_chip_info adv7282_m_info = { +- .flags = ADV7180_FLAG_V2 | ADV7180_FLAG_MIPI_CSI2 | ADV7180_FLAG_I2P, ++ .flags = ADV7180_FLAG_V2 | ADV7180_FLAG_MIPI_CSI2 | ADV7180_FLAG_I2P | ++ ADV7180_FLAG_TEST_PATTERN, + .valid_input_mask = BIT(ADV7182_INPUT_CVBS_AIN1) | + BIT(ADV7182_INPUT_CVBS_AIN2) | + BIT(ADV7182_INPUT_CVBS_AIN3) | +-- +2.39.5 + diff --git a/queue-6.14/media-c8sectpfe-call-of_node_put-i2c_bus-only-once-i.patch b/queue-6.14/media-c8sectpfe-call-of_node_put-i2c_bus-only-once-i.patch new file mode 100644 index 0000000000..ac3cb5abd5 --- /dev/null +++ b/queue-6.14/media-c8sectpfe-call-of_node_put-i2c_bus-only-once-i.patch @@ -0,0 +1,45 @@ +From 3db14100f8e867508ec59f8290d1b9bd872c9024 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 4 Oct 2024 15:50:15 +0200 +Subject: media: c8sectpfe: Call of_node_put(i2c_bus) only once in + c8sectpfe_probe() + +From: Markus Elfring + +[ Upstream commit b773530a34df0687020520015057075f8b7b4ac4 ] + +An of_node_put(i2c_bus) call was immediately used after a pointer check +for an of_find_i2c_adapter_by_node() call in this function implementation. +Thus call such a function only once instead directly before the check. + +This issue was transformed by using the Coccinelle software. + +Signed-off-by: Markus Elfring +Signed-off-by: Hans Verkuil +Signed-off-by: Sasha Levin +--- + drivers/media/platform/st/sti/c8sectpfe/c8sectpfe-core.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/drivers/media/platform/st/sti/c8sectpfe/c8sectpfe-core.c b/drivers/media/platform/st/sti/c8sectpfe/c8sectpfe-core.c +index 7b3a37957e3ae..d151d2ed1f64b 100644 +--- a/drivers/media/platform/st/sti/c8sectpfe/c8sectpfe-core.c ++++ b/drivers/media/platform/st/sti/c8sectpfe/c8sectpfe-core.c +@@ -797,13 +797,12 @@ static int c8sectpfe_probe(struct platform_device *pdev) + } + tsin->i2c_adapter = + of_find_i2c_adapter_by_node(i2c_bus); ++ of_node_put(i2c_bus); + if (!tsin->i2c_adapter) { + dev_err(&pdev->dev, "No i2c adapter found\n"); +- of_node_put(i2c_bus); + ret = -ENODEV; + goto err_node_put; + } +- of_node_put(i2c_bus); + + /* Acquire reset GPIO and activate it */ + tsin->rst_gpio = devm_fwnode_gpiod_get(dev, +-- +2.39.5 + diff --git a/queue-6.14/media-cec-use-us_to_ktime-where-appropriate.patch b/queue-6.14/media-cec-use-us_to_ktime-where-appropriate.patch new file mode 100644 index 0000000000..ed26c01026 --- /dev/null +++ b/queue-6.14/media-cec-use-us_to_ktime-where-appropriate.patch @@ -0,0 +1,81 @@ +From f7cea4792cb0ba04f12d546629c5dbe54c906d49 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Mar 2025 20:11:25 +0500 +Subject: media: cec: use us_to_ktime() where appropriate + +From: Vitaliy Shevtsov + +[ Upstream commit c0c1a6bf80e9075e3f6b81fd542550d8eb91e57a ] + +[Why] +There are several ns_to_ktime() calls that require using nanoseconds. It is +better to replace them with us_to_ktime() to make code clear, getting rid +of multiplication by 1000. + +Also the timer function code may have an integer wrap-around issue. Since +both tx_custom_low_usecs and tx_custom_high_usecs can be set to up to +9999999 from the user space via cec_pin_error_inj_parse_line(), this may +cause usecs to be overflowed when adap->monitor_pin_cnt is zero and usecs +is multiplied by 1000. + +[How] +Take advantage of using an appropriate helper func us_to_ktime() instead of +ns_to_ktime() to improve readability and to make the code clearer. And this +also mitigates possible integer wrap-arounds when usecs value is too large +and it is multiplied by 1000. + +Found by Linux Verification Center (linuxtesting.org) with Svace. + +Signed-off-by: Vitaliy Shevtsov +Signed-off-by: Hans Verkuil +Signed-off-by: Sasha Levin +--- + drivers/media/cec/core/cec-pin.c | 11 +++++------ + 1 file changed, 5 insertions(+), 6 deletions(-) + +diff --git a/drivers/media/cec/core/cec-pin.c b/drivers/media/cec/core/cec-pin.c +index a70451d99ebc9..f232c3df7ee16 100644 +--- a/drivers/media/cec/core/cec-pin.c ++++ b/drivers/media/cec/core/cec-pin.c +@@ -873,19 +873,19 @@ static enum hrtimer_restart cec_pin_timer(struct hrtimer *timer) + if (pin->wait_usecs > 150) { + pin->wait_usecs -= 100; + pin->timer_ts = ktime_add_us(ts, 100); +- hrtimer_forward_now(timer, ns_to_ktime(100000)); ++ hrtimer_forward_now(timer, us_to_ktime(100)); + return HRTIMER_RESTART; + } + if (pin->wait_usecs > 100) { + pin->wait_usecs /= 2; + pin->timer_ts = ktime_add_us(ts, pin->wait_usecs); + hrtimer_forward_now(timer, +- ns_to_ktime(pin->wait_usecs * 1000)); ++ us_to_ktime(pin->wait_usecs)); + return HRTIMER_RESTART; + } + pin->timer_ts = ktime_add_us(ts, pin->wait_usecs); + hrtimer_forward_now(timer, +- ns_to_ktime(pin->wait_usecs * 1000)); ++ us_to_ktime(pin->wait_usecs)); + pin->wait_usecs = 0; + return HRTIMER_RESTART; + } +@@ -1020,13 +1020,12 @@ static enum hrtimer_restart cec_pin_timer(struct hrtimer *timer) + if (!adap->monitor_pin_cnt || usecs <= 150) { + pin->wait_usecs = 0; + pin->timer_ts = ktime_add_us(ts, usecs); +- hrtimer_forward_now(timer, +- ns_to_ktime(usecs * 1000)); ++ hrtimer_forward_now(timer, us_to_ktime(usecs)); + return HRTIMER_RESTART; + } + pin->wait_usecs = usecs - 100; + pin->timer_ts = ktime_add_us(ts, 100); +- hrtimer_forward_now(timer, ns_to_ktime(100000)); ++ hrtimer_forward_now(timer, us_to_ktime(100)); + return HRTIMER_RESTART; + } + +-- +2.39.5 + diff --git a/queue-6.14/media-cx231xx-set-device_caps-for-417.patch b/queue-6.14/media-cx231xx-set-device_caps-for-417.patch new file mode 100644 index 0000000000..9f5dbd2e9b --- /dev/null +++ b/queue-6.14/media-cx231xx-set-device_caps-for-417.patch @@ -0,0 +1,40 @@ +From dbbe4ee6a2a37eb0da5500ca4556058bf97fcf40 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 24 Feb 2025 14:13:24 +0100 +Subject: media: cx231xx: set device_caps for 417 + +From: Hans Verkuil + +[ Upstream commit a79efc44b51432490538a55b9753a721f7d3ea42 ] + +The video_device for the MPEG encoder did not set device_caps. + +Add this, otherwise the video device can't be registered (you get a +WARN_ON instead). + +Not seen before since currently 417 support is disabled, but I found +this while experimenting with it. + +Signed-off-by: Hans Verkuil +Signed-off-by: Mauro Carvalho Chehab +Signed-off-by: Sasha Levin +--- + drivers/media/usb/cx231xx/cx231xx-417.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/media/usb/cx231xx/cx231xx-417.c b/drivers/media/usb/cx231xx/cx231xx-417.c +index a4a9781328c50..06d61e52f018c 100644 +--- a/drivers/media/usb/cx231xx/cx231xx-417.c ++++ b/drivers/media/usb/cx231xx/cx231xx-417.c +@@ -1720,6 +1720,8 @@ static void cx231xx_video_dev_init( + vfd->lock = &dev->lock; + vfd->release = video_device_release_empty; + vfd->ctrl_handler = &dev->mpeg_ctrl_handler.hdl; ++ vfd->device_caps = V4L2_CAP_READWRITE | V4L2_CAP_STREAMING | ++ V4L2_CAP_VIDEO_CAPTURE; + video_set_drvdata(vfd, dev); + if (dev->tuner_type == TUNER_ABSENT) { + v4l2_disable_ioctl(vfd, VIDIOC_G_FREQUENCY); +-- +2.39.5 + diff --git a/queue-6.14/media-i2c-imx219-correct-the-minimum-vblanking-value.patch b/queue-6.14/media-i2c-imx219-correct-the-minimum-vblanking-value.patch new file mode 100644 index 0000000000..760574c683 --- /dev/null +++ b/queue-6.14/media-i2c-imx219-correct-the-minimum-vblanking-value.patch @@ -0,0 +1,40 @@ +From 955cc49005f44abb8f2ec0154802075071bcfe07 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 4 Feb 2025 12:34:36 +0530 +Subject: media: i2c: imx219: Correct the minimum vblanking value + +From: David Plowman + +[ Upstream commit e3b82d49bf676f3c873e642038765eac32ab6d39 ] + +The datasheet for this sensor documents the minimum vblanking as being +32 lines. It does fix some problems with occasional black lines at the +bottom of images (tested on Raspberry Pi). + +Signed-off-by: David Plowman +Reviewed-by: Jacopo Mondi +Reviewed-by: Dave Stevenson +Signed-off-by: Jai Luthra +Signed-off-by: Sakari Ailus +Signed-off-by: Hans Verkuil +Signed-off-by: Sasha Levin +--- + drivers/media/i2c/imx219.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/media/i2c/imx219.c b/drivers/media/i2c/imx219.c +index 64227eb423d43..dd5a8577d7479 100644 +--- a/drivers/media/i2c/imx219.c ++++ b/drivers/media/i2c/imx219.c +@@ -73,7 +73,7 @@ + #define IMX219_REG_VTS CCI_REG16(0x0160) + #define IMX219_VTS_MAX 0xffff + +-#define IMX219_VBLANK_MIN 4 ++#define IMX219_VBLANK_MIN 32 + + /* HBLANK control - read only */ + #define IMX219_PPL_DEFAULT 3448 +-- +2.39.5 + diff --git a/queue-6.14/media-i2c-ov2740-free-control-handler-on-error-path.patch b/queue-6.14/media-i2c-ov2740-free-control-handler-on-error-path.patch new file mode 100644 index 0000000000..adc1e09e88 --- /dev/null +++ b/queue-6.14/media-i2c-ov2740-free-control-handler-on-error-path.patch @@ -0,0 +1,40 @@ +From 588e70f42c037871ce2c659ab03946bffb17c98b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 10 Jan 2025 09:33:33 +0200 +Subject: media: i2c: ov2740: Free control handler on error path + +From: Sakari Ailus + +[ Upstream commit 71dfb2c7548994aad6cb0a316c2601e7144d15a5 ] + +The control handler wasn't freed if v4l2_fwnode_device_parse() failed. Do +that now. + +Co-developed-by: Hans de Goede +Signed-off-by: Hans de Goede +Signed-off-by: Sakari Ailus +Signed-off-by: Hans Verkuil +Signed-off-by: Sasha Levin +--- + drivers/media/i2c/ov2740.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/media/i2c/ov2740.c b/drivers/media/i2c/ov2740.c +index 9a5d118b87b01..04e93618f408a 100644 +--- a/drivers/media/i2c/ov2740.c ++++ b/drivers/media/i2c/ov2740.c +@@ -828,8 +828,10 @@ static int ov2740_init_controls(struct ov2740 *ov2740) + 0, 0, ov2740_test_pattern_menu); + + ret = v4l2_fwnode_device_parse(&client->dev, &props); +- if (ret) ++ if (ret) { ++ v4l2_ctrl_handler_free(ctrl_hdlr); + return ret; ++ } + + v4l2_ctrl_new_fwnode_properties(ctrl_hdlr, &ov2740_ctrl_ops, &props); + +-- +2.39.5 + diff --git a/queue-6.14/media-imx335-set-vblank-immediately.patch b/queue-6.14/media-imx335-set-vblank-immediately.patch new file mode 100644 index 0000000000..81a4f42baa --- /dev/null +++ b/queue-6.14/media-imx335-set-vblank-immediately.patch @@ -0,0 +1,66 @@ +From 27429774510d80581d42ec24a31cbbdd1bc28ee3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 28 Feb 2025 18:17:31 +0900 +Subject: media: imx335: Set vblank immediately + +From: Paul Elder + +[ Upstream commit c0aa40f45fef80b4182704d1bc089cbf8ae8bed0 ] + +When the vblank v4l2 control is set, it does not get written to the +hardware unless exposure is also changed. Change the behavior such that +the vblank is written immediately when the control is set, as setting +the vblank without changing the exposure is a valid use case (such as +for changing the frame rate). + +Signed-off-by: Paul Elder +Reviewed-by: Kieran Bingham +Signed-off-by: Sakari Ailus +Signed-off-by: Hans Verkuil +Signed-off-by: Sasha Levin +--- + drivers/media/i2c/imx335.c | 21 +++++++++++++++------ + 1 file changed, 15 insertions(+), 6 deletions(-) + +diff --git a/drivers/media/i2c/imx335.c b/drivers/media/i2c/imx335.c +index fcfd1d851bd4a..0beb80b8c4581 100644 +--- a/drivers/media/i2c/imx335.c ++++ b/drivers/media/i2c/imx335.c +@@ -559,12 +559,14 @@ static int imx335_set_ctrl(struct v4l2_ctrl *ctrl) + imx335->vblank, + imx335->vblank + imx335->cur_mode->height); + +- return __v4l2_ctrl_modify_range(imx335->exp_ctrl, +- IMX335_EXPOSURE_MIN, +- imx335->vblank + +- imx335->cur_mode->height - +- IMX335_EXPOSURE_OFFSET, +- 1, IMX335_EXPOSURE_DEFAULT); ++ ret = __v4l2_ctrl_modify_range(imx335->exp_ctrl, ++ IMX335_EXPOSURE_MIN, ++ imx335->vblank + ++ imx335->cur_mode->height - ++ IMX335_EXPOSURE_OFFSET, ++ 1, IMX335_EXPOSURE_DEFAULT); ++ if (ret) ++ return ret; + } + + /* +@@ -575,6 +577,13 @@ static int imx335_set_ctrl(struct v4l2_ctrl *ctrl) + return 0; + + switch (ctrl->id) { ++ case V4L2_CID_VBLANK: ++ exposure = imx335->exp_ctrl->val; ++ analog_gain = imx335->again_ctrl->val; ++ ++ ret = imx335_update_exp_gain(imx335, exposure, analog_gain); ++ ++ break; + case V4L2_CID_EXPOSURE: + exposure = ctrl->val; + analog_gain = imx335->again_ctrl->val; +-- +2.39.5 + diff --git a/queue-6.14/media-qcom-camss-add-default-case-in-vfe_src_pad_cod.patch b/queue-6.14/media-qcom-camss-add-default-case-in-vfe_src_pad_cod.patch new file mode 100644 index 0000000000..12cc76df11 --- /dev/null +++ b/queue-6.14/media-qcom-camss-add-default-case-in-vfe_src_pad_cod.patch @@ -0,0 +1,38 @@ +From f19f43ace03ad7aba554952cb531568ed833448d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 13 Jan 2025 10:01:27 +0530 +Subject: media: qcom: camss: Add default case in vfe_src_pad_code + +From: Depeng Shao + +[ Upstream commit 2f4204bb00b32eca3391a468d3b37e87feb96fa9 ] + +Add a default case in vfe_src_pad_code to get rid of a compile +warning if a new hw enum is added. + +Signed-off-by: Depeng Shao +Reviewed-by: Bryan O'Donoghue +Signed-off-by: Hans Verkuil +Signed-off-by: Sasha Levin +--- + drivers/media/platform/qcom/camss/camss-vfe.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/drivers/media/platform/qcom/camss/camss-vfe.c b/drivers/media/platform/qcom/camss/camss-vfe.c +index 95f6a1ac7eaf5..3c5811c6c028e 100644 +--- a/drivers/media/platform/qcom/camss/camss-vfe.c ++++ b/drivers/media/platform/qcom/camss/camss-vfe.c +@@ -400,6 +400,10 @@ static u32 vfe_src_pad_code(struct vfe_line *line, u32 sink_code, + return sink_code; + } + break; ++ default: ++ WARN(1, "Unsupported HW version: %x\n", ++ vfe->camss->res->version); ++ break; + } + return 0; + } +-- +2.39.5 + diff --git a/queue-6.14/media-qcom-camss-csid-only-add-tpg-v4l2-ctrl-if-tpg-.patch b/queue-6.14/media-qcom-camss-csid-only-add-tpg-v4l2-ctrl-if-tpg-.patch new file mode 100644 index 0000000000..9a03e3df10 --- /dev/null +++ b/queue-6.14/media-qcom-camss-csid-only-add-tpg-v4l2-ctrl-if-tpg-.patch @@ -0,0 +1,141 @@ +From 9b0d9278bd9788fd1a1907fa96447a1be52b92ac Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 13 Jan 2025 10:01:28 +0530 +Subject: media: qcom: camss: csid: Only add TPG v4l2 ctrl if TPG hardware is + available + +From: Depeng Shao + +[ Upstream commit 2f1361f862a68063f37362f1beb400e78e289581 ] + +There is no CSID TPG on some SoCs, so the v4l2 ctrl in CSID driver +shouldn't be registered. Checking the supported TPG modes to indicate +if the TPG hardware exists or not and only registering v4l2 ctrl for +CSID only when the TPG hardware is present. + +Signed-off-by: Depeng Shao +Signed-off-by: Hans Verkuil +Signed-off-by: Sasha Levin +--- + .../media/platform/qcom/camss/camss-csid.c | 60 +++++++++++-------- + 1 file changed, 35 insertions(+), 25 deletions(-) + +diff --git a/drivers/media/platform/qcom/camss/camss-csid.c b/drivers/media/platform/qcom/camss/camss-csid.c +index 858db5d4ca75c..e51f2ed3f0315 100644 +--- a/drivers/media/platform/qcom/camss/camss-csid.c ++++ b/drivers/media/platform/qcom/camss/camss-csid.c +@@ -683,11 +683,13 @@ static int csid_set_stream(struct v4l2_subdev *sd, int enable) + int ret; + + if (enable) { +- ret = v4l2_ctrl_handler_setup(&csid->ctrls); +- if (ret < 0) { +- dev_err(csid->camss->dev, +- "could not sync v4l2 controls: %d\n", ret); +- return ret; ++ if (csid->testgen.nmodes != CSID_PAYLOAD_MODE_DISABLED) { ++ ret = v4l2_ctrl_handler_setup(&csid->ctrls); ++ if (ret < 0) { ++ dev_err(csid->camss->dev, ++ "could not sync v4l2 controls: %d\n", ret); ++ return ret; ++ } + } + + if (!csid->testgen.enabled && +@@ -761,7 +763,8 @@ static void csid_try_format(struct csid_device *csid, + break; + + case MSM_CSID_PAD_SRC: +- if (csid->testgen_mode->cur.val == 0) { ++ if (csid->testgen.nmodes == CSID_PAYLOAD_MODE_DISABLED || ++ csid->testgen_mode->cur.val == 0) { + /* Test generator is disabled, */ + /* keep pad formats in sync */ + u32 code = fmt->code; +@@ -811,7 +814,8 @@ static int csid_enum_mbus_code(struct v4l2_subdev *sd, + + code->code = csid->res->formats->formats[code->index].code; + } else { +- if (csid->testgen_mode->cur.val == 0) { ++ if (csid->testgen.nmodes == CSID_PAYLOAD_MODE_DISABLED || ++ csid->testgen_mode->cur.val == 0) { + struct v4l2_mbus_framefmt *sink_fmt; + + sink_fmt = __csid_get_format(csid, sd_state, +@@ -1190,7 +1194,8 @@ static int csid_link_setup(struct media_entity *entity, + + /* If test generator is enabled */ + /* do not allow a link from CSIPHY to CSID */ +- if (csid->testgen_mode->cur.val != 0) ++ if (csid->testgen.nmodes != CSID_PAYLOAD_MODE_DISABLED && ++ csid->testgen_mode->cur.val != 0) + return -EBUSY; + + sd = media_entity_to_v4l2_subdev(remote->entity); +@@ -1283,24 +1288,27 @@ int msm_csid_register_entity(struct csid_device *csid, + MSM_CSID_NAME, csid->id); + v4l2_set_subdevdata(sd, csid); + +- ret = v4l2_ctrl_handler_init(&csid->ctrls, 1); +- if (ret < 0) { +- dev_err(dev, "Failed to init ctrl handler: %d\n", ret); +- return ret; +- } ++ if (csid->testgen.nmodes != CSID_PAYLOAD_MODE_DISABLED) { ++ ret = v4l2_ctrl_handler_init(&csid->ctrls, 1); ++ if (ret < 0) { ++ dev_err(dev, "Failed to init ctrl handler: %d\n", ret); ++ return ret; ++ } + +- csid->testgen_mode = v4l2_ctrl_new_std_menu_items(&csid->ctrls, +- &csid_ctrl_ops, V4L2_CID_TEST_PATTERN, +- csid->testgen.nmodes, 0, 0, +- csid->testgen.modes); ++ csid->testgen_mode = ++ v4l2_ctrl_new_std_menu_items(&csid->ctrls, ++ &csid_ctrl_ops, V4L2_CID_TEST_PATTERN, ++ csid->testgen.nmodes, 0, 0, ++ csid->testgen.modes); + +- if (csid->ctrls.error) { +- dev_err(dev, "Failed to init ctrl: %d\n", csid->ctrls.error); +- ret = csid->ctrls.error; +- goto free_ctrl; +- } ++ if (csid->ctrls.error) { ++ dev_err(dev, "Failed to init ctrl: %d\n", csid->ctrls.error); ++ ret = csid->ctrls.error; ++ goto free_ctrl; ++ } + +- csid->subdev.ctrl_handler = &csid->ctrls; ++ csid->subdev.ctrl_handler = &csid->ctrls; ++ } + + ret = csid_init_formats(sd, NULL); + if (ret < 0) { +@@ -1331,7 +1339,8 @@ int msm_csid_register_entity(struct csid_device *csid, + media_cleanup: + media_entity_cleanup(&sd->entity); + free_ctrl: +- v4l2_ctrl_handler_free(&csid->ctrls); ++ if (csid->testgen.nmodes != CSID_PAYLOAD_MODE_DISABLED) ++ v4l2_ctrl_handler_free(&csid->ctrls); + + return ret; + } +@@ -1344,7 +1353,8 @@ void msm_csid_unregister_entity(struct csid_device *csid) + { + v4l2_device_unregister_subdev(&csid->subdev); + media_entity_cleanup(&csid->subdev.entity); +- v4l2_ctrl_handler_free(&csid->ctrls); ++ if (csid->testgen.nmodes != CSID_PAYLOAD_MODE_DISABLED) ++ v4l2_ctrl_handler_free(&csid->ctrls); + } + + inline bool csid_is_lite(struct csid_device *csid) +-- +2.39.5 + diff --git a/queue-6.14/media-stm32-csi-add-missing-pm_runtime_put-on-error.patch b/queue-6.14/media-stm32-csi-add-missing-pm_runtime_put-on-error.patch new file mode 100644 index 0000000000..714c06859d --- /dev/null +++ b/queue-6.14/media-stm32-csi-add-missing-pm_runtime_put-on-error.patch @@ -0,0 +1,68 @@ +From 929ac089d93fca68ade7bbe89989e57b08d6c133 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 13 Jan 2025 09:57:53 +0100 +Subject: media: stm32: csi: add missing pm_runtime_put on error + +From: Alain Volmat + +[ Upstream commit f7cd9c94959e7a5b8c4eca33e20bd6ba1b048a64 ] + +Within the stm32_csi_start function, pm_runtime_put should +be called upon error following pm_runtime_get_sync. +Rework the function error handling by putting a label in +order to have common error handling for all calls requiring +pm_runtime_put. + +Signed-off-by: Alain Volmat +Signed-off-by: Sakari Ailus +Signed-off-by: Hans Verkuil +Signed-off-by: Sasha Levin +--- + drivers/media/platform/st/stm32/stm32-csi.c | 16 +++++++++------- + 1 file changed, 9 insertions(+), 7 deletions(-) + +diff --git a/drivers/media/platform/st/stm32/stm32-csi.c b/drivers/media/platform/st/stm32/stm32-csi.c +index a4f8db608cedd..0c776e4a7ce83 100644 +--- a/drivers/media/platform/st/stm32/stm32-csi.c ++++ b/drivers/media/platform/st/stm32/stm32-csi.c +@@ -499,21 +499,19 @@ static int stm32_csi_start(struct stm32_csi_dev *csidev, + + ret = pm_runtime_get_sync(csidev->dev); + if (ret < 0) +- return ret; ++ goto error_put; + + /* Retrieve CSI2PHY clock rate to compute CCFR value */ + phy_clk_frate = clk_get_rate(csidev->clks[STM32_CSI_CLK_CSI2PHY].clk); + if (!phy_clk_frate) { +- pm_runtime_put(csidev->dev); + dev_err(csidev->dev, "CSI2PHY clock rate invalid (0)\n"); +- return ret; ++ ret = -EINVAL; ++ goto error_put; + } + + ret = stm32_csi_setup_lane_merger(csidev); +- if (ret) { +- pm_runtime_put(csidev->dev); +- return ret; +- } ++ if (ret) ++ goto error_put; + + /* Enable the CSI */ + writel_relaxed(STM32_CSI_CR_CSIEN, csidev->base + STM32_CSI_CR); +@@ -569,6 +567,10 @@ static int stm32_csi_start(struct stm32_csi_dev *csidev, + writel_relaxed(0, csidev->base + STM32_CSI_PMCR); + + return ret; ++ ++error_put: ++ pm_runtime_put(csidev->dev); ++ return ret; + } + + static void stm32_csi_stop(struct stm32_csi_dev *csidev) +-- +2.39.5 + diff --git a/queue-6.14/media-stm32-csi-use-array_size-to-search-d-phy-table.patch b/queue-6.14/media-stm32-csi-use-array_size-to-search-d-phy-table.patch new file mode 100644 index 0000000000..27f20b4948 --- /dev/null +++ b/queue-6.14/media-stm32-csi-use-array_size-to-search-d-phy-table.patch @@ -0,0 +1,82 @@ +From 730521f922b1bad822c42750d47065062f398274 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 13 Jan 2025 09:57:55 +0100 +Subject: media: stm32: csi: use ARRAY_SIZE to search D-PHY table + +From: Alain Volmat + +[ Upstream commit a3a91b6e62be24c5df47a800c367504cb41e502b ] + +Within stm32_csi_start, use ARRAY_SIZE loop in order to search +for the right setting. +Avoid useless init of lanes_ie / lanes_en. + +Signed-off-by: Alain Volmat +Signed-off-by: Sakari Ailus +Signed-off-by: Hans Verkuil +Signed-off-by: Sasha Levin +--- + drivers/media/platform/st/stm32/stm32-csi.c | 20 +++++++++++--------- + 1 file changed, 11 insertions(+), 9 deletions(-) + +diff --git a/drivers/media/platform/st/stm32/stm32-csi.c b/drivers/media/platform/st/stm32/stm32-csi.c +index 48941aae8c9b8..a4f8db608cedd 100644 +--- a/drivers/media/platform/st/stm32/stm32-csi.c ++++ b/drivers/media/platform/st/stm32/stm32-csi.c +@@ -325,7 +325,6 @@ static const struct stm32_csi_mbps_phy_reg snps_stm32mp25[] = { + { .mbps = 2400, .hsfreqrange = 0x47, .osc_freq_target = 442 }, + { .mbps = 2450, .hsfreqrange = 0x48, .osc_freq_target = 451 }, + { .mbps = 2500, .hsfreqrange = 0x49, .osc_freq_target = 460 }, +- { /* sentinel */ } + }; + + static const struct v4l2_mbus_framefmt fmt_default = { +@@ -444,13 +443,13 @@ static void stm32_csi_phy_reg_write(struct stm32_csi_dev *csidev, + static int stm32_csi_start(struct stm32_csi_dev *csidev, + struct v4l2_subdev_state *state) + { +- const struct stm32_csi_mbps_phy_reg *phy_regs; ++ const struct stm32_csi_mbps_phy_reg *phy_regs = NULL; + struct v4l2_mbus_framefmt *sink_fmt; + const struct stm32_csi_fmts *fmt; + unsigned long phy_clk_frate; ++ u32 lanes_ie, lanes_en; + unsigned int mbps; +- u32 lanes_ie = 0; +- u32 lanes_en = 0; ++ unsigned int i; + s64 link_freq; + int ret; + u32 ccfr; +@@ -474,11 +473,14 @@ static int stm32_csi_start(struct stm32_csi_dev *csidev, + mbps = div_s64(link_freq, 500000); + dev_dbg(csidev->dev, "Computed Mbps: %u\n", mbps); + +- for (phy_regs = snps_stm32mp25; phy_regs->mbps != 0; phy_regs++) +- if (phy_regs->mbps >= mbps) ++ for (i = 0; i < ARRAY_SIZE(snps_stm32mp25); i++) { ++ if (snps_stm32mp25[i].mbps >= mbps) { ++ phy_regs = &snps_stm32mp25[i]; + break; ++ } ++ } + +- if (!phy_regs->mbps) { ++ if (!phy_regs) { + dev_err(csidev->dev, "Unsupported PHY speed (%u Mbps)", mbps); + return -ERANGE; + } +@@ -488,8 +490,8 @@ static int stm32_csi_start(struct stm32_csi_dev *csidev, + phy_regs->osc_freq_target); + + /* Prepare lanes related configuration bits */ +- lanes_ie |= STM32_CSI_SR1_DL0_ERRORS; +- lanes_en |= STM32_CSI_PCR_DL0EN; ++ lanes_ie = STM32_CSI_SR1_DL0_ERRORS; ++ lanes_en = STM32_CSI_PCR_DL0EN; + if (csidev->num_lanes == 2) { + lanes_ie |= STM32_CSI_SR1_DL1_ERRORS; + lanes_en |= STM32_CSI_PCR_DL1EN; +-- +2.39.5 + diff --git a/queue-6.14/media-tc358746-improve-calculation-of-the-d-phy-timi.patch b/queue-6.14/media-tc358746-improve-calculation-of-the-d-phy-timi.patch new file mode 100644 index 0000000000..9ec2daf46c --- /dev/null +++ b/queue-6.14/media-tc358746-improve-calculation-of-the-d-phy-timi.patch @@ -0,0 +1,80 @@ +From 1ed20d45c9467a92c3d2586ecd8f3afe5dcd2014 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 Jan 2025 17:07:01 +0100 +Subject: media: tc358746: improve calculation of the D-PHY timing registers + +From: Matthias Fend + +[ Upstream commit 78d7265e2e1ce349e7f3c6a085f2b66d7b73f4ca ] + +When calculating D-PHY registers, using data rates that are not multiples +of 16 can lead to precision loss in division operations. This can result in +register values that produce timing violations against the MIPI standard. + +An example: +cfg->hs_clk_rate = 294MHz +hf_clk = 18 + +If the desired value in cfg->init is 100us, which is the minimum allowed +value, then the LINEINITCNT register is calculated as 1799. But since the +actual clock is 18.375MHz instead of 18MHz, this setting results in a time +that is shorter than 100us and thus violates the standard. The correct +value for LINEINITCNT would be 1837. + +Improve the precision of calculations by using Hz instead of MHz as unit. + +Signed-off-by: Matthias Fend +Reviewed-by: Marco Felsch +Signed-off-by: Hans Verkuil +Signed-off-by: Sasha Levin +--- + drivers/media/i2c/tc358746.c | 19 +++++++------------ + 1 file changed, 7 insertions(+), 12 deletions(-) + +diff --git a/drivers/media/i2c/tc358746.c b/drivers/media/i2c/tc358746.c +index 389582420ba78..048a1a381b333 100644 +--- a/drivers/media/i2c/tc358746.c ++++ b/drivers/media/i2c/tc358746.c +@@ -460,24 +460,20 @@ static int tc358746_apply_misc_config(struct tc358746 *tc358746) + return err; + } + +-/* Use MHz as base so the div needs no u64 */ +-static u32 tc358746_cfg_to_cnt(unsigned int cfg_val, +- unsigned int clk_mhz, +- unsigned int time_base) ++static u32 tc358746_cfg_to_cnt(unsigned long cfg_val, unsigned long clk_hz, ++ unsigned long long time_base) + { +- return DIV_ROUND_UP(cfg_val * clk_mhz, time_base); ++ return div64_u64((u64)cfg_val * clk_hz + time_base - 1, time_base); + } + +-static u32 tc358746_ps_to_cnt(unsigned int cfg_val, +- unsigned int clk_mhz) ++static u32 tc358746_ps_to_cnt(unsigned long cfg_val, unsigned long clk_hz) + { +- return tc358746_cfg_to_cnt(cfg_val, clk_mhz, USEC_PER_SEC); ++ return tc358746_cfg_to_cnt(cfg_val, clk_hz, PSEC_PER_SEC); + } + +-static u32 tc358746_us_to_cnt(unsigned int cfg_val, +- unsigned int clk_mhz) ++static u32 tc358746_us_to_cnt(unsigned long cfg_val, unsigned long clk_hz) + { +- return tc358746_cfg_to_cnt(cfg_val, clk_mhz, 1); ++ return tc358746_cfg_to_cnt(cfg_val, clk_hz, USEC_PER_SEC); + } + + static int tc358746_apply_dphy_config(struct tc358746 *tc358746) +@@ -492,7 +488,6 @@ static int tc358746_apply_dphy_config(struct tc358746 *tc358746) + + /* The hs_byte_clk is also called SYSCLK in the excel sheet */ + hs_byte_clk = cfg->hs_clk_rate / 8; +- hs_byte_clk /= HZ_PER_MHZ; + hf_clk = hs_byte_clk / 2; + + val = tc358746_us_to_cnt(cfg->init, hf_clk) - 1; +-- +2.39.5 + diff --git a/queue-6.14/media-test-drivers-vivid-don-t-call-schedule-in-loop.patch b/queue-6.14/media-test-drivers-vivid-don-t-call-schedule-in-loop.patch new file mode 100644 index 0000000000..a5475b1e36 --- /dev/null +++ b/queue-6.14/media-test-drivers-vivid-don-t-call-schedule-in-loop.patch @@ -0,0 +1,128 @@ +From 63809221d437e74748ee61f6e5d01c257b3ba24b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 9 Dec 2024 16:00:16 +0100 +Subject: media: test-drivers: vivid: don't call schedule in loop + +From: Hans Verkuil + +[ Upstream commit e4740118b752005cbed339aec9a1d1c43620e0b9 ] + +Artem reported that the CPU load was 100% when capturing from +vivid at low resolution with ffmpeg. + +This was caused by: + +while (time_is_after_jiffies(cur_jiffies + wait_jiffies) && + !kthread_should_stop()) + schedule(); + +If there are no other processes running that can be scheduled, +then this is basically a busy-loop. + +Change it to wait_event_interruptible_timeout() which doesn't +have that problem. + +Signed-off-by: Hans Verkuil +Reported-by: Artem S. Tashkinov +Closes: https://bugzilla.kernel.org/show_bug.cgi?id=219570 +Reviewed-by: Nicolas Dufresne +Signed-off-by: Mauro Carvalho Chehab +Signed-off-by: Sasha Levin +--- + drivers/media/test-drivers/vivid/vivid-kthread-cap.c | 11 ++++++++--- + drivers/media/test-drivers/vivid/vivid-kthread-out.c | 11 ++++++++--- + .../media/test-drivers/vivid/vivid-kthread-touch.c | 11 ++++++++--- + drivers/media/test-drivers/vivid/vivid-sdr-cap.c | 11 ++++++++--- + 4 files changed, 32 insertions(+), 12 deletions(-) + +diff --git a/drivers/media/test-drivers/vivid/vivid-kthread-cap.c b/drivers/media/test-drivers/vivid/vivid-kthread-cap.c +index 669bd96da4c79..273e8ed8c2a90 100644 +--- a/drivers/media/test-drivers/vivid/vivid-kthread-cap.c ++++ b/drivers/media/test-drivers/vivid/vivid-kthread-cap.c +@@ -789,9 +789,14 @@ static int vivid_thread_vid_cap(void *data) + next_jiffies_since_start = jiffies_since_start; + + wait_jiffies = next_jiffies_since_start - jiffies_since_start; +- while (time_is_after_jiffies(cur_jiffies + wait_jiffies) && +- !kthread_should_stop()) +- schedule(); ++ if (!time_is_after_jiffies(cur_jiffies + wait_jiffies)) ++ continue; ++ ++ wait_queue_head_t wait; ++ ++ init_waitqueue_head(&wait); ++ wait_event_interruptible_timeout(wait, kthread_should_stop(), ++ cur_jiffies + wait_jiffies - jiffies); + } + dprintk(dev, 1, "Video Capture Thread End\n"); + return 0; +diff --git a/drivers/media/test-drivers/vivid/vivid-kthread-out.c b/drivers/media/test-drivers/vivid/vivid-kthread-out.c +index fac6208b51da8..015a7b166a1e6 100644 +--- a/drivers/media/test-drivers/vivid/vivid-kthread-out.c ++++ b/drivers/media/test-drivers/vivid/vivid-kthread-out.c +@@ -235,9 +235,14 @@ static int vivid_thread_vid_out(void *data) + next_jiffies_since_start = jiffies_since_start; + + wait_jiffies = next_jiffies_since_start - jiffies_since_start; +- while (time_is_after_jiffies(cur_jiffies + wait_jiffies) && +- !kthread_should_stop()) +- schedule(); ++ if (!time_is_after_jiffies(cur_jiffies + wait_jiffies)) ++ continue; ++ ++ wait_queue_head_t wait; ++ ++ init_waitqueue_head(&wait); ++ wait_event_interruptible_timeout(wait, kthread_should_stop(), ++ cur_jiffies + wait_jiffies - jiffies); + } + dprintk(dev, 1, "Video Output Thread End\n"); + return 0; +diff --git a/drivers/media/test-drivers/vivid/vivid-kthread-touch.c b/drivers/media/test-drivers/vivid/vivid-kthread-touch.c +index fa711ee36a3fb..c862689786b69 100644 +--- a/drivers/media/test-drivers/vivid/vivid-kthread-touch.c ++++ b/drivers/media/test-drivers/vivid/vivid-kthread-touch.c +@@ -135,9 +135,14 @@ static int vivid_thread_touch_cap(void *data) + next_jiffies_since_start = jiffies_since_start; + + wait_jiffies = next_jiffies_since_start - jiffies_since_start; +- while (time_is_after_jiffies(cur_jiffies + wait_jiffies) && +- !kthread_should_stop()) +- schedule(); ++ if (!time_is_after_jiffies(cur_jiffies + wait_jiffies)) ++ continue; ++ ++ wait_queue_head_t wait; ++ ++ init_waitqueue_head(&wait); ++ wait_event_interruptible_timeout(wait, kthread_should_stop(), ++ cur_jiffies + wait_jiffies - jiffies); + } + dprintk(dev, 1, "Touch Capture Thread End\n"); + return 0; +diff --git a/drivers/media/test-drivers/vivid/vivid-sdr-cap.c b/drivers/media/test-drivers/vivid/vivid-sdr-cap.c +index 74a91d28c8be9..c633fc2ed664f 100644 +--- a/drivers/media/test-drivers/vivid/vivid-sdr-cap.c ++++ b/drivers/media/test-drivers/vivid/vivid-sdr-cap.c +@@ -206,9 +206,14 @@ static int vivid_thread_sdr_cap(void *data) + next_jiffies_since_start = jiffies_since_start; + + wait_jiffies = next_jiffies_since_start - jiffies_since_start; +- while (time_is_after_jiffies(cur_jiffies + wait_jiffies) && +- !kthread_should_stop()) +- schedule(); ++ if (!time_is_after_jiffies(cur_jiffies + wait_jiffies)) ++ continue; ++ ++ wait_queue_head_t wait; ++ ++ init_waitqueue_head(&wait); ++ wait_event_interruptible_timeout(wait, kthread_should_stop(), ++ cur_jiffies + wait_jiffies - jiffies); + } + dprintk(dev, 1, "SDR Capture Thread End\n"); + return 0; +-- +2.39.5 + diff --git a/queue-6.14/media-uvcvideo-add-sanity-check-to-uvc_ioctl_xu_ctrl.patch b/queue-6.14/media-uvcvideo-add-sanity-check-to-uvc_ioctl_xu_ctrl.patch new file mode 100644 index 0000000000..2830fa6211 --- /dev/null +++ b/queue-6.14/media-uvcvideo-add-sanity-check-to-uvc_ioctl_xu_ctrl.patch @@ -0,0 +1,42 @@ +From 3ea6d8dfec4f3c5548a24e5dc4daeed3ea8177c5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 3 Feb 2025 11:55:51 +0000 +Subject: media: uvcvideo: Add sanity check to uvc_ioctl_xu_ctrl_map + +From: Ricardo Ribalda + +[ Upstream commit 990262fdfce24d6055df9711424343d94d829e6a ] + +Do not process unknown data types. + +Tested-by: Yunke Cao +Reviewed-by: Hans de Goede +Signed-off-by: Ricardo Ribalda +Link: https://lore.kernel.org/r/20250203-uvc-roi-v17-15-5900a9fed613@chromium.org +Signed-off-by: Hans de Goede +Signed-off-by: Hans Verkuil +Signed-off-by: Sasha Levin +--- + drivers/media/usb/uvc/uvc_v4l2.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/drivers/media/usb/uvc/uvc_v4l2.c b/drivers/media/usb/uvc/uvc_v4l2.c +index 93c6cdb238812..75216507cbdcf 100644 +--- a/drivers/media/usb/uvc/uvc_v4l2.c ++++ b/drivers/media/usb/uvc/uvc_v4l2.c +@@ -108,6 +108,12 @@ static int uvc_ioctl_xu_ctrl_map(struct uvc_video_chain *chain, + struct uvc_control_mapping *map; + int ret; + ++ if (xmap->data_type > UVC_CTRL_DATA_TYPE_BITMASK) { ++ uvc_dbg(chain->dev, CONTROL, ++ "Unsupported UVC data type %u\n", xmap->data_type); ++ return -EINVAL; ++ } ++ + map = kzalloc(sizeof(*map), GFP_KERNEL); + if (map == NULL) + return -ENOMEM; +-- +2.39.5 + diff --git a/queue-6.14/media-uvcvideo-handle-uvc-menu-translation-inside-uv.patch b/queue-6.14/media-uvcvideo-handle-uvc-menu-translation-inside-uv.patch new file mode 100644 index 0000000000..cc2ac30d07 --- /dev/null +++ b/queue-6.14/media-uvcvideo-handle-uvc-menu-translation-inside-uv.patch @@ -0,0 +1,161 @@ +From f93ccf5192861c3127b0fe4db039770abce38416 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 3 Feb 2025 11:55:40 +0000 +Subject: media: uvcvideo: Handle uvc menu translation inside uvc_get_le_value + +From: Ricardo Ribalda + +[ Upstream commit 9109a0b4cb10fd681e9c6e9a4497a6fec5b91c39 ] + +map->get() gets a value from an uvc_control in "UVC format" and converts +it to a value that can be consumed by v4l2. + +Instead of using a special get function for V4L2_CTRL_TYPE_MENU, we +were converting from uvc_get_le_value in two different places. + +Move the conversion to uvc_get_le_value(). + +Reviewed-by: Hans de Goede +Tested-by: Yunke Cao +Signed-off-by: Ricardo Ribalda +Link: https://lore.kernel.org/r/20250203-uvc-roi-v17-4-5900a9fed613@chromium.org +Signed-off-by: Hans de Goede +Signed-off-by: Hans Verkuil +Signed-off-by: Sasha Levin +--- + drivers/media/usb/uvc/uvc_ctrl.c | 77 +++++++++++++------------------- + 1 file changed, 32 insertions(+), 45 deletions(-) + +diff --git a/drivers/media/usb/uvc/uvc_ctrl.c b/drivers/media/usb/uvc/uvc_ctrl.c +index 4e58476d305ef..4a55cf78ec526 100644 +--- a/drivers/media/usb/uvc/uvc_ctrl.c ++++ b/drivers/media/usb/uvc/uvc_ctrl.c +@@ -862,6 +862,25 @@ static inline void uvc_clear_bit(u8 *data, int bit) + data[bit >> 3] &= ~(1 << (bit & 7)); + } + ++static s32 uvc_menu_to_v4l2_menu(struct uvc_control_mapping *mapping, s32 val) ++{ ++ unsigned int i; ++ ++ for (i = 0; BIT(i) <= mapping->menu_mask; ++i) { ++ u32 menu_value; ++ ++ if (!test_bit(i, &mapping->menu_mask)) ++ continue; ++ ++ menu_value = uvc_mapping_get_menu_value(mapping, i); ++ ++ if (menu_value == val) ++ return i; ++ } ++ ++ return val; ++} ++ + /* + * Extract the bit string specified by mapping->offset and mapping->size + * from the little-endian data stored at 'data' and return the result as +@@ -896,6 +915,16 @@ static s32 uvc_get_le_value(struct uvc_control_mapping *mapping, + if (mapping->data_type == UVC_CTRL_DATA_TYPE_SIGNED) + value |= -(value & (1 << (mapping->size - 1))); + ++ /* If it is a menu, convert from uvc to v4l2. */ ++ if (mapping->v4l2_type != V4L2_CTRL_TYPE_MENU) ++ return value; ++ ++ switch (query) { ++ case UVC_GET_CUR: ++ case UVC_GET_DEF: ++ return uvc_menu_to_v4l2_menu(mapping, value); ++ } ++ + return value; + } + +@@ -1060,32 +1089,6 @@ static int uvc_ctrl_populate_cache(struct uvc_video_chain *chain, + return 0; + } + +-static s32 __uvc_ctrl_get_value(struct uvc_control_mapping *mapping, +- const u8 *data) +-{ +- s32 value = mapping->get(mapping, UVC_GET_CUR, data); +- +- if (mapping->v4l2_type == V4L2_CTRL_TYPE_MENU) { +- unsigned int i; +- +- for (i = 0; BIT(i) <= mapping->menu_mask; ++i) { +- u32 menu_value; +- +- if (!test_bit(i, &mapping->menu_mask)) +- continue; +- +- menu_value = uvc_mapping_get_menu_value(mapping, i); +- +- if (menu_value == value) { +- value = i; +- break; +- } +- } +- } +- +- return value; +-} +- + static int __uvc_ctrl_load_cur(struct uvc_video_chain *chain, + struct uvc_control *ctrl) + { +@@ -1136,8 +1139,8 @@ static int __uvc_ctrl_get(struct uvc_video_chain *chain, + if (ret < 0) + return ret; + +- *value = __uvc_ctrl_get_value(mapping, +- uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT)); ++ *value = mapping->get(mapping, UVC_GET_CUR, ++ uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT)); + + return 0; + } +@@ -1287,7 +1290,6 @@ static int __uvc_query_v4l2_ctrl(struct uvc_video_chain *chain, + { + struct uvc_control_mapping *master_map = NULL; + struct uvc_control *master_ctrl = NULL; +- unsigned int i; + + memset(v4l2_ctrl, 0, sizeof(*v4l2_ctrl)); + v4l2_ctrl->id = mapping->id; +@@ -1330,21 +1332,6 @@ static int __uvc_query_v4l2_ctrl(struct uvc_video_chain *chain, + v4l2_ctrl->minimum = ffs(mapping->menu_mask) - 1; + v4l2_ctrl->maximum = fls(mapping->menu_mask) - 1; + v4l2_ctrl->step = 1; +- +- for (i = 0; BIT(i) <= mapping->menu_mask; ++i) { +- u32 menu_value; +- +- if (!test_bit(i, &mapping->menu_mask)) +- continue; +- +- menu_value = uvc_mapping_get_menu_value(mapping, i); +- +- if (menu_value == v4l2_ctrl->default_value) { +- v4l2_ctrl->default_value = i; +- break; +- } +- } +- + return 0; + + case V4L2_CTRL_TYPE_BOOLEAN: +@@ -1630,7 +1617,7 @@ void uvc_ctrl_status_event(struct uvc_video_chain *chain, + uvc_ctrl_set_handle(handle, ctrl, NULL); + + list_for_each_entry(mapping, &ctrl->info.mappings, list) { +- s32 value = __uvc_ctrl_get_value(mapping, data); ++ s32 value = mapping->get(mapping, UVC_GET_CUR, data); + + /* + * handle may be NULL here if the device sends auto-update +-- +2.39.5 + diff --git a/queue-6.14/media-v4l-memset-argument-to-0-before-calling-get_mb.patch b/queue-6.14/media-v4l-memset-argument-to-0-before-calling-get_mb.patch new file mode 100644 index 0000000000..d67b545b2e --- /dev/null +++ b/queue-6.14/media-v4l-memset-argument-to-0-before-calling-get_mb.patch @@ -0,0 +1,55 @@ +From 11fb2fba0629459f098d9b5845883a7db5a6697b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 16 Dec 2024 10:48:49 +0200 +Subject: media: v4l: Memset argument to 0 before calling get_mbus_config pad + op + +From: Sakari Ailus + +[ Upstream commit 91d6a99acfa5ce9f95ede775074b80f7193bd717 ] + +Memset the config argument to get_mbus_config V4L2 sub-device pad +operation to zero before calling the operation. This ensures the callers +don't need to bother with it nor the implementations need to set all +fields that may not be relevant to them. + +Signed-off-by: Sakari Ailus +Reviewed-by: Tomi Valkeinen +Signed-off-by: Hans Verkuil +Signed-off-by: Sasha Levin +--- + drivers/media/v4l2-core/v4l2-subdev.c | 2 ++ + include/media/v4l2-subdev.h | 4 +++- + 2 files changed, 5 insertions(+), 1 deletion(-) + +diff --git a/drivers/media/v4l2-core/v4l2-subdev.c b/drivers/media/v4l2-core/v4l2-subdev.c +index cde1774c9098d..a3074f469b150 100644 +--- a/drivers/media/v4l2-core/v4l2-subdev.c ++++ b/drivers/media/v4l2-core/v4l2-subdev.c +@@ -444,6 +444,8 @@ static int call_enum_dv_timings(struct v4l2_subdev *sd, + static int call_get_mbus_config(struct v4l2_subdev *sd, unsigned int pad, + struct v4l2_mbus_config *config) + { ++ memset(config, 0, sizeof(*config)); ++ + return check_pad(sd, pad) ? : + sd->ops->pad->get_mbus_config(sd, pad, config); + } +diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h +index 2f2200875b038..57f2bcb4eb16c 100644 +--- a/include/media/v4l2-subdev.h ++++ b/include/media/v4l2-subdev.h +@@ -822,7 +822,9 @@ struct v4l2_subdev_state { + * possible configuration from the remote end, likely calling + * this operation as close as possible to stream on time. The + * operation shall fail if the pad index it has been called on +- * is not valid or in case of unrecoverable failures. ++ * is not valid or in case of unrecoverable failures. The ++ * config argument has been memset to 0 just before calling ++ * the op. + * + * @set_routing: Enable or disable data connection routes described in the + * subdevice routing table. Subdevs that implement this operation +-- +2.39.5 + diff --git a/queue-6.14/mei-vsc-use-struct-vsc_tp_packet-as-vsc-tp-tx_buf-an.patch b/queue-6.14/mei-vsc-use-struct-vsc_tp_packet-as-vsc-tp-tx_buf-an.patch new file mode 100644 index 0000000000..7eb3b104ac --- /dev/null +++ b/queue-6.14/mei-vsc-use-struct-vsc_tp_packet-as-vsc-tp-tx_buf-an.patch @@ -0,0 +1,82 @@ +From 3be4e488b5b483386cb72e98cffa5d1a1f8573fc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 18 Mar 2025 15:12:03 +0100 +Subject: mei: vsc: Use struct vsc_tp_packet as vsc-tp tx_buf and rx_buf type + +From: Hans de Goede + +[ Upstream commit f88c0c72ffb014e5eba676ee337c4eb3b1d6a119 ] + +vsc_tp.tx_buf and vsc_tp.rx_buf point to a struct vsc_tp_packet, use +the correct type instead of "void *" and use sizeof(*ptr) when allocating +memory for these buffers. + +Signed-off-by: Hans de Goede +Reviewed-by: Alexander Usyskin +Reviewed-by: Sakari Ailus +Link: https://lore.kernel.org/r/20250318141203.94342-3-hdegoede@redhat.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/misc/mei/vsc-tp.c | 14 +++++++------- + 1 file changed, 7 insertions(+), 7 deletions(-) + +diff --git a/drivers/misc/mei/vsc-tp.c b/drivers/misc/mei/vsc-tp.c +index fa553d4914b6e..da26a080916c5 100644 +--- a/drivers/misc/mei/vsc-tp.c ++++ b/drivers/misc/mei/vsc-tp.c +@@ -71,8 +71,8 @@ struct vsc_tp { + u32 seq; + + /* command buffer */ +- void *tx_buf; +- void *rx_buf; ++ struct vsc_tp_packet *tx_buf; ++ struct vsc_tp_packet *rx_buf; + + atomic_t assert_cnt; + wait_queue_head_t xfer_wait; +@@ -164,7 +164,7 @@ static int vsc_tp_xfer_helper(struct vsc_tp *tp, struct vsc_tp_packet *pkt, + { + int ret, offset = 0, cpy_len, src_len, dst_len = sizeof(struct vsc_tp_packet_hdr); + int next_xfer_len = VSC_TP_PACKET_SIZE(pkt) + VSC_TP_XFER_TIMEOUT_BYTES; +- u8 *src, *crc_src, *rx_buf = tp->rx_buf; ++ u8 *src, *crc_src, *rx_buf = (u8 *)tp->rx_buf; + int count_down = VSC_TP_MAX_XFER_COUNT; + u32 recv_crc = 0, crc = ~0; + struct vsc_tp_packet_hdr ack; +@@ -324,7 +324,7 @@ int vsc_tp_rom_xfer(struct vsc_tp *tp, const void *obuf, void *ibuf, size_t len) + guard(mutex)(&tp->mutex); + + /* rom xfer is big endian */ +- cpu_to_be32_array(tp->tx_buf, obuf, words); ++ cpu_to_be32_array((u32 *)tp->tx_buf, obuf, words); + + ret = read_poll_timeout(gpiod_get_value_cansleep, ret, + !ret, VSC_TP_ROM_XFER_POLL_DELAY_US, +@@ -340,7 +340,7 @@ int vsc_tp_rom_xfer(struct vsc_tp *tp, const void *obuf, void *ibuf, size_t len) + return ret; + + if (ibuf) +- be32_to_cpu_array(ibuf, tp->rx_buf, words); ++ be32_to_cpu_array(ibuf, (u32 *)tp->rx_buf, words); + + return ret; + } +@@ -494,11 +494,11 @@ static int vsc_tp_probe(struct spi_device *spi) + if (!tp) + return -ENOMEM; + +- tp->tx_buf = devm_kzalloc(dev, VSC_TP_MAX_XFER_SIZE, GFP_KERNEL); ++ tp->tx_buf = devm_kzalloc(dev, sizeof(*tp->tx_buf), GFP_KERNEL); + if (!tp->tx_buf) + return -ENOMEM; + +- tp->rx_buf = devm_kzalloc(dev, VSC_TP_MAX_XFER_SIZE, GFP_KERNEL); ++ tp->rx_buf = devm_kzalloc(dev, sizeof(*tp->rx_buf), GFP_KERNEL); + if (!tp->rx_buf) + return -ENOMEM; + +-- +2.39.5 + diff --git a/queue-6.14/mfd-axp20x-axp717-add-axp717_ts_pin_cfg-to-writeable.patch b/queue-6.14/mfd-axp20x-axp717-add-axp717_ts_pin_cfg-to-writeable.patch new file mode 100644 index 0000000000..6f6d433b1b --- /dev/null +++ b/queue-6.14/mfd-axp20x-axp717-add-axp717_ts_pin_cfg-to-writeable.patch @@ -0,0 +1,49 @@ +From 6a7a84a63bd8faa5baf17d1432d9303367c763ee Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 4 Feb 2025 09:58:32 -0600 +Subject: mfd: axp20x: AXP717: Add AXP717_TS_PIN_CFG to writeable regs + +From: Chris Morgan + +[ Upstream commit bfad07fe298bfba0c7ddab87c5b5325970203a1e ] + +Add AXP717_TS_PIN_CFG (register 0x50) to the table of writeable +registers so that the temperature sensor can be configured by the +battery driver. + +Signed-off-by: Chris Morgan +Link: https://lore.kernel.org/r/20250204155835.161973-3-macroalpha82@gmail.com +Signed-off-by: Lee Jones +Signed-off-by: Sasha Levin +--- + drivers/mfd/axp20x.c | 1 + + include/linux/mfd/axp20x.h | 1 + + 2 files changed, 2 insertions(+) + +diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c +index cff56deba24f0..e9914e8a29a33 100644 +--- a/drivers/mfd/axp20x.c ++++ b/drivers/mfd/axp20x.c +@@ -224,6 +224,7 @@ static const struct regmap_range axp717_writeable_ranges[] = { + regmap_reg_range(AXP717_VSYS_V_POWEROFF, AXP717_VSYS_V_POWEROFF), + regmap_reg_range(AXP717_IRQ0_EN, AXP717_IRQ4_EN), + regmap_reg_range(AXP717_IRQ0_STATE, AXP717_IRQ4_STATE), ++ regmap_reg_range(AXP717_TS_PIN_CFG, AXP717_TS_PIN_CFG), + regmap_reg_range(AXP717_ICC_CHG_SET, AXP717_CV_CHG_SET), + regmap_reg_range(AXP717_DCDC_OUTPUT_CONTROL, AXP717_CPUSLDO_CONTROL), + regmap_reg_range(AXP717_ADC_CH_EN_CONTROL, AXP717_ADC_CH_EN_CONTROL), +diff --git a/include/linux/mfd/axp20x.h b/include/linux/mfd/axp20x.h +index c3df0e615fbf4..3c5aecf1d4b5b 100644 +--- a/include/linux/mfd/axp20x.h ++++ b/include/linux/mfd/axp20x.h +@@ -137,6 +137,7 @@ enum axp20x_variants { + #define AXP717_IRQ2_STATE 0x4a + #define AXP717_IRQ3_STATE 0x4b + #define AXP717_IRQ4_STATE 0x4c ++#define AXP717_TS_PIN_CFG 0x50 + #define AXP717_ICC_CHG_SET 0x62 + #define AXP717_ITERM_CHG_SET 0x63 + #define AXP717_CV_CHG_SET 0x64 +-- +2.39.5 + diff --git a/queue-6.14/mfd-syscon-add-check-for-invalid-resource-size.patch b/queue-6.14/mfd-syscon-add-check-for-invalid-resource-size.patch new file mode 100644 index 0000000000..9437873409 --- /dev/null +++ b/queue-6.14/mfd-syscon-add-check-for-invalid-resource-size.patch @@ -0,0 +1,58 @@ +From bb7af46c73c6233bbc8b6098fbc3d2755df3daa9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 12 Feb 2025 19:45:24 +0100 +Subject: mfd: syscon: Add check for invalid resource size + +From: Eder Zulian + +[ Upstream commit ba09916efb29f80e438a54e634970209ce12750f ] + +Add a consistency check to avoid assigning an invalid value to +max_register due to a possible DT misconfiguration. + +Suggested-by: Mark Langsdorf +Signed-off-by: Eder Zulian +Link: https://lore.kernel.org/r/20250212184524.585882-1-ezulian@redhat.com +Signed-off-by: Lee Jones +Signed-off-by: Sasha Levin +--- + drivers/mfd/syscon.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/drivers/mfd/syscon.c b/drivers/mfd/syscon.c +index aa4a9940b569a..ae71a2710bed8 100644 +--- a/drivers/mfd/syscon.c ++++ b/drivers/mfd/syscon.c +@@ -47,6 +47,7 @@ static struct syscon *of_syscon_register(struct device_node *np, bool check_res) + struct regmap_config syscon_config = syscon_regmap_config; + struct resource res; + struct reset_control *reset; ++ resource_size_t res_size; + + WARN_ON(!mutex_is_locked(&syscon_list_lock)); + +@@ -96,6 +97,12 @@ static struct syscon *of_syscon_register(struct device_node *np, bool check_res) + } + } + ++ res_size = resource_size(&res); ++ if (res_size < reg_io_width) { ++ ret = -EFAULT; ++ goto err_regmap; ++ } ++ + syscon_config.name = kasprintf(GFP_KERNEL, "%pOFn@%pa", np, &res.start); + if (!syscon_config.name) { + ret = -ENOMEM; +@@ -103,7 +110,7 @@ static struct syscon *of_syscon_register(struct device_node *np, bool check_res) + } + syscon_config.reg_stride = reg_io_width; + syscon_config.val_bits = reg_io_width * 8; +- syscon_config.max_register = resource_size(&res) - reg_io_width; ++ syscon_config.max_register = res_size - reg_io_width; + if (!syscon_config.max_register) + syscon_config.max_register_is_0 = true; + +-- +2.39.5 + diff --git a/queue-6.14/mfd-tps65219-remove-tps65219_reg_ti_dev_id-check.patch b/queue-6.14/mfd-tps65219-remove-tps65219_reg_ti_dev_id-check.patch new file mode 100644 index 0000000000..664d6796c7 --- /dev/null +++ b/queue-6.14/mfd-tps65219-remove-tps65219_reg_ti_dev_id-check.patch @@ -0,0 +1,58 @@ +From 3b4ee60d88a6e416400d0a771283d6a9d3a17a84 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Feb 2025 11:37:23 -0600 +Subject: mfd: tps65219: Remove TPS65219_REG_TI_DEV_ID check + +From: Shree Ramamoorthy + +[ Upstream commit 76b58d5111fdcffce615beb71520bc7a6f1742c9 ] + +The chipid macro/variable and regmap_read function call is not needed +because the TPS65219_REG_TI_DEV_ID register value is not a consistent value +across TPS65219 PMIC config versions. Reading from the DEV_ID register +without a consistent value to compare it to isn't useful. There isn't a +way to verify the match data ID is the same ID read from the DEV_ID device +register. 0xF0 isn't a DEV_ID value consistent across TPS65219 NVM +configurations. + +For TPS65215, there is a consistent value in bits 5-0 of the DEV_ID +register. However, there are other error checks in place within probe() +that apply to both PMICs rather than keeping this isolated check for one +PMIC. + +Signed-off-by: Shree Ramamoorthy +Link: https://lore.kernel.org/r/20250206173725.386720-4-s-ramamoorthy@ti.com +Signed-off-by: Lee Jones +Signed-off-by: Sasha Levin +--- + drivers/mfd/tps65219.c | 7 ------- + 1 file changed, 7 deletions(-) + +diff --git a/drivers/mfd/tps65219.c b/drivers/mfd/tps65219.c +index 081c5a30b04a2..4aca922658e34 100644 +--- a/drivers/mfd/tps65219.c ++++ b/drivers/mfd/tps65219.c +@@ -221,7 +221,6 @@ static const struct regmap_irq_chip tps65219_irq_chip = { + static int tps65219_probe(struct i2c_client *client) + { + struct tps65219 *tps; +- unsigned int chipid; + bool pwr_button; + int ret; + +@@ -246,12 +245,6 @@ static int tps65219_probe(struct i2c_client *client) + if (ret) + return ret; + +- ret = regmap_read(tps->regmap, TPS65219_REG_TI_DEV_ID, &chipid); +- if (ret) { +- dev_err(tps->dev, "Failed to read device ID: %d\n", ret); +- return ret; +- } +- + ret = devm_mfd_add_devices(tps->dev, PLATFORM_DEVID_AUTO, + tps65219_cells, ARRAY_SIZE(tps65219_cells), + NULL, 0, regmap_irq_get_domain(tps->irq_data)); +-- +2.39.5 + diff --git a/queue-6.14/mips-pm-cps-use-per-cpu-variables-as-per-cpu-not-per.patch b/queue-6.14/mips-pm-cps-use-per-cpu-variables-as-per-cpu-not-per.patch new file mode 100644 index 0000000000..aab83be94c --- /dev/null +++ b/queue-6.14/mips-pm-cps-use-per-cpu-variables-as-per-cpu-not-per.patch @@ -0,0 +1,128 @@ +From 389bcb990935a18c9eadb6294e5de4744576f886 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 29 Jan 2025 13:32:48 +0100 +Subject: MIPS: pm-cps: Use per-CPU variables as per-CPU, not per-core + +From: Paul Burton + +[ Upstream commit 00a134fc2bb4a5f8fada58cf7ff4259149691d64 ] + +The pm-cps code has up until now used per-CPU variables indexed by core, +rather than CPU number, in order to share data amongst sibling CPUs (ie. +VPs/threads in a core). This works fine for single cluster systems, but +with multi-cluster systems a core number is no longer unique in the +system, leading to sharing between CPUs that are not actually siblings. + +Avoid this issue by using per-CPU variables as they are more generally +used - ie. access them using CPU numbers rather than core numbers. +Sharing between siblings is then accomplished by: + - Assigning the same pointer to entries for each sibling CPU for the + nc_asm_enter & ready_count variables, which allow this by virtue of + being per-CPU pointers. + + - Indexing by the first CPU set in a CPUs cpu_sibling_map in the case + of pm_barrier, for which we can't use the previous approach because + the per-CPU variable is not a pointer. + +Signed-off-by: Paul Burton +Signed-off-by: Dragan Mladjenovic +Signed-off-by: Aleksandar Rikalo +Tested-by: Serge Semin +Tested-by: Gregory CLEMENT +Signed-off-by: Thomas Bogendoerfer +Signed-off-by: Sasha Levin +--- + arch/mips/kernel/pm-cps.c | 30 +++++++++++++++++------------- + 1 file changed, 17 insertions(+), 13 deletions(-) + +diff --git a/arch/mips/kernel/pm-cps.c b/arch/mips/kernel/pm-cps.c +index d09ca77e624d7..9369a8dc385e2 100644 +--- a/arch/mips/kernel/pm-cps.c ++++ b/arch/mips/kernel/pm-cps.c +@@ -57,10 +57,7 @@ static DEFINE_PER_CPU_ALIGNED(u32*, ready_count); + /* Indicates online CPUs coupled with the current CPU */ + static DEFINE_PER_CPU_ALIGNED(cpumask_t, online_coupled); + +-/* +- * Used to synchronize entry to deep idle states. Actually per-core rather +- * than per-CPU. +- */ ++/* Used to synchronize entry to deep idle states */ + static DEFINE_PER_CPU_ALIGNED(atomic_t, pm_barrier); + + /* Saved CPU state across the CPS_PM_POWER_GATED state */ +@@ -112,9 +109,10 @@ int cps_pm_enter_state(enum cps_pm_state state) + cps_nc_entry_fn entry; + struct core_boot_config *core_cfg; + struct vpe_boot_config *vpe_cfg; ++ atomic_t *barrier; + + /* Check that there is an entry function for this state */ +- entry = per_cpu(nc_asm_enter, core)[state]; ++ entry = per_cpu(nc_asm_enter, cpu)[state]; + if (!entry) + return -EINVAL; + +@@ -150,7 +148,7 @@ int cps_pm_enter_state(enum cps_pm_state state) + smp_mb__after_atomic(); + + /* Create a non-coherent mapping of the core ready_count */ +- core_ready_count = per_cpu(ready_count, core); ++ core_ready_count = per_cpu(ready_count, cpu); + nc_addr = kmap_noncoherent(virt_to_page(core_ready_count), + (unsigned long)core_ready_count); + nc_addr += ((unsigned long)core_ready_count & ~PAGE_MASK); +@@ -158,7 +156,8 @@ int cps_pm_enter_state(enum cps_pm_state state) + + /* Ensure ready_count is zero-initialised before the assembly runs */ + WRITE_ONCE(*nc_core_ready_count, 0); +- coupled_barrier(&per_cpu(pm_barrier, core), online); ++ barrier = &per_cpu(pm_barrier, cpumask_first(&cpu_sibling_map[cpu])); ++ coupled_barrier(barrier, online); + + /* Run the generated entry code */ + left = entry(online, nc_core_ready_count); +@@ -629,12 +628,14 @@ static void *cps_gen_entry_code(unsigned cpu, enum cps_pm_state state) + + static int cps_pm_online_cpu(unsigned int cpu) + { +- enum cps_pm_state state; +- unsigned core = cpu_core(&cpu_data[cpu]); ++ unsigned int sibling, core; + void *entry_fn, *core_rc; ++ enum cps_pm_state state; ++ ++ core = cpu_core(&cpu_data[cpu]); + + for (state = CPS_PM_NC_WAIT; state < CPS_PM_STATE_COUNT; state++) { +- if (per_cpu(nc_asm_enter, core)[state]) ++ if (per_cpu(nc_asm_enter, cpu)[state]) + continue; + if (!test_bit(state, state_support)) + continue; +@@ -646,16 +647,19 @@ static int cps_pm_online_cpu(unsigned int cpu) + clear_bit(state, state_support); + } + +- per_cpu(nc_asm_enter, core)[state] = entry_fn; ++ for_each_cpu(sibling, &cpu_sibling_map[cpu]) ++ per_cpu(nc_asm_enter, sibling)[state] = entry_fn; + } + +- if (!per_cpu(ready_count, core)) { ++ if (!per_cpu(ready_count, cpu)) { + core_rc = kmalloc(sizeof(u32), GFP_KERNEL); + if (!core_rc) { + pr_err("Failed allocate core %u ready_count\n", core); + return -ENOMEM; + } +- per_cpu(ready_count, core) = core_rc; ++ ++ for_each_cpu(sibling, &cpu_sibling_map[cpu]) ++ per_cpu(ready_count, sibling) = core_rc; + } + + return 0; +-- +2.39.5 + diff --git a/queue-6.14/mips-use-arch-specific-syscall-name-match-function.patch b/queue-6.14/mips-use-arch-specific-syscall-name-match-function.patch new file mode 100644 index 0000000000..a10d1afb03 --- /dev/null +++ b/queue-6.14/mips-use-arch-specific-syscall-name-match-function.patch @@ -0,0 +1,55 @@ +From df17265e941ed7fd5e5b9f2e8038f4081a8fe2ed Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 9 Jun 2020 10:54:35 +0800 +Subject: MIPS: Use arch specific syscall name match function + +From: Bibo Mao + +[ Upstream commit 756276ce78d5624dc814f9d99f7d16c8fd51076e ] + +On MIPS system, most of the syscall function name begin with prefix +sys_. Some syscalls are special such as clone/fork, function name of +these begin with __sys_. Since scratch registers need be saved in +stack when these system calls happens. + +With ftrace system call method, system call functions are declared with +SYSCALL_DEFINEx, metadata of the system call symbol name begins with +sys_. Here mips specific function arch_syscall_match_sym_name is used to +compare function name between sys_call_table[] and metadata of syscall +symbol. + +Signed-off-by: Bibo Mao +Signed-off-by: Thomas Bogendoerfer +Signed-off-by: Sasha Levin +--- + arch/mips/include/asm/ftrace.h | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + +diff --git a/arch/mips/include/asm/ftrace.h b/arch/mips/include/asm/ftrace.h +index dc025888f6d28..b41fc10446688 100644 +--- a/arch/mips/include/asm/ftrace.h ++++ b/arch/mips/include/asm/ftrace.h +@@ -91,4 +91,20 @@ void prepare_ftrace_return(unsigned long *parent_ra_addr, unsigned long self_ra, + + #endif /* __ASSEMBLY__ */ + #endif /* CONFIG_FUNCTION_TRACER */ ++ ++#ifdef CONFIG_FTRACE_SYSCALLS ++#ifndef __ASSEMBLY__ ++/* ++ * Some syscall entry functions on mips start with "__sys_" (fork and clone, ++ * for instance). We should also match the sys_ variant with those. ++ */ ++#define ARCH_HAS_SYSCALL_MATCH_SYM_NAME ++static inline bool arch_syscall_match_sym_name(const char *sym, ++ const char *name) ++{ ++ return !strcmp(sym, name) || ++ (!strncmp(sym, "__sys_", 6) && !strcmp(sym + 6, name + 4)); ++} ++#endif /* __ASSEMBLY__ */ ++#endif /* CONFIG_FTRACE_SYSCALLS */ + #endif /* _ASM_MIPS_FTRACE_H */ +-- +2.39.5 + diff --git a/queue-6.14/misc-pci_endpoint_test-give-disabled-bars-a-distinct.patch b/queue-6.14/misc-pci_endpoint_test-give-disabled-bars-a-distinct.patch new file mode 100644 index 0000000000..67c01ed3c2 --- /dev/null +++ b/queue-6.14/misc-pci_endpoint_test-give-disabled-bars-a-distinct.patch @@ -0,0 +1,66 @@ +From 490832036da12ad8968bd1998b4be593a19e6b14 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 23 Jan 2025 13:01:48 +0100 +Subject: misc: pci_endpoint_test: Give disabled BARs a distinct error code +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Niklas Cassel + +[ Upstream commit 7e80bbef1d697dbce7a39cfad0df770880fe3f29 ] + +The current code returns -ENOMEM if test->bar[barno] is NULL. + +There can be two reasons why test->bar[barno] is NULL: + + 1) The pci_ioremap_bar() call in pci_endpoint_test_probe() failed. + 2) The BAR was skipped, because it is disabled by the endpoint. + +Many PCI endpoint controller drivers will disable all BARs in their +init function. A disabled BAR will have a size of 0. + +A PCI endpoint function driver will be able to enable any BAR that +is not marked as BAR_RESERVED (which means that the BAR should not +be touched by the EPF driver). + +Thus, perform check if the size is 0, before checking if +test->bar[barno] is NULL, such that we can return different errors. + +This will allow the selftests to return SKIP instead of FAIL for +disabled BARs. + +Signed-off-by: Niklas Cassel +Reviewed-by: Manivannan Sadhasivam +Link: https://lore.kernel.org/r/20250123120147.3603409-3-cassel@kernel.org +Signed-off-by: Manivannan Sadhasivam +[kwilczynski: commit log] +Signed-off-by: Krzysztof Wilczyński +Signed-off-by: Sasha Levin +--- + drivers/misc/pci_endpoint_test.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/drivers/misc/pci_endpoint_test.c b/drivers/misc/pci_endpoint_test.c +index 4c0f37ad0281b..8a7e860c06812 100644 +--- a/drivers/misc/pci_endpoint_test.c ++++ b/drivers/misc/pci_endpoint_test.c +@@ -295,11 +295,13 @@ static int pci_endpoint_test_bar(struct pci_endpoint_test *test, + struct pci_dev *pdev = test->pdev; + int buf_size; + ++ bar_size = pci_resource_len(pdev, barno); ++ if (!bar_size) ++ return -ENODATA; ++ + if (!test->bar[barno]) + return -ENOMEM; + +- bar_size = pci_resource_len(pdev, barno); +- + if (barno == test->test_reg_bar) + bar_size = 0x4; + +-- +2.39.5 + diff --git a/queue-6.14/mmc-dw_mmc-add-exynos7870-dw-mmc-support.patch b/queue-6.14/mmc-dw_mmc-add-exynos7870-dw-mmc-support.patch new file mode 100644 index 0000000000..420c70cdcf --- /dev/null +++ b/queue-6.14/mmc-dw_mmc-add-exynos7870-dw-mmc-support.patch @@ -0,0 +1,174 @@ +From a12bbab84a13269ad1251ba69c4c1550cb310419 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 19 Feb 2025 00:17:49 +0530 +Subject: mmc: dw_mmc: add exynos7870 DW MMC support + +From: Kaustabh Chakraborty + +[ Upstream commit 7cbe799ac10fd8be85af5e0615c4337f81e575f3 ] + +Add support for Exynos7870 DW MMC controllers, for both SMU and non-SMU +variants. These controllers require a quirk to access 64-bit FIFO in 32-bit +accesses (DW_MMC_QUIRK_FIFO64_32). + +Signed-off-by: Kaustabh Chakraborty +Link: https://lore.kernel.org/r/20250219-exynos7870-mmc-v2-3-b4255a3e39ed@disroot.org +Signed-off-by: Ulf Hansson +Signed-off-by: Sasha Levin +--- + drivers/mmc/host/dw_mmc-exynos.c | 41 +++++++++++++++++++++++++++++++- + 1 file changed, 40 insertions(+), 1 deletion(-) + +diff --git a/drivers/mmc/host/dw_mmc-exynos.c b/drivers/mmc/host/dw_mmc-exynos.c +index 53d32d0f2709e..e3548408ca392 100644 +--- a/drivers/mmc/host/dw_mmc-exynos.c ++++ b/drivers/mmc/host/dw_mmc-exynos.c +@@ -27,6 +27,8 @@ enum dw_mci_exynos_type { + DW_MCI_TYPE_EXYNOS5420_SMU, + DW_MCI_TYPE_EXYNOS7, + DW_MCI_TYPE_EXYNOS7_SMU, ++ DW_MCI_TYPE_EXYNOS7870, ++ DW_MCI_TYPE_EXYNOS7870_SMU, + DW_MCI_TYPE_ARTPEC8, + }; + +@@ -69,6 +71,12 @@ static struct dw_mci_exynos_compatible { + }, { + .compatible = "samsung,exynos7-dw-mshc-smu", + .ctrl_type = DW_MCI_TYPE_EXYNOS7_SMU, ++ }, { ++ .compatible = "samsung,exynos7870-dw-mshc", ++ .ctrl_type = DW_MCI_TYPE_EXYNOS7870, ++ }, { ++ .compatible = "samsung,exynos7870-dw-mshc-smu", ++ .ctrl_type = DW_MCI_TYPE_EXYNOS7870_SMU, + }, { + .compatible = "axis,artpec8-dw-mshc", + .ctrl_type = DW_MCI_TYPE_ARTPEC8, +@@ -85,6 +93,8 @@ static inline u8 dw_mci_exynos_get_ciu_div(struct dw_mci *host) + return EXYNOS4210_FIXED_CIU_CLK_DIV; + else if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 || + priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU || ++ priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870 || ++ priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870_SMU || + priv->ctrl_type == DW_MCI_TYPE_ARTPEC8) + return SDMMC_CLKSEL_GET_DIV(mci_readl(host, CLKSEL64)) + 1; + else +@@ -100,7 +110,8 @@ static void dw_mci_exynos_config_smu(struct dw_mci *host) + * set for non-ecryption mode at this time. + */ + if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS5420_SMU || +- priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU) { ++ priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU || ++ priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870_SMU) { + mci_writel(host, MPSBEGIN0, 0); + mci_writel(host, MPSEND0, SDMMC_ENDING_SEC_NR_MAX); + mci_writel(host, MPSCTRL0, SDMMC_MPSCTRL_SECURE_WRITE_BIT | +@@ -126,6 +137,12 @@ static int dw_mci_exynos_priv_init(struct dw_mci *host) + DQS_CTRL_GET_RD_DELAY(priv->saved_strobe_ctrl); + } + ++ if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870 || ++ priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870_SMU) { ++ /* Quirk needed for certain Exynos SoCs */ ++ host->quirks |= DW_MMC_QUIRK_FIFO64_32; ++ } ++ + if (priv->ctrl_type == DW_MCI_TYPE_ARTPEC8) { + /* Quirk needed for the ARTPEC-8 SoC */ + host->quirks |= DW_MMC_QUIRK_EXTENDED_TMOUT; +@@ -143,6 +160,8 @@ static void dw_mci_exynos_set_clksel_timing(struct dw_mci *host, u32 timing) + + if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 || + priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU || ++ priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870 || ++ priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870_SMU || + priv->ctrl_type == DW_MCI_TYPE_ARTPEC8) + clksel = mci_readl(host, CLKSEL64); + else +@@ -152,6 +171,8 @@ static void dw_mci_exynos_set_clksel_timing(struct dw_mci *host, u32 timing) + + if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 || + priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU || ++ priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870 || ++ priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870_SMU || + priv->ctrl_type == DW_MCI_TYPE_ARTPEC8) + mci_writel(host, CLKSEL64, clksel); + else +@@ -222,6 +243,8 @@ static int dw_mci_exynos_resume_noirq(struct device *dev) + + if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 || + priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU || ++ priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870 || ++ priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870_SMU || + priv->ctrl_type == DW_MCI_TYPE_ARTPEC8) + clksel = mci_readl(host, CLKSEL64); + else +@@ -230,6 +253,8 @@ static int dw_mci_exynos_resume_noirq(struct device *dev) + if (clksel & SDMMC_CLKSEL_WAKEUP_INT) { + if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 || + priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU || ++ priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870 || ++ priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870_SMU || + priv->ctrl_type == DW_MCI_TYPE_ARTPEC8) + mci_writel(host, CLKSEL64, clksel); + else +@@ -409,6 +434,8 @@ static inline u8 dw_mci_exynos_get_clksmpl(struct dw_mci *host) + + if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 || + priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU || ++ priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870 || ++ priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870_SMU || + priv->ctrl_type == DW_MCI_TYPE_ARTPEC8) + return SDMMC_CLKSEL_CCLK_SAMPLE(mci_readl(host, CLKSEL64)); + else +@@ -422,6 +449,8 @@ static inline void dw_mci_exynos_set_clksmpl(struct dw_mci *host, u8 sample) + + if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 || + priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU || ++ priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870 || ++ priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870_SMU || + priv->ctrl_type == DW_MCI_TYPE_ARTPEC8) + clksel = mci_readl(host, CLKSEL64); + else +@@ -429,6 +458,8 @@ static inline void dw_mci_exynos_set_clksmpl(struct dw_mci *host, u8 sample) + clksel = SDMMC_CLKSEL_UP_SAMPLE(clksel, sample); + if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 || + priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU || ++ priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870 || ++ priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870_SMU || + priv->ctrl_type == DW_MCI_TYPE_ARTPEC8) + mci_writel(host, CLKSEL64, clksel); + else +@@ -443,6 +474,8 @@ static inline u8 dw_mci_exynos_move_next_clksmpl(struct dw_mci *host) + + if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 || + priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU || ++ priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870 || ++ priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870_SMU || + priv->ctrl_type == DW_MCI_TYPE_ARTPEC8) + clksel = mci_readl(host, CLKSEL64); + else +@@ -453,6 +486,8 @@ static inline u8 dw_mci_exynos_move_next_clksmpl(struct dw_mci *host) + + if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 || + priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU || ++ priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870 || ++ priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870_SMU || + priv->ctrl_type == DW_MCI_TYPE_ARTPEC8) + mci_writel(host, CLKSEL64, clksel); + else +@@ -632,6 +667,10 @@ static const struct of_device_id dw_mci_exynos_match[] = { + .data = &exynos_drv_data, }, + { .compatible = "samsung,exynos7-dw-mshc-smu", + .data = &exynos_drv_data, }, ++ { .compatible = "samsung,exynos7870-dw-mshc", ++ .data = &exynos_drv_data, }, ++ { .compatible = "samsung,exynos7870-dw-mshc-smu", ++ .data = &exynos_drv_data, }, + { .compatible = "axis,artpec8-dw-mshc", + .data = &artpec_drv_data, }, + {}, +-- +2.39.5 + diff --git a/queue-6.14/mmc-host-wait-for-vdd-to-settle-on-card-power-off.patch b/queue-6.14/mmc-host-wait-for-vdd-to-settle-on-card-power-off.patch new file mode 100644 index 0000000000..19d82df4bb --- /dev/null +++ b/queue-6.14/mmc-host-wait-for-vdd-to-settle-on-card-power-off.patch @@ -0,0 +1,46 @@ +From 8e4d98a534311eef32572adbc84918ede7a03cd6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 14 Mar 2025 14:50:21 -0500 +Subject: mmc: host: Wait for Vdd to settle on card power off + +From: Erick Shepherd + +[ Upstream commit 31e75ed964582257f59156ce6a42860e1ae4cc39 ] + +The SD spec version 6.0 section 6.4.1.5 requires that Vdd must be +lowered to less than 0.5V for a minimum of 1 ms when powering off a +card. Increase wait to 15 ms so that voltage has time to drain down +to 0.5V and cards can power off correctly. Issues with voltage drain +time were only observed on Apollo Lake and Bay Trail host controllers +so this fix is limited to those devices. + +Signed-off-by: Erick Shepherd +Acked-by: Adrian Hunter +Link: https://lore.kernel.org/r/20250314195021.1588090-1-erick.shepherd@ni.com +Signed-off-by: Ulf Hansson +Signed-off-by: Sasha Levin +--- + drivers/mmc/host/sdhci-pci-core.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/drivers/mmc/host/sdhci-pci-core.c b/drivers/mmc/host/sdhci-pci-core.c +index 1f0bd723f0112..13a84b9309e06 100644 +--- a/drivers/mmc/host/sdhci-pci-core.c ++++ b/drivers/mmc/host/sdhci-pci-core.c +@@ -610,8 +610,12 @@ static void sdhci_intel_set_power(struct sdhci_host *host, unsigned char mode, + + sdhci_set_power(host, mode, vdd); + +- if (mode == MMC_POWER_OFF) ++ if (mode == MMC_POWER_OFF) { ++ if (slot->chip->pdev->device == PCI_DEVICE_ID_INTEL_APL_SD || ++ slot->chip->pdev->device == PCI_DEVICE_ID_INTEL_BYT_SD) ++ usleep_range(15000, 17500); + return; ++ } + + /* + * Bus power might not enable after D3 -> D0 transition due to the +-- +2.39.5 + diff --git a/queue-6.14/mmc-sdhci-disable-sd-card-clock-before-changing-para.patch b/queue-6.14/mmc-sdhci-disable-sd-card-clock-before-changing-para.patch new file mode 100644 index 0000000000..aa7faf6e54 --- /dev/null +++ b/queue-6.14/mmc-sdhci-disable-sd-card-clock-before-changing-para.patch @@ -0,0 +1,54 @@ +From 7c984b26b26153d97008ff9b74d5c41cc3f7416a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 11 Feb 2025 15:46:45 -0600 +Subject: mmc: sdhci: Disable SD card clock before changing parameters +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Erick Shepherd + +[ Upstream commit fb3bbc46c94f261b6156ee863c1b06c84cf157dc ] + +Per the SD Host Controller Simplified Specification v4.20 §3.2.3, change +the SD card clock parameters only after first disabling the external card +clock. Doing this fixes a spurious clock pulse on Baytrail and Apollo Lake +SD controllers which otherwise breaks voltage switching with a specific +Swissbit SD card. + +Signed-off-by: Kyle Roeschley +Signed-off-by: Brad Mouring +Signed-off-by: Erick Shepherd +Acked-by: Adrian Hunter +Link: https://lore.kernel.org/r/20250211214645.469279-1-erick.shepherd@ni.com +Signed-off-by: Ulf Hansson +Signed-off-by: Sasha Levin +--- + drivers/mmc/host/sdhci.c | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c +index f4a7733a8ad22..5f91b44891f9b 100644 +--- a/drivers/mmc/host/sdhci.c ++++ b/drivers/mmc/host/sdhci.c +@@ -2065,10 +2065,15 @@ void sdhci_set_clock(struct sdhci_host *host, unsigned int clock) + + host->mmc->actual_clock = 0; + +- sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL); ++ clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL); ++ if (clk & SDHCI_CLOCK_CARD_EN) ++ sdhci_writew(host, clk & ~SDHCI_CLOCK_CARD_EN, ++ SDHCI_CLOCK_CONTROL); + +- if (clock == 0) ++ if (clock == 0) { ++ sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL); + return; ++ } + + clk = sdhci_calc_clk(host, clock, &host->mmc->actual_clock); + sdhci_enable_clk(host, clk); +-- +2.39.5 + diff --git a/queue-6.14/mptcp-pm-userspace-flags-clearer-msg-if-no-remote-ad.patch b/queue-6.14/mptcp-pm-userspace-flags-clearer-msg-if-no-remote-ad.patch new file mode 100644 index 0000000000..c958dba146 --- /dev/null +++ b/queue-6.14/mptcp-pm-userspace-flags-clearer-msg-if-no-remote-ad.patch @@ -0,0 +1,55 @@ +From e1241a635e77a6c6f15110a13eef5daa4cc8874f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 7 Feb 2025 14:59:20 +0100 +Subject: mptcp: pm: userspace: flags: clearer msg if no remote addr + +From: Matthieu Baerts (NGI0) + +[ Upstream commit 58b21309f97b08b6b9814d1ee1419249eba9ef08 ] + +Since its introduction in commit 892f396c8e68 ("mptcp: netlink: issue +MP_PRIO signals from userspace PMs"), it was mandatory to specify the +remote address, because of the 'if (rem->addr.family == AF_UNSPEC)' +check done later one. + +In theory, this attribute can be optional, but it sounds better to be +precise to avoid sending the MP_PRIO on the wrong subflow, e.g. if there +are multiple subflows attached to the same local ID. This can be relaxed +later on if there is a need to act on multiple subflows with one +command. + +For the moment, the check to see if attr_rem is NULL can be removed, +because mptcp_pm_parse_entry() will do this check as well, no need to do +that differently here. + +Reviewed-by: Geliang Tang +Signed-off-by: Matthieu Baerts (NGI0) +Reviewed-by: Simon Horman +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/mptcp/pm_userspace.c | 8 +++----- + 1 file changed, 3 insertions(+), 5 deletions(-) + +diff --git a/net/mptcp/pm_userspace.c b/net/mptcp/pm_userspace.c +index 940ca94c88634..cd220742d2493 100644 +--- a/net/mptcp/pm_userspace.c ++++ b/net/mptcp/pm_userspace.c +@@ -583,11 +583,9 @@ int mptcp_userspace_pm_set_flags(struct sk_buff *skb, struct genl_info *info) + if (ret < 0) + goto set_flags_err; + +- if (attr_rem) { +- ret = mptcp_pm_parse_entry(attr_rem, info, false, &rem); +- if (ret < 0) +- goto set_flags_err; +- } ++ ret = mptcp_pm_parse_entry(attr_rem, info, false, &rem); ++ if (ret < 0) ++ goto set_flags_err; + + if (loc.addr.family == AF_UNSPEC || + rem.addr.family == AF_UNSPEC) { +-- +2.39.5 + diff --git a/queue-6.14/net-ethernet-mtk_ppe_offload-allow-qinq-double-eth_p.patch b/queue-6.14/net-ethernet-mtk_ppe_offload-allow-qinq-double-eth_p.patch new file mode 100644 index 0000000000..ddb66c7cc5 --- /dev/null +++ b/queue-6.14/net-ethernet-mtk_ppe_offload-allow-qinq-double-eth_p.patch @@ -0,0 +1,88 @@ +From cb74d0847afe9e6a8ccbafdefe2088d55ab31929 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 25 Feb 2025 21:15:09 +0100 +Subject: net: ethernet: mtk_ppe_offload: Allow QinQ, double ETH_P_8021Q only + +From: Eric Woudstra + +[ Upstream commit 7fe0353606d77a32c4c7f2814833dd1c043ebdd2 ] + +mtk_foe_entry_set_vlan() in mtk_ppe.c already supports double vlan +tagging, but mtk_flow_offload_replace() in mtk_ppe_offload.c only allows +for 1 vlan tag, optionally in combination with pppoe and dsa tags. + +However, mtk_foe_entry_set_vlan() only allows for setting the vlan id. +The protocol cannot be set, it is always ETH_P_8021Q, for inner and outer +tag. This patch adds QinQ support to mtk_flow_offload_replace(), only in +the case that both inner and outer tags are ETH_P_8021Q. + +Only PPPoE-in-Q (as before) and Q-in-Q are allowed. A combination +of PPPoE and Q-in-Q is not allowed. + +Signed-off-by: Eric Woudstra +Link: https://patch.msgid.link/20250225201509.20843-1-ericwouds@gmail.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + .../net/ethernet/mediatek/mtk_ppe_offload.c | 22 +++++++++---------- + 1 file changed, 11 insertions(+), 11 deletions(-) + +diff --git a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c +index f20bb390df3ad..c855fb799ce14 100644 +--- a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c ++++ b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c +@@ -34,8 +34,10 @@ struct mtk_flow_data { + u16 vlan_in; + + struct { +- u16 id; +- __be16 proto; ++ struct { ++ u16 id; ++ __be16 proto; ++ } vlans[2]; + u8 num; + } vlan; + struct { +@@ -349,18 +351,19 @@ mtk_flow_offload_replace(struct mtk_eth *eth, struct flow_cls_offload *f, + case FLOW_ACTION_CSUM: + break; + case FLOW_ACTION_VLAN_PUSH: +- if (data.vlan.num == 1 || ++ if (data.vlan.num + data.pppoe.num == 2 || + act->vlan.proto != htons(ETH_P_8021Q)) + return -EOPNOTSUPP; + +- data.vlan.id = act->vlan.vid; +- data.vlan.proto = act->vlan.proto; ++ data.vlan.vlans[data.vlan.num].id = act->vlan.vid; ++ data.vlan.vlans[data.vlan.num].proto = act->vlan.proto; + data.vlan.num++; + break; + case FLOW_ACTION_VLAN_POP: + break; + case FLOW_ACTION_PPPOE_PUSH: +- if (data.pppoe.num == 1) ++ if (data.pppoe.num == 1 || ++ data.vlan.num == 2) + return -EOPNOTSUPP; + + data.pppoe.sid = act->pppoe.sid; +@@ -450,12 +453,9 @@ mtk_flow_offload_replace(struct mtk_eth *eth, struct flow_cls_offload *f, + if (offload_type == MTK_PPE_PKT_TYPE_BRIDGE) + foe.bridge.vlan = data.vlan_in; + +- if (data.vlan.num == 1) { +- if (data.vlan.proto != htons(ETH_P_8021Q)) +- return -EOPNOTSUPP; ++ for (i = 0; i < data.vlan.num; i++) ++ mtk_foe_entry_set_vlan(eth, &foe, data.vlan.vlans[i].id); + +- mtk_foe_entry_set_vlan(eth, &foe, data.vlan.id); +- } + if (data.pppoe.num == 1) + mtk_foe_entry_set_pppoe(eth, &foe, data.pppoe.sid); + +-- +2.39.5 + diff --git a/queue-6.14/net-ethernet-ti-cpsw_new-populate-netdev-of_node.patch b/queue-6.14/net-ethernet-ti-cpsw_new-populate-netdev-of_node.patch new file mode 100644 index 0000000000..5b6c2aa061 --- /dev/null +++ b/queue-6.14/net-ethernet-ti-cpsw_new-populate-netdev-of_node.patch @@ -0,0 +1,37 @@ +From 73beb4826f12949227b87e9c9a5ec4a6191da179 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 3 Mar 2025 08:46:57 +0100 +Subject: net: ethernet: ti: cpsw_new: populate netdev of_node + +From: Alexander Sverdlin + +[ Upstream commit 7ff1c88fc89688c27f773ba956f65f0c11367269 ] + +So that of_find_net_device_by_node() can find CPSW ports and other DSA +switches can be stacked downstream. Tested in conjunction with KSZ8873. + +Reviewed-by: Siddharth Vadapalli +Reviewed-by: Andrew Lunn +Signed-off-by: Alexander Sverdlin +Link: https://patch.msgid.link/20250303074703.1758297-1-alexander.sverdlin@siemens.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/ti/cpsw_new.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/net/ethernet/ti/cpsw_new.c b/drivers/net/ethernet/ti/cpsw_new.c +index cec0a90659d94..66713bc931741 100644 +--- a/drivers/net/ethernet/ti/cpsw_new.c ++++ b/drivers/net/ethernet/ti/cpsw_new.c +@@ -1418,6 +1418,7 @@ static int cpsw_create_ports(struct cpsw_common *cpsw) + ndev->netdev_ops = &cpsw_netdev_ops; + ndev->ethtool_ops = &cpsw_ethtool_ops; + SET_NETDEV_DEV(ndev, dev); ++ ndev->dev.of_node = slave_data->slave_node; + + if (!napi_ndev) { + /* CPSW Host port CPDMA interface is shared between +-- +2.39.5 + diff --git a/queue-6.14/net-ethtool-prevent-flow-steering-to-rss-contexts-wh.patch b/queue-6.14/net-ethtool-prevent-flow-steering-to-rss-contexts-wh.patch new file mode 100644 index 0000000000..a33ae7bf59 --- /dev/null +++ b/queue-6.14/net-ethtool-prevent-flow-steering-to-rss-contexts-wh.patch @@ -0,0 +1,48 @@ +From 845cdfd025cb2eac5c949cecf90e9470493a1662 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Feb 2025 15:53:28 -0800 +Subject: net: ethtool: prevent flow steering to RSS contexts which don't exist + +From: Jakub Kicinski + +[ Upstream commit de7f7582dff292832fbdeaeff34e6b2ee6f9f95f ] + +Since commit 42dc431f5d0e ("ethtool: rss: prevent rss ctx deletion +when in use") we prevent removal of RSS contexts pointed to by +existing flow rules. Core should also prevent creation of rules +which point to RSS context which don't exist in the first place. + +Reviewed-by: Joe Damato +Link: https://patch.msgid.link/20250206235334.1425329-2-kuba@kernel.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/ethtool/ioctl.c | 12 ++++++++---- + 1 file changed, 8 insertions(+), 4 deletions(-) + +diff --git a/net/ethtool/ioctl.c b/net/ethtool/ioctl.c +index 1c3ba2247776b..0d3a70a18884f 100644 +--- a/net/ethtool/ioctl.c ++++ b/net/ethtool/ioctl.c +@@ -993,10 +993,14 @@ static noinline_for_stack int ethtool_set_rxnfc(struct net_device *dev, + return rc; + + /* Nonzero ring with RSS only makes sense if NIC adds them together */ +- if (cmd == ETHTOOL_SRXCLSRLINS && info.fs.flow_type & FLOW_RSS && +- !ops->cap_rss_rxnfc_adds && +- ethtool_get_flow_spec_ring(info.fs.ring_cookie)) +- return -EINVAL; ++ if (cmd == ETHTOOL_SRXCLSRLINS && info.fs.flow_type & FLOW_RSS) { ++ if (!ops->cap_rss_rxnfc_adds && ++ ethtool_get_flow_spec_ring(info.fs.ring_cookie)) ++ return -EINVAL; ++ ++ if (!xa_load(&dev->ethtool->rss_ctx, info.rss_context)) ++ return -EINVAL; ++ } + + if (cmd == ETHTOOL_SRXFH && ops->get_rxfh) { + struct ethtool_rxfh_param rxfh = {}; +-- +2.39.5 + diff --git a/queue-6.14/net-fec-refactor-mac-reset-to-function.patch b/queue-6.14/net-fec-refactor-mac-reset-to-function.patch new file mode 100644 index 0000000000..119b8c9500 --- /dev/null +++ b/queue-6.14/net-fec-refactor-mac-reset-to-function.patch @@ -0,0 +1,118 @@ +From 05c210bcafb4eb6a1de9d2a3134f5dca5a50598d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 7 Feb 2025 13:12:55 +0100 +Subject: net: fec: Refactor MAC reset to function +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Csókás, Bence + +[ Upstream commit 67800d296191d0a9bde0a7776f99ca1ddfa0fc26 ] + +The core is reset both in `fec_restart()` (called on link-up) and +`fec_stop()` (going to sleep, driver remove etc.). These two functions +had their separate implementations, which was at first only a register +write and a `udelay()` (and the accompanying block comment). However, +since then we got soft-reset (MAC disable) and Wake-on-LAN support, which +meant that these implementations diverged, often causing bugs. + +For instance, as of now, `fec_stop()` does not check for +`FEC_QUIRK_NO_HARD_RESET`, meaning the MII/RMII mode is cleared on eg. +a PM power-down event; and `fec_restart()` missed the refactor renaming +the "magic" constant `1` to `FEC_ECR_RESET`. + +To harmonize current implementations, and eliminate this source of +potential future bugs, refactor implementation to a common function. + +Reviewed-by: Michal Swiatkowski +Reviewed-by: Jacob Keller +Reviewed-by: Simon Horman +Signed-off-by: Csókás, Bence +Link: https://patch.msgid.link/20250207121255.161146-2-csokas.bence@prolan.hu +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/freescale/fec_main.c | 52 +++++++++++------------ + 1 file changed, 25 insertions(+), 27 deletions(-) + +diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c +index c5d5fa8d7dfdd..17e9bddb9ddd5 100644 +--- a/drivers/net/ethernet/freescale/fec_main.c ++++ b/drivers/net/ethernet/freescale/fec_main.c +@@ -1098,6 +1098,29 @@ static void fec_enet_enable_ring(struct net_device *ndev) + } + } + ++/* Whack a reset. We should wait for this. ++ * For i.MX6SX SOC, enet use AXI bus, we use disable MAC ++ * instead of reset MAC itself. ++ */ ++static void fec_ctrl_reset(struct fec_enet_private *fep, bool allow_wol) ++{ ++ u32 val; ++ ++ if (!allow_wol || !(fep->wol_flag & FEC_WOL_FLAG_SLEEP_ON)) { ++ if (fep->quirks & FEC_QUIRK_HAS_MULTI_QUEUES || ++ ((fep->quirks & FEC_QUIRK_NO_HARD_RESET) && fep->link)) { ++ writel(0, fep->hwp + FEC_ECNTRL); ++ } else { ++ writel(FEC_ECR_RESET, fep->hwp + FEC_ECNTRL); ++ udelay(10); ++ } ++ } else { ++ val = readl(fep->hwp + FEC_ECNTRL); ++ val |= (FEC_ECR_MAGICEN | FEC_ECR_SLEEP); ++ writel(val, fep->hwp + FEC_ECNTRL); ++ } ++} ++ + /* + * This function is called to start or restart the FEC during a link + * change, transmit timeout, or to reconfigure the FEC. The network +@@ -1114,17 +1137,7 @@ fec_restart(struct net_device *ndev) + if (fep->bufdesc_ex) + fec_ptp_save_state(fep); + +- /* Whack a reset. We should wait for this. +- * For i.MX6SX SOC, enet use AXI bus, we use disable MAC +- * instead of reset MAC itself. +- */ +- if (fep->quirks & FEC_QUIRK_HAS_MULTI_QUEUES || +- ((fep->quirks & FEC_QUIRK_NO_HARD_RESET) && fep->link)) { +- writel(0, fep->hwp + FEC_ECNTRL); +- } else { +- writel(1, fep->hwp + FEC_ECNTRL); +- udelay(10); +- } ++ fec_ctrl_reset(fep, false); + + /* + * enet-mac reset will reset mac address registers too, +@@ -1378,22 +1391,7 @@ fec_stop(struct net_device *ndev) + if (fep->bufdesc_ex) + fec_ptp_save_state(fep); + +- /* Whack a reset. We should wait for this. +- * For i.MX6SX SOC, enet use AXI bus, we use disable MAC +- * instead of reset MAC itself. +- */ +- if (!(fep->wol_flag & FEC_WOL_FLAG_SLEEP_ON)) { +- if (fep->quirks & FEC_QUIRK_HAS_MULTI_QUEUES) { +- writel(0, fep->hwp + FEC_ECNTRL); +- } else { +- writel(FEC_ECR_RESET, fep->hwp + FEC_ECNTRL); +- udelay(10); +- } +- } else { +- val = readl(fep->hwp + FEC_ECNTRL); +- val |= (FEC_ECR_MAGICEN | FEC_ECR_SLEEP); +- writel(val, fep->hwp + FEC_ECNTRL); +- } ++ fec_ctrl_reset(fep, true); + writel(fep->phy_speed, fep->hwp + FEC_MII_SPEED); + writel(FEC_DEFAULT_IMASK, fep->hwp + FEC_IMASK); + +-- +2.39.5 + diff --git a/queue-6.14/net-flush_backlog-small-changes.patch b/queue-6.14/net-flush_backlog-small-changes.patch new file mode 100644 index 0000000000..2d226c4677 --- /dev/null +++ b/queue-6.14/net-flush_backlog-small-changes.patch @@ -0,0 +1,75 @@ +From ca77c9d14a7ce2b3f171996f86fc7788c192f69b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 4 Feb 2025 14:48:25 +0000 +Subject: net: flush_backlog() small changes + +From: Eric Dumazet + +[ Upstream commit cbe08724c18078564abefbf6591078a7c98e5e0f ] + +Add READ_ONCE() around reads of skb->dev->reg_state, because +this field can be changed from other threads/cpus. + +Instead of calling dev_kfree_skb_irq() and kfree_skb() +while interrupts are masked and locks held, +use a temporary list and use __skb_queue_purge_reason() + +Use SKB_DROP_REASON_DEV_READY drop reason to better +describe why these skbs are dropped. + +Signed-off-by: Eric Dumazet +Reviewed-by: Jason Xing +Link: https://patch.msgid.link/20250204144825.316785-1-edumazet@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/core/dev.c | 12 ++++++++---- + 1 file changed, 8 insertions(+), 4 deletions(-) + +diff --git a/net/core/dev.c b/net/core/dev.c +index 2f7f5fd9ffec7..77306b522966c 100644 +--- a/net/core/dev.c ++++ b/net/core/dev.c +@@ -6187,16 +6187,18 @@ EXPORT_SYMBOL(netif_receive_skb_list); + static void flush_backlog(struct work_struct *work) + { + struct sk_buff *skb, *tmp; ++ struct sk_buff_head list; + struct softnet_data *sd; + ++ __skb_queue_head_init(&list); + local_bh_disable(); + sd = this_cpu_ptr(&softnet_data); + + backlog_lock_irq_disable(sd); + skb_queue_walk_safe(&sd->input_pkt_queue, skb, tmp) { +- if (skb->dev->reg_state == NETREG_UNREGISTERING) { ++ if (READ_ONCE(skb->dev->reg_state) == NETREG_UNREGISTERING) { + __skb_unlink(skb, &sd->input_pkt_queue); +- dev_kfree_skb_irq(skb); ++ __skb_queue_tail(&list, skb); + rps_input_queue_head_incr(sd); + } + } +@@ -6204,14 +6206,16 @@ static void flush_backlog(struct work_struct *work) + + local_lock_nested_bh(&softnet_data.process_queue_bh_lock); + skb_queue_walk_safe(&sd->process_queue, skb, tmp) { +- if (skb->dev->reg_state == NETREG_UNREGISTERING) { ++ if (READ_ONCE(skb->dev->reg_state) == NETREG_UNREGISTERING) { + __skb_unlink(skb, &sd->process_queue); +- kfree_skb(skb); ++ __skb_queue_tail(&list, skb); + rps_input_queue_head_incr(sd); + } + } + local_unlock_nested_bh(&softnet_data.process_queue_bh_lock); + local_bh_enable(); ++ ++ __skb_queue_purge_reason(&list, SKB_DROP_REASON_DEV_READY); + } + + static bool flush_required(int cpu) +-- +2.39.5 + diff --git a/queue-6.14/net-hsr-fix-prp-duplicate-detection.patch b/queue-6.14/net-hsr-fix-prp-duplicate-detection.patch new file mode 100644 index 0000000000..57e4b45b53 --- /dev/null +++ b/queue-6.14/net-hsr-fix-prp-duplicate-detection.patch @@ -0,0 +1,247 @@ +From b80009ffcba8c94bbcc8ed2e480ed237506bf1af Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 7 Mar 2025 18:16:59 +0200 +Subject: net: hsr: Fix PRP duplicate detection + +From: Jaakko Karrenpalo + +[ Upstream commit 05fd00e5e7b1ac60d264f72423fba38cc382b447 ] + +Add PRP specific function for handling duplicate +packets. This is needed because of potential +L2 802.1p prioritization done by network switches. + +The L2 prioritization can re-order the PRP packets +from a node causing the existing implementation to +discard the frame(s) that have been received 'late' +because the sequence number is before the previous +received packet. This can happen if the node is +sending multiple frames back-to-back with different +priority. + +Signed-off-by: Jaakko Karrenpalo +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20250307161700.1045-1-jkarrenpalo@gmail.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/hsr/hsr_device.c | 2 + + net/hsr/hsr_forward.c | 4 +- + net/hsr/hsr_framereg.c | 95 ++++++++++++++++++++++++++++++++++++++++-- + net/hsr/hsr_framereg.h | 8 +++- + net/hsr/hsr_main.h | 2 + + 5 files changed, 104 insertions(+), 7 deletions(-) + +diff --git a/net/hsr/hsr_device.c b/net/hsr/hsr_device.c +index b6fb18469439a..2c43776b7c4fb 100644 +--- a/net/hsr/hsr_device.c ++++ b/net/hsr/hsr_device.c +@@ -616,6 +616,7 @@ static struct hsr_proto_ops hsr_ops = { + .drop_frame = hsr_drop_frame, + .fill_frame_info = hsr_fill_frame_info, + .invalid_dan_ingress_frame = hsr_invalid_dan_ingress_frame, ++ .register_frame_out = hsr_register_frame_out, + }; + + static struct hsr_proto_ops prp_ops = { +@@ -626,6 +627,7 @@ static struct hsr_proto_ops prp_ops = { + .fill_frame_info = prp_fill_frame_info, + .handle_san_frame = prp_handle_san_frame, + .update_san_info = prp_update_san_info, ++ .register_frame_out = prp_register_frame_out, + }; + + void hsr_dev_setup(struct net_device *dev) +diff --git a/net/hsr/hsr_forward.c b/net/hsr/hsr_forward.c +index a4bacf1985558..c67c0d35921de 100644 +--- a/net/hsr/hsr_forward.c ++++ b/net/hsr/hsr_forward.c +@@ -536,8 +536,8 @@ static void hsr_forward_do(struct hsr_frame_info *frame) + * Also for SAN, this shouldn't be done. + */ + if (!frame->is_from_san && +- hsr_register_frame_out(port, frame->node_src, +- frame->sequence_nr)) ++ hsr->proto_ops->register_frame_out && ++ hsr->proto_ops->register_frame_out(port, frame)) + continue; + + if (frame->is_supervision && port->type == HSR_PT_MASTER && +diff --git a/net/hsr/hsr_framereg.c b/net/hsr/hsr_framereg.c +index 73bc6f659812f..85991fab7db58 100644 +--- a/net/hsr/hsr_framereg.c ++++ b/net/hsr/hsr_framereg.c +@@ -35,6 +35,7 @@ static bool seq_nr_after(u16 a, u16 b) + + #define seq_nr_before(a, b) seq_nr_after((b), (a)) + #define seq_nr_before_or_eq(a, b) (!seq_nr_after((a), (b))) ++#define PRP_DROP_WINDOW_LEN 32768 + + bool hsr_addr_is_redbox(struct hsr_priv *hsr, unsigned char *addr) + { +@@ -176,8 +177,11 @@ static struct hsr_node *hsr_add_node(struct hsr_priv *hsr, + new_node->time_in[i] = now; + new_node->time_out[i] = now; + } +- for (i = 0; i < HSR_PT_PORTS; i++) ++ for (i = 0; i < HSR_PT_PORTS; i++) { + new_node->seq_out[i] = seq_out; ++ new_node->seq_expected[i] = seq_out + 1; ++ new_node->seq_start[i] = seq_out + 1; ++ } + + if (san && hsr->proto_ops->handle_san_frame) + hsr->proto_ops->handle_san_frame(san, rx_port, new_node); +@@ -482,9 +486,11 @@ void hsr_register_frame_in(struct hsr_node *node, struct hsr_port *port, + * 0 otherwise, or + * negative error code on error + */ +-int hsr_register_frame_out(struct hsr_port *port, struct hsr_node *node, +- u16 sequence_nr) ++int hsr_register_frame_out(struct hsr_port *port, struct hsr_frame_info *frame) + { ++ struct hsr_node *node = frame->node_src; ++ u16 sequence_nr = frame->sequence_nr; ++ + spin_lock_bh(&node->seq_out_lock); + if (seq_nr_before_or_eq(sequence_nr, node->seq_out[port->type]) && + time_is_after_jiffies(node->time_out[port->type] + +@@ -499,6 +505,89 @@ int hsr_register_frame_out(struct hsr_port *port, struct hsr_node *node, + return 0; + } + ++/* Adaptation of the PRP duplicate discard algorithm described in wireshark ++ * wiki (https://wiki.wireshark.org/PRP) ++ * ++ * A drop window is maintained for both LANs with start sequence set to the ++ * first sequence accepted on the LAN that has not been seen on the other LAN, ++ * and expected sequence set to the latest received sequence number plus one. ++ * ++ * When a frame is received on either LAN it is compared against the received ++ * frames on the other LAN. If it is outside the drop window of the other LAN ++ * the frame is accepted and the drop window is updated. ++ * The drop window for the other LAN is reset. ++ * ++ * 'port' is the outgoing interface ++ * 'frame' is the frame to be sent ++ * ++ * Return: ++ * 1 if frame can be shown to have been sent recently on this interface, ++ * 0 otherwise ++ */ ++int prp_register_frame_out(struct hsr_port *port, struct hsr_frame_info *frame) ++{ ++ enum hsr_port_type other_port; ++ enum hsr_port_type rcv_port; ++ struct hsr_node *node; ++ u16 sequence_diff; ++ u16 sequence_exp; ++ u16 sequence_nr; ++ ++ /* out-going frames are always in order ++ * and can be checked the same way as for HSR ++ */ ++ if (frame->port_rcv->type == HSR_PT_MASTER) ++ return hsr_register_frame_out(port, frame); ++ ++ /* for PRP we should only forward frames from the slave ports ++ * to the master port ++ */ ++ if (port->type != HSR_PT_MASTER) ++ return 1; ++ ++ node = frame->node_src; ++ sequence_nr = frame->sequence_nr; ++ sequence_exp = sequence_nr + 1; ++ rcv_port = frame->port_rcv->type; ++ other_port = rcv_port == HSR_PT_SLAVE_A ? HSR_PT_SLAVE_B : ++ HSR_PT_SLAVE_A; ++ ++ spin_lock_bh(&node->seq_out_lock); ++ if (time_is_before_jiffies(node->time_out[port->type] + ++ msecs_to_jiffies(HSR_ENTRY_FORGET_TIME)) || ++ (node->seq_start[rcv_port] == node->seq_expected[rcv_port] && ++ node->seq_start[other_port] == node->seq_expected[other_port])) { ++ /* the node hasn't been sending for a while ++ * or both drop windows are empty, forward the frame ++ */ ++ node->seq_start[rcv_port] = sequence_nr; ++ } else if (seq_nr_before(sequence_nr, node->seq_expected[other_port]) && ++ seq_nr_before_or_eq(node->seq_start[other_port], sequence_nr)) { ++ /* drop the frame, update the drop window for the other port ++ * and reset our drop window ++ */ ++ node->seq_start[other_port] = sequence_exp; ++ node->seq_expected[rcv_port] = sequence_exp; ++ node->seq_start[rcv_port] = node->seq_expected[rcv_port]; ++ spin_unlock_bh(&node->seq_out_lock); ++ return 1; ++ } ++ ++ /* update the drop window for the port where this frame was received ++ * and clear the drop window for the other port ++ */ ++ node->seq_start[other_port] = node->seq_expected[other_port]; ++ node->seq_expected[rcv_port] = sequence_exp; ++ sequence_diff = sequence_exp - node->seq_start[rcv_port]; ++ if (sequence_diff > PRP_DROP_WINDOW_LEN) ++ node->seq_start[rcv_port] = sequence_exp - PRP_DROP_WINDOW_LEN; ++ ++ node->time_out[port->type] = jiffies; ++ node->seq_out[port->type] = sequence_nr; ++ spin_unlock_bh(&node->seq_out_lock); ++ return 0; ++} ++ + static struct hsr_port *get_late_port(struct hsr_priv *hsr, + struct hsr_node *node) + { +diff --git a/net/hsr/hsr_framereg.h b/net/hsr/hsr_framereg.h +index 993fa950d8144..b04948659d84d 100644 +--- a/net/hsr/hsr_framereg.h ++++ b/net/hsr/hsr_framereg.h +@@ -44,8 +44,7 @@ void hsr_addr_subst_dest(struct hsr_node *node_src, struct sk_buff *skb, + + void hsr_register_frame_in(struct hsr_node *node, struct hsr_port *port, + u16 sequence_nr); +-int hsr_register_frame_out(struct hsr_port *port, struct hsr_node *node, +- u16 sequence_nr); ++int hsr_register_frame_out(struct hsr_port *port, struct hsr_frame_info *frame); + + void hsr_prune_nodes(struct timer_list *t); + void hsr_prune_proxy_nodes(struct timer_list *t); +@@ -73,6 +72,8 @@ void prp_update_san_info(struct hsr_node *node, bool is_sup); + bool hsr_is_node_in_db(struct list_head *node_db, + const unsigned char addr[ETH_ALEN]); + ++int prp_register_frame_out(struct hsr_port *port, struct hsr_frame_info *frame); ++ + struct hsr_node { + struct list_head mac_list; + /* Protect R/W access to seq_out */ +@@ -89,6 +90,9 @@ struct hsr_node { + bool san_b; + u16 seq_out[HSR_PT_PORTS]; + bool removed; ++ /* PRP specific duplicate handling */ ++ u16 seq_expected[HSR_PT_PORTS]; ++ u16 seq_start[HSR_PT_PORTS]; + struct rcu_head rcu_head; + }; + +diff --git a/net/hsr/hsr_main.h b/net/hsr/hsr_main.h +index 7561845b8bf6f..1bc47b17a2968 100644 +--- a/net/hsr/hsr_main.h ++++ b/net/hsr/hsr_main.h +@@ -175,6 +175,8 @@ struct hsr_proto_ops { + struct hsr_frame_info *frame); + bool (*invalid_dan_ingress_frame)(__be16 protocol); + void (*update_san_info)(struct hsr_node *node, bool is_sup); ++ int (*register_frame_out)(struct hsr_port *port, ++ struct hsr_frame_info *frame); + }; + + struct hsr_self_node { +-- +2.39.5 + diff --git a/queue-6.14/net-ipv6-init-tunnel-link-netns-before-registering-d.patch b/queue-6.14/net-ipv6-init-tunnel-link-netns-before-registering-d.patch new file mode 100644 index 0000000000..bae333450d --- /dev/null +++ b/queue-6.14/net-ipv6-init-tunnel-link-netns-before-registering-d.patch @@ -0,0 +1,157 @@ +From 129b0146292d5954901c021d23751a6ec6d1128e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 19 Feb 2025 20:50:33 +0800 +Subject: net: ipv6: Init tunnel link-netns before registering dev + +From: Xiao Liang + +[ Upstream commit db014522f35606031d8ac58b4aed6b1ed84f03d1 ] + +Currently some IPv6 tunnel drivers set tnl->net to dev_net(dev) in +ndo_init(), which is called in register_netdevice(). However, it lacks +the context of link-netns when we enable cross-net tunnels at device +registration time. + +Let's move the init of tunnel link-netns before register_netdevice(). + +ip6_gre has already initialized netns, so just remove the redundant +assignment. + +Signed-off-by: Xiao Liang +Reviewed-by: Kuniyuki Iwashima +Link: https://patch.msgid.link/20250219125039.18024-8-shaw.leon@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/ipv6/ip6_gre.c | 2 -- + net/ipv6/ip6_tunnel.c | 3 ++- + net/ipv6/ip6_vti.c | 3 ++- + net/ipv6/sit.c | 8 +++++--- + 4 files changed, 9 insertions(+), 7 deletions(-) + +diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c +index 235808cfec705..68e9a41eed491 100644 +--- a/net/ipv6/ip6_gre.c ++++ b/net/ipv6/ip6_gre.c +@@ -1498,7 +1498,6 @@ static int ip6gre_tunnel_init_common(struct net_device *dev) + tunnel = netdev_priv(dev); + + tunnel->dev = dev; +- tunnel->net = dev_net(dev); + strcpy(tunnel->parms.name, dev->name); + + ret = dst_cache_init(&tunnel->dst_cache, GFP_KERNEL); +@@ -1882,7 +1881,6 @@ static int ip6erspan_tap_init(struct net_device *dev) + tunnel = netdev_priv(dev); + + tunnel->dev = dev; +- tunnel->net = dev_net(dev); + strcpy(tunnel->parms.name, dev->name); + + ret = dst_cache_init(&tunnel->dst_cache, GFP_KERNEL); +diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c +index 48fd53b989726..5350c9bb2319b 100644 +--- a/net/ipv6/ip6_tunnel.c ++++ b/net/ipv6/ip6_tunnel.c +@@ -1878,7 +1878,6 @@ ip6_tnl_dev_init_gen(struct net_device *dev) + int t_hlen; + + t->dev = dev; +- t->net = dev_net(dev); + + ret = dst_cache_init(&t->dst_cache, GFP_KERNEL); + if (ret) +@@ -1940,6 +1939,7 @@ static int __net_init ip6_fb_tnl_dev_init(struct net_device *dev) + struct net *net = dev_net(dev); + struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id); + ++ t->net = net; + t->parms.proto = IPPROTO_IPV6; + + rcu_assign_pointer(ip6n->tnls_wc[0], t); +@@ -2013,6 +2013,7 @@ static int ip6_tnl_newlink(struct net *src_net, struct net_device *dev, + int err; + + nt = netdev_priv(dev); ++ nt->net = net; + + if (ip_tunnel_netlink_encap_parms(data, &ipencap)) { + err = ip6_tnl_encap_setup(nt, &ipencap); +diff --git a/net/ipv6/ip6_vti.c b/net/ipv6/ip6_vti.c +index 590737c275379..0123504691443 100644 +--- a/net/ipv6/ip6_vti.c ++++ b/net/ipv6/ip6_vti.c +@@ -925,7 +925,6 @@ static inline int vti6_dev_init_gen(struct net_device *dev) + struct ip6_tnl *t = netdev_priv(dev); + + t->dev = dev; +- t->net = dev_net(dev); + netdev_hold(dev, &t->dev_tracker, GFP_KERNEL); + netdev_lockdep_set_classes(dev); + return 0; +@@ -958,6 +957,7 @@ static int __net_init vti6_fb_tnl_dev_init(struct net_device *dev) + struct net *net = dev_net(dev); + struct vti6_net *ip6n = net_generic(net, vti6_net_id); + ++ t->net = net; + t->parms.proto = IPPROTO_IPV6; + + rcu_assign_pointer(ip6n->tnls_wc[0], t); +@@ -1008,6 +1008,7 @@ static int vti6_newlink(struct net *src_net, struct net_device *dev, + vti6_netlink_parms(data, &nt->parms); + + nt->parms.proto = IPPROTO_IPV6; ++ nt->net = net; + + if (vti6_locate(net, &nt->parms, 0)) + return -EEXIST; +diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c +index 39bd8951bfca1..3c15a0ae228e2 100644 +--- a/net/ipv6/sit.c ++++ b/net/ipv6/sit.c +@@ -269,6 +269,7 @@ static struct ip_tunnel *ipip6_tunnel_locate(struct net *net, + + nt = netdev_priv(dev); + ++ nt->net = net; + nt->parms = *parms; + if (ipip6_tunnel_create(dev) < 0) + goto failed_free; +@@ -1449,7 +1450,6 @@ static int ipip6_tunnel_init(struct net_device *dev) + int err; + + tunnel->dev = dev; +- tunnel->net = dev_net(dev); + strcpy(tunnel->parms.name, dev->name); + + ipip6_tunnel_bind_dev(dev); +@@ -1563,6 +1563,7 @@ static int ipip6_newlink(struct net *src_net, struct net_device *dev, + int err; + + nt = netdev_priv(dev); ++ nt->net = net; + + if (ip_tunnel_netlink_encap_parms(data, &ipencap)) { + err = ip_tunnel_encap_setup(nt, &ipencap); +@@ -1858,6 +1859,9 @@ static int __net_init sit_init_net(struct net *net) + */ + sitn->fb_tunnel_dev->netns_local = true; + ++ t = netdev_priv(sitn->fb_tunnel_dev); ++ t->net = net; ++ + err = register_netdev(sitn->fb_tunnel_dev); + if (err) + goto err_reg_dev; +@@ -1865,8 +1869,6 @@ static int __net_init sit_init_net(struct net *net) + ipip6_tunnel_clone_6rd(sitn->fb_tunnel_dev, sitn); + ipip6_fb_tunnel_init(sitn->fb_tunnel_dev); + +- t = netdev_priv(sitn->fb_tunnel_dev); +- + strcpy(t->parms.name, sitn->fb_tunnel_dev->name); + return 0; + +-- +2.39.5 + diff --git a/queue-6.14/net-mana-fix-warning-in-the-writer-of-client-oob.patch b/queue-6.14/net-mana-fix-warning-in-the-writer-of-client-oob.patch new file mode 100644 index 0000000000..6b0880a6a2 --- /dev/null +++ b/queue-6.14/net-mana-fix-warning-in-the-writer-of-client-oob.patch @@ -0,0 +1,37 @@ +From 0eae065450be2ef104c0dc82bac62985379ba2ec Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 20 Jan 2025 09:27:14 -0800 +Subject: net/mana: fix warning in the writer of client oob + +From: Konstantin Taranov + +[ Upstream commit 5ec7e1c86c441c46a374577bccd9488abea30037 ] + +Do not warn on missing pad_data when oob is in sgl. + +Signed-off-by: Konstantin Taranov +Link: https://patch.msgid.link/1737394039-28772-9-git-send-email-kotaranov@linux.microsoft.com +Reviewed-by: Shiraz Saleem +Reviewed-by: Long Li +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/microsoft/mana/gdma_main.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/microsoft/mana/gdma_main.c b/drivers/net/ethernet/microsoft/mana/gdma_main.c +index 638ef64d639f3..f412e17b0d505 100644 +--- a/drivers/net/ethernet/microsoft/mana/gdma_main.c ++++ b/drivers/net/ethernet/microsoft/mana/gdma_main.c +@@ -1047,7 +1047,7 @@ static u32 mana_gd_write_client_oob(const struct gdma_wqe_request *wqe_req, + header->inline_oob_size_div4 = client_oob_size / sizeof(u32); + + if (oob_in_sgl) { +- WARN_ON_ONCE(!pad_data || wqe_req->num_sge < 2); ++ WARN_ON_ONCE(wqe_req->num_sge < 2); + + header->client_oob_in_sgl = 1; + +-- +2.39.5 + diff --git a/queue-6.14/net-mlx4_core-avoid-impossible-mlx4_db_alloc-order-v.patch b/queue-6.14/net-mlx4_core-avoid-impossible-mlx4_db_alloc-order-v.patch new file mode 100644 index 0000000000..16237c2cd4 --- /dev/null +++ b/queue-6.14/net-mlx4_core-avoid-impossible-mlx4_db_alloc-order-v.patch @@ -0,0 +1,78 @@ +From 8766c43a2a807b13d42dbdb37c90118ca506d6a1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 10 Feb 2025 09:45:05 -0800 +Subject: net/mlx4_core: Avoid impossible mlx4_db_alloc() order value + +From: Kees Cook + +[ Upstream commit 4a6f18f28627e121bd1f74b5fcc9f945d6dbeb1e ] + +GCC can see that the value range for "order" is capped, but this leads +it to consider that it might be negative, leading to a false positive +warning (with GCC 15 with -Warray-bounds -fdiagnostics-details): + +../drivers/net/ethernet/mellanox/mlx4/alloc.c:691:47: error: array subscript -1 is below array bounds of 'long unsigned int *[2]' [-Werror=array-bounds=] + 691 | i = find_first_bit(pgdir->bits[o], MLX4_DB_PER_PAGE >> o); + | ~~~~~~~~~~~^~~ + 'mlx4_alloc_db_from_pgdir': events 1-2 + 691 | i = find_first_bit(pgdir->bits[o], MLX4_DB_PER_PAGE >> o); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + | | | | | (2) out of array bounds here + | (1) when the condition is evaluated to true In file included from ../drivers/net/ethernet/mellanox/mlx4/mlx4.h:53, + from ../drivers/net/ethernet/mellanox/mlx4/alloc.c:42: +../include/linux/mlx4/device.h:664:33: note: while referencing 'bits' + 664 | unsigned long *bits[2]; + | ^~~~ + +Switch the argument to unsigned int, which removes the compiler needing +to consider negative values. + +Signed-off-by: Kees Cook +Link: https://patch.msgid.link/20250210174504.work.075-kees@kernel.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx4/alloc.c | 6 +++--- + include/linux/mlx4/device.h | 2 +- + 2 files changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx4/alloc.c b/drivers/net/ethernet/mellanox/mlx4/alloc.c +index b330020dc0d67..f2bded847e61d 100644 +--- a/drivers/net/ethernet/mellanox/mlx4/alloc.c ++++ b/drivers/net/ethernet/mellanox/mlx4/alloc.c +@@ -682,9 +682,9 @@ static struct mlx4_db_pgdir *mlx4_alloc_db_pgdir(struct device *dma_device) + } + + static int mlx4_alloc_db_from_pgdir(struct mlx4_db_pgdir *pgdir, +- struct mlx4_db *db, int order) ++ struct mlx4_db *db, unsigned int order) + { +- int o; ++ unsigned int o; + int i; + + for (o = order; o <= 1; ++o) { +@@ -712,7 +712,7 @@ static int mlx4_alloc_db_from_pgdir(struct mlx4_db_pgdir *pgdir, + return 0; + } + +-int mlx4_db_alloc(struct mlx4_dev *dev, struct mlx4_db *db, int order) ++int mlx4_db_alloc(struct mlx4_dev *dev, struct mlx4_db *db, unsigned int order) + { + struct mlx4_priv *priv = mlx4_priv(dev); + struct mlx4_db_pgdir *pgdir; +diff --git a/include/linux/mlx4/device.h b/include/linux/mlx4/device.h +index 27f42f713c891..86f0f2a25a3d6 100644 +--- a/include/linux/mlx4/device.h ++++ b/include/linux/mlx4/device.h +@@ -1135,7 +1135,7 @@ int mlx4_write_mtt(struct mlx4_dev *dev, struct mlx4_mtt *mtt, + int mlx4_buf_write_mtt(struct mlx4_dev *dev, struct mlx4_mtt *mtt, + struct mlx4_buf *buf); + +-int mlx4_db_alloc(struct mlx4_dev *dev, struct mlx4_db *db, int order); ++int mlx4_db_alloc(struct mlx4_dev *dev, struct mlx4_db *db, unsigned int order); + void mlx4_db_free(struct mlx4_dev *dev, struct mlx4_db *db); + + int mlx4_alloc_hwq_res(struct mlx4_dev *dev, struct mlx4_hwq_resources *wqres, +-- +2.39.5 + diff --git a/queue-6.14/net-mlx5-apply-rate-limiting-to-high-temperature-war.patch b/queue-6.14/net-mlx5-apply-rate-limiting-to-high-temperature-war.patch new file mode 100644 index 0000000000..c1608a3b7d --- /dev/null +++ b/queue-6.14/net-mlx5-apply-rate-limiting-to-high-temperature-war.patch @@ -0,0 +1,45 @@ +From 894796f40c339ca5060f7d2f7254bb0a4d299ef3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 13 Feb 2025 11:46:38 +0200 +Subject: net/mlx5: Apply rate-limiting to high temperature warning + +From: Shahar Shitrit + +[ Upstream commit 9dd3d5d258aceb37bdf09c8b91fa448f58ea81f0 ] + +Wrap the high temperature warning in a temperature event with +a call to net_ratelimit() to prevent flooding the kernel log +with repeated warning messages when temperature exceeds the +threshold multiple times within a short duration. + +Signed-off-by: Shahar Shitrit +Signed-off-by: Tariq Toukan +Reviewed-by: Mateusz Polchlopek +Link: https://patch.msgid.link/20250213094641.226501-2-tariqt@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/events.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/events.c b/drivers/net/ethernet/mellanox/mlx5/core/events.c +index cd8d107f7d9e3..fc6e56305cbbc 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/events.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/events.c +@@ -169,9 +169,10 @@ static int temp_warn(struct notifier_block *nb, unsigned long type, void *data) + value_lsb &= 0x1; + value_msb = be64_to_cpu(eqe->data.temp_warning.sensor_warning_msb); + +- mlx5_core_warn(events->dev, +- "High temperature on sensors with bit set %llx %llx", +- value_msb, value_lsb); ++ if (net_ratelimit()) ++ mlx5_core_warn(events->dev, ++ "High temperature on sensors with bit set %llx %llx", ++ value_msb, value_lsb); + + return NOTIFY_OK; + } +-- +2.39.5 + diff --git a/queue-6.14/net-mlx5-avoid-report-two-health-errors-on-same-synd.patch b/queue-6.14/net-mlx5-avoid-report-two-health-errors-on-same-synd.patch new file mode 100644 index 0000000000..ab93b9bba2 --- /dev/null +++ b/queue-6.14/net-mlx5-avoid-report-two-health-errors-on-same-synd.patch @@ -0,0 +1,42 @@ +From d482bef9ee8e9465d672e40ac3cded961e789e0c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 26 Feb 2025 14:25:40 +0200 +Subject: net/mlx5: Avoid report two health errors on same syndrome + +From: Moshe Shemesh + +[ Upstream commit b5d7b2f04ebcff740f44ef4d295b3401aeb029f4 ] + +In case health counter has not increased for few polling intervals, miss +counter will reach max misses threshold and health report will be +triggered for FW health reporter. In case syndrome found on same health +poll another health report will be triggered. + +Avoid two health reports on same syndrome by marking this syndrome as +already known. + +Signed-off-by: Moshe Shemesh +Reviewed-by: Shahar Shitrit +Signed-off-by: Tariq Toukan +Reviewed-by: Kalesh AP +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/health.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/health.c b/drivers/net/ethernet/mellanox/mlx5/core/health.c +index a6329ca2d9bff..52c8035547be5 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/health.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/health.c +@@ -799,6 +799,7 @@ static void poll_health(struct timer_list *t) + health->prev = count; + if (health->miss_counter == MAX_MISSES) { + mlx5_core_err(dev, "device's health compromised - reached miss count\n"); ++ health->synd = ioread8(&h->synd); + print_health_info(dev); + queue_work(health->wq, &health->report_work); + } +-- +2.39.5 + diff --git a/queue-6.14/net-mlx5-change-pool_next_size-define-value-and-make.patch b/queue-6.14/net-mlx5-change-pool_next_size-define-value-and-make.patch new file mode 100644 index 0000000000..6979ce7aa4 --- /dev/null +++ b/queue-6.14/net-mlx5-change-pool_next_size-define-value-and-make.patch @@ -0,0 +1,108 @@ +From f9e3263d6695e7ebd6d5a2458383be396d953ede Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 19 Feb 2025 10:58:08 +0200 +Subject: net/mlx5: Change POOL_NEXT_SIZE define value and make it global + +From: Patrisious Haddad + +[ Upstream commit 80df31f384b4146a62a01b3d4beb376cc7b9a89e ] + +Change POOL_NEXT_SIZE define value from 0 to BIT(30), since this define +is used to request the available maximum sized flow table, and zero doesn't +make sense for it, whereas some places in the driver use zero explicitly +expecting the smallest table size possible but instead due to this +define they end up allocating the biggest table size unawarely. + +In addition move the definition to "include/linux/mlx5/fs.h" to expose the +define to IB driver as well, while appropriately renaming it. + +Signed-off-by: Patrisious Haddad +Reviewed-by: Maor Gottlieb +Reviewed-by: Mark Bloch +Signed-off-by: Tariq Toukan +Link: https://patch.msgid.link/20250219085808.349923-3-tariqt@nvidia.com +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/esw/legacy.c | 2 +- + drivers/net/ethernet/mellanox/mlx5/core/fs_ft_pool.c | 6 ++++-- + drivers/net/ethernet/mellanox/mlx5/core/fs_ft_pool.h | 2 -- + drivers/net/ethernet/mellanox/mlx5/core/lib/fs_chains.c | 3 ++- + include/linux/mlx5/fs.h | 2 ++ + 5 files changed, 9 insertions(+), 6 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/legacy.c b/drivers/net/ethernet/mellanox/mlx5/core/esw/legacy.c +index 45183de424f3d..76382626ad41d 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/esw/legacy.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/legacy.c +@@ -96,7 +96,7 @@ static int esw_create_legacy_fdb_table(struct mlx5_eswitch *esw) + if (!flow_group_in) + return -ENOMEM; + +- ft_attr.max_fte = POOL_NEXT_SIZE; ++ ft_attr.max_fte = MLX5_FS_MAX_POOL_SIZE; + ft_attr.prio = LEGACY_FDB_PRIO; + fdb = mlx5_create_flow_table(root_ns, &ft_attr); + if (IS_ERR(fdb)) { +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_ft_pool.c b/drivers/net/ethernet/mellanox/mlx5/core/fs_ft_pool.c +index c14590acc7726..f6abfd00d7e68 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/fs_ft_pool.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_ft_pool.c +@@ -50,10 +50,12 @@ mlx5_ft_pool_get_avail_sz(struct mlx5_core_dev *dev, enum fs_flow_table_type tab + int i, found_i = -1; + + for (i = ARRAY_SIZE(FT_POOLS) - 1; i >= 0; i--) { +- if (dev->priv.ft_pool->ft_left[i] && FT_POOLS[i] >= desired_size && ++ if (dev->priv.ft_pool->ft_left[i] && ++ (FT_POOLS[i] >= desired_size || ++ desired_size == MLX5_FS_MAX_POOL_SIZE) && + FT_POOLS[i] <= max_ft_size) { + found_i = i; +- if (desired_size != POOL_NEXT_SIZE) ++ if (desired_size != MLX5_FS_MAX_POOL_SIZE) + break; + } + } +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_ft_pool.h b/drivers/net/ethernet/mellanox/mlx5/core/fs_ft_pool.h +index 25f4274b372b5..173e312db7204 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/fs_ft_pool.h ++++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_ft_pool.h +@@ -7,8 +7,6 @@ + #include + #include "fs_core.h" + +-#define POOL_NEXT_SIZE 0 +- + int mlx5_ft_pool_init(struct mlx5_core_dev *dev); + void mlx5_ft_pool_destroy(struct mlx5_core_dev *dev); + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/fs_chains.c b/drivers/net/ethernet/mellanox/mlx5/core/lib/fs_chains.c +index 711d14dea2485..d313cb7f0ed88 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/lib/fs_chains.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/fs_chains.c +@@ -161,7 +161,8 @@ mlx5_chains_create_table(struct mlx5_fs_chains *chains, + ft_attr.flags |= (MLX5_FLOW_TABLE_TUNNEL_EN_REFORMAT | + MLX5_FLOW_TABLE_TUNNEL_EN_DECAP); + +- sz = (chain == mlx5_chains_get_nf_ft_chain(chains)) ? FT_TBL_SZ : POOL_NEXT_SIZE; ++ sz = (chain == mlx5_chains_get_nf_ft_chain(chains)) ? ++ FT_TBL_SZ : MLX5_FS_MAX_POOL_SIZE; + ft_attr.max_fte = sz; + + /* We use chains_default_ft(chains) as the table's next_ft till +diff --git a/include/linux/mlx5/fs.h b/include/linux/mlx5/fs.h +index 2a69d9d71276d..01cb72d68c231 100644 +--- a/include/linux/mlx5/fs.h ++++ b/include/linux/mlx5/fs.h +@@ -40,6 +40,8 @@ + + #define MLX5_SET_CFG(p, f, v) MLX5_SET(create_flow_group_in, p, f, v) + ++#define MLX5_FS_MAX_POOL_SIZE BIT(30) ++ + enum mlx5_flow_destination_type { + MLX5_FLOW_DESTINATION_TYPE_NONE, + MLX5_FLOW_DESTINATION_TYPE_VPORT, +-- +2.39.5 + diff --git a/queue-6.14/net-mlx5-extend-ethtool-loopback-selftest-to-support.patch b/queue-6.14/net-mlx5-extend-ethtool-loopback-selftest-to-support.patch new file mode 100644 index 0000000000..7ec2204df1 --- /dev/null +++ b/queue-6.14/net-mlx5-extend-ethtool-loopback-selftest-to-support.patch @@ -0,0 +1,41 @@ +From 1db593b5993f4cae52fe73069849089607d66e43 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 9 Feb 2025 12:17:15 +0200 +Subject: net/mlx5: Extend Ethtool loopback selftest to support non-linear SKB + +From: Alexei Lazar + +[ Upstream commit 95b9606b15bb3ce1198d28d2393dd0e1f0a5f3e9 ] + +Current loopback test validation ignores non-linear SKB case in +the SKB access, which can lead to failures in scenarios such as +when HW GRO is enabled. +Linearize the SKB so both cases will be handled. + +Signed-off-by: Alexei Lazar +Reviewed-by: Dragos Tatulea +Signed-off-by: Tariq Toukan +Link: https://patch.msgid.link/20250209101716.112774-15-tariqt@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/en_selftest.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_selftest.c b/drivers/net/ethernet/mellanox/mlx5/core/en_selftest.c +index 1d60465cc2ca4..2f7a543feca62 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_selftest.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_selftest.c +@@ -166,6 +166,9 @@ mlx5e_test_loopback_validate(struct sk_buff *skb, + struct udphdr *udph; + struct iphdr *iph; + ++ if (skb_linearize(skb)) ++ goto out; ++ + /* We are only going to peek, no need to clone the SKB */ + if (MLX5E_TEST_PKT_SIZE - ETH_HLEN > skb_headlen(skb)) + goto out; +-- +2.39.5 + diff --git a/queue-6.14/net-mlx5-modify-lsb-bitmask-in-temperature-event-to-.patch b/queue-6.14/net-mlx5-modify-lsb-bitmask-in-temperature-event-to-.patch new file mode 100644 index 0000000000..1aa5412d83 --- /dev/null +++ b/queue-6.14/net-mlx5-modify-lsb-bitmask-in-temperature-event-to-.patch @@ -0,0 +1,46 @@ +From fcd6556f31f0e513fdba3e09a42efaed43ca5037 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 13 Feb 2025 11:46:40 +0200 +Subject: net/mlx5: Modify LSB bitmask in temperature event to include only the + first bit + +From: Shahar Shitrit + +[ Upstream commit 633f16d7e07c129a36b882c05379e01ce5bdb542 ] + +In the sensor_count field of the MTEWE register, bits 1-62 are +supported only for unmanaged switches, not for NICs, and bit 63 +is reserved for internal use. + +To prevent confusing output that may include set bits that are +not relevant to NIC sensors, we update the bitmask to retain only +the first bit, which corresponds to the sensor ASIC. + +Signed-off-by: Shahar Shitrit +Signed-off-by: Tariq Toukan +Reviewed-by: Mateusz Polchlopek +Link: https://patch.msgid.link/20250213094641.226501-4-tariqt@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/events.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/events.c b/drivers/net/ethernet/mellanox/mlx5/core/events.c +index d91ea53eb394d..cd8d107f7d9e3 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/events.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/events.c +@@ -163,6 +163,10 @@ static int temp_warn(struct notifier_block *nb, unsigned long type, void *data) + u64 value_msb; + + value_lsb = be64_to_cpu(eqe->data.temp_warning.sensor_warning_lsb); ++ /* bit 1-63 are not supported for NICs, ++ * hence read only bit 0 (asic) from lsb. ++ */ ++ value_lsb &= 0x1; + value_msb = be64_to_cpu(eqe->data.temp_warning.sensor_warning_msb); + + mlx5_core_warn(events->dev, +-- +2.39.5 + diff --git a/queue-6.14/net-mlx5-preserve-rate-settings-when-creating-a-rate.patch b/queue-6.14/net-mlx5-preserve-rate-settings-when-creating-a-rate.patch new file mode 100644 index 0000000000..1ec9d440b4 --- /dev/null +++ b/queue-6.14/net-mlx5-preserve-rate-settings-when-creating-a-rate.patch @@ -0,0 +1,75 @@ +From a6f75385517e1301967fa0924396a8853f308606 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 10 Mar 2025 23:26:55 +0200 +Subject: net/mlx5: Preserve rate settings when creating a rate node + +From: Carolina Jubran + +[ Upstream commit f88c349c75e3784a3f5463f5b403ff28dd823782 ] + +Modify `esw_qos_create_node_sched_elem()` to receive max_rate and +bw_share values while maintaining the previous configuration. + +This change is essential for the upcoming patch that will modify rate +nodes and requires the existing settings to be preserved unless +explicitly changed. + +Signed-off-by: Carolina Jubran +Reviewed-by: Dragos Tatulea +Signed-off-by: Tariq Toukan +Link: https://patch.msgid.link/1741642016-44918-4-git-send-email-tariqt@nvidia.com +Reviewed-by: Jacob Keller +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/esw/qos.c | 13 +++++++++---- + 1 file changed, 9 insertions(+), 4 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/qos.c b/drivers/net/ethernet/mellanox/mlx5/core/esw/qos.c +index 823c1ba456cd1..803bacf2a95e6 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/esw/qos.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/qos.c +@@ -305,8 +305,9 @@ static int esw_qos_set_node_min_rate(struct mlx5_esw_sched_node *node, + return 0; + } + +-static int esw_qos_create_node_sched_elem(struct mlx5_core_dev *dev, u32 parent_element_id, +- u32 *tsar_ix) ++static int ++esw_qos_create_node_sched_elem(struct mlx5_core_dev *dev, u32 parent_element_id, ++ u32 max_rate, u32 bw_share, u32 *tsar_ix) + { + u32 tsar_ctx[MLX5_ST_SZ_DW(scheduling_context)] = {}; + void *attr; +@@ -323,6 +324,8 @@ static int esw_qos_create_node_sched_elem(struct mlx5_core_dev *dev, u32 parent_ + SCHEDULING_CONTEXT_ELEMENT_TYPE_TSAR); + MLX5_SET(scheduling_context, tsar_ctx, parent_element_id, + parent_element_id); ++ MLX5_SET(scheduling_context, tsar_ctx, max_average_bw, max_rate); ++ MLX5_SET(scheduling_context, tsar_ctx, bw_share, bw_share); + attr = MLX5_ADDR_OF(scheduling_context, tsar_ctx, element_attributes); + MLX5_SET(tsar_element, attr, tsar_type, TSAR_ELEMENT_TSAR_TYPE_DWRR); + +@@ -396,7 +399,8 @@ __esw_qos_create_vports_sched_node(struct mlx5_eswitch *esw, struct mlx5_esw_sch + u32 tsar_ix; + int err; + +- err = esw_qos_create_node_sched_elem(esw->dev, esw->qos.root_tsar_ix, &tsar_ix); ++ err = esw_qos_create_node_sched_elem(esw->dev, esw->qos.root_tsar_ix, 0, ++ 0, &tsar_ix); + if (err) { + NL_SET_ERR_MSG_MOD(extack, "E-Switch create TSAR for node failed"); + return ERR_PTR(err); +@@ -463,7 +467,8 @@ static int esw_qos_create(struct mlx5_eswitch *esw, struct netlink_ext_ack *exta + if (!MLX5_CAP_GEN(dev, qos) || !MLX5_CAP_QOS(dev, esw_scheduling)) + return -EOPNOTSUPP; + +- err = esw_qos_create_node_sched_elem(esw->dev, 0, &esw->qos.root_tsar_ix); ++ err = esw_qos_create_node_sched_elem(esw->dev, 0, 0, 0, ++ &esw->qos.root_tsar_ix); + if (err) { + esw_warn(dev, "E-Switch create root TSAR failed (%d)\n", err); + return err; +-- +2.39.5 + diff --git a/queue-6.14/net-mlx5-xdp-enable-tx-side-xdp-multi-buffer-support.patch b/queue-6.14/net-mlx5-xdp-enable-tx-side-xdp-multi-buffer-support.patch new file mode 100644 index 0000000000..c2f69cc16d --- /dev/null +++ b/queue-6.14/net-mlx5-xdp-enable-tx-side-xdp-multi-buffer-support.patch @@ -0,0 +1,206 @@ +From a1db918b63c891afe350c9fc7c6d09ae46061fc0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 9 Feb 2025 12:17:16 +0200 +Subject: net/mlx5: XDP, Enable TX side XDP multi-buffer support + +From: Alexei Lazar + +[ Upstream commit 1a9304859b3a4119579524c293b902a8927180f3 ] + +In XDP scenarios, fragmented packets can occur if the MTU is larger +than the page size, even when the packet size fits within the linear +part. +If XDP multi-buffer support is disabled, the fragmented part won't be +handled in the TX flow, leading to packet drops. + +Since XDP multi-buffer support is always available, this commit removes +the conditional check for enabling it. +This ensures that XDP multi-buffer support is always enabled, +regardless of the `is_xdp_mb` parameter, and guarantees the handling of +fragmented packets in such scenarios. + +Signed-off-by: Alexei Lazar +Signed-off-by: Tariq Toukan +Link: https://patch.msgid.link/20250209101716.112774-16-tariqt@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/en.h | 1 - + .../ethernet/mellanox/mlx5/core/en/params.c | 1 - + .../ethernet/mellanox/mlx5/core/en/params.h | 1 - + .../mellanox/mlx5/core/en/reporter_tx.c | 1 - + .../net/ethernet/mellanox/mlx5/core/en/xdp.c | 49 ++++++++----------- + .../net/ethernet/mellanox/mlx5/core/en_main.c | 29 ----------- + 6 files changed, 21 insertions(+), 61 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h +index 979fc56205e1f..8f9ec48ecc06d 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en.h ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h +@@ -386,7 +386,6 @@ enum { + MLX5E_SQ_STATE_VLAN_NEED_L2_INLINE, + MLX5E_SQ_STATE_PENDING_XSK_TX, + MLX5E_SQ_STATE_PENDING_TLS_RX_RESYNC, +- MLX5E_SQ_STATE_XDP_MULTIBUF, + MLX5E_NUM_SQ_STATES, /* Must be kept last */ + }; + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/params.c b/drivers/net/ethernet/mellanox/mlx5/core/en/params.c +index 31eb99f09c63c..8c4d710e85675 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en/params.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en/params.c +@@ -1242,7 +1242,6 @@ void mlx5e_build_xdpsq_param(struct mlx5_core_dev *mdev, + mlx5e_build_sq_param_common(mdev, param); + MLX5_SET(wq, wq, log_wq_sz, params->log_sq_size); + param->is_mpw = MLX5E_GET_PFLAG(params, MLX5E_PFLAG_XDP_TX_MPWQE); +- param->is_xdp_mb = !mlx5e_rx_is_linear_skb(mdev, params, xsk); + mlx5e_build_tx_cq_param(mdev, params, ¶m->cqp); + } + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/params.h b/drivers/net/ethernet/mellanox/mlx5/core/en/params.h +index 3f8986f9d8629..bd5877acc5b1e 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en/params.h ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en/params.h +@@ -33,7 +33,6 @@ struct mlx5e_sq_param { + struct mlx5_wq_param wq; + bool is_mpw; + bool is_tls; +- bool is_xdp_mb; + u16 stop_room; + }; + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c b/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c +index c8adf309ecad0..dbd9482359e1e 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c +@@ -16,7 +16,6 @@ static const char * const sq_sw_state_type_name[] = { + [MLX5E_SQ_STATE_VLAN_NEED_L2_INLINE] = "vlan_need_l2_inline", + [MLX5E_SQ_STATE_PENDING_XSK_TX] = "pending_xsk_tx", + [MLX5E_SQ_STATE_PENDING_TLS_RX_RESYNC] = "pending_tls_rx_resync", +- [MLX5E_SQ_STATE_XDP_MULTIBUF] = "xdp_multibuf", + }; + + static int mlx5e_wait_for_sq_flush(struct mlx5e_txqsq *sq) +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c b/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c +index 94b2916620873..7a6cc0f4002ea 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c +@@ -546,6 +546,7 @@ mlx5e_xmit_xdp_frame(struct mlx5e_xdpsq *sq, struct mlx5e_xmit_data *xdptxd, + bool inline_ok; + bool linear; + u16 pi; ++ int i; + + struct mlx5e_xdpsq_stats *stats = sq->stats; + +@@ -612,41 +613,33 @@ mlx5e_xmit_xdp_frame(struct mlx5e_xdpsq *sq, struct mlx5e_xmit_data *xdptxd, + + cseg->opmod_idx_opcode = cpu_to_be32((sq->pc << 8) | MLX5_OPCODE_SEND); + +- if (test_bit(MLX5E_SQ_STATE_XDP_MULTIBUF, &sq->state)) { +- int i; +- +- memset(&cseg->trailer, 0, sizeof(cseg->trailer)); +- memset(eseg, 0, sizeof(*eseg) - sizeof(eseg->trailer)); +- +- eseg->inline_hdr.sz = cpu_to_be16(inline_hdr_sz); ++ memset(&cseg->trailer, 0, sizeof(cseg->trailer)); ++ memset(eseg, 0, sizeof(*eseg) - sizeof(eseg->trailer)); + +- for (i = 0; i < num_frags; i++) { +- skb_frag_t *frag = &xdptxdf->sinfo->frags[i]; +- dma_addr_t addr; ++ eseg->inline_hdr.sz = cpu_to_be16(inline_hdr_sz); + +- addr = xdptxdf->dma_arr ? xdptxdf->dma_arr[i] : +- page_pool_get_dma_addr(skb_frag_page(frag)) + +- skb_frag_off(frag); ++ for (i = 0; i < num_frags; i++) { ++ skb_frag_t *frag = &xdptxdf->sinfo->frags[i]; ++ dma_addr_t addr; + +- dseg->addr = cpu_to_be64(addr); +- dseg->byte_count = cpu_to_be32(skb_frag_size(frag)); +- dseg->lkey = sq->mkey_be; +- dseg++; +- } ++ addr = xdptxdf->dma_arr ? xdptxdf->dma_arr[i] : ++ page_pool_get_dma_addr(skb_frag_page(frag)) + ++ skb_frag_off(frag); + +- cseg->qpn_ds = cpu_to_be32((sq->sqn << 8) | ds_cnt); ++ dseg->addr = cpu_to_be64(addr); ++ dseg->byte_count = cpu_to_be32(skb_frag_size(frag)); ++ dseg->lkey = sq->mkey_be; ++ dseg++; ++ } + +- sq->db.wqe_info[pi] = (struct mlx5e_xdp_wqe_info) { +- .num_wqebbs = num_wqebbs, +- .num_pkts = 1, +- }; ++ cseg->qpn_ds = cpu_to_be32((sq->sqn << 8) | ds_cnt); + +- sq->pc += num_wqebbs; +- } else { +- cseg->fm_ce_se = 0; ++ sq->db.wqe_info[pi] = (struct mlx5e_xdp_wqe_info) { ++ .num_wqebbs = num_wqebbs, ++ .num_pkts = 1, ++ }; + +- sq->pc++; +- } ++ sq->pc += num_wqebbs; + + xsk_tx_metadata_request(meta, &mlx5e_xsk_tx_metadata_ops, eseg); + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +index 5c5168bdacb90..b0748e46b1ac4 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +@@ -2023,41 +2023,12 @@ int mlx5e_open_xdpsq(struct mlx5e_channel *c, struct mlx5e_params *params, + csp.min_inline_mode = sq->min_inline_mode; + set_bit(MLX5E_SQ_STATE_ENABLED, &sq->state); + +- if (param->is_xdp_mb) +- set_bit(MLX5E_SQ_STATE_XDP_MULTIBUF, &sq->state); +- + err = mlx5e_create_sq_rdy(c->mdev, param, &csp, 0, &sq->sqn); + if (err) + goto err_free_xdpsq; + + mlx5e_set_xmit_fp(sq, param->is_mpw); + +- if (!param->is_mpw && !test_bit(MLX5E_SQ_STATE_XDP_MULTIBUF, &sq->state)) { +- unsigned int ds_cnt = MLX5E_TX_WQE_EMPTY_DS_COUNT + 1; +- unsigned int inline_hdr_sz = 0; +- int i; +- +- if (sq->min_inline_mode != MLX5_INLINE_MODE_NONE) { +- inline_hdr_sz = MLX5E_XDP_MIN_INLINE; +- ds_cnt++; +- } +- +- /* Pre initialize fixed WQE fields */ +- for (i = 0; i < mlx5_wq_cyc_get_size(&sq->wq); i++) { +- struct mlx5e_tx_wqe *wqe = mlx5_wq_cyc_get_wqe(&sq->wq, i); +- struct mlx5_wqe_ctrl_seg *cseg = &wqe->ctrl; +- struct mlx5_wqe_eth_seg *eseg = &wqe->eth; +- +- sq->db.wqe_info[i] = (struct mlx5e_xdp_wqe_info) { +- .num_wqebbs = 1, +- .num_pkts = 1, +- }; +- +- cseg->qpn_ds = cpu_to_be32((sq->sqn << 8) | ds_cnt); +- eseg->inline_hdr.sz = cpu_to_be16(inline_hdr_sz); +- } +- } +- + return 0; + + err_free_xdpsq: +-- +2.39.5 + diff --git a/queue-6.14/net-mlx5e-add-correct-match-to-check-ipsec-syndromes.patch b/queue-6.14/net-mlx5e-add-correct-match-to-check-ipsec-syndromes.patch new file mode 100644 index 0000000000..ed9bd8a7e1 --- /dev/null +++ b/queue-6.14/net-mlx5e-add-correct-match-to-check-ipsec-syndromes.patch @@ -0,0 +1,148 @@ +From 984b87e77bc29631de3bf705d750dd1f257db26b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 20 Feb 2025 23:39:53 +0200 +Subject: net/mlx5e: Add correct match to check IPSec syndromes for switchdev + mode + +From: Jianbo Liu + +[ Upstream commit 85e4a808af2545fefaf18c8fe50071b06fcbdabc ] + +In commit dddb49b63d86 ("net/mlx5e: Add IPsec and ASO syndromes check +in HW"), IPSec and ASO syndromes checks after decryption for the +specified ASO object were added. But they are correct only for eswith +in legacy mode. For switchdev mode, metadata register c1 is used to +save the mapped id (not ASO object id). So, need to change the match +accordingly for the check rules in status table. + +Signed-off-by: Jianbo Liu +Reviewed-by: Leon Romanovsky +Reviewed-by: Patrisious Haddad +Signed-off-by: Tariq Toukan +Link: https://patch.msgid.link/20250220213959.504304-4-tariqt@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + .../mellanox/mlx5/core/en_accel/ipsec_fs.c | 28 ++++++++++++++----- + .../mellanox/mlx5/core/esw/ipsec_fs.c | 13 +++++++++ + .../mellanox/mlx5/core/esw/ipsec_fs.h | 5 ++++ + include/linux/mlx5/eswitch.h | 2 ++ + 4 files changed, 41 insertions(+), 7 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c +index e7b64679f1219..3cf44fbdf5ee6 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c +@@ -165,6 +165,25 @@ static void ipsec_rx_status_pass_destroy(struct mlx5e_ipsec *ipsec, + #endif + } + ++static void ipsec_rx_rule_add_match_obj(struct mlx5e_ipsec_sa_entry *sa_entry, ++ struct mlx5e_ipsec_rx *rx, ++ struct mlx5_flow_spec *spec) ++{ ++ struct mlx5e_ipsec *ipsec = sa_entry->ipsec; ++ ++ if (rx == ipsec->rx_esw) { ++ mlx5_esw_ipsec_rx_rule_add_match_obj(sa_entry, spec); ++ } else { ++ MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, ++ misc_parameters_2.metadata_reg_c_2); ++ MLX5_SET(fte_match_param, spec->match_value, ++ misc_parameters_2.metadata_reg_c_2, ++ sa_entry->ipsec_obj_id | BIT(31)); ++ ++ spec->match_criteria_enable |= MLX5_MATCH_MISC_PARAMETERS_2; ++ } ++} ++ + static int rx_add_rule_drop_auth_trailer(struct mlx5e_ipsec_sa_entry *sa_entry, + struct mlx5e_ipsec_rx *rx) + { +@@ -200,11 +219,8 @@ static int rx_add_rule_drop_auth_trailer(struct mlx5e_ipsec_sa_entry *sa_entry, + + MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, misc_parameters_2.ipsec_syndrome); + MLX5_SET(fte_match_param, spec->match_value, misc_parameters_2.ipsec_syndrome, 1); +- MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, misc_parameters_2.metadata_reg_c_2); +- MLX5_SET(fte_match_param, spec->match_value, +- misc_parameters_2.metadata_reg_c_2, +- sa_entry->ipsec_obj_id | BIT(31)); + spec->match_criteria_enable = MLX5_MATCH_MISC_PARAMETERS_2; ++ ipsec_rx_rule_add_match_obj(sa_entry, rx, spec); + rule = mlx5_add_flow_rules(ft, spec, &flow_act, &dest, 1); + if (IS_ERR(rule)) { + err = PTR_ERR(rule); +@@ -281,10 +297,8 @@ static int rx_add_rule_drop_replay(struct mlx5e_ipsec_sa_entry *sa_entry, struct + + MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, misc_parameters_2.metadata_reg_c_4); + MLX5_SET(fte_match_param, spec->match_value, misc_parameters_2.metadata_reg_c_4, 1); +- MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, misc_parameters_2.metadata_reg_c_2); +- MLX5_SET(fte_match_param, spec->match_value, misc_parameters_2.metadata_reg_c_2, +- sa_entry->ipsec_obj_id | BIT(31)); + spec->match_criteria_enable = MLX5_MATCH_MISC_PARAMETERS_2; ++ ipsec_rx_rule_add_match_obj(sa_entry, rx, spec); + rule = mlx5_add_flow_rules(ft, spec, &flow_act, &dest, 1); + if (IS_ERR(rule)) { + err = PTR_ERR(rule); +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/ipsec_fs.c b/drivers/net/ethernet/mellanox/mlx5/core/esw/ipsec_fs.c +index ed977ae75fab8..4bba2884c1c05 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/esw/ipsec_fs.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/ipsec_fs.c +@@ -85,6 +85,19 @@ int mlx5_esw_ipsec_rx_setup_modify_header(struct mlx5e_ipsec_sa_entry *sa_entry, + return err; + } + ++void mlx5_esw_ipsec_rx_rule_add_match_obj(struct mlx5e_ipsec_sa_entry *sa_entry, ++ struct mlx5_flow_spec *spec) ++{ ++ MLX5_SET(fte_match_param, spec->match_criteria, ++ misc_parameters_2.metadata_reg_c_1, ++ ESW_IPSEC_RX_MAPPED_ID_MATCH_MASK); ++ MLX5_SET(fte_match_param, spec->match_value, ++ misc_parameters_2.metadata_reg_c_1, ++ sa_entry->rx_mapped_id << ESW_ZONE_ID_BITS); ++ ++ spec->match_criteria_enable |= MLX5_MATCH_MISC_PARAMETERS_2; ++} ++ + void mlx5_esw_ipsec_rx_id_mapping_remove(struct mlx5e_ipsec_sa_entry *sa_entry) + { + struct mlx5e_ipsec *ipsec = sa_entry->ipsec; +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/ipsec_fs.h b/drivers/net/ethernet/mellanox/mlx5/core/esw/ipsec_fs.h +index ac9c65b89166e..514c15258b1d1 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/esw/ipsec_fs.h ++++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/ipsec_fs.h +@@ -20,6 +20,8 @@ int mlx5_esw_ipsec_rx_ipsec_obj_id_search(struct mlx5e_priv *priv, u32 id, + void mlx5_esw_ipsec_tx_create_attr_set(struct mlx5e_ipsec *ipsec, + struct mlx5e_ipsec_tx_create_attr *attr); + void mlx5_esw_ipsec_restore_dest_uplink(struct mlx5_core_dev *mdev); ++void mlx5_esw_ipsec_rx_rule_add_match_obj(struct mlx5e_ipsec_sa_entry *sa_entry, ++ struct mlx5_flow_spec *spec); + #else + static inline void mlx5_esw_ipsec_rx_create_attr_set(struct mlx5e_ipsec *ipsec, + struct mlx5e_ipsec_rx_create_attr *attr) {} +@@ -48,5 +50,8 @@ static inline void mlx5_esw_ipsec_tx_create_attr_set(struct mlx5e_ipsec *ipsec, + struct mlx5e_ipsec_tx_create_attr *attr) {} + + static inline void mlx5_esw_ipsec_restore_dest_uplink(struct mlx5_core_dev *mdev) {} ++static inline void ++mlx5_esw_ipsec_rx_rule_add_match_obj(struct mlx5e_ipsec_sa_entry *sa_entry, ++ struct mlx5_flow_spec *spec) {} + #endif /* CONFIG_MLX5_ESWITCH */ + #endif /* __MLX5_ESW_IPSEC_FS_H__ */ +diff --git a/include/linux/mlx5/eswitch.h b/include/linux/mlx5/eswitch.h +index df73a2ccc9af3..67256e776566c 100644 +--- a/include/linux/mlx5/eswitch.h ++++ b/include/linux/mlx5/eswitch.h +@@ -147,6 +147,8 @@ u32 mlx5_eswitch_get_vport_metadata_for_set(struct mlx5_eswitch *esw, + + /* reuse tun_opts for the mapped ipsec obj id when tun_id is 0 (invalid) */ + #define ESW_IPSEC_RX_MAPPED_ID_MASK GENMASK(ESW_TUN_OPTS_BITS - 1, 0) ++#define ESW_IPSEC_RX_MAPPED_ID_MATCH_MASK \ ++ GENMASK(31 - ESW_RESERVED_BITS, ESW_ZONE_ID_BITS) + + u8 mlx5_eswitch_mode(const struct mlx5_core_dev *dev); + u16 mlx5_eswitch_get_total_vports(const struct mlx5_core_dev *dev); +-- +2.39.5 + diff --git a/queue-6.14/net-mlx5e-avoid-warn_on-when-configuring-mqprio-with.patch b/queue-6.14/net-mlx5e-avoid-warn_on-when-configuring-mqprio-with.patch new file mode 100644 index 0000000000..c0095ad0d0 --- /dev/null +++ b/queue-6.14/net-mlx5e-avoid-warn_on-when-configuring-mqprio-with.patch @@ -0,0 +1,49 @@ +From 81be469372b609c2204aa87520afc63f6e11ee5b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 3 Feb 2025 23:35:16 +0200 +Subject: net/mlx5e: Avoid WARN_ON when configuring MQPRIO with HTB offload + enabled + +From: Carolina Jubran + +[ Upstream commit 689805dcc474c2accb5cffbbcea1c06ee4a54570 ] + +When attempting to enable MQPRIO while HTB offload is already +configured, the driver currently returns `-EINVAL` and triggers a +`WARN_ON`, leading to an unnecessary call trace. + +Update the code to handle this case more gracefully by returning +`-EOPNOTSUPP` instead, while also providing a helpful user message. + +Signed-off-by: Carolina Jubran +Reviewed-by: Yael Chemla +Reviewed-by: Cosmin Ratiu +Signed-off-by: Tariq Toukan +Reviewed-by: Kalesh AP +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +index b0748e46b1ac4..ca56740f6d2f9 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +@@ -3787,8 +3787,11 @@ static int mlx5e_setup_tc_mqprio(struct mlx5e_priv *priv, + /* MQPRIO is another toplevel qdisc that can't be attached + * simultaneously with the offloaded HTB. + */ +- if (WARN_ON(mlx5e_selq_is_htb_enabled(&priv->selq))) +- return -EINVAL; ++ if (mlx5e_selq_is_htb_enabled(&priv->selq)) { ++ NL_SET_ERR_MSG_MOD(mqprio->extack, ++ "MQPRIO cannot be configured when HTB offload is enabled."); ++ return -EOPNOTSUPP; ++ } + + switch (mqprio->mode) { + case TC_MQPRIO_MODE_DCB: +-- +2.39.5 + diff --git a/queue-6.14/net-mlx5e-reduce-rep-rxq-depth-to-256-for-ecpf.patch b/queue-6.14/net-mlx5e-reduce-rep-rxq-depth-to-256-for-ecpf.patch new file mode 100644 index 0000000000..e1cd8cc15c --- /dev/null +++ b/queue-6.14/net-mlx5e-reduce-rep-rxq-depth-to-256-for-ecpf.patch @@ -0,0 +1,75 @@ +From 136415b75883fd2ee71b4950c752bc2e2800c0b1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 9 Feb 2025 12:17:08 +0200 +Subject: net/mlx5e: reduce rep rxq depth to 256 for ECPF + +From: William Tu + +[ Upstream commit b9cc8f9d700867aaa77aedddfea85e53d5e5d584 ] + +By experiments, a single queue representor netdev consumes kernel +memory around 2.8MB, and 1.8MB out of the 2.8MB is due to page +pool for the RXQ. Scaling to a thousand representors consumes 2.8GB, +which becomes a memory pressure issue for embedded devices such as +BlueField-2 16GB / BlueField-3 32GB memory. + +Since representor netdevs mostly handles miss traffic, and ideally, +most of the traffic will be offloaded, reduce the default non-uplink +rep netdev's RXQ default depth from 1024 to 256 if mdev is ecpf eswitch +manager. This saves around 1MB of memory per regular RQ, +(1024 - 256) * 2KB, allocated from page pool. + +With rxq depth of 256, the netlink page pool tool reports +$./tools/net/ynl/cli.py --spec Documentation/netlink/specs/netdev.yaml \ + --dump page-pool-get + {'id': 277, + 'ifindex': 9, + 'inflight': 128, + 'inflight-mem': 786432, + 'napi-id': 775}] + +This is due to mtu 1500 + headroom consumes half pages, so 256 rxq +entries consumes around 128 pages (thus create a page pool with +size 128), shown above at inflight. + +Note that each netdev has multiple types of RQs, including +Regular RQ, XSK, PTP, Drop, Trap RQ. Since non-uplink representor +only supports regular rq, this patch only changes the regular RQ's +default depth. + +Signed-off-by: William Tu +Reviewed-by: Bodong Wang +Reviewed-by: Saeed Mahameed +Signed-off-by: Tariq Toukan +Reviewed-by: Michal Swiatkowski +Link: https://patch.msgid.link/20250209101716.112774-8-tariqt@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/en_rep.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c +index 6667ec26e079b..07f38f472a279 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c +@@ -65,6 +65,7 @@ + #define MLX5E_REP_PARAMS_DEF_LOG_SQ_SIZE \ + max(0x7, MLX5E_PARAMS_MINIMUM_LOG_SQ_SIZE) + #define MLX5E_REP_PARAMS_DEF_NUM_CHANNELS 1 ++#define MLX5E_REP_PARAMS_DEF_LOG_RQ_SIZE 0x8 + + static const char mlx5e_rep_driver_name[] = "mlx5e_rep"; + +@@ -855,6 +856,8 @@ static void mlx5e_build_rep_params(struct net_device *netdev) + + /* RQ */ + mlx5e_build_rq_params(mdev, params); ++ if (!mlx5e_is_uplink_rep(priv) && mlx5_core_is_ecpf(mdev)) ++ params->log_rq_mtu_frames = MLX5E_REP_PARAMS_DEF_LOG_RQ_SIZE; + + /* If netdev is already registered (e.g. move from nic profile to uplink, + * RTNL lock must be held before triggering netdev notifiers. +-- +2.39.5 + diff --git a/queue-6.14/net-mlx5e-reduce-the-max-log-mpwrq-sz-for-ecpf-and-r.patch b/queue-6.14/net-mlx5e-reduce-the-max-log-mpwrq-sz-for-ecpf-and-r.patch new file mode 100644 index 0000000000..7e18b74ce9 --- /dev/null +++ b/queue-6.14/net-mlx5e-reduce-the-max-log-mpwrq-sz-for-ecpf-and-r.patch @@ -0,0 +1,92 @@ +From 520fb38905a8e646a6abf84c0ae7e32000499b08 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 9 Feb 2025 12:17:07 +0200 +Subject: net/mlx5e: reduce the max log mpwrq sz for ECPF and reps + +From: William Tu + +[ Upstream commit e1d68ea58c7e9ebacd9ad7a99b25a3578fa62182 ] + +For the ECPF and representors, reduce the max MPWRQ size from 256KB (18) +to 128KB (17). This prepares the later patch for saving representor +memory. + +With Striding RQ, there is a minimum of 4 MPWQEs. So with 128KB of max +MPWRQ size, the minimal memory is 4 * 128KB = 512KB. When creating page +pool, consider 1500 mtu, the minimal page pool size will be 512KB/4KB = +128 pages = 256 rx ring entries (2 entries per page). + +Before this patch, setting RX ringsize (ethtool -G rx) to 256 causes +driver to allocate page pool size more than it needs due to max MPWRQ +is 256KB (18). Ex: 4 * 256KB = 1MB, 1MB/4KB = 256 pages, but actually +128 pages is good enough. Reducing the max MPWRQ to 128KB fixes the +limitation. + +Signed-off-by: William Tu +Signed-off-by: Tariq Toukan +Reviewed-by: Michal Swiatkowski +Link: https://patch.msgid.link/20250209101716.112774-7-tariqt@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/en.h | 2 -- + .../net/ethernet/mellanox/mlx5/core/en/params.c | 15 +++++++++++---- + 2 files changed, 11 insertions(+), 6 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h +index 8f9ec48ecc06d..769e683f24883 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en.h ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h +@@ -95,8 +95,6 @@ struct page_pool; + #define MLX5_MPWRQ_DEF_LOG_STRIDE_SZ(mdev) \ + MLX5_MPWRQ_LOG_STRIDE_SZ(mdev, order_base_2(MLX5E_RX_MAX_HEAD)) + +-#define MLX5_MPWRQ_MAX_LOG_WQE_SZ 18 +- + /* Keep in sync with mlx5e_mpwrq_log_wqe_sz. + * These are theoretical maximums, which can be further restricted by + * capabilities. These values are used for static resource allocations and +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/params.c b/drivers/net/ethernet/mellanox/mlx5/core/en/params.c +index 8c4d710e85675..58ec5e44aa7ad 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en/params.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en/params.c +@@ -10,6 +10,9 @@ + #include + #include + ++#define MLX5_MPWRQ_MAX_LOG_WQE_SZ 18 ++#define MLX5_REP_MPWRQ_MAX_LOG_WQE_SZ 17 ++ + static u8 mlx5e_mpwrq_min_page_shift(struct mlx5_core_dev *mdev) + { + u8 min_page_shift = MLX5_CAP_GEN_2(mdev, log_min_mkey_entity_size); +@@ -103,18 +106,22 @@ u8 mlx5e_mpwrq_log_wqe_sz(struct mlx5_core_dev *mdev, u8 page_shift, + enum mlx5e_mpwrq_umr_mode umr_mode) + { + u8 umr_entry_size = mlx5e_mpwrq_umr_entry_size(umr_mode); +- u8 max_pages_per_wqe, max_log_mpwqe_size; ++ u8 max_pages_per_wqe, max_log_wqe_size_calc; ++ u8 max_log_wqe_size_cap; + u16 max_wqe_size; + + /* Keep in sync with MLX5_MPWRQ_MAX_PAGES_PER_WQE. */ + max_wqe_size = mlx5e_get_max_sq_aligned_wqebbs(mdev) * MLX5_SEND_WQE_BB; + max_pages_per_wqe = ALIGN_DOWN(max_wqe_size - sizeof(struct mlx5e_umr_wqe), + MLX5_UMR_FLEX_ALIGNMENT) / umr_entry_size; +- max_log_mpwqe_size = ilog2(max_pages_per_wqe) + page_shift; ++ max_log_wqe_size_calc = ilog2(max_pages_per_wqe) + page_shift; ++ ++ WARN_ON_ONCE(max_log_wqe_size_calc < MLX5E_ORDER2_MAX_PACKET_MTU); + +- WARN_ON_ONCE(max_log_mpwqe_size < MLX5E_ORDER2_MAX_PACKET_MTU); ++ max_log_wqe_size_cap = mlx5_core_is_ecpf(mdev) ? ++ MLX5_REP_MPWRQ_MAX_LOG_WQE_SZ : MLX5_MPWRQ_MAX_LOG_WQE_SZ; + +- return min_t(u8, max_log_mpwqe_size, MLX5_MPWRQ_MAX_LOG_WQE_SZ); ++ return min_t(u8, max_log_wqe_size_calc, max_log_wqe_size_cap); + } + + u8 mlx5e_mpwrq_pages_per_wqe(struct mlx5_core_dev *mdev, u8 page_shift, +-- +2.39.5 + diff --git a/queue-6.14/net-mlx5e-set-the-tx_queue_len-for-pfifo_fast.patch b/queue-6.14/net-mlx5e-set-the-tx_queue_len-for-pfifo_fast.patch new file mode 100644 index 0000000000..82bee805a7 --- /dev/null +++ b/queue-6.14/net-mlx5e-set-the-tx_queue_len-for-pfifo_fast.patch @@ -0,0 +1,44 @@ +From 48303af4e778c6afef9da761f76969baa5635f77 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 9 Feb 2025 12:17:09 +0200 +Subject: net/mlx5e: set the tx_queue_len for pfifo_fast + +From: William Tu + +[ Upstream commit a38cc5706fb9f7dc4ee3a443f61de13ce1e410ed ] + +By default, the mq netdev creates a pfifo_fast qdisc. On a +system with 16 core, the pfifo_fast with 3 bands consumes +16 * 3 * 8 (size of pointer) * 1024 (default tx queue len) += 393KB. The patch sets the tx qlen to representor default +value, 128 (1< +Reviewed-by: Daniel Jurgens +Signed-off-by: Tariq Toukan +Reviewed-by: Michal Swiatkowski +Link: https://patch.msgid.link/20250209101716.112774-9-tariqt@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/en_rep.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c +index fdff9fd8a89ec..6667ec26e079b 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c +@@ -886,6 +886,8 @@ static void mlx5e_build_rep_netdev(struct net_device *netdev, + netdev->ethtool_ops = &mlx5e_rep_ethtool_ops; + + netdev->watchdog_timeo = 15 * HZ; ++ if (mlx5_core_is_ecpf(mdev)) ++ netdev->tx_queue_len = 1 << MLX5E_REP_PARAMS_DEF_LOG_SQ_SIZE; + + #if IS_ENABLED(CONFIG_MLX5_CLS_ACT) + netdev->hw_features |= NETIF_F_HW_TC; +-- +2.39.5 + diff --git a/queue-6.14/net-mlx5e-use-right-api-to-free-bitmap-memory.patch b/queue-6.14/net-mlx5e-use-right-api-to-free-bitmap-memory.patch new file mode 100644 index 0000000000..948de9fd70 --- /dev/null +++ b/queue-6.14/net-mlx5e-use-right-api-to-free-bitmap-memory.patch @@ -0,0 +1,49 @@ +From e2a0adfa0868fc06ac92ec364d80d72fa142efe0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 19 Mar 2025 21:23:18 +0200 +Subject: net/mlx5e: Use right API to free bitmap memory + +From: Mark Zhang + +[ Upstream commit cac48eb6d383ee4f037e320608efa5dec029e26a ] + +Use bitmap_free() to free memory allocated with bitmap_zalloc_node(). +This fixes memtrack error: + mtl rsc inconsistency: memtrack_free: .../drivers/net/ethernet/mellanox/mlx5/core/en_main.c::466: kfree for unknown address=0xFFFF0000CA3619E8, device=0x0 + +Signed-off-by: Mark Zhang +Reviewed-by: Maher Sanalla +Signed-off-by: Tariq Toukan +Reviewed-by: Kalesh AP +Link: https://patch.msgid.link/1742412199-159596-3-git-send-email-tariqt@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +index 01f6a60308cb7..5c5168bdacb90 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +@@ -359,7 +359,7 @@ static int mlx5e_rq_shampo_hd_info_alloc(struct mlx5e_rq *rq, int node) + return 0; + + err_nomem: +- kvfree(shampo->bitmap); ++ bitmap_free(shampo->bitmap); + kvfree(shampo->pages); + + return -ENOMEM; +@@ -367,7 +367,7 @@ static int mlx5e_rq_shampo_hd_info_alloc(struct mlx5e_rq *rq, int node) + + static void mlx5e_rq_shampo_hd_info_free(struct mlx5e_rq *rq) + { +- kvfree(rq->mpwqe.shampo->bitmap); ++ bitmap_free(rq->mpwqe.shampo->bitmap); + kvfree(rq->mpwqe.shampo->pages); + } + +-- +2.39.5 + diff --git a/queue-6.14/net-page_pool-avoid-false-positive-warning-if-napi-w.patch b/queue-6.14/net-page_pool-avoid-false-positive-warning-if-napi-w.patch new file mode 100644 index 0000000000..bbed705578 --- /dev/null +++ b/queue-6.14/net-page_pool-avoid-false-positive-warning-if-napi-w.patch @@ -0,0 +1,72 @@ +From 88e115fd81bf2c9243f959067c3fa20a1934296d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Feb 2025 14:56:37 -0800 +Subject: net: page_pool: avoid false positive warning if NAPI was never added + +From: Jakub Kicinski + +[ Upstream commit c1e00bc4be06cacee6307cedb9b55bbaddb5044d ] + +We expect NAPI to be in disabled state when page pool is torn down. +But it is also legal if the NAPI is completely uninitialized. + +Reviewed-by: Mina Almasry +Link: https://patch.msgid.link/20250206225638.1387810-4-kuba@kernel.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/core/dev.h | 12 ++++++++++++ + net/core/page_pool.c | 7 ++----- + 2 files changed, 14 insertions(+), 5 deletions(-) + +diff --git a/net/core/dev.h b/net/core/dev.h +index a5b166bbd169a..caa13e431a6bc 100644 +--- a/net/core/dev.h ++++ b/net/core/dev.h +@@ -299,6 +299,18 @@ void xdp_do_check_flushed(struct napi_struct *napi); + static inline void xdp_do_check_flushed(struct napi_struct *napi) { } + #endif + ++/* Best effort check that NAPI is not idle (can't be scheduled to run) */ ++static inline void napi_assert_will_not_race(const struct napi_struct *napi) ++{ ++ /* uninitialized instance, can't race */ ++ if (!napi->poll_list.next) ++ return; ++ ++ /* SCHED bit is set on disabled instances */ ++ WARN_ON(!test_bit(NAPI_STATE_SCHED, &napi->state)); ++ WARN_ON(READ_ONCE(napi->list_owner) != -1); ++} ++ + void kick_defer_list_purge(struct softnet_data *sd, unsigned int cpu); + + #define XMIT_RECURSION_LIMIT 8 +diff --git a/net/core/page_pool.c b/net/core/page_pool.c +index ede82c610936e..cca51aa2e876f 100644 +--- a/net/core/page_pool.c ++++ b/net/core/page_pool.c +@@ -25,6 +25,7 @@ + + #include + ++#include "dev.h" + #include "mp_dmabuf_devmem.h" + #include "netmem_priv.h" + #include "page_pool_priv.h" +@@ -1146,11 +1147,7 @@ void page_pool_disable_direct_recycling(struct page_pool *pool) + if (!pool->p.napi) + return; + +- /* To avoid races with recycling and additional barriers make sure +- * pool and NAPI are unlinked when NAPI is disabled. +- */ +- WARN_ON(!test_bit(NAPI_STATE_SCHED, &pool->p.napi->state)); +- WARN_ON(READ_ONCE(pool->p.napi->list_owner) != -1); ++ napi_assert_will_not_race(pool->p.napi); + + mutex_lock(&page_pools_lock); + WRITE_ONCE(pool->p.napi, NULL); +-- +2.39.5 + diff --git a/queue-6.14/net-phy-nxp-c45-tja11xx-add-match_phy_device-to-tja1.patch b/queue-6.14/net-phy-nxp-c45-tja11xx-add-match_phy_device-to-tja1.patch new file mode 100644 index 0000000000..7d055670d6 --- /dev/null +++ b/queue-6.14/net-phy-nxp-c45-tja11xx-add-match_phy_device-to-tja1.patch @@ -0,0 +1,118 @@ +From 380e3cc8821631c385db6d35ecb6769fd8d99c70 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 28 Feb 2025 17:43:19 +0200 +Subject: net: phy: nxp-c45-tja11xx: add match_phy_device to TJA1103/TJA1104 + +From: Andrei Botila + +[ Upstream commit a06a868a0cd96bc51401cdea897313a3f6ad01a0 ] + +Add .match_phy_device for the existing TJAs to differentiate between +TJA1103 and TJA1104. +TJA1103 and TJA1104 share the same PHY_ID but TJA1104 has MACsec +capabilities while TJA1103 doesn't. + +Signed-off-by: Andrei Botila +Reviewed-by: Andrew Lunn +Link: https://patch.msgid.link/20250228154320.2979000-2-andrei.botila@oss.nxp.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/phy/nxp-c45-tja11xx.c | 54 +++++++++++++++++++++++++++++-- + 1 file changed, 52 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/phy/nxp-c45-tja11xx.c b/drivers/net/phy/nxp-c45-tja11xx.c +index e9fc54517449c..16e1c13ae2f8d 100644 +--- a/drivers/net/phy/nxp-c45-tja11xx.c ++++ b/drivers/net/phy/nxp-c45-tja11xx.c +@@ -1,6 +1,6 @@ + // SPDX-License-Identifier: GPL-2.0 + /* NXP C45 PHY driver +- * Copyright 2021-2023 NXP ++ * Copyright 2021-2025 NXP + * Author: Radu Pirea + */ + +@@ -19,6 +19,8 @@ + + #include "nxp-c45-tja11xx.h" + ++#define PHY_ID_MASK GENMASK(31, 4) ++/* Same id: TJA1103, TJA1104 */ + #define PHY_ID_TJA_1103 0x001BB010 + #define PHY_ID_TJA_1120 0x001BB031 + +@@ -1956,6 +1958,30 @@ static void tja1120_nmi_handler(struct phy_device *phydev, + } + } + ++static int nxp_c45_macsec_ability(struct phy_device *phydev) ++{ ++ bool macsec_ability; ++ int phy_abilities; ++ ++ phy_abilities = phy_read_mmd(phydev, MDIO_MMD_VEND1, ++ VEND1_PORT_ABILITIES); ++ macsec_ability = !!(phy_abilities & MACSEC_ABILITY); ++ ++ return macsec_ability; ++} ++ ++static int tja1103_match_phy_device(struct phy_device *phydev) ++{ ++ return phy_id_compare(phydev->phy_id, PHY_ID_TJA_1103, PHY_ID_MASK) && ++ !nxp_c45_macsec_ability(phydev); ++} ++ ++static int tja1104_match_phy_device(struct phy_device *phydev) ++{ ++ return phy_id_compare(phydev->phy_id, PHY_ID_TJA_1103, PHY_ID_MASK) && ++ nxp_c45_macsec_ability(phydev); ++} ++ + static const struct nxp_c45_regmap tja1120_regmap = { + .vend1_ptp_clk_period = 0x1020, + .vend1_event_msg_filt = 0x9010, +@@ -2026,7 +2052,6 @@ static const struct nxp_c45_phy_data tja1120_phy_data = { + + static struct phy_driver nxp_c45_driver[] = { + { +- PHY_ID_MATCH_MODEL(PHY_ID_TJA_1103), + .name = "NXP C45 TJA1103", + .get_features = nxp_c45_get_features, + .driver_data = &tja1103_phy_data, +@@ -2048,6 +2073,31 @@ static struct phy_driver nxp_c45_driver[] = { + .get_sqi = nxp_c45_get_sqi, + .get_sqi_max = nxp_c45_get_sqi_max, + .remove = nxp_c45_remove, ++ .match_phy_device = tja1103_match_phy_device, ++ }, ++ { ++ .name = "NXP C45 TJA1104", ++ .get_features = nxp_c45_get_features, ++ .driver_data = &tja1103_phy_data, ++ .probe = nxp_c45_probe, ++ .soft_reset = nxp_c45_soft_reset, ++ .config_aneg = genphy_c45_config_aneg, ++ .config_init = nxp_c45_config_init, ++ .config_intr = tja1103_config_intr, ++ .handle_interrupt = nxp_c45_handle_interrupt, ++ .read_status = genphy_c45_read_status, ++ .suspend = genphy_c45_pma_suspend, ++ .resume = genphy_c45_pma_resume, ++ .get_sset_count = nxp_c45_get_sset_count, ++ .get_strings = nxp_c45_get_strings, ++ .get_stats = nxp_c45_get_stats, ++ .cable_test_start = nxp_c45_cable_test_start, ++ .cable_test_get_status = nxp_c45_cable_test_get_status, ++ .set_loopback = genphy_c45_loopback, ++ .get_sqi = nxp_c45_get_sqi, ++ .get_sqi_max = nxp_c45_get_sqi_max, ++ .remove = nxp_c45_remove, ++ .match_phy_device = tja1104_match_phy_device, + }, + { + PHY_ID_MATCH_MODEL(PHY_ID_TJA_1120), +-- +2.39.5 + diff --git a/queue-6.14/net-phylink-use-pl-link_interface-in-phylink_expects.patch b/queue-6.14/net-phylink-use-pl-link_interface-in-phylink_expects.patch new file mode 100644 index 0000000000..4785d4b0e1 --- /dev/null +++ b/queue-6.14/net-phylink-use-pl-link_interface-in-phylink_expects.patch @@ -0,0 +1,59 @@ +From dafdfabb39ba3801a53e173db7f7043177b9ffdb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 27 Feb 2025 20:15:17 +0800 +Subject: net: phylink: use pl->link_interface in phylink_expects_phy() + +From: Choong Yong Liang + +[ Upstream commit b63263555eaafbf9ab1a82f2020bbee872d83759 ] + +The phylink_expects_phy() function allows MAC drivers to check if they are +expecting a PHY to attach. The checking condition in phylink_expects_phy() +aims to achieve the same result as the checking condition in +phylink_attach_phy(). + +However, the checking condition in phylink_expects_phy() uses +pl->link_config.interface, while phylink_attach_phy() uses +pl->link_interface. + +Initially, both pl->link_interface and pl->link_config.interface are set +to SGMII, and pl->cfg_link_an_mode is set to MLO_AN_INBAND. + +When the interface switches from SGMII to 2500BASE-X, +pl->link_config.interface is updated by phylink_major_config(). +At this point, pl->cfg_link_an_mode remains MLO_AN_INBAND, and +pl->link_config.interface is set to 2500BASE-X. +Subsequently, when the STMMAC interface is taken down +administratively and brought back up, it is blocked by +phylink_expects_phy(). + +Since phylink_expects_phy() and phylink_attach_phy() aim to achieve the +same result, phylink_expects_phy() should check pl->link_interface, +which never changes, instead of pl->link_config.interface, which is +updated by phylink_major_config(). + +Reviewed-by: Russell King (Oracle) +Signed-off-by: Choong Yong Liang +Link: https://patch.msgid.link/20250227121522.1802832-2-yong.liang.choong@linux.intel.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/phy/phylink.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c +index 5be48eb810abb..8c4dfe9dc7650 100644 +--- a/drivers/net/phy/phylink.c ++++ b/drivers/net/phy/phylink.c +@@ -2074,7 +2074,7 @@ bool phylink_expects_phy(struct phylink *pl) + { + if (pl->cfg_link_an_mode == MLO_AN_FIXED || + (pl->cfg_link_an_mode == MLO_AN_INBAND && +- phy_interface_mode_is_8023z(pl->link_config.interface))) ++ phy_interface_mode_is_8023z(pl->link_interface))) + return false; + return true; + } +-- +2.39.5 + diff --git a/queue-6.14/net-pktgen-fix-access-outside-of-user-given-buffer-i.patch b/queue-6.14/net-pktgen-fix-access-outside-of-user-given-buffer-i.patch new file mode 100644 index 0000000000..9b630b9745 --- /dev/null +++ b/queue-6.14/net-pktgen-fix-access-outside-of-user-given-buffer-i.patch @@ -0,0 +1,50 @@ +From ec49b24cc60acb617863681c81531cbee7910242 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 19 Feb 2025 09:45:27 +0100 +Subject: net: pktgen: fix access outside of user given buffer in + pktgen_thread_write() + +From: Peter Seiderer + +[ Upstream commit 425e64440ad0a2f03bdaf04be0ae53dededbaa77 ] + +Honour the user given buffer size for the strn_len() calls (otherwise +strn_len() will access memory outside of the user given buffer). + +Signed-off-by: Peter Seiderer +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20250219084527.20488-8-ps.report@gmx.net +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/core/pktgen.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/net/core/pktgen.c b/net/core/pktgen.c +index 6ea34c95179f4..d3a76e81dd886 100644 +--- a/net/core/pktgen.c ++++ b/net/core/pktgen.c +@@ -1898,8 +1898,8 @@ static ssize_t pktgen_thread_write(struct file *file, + i = len; + + /* Read variable name */ +- +- len = strn_len(&user_buffer[i], sizeof(name) - 1); ++ max = min(sizeof(name) - 1, count - i); ++ len = strn_len(&user_buffer[i], max); + if (len < 0) + return len; + +@@ -1929,7 +1929,8 @@ static ssize_t pktgen_thread_write(struct file *file, + if (!strcmp(name, "add_device")) { + char f[32]; + memset(f, 0, 32); +- len = strn_len(&user_buffer[i], sizeof(f) - 1); ++ max = min(sizeof(f) - 1, count - i); ++ len = strn_len(&user_buffer[i], max); + if (len < 0) { + ret = len; + goto out; +-- +2.39.5 + diff --git a/queue-6.14/net-pktgen-fix-mpls-maximum-labels-list-parsing.patch b/queue-6.14/net-pktgen-fix-mpls-maximum-labels-list-parsing.patch new file mode 100644 index 0000000000..b34e9fa519 --- /dev/null +++ b/queue-6.14/net-pktgen-fix-mpls-maximum-labels-list-parsing.patch @@ -0,0 +1,52 @@ +From 16a7d534f34a0c3efb7bc04bc1a1aa1b5136a027 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 27 Feb 2025 14:56:00 +0100 +Subject: net: pktgen: fix mpls maximum labels list parsing + +From: Peter Seiderer + +[ Upstream commit 2b15a0693f70d1e8119743ee89edbfb1271b3ea8 ] + +Fix mpls maximum labels list parsing up to MAX_MPLS_LABELS entries (instead +of up to MAX_MPLS_LABELS - 1). + +Addresses the following: + + $ echo "mpls 00000f00,00000f01,00000f02,00000f03,00000f04,00000f05,00000f06,00000f07,00000f08,00000f09,00000f0a,00000f0b,00000f0c,00000f0d,00000f0e,00000f0f" > /proc/net/pktgen/lo\@0 + -bash: echo: write error: Argument list too long + +Signed-off-by: Peter Seiderer +Reviewed-by: Simon Horman +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/core/pktgen.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/net/core/pktgen.c b/net/core/pktgen.c +index 82b6a2c3c141f..6ea34c95179f4 100644 +--- a/net/core/pktgen.c ++++ b/net/core/pktgen.c +@@ -898,6 +898,10 @@ static ssize_t get_labels(const char __user *buffer, struct pktgen_dev *pkt_dev) + pkt_dev->nr_labels = 0; + do { + __u32 tmp; ++ ++ if (n >= MAX_MPLS_LABELS) ++ return -E2BIG; ++ + len = hex32_arg(&buffer[i], 8, &tmp); + if (len <= 0) + return len; +@@ -909,8 +913,6 @@ static ssize_t get_labels(const char __user *buffer, struct pktgen_dev *pkt_dev) + return -EFAULT; + i++; + n++; +- if (n >= MAX_MPLS_LABELS) +- return -E2BIG; + } while (c == ','); + + pkt_dev->nr_labels = n; +-- +2.39.5 + diff --git a/queue-6.14/net-smc-use-the-correct-ndev-to-find-pnetid-by-pneti.patch b/queue-6.14/net-smc-use-the-correct-ndev-to-find-pnetid-by-pneti.patch new file mode 100644 index 0000000000..1813ba254d --- /dev/null +++ b/queue-6.14/net-smc-use-the-correct-ndev-to-find-pnetid-by-pneti.patch @@ -0,0 +1,120 @@ +From cbcdcb81b6ed3296cc78cf7750bb4fa244293937 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 4 Mar 2025 20:43:04 +0800 +Subject: net/smc: use the correct ndev to find pnetid by pnetid table + +From: Guangguan Wang + +[ Upstream commit bfc6c67ec2d64d0ca4e5cc3e1ac84298a10b8d62 ] + +When using smc_pnet in SMC, it will only search the pnetid in the +base_ndev of the netdev hierarchy(both HW PNETID and User-defined +sw pnetid). This may not work for some scenarios when using SMC in +container on cloud environment. +In container, there have choices of different container network, +such as directly using host network, virtual network IPVLAN, veth, +etc. Different choices of container network have different netdev +hierarchy. Examples of netdev hierarchy show below. (eth0 and eth1 +in host below is the netdev directly related to the physical device). + _______________________________ + | _________________ | + | |POD | | + | | | | + | | eth0_________ | | + | |____| |__| | + | | | | + | | | | + | eth1|base_ndev| eth0_______ | + | | | | RDMA || + | host |_________| |_______|| + --------------------------------- + netdev hierarchy if directly using host network + ________________________________ + | _________________ | + | |POD __________ | | + | | |upper_ndev| | | + | |eth0|__________| | | + | |_______|_________| | + | |lower netdev | + | __|______ | + | eth1| | eth0_______ | + | |base_ndev| | RDMA || + | host |_________| |_______|| + --------------------------------- + netdev hierarchy if using IPVLAN + _______________________________ + | _____________________ | + | |POD _________ | | + | | |base_ndev|| | + | |eth0(veth)|_________|| | + | |____________|________| | + | |pairs | + | _______|_ | + | | | eth0_______ | + | veth|base_ndev| | RDMA || + | |_________| |_______|| + | _________ | + | eth1|base_ndev| | + | host |_________| | + --------------------------------- + netdev hierarchy if using veth +Due to some reasons, the eth1 in host is not RDMA attached netdevice, +pnetid is needed to map the eth1(in host) with RDMA device so that POD +can do SMC-R. Because the eth1(in host) is managed by CNI plugin(such +as Terway, network management plugin in container environment), and in +cloud environment the eth(in host) can dynamically be inserted by CNI +when POD create and dynamically be removed by CNI when POD destroy and +no POD related to the eth(in host) anymore. It is hard to config the +pnetid to the eth1(in host). But it is easy to config the pnetid to the +netdevice which can be seen in POD. When do SMC-R, both the container +directly using host network and the container using veth network can +successfully match the RDMA device, because the configured pnetid netdev +is a base_ndev. But the container using IPVLAN can not successfully +match the RDMA device and 0x03030000 fallback happens, because the +configured pnetid netdev is not a base_ndev. Additionally, if config +pnetid to the eth1(in host) also can not work for matching RDMA device +when using veth network and doing SMC-R in POD. + +To resolve the problems list above, this patch extends to search user +-defined sw pnetid in the clc handshake ndev when no pnetid can be found +in the base_ndev, and the base_ndev take precedence over ndev for backward +compatibility. This patch also can unify the pnetid setup of different +network choices list above in container(Config user-defined sw pnetid in +the netdevice can be seen in POD). + +Signed-off-by: Guangguan Wang +Reviewed-by: Wenjia Zhang +Reviewed-by: Halil Pasic +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + net/smc/smc_pnet.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +diff --git a/net/smc/smc_pnet.c b/net/smc/smc_pnet.c +index 716808f374a8d..b391c2ef463f2 100644 +--- a/net/smc/smc_pnet.c ++++ b/net/smc/smc_pnet.c +@@ -1079,14 +1079,16 @@ static void smc_pnet_find_roce_by_pnetid(struct net_device *ndev, + struct smc_init_info *ini) + { + u8 ndev_pnetid[SMC_MAX_PNETID_LEN]; ++ struct net_device *base_ndev; + struct net *net; + +- ndev = pnet_find_base_ndev(ndev); ++ base_ndev = pnet_find_base_ndev(ndev); + net = dev_net(ndev); +- if (smc_pnetid_by_dev_port(ndev->dev.parent, ndev->dev_port, ++ if (smc_pnetid_by_dev_port(base_ndev->dev.parent, base_ndev->dev_port, + ndev_pnetid) && ++ smc_pnet_find_ndev_pnetid_by_table(base_ndev, ndev_pnetid) && + smc_pnet_find_ndev_pnetid_by_table(ndev, ndev_pnetid)) { +- smc_pnet_find_rdma_dev(ndev, ini); ++ smc_pnet_find_rdma_dev(base_ndev, ini); + return; /* pnetid could not be determined */ + } + _smc_pnet_find_roce_by_pnetid(ndev_pnetid, ini, NULL, net); +-- +2.39.5 + diff --git a/queue-6.14/net-stmmac-correct-usage-of-maximum-queue-number-mac.patch b/queue-6.14/net-stmmac-correct-usage-of-maximum-queue-number-mac.patch new file mode 100644 index 0000000000..02e24e3b7a --- /dev/null +++ b/queue-6.14/net-stmmac-correct-usage-of-maximum-queue-number-mac.patch @@ -0,0 +1,78 @@ +From 91580649a46bd64ecebd715ec96da81348ed220a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 21 Feb 2025 14:18:18 +0900 +Subject: net: stmmac: Correct usage of maximum queue number macros + +From: Kunihiko Hayashi + +[ Upstream commit 352bc4513ec3907db71cb5674fb93a76fc341ca9 ] + +The maximum numbers of each Rx and Tx queues are defined by +MTL_MAX_RX_QUEUES and MTL_MAX_TX_QUEUES respectively. + +There are some places where Rx and Tx are used in reverse. There is no +issue when the Tx and Rx macros have the same value, but should correct +usage of macros for maximum queue number to keep consistency and prevent +unexpected mistakes. + +Reviewed-by: Russell King (Oracle) +Reviewed-by: Huacai Chen +Signed-off-by: Kunihiko Hayashi +Link: https://patch.msgid.link/20250221051818.4163678-1-hayashi.kunihiko@socionext.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/stmicro/stmmac/common.h | 4 ++-- + drivers/net/ethernet/stmicro/stmmac/stmmac.h | 7 +++---- + 2 files changed, 5 insertions(+), 6 deletions(-) + +diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h +index e25db747a81a5..c660eb933f24b 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/common.h ++++ b/drivers/net/ethernet/stmicro/stmmac/common.h +@@ -101,8 +101,8 @@ struct stmmac_rxq_stats { + /* Updates on each CPU protected by not allowing nested irqs. */ + struct stmmac_pcpu_stats { + struct u64_stats_sync syncp; +- u64_stats_t rx_normal_irq_n[MTL_MAX_TX_QUEUES]; +- u64_stats_t tx_normal_irq_n[MTL_MAX_RX_QUEUES]; ++ u64_stats_t rx_normal_irq_n[MTL_MAX_RX_QUEUES]; ++ u64_stats_t tx_normal_irq_n[MTL_MAX_TX_QUEUES]; + }; + + /* Extra statistic and debug information exposed by ethtool */ +diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h +index f05cae103d836..dae279ee2c280 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h +@@ -257,7 +257,7 @@ struct stmmac_priv { + /* Frequently used values are kept adjacent for cache effect */ + u32 tx_coal_frames[MTL_MAX_TX_QUEUES]; + u32 tx_coal_timer[MTL_MAX_TX_QUEUES]; +- u32 rx_coal_frames[MTL_MAX_TX_QUEUES]; ++ u32 rx_coal_frames[MTL_MAX_RX_QUEUES]; + + int hwts_tx_en; + bool tx_path_in_lpi_mode; +@@ -265,8 +265,7 @@ struct stmmac_priv { + int sph; + int sph_cap; + u32 sarc_type; +- +- u32 rx_riwt[MTL_MAX_TX_QUEUES]; ++ u32 rx_riwt[MTL_MAX_RX_QUEUES]; + int hwts_rx_en; + + void __iomem *ioaddr; +@@ -343,7 +342,7 @@ struct stmmac_priv { + char int_name_sfty[IFNAMSIZ + 10]; + char int_name_sfty_ce[IFNAMSIZ + 10]; + char int_name_sfty_ue[IFNAMSIZ + 10]; +- char int_name_rx_irq[MTL_MAX_TX_QUEUES][IFNAMSIZ + 14]; ++ char int_name_rx_irq[MTL_MAX_RX_QUEUES][IFNAMSIZ + 14]; + char int_name_tx_irq[MTL_MAX_TX_QUEUES][IFNAMSIZ + 18]; + + #ifdef CONFIG_DEBUG_FS +-- +2.39.5 + diff --git a/queue-6.14/net-stmmac-dwmac-loongson-set-correct-tx-rx-_fifo_si.patch b/queue-6.14/net-stmmac-dwmac-loongson-set-correct-tx-rx-_fifo_si.patch new file mode 100644 index 0000000000..b97166123f --- /dev/null +++ b/queue-6.14/net-stmmac-dwmac-loongson-set-correct-tx-rx-_fifo_si.patch @@ -0,0 +1,52 @@ +From 3ab4f7a18b95085c7dfcd17f11867332fd3e768c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 10 Feb 2025 21:43:28 +0800 +Subject: net: stmmac: dwmac-loongson: Set correct {tx,rx}_fifo_size + +From: Huacai Chen + +[ Upstream commit 8dbf0c7556454b52af91bae305ca71500c31495c ] + +Now for dwmac-loongson {tx,rx}_fifo_size are uninitialised, which means +zero. This means dwmac-loongson doesn't support changing MTU because in +stmmac_change_mtu() it requires the fifo size be no less than MTU. Thus, +set the correct tx_fifo_size and rx_fifo_size for it (16KB multiplied by +queue counts). + +Here {tx,rx}_fifo_size is initialised with the initial value (also the +maximum value) of {tx,rx}_queues_to_use. So it will keep as 16KB if we +don't change the queue count, and will be larger than 16KB if we change +(decrease) the queue count. However stmmac_change_mtu() still work well +with current logic (MTU cannot be larger than 16KB for stmmac). + +Note: the Fixes tag picked here is the oldest commit and key commit of +the dwmac-loongson series "stmmac: Add Loongson platform support". + +Acked-by: Yanteng Si +Reviewed-by: Simon Horman +Signed-off-by: Chong Qiao +Signed-off-by: Huacai Chen +Link: https://patch.msgid.link/20250210134328.2755328-1-chenhuacai@loongson.cn +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c +index ab7c2750c1042..702ea5a00b56d 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c ++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c +@@ -590,6 +590,9 @@ static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id + if (ret) + goto err_disable_device; + ++ plat->tx_fifo_size = SZ_16K * plat->tx_queues_to_use; ++ plat->rx_fifo_size = SZ_16K * plat->rx_queues_to_use; ++ + if (dev_of_node(&pdev->dev)) + ret = loongson_dwmac_dt_config(pdev, plat, &res); + else +-- +2.39.5 + diff --git a/queue-6.14/net-stmmac-dwmac-rk-validate-grf-and-peripheral-grf-.patch b/queue-6.14/net-stmmac-dwmac-rk-validate-grf-and-peripheral-grf-.patch new file mode 100644 index 0000000000..86c42cc427 --- /dev/null +++ b/queue-6.14/net-stmmac-dwmac-rk-validate-grf-and-peripheral-grf-.patch @@ -0,0 +1,91 @@ +From 545dbeee5fc5d5c812a5c3511b979cade807e337 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 8 Mar 2025 21:37:14 +0000 +Subject: net: stmmac: dwmac-rk: Validate GRF and peripheral GRF during probe + +From: Jonas Karlman + +[ Upstream commit 247e84f66a3d1946193d739fec5dc3d69833fd00 ] + +All Rockchip GMAC variants typically write to GRF regs to control e.g. +interface mode, speed and MAC rx/tx delay. Newer SoCs such as RK3576 and +RK3588 use a mix of GRF and peripheral GRF regs. These syscon regmaps is +located with help of a rockchip,grf and rockchip,php-grf phandle. + +However, validating the rockchip,grf and rockchip,php-grf syscon regmap +is deferred until e.g. interface mode or speed is configured, inside the +individual SoC specific operations. + +Change to validate the rockchip,grf and rockchip,php-grf syscon regmap +at probe time to simplify all SoC specific operations. + +This should not introduce any backward compatibility issues as all +GMAC nodes have been added together with a rockchip,grf phandle (and +rockchip,php-grf where required) in their initial commit. + +Signed-off-by: Jonas Karlman +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20250308213720.2517944-3-jonas@kwiboo.se +Reviewed-by: Sebastian Reichel +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + .../net/ethernet/stmicro/stmmac/dwmac-rk.c | 21 +++++++++++++++++-- + 1 file changed, 19 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c +index a4dc89e23a68e..a33be23121b35 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c ++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c +@@ -33,6 +33,7 @@ struct rk_gmac_ops { + void (*set_clock_selection)(struct rk_priv_data *bsp_priv, bool input, + bool enable); + void (*integrated_phy_powerup)(struct rk_priv_data *bsp_priv); ++ bool php_grf_required; + bool regs_valid; + u32 regs[]; + }; +@@ -1254,6 +1255,7 @@ static const struct rk_gmac_ops rk3576_ops = { + .set_rgmii_speed = rk3576_set_gmac_speed, + .set_rmii_speed = rk3576_set_gmac_speed, + .set_clock_selection = rk3576_set_clock_selection, ++ .php_grf_required = true, + .regs_valid = true, + .regs = { + 0x2a220000, /* gmac0 */ +@@ -1401,6 +1403,7 @@ static const struct rk_gmac_ops rk3588_ops = { + .set_rgmii_speed = rk3588_set_gmac_speed, + .set_rmii_speed = rk3588_set_gmac_speed, + .set_clock_selection = rk3588_set_clock_selection, ++ .php_grf_required = true, + .regs_valid = true, + .regs = { + 0xfe1b0000, /* gmac0 */ +@@ -1812,8 +1815,22 @@ static struct rk_priv_data *rk_gmac_setup(struct platform_device *pdev, + + bsp_priv->grf = syscon_regmap_lookup_by_phandle(dev->of_node, + "rockchip,grf"); +- bsp_priv->php_grf = syscon_regmap_lookup_by_phandle(dev->of_node, +- "rockchip,php-grf"); ++ if (IS_ERR(bsp_priv->grf)) { ++ dev_err_probe(dev, PTR_ERR(bsp_priv->grf), ++ "failed to lookup rockchip,grf\n"); ++ return ERR_CAST(bsp_priv->grf); ++ } ++ ++ if (ops->php_grf_required) { ++ bsp_priv->php_grf = ++ syscon_regmap_lookup_by_phandle(dev->of_node, ++ "rockchip,php-grf"); ++ if (IS_ERR(bsp_priv->php_grf)) { ++ dev_err_probe(dev, PTR_ERR(bsp_priv->php_grf), ++ "failed to lookup rockchip,php-grf\n"); ++ return ERR_CAST(bsp_priv->php_grf); ++ } ++ } + + if (plat->phy_node) { + bsp_priv->integrated_phy = of_property_read_bool(plat->phy_node, +-- +2.39.5 + diff --git a/queue-6.14/net-sysfs-restore-behavior-for-not-running-devices.patch b/queue-6.14/net-sysfs-restore-behavior-for-not-running-devices.patch new file mode 100644 index 0000000000..232b0b76b6 --- /dev/null +++ b/queue-6.14/net-sysfs-restore-behavior-for-not-running-devices.patch @@ -0,0 +1,72 @@ +From 66ff3b0a7b7c1cf9093d438345d826304a6bdab3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 21 Feb 2025 05:12:23 +0000 +Subject: net-sysfs: restore behavior for not running devices + +From: Eric Dumazet + +[ Upstream commit 75bc3dab4e49b4daccb27ad6ce8ce2fcd253fc1b ] + +modprobe dummy dumdummies=1 + +Old behavior : + +$ cat /sys/class/net/dummy0/carrier +cat: /sys/class/net/dummy0/carrier: Invalid argument + +After blamed commit, an empty string is reported. + +$ cat /sys/class/net/dummy0/carrier +$ + +In this commit, I restore the old behavior for carrier, +speed and duplex attributes. + +Fixes: 79c61899b5ee ("net-sysfs: remove rtnl_trylock from device attributes") +Signed-off-by: Eric Dumazet +Reported-by: Marco Leogrande +Reviewed-by: Antoine Tenart +Link: https://patch.msgid.link/20250221051223.576726-1-edumazet@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/core/net-sysfs.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c +index 07cb99b114bdd..88e001a4e0810 100644 +--- a/net/core/net-sysfs.c ++++ b/net/core/net-sysfs.c +@@ -232,11 +232,12 @@ static ssize_t carrier_show(struct device *dev, + struct device_attribute *attr, char *buf) + { + struct net_device *netdev = to_net_dev(dev); +- int ret = -EINVAL; ++ int ret; + + if (!rtnl_trylock()) + return restart_syscall(); + ++ ret = -EINVAL; + if (netif_running(netdev)) { + /* Synchronize carrier state with link watch, + * see also rtnl_getlink(). +@@ -266,6 +267,7 @@ static ssize_t speed_show(struct device *dev, + if (!rtnl_trylock()) + return restart_syscall(); + ++ ret = -EINVAL; + if (netif_running(netdev)) { + struct ethtool_link_ksettings cmd; + +@@ -292,6 +294,7 @@ static ssize_t duplex_show(struct device *dev, + if (!rtnl_trylock()) + return restart_syscall(); + ++ ret = -EINVAL; + if (netif_running(netdev)) { + struct ethtool_link_ksettings cmd; + +-- +2.39.5 + diff --git a/queue-6.14/net-tn40xx-add-pci-id-of-the-aqr105-based-tehuti-tn4.patch b/queue-6.14/net-tn40xx-add-pci-id-of-the-aqr105-based-tehuti-tn4.patch new file mode 100644 index 0000000000..f247cabf7e --- /dev/null +++ b/queue-6.14/net-tn40xx-add-pci-id-of-the-aqr105-based-tehuti-tn4.patch @@ -0,0 +1,43 @@ +From a0eac8e8be4ffe356c41818185280ba493862429 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 22 Mar 2025 11:45:58 +0100 +Subject: net: tn40xx: add pci-id of the aqr105-based Tehuti TN4010 cards + +From: Hans-Frieder Vogt + +[ Upstream commit 53377b5c2952097527b01ce2f1d9a9332f042f70 ] + +Add the PCI-ID of the AQR105-based Tehuti TN4010 cards to allow loading +of the tn40xx driver on these cards. Here, I chose the detailed definition +with the subvendor ID similar to the QT2025 cards with the PCI-ID +TEHUTI:0x4022, because there is a card with an AQ2104 hiding amongst the +AQR105 cards, and they all come with the same PCI-ID (TEHUTI:0x4025). But +the AQ2104 is currently not supported. + +Signed-off-by: Hans-Frieder Vogt +Reviewed-by: Andrew Lunn +Link: https://patch.msgid.link/20250322-tn9510-v3a-v7-7-672a9a3d8628@gmx.net +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/tehuti/tn40.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/drivers/net/ethernet/tehuti/tn40.c b/drivers/net/ethernet/tehuti/tn40.c +index 259bdac24cf21..a6965258441c4 100644 +--- a/drivers/net/ethernet/tehuti/tn40.c ++++ b/drivers/net/ethernet/tehuti/tn40.c +@@ -1832,6 +1832,10 @@ static const struct pci_device_id tn40_id_table[] = { + PCI_VENDOR_ID_ASUSTEK, 0x8709) }, + { PCI_DEVICE_SUB(PCI_VENDOR_ID_TEHUTI, 0x4022, + PCI_VENDOR_ID_EDIMAX, 0x8103) }, ++ { PCI_DEVICE_SUB(PCI_VENDOR_ID_TEHUTI, PCI_DEVICE_ID_TEHUTI_TN9510, ++ PCI_VENDOR_ID_TEHUTI, 0x3015) }, ++ { PCI_DEVICE_SUB(PCI_VENDOR_ID_TEHUTI, PCI_DEVICE_ID_TEHUTI_TN9510, ++ PCI_VENDOR_ID_EDIMAX, 0x8102) }, + { } + }; + +-- +2.39.5 + diff --git a/queue-6.14/net-tn40xx-create-swnode-for-mdio-and-aqr105-phy-and.patch b/queue-6.14/net-tn40xx-create-swnode-for-mdio-and-aqr105-phy-and.patch new file mode 100644 index 0000000000..b381ab78a5 --- /dev/null +++ b/queue-6.14/net-tn40xx-create-swnode-for-mdio-and-aqr105-phy-and.patch @@ -0,0 +1,240 @@ +From 7e32147f0508f30b1f90514151d0136c38d39cd7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 22 Mar 2025 11:45:56 +0100 +Subject: net: tn40xx: create swnode for mdio and aqr105 phy and add to mdiobus + +From: Hans-Frieder Vogt + +[ Upstream commit 25b6a6d29d4082f6ac231c056ac321a996eb55c9 ] + +In case of an AQR105-based device, create a software node for the mdio +function, with a child node for the Aquantia AQR105 PHY, providing a +firmware-name (and a bit more, which may be used for future checks) to +allow the PHY to load a MAC specific firmware from the file system. + +The name of the PHY software node follows the naming convention suggested +in the patch for the mdiobus_scan function (in the same patch series). + +Signed-off-by: Hans-Frieder Vogt +Reviewed-by: Andrew Lunn +Link: https://patch.msgid.link/20250322-tn9510-v3a-v7-5-672a9a3d8628@gmx.net +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/tehuti/tn40.c | 5 +- + drivers/net/ethernet/tehuti/tn40.h | 33 ++++++++++ + drivers/net/ethernet/tehuti/tn40_mdio.c | 82 ++++++++++++++++++++++++- + 3 files changed, 117 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/ethernet/tehuti/tn40.c b/drivers/net/ethernet/tehuti/tn40.c +index a6965258441c4..558b791a97edd 100644 +--- a/drivers/net/ethernet/tehuti/tn40.c ++++ b/drivers/net/ethernet/tehuti/tn40.c +@@ -1778,7 +1778,7 @@ static int tn40_probe(struct pci_dev *pdev, const struct pci_device_id *ent) + ret = tn40_phy_register(priv); + if (ret) { + dev_err(&pdev->dev, "failed to set up PHY.\n"); +- goto err_free_irq; ++ goto err_cleanup_swnodes; + } + + ret = tn40_priv_init(priv); +@@ -1795,6 +1795,8 @@ static int tn40_probe(struct pci_dev *pdev, const struct pci_device_id *ent) + return 0; + err_unregister_phydev: + tn40_phy_unregister(priv); ++err_cleanup_swnodes: ++ tn40_swnodes_cleanup(priv); + err_free_irq: + pci_free_irq_vectors(pdev); + err_unset_drvdata: +@@ -1816,6 +1818,7 @@ static void tn40_remove(struct pci_dev *pdev) + unregister_netdev(ndev); + + tn40_phy_unregister(priv); ++ tn40_swnodes_cleanup(priv); + pci_free_irq_vectors(priv->pdev); + pci_set_drvdata(pdev, NULL); + iounmap(priv->regs); +diff --git a/drivers/net/ethernet/tehuti/tn40.h b/drivers/net/ethernet/tehuti/tn40.h +index 490781fe51205..25da8686d4691 100644 +--- a/drivers/net/ethernet/tehuti/tn40.h ++++ b/drivers/net/ethernet/tehuti/tn40.h +@@ -4,10 +4,13 @@ + #ifndef _TN40_H_ + #define _TN40_H_ + ++#include + #include "tn40_regs.h" + + #define TN40_DRV_NAME "tn40xx" + ++#define PCI_DEVICE_ID_TEHUTI_TN9510 0x4025 ++ + #define TN40_MDIO_SPEED_1MHZ (1) + #define TN40_MDIO_SPEED_6MHZ (6) + +@@ -102,10 +105,39 @@ struct tn40_txdb { + int size; /* Number of elements in the db */ + }; + ++#define NODE_PROP(_NAME, _PROP) ( \ ++ (const struct software_node) { \ ++ .name = _NAME, \ ++ .properties = _PROP, \ ++ }) ++ ++#define NODE_PAR_PROP(_NAME, _PAR, _PROP) ( \ ++ (const struct software_node) { \ ++ .name = _NAME, \ ++ .parent = _PAR, \ ++ .properties = _PROP, \ ++ }) ++ ++enum tn40_swnodes { ++ SWNODE_MDIO, ++ SWNODE_PHY, ++ SWNODE_MAX ++}; ++ ++struct tn40_nodes { ++ char phy_name[32]; ++ char mdio_name[32]; ++ struct property_entry phy_props[3]; ++ struct software_node swnodes[SWNODE_MAX]; ++ const struct software_node *group[SWNODE_MAX + 1]; ++}; ++ + struct tn40_priv { + struct net_device *ndev; + struct pci_dev *pdev; + ++ struct tn40_nodes nodes; ++ + struct napi_struct napi; + /* RX FIFOs: 1 for data (full) descs, and 2 for free descs */ + struct tn40_rxd_fifo rxd_fifo0; +@@ -225,6 +257,7 @@ static inline void tn40_write_reg(struct tn40_priv *priv, u32 reg, u32 val) + + int tn40_set_link_speed(struct tn40_priv *priv, u32 speed); + ++void tn40_swnodes_cleanup(struct tn40_priv *priv); + int tn40_mdiobus_init(struct tn40_priv *priv); + + int tn40_phy_register(struct tn40_priv *priv); +diff --git a/drivers/net/ethernet/tehuti/tn40_mdio.c b/drivers/net/ethernet/tehuti/tn40_mdio.c +index af18615d64a8a..5bb0cbc87d064 100644 +--- a/drivers/net/ethernet/tehuti/tn40_mdio.c ++++ b/drivers/net/ethernet/tehuti/tn40_mdio.c +@@ -14,6 +14,8 @@ + (FIELD_PREP(TN40_MDIO_PRTAD_MASK, (port)))) + #define TN40_MDIO_CMD_READ BIT(15) + ++#define AQR105_FIRMWARE "tehuti/aqr105-tn40xx.cld" ++ + static void tn40_mdio_set_speed(struct tn40_priv *priv, u32 speed) + { + void __iomem *regs = priv->regs; +@@ -111,6 +113,56 @@ static int tn40_mdio_write_c45(struct mii_bus *mii_bus, int addr, int devnum, + return tn40_mdio_write(mii_bus->priv, addr, devnum, regnum, val); + } + ++/* registers an mdio node and an aqr105 PHY at address 1 ++ * tn40_mdio-%id { ++ * ethernet-phy@1 { ++ * compatible = "ethernet-phy-id03a1.b4a3"; ++ * reg = <1>; ++ * firmware-name = AQR105_FIRMWARE; ++ * }; ++ * }; ++ */ ++static int tn40_swnodes_register(struct tn40_priv *priv) ++{ ++ struct tn40_nodes *nodes = &priv->nodes; ++ struct pci_dev *pdev = priv->pdev; ++ struct software_node *swnodes; ++ u32 id; ++ ++ id = pci_dev_id(pdev); ++ ++ snprintf(nodes->phy_name, sizeof(nodes->phy_name), "ethernet-phy@1"); ++ snprintf(nodes->mdio_name, sizeof(nodes->mdio_name), "tn40_mdio-%x", ++ id); ++ ++ swnodes = nodes->swnodes; ++ ++ swnodes[SWNODE_MDIO] = NODE_PROP(nodes->mdio_name, NULL); ++ ++ nodes->phy_props[0] = PROPERTY_ENTRY_STRING("compatible", ++ "ethernet-phy-id03a1.b4a3"); ++ nodes->phy_props[1] = PROPERTY_ENTRY_U32("reg", 1); ++ nodes->phy_props[2] = PROPERTY_ENTRY_STRING("firmware-name", ++ AQR105_FIRMWARE); ++ swnodes[SWNODE_PHY] = NODE_PAR_PROP(nodes->phy_name, ++ &swnodes[SWNODE_MDIO], ++ nodes->phy_props); ++ ++ nodes->group[SWNODE_PHY] = &swnodes[SWNODE_PHY]; ++ nodes->group[SWNODE_MDIO] = &swnodes[SWNODE_MDIO]; ++ return software_node_register_node_group(nodes->group); ++} ++ ++void tn40_swnodes_cleanup(struct tn40_priv *priv) ++{ ++ /* cleanup of swnodes is only needed for AQR105-based cards */ ++ if (priv->pdev->device == PCI_DEVICE_ID_TEHUTI_TN9510) { ++ fwnode_handle_put(dev_fwnode(&priv->mdio->dev)); ++ device_remove_software_node(&priv->mdio->dev); ++ software_node_unregister_node_group(priv->nodes.group); ++ } ++} ++ + int tn40_mdiobus_init(struct tn40_priv *priv) + { + struct pci_dev *pdev = priv->pdev; +@@ -129,14 +181,40 @@ int tn40_mdiobus_init(struct tn40_priv *priv) + + bus->read_c45 = tn40_mdio_read_c45; + bus->write_c45 = tn40_mdio_write_c45; ++ priv->mdio = bus; ++ ++ /* provide swnodes for AQR105-based cards only */ ++ if (pdev->device == PCI_DEVICE_ID_TEHUTI_TN9510) { ++ ret = tn40_swnodes_register(priv); ++ if (ret) { ++ pr_err("swnodes failed\n"); ++ return ret; ++ } ++ ++ ret = device_add_software_node(&bus->dev, ++ priv->nodes.group[SWNODE_MDIO]); ++ if (ret) { ++ dev_err(&pdev->dev, ++ "device_add_software_node failed: %d\n", ret); ++ goto err_swnodes_unregister; ++ } ++ } + + ret = devm_mdiobus_register(&pdev->dev, bus); + if (ret) { + dev_err(&pdev->dev, "failed to register mdiobus %d %u %u\n", + ret, bus->state, MDIOBUS_UNREGISTERED); +- return ret; ++ goto err_swnodes_cleanup; + } + tn40_mdio_set_speed(priv, TN40_MDIO_SPEED_6MHZ); +- priv->mdio = bus; + return 0; ++ ++err_swnodes_unregister: ++ software_node_unregister_node_group(priv->nodes.group); ++ return ret; ++err_swnodes_cleanup: ++ tn40_swnodes_cleanup(priv); ++ return ret; + } ++ ++MODULE_FIRMWARE(AQR105_FIRMWARE); +-- +2.39.5 + diff --git a/queue-6.14/net-xgene-v2-remove-incorrect-acpi_ptr-annotation.patch b/queue-6.14/net-xgene-v2-remove-incorrect-acpi_ptr-annotation.patch new file mode 100644 index 0000000000..46a9bdeb1b --- /dev/null +++ b/queue-6.14/net-xgene-v2-remove-incorrect-acpi_ptr-annotation.patch @@ -0,0 +1,47 @@ +From c9c4a0380f0f18dfda0f106df68b63409d3c1fc8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 25 Feb 2025 17:33:33 +0100 +Subject: net: xgene-v2: remove incorrect ACPI_PTR annotation + +From: Arnd Bergmann + +[ Upstream commit 01358e8fe922f716c05d7864ac2213b2440026e7 ] + +Building with W=1 shows a warning about xge_acpi_match being unused when +CONFIG_ACPI is disabled: + +drivers/net/ethernet/apm/xgene-v2/main.c:723:36: error: unused variable 'xge_acpi_match' [-Werror,-Wunused-const-variable] + +Signed-off-by: Arnd Bergmann +Link: https://patch.msgid.link/20250225163341.4168238-2-arnd@kernel.org +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/apm/xgene-v2/main.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +diff --git a/drivers/net/ethernet/apm/xgene-v2/main.c b/drivers/net/ethernet/apm/xgene-v2/main.c +index 2a91c84aebdb0..d7ca847d44c7c 100644 +--- a/drivers/net/ethernet/apm/xgene-v2/main.c ++++ b/drivers/net/ethernet/apm/xgene-v2/main.c +@@ -9,8 +9,6 @@ + + #include "main.h" + +-static const struct acpi_device_id xge_acpi_match[]; +- + static int xge_get_resources(struct xge_pdata *pdata) + { + struct platform_device *pdev; +@@ -731,7 +729,7 @@ MODULE_DEVICE_TABLE(acpi, xge_acpi_match); + static struct platform_driver xge_driver = { + .driver = { + .name = "xgene-enet-v2", +- .acpi_match_table = ACPI_PTR(xge_acpi_match), ++ .acpi_match_table = xge_acpi_match, + }, + .probe = xge_probe, + .remove = xge_remove, +-- +2.39.5 + diff --git a/queue-6.14/netdevsim-allow-normal-queue-reset-while-down.patch b/queue-6.14/netdevsim-allow-normal-queue-reset-while-down.patch new file mode 100644 index 0000000000..9d28b0943d --- /dev/null +++ b/queue-6.14/netdevsim-allow-normal-queue-reset-while-down.patch @@ -0,0 +1,90 @@ +From f6fc83791c2b992379c98c7d18449ffc2361a8d9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Feb 2025 14:56:38 -0800 +Subject: netdevsim: allow normal queue reset while down + +From: Jakub Kicinski + +[ Upstream commit 285b3f78eabd951e59e98f01f86abaaa6c76cd44 ] + +Resetting queues while the device is down should be legal. +Allow it, test it. Ideally we'd test this with a real device +supporting devmem but I don't have access to such devices. + +Reviewed-by: Mina Almasry +Link: https://patch.msgid.link/20250206225638.1387810-5-kuba@kernel.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/netdevsim/netdev.c | 10 ++++------ + tools/testing/selftests/net/nl_netdev.py | 18 +++++++++++++++++- + 2 files changed, 21 insertions(+), 7 deletions(-) + +diff --git a/drivers/net/netdevsim/netdev.c b/drivers/net/netdevsim/netdev.c +index e4c0d77849b82..a41dc79e9c2e0 100644 +--- a/drivers/net/netdevsim/netdev.c ++++ b/drivers/net/netdevsim/netdev.c +@@ -664,8 +664,11 @@ nsim_queue_mem_alloc(struct net_device *dev, void *per_queue_mem, int idx) + if (ns->rq_reset_mode > 3) + return -EINVAL; + +- if (ns->rq_reset_mode == 1) ++ if (ns->rq_reset_mode == 1) { ++ if (!netif_running(ns->netdev)) ++ return -ENETDOWN; + return nsim_create_page_pool(&qmem->pp, &ns->rq[idx]->napi); ++ } + + qmem->rq = nsim_queue_alloc(); + if (!qmem->rq) +@@ -773,11 +776,6 @@ nsim_qreset_write(struct file *file, const char __user *data, + return -EINVAL; + + rtnl_lock(); +- if (!netif_running(ns->netdev)) { +- ret = -ENETDOWN; +- goto exit_unlock; +- } +- + if (queue >= ns->netdev->real_num_rx_queues) { + ret = -EINVAL; + goto exit_unlock; +diff --git a/tools/testing/selftests/net/nl_netdev.py b/tools/testing/selftests/net/nl_netdev.py +index 93e8cb671c3d9..beaee5e4e2aab 100755 +--- a/tools/testing/selftests/net/nl_netdev.py ++++ b/tools/testing/selftests/net/nl_netdev.py +@@ -35,6 +35,21 @@ def napi_list_check(nf) -> None: + comment=f"queue count after reset queue {q} mode {i}") + + ++def nsim_rxq_reset_down(nf) -> None: ++ """ ++ Test that the queue API supports resetting a queue ++ while the interface is down. We should convert this ++ test to testing real HW once more devices support ++ queue API. ++ """ ++ with NetdevSimDev(queue_count=4) as nsimdev: ++ nsim = nsimdev.nsims[0] ++ ++ ip(f"link set dev {nsim.ifname} down") ++ for i in [0, 2, 3]: ++ nsim.dfs_write("queue_reset", f"1 {i}") ++ ++ + def page_pool_check(nf) -> None: + with NetdevSimDev() as nsimdev: + nsim = nsimdev.nsims[0] +@@ -106,7 +121,8 @@ def page_pool_check(nf) -> None: + + def main() -> None: + nf = NetdevFamily() +- ksft_run([empty_check, lo_check, page_pool_check, napi_list_check], ++ ksft_run([empty_check, lo_check, page_pool_check, napi_list_check, ++ nsim_rxq_reset_down], + args=(nf, )) + ksft_exit() + +-- +2.39.5 + diff --git a/queue-6.14/netdevsim-call-napi_schedule-from-a-timer-context.patch b/queue-6.14/netdevsim-call-napi_schedule-from-a-timer-context.patch new file mode 100644 index 0000000000..bce6dff2cc --- /dev/null +++ b/queue-6.14/netdevsim-call-napi_schedule-from-a-timer-context.patch @@ -0,0 +1,98 @@ +From bc86ccb1060c6e2f099354b406e9d492b2300b21 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 19 Feb 2025 08:41:20 -0800 +Subject: netdevsim: call napi_schedule from a timer context + +From: Breno Leitao + +[ Upstream commit bf3624cf1c3708284c53ed99a1c43f2e104dc2dd ] + +The netdevsim driver was experiencing NOHZ tick-stop errors during packet +transmission due to pending softirq work when calling napi_schedule(). +This issue was observed when running the netconsole selftest, which +triggered the following error message: + + NOHZ tick-stop error: local softirq work is pending, handler #08!!! + +To fix this issue, introduce a timer that schedules napi_schedule() +from a timer context instead of calling it directly from the TX path. + +Create an hrtimer for each queue and kick it from the TX path, +which then schedules napi_schedule() from the timer context. + +Suggested-by: Jakub Kicinski +Signed-off-by: Breno Leitao +Link: https://patch.msgid.link/20250219-netdevsim-v3-1-811e2b8abc4c@debian.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/netdevsim/netdev.c | 21 ++++++++++++++++++++- + drivers/net/netdevsim/netdevsim.h | 1 + + 2 files changed, 21 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/netdevsim/netdev.c b/drivers/net/netdevsim/netdev.c +index 42f247cbdceec..e4c0d77849b82 100644 +--- a/drivers/net/netdevsim/netdev.c ++++ b/drivers/net/netdevsim/netdev.c +@@ -87,7 +87,8 @@ static netdev_tx_t nsim_start_xmit(struct sk_buff *skb, struct net_device *dev) + if (unlikely(nsim_forward_skb(peer_dev, skb, rq) == NET_RX_DROP)) + goto out_drop_cnt; + +- napi_schedule(&rq->napi); ++ if (!hrtimer_active(&rq->napi_timer)) ++ hrtimer_start(&rq->napi_timer, us_to_ktime(5), HRTIMER_MODE_REL); + + rcu_read_unlock(); + u64_stats_update_begin(&ns->syncp); +@@ -426,6 +427,22 @@ static int nsim_init_napi(struct netdevsim *ns) + return err; + } + ++static enum hrtimer_restart nsim_napi_schedule(struct hrtimer *timer) ++{ ++ struct nsim_rq *rq; ++ ++ rq = container_of(timer, struct nsim_rq, napi_timer); ++ napi_schedule(&rq->napi); ++ ++ return HRTIMER_NORESTART; ++} ++ ++static void nsim_rq_timer_init(struct nsim_rq *rq) ++{ ++ hrtimer_init(&rq->napi_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); ++ rq->napi_timer.function = nsim_napi_schedule; ++} ++ + static void nsim_enable_napi(struct netdevsim *ns) + { + struct net_device *dev = ns->netdev; +@@ -615,11 +632,13 @@ static struct nsim_rq *nsim_queue_alloc(void) + return NULL; + + skb_queue_head_init(&rq->skb_queue); ++ nsim_rq_timer_init(rq); + return rq; + } + + static void nsim_queue_free(struct nsim_rq *rq) + { ++ hrtimer_cancel(&rq->napi_timer); + skb_queue_purge_reason(&rq->skb_queue, SKB_DROP_REASON_QUEUE_PURGE); + kfree(rq); + } +diff --git a/drivers/net/netdevsim/netdevsim.h b/drivers/net/netdevsim/netdevsim.h +index 96d54c08043d3..e757f85ed8617 100644 +--- a/drivers/net/netdevsim/netdevsim.h ++++ b/drivers/net/netdevsim/netdevsim.h +@@ -97,6 +97,7 @@ struct nsim_rq { + struct napi_struct napi; + struct sk_buff_head skb_queue; + struct page_pool *page_pool; ++ struct hrtimer napi_timer; + }; + + struct netdevsim { +-- +2.39.5 + diff --git a/queue-6.14/netfilter-conntrack-bound-nf_conntrack-sysctl-writes.patch b/queue-6.14/netfilter-conntrack-bound-nf_conntrack-sysctl-writes.patch new file mode 100644 index 0000000000..fd6b23b50c --- /dev/null +++ b/queue-6.14/netfilter-conntrack-bound-nf_conntrack-sysctl-writes.patch @@ -0,0 +1,85 @@ +From 2519fbb3ffa61369fa084c37c49dbe08bd7366fe Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 29 Jan 2025 18:06:30 +0100 +Subject: netfilter: conntrack: Bound nf_conntrack sysctl writes + +From: Nicolas Bouchinet + +[ Upstream commit 8b6861390ffee6b8ed78b9395e3776c16fec6579 ] + +nf_conntrack_max and nf_conntrack_expect_max sysctls were authorized to +be written any negative value, which would then be stored in the +unsigned int variables nf_conntrack_max and nf_ct_expect_max variables. + +While the do_proc_dointvec_conv function is supposed to limit writing +handled by proc_dointvec proc_handler to INT_MAX. Such a negative value +being written in an unsigned int leads to a very high value, exceeding +this limit. + +Moreover, the nf_conntrack_expect_max sysctl documentation specifies the +minimum value is 1. + +The proc_handlers have thus been updated to proc_dointvec_minmax in +order to specify the following write bounds : + +* Bound nf_conntrack_max sysctl writings between SYSCTL_ZERO + and SYSCTL_INT_MAX. + +* Bound nf_conntrack_expect_max sysctl writings between SYSCTL_ONE + and SYSCTL_INT_MAX as defined in the sysctl documentation. + +With this patch applied, sysctl writes outside the defined in the bound +will thus lead to a write error : + +``` +sysctl -w net.netfilter.nf_conntrack_expect_max=-1 +sysctl: setting key "net.netfilter.nf_conntrack_expect_max": Invalid argument +``` + +Signed-off-by: Nicolas Bouchinet +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Sasha Levin +--- + net/netfilter/nf_conntrack_standalone.c | 12 +++++++++--- + 1 file changed, 9 insertions(+), 3 deletions(-) + +diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c +index 502cf10aab41d..2f666751c7e7c 100644 +--- a/net/netfilter/nf_conntrack_standalone.c ++++ b/net/netfilter/nf_conntrack_standalone.c +@@ -618,7 +618,9 @@ static struct ctl_table nf_ct_sysctl_table[] = { + .data = &nf_conntrack_max, + .maxlen = sizeof(int), + .mode = 0644, +- .proc_handler = proc_dointvec, ++ .proc_handler = proc_dointvec_minmax, ++ .extra1 = SYSCTL_ZERO, ++ .extra2 = SYSCTL_INT_MAX, + }, + [NF_SYSCTL_CT_COUNT] = { + .procname = "nf_conntrack_count", +@@ -654,7 +656,9 @@ static struct ctl_table nf_ct_sysctl_table[] = { + .data = &nf_ct_expect_max, + .maxlen = sizeof(int), + .mode = 0644, +- .proc_handler = proc_dointvec, ++ .proc_handler = proc_dointvec_minmax, ++ .extra1 = SYSCTL_ONE, ++ .extra2 = SYSCTL_INT_MAX, + }, + [NF_SYSCTL_CT_ACCT] = { + .procname = "nf_conntrack_acct", +@@ -947,7 +951,9 @@ static struct ctl_table nf_ct_netfilter_table[] = { + .data = &nf_conntrack_max, + .maxlen = sizeof(int), + .mode = 0644, +- .proc_handler = proc_dointvec, ++ .proc_handler = proc_dointvec_minmax, ++ .extra1 = SYSCTL_ZERO, ++ .extra2 = SYSCTL_INT_MAX, + }, + }; + +-- +2.39.5 + diff --git a/queue-6.14/nfs-don-t-allow-waiting-for-exiting-tasks.patch b/queue-6.14/nfs-don-t-allow-waiting-for-exiting-tasks.patch new file mode 100644 index 0000000000..6be95fb2dd --- /dev/null +++ b/queue-6.14/nfs-don-t-allow-waiting-for-exiting-tasks.patch @@ -0,0 +1,108 @@ +From d8b29bfdfb205853a7976e7119f35e60c5fd352a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 28 Mar 2025 13:19:18 -0400 +Subject: NFS: Don't allow waiting for exiting tasks + +From: Trond Myklebust + +[ Upstream commit 8d3ca331026a7f9700d3747eed59a67b8f828cdc ] + +Once a task calls exit_signals() it can no longer be signalled. So do +not allow it to do killable waits. + +Reviewed-by: Jeff Layton +Signed-off-by: Trond Myklebust +Signed-off-by: Sasha Levin +--- + fs/nfs/inode.c | 2 ++ + fs/nfs/internal.h | 5 +++++ + fs/nfs/nfs3proc.c | 2 +- + fs/nfs/nfs4proc.c | 9 +++++++-- + 4 files changed, 15 insertions(+), 3 deletions(-) + +diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c +index 1aa67fca69b2f..119e447758b99 100644 +--- a/fs/nfs/inode.c ++++ b/fs/nfs/inode.c +@@ -74,6 +74,8 @@ nfs_fattr_to_ino_t(struct nfs_fattr *fattr) + + int nfs_wait_bit_killable(struct wait_bit_key *key, int mode) + { ++ if (unlikely(nfs_current_task_exiting())) ++ return -EINTR; + schedule(); + if (signal_pending_state(mode, current)) + return -ERESTARTSYS; +diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h +index 59bb4d0338f39..3cedb7979fcd0 100644 +--- a/fs/nfs/internal.h ++++ b/fs/nfs/internal.h +@@ -905,6 +905,11 @@ static inline u32 nfs_stateid_hash(const nfs4_stateid *stateid) + NFS4_STATEID_OTHER_SIZE); + } + ++static inline bool nfs_current_task_exiting(void) ++{ ++ return (current->flags & PF_EXITING) != 0; ++} ++ + static inline bool nfs_error_is_fatal(int err) + { + switch (err) { +diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c +index 0c3bc98cd999c..c1736dbb92b63 100644 +--- a/fs/nfs/nfs3proc.c ++++ b/fs/nfs/nfs3proc.c +@@ -39,7 +39,7 @@ nfs3_rpc_wrapper(struct rpc_clnt *clnt, struct rpc_message *msg, int flags) + __set_current_state(TASK_KILLABLE|TASK_FREEZABLE_UNSAFE); + schedule_timeout(NFS_JUKEBOX_RETRY_TIME); + res = -ERESTARTSYS; +- } while (!fatal_signal_pending(current)); ++ } while (!fatal_signal_pending(current) && !nfs_current_task_exiting()); + return res; + } + +diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c +index 810cfd9b7e533..cfdbd521fc7b6 100644 +--- a/fs/nfs/nfs4proc.c ++++ b/fs/nfs/nfs4proc.c +@@ -443,6 +443,8 @@ static int nfs4_delay_killable(long *timeout) + { + might_sleep(); + ++ if (unlikely(nfs_current_task_exiting())) ++ return -EINTR; + __set_current_state(TASK_KILLABLE|TASK_FREEZABLE_UNSAFE); + schedule_timeout(nfs4_update_delay(timeout)); + if (!__fatal_signal_pending(current)) +@@ -454,6 +456,8 @@ static int nfs4_delay_interruptible(long *timeout) + { + might_sleep(); + ++ if (unlikely(nfs_current_task_exiting())) ++ return -EINTR; + __set_current_state(TASK_INTERRUPTIBLE|TASK_FREEZABLE_UNSAFE); + schedule_timeout(nfs4_update_delay(timeout)); + if (!signal_pending(current)) +@@ -1774,7 +1778,8 @@ static void nfs_set_open_stateid_locked(struct nfs4_state *state, + rcu_read_unlock(); + trace_nfs4_open_stateid_update_wait(state->inode, stateid, 0); + +- if (!fatal_signal_pending(current)) { ++ if (!fatal_signal_pending(current) && ++ !nfs_current_task_exiting()) { + if (schedule_timeout(5*HZ) == 0) + status = -EAGAIN; + else +@@ -3578,7 +3583,7 @@ static bool nfs4_refresh_open_old_stateid(nfs4_stateid *dst, + write_sequnlock(&state->seqlock); + trace_nfs4_close_stateid_update_wait(state->inode, dst, 0); + +- if (fatal_signal_pending(current)) ++ if (fatal_signal_pending(current) || nfs_current_task_exiting()) + status = -EINTR; + else + if (schedule_timeout(5*HZ) != 0) +-- +2.39.5 + diff --git a/queue-6.14/nfsv4-check-for-delegation-validity-in-nfs_start_del.patch b/queue-6.14/nfsv4-check-for-delegation-validity-in-nfs_start_del.patch new file mode 100644 index 0000000000..6ba09b1024 --- /dev/null +++ b/queue-6.14/nfsv4-check-for-delegation-validity-in-nfs_start_del.patch @@ -0,0 +1,36 @@ +From fc00ea48a17838d3642bb05832f3750b65857e27 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 27 Mar 2025 19:20:53 -0400 +Subject: NFSv4: Check for delegation validity in + nfs_start_delegation_return_locked() + +From: Trond Myklebust + +[ Upstream commit 9e8f324bd44c1fe026b582b75213de4eccfa1163 ] + +Check that the delegation is still attached after taking the spin lock +in nfs_start_delegation_return_locked(). + +Signed-off-by: Trond Myklebust +Signed-off-by: Sasha Levin +--- + fs/nfs/delegation.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c +index 325ba0663a6de..8bdbc4dca89ca 100644 +--- a/fs/nfs/delegation.c ++++ b/fs/nfs/delegation.c +@@ -307,7 +307,8 @@ nfs_start_delegation_return_locked(struct nfs_inode *nfsi) + if (delegation == NULL) + goto out; + spin_lock(&delegation->lock); +- if (!test_and_set_bit(NFS_DELEGATION_RETURNING, &delegation->flags)) { ++ if (delegation->inode && ++ !test_and_set_bit(NFS_DELEGATION_RETURNING, &delegation->flags)) { + clear_bit(NFS_DELEGATION_RETURN_DELAYED, &delegation->flags); + /* Refcount matched in nfs_end_delegation_return() */ + ret = nfs_get_delegation(delegation); +-- +2.39.5 + diff --git a/queue-6.14/nfsv4-treat-enetunreach-errors-as-fatal-for-state-re.patch b/queue-6.14/nfsv4-treat-enetunreach-errors-as-fatal-for-state-re.patch new file mode 100644 index 0000000000..ab21ba326b --- /dev/null +++ b/queue-6.14/nfsv4-treat-enetunreach-errors-as-fatal-for-state-re.patch @@ -0,0 +1,46 @@ +From fb8c3e11e202e7b62b58de206321f1e778857f49 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 24 Mar 2025 20:35:33 -0400 +Subject: NFSv4: Treat ENETUNREACH errors as fatal for state recovery + +From: Trond Myklebust + +[ Upstream commit 0af5fb5ed3d2fd9e110c6112271f022b744a849a ] + +If a containerised process is killed and causes an ENETUNREACH or +ENETDOWN error to be propagated to the state manager, then mark the +nfs_client as being dead so that we don't loop in functions that are +expecting recovery to succeed. + +Reviewed-by: Jeff Layton +Reviewed-by: Benjamin Coddington +Signed-off-by: Trond Myklebust +Signed-off-by: Sasha Levin +--- + fs/nfs/nfs4state.c | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) + +diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c +index 542cdf71229fe..04c726cc2900b 100644 +--- a/fs/nfs/nfs4state.c ++++ b/fs/nfs/nfs4state.c +@@ -2739,7 +2739,15 @@ static void nfs4_state_manager(struct nfs_client *clp) + pr_warn_ratelimited("NFS: state manager%s%s failed on NFSv4 server %s" + " with error %d\n", section_sep, section, + clp->cl_hostname, -status); +- ssleep(1); ++ switch (status) { ++ case -ENETDOWN: ++ case -ENETUNREACH: ++ nfs_mark_client_ready(clp, -EIO); ++ break; ++ default: ++ ssleep(1); ++ break; ++ } + out_drain: + memalloc_nofs_restore(memflags); + nfs4_end_drain_session(clp); +-- +2.39.5 + diff --git a/queue-6.14/null_blk-generate-null_blk-configfs-features-string.patch b/queue-6.14/null_blk-generate-null_blk-configfs-features-string.patch new file mode 100644 index 0000000000..b193ec22aa --- /dev/null +++ b/queue-6.14/null_blk-generate-null_blk-configfs-features-string.patch @@ -0,0 +1,151 @@ +From 870c1a026c6be100cb616275fac6fa23e7816eb3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 26 Feb 2025 19:06:09 +0900 +Subject: null_blk: generate null_blk configfs features string + +From: Shin'ichiro Kawasaki + +[ Upstream commit 2cadb8ef25a6157b5bd3e8fe0d3e23f32defec25 ] + +The null_blk configfs file 'features' provides a string that lists +available null_blk features for userspace programs to reference. +The string is defined as a long constant in the code, which tends to be +forgotten for updates. It also causes checkpatch.pl to report +"WARNING: quoted string split across lines". + +To avoid these drawbacks, generate the feature string on the fly. Refer +to the ca_name field of each element in the nullb_device_attrs table and +concatenate them in the given buffer. Also, sorted nullb_device_attrs +table elements in alphabetical order. + +Of note is that the feature "index" was missing before this commit. +This commit adds it to the generated string. + +Suggested-by: Bart Van Assche +Reviewed-by: Bart Van Assche +Reviewed-by: Damien Le Moal +Reviewed-by: Chaitanya Kulkarni +Reviewed-by: Johannes Thumshirn +Signed-off-by: Shin'ichiro Kawasaki +Link: https://lore.kernel.org/r/20250226100613.1622564-2-shinichiro.kawasaki@wdc.com +Signed-off-by: Jens Axboe +Signed-off-by: Sasha Levin +--- + drivers/block/null_blk/main.c | 86 ++++++++++++++++++++--------------- + 1 file changed, 49 insertions(+), 37 deletions(-) + +diff --git a/drivers/block/null_blk/main.c b/drivers/block/null_blk/main.c +index 175566a71bb3f..41c2cd5818b4a 100644 +--- a/drivers/block/null_blk/main.c ++++ b/drivers/block/null_blk/main.c +@@ -592,41 +592,41 @@ static ssize_t nullb_device_zone_offline_store(struct config_item *item, + CONFIGFS_ATTR_WO(nullb_device_, zone_offline); + + static struct configfs_attribute *nullb_device_attrs[] = { +- &nullb_device_attr_size, ++ &nullb_device_attr_badblocks, ++ &nullb_device_attr_blocking, ++ &nullb_device_attr_blocksize, ++ &nullb_device_attr_cache_size, + &nullb_device_attr_completion_nsec, +- &nullb_device_attr_submit_queues, +- &nullb_device_attr_poll_queues, ++ &nullb_device_attr_discard, ++ &nullb_device_attr_fua, + &nullb_device_attr_home_node, +- &nullb_device_attr_queue_mode, +- &nullb_device_attr_blocksize, +- &nullb_device_attr_max_sectors, +- &nullb_device_attr_irqmode, + &nullb_device_attr_hw_queue_depth, + &nullb_device_attr_index, +- &nullb_device_attr_blocking, +- &nullb_device_attr_use_per_node_hctx, +- &nullb_device_attr_power, +- &nullb_device_attr_memory_backed, +- &nullb_device_attr_discard, ++ &nullb_device_attr_irqmode, ++ &nullb_device_attr_max_sectors, + &nullb_device_attr_mbps, +- &nullb_device_attr_cache_size, +- &nullb_device_attr_badblocks, +- &nullb_device_attr_zoned, +- &nullb_device_attr_zone_size, ++ &nullb_device_attr_memory_backed, ++ &nullb_device_attr_no_sched, ++ &nullb_device_attr_poll_queues, ++ &nullb_device_attr_power, ++ &nullb_device_attr_queue_mode, ++ &nullb_device_attr_rotational, ++ &nullb_device_attr_shared_tag_bitmap, ++ &nullb_device_attr_shared_tags, ++ &nullb_device_attr_size, ++ &nullb_device_attr_submit_queues, ++ &nullb_device_attr_use_per_node_hctx, ++ &nullb_device_attr_virt_boundary, ++ &nullb_device_attr_zone_append_max_sectors, + &nullb_device_attr_zone_capacity, +- &nullb_device_attr_zone_nr_conv, +- &nullb_device_attr_zone_max_open, ++ &nullb_device_attr_zone_full, + &nullb_device_attr_zone_max_active, +- &nullb_device_attr_zone_append_max_sectors, +- &nullb_device_attr_zone_readonly, ++ &nullb_device_attr_zone_max_open, ++ &nullb_device_attr_zone_nr_conv, + &nullb_device_attr_zone_offline, +- &nullb_device_attr_zone_full, +- &nullb_device_attr_virt_boundary, +- &nullb_device_attr_no_sched, +- &nullb_device_attr_shared_tags, +- &nullb_device_attr_shared_tag_bitmap, +- &nullb_device_attr_fua, +- &nullb_device_attr_rotational, ++ &nullb_device_attr_zone_readonly, ++ &nullb_device_attr_zone_size, ++ &nullb_device_attr_zoned, + NULL, + }; + +@@ -704,16 +704,28 @@ nullb_group_drop_item(struct config_group *group, struct config_item *item) + + static ssize_t memb_group_features_show(struct config_item *item, char *page) + { +- return snprintf(page, PAGE_SIZE, +- "badblocks,blocking,blocksize,cache_size,fua," +- "completion_nsec,discard,home_node,hw_queue_depth," +- "irqmode,max_sectors,mbps,memory_backed,no_sched," +- "poll_queues,power,queue_mode,shared_tag_bitmap," +- "shared_tags,size,submit_queues,use_per_node_hctx," +- "virt_boundary,zoned,zone_capacity,zone_max_active," +- "zone_max_open,zone_nr_conv,zone_offline,zone_readonly," +- "zone_size,zone_append_max_sectors,zone_full," +- "rotational\n"); ++ ++ struct configfs_attribute **entry; ++ char delimiter = ','; ++ size_t left = PAGE_SIZE; ++ size_t written = 0; ++ int ret; ++ ++ for (entry = &nullb_device_attrs[0]; *entry && left > 0; entry++) { ++ if (!*(entry + 1)) ++ delimiter = '\n'; ++ ret = snprintf(page + written, left, "%s%c", (*entry)->ca_name, ++ delimiter); ++ if (ret >= left) { ++ WARN_ONCE(1, "Too many null_blk features to print\n"); ++ memzero_explicit(page, PAGE_SIZE); ++ return -ENOBUFS; ++ } ++ left -= ret; ++ written += ret; ++ } ++ ++ return written; + } + + CONFIGFS_ATTR_RO(memb_group_, features); +-- +2.39.5 + diff --git a/queue-6.14/nvme-map-uring_cmd-data-even-if-address-is-0.patch b/queue-6.14/nvme-map-uring_cmd-data-even-if-address-is-0.patch new file mode 100644 index 0000000000..722bee7706 --- /dev/null +++ b/queue-6.14/nvme-map-uring_cmd-data-even-if-address-is-0.patch @@ -0,0 +1,48 @@ +From f2bb98e26000a4275706bb5c26b02be15ae41e5f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 27 Feb 2025 14:39:13 -0800 +Subject: nvme: map uring_cmd data even if address is 0 + +From: Xinyu Zhang + +[ Upstream commit 99fde895ff56ac2241e7b7b4566731d72f2fdaa7 ] + +When using kernel registered bvec fixed buffers, the "address" is +actually the offset into the bvec rather than userspace address. +Therefore it can be 0. + +We can skip checking whether the address is NULL before mapping +uring_cmd data. Bad userspace address will be handled properly later when +the user buffer is imported. + +With this patch, we will be able to use the kernel registered bvec fixed +buffers in io_uring NVMe passthru with ublk zero-copy support. + +Reviewed-by: Caleb Sander Mateos +Reviewed-by: Jens Axboe +Reviewed-by: Ming Lei +Signed-off-by: Xinyu Zhang +Signed-off-by: Keith Busch +Link: https://lore.kernel.org/r/20250227223916.143006-4-kbusch@meta.com +Signed-off-by: Jens Axboe +Signed-off-by: Sasha Levin +--- + drivers/nvme/host/ioctl.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/nvme/host/ioctl.c b/drivers/nvme/host/ioctl.c +index fed6b29098ad3..11509ffd28fb5 100644 +--- a/drivers/nvme/host/ioctl.c ++++ b/drivers/nvme/host/ioctl.c +@@ -514,7 +514,7 @@ static int nvme_uring_cmd_io(struct nvme_ctrl *ctrl, struct nvme_ns *ns, + return PTR_ERR(req); + req->timeout = d.timeout_ms ? msecs_to_jiffies(d.timeout_ms) : 0; + +- if (d.addr && d.data_len) { ++ if (d.data_len) { + ret = nvme_map_user_request(req, d.addr, + d.data_len, nvme_to_user_ptr(d.metadata), + d.metadata_len, ioucmd, vec); +-- +2.39.5 + diff --git a/queue-6.14/nvme-pci-add-quirks-for-device-126f-1001.patch b/queue-6.14/nvme-pci-add-quirks-for-device-126f-1001.patch new file mode 100644 index 0000000000..b6fa5bc67d --- /dev/null +++ b/queue-6.14/nvme-pci-add-quirks-for-device-126f-1001.patch @@ -0,0 +1,49 @@ +From 7a187e62372ea77f5d983698f4a275b4d2215ded Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 22 Apr 2025 20:17:25 +0800 +Subject: nvme-pci: add quirks for device 126f:1001 + +From: Wentao Guan + +[ Upstream commit 5b960f92ac3e5b4d7f60a506a6b6735eead1da01 ] + +This commit adds NVME_QUIRK_NO_DEEPEST_PS and NVME_QUIRK_BOGUS_NID for +device [126f:1001]. + +It is similar to commit e89086c43f05 ("drivers/nvme: Add quirks for +device 126f:2262") + +Diff is according the dmesg, use NVME_QUIRK_IGNORE_DEV_SUBNQN. + +dmesg | grep -i nvme0: + nvme nvme0: pci function 0000:01:00.0 + nvme nvme0: missing or invalid SUBNQN field. + nvme nvme0: 12/0/0 default/read/poll queues + +Link:https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=e89086c43f0500bc7c4ce225495b73b8ce234c1f +Signed-off-by: Wentao Guan +Signed-off-by: WangYuli +Reviewed-by: Sagi Grimberg +Signed-off-by: Christoph Hellwig +Signed-off-by: Sasha Levin +--- + drivers/nvme/host/pci.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c +index 00bd21b5c641e..63b03a5a5b765 100644 +--- a/drivers/nvme/host/pci.c ++++ b/drivers/nvme/host/pci.c +@@ -3628,6 +3628,9 @@ static const struct pci_device_id nvme_id_table[] = { + .driver_data = NVME_QUIRK_BOGUS_NID, }, + { PCI_DEVICE(0x1217, 0x8760), /* O2 Micro 64GB Steam Deck */ + .driver_data = NVME_QUIRK_DMAPOOL_ALIGN_512, }, ++ { PCI_DEVICE(0x126f, 0x1001), /* Silicon Motion generic */ ++ .driver_data = NVME_QUIRK_NO_DEEPEST_PS | ++ NVME_QUIRK_IGNORE_DEV_SUBNQN, }, + { PCI_DEVICE(0x126f, 0x2262), /* Silicon Motion generic */ + .driver_data = NVME_QUIRK_NO_DEEPEST_PS | + NVME_QUIRK_BOGUS_NID, }, +-- +2.39.5 + diff --git a/queue-6.14/nvme-pci-add-quirks-for-wdc-blue-sn550-15b7-5009.patch b/queue-6.14/nvme-pci-add-quirks-for-wdc-blue-sn550-15b7-5009.patch new file mode 100644 index 0000000000..2fbd1d0cd5 --- /dev/null +++ b/queue-6.14/nvme-pci-add-quirks-for-wdc-blue-sn550-15b7-5009.patch @@ -0,0 +1,87 @@ +From 7428e8064eb3d715524f37c3c3b6d701ea1805ce Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 24 Apr 2025 10:40:10 +0800 +Subject: nvme-pci: add quirks for WDC Blue SN550 15b7:5009 + +From: Wentao Guan + +[ Upstream commit ab35ad950d439ec3409509835d229b3d93d3c7f9 ] + +Add two quirks for the WDC Blue SN550 (PCI ID 15b7:5009) based on user +reports and hardware analysis: + + - NVME_QUIRK_NO_DEEPEST_PS: + liaozw talked to me the problem and solved with + nvme_core.default_ps_max_latency_us=0, so add the quirk. + I also found some reports in the following link. + + - NVME_QUIRK_BROKEN_MSI: + after get the lspci from Jack Rio. + I think that the disk also have NVME_QUIRK_BROKEN_MSI. + described in commit d5887dc6b6c0 ("nvme-pci: Add quirk for broken MSIs") + as sean said in link which match the MSI 1/32 and MSI-X 17. + +Log: +lspci -nn | grep -i memory +03:00.0 Non-Volatile memory controller [0108]: Sandisk Corp SanDisk Ultra 3D / WD PC SN530, IX SN530, Blue SN550 NVMe SSD (DRAM-less) [15b7:5009] (rev 01) +lspci -v -d 15b7:5009 +03:00.0 Non-Volatile memory controller: Sandisk Corp SanDisk Ultra 3D / WD PC SN530, IX SN530, Blue SN550 NVMe SSD (DRAM-less) (rev 01) (prog-if 02 [NVM Express]) + Subsystem: Sandisk Corp WD Blue SN550 NVMe SSD + Flags: bus master, fast devsel, latency 0, IRQ 35, IOMMU group 10 + Memory at fe800000 (64-bit, non-prefetchable) [size=16K] + Memory at fe804000 (64-bit, non-prefetchable) [size=256] + Capabilities: [80] Power Management version 3 + Capabilities: [90] MSI: Enable- Count=1/32 Maskable- 64bit+ + Capabilities: [b0] MSI-X: Enable+ Count=17 Masked- + Capabilities: [c0] Express Endpoint, MSI 00 + Capabilities: [100] Advanced Error Reporting + Capabilities: [150] Device Serial Number 00-00-00-00-00-00-00-00 + Capabilities: [1b8] Latency Tolerance Reporting + Capabilities: [300] Secondary PCI Express + Capabilities: [900] L1 PM Substates + Kernel driver in use: nvme +dmesg | grep nvme +[ 0.000000] Command line: BOOT_IMAGE=/vmlinuz-6.12.20-amd64-desktop-rolling root=UUID= ro splash quiet nvme_core.default_ps_max_latency_us=0 DEEPIN_GFXMODE= +[ 0.059301] Kernel command line: BOOT_IMAGE=/vmlinuz-6.12.20-amd64-desktop-rolling root=UUID= ro splash quiet nvme_core.default_ps_max_latency_us=0 DEEPIN_GFXMODE= +[ 0.542430] nvme nvme0: pci function 0000:03:00.0 +[ 0.560426] nvme nvme0: allocated 32 MiB host memory buffer. +[ 0.562491] nvme nvme0: 16/0/0 default/read/poll queues +[ 0.567764] nvme0n1: p1 p2 p3 p4 p5 p6 p7 p8 p9 +[ 6.388726] EXT4-fs (nvme0n1p7): mounted filesystem ro with ordered data mode. Quota mode: none. +[ 6.893421] EXT4-fs (nvme0n1p7): re-mounted r/w. Quota mode: none. +[ 7.125419] Adding 16777212k swap on /dev/nvme0n1p8. Priority:-2 extents:1 across:16777212k SS +[ 7.157588] EXT4-fs (nvme0n1p6): mounted filesystem r/w with ordered data mode. Quota mode: none. +[ 7.165021] EXT4-fs (nvme0n1p9): mounted filesystem r/w with ordered data mode. Quota mode: none. +[ 8.036932] nvme nvme0: using unchecked data buffer +[ 8.096023] block nvme0n1: No UUID available providing old NGUID + +Link: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=d5887dc6b6c054d0da3cd053afc15b7be1f45ff6 +Link: https://lore.kernel.org/all/20240422162822.3539156-1-sean.anderson@linux.dev/ +Reported-by: liaozw +Closes: https://bbs.deepin.org.cn/post/286300 +Reported-by: rugk +Closes: https://bugzilla.kernel.org/show_bug.cgi?id=208123 +Signed-off-by: Wentao Guan +Signed-off-by: Christoph Hellwig +Signed-off-by: Sasha Levin +--- + drivers/nvme/host/pci.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c +index 63b03a5a5b765..abd097eba6623 100644 +--- a/drivers/nvme/host/pci.c ++++ b/drivers/nvme/host/pci.c +@@ -3654,6 +3654,9 @@ static const struct pci_device_id nvme_id_table[] = { + NVME_QUIRK_IGNORE_DEV_SUBNQN, }, + { PCI_DEVICE(0x15b7, 0x5008), /* Sandisk SN530 */ + .driver_data = NVME_QUIRK_BROKEN_MSI }, ++ { PCI_DEVICE(0x15b7, 0x5009), /* Sandisk SN550 */ ++ .driver_data = NVME_QUIRK_BROKEN_MSI | ++ NVME_QUIRK_NO_DEEPEST_PS }, + { PCI_DEVICE(0x1987, 0x5012), /* Phison E12 */ + .driver_data = NVME_QUIRK_BOGUS_NID, }, + { PCI_DEVICE(0x1987, 0x5016), /* Phison E16 */ +-- +2.39.5 + diff --git a/queue-6.14/nvmem-core-fix-bit-offsets-of-more-than-one-byte.patch b/queue-6.14/nvmem-core-fix-bit-offsets-of-more-than-one-byte.patch new file mode 100644 index 0000000000..8d2d96e820 --- /dev/null +++ b/queue-6.14/nvmem-core-fix-bit-offsets-of-more-than-one-byte.patch @@ -0,0 +1,76 @@ +From 61587d03820e1f0da6cbaec219c75b83f1fba7bb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 11 Apr 2025 12:22:46 +0100 +Subject: nvmem: core: fix bit offsets of more than one byte + +From: Dmitry Baryshkov + +[ Upstream commit 7a06ef75107799675ea6e4d73b9df37e18e352a8 ] + +If the NVMEM specifies a stride to access data, reading particular cell +might require bit offset that is bigger than one byte. Rework NVMEM core +code to support bit offsets of more than 8 bits. + +Signed-off-by: Dmitry Baryshkov +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20250411112251.68002-9-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/nvmem/core.c | 24 +++++++++++++++++------- + 1 file changed, 17 insertions(+), 7 deletions(-) + +diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c +index fff85bbf0ecd0..7872903c08a11 100644 +--- a/drivers/nvmem/core.c ++++ b/drivers/nvmem/core.c +@@ -837,7 +837,9 @@ static int nvmem_add_cells_from_dt(struct nvmem_device *nvmem, struct device_nod + if (addr && len == (2 * sizeof(u32))) { + info.bit_offset = be32_to_cpup(addr++); + info.nbits = be32_to_cpup(addr); +- if (info.bit_offset >= BITS_PER_BYTE || info.nbits < 1) { ++ if (info.bit_offset >= BITS_PER_BYTE * info.bytes || ++ info.nbits < 1 || ++ info.bit_offset + info.nbits > BITS_PER_BYTE * info.bytes) { + dev_err(dev, "nvmem: invalid bits on %pOF\n", child); + of_node_put(child); + return -EINVAL; +@@ -1630,21 +1632,29 @@ EXPORT_SYMBOL_GPL(nvmem_cell_put); + static void nvmem_shift_read_buffer_in_place(struct nvmem_cell_entry *cell, void *buf) + { + u8 *p, *b; +- int i, extra, bit_offset = cell->bit_offset; ++ int i, extra, bytes_offset; ++ int bit_offset = cell->bit_offset; + + p = b = buf; +- if (bit_offset) { ++ ++ bytes_offset = bit_offset / BITS_PER_BYTE; ++ b += bytes_offset; ++ bit_offset %= BITS_PER_BYTE; ++ ++ if (bit_offset % BITS_PER_BYTE) { + /* First shift */ +- *b++ >>= bit_offset; ++ *p = *b++ >> bit_offset; + + /* setup rest of the bytes if any */ + for (i = 1; i < cell->bytes; i++) { + /* Get bits from next byte and shift them towards msb */ +- *p |= *b << (BITS_PER_BYTE - bit_offset); ++ *p++ |= *b << (BITS_PER_BYTE - bit_offset); + +- p = b; +- *b++ >>= bit_offset; ++ *p = *b++ >> bit_offset; + } ++ } else if (p != b) { ++ memmove(p, b, cell->bytes - bytes_offset); ++ p += cell->bytes - 1; + } else { + /* point to the msb */ + p += cell->bytes - 1; +-- +2.39.5 + diff --git a/queue-6.14/nvmem-core-update-raw_len-if-the-bit-reading-is-requ.patch b/queue-6.14/nvmem-core-update-raw_len-if-the-bit-reading-is-requ.patch new file mode 100644 index 0000000000..7d11fb9824 --- /dev/null +++ b/queue-6.14/nvmem-core-update-raw_len-if-the-bit-reading-is-requ.patch @@ -0,0 +1,42 @@ +From 02b3db4f4badafd3be309f0cbe76c77716c4e507 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 11 Apr 2025 12:22:48 +0100 +Subject: nvmem: core: update raw_len if the bit reading is required + +From: Dmitry Baryshkov + +[ Upstream commit 6786484223d5705bf7f919c1e5055d478ebeec32 ] + +If NVMEM cell uses bit offset or specifies bit truncation, update +raw_len manually (following the cell->bytes update), ensuring that the +NVMEM access is still word-aligned. + +Signed-off-by: Dmitry Baryshkov +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20250411112251.68002-11-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/nvmem/core.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c +index 7b8c85f9e035c..e206efc29a004 100644 +--- a/drivers/nvmem/core.c ++++ b/drivers/nvmem/core.c +@@ -594,9 +594,11 @@ static int nvmem_cell_info_to_nvmem_cell_entry_nodup(struct nvmem_device *nvmem, + cell->nbits = info->nbits; + cell->np = info->np; + +- if (cell->nbits) ++ if (cell->nbits) { + cell->bytes = DIV_ROUND_UP(cell->nbits + cell->bit_offset, + BITS_PER_BYTE); ++ cell->raw_len = ALIGN(cell->bytes, nvmem->word_size); ++ } + + if (!IS_ALIGNED(cell->offset, nvmem->stride)) { + dev_err(&nvmem->dev, +-- +2.39.5 + diff --git a/queue-6.14/nvmem-core-verify-cell-s-raw_len.patch b/queue-6.14/nvmem-core-verify-cell-s-raw_len.patch new file mode 100644 index 0000000000..8d34dd638f --- /dev/null +++ b/queue-6.14/nvmem-core-verify-cell-s-raw_len.patch @@ -0,0 +1,48 @@ +From c68bb59e4462412e25de5bfa7d56abf7fddc307a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 11 Apr 2025 12:22:47 +0100 +Subject: nvmem: core: verify cell's raw_len + +From: Dmitry Baryshkov + +[ Upstream commit 13bcd440f2ff38cd7e42a179c223d4b833158b33 ] + +Check that the NVMEM cell's raw_len is a aligned to word_size. Otherwise +Otherwise drivers might face incomplete read while accessing the last +part of the NVMEM cell. + +Signed-off-by: Dmitry Baryshkov +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20250411112251.68002-10-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/nvmem/core.c | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c +index 7872903c08a11..7b8c85f9e035c 100644 +--- a/drivers/nvmem/core.c ++++ b/drivers/nvmem/core.c +@@ -605,6 +605,18 @@ static int nvmem_cell_info_to_nvmem_cell_entry_nodup(struct nvmem_device *nvmem, + return -EINVAL; + } + ++ if (!IS_ALIGNED(cell->raw_len, nvmem->word_size)) { ++ dev_err(&nvmem->dev, ++ "cell %s raw len %zd unaligned to nvmem word size %d\n", ++ cell->name ?: "", cell->raw_len, ++ nvmem->word_size); ++ ++ if (info->raw_len) ++ return -EINVAL; ++ ++ cell->raw_len = ALIGN(cell->raw_len, nvmem->word_size); ++ } ++ + return 0; + } + +-- +2.39.5 + diff --git a/queue-6.14/nvmem-qfprom-switch-to-4-byte-aligned-reads.patch b/queue-6.14/nvmem-qfprom-switch-to-4-byte-aligned-reads.patch new file mode 100644 index 0000000000..8779717988 --- /dev/null +++ b/queue-6.14/nvmem-qfprom-switch-to-4-byte-aligned-reads.patch @@ -0,0 +1,84 @@ +From a2c90e7c892db8e698208dd025350732b0908636 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 11 Apr 2025 12:22:49 +0100 +Subject: nvmem: qfprom: switch to 4-byte aligned reads + +From: Dmitry Baryshkov + +[ Upstream commit 3566a737db87a9bf360c2fd36433c5149f805f2e ] + +All platforms since Snapdragon 8 Gen1 (SM8450) require using 4-byte +reads to access QFPROM data. While older platforms were more than happy +with 1-byte reads, change the qfprom driver to use 4-byte reads for all +the platforms. Specify stride and word size of 4 bytes. To retain +compatibility with the existing DT and to simplify porting data from +vendor kernels, use fixup_dt_cell_info in order to bump alignment +requirements. + +Signed-off-by: Dmitry Baryshkov +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20250411112251.68002-12-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/nvmem/qfprom.c | 26 ++++++++++++++++++++------ + 1 file changed, 20 insertions(+), 6 deletions(-) + +diff --git a/drivers/nvmem/qfprom.c b/drivers/nvmem/qfprom.c +index 116a39e804c70..a872c640b8c5a 100644 +--- a/drivers/nvmem/qfprom.c ++++ b/drivers/nvmem/qfprom.c +@@ -321,19 +321,32 @@ static int qfprom_reg_read(void *context, + unsigned int reg, void *_val, size_t bytes) + { + struct qfprom_priv *priv = context; +- u8 *val = _val; +- int i = 0, words = bytes; ++ u32 *val = _val; + void __iomem *base = priv->qfpcorrected; ++ int words = DIV_ROUND_UP(bytes, sizeof(u32)); ++ int i; + + if (read_raw_data && priv->qfpraw) + base = priv->qfpraw; + +- while (words--) +- *val++ = readb(base + reg + i++); ++ for (i = 0; i < words; i++) ++ *val++ = readl(base + reg + i * sizeof(u32)); + + return 0; + } + ++/* Align reads to word boundary */ ++static void qfprom_fixup_dt_cell_info(struct nvmem_device *nvmem, ++ struct nvmem_cell_info *cell) ++{ ++ unsigned int byte_offset = cell->offset % sizeof(u32); ++ ++ cell->bit_offset += byte_offset * BITS_PER_BYTE; ++ cell->offset -= byte_offset; ++ if (byte_offset && !cell->nbits) ++ cell->nbits = cell->bytes * BITS_PER_BYTE; ++} ++ + static void qfprom_runtime_disable(void *data) + { + pm_runtime_disable(data); +@@ -358,10 +371,11 @@ static int qfprom_probe(struct platform_device *pdev) + struct nvmem_config econfig = { + .name = "qfprom", + .add_legacy_fixed_of_cells = true, +- .stride = 1, +- .word_size = 1, ++ .stride = 4, ++ .word_size = 4, + .id = NVMEM_DEVID_AUTO, + .reg_read = qfprom_reg_read, ++ .fixup_dt_cell_info = qfprom_fixup_dt_cell_info, + }; + struct device *dev = &pdev->dev; + struct resource *res; +-- +2.39.5 + diff --git a/queue-6.14/nvmem-rockchip-otp-add-rk3576-variant-data.patch b/queue-6.14/nvmem-rockchip-otp-add-rk3576-variant-data.patch new file mode 100644 index 0000000000..4aca006ce1 --- /dev/null +++ b/queue-6.14/nvmem-rockchip-otp-add-rk3576-variant-data.patch @@ -0,0 +1,55 @@ +From 9e01c16adf9181e9dbc67ce094799209d7d66b42 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 11 Apr 2025 12:22:42 +0100 +Subject: nvmem: rockchip-otp: add rk3576 variant data + +From: Heiko Stuebner + +[ Upstream commit 50d75a13a9ce880a5ef07a4ccc63ba561cc2e69a ] + +The variant works very similar to the rk3588, just with a different +read-offset and size. + +Signed-off-by: Heiko Stuebner +Tested-by: Nicolas Frattaroli +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20250411112251.68002-5-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/nvmem/rockchip-otp.c | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/drivers/nvmem/rockchip-otp.c b/drivers/nvmem/rockchip-otp.c +index 3edfbfc2d7220..d88f12c532426 100644 +--- a/drivers/nvmem/rockchip-otp.c ++++ b/drivers/nvmem/rockchip-otp.c +@@ -274,6 +274,14 @@ static const struct rockchip_data px30_data = { + .reg_read = px30_otp_read, + }; + ++static const struct rockchip_data rk3576_data = { ++ .size = 0x100, ++ .read_offset = 0x700, ++ .clks = px30_otp_clocks, ++ .num_clks = ARRAY_SIZE(px30_otp_clocks), ++ .reg_read = rk3588_otp_read, ++}; ++ + static const char * const rk3588_otp_clocks[] = { + "otp", "apb_pclk", "phy", "arb", + }; +@@ -295,6 +303,10 @@ static const struct of_device_id rockchip_otp_match[] = { + .compatible = "rockchip,rk3308-otp", + .data = &px30_data, + }, ++ { ++ .compatible = "rockchip,rk3576-otp", ++ .data = &rk3576_data, ++ }, + { + .compatible = "rockchip,rk3588-otp", + .data = &rk3588_data, +-- +2.39.5 + diff --git a/queue-6.14/nvmem-rockchip-otp-move-read-offset-into-variant-dat.patch b/queue-6.14/nvmem-rockchip-otp-move-read-offset-into-variant-dat.patch new file mode 100644 index 0000000000..6480fb5bcc --- /dev/null +++ b/queue-6.14/nvmem-rockchip-otp-move-read-offset-into-variant-dat.patch @@ -0,0 +1,67 @@ +From f794bdd3978ecd50923e883f3272717b9cfac22c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 11 Apr 2025 12:22:39 +0100 +Subject: nvmem: rockchip-otp: Move read-offset into variant-data + +From: Heiko Stuebner + +[ Upstream commit 6907e8093b3070d877ee607e5ceede60cfd08bde ] + +The RK3588 has an offset into the OTP area where the readable area begins +and automatically adds this to the start address. +Other variants are very much similar to rk3588, just with a different +offset, so move that value into variant-data. + +To match the size in bytes, store this value also in bytes and not in +number of blocks. + +Signed-off-by: Heiko Stuebner +Tested-by: Nicolas Frattaroli +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20250411112251.68002-2-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/nvmem/rockchip-otp.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/drivers/nvmem/rockchip-otp.c b/drivers/nvmem/rockchip-otp.c +index ebc3f0b24166b..3edfbfc2d7220 100644 +--- a/drivers/nvmem/rockchip-otp.c ++++ b/drivers/nvmem/rockchip-otp.c +@@ -59,7 +59,6 @@ + #define RK3588_OTPC_AUTO_EN 0x08 + #define RK3588_OTPC_INT_ST 0x84 + #define RK3588_OTPC_DOUT0 0x20 +-#define RK3588_NO_SECURE_OFFSET 0x300 + #define RK3588_NBYTES 4 + #define RK3588_BURST_NUM 1 + #define RK3588_BURST_SHIFT 8 +@@ -69,6 +68,7 @@ + + struct rockchip_data { + int size; ++ int read_offset; + const char * const *clks; + int num_clks; + nvmem_reg_read_t reg_read; +@@ -196,7 +196,7 @@ static int rk3588_otp_read(void *context, unsigned int offset, + addr_start = round_down(offset, RK3588_NBYTES) / RK3588_NBYTES; + addr_end = round_up(offset + bytes, RK3588_NBYTES) / RK3588_NBYTES; + addr_len = addr_end - addr_start; +- addr_start += RK3588_NO_SECURE_OFFSET; ++ addr_start += otp->data->read_offset / RK3588_NBYTES; + + buf = kzalloc(array_size(addr_len, RK3588_NBYTES), GFP_KERNEL); + if (!buf) +@@ -280,6 +280,7 @@ static const char * const rk3588_otp_clocks[] = { + + static const struct rockchip_data rk3588_data = { + .size = 0x400, ++ .read_offset = 0xc00, + .clks = rk3588_otp_clocks, + .num_clks = ARRAY_SIZE(rk3588_otp_clocks), + .reg_read = rk3588_otp_read, +-- +2.39.5 + diff --git a/queue-6.14/nvmet-pci-epf-clear-completion-queue-irq-flag-on-del.patch b/queue-6.14/nvmet-pci-epf-clear-completion-queue-irq-flag-on-del.patch new file mode 100644 index 0000000000..401b39db6f --- /dev/null +++ b/queue-6.14/nvmet-pci-epf-clear-completion-queue-irq-flag-on-del.patch @@ -0,0 +1,46 @@ +From 79fc0c44b1c4dc306e2f89d909c56b626af2e132 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 9 May 2025 08:25:00 +0900 +Subject: nvmet: pci-epf: clear completion queue IRQ flag on delete + +From: Damien Le Moal + +[ Upstream commit 85adf2094abb9084770dc4ab302aaa9c5d26dd2d ] + +The function nvmet_pci_epf_delete_cq() unconditionally calls +nvmet_pci_epf_remove_irq_vector() even for completion queues that do not +have interrupts enabled. Furthermore, for completion queues that do +have IRQ enabled, deleting and re-creating the completion queue leaves +the flag NVMET_PCI_EPF_Q_IRQ_ENABLED set, even if the completion queue +is being re-created with IRQ disabled. + +Fix these issues by calling nvmet_pci_epf_remove_irq_vector() only if +NVMET_PCI_EPF_Q_IRQ_ENABLED is set and make sure to always clear that +flag. + +Fixes: 0faa0fe6f90e ("nvmet: New NVMe PCI endpoint function target driver") +Cc: stable@vger.kernel.org +Signed-off-by: Damien Le Moal +Signed-off-by: Christoph Hellwig +Signed-off-by: Sasha Levin +--- + drivers/nvme/target/pci-epf.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/nvme/target/pci-epf.c b/drivers/nvme/target/pci-epf.c +index 81957b6e84986..fbc167f47d8a6 100644 +--- a/drivers/nvme/target/pci-epf.c ++++ b/drivers/nvme/target/pci-epf.c +@@ -1344,7 +1344,8 @@ static u16 nvmet_pci_epf_delete_cq(struct nvmet_ctrl *tctrl, u16 cqid) + + cancel_delayed_work_sync(&cq->work); + nvmet_pci_epf_drain_queue(cq); +- nvmet_pci_epf_remove_irq_vector(ctrl, cq->vector); ++ if (test_and_clear_bit(NVMET_PCI_EPF_Q_IRQ_ENABLED, &cq->flags)) ++ nvmet_pci_epf_remove_irq_vector(ctrl, cq->vector); + nvmet_pci_epf_mem_unmap(ctrl->nvme_epf, &cq->pci_map); + + return NVME_SC_SUCCESS; +-- +2.39.5 + diff --git a/queue-6.14/nvmet-pci-epf-keep-completion-queues-mapped.patch b/queue-6.14/nvmet-pci-epf-keep-completion-queues-mapped.patch new file mode 100644 index 0000000000..3efff24562 --- /dev/null +++ b/queue-6.14/nvmet-pci-epf-keep-completion-queues-mapped.patch @@ -0,0 +1,161 @@ +From 80f6ffb45100c939a8cbfaffde56ec0400becf52 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 13 Mar 2025 17:22:18 +0900 +Subject: nvmet: pci-epf: Keep completion queues mapped + +From: Damien Le Moal + +[ Upstream commit ea7789c1541084a3dae65ffd36778348dd98f61b ] + +Instead of mapping and unmapping the completion queues memory to the +host PCI address space whenever nvmet_pci_epf_cq_work() is called, map +a completion queue to the host PCI address space when the completion +queue is created with nvmet_pci_epf_create_cq() and unmap it when the +completion queue is deleted with nvmet_pci_epf_delete_cq(). + +This removes the completion queue mapping/unmapping from +nvmet_pci_epf_cq_work() and significantly increases performance. For +a single job 4K random read QD=1 workload, the IOPS is increased from +23 KIOPS to 25 KIOPS. Some significant throughput increasde for high +queue depth and large IOs workloads can also be seen. + +Since the functions nvmet_pci_epf_map_queue() and +nvmet_pci_epf_unmap_queue() are called respectively only from +nvmet_pci_epf_create_cq() and nvmet_pci_epf_delete_cq(), these functions +are removed and open-coded in their respective call sites. + +Signed-off-by: Damien Le Moal +Reviewed-by: Christoph Hellwig +Signed-off-by: Keith Busch +Stable-dep-of: 85adf2094abb ("nvmet: pci-epf: clear completion queue IRQ flag on delete") +Signed-off-by: Sasha Levin +--- + drivers/nvme/target/pci-epf.c | 63 ++++++++++++++--------------------- + 1 file changed, 25 insertions(+), 38 deletions(-) + +diff --git a/drivers/nvme/target/pci-epf.c b/drivers/nvme/target/pci-epf.c +index bc1daa9aede9d..81957b6e84986 100644 +--- a/drivers/nvme/target/pci-epf.c ++++ b/drivers/nvme/target/pci-epf.c +@@ -1264,6 +1264,7 @@ static u16 nvmet_pci_epf_create_cq(struct nvmet_ctrl *tctrl, + struct nvmet_pci_epf_ctrl *ctrl = tctrl->drvdata; + struct nvmet_pci_epf_queue *cq = &ctrl->cq[cqid]; + u16 status; ++ int ret; + + if (test_bit(NVMET_PCI_EPF_Q_LIVE, &cq->flags)) + return NVME_SC_QID_INVALID | NVME_STATUS_DNR; +@@ -1298,6 +1299,24 @@ static u16 nvmet_pci_epf_create_cq(struct nvmet_ctrl *tctrl, + if (status != NVME_SC_SUCCESS) + goto err; + ++ /* ++ * Map the CQ PCI address space and since PCI endpoint controllers may ++ * return a partial mapping, check that the mapping is large enough. ++ */ ++ ret = nvmet_pci_epf_mem_map(ctrl->nvme_epf, cq->pci_addr, cq->pci_size, ++ &cq->pci_map); ++ if (ret) { ++ dev_err(ctrl->dev, "Failed to map CQ %u (err=%d)\n", ++ cq->qid, ret); ++ goto err_internal; ++ } ++ ++ if (cq->pci_map.pci_size < cq->pci_size) { ++ dev_err(ctrl->dev, "Invalid partial mapping of queue %u\n", ++ cq->qid); ++ goto err_unmap_queue; ++ } ++ + set_bit(NVMET_PCI_EPF_Q_LIVE, &cq->flags); + + dev_dbg(ctrl->dev, "CQ[%u]: %u entries of %zu B, IRQ vector %u\n", +@@ -1305,6 +1324,10 @@ static u16 nvmet_pci_epf_create_cq(struct nvmet_ctrl *tctrl, + + return NVME_SC_SUCCESS; + ++err_unmap_queue: ++ nvmet_pci_epf_mem_unmap(ctrl->nvme_epf, &cq->pci_map); ++err_internal: ++ status = NVME_SC_INTERNAL | NVME_STATUS_DNR; + err: + if (test_and_clear_bit(NVMET_PCI_EPF_Q_IRQ_ENABLED, &cq->flags)) + nvmet_pci_epf_remove_irq_vector(ctrl, cq->vector); +@@ -1322,6 +1345,7 @@ static u16 nvmet_pci_epf_delete_cq(struct nvmet_ctrl *tctrl, u16 cqid) + cancel_delayed_work_sync(&cq->work); + nvmet_pci_epf_drain_queue(cq); + nvmet_pci_epf_remove_irq_vector(ctrl, cq->vector); ++ nvmet_pci_epf_mem_unmap(ctrl->nvme_epf, &cq->pci_map); + + return NVME_SC_SUCCESS; + } +@@ -1554,36 +1578,6 @@ static void nvmet_pci_epf_free_queues(struct nvmet_pci_epf_ctrl *ctrl) + ctrl->cq = NULL; + } + +-static int nvmet_pci_epf_map_queue(struct nvmet_pci_epf_ctrl *ctrl, +- struct nvmet_pci_epf_queue *queue) +-{ +- struct nvmet_pci_epf *nvme_epf = ctrl->nvme_epf; +- int ret; +- +- ret = nvmet_pci_epf_mem_map(nvme_epf, queue->pci_addr, +- queue->pci_size, &queue->pci_map); +- if (ret) { +- dev_err(ctrl->dev, "Failed to map queue %u (err=%d)\n", +- queue->qid, ret); +- return ret; +- } +- +- if (queue->pci_map.pci_size < queue->pci_size) { +- dev_err(ctrl->dev, "Invalid partial mapping of queue %u\n", +- queue->qid); +- nvmet_pci_epf_mem_unmap(nvme_epf, &queue->pci_map); +- return -ENOMEM; +- } +- +- return 0; +-} +- +-static inline void nvmet_pci_epf_unmap_queue(struct nvmet_pci_epf_ctrl *ctrl, +- struct nvmet_pci_epf_queue *queue) +-{ +- nvmet_pci_epf_mem_unmap(ctrl->nvme_epf, &queue->pci_map); +-} +- + static void nvmet_pci_epf_exec_iod_work(struct work_struct *work) + { + struct nvmet_pci_epf_iod *iod = +@@ -1749,11 +1743,7 @@ static void nvmet_pci_epf_cq_work(struct work_struct *work) + struct nvme_completion *cqe; + struct nvmet_pci_epf_iod *iod; + unsigned long flags; +- int ret, n = 0; +- +- ret = nvmet_pci_epf_map_queue(ctrl, cq); +- if (ret) +- goto again; ++ int ret = 0, n = 0; + + while (test_bit(NVMET_PCI_EPF_Q_LIVE, &cq->flags) && ctrl->link_up) { + +@@ -1809,8 +1799,6 @@ static void nvmet_pci_epf_cq_work(struct work_struct *work) + n++; + } + +- nvmet_pci_epf_unmap_queue(ctrl, cq); +- + /* + * We do not support precise IRQ coalescing time (100ns units as per + * NVMe specifications). So if we have posted completion entries without +@@ -1819,7 +1807,6 @@ static void nvmet_pci_epf_cq_work(struct work_struct *work) + if (n) + nvmet_pci_epf_raise_irq(ctrl, cq, true); + +-again: + if (ret < 0) + queue_delayed_work(system_highpri_wq, &cq->work, + NVMET_PCI_EPF_CQ_RETRY_INTERVAL); +-- +2.39.5 + diff --git a/queue-6.14/nvmet-tcp-don-t-restore-null-sk_state_change.patch b/queue-6.14/nvmet-tcp-don-t-restore-null-sk_state_change.patch new file mode 100644 index 0000000000..b211e7aca0 --- /dev/null +++ b/queue-6.14/nvmet-tcp-don-t-restore-null-sk_state_change.patch @@ -0,0 +1,227 @@ +From 031ea99745f8866c58cea9cb93e2a7d53bccf37a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 23 Apr 2025 16:06:21 +1000 +Subject: nvmet-tcp: don't restore null sk_state_change + +From: Alistair Francis + +[ Upstream commit 46d22b47df2741996af277a2838b95f130436c13 ] + +queue->state_change is set as part of nvmet_tcp_set_queue_sock(), but if +the TCP connection isn't established when nvmet_tcp_set_queue_sock() is +called then queue->state_change isn't set and sock->sk->sk_state_change +isn't replaced. + +As such we don't need to restore sock->sk->sk_state_change if +queue->state_change is NULL. + +This avoids NULL pointer dereferences such as this: + +[ 286.462026][ C0] BUG: kernel NULL pointer dereference, address: 0000000000000000 +[ 286.462814][ C0] #PF: supervisor instruction fetch in kernel mode +[ 286.463796][ C0] #PF: error_code(0x0010) - not-present page +[ 286.464392][ C0] PGD 8000000140620067 P4D 8000000140620067 PUD 114201067 PMD 0 +[ 286.465086][ C0] Oops: Oops: 0010 [#1] SMP KASAN PTI +[ 286.465559][ C0] CPU: 0 UID: 0 PID: 1628 Comm: nvme Not tainted 6.15.0-rc2+ #11 PREEMPT(voluntary) +[ 286.466393][ C0] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.16.3-3.fc41 04/01/2014 +[ 286.467147][ C0] RIP: 0010:0x0 +[ 286.467420][ C0] Code: Unable to access opcode bytes at 0xffffffffffffffd6. +[ 286.467977][ C0] RSP: 0018:ffff8883ae008580 EFLAGS: 00010246 +[ 286.468425][ C0] RAX: 0000000000000000 RBX: ffff88813fd34100 RCX: ffffffffa386cc43 +[ 286.469019][ C0] RDX: 1ffff11027fa68b6 RSI: 0000000000000008 RDI: ffff88813fd34100 +[ 286.469545][ C0] RBP: ffff88813fd34160 R08: 0000000000000000 R09: ffffed1027fa682c +[ 286.470072][ C0] R10: ffff88813fd34167 R11: 0000000000000000 R12: ffff88813fd344c3 +[ 286.470585][ C0] R13: ffff88813fd34112 R14: ffff88813fd34aec R15: ffff888132cdd268 +[ 286.471070][ C0] FS: 00007fe3c04c7d80(0000) GS:ffff88840743f000(0000) knlGS:0000000000000000 +[ 286.471644][ C0] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +[ 286.472543][ C0] CR2: ffffffffffffffd6 CR3: 000000012daca000 CR4: 00000000000006f0 +[ 286.473500][ C0] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 +[ 286.474467][ C0] DR3: 0000000000000000 DR6: 00000000ffff07f0 DR7: 0000000000000400 +[ 286.475453][ C0] Call Trace: +[ 286.476102][ C0] +[ 286.476719][ C0] tcp_fin+0x2bb/0x440 +[ 286.477429][ C0] tcp_data_queue+0x190f/0x4e60 +[ 286.478174][ C0] ? __build_skb_around+0x234/0x330 +[ 286.478940][ C0] ? rcu_is_watching+0x11/0xb0 +[ 286.479659][ C0] ? __pfx_tcp_data_queue+0x10/0x10 +[ 286.480431][ C0] ? tcp_try_undo_loss+0x640/0x6c0 +[ 286.481196][ C0] ? seqcount_lockdep_reader_access.constprop.0+0x82/0x90 +[ 286.482046][ C0] ? kvm_clock_get_cycles+0x14/0x30 +[ 286.482769][ C0] ? ktime_get+0x66/0x150 +[ 286.483433][ C0] ? rcu_is_watching+0x11/0xb0 +[ 286.484146][ C0] tcp_rcv_established+0x6e4/0x2050 +[ 286.484857][ C0] ? rcu_is_watching+0x11/0xb0 +[ 286.485523][ C0] ? ipv4_dst_check+0x160/0x2b0 +[ 286.486203][ C0] ? __pfx_tcp_rcv_established+0x10/0x10 +[ 286.486917][ C0] ? lock_release+0x217/0x2c0 +[ 286.487595][ C0] tcp_v4_do_rcv+0x4d6/0x9b0 +[ 286.488279][ C0] tcp_v4_rcv+0x2af8/0x3e30 +[ 286.488904][ C0] ? raw_local_deliver+0x51b/0xad0 +[ 286.489551][ C0] ? rcu_is_watching+0x11/0xb0 +[ 286.490198][ C0] ? __pfx_tcp_v4_rcv+0x10/0x10 +[ 286.490813][ C0] ? __pfx_raw_local_deliver+0x10/0x10 +[ 286.491487][ C0] ? __pfx_nf_confirm+0x10/0x10 [nf_conntrack] +[ 286.492275][ C0] ? rcu_is_watching+0x11/0xb0 +[ 286.492900][ C0] ip_protocol_deliver_rcu+0x8f/0x370 +[ 286.493579][ C0] ip_local_deliver_finish+0x297/0x420 +[ 286.494268][ C0] ip_local_deliver+0x168/0x430 +[ 286.494867][ C0] ? __pfx_ip_local_deliver+0x10/0x10 +[ 286.495498][ C0] ? __pfx_ip_local_deliver_finish+0x10/0x10 +[ 286.496204][ C0] ? ip_rcv_finish_core+0x19a/0x1f20 +[ 286.496806][ C0] ? lock_release+0x217/0x2c0 +[ 286.497414][ C0] ip_rcv+0x455/0x6e0 +[ 286.497945][ C0] ? __pfx_ip_rcv+0x10/0x10 +[ 286.498550][ C0] ? rcu_is_watching+0x11/0xb0 +[ 286.499137][ C0] ? __pfx_ip_rcv_finish+0x10/0x10 +[ 286.499763][ C0] ? lock_release+0x217/0x2c0 +[ 286.500327][ C0] ? dl_scaled_delta_exec+0xd1/0x2c0 +[ 286.500922][ C0] ? __pfx_ip_rcv+0x10/0x10 +[ 286.501480][ C0] __netif_receive_skb_one_core+0x166/0x1b0 +[ 286.502173][ C0] ? __pfx___netif_receive_skb_one_core+0x10/0x10 +[ 286.502903][ C0] ? lock_acquire+0x2b2/0x310 +[ 286.503487][ C0] ? process_backlog+0x372/0x1350 +[ 286.504087][ C0] ? lock_release+0x217/0x2c0 +[ 286.504642][ C0] process_backlog+0x3b9/0x1350 +[ 286.505214][ C0] ? process_backlog+0x372/0x1350 +[ 286.505779][ C0] __napi_poll.constprop.0+0xa6/0x490 +[ 286.506363][ C0] net_rx_action+0x92e/0xe10 +[ 286.506889][ C0] ? __pfx_net_rx_action+0x10/0x10 +[ 286.507437][ C0] ? timerqueue_add+0x1f0/0x320 +[ 286.507977][ C0] ? sched_clock_cpu+0x68/0x540 +[ 286.508492][ C0] ? lock_acquire+0x2b2/0x310 +[ 286.509043][ C0] ? kvm_sched_clock_read+0xd/0x20 +[ 286.509607][ C0] ? handle_softirqs+0x1aa/0x7d0 +[ 286.510187][ C0] handle_softirqs+0x1f2/0x7d0 +[ 286.510754][ C0] ? __pfx_handle_softirqs+0x10/0x10 +[ 286.511348][ C0] ? irqtime_account_irq+0x181/0x290 +[ 286.511937][ C0] ? __dev_queue_xmit+0x85d/0x3450 +[ 286.512510][ C0] do_softirq.part.0+0x89/0xc0 +[ 286.513100][ C0] +[ 286.513548][ C0] +[ 286.513953][ C0] __local_bh_enable_ip+0x112/0x140 +[ 286.514522][ C0] ? __dev_queue_xmit+0x85d/0x3450 +[ 286.515072][ C0] __dev_queue_xmit+0x872/0x3450 +[ 286.515619][ C0] ? nft_do_chain+0xe16/0x15b0 [nf_tables] +[ 286.516252][ C0] ? __pfx___dev_queue_xmit+0x10/0x10 +[ 286.516817][ C0] ? selinux_ip_postroute+0x43c/0xc50 +[ 286.517433][ C0] ? __pfx_selinux_ip_postroute+0x10/0x10 +[ 286.518061][ C0] ? rcu_is_watching+0x11/0xb0 +[ 286.518606][ C0] ? ip_output+0x164/0x4a0 +[ 286.519149][ C0] ? rcu_is_watching+0x11/0xb0 +[ 286.519671][ C0] ? ip_finish_output2+0x17d5/0x1fb0 +[ 286.520258][ C0] ip_finish_output2+0xb4b/0x1fb0 +[ 286.520787][ C0] ? __pfx_ip_finish_output2+0x10/0x10 +[ 286.521355][ C0] ? __ip_finish_output+0x15d/0x750 +[ 286.521890][ C0] ip_output+0x164/0x4a0 +[ 286.522372][ C0] ? __pfx_ip_output+0x10/0x10 +[ 286.522872][ C0] ? rcu_is_watching+0x11/0xb0 +[ 286.523402][ C0] ? _raw_spin_unlock_irqrestore+0x4c/0x60 +[ 286.524031][ C0] ? __pfx_ip_finish_output+0x10/0x10 +[ 286.524605][ C0] ? __ip_queue_xmit+0x999/0x2260 +[ 286.525200][ C0] ? rcu_is_watching+0x11/0xb0 +[ 286.525744][ C0] ? ipv4_dst_check+0x16a/0x2b0 +[ 286.526279][ C0] ? lock_release+0x217/0x2c0 +[ 286.526793][ C0] __ip_queue_xmit+0x1883/0x2260 +[ 286.527324][ C0] ? __skb_clone+0x54c/0x730 +[ 286.527827][ C0] __tcp_transmit_skb+0x209b/0x37a0 +[ 286.528374][ C0] ? __pfx___tcp_transmit_skb+0x10/0x10 +[ 286.528952][ C0] ? rcu_is_watching+0x11/0xb0 +[ 286.529472][ C0] ? seqcount_lockdep_reader_access.constprop.0+0x82/0x90 +[ 286.530152][ C0] ? trace_hardirqs_on+0x12/0x120 +[ 286.530691][ C0] tcp_write_xmit+0xb81/0x88b0 +[ 286.531224][ C0] ? mod_memcg_state+0x4d/0x60 +[ 286.531736][ C0] ? rcu_is_watching+0x11/0xb0 +[ 286.532253][ C0] __tcp_push_pending_frames+0x90/0x320 +[ 286.532826][ C0] tcp_send_fin+0x141/0xb50 +[ 286.533352][ C0] ? __pfx_tcp_send_fin+0x10/0x10 +[ 286.533908][ C0] ? __local_bh_enable_ip+0xab/0x140 +[ 286.534495][ C0] inet_shutdown+0x243/0x320 +[ 286.535077][ C0] nvme_tcp_alloc_queue+0xb3b/0x2590 [nvme_tcp] +[ 286.535709][ C0] ? do_raw_spin_lock+0x129/0x260 +[ 286.536314][ C0] ? __pfx_nvme_tcp_alloc_queue+0x10/0x10 [nvme_tcp] +[ 286.536996][ C0] ? do_raw_spin_unlock+0x54/0x1e0 +[ 286.537550][ C0] ? _raw_spin_unlock+0x29/0x50 +[ 286.538127][ C0] ? do_raw_spin_lock+0x129/0x260 +[ 286.538664][ C0] ? __pfx_do_raw_spin_lock+0x10/0x10 +[ 286.539249][ C0] ? nvme_tcp_alloc_admin_queue+0xd5/0x340 [nvme_tcp] +[ 286.539892][ C0] ? __wake_up+0x40/0x60 +[ 286.540392][ C0] nvme_tcp_alloc_admin_queue+0xd5/0x340 [nvme_tcp] +[ 286.541047][ C0] ? rcu_is_watching+0x11/0xb0 +[ 286.541589][ C0] nvme_tcp_setup_ctrl+0x8b/0x7a0 [nvme_tcp] +[ 286.542254][ C0] ? _raw_spin_unlock_irqrestore+0x4c/0x60 +[ 286.542887][ C0] ? __pfx_nvme_tcp_setup_ctrl+0x10/0x10 [nvme_tcp] +[ 286.543568][ C0] ? trace_hardirqs_on+0x12/0x120 +[ 286.544166][ C0] ? _raw_spin_unlock_irqrestore+0x35/0x60 +[ 286.544792][ C0] ? nvme_change_ctrl_state+0x196/0x2e0 [nvme_core] +[ 286.545477][ C0] nvme_tcp_create_ctrl+0x839/0xb90 [nvme_tcp] +[ 286.546126][ C0] nvmf_dev_write+0x3db/0x7e0 [nvme_fabrics] +[ 286.546775][ C0] ? rw_verify_area+0x69/0x520 +[ 286.547334][ C0] vfs_write+0x218/0xe90 +[ 286.547854][ C0] ? do_syscall_64+0x9f/0x190 +[ 286.548408][ C0] ? trace_hardirqs_on_prepare+0xdb/0x120 +[ 286.549037][ C0] ? syscall_exit_to_user_mode+0x93/0x280 +[ 286.549659][ C0] ? __pfx_vfs_write+0x10/0x10 +[ 286.550259][ C0] ? do_syscall_64+0x9f/0x190 +[ 286.550840][ C0] ? syscall_exit_to_user_mode+0x8e/0x280 +[ 286.551516][ C0] ? trace_hardirqs_on_prepare+0xdb/0x120 +[ 286.552180][ C0] ? syscall_exit_to_user_mode+0x93/0x280 +[ 286.552834][ C0] ? ksys_read+0xf5/0x1c0 +[ 286.553386][ C0] ? __pfx_ksys_read+0x10/0x10 +[ 286.553964][ C0] ksys_write+0xf5/0x1c0 +[ 286.554499][ C0] ? __pfx_ksys_write+0x10/0x10 +[ 286.555072][ C0] ? trace_hardirqs_on_prepare+0xdb/0x120 +[ 286.555698][ C0] ? syscall_exit_to_user_mode+0x93/0x280 +[ 286.556319][ C0] ? do_syscall_64+0x54/0x190 +[ 286.556866][ C0] do_syscall_64+0x93/0x190 +[ 286.557420][ C0] ? rcu_read_unlock+0x17/0x60 +[ 286.557986][ C0] ? rcu_is_watching+0x11/0xb0 +[ 286.558526][ C0] ? lock_release+0x217/0x2c0 +[ 286.559087][ C0] ? rcu_is_watching+0x11/0xb0 +[ 286.559659][ C0] ? count_memcg_events.constprop.0+0x4a/0x60 +[ 286.560476][ C0] ? exc_page_fault+0x7a/0x110 +[ 286.561064][ C0] ? rcu_is_watching+0x11/0xb0 +[ 286.561647][ C0] ? lock_release+0x217/0x2c0 +[ 286.562257][ C0] ? do_user_addr_fault+0x171/0xa00 +[ 286.562839][ C0] ? do_user_addr_fault+0x4a2/0xa00 +[ 286.563453][ C0] ? irqentry_exit_to_user_mode+0x84/0x270 +[ 286.564112][ C0] ? rcu_is_watching+0x11/0xb0 +[ 286.564677][ C0] ? irqentry_exit_to_user_mode+0x84/0x270 +[ 286.565317][ C0] ? trace_hardirqs_on_prepare+0xdb/0x120 +[ 286.565922][ C0] entry_SYSCALL_64_after_hwframe+0x76/0x7e +[ 286.566542][ C0] RIP: 0033:0x7fe3c05e6504 +[ 286.567102][ C0] Code: c7 00 16 00 00 00 b8 ff ff ff ff c3 66 2e 0f 1f 84 00 00 00 00 00 f3 0f 1e fa 80 3d c5 8b 10 00 00 74 13 b8 01 00 00 00 0f 05 <48> 3d 00 f0 ff ff 77 54 c3 0f 1f 00 55 48 89 e5 48 83 ec 20 48 89 +[ 286.568931][ C0] RSP: 002b:00007fff76444f58 EFLAGS: 00000202 ORIG_RAX: 0000000000000001 +[ 286.569807][ C0] RAX: ffffffffffffffda RBX: 000000003b40d930 RCX: 00007fe3c05e6504 +[ 286.570621][ C0] RDX: 00000000000000cf RSI: 000000003b40d930 RDI: 0000000000000003 +[ 286.571443][ C0] RBP: 0000000000000003 R08: 00000000000000cf R09: 000000003b40d930 +[ 286.572246][ C0] R10: 0000000000000000 R11: 0000000000000202 R12: 000000003b40cd60 +[ 286.573069][ C0] R13: 00000000000000cf R14: 00007fe3c07417f8 R15: 00007fe3c073502e +[ 286.573886][ C0] + +Closes: https://lore.kernel.org/linux-nvme/5hdonndzoqa265oq3bj6iarwtfk5dewxxjtbjvn5uqnwclpwt6@a2n6w3taxxex/ +Signed-off-by: Alistair Francis +Reviewed-by: Sagi Grimberg +Tested-by: Shin'ichiro Kawasaki +Signed-off-by: Christoph Hellwig +Signed-off-by: Sasha Levin +--- + drivers/nvme/target/tcp.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/nvme/target/tcp.c b/drivers/nvme/target/tcp.c +index 4f9cac8a5abe0..259ad77c03c50 100644 +--- a/drivers/nvme/target/tcp.c ++++ b/drivers/nvme/target/tcp.c +@@ -1560,6 +1560,9 @@ static void nvmet_tcp_restore_socket_callbacks(struct nvmet_tcp_queue *queue) + { + struct socket *sock = queue->sock; + ++ if (!queue->state_change) ++ return; ++ + write_lock_bh(&sock->sk->sk_callback_lock); + sock->sk->sk_data_ready = queue->data_ready; + sock->sk->sk_state_change = queue->state_change; +-- +2.39.5 + diff --git a/queue-6.14/objtool-fix-error-handling-inconsistencies-in-check.patch b/queue-6.14/objtool-fix-error-handling-inconsistencies-in-check.patch new file mode 100644 index 0000000000..1547922175 --- /dev/null +++ b/queue-6.14/objtool-fix-error-handling-inconsistencies-in-check.patch @@ -0,0 +1,67 @@ +From 8c5fc31078ea90f0d8b57af1b352fd5119c4fd1d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 14 Mar 2025 12:29:00 -0700 +Subject: objtool: Fix error handling inconsistencies in check() + +From: Josh Poimboeuf + +[ Upstream commit b745962cb97569aad026806bb0740663cf813147 ] + +Make sure all fatal errors are funneled through the 'out' label with a +negative ret. + +Signed-off-by: Josh Poimboeuf +Signed-off-by: Peter Zijlstra (Intel) +Reviewed-by: Brendan Jackman +Link: https://lore.kernel.org/r/0f49d6a27a080b4012e84e6df1e23097f44cc082.1741975349.git.jpoimboe@kernel.org +Signed-off-by: Sasha Levin +--- + tools/objtool/check.c | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +diff --git a/tools/objtool/check.c b/tools/objtool/check.c +index 522ae26f581be..70f5b3fa587c5 100644 +--- a/tools/objtool/check.c ++++ b/tools/objtool/check.c +@@ -4633,8 +4633,10 @@ int check(struct objtool_file *file) + init_cfi_state(&force_undefined_cfi); + force_undefined_cfi.force_undefined = true; + +- if (!cfi_hash_alloc(1UL << (file->elf->symbol_bits - 3))) ++ if (!cfi_hash_alloc(1UL << (file->elf->symbol_bits - 3))) { ++ ret = -1; + goto out; ++ } + + cfi_hash_add(&init_cfi); + cfi_hash_add(&func_cfi); +@@ -4651,7 +4653,7 @@ int check(struct objtool_file *file) + if (opts.retpoline) { + ret = validate_retpoline(file); + if (ret < 0) +- return ret; ++ goto out; + warnings += ret; + } + +@@ -4687,7 +4689,7 @@ int check(struct objtool_file *file) + */ + ret = validate_unrets(file); + if (ret < 0) +- return ret; ++ goto out; + warnings += ret; + } + +@@ -4750,7 +4752,7 @@ int check(struct objtool_file *file) + if (opts.prefix) { + ret = add_prefix_symbols(file); + if (ret < 0) +- return ret; ++ goto out; + warnings += ret; + } + +-- +2.39.5 + diff --git a/queue-6.14/objtool-properly-disable-uaccess-validation.patch b/queue-6.14/objtool-properly-disable-uaccess-validation.patch new file mode 100644 index 0000000000..542c06a08b --- /dev/null +++ b/queue-6.14/objtool-properly-disable-uaccess-validation.patch @@ -0,0 +1,68 @@ +From 110b1fc10c00543d827ba11ed739f1b44c72d50b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 24 Mar 2025 14:55:58 -0700 +Subject: objtool: Properly disable uaccess validation + +From: Josh Poimboeuf + +[ Upstream commit e1a9dda74dbffbc3fa2069ff418a1876dc99fb14 ] + +If opts.uaccess isn't set, the uaccess validation is disabled, but only +partially: it doesn't read the uaccess_safe_builtin list but still tries +to do the validation. Disable it completely to prevent false warnings. + +Signed-off-by: Josh Poimboeuf +Signed-off-by: Ingo Molnar +Cc: Linus Torvalds +Link: https://lore.kernel.org/r/0e95581c1d2107fb5f59418edf2b26bba38b0cbb.1742852846.git.jpoimboe@kernel.org +Signed-off-by: Sasha Levin +--- + tools/objtool/check.c | 11 +++++++++-- + 1 file changed, 9 insertions(+), 2 deletions(-) + +diff --git a/tools/objtool/check.c b/tools/objtool/check.c +index a7dcf2d00ab65..522ae26f581be 100644 +--- a/tools/objtool/check.c ++++ b/tools/objtool/check.c +@@ -3209,7 +3209,7 @@ static int handle_insn_ops(struct instruction *insn, + if (update_cfi_state(insn, next_insn, &state->cfi, op)) + return 1; + +- if (!insn->alt_group) ++ if (!opts.uaccess || !insn->alt_group) + continue; + + if (op->dest.type == OP_DEST_PUSHF) { +@@ -3676,6 +3676,9 @@ static int validate_branch(struct objtool_file *file, struct symbol *func, + return 0; + + case INSN_STAC: ++ if (!opts.uaccess) ++ break; ++ + if (state.uaccess) { + WARN_INSN(insn, "recursive UACCESS enable"); + return 1; +@@ -3685,6 +3688,9 @@ static int validate_branch(struct objtool_file *file, struct symbol *func, + break; + + case INSN_CLAC: ++ if (!opts.uaccess) ++ break; ++ + if (!state.uaccess && func) { + WARN_INSN(insn, "redundant UACCESS disable"); + return 1; +@@ -4160,7 +4166,8 @@ static int validate_symbol(struct objtool_file *file, struct section *sec, + if (!insn || insn->ignore || insn->visited) + return 0; + +- state->uaccess = sym->uaccess_safe; ++ if (opts.uaccess) ++ state->uaccess = sym->uaccess_safe; + + ret = validate_branch(file, insn_func(insn), insn, *state); + if (ret) +-- +2.39.5 + diff --git a/queue-6.14/octeontx2-af-rpm-register-driver-with-pci-subsys-ids.patch b/queue-6.14/octeontx2-af-rpm-register-driver-with-pci-subsys-ids.patch new file mode 100644 index 0000000000..fffeb65586 --- /dev/null +++ b/queue-6.14/octeontx2-af-rpm-register-driver-with-pci-subsys-ids.patch @@ -0,0 +1,67 @@ +From 7c7472a0e17f7f613f9ee3a5260a0be5ac74722d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 24 Feb 2025 09:26:03 +0530 +Subject: Octeontx2-af: RPM: Register driver with PCI subsys IDs + +From: Hariprasad Kelam + +[ Upstream commit fc9167192f29485be5621e2e9c8208b717b65753 ] + +Although the PCI device ID and Vendor ID for the RPM (MAC) block +have remained the same across Octeon CN10K and the next-generation +CN20K silicon, Hardware architecture has changed (NIX mapped RPMs +and RFOE Mapped RPMs). + +Add PCI Subsystem IDs to the device table to ensure that this driver +can be probed from NIX mapped RPM devices only. + +Signed-off-by: Hariprasad Kelam +Link: https://patch.msgid.link/20250224035603.1220913-1-hkelam@marvell.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/marvell/octeontx2/af/cgx.c | 14 ++++++++++++-- + drivers/net/ethernet/marvell/octeontx2/af/rvu.h | 2 ++ + 2 files changed, 14 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/marvell/octeontx2/af/cgx.c b/drivers/net/ethernet/marvell/octeontx2/af/cgx.c +index e43c4608d3ba3..971993586fb49 100644 +--- a/drivers/net/ethernet/marvell/octeontx2/af/cgx.c ++++ b/drivers/net/ethernet/marvell/octeontx2/af/cgx.c +@@ -66,8 +66,18 @@ static int cgx_fwi_link_change(struct cgx *cgx, int lmac_id, bool en); + /* Supported devices */ + static const struct pci_device_id cgx_id_table[] = { + { PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, PCI_DEVID_OCTEONTX2_CGX) }, +- { PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, PCI_DEVID_CN10K_RPM) }, +- { PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, PCI_DEVID_CN10KB_RPM) }, ++ { PCI_DEVICE_SUB(PCI_VENDOR_ID_CAVIUM, PCI_DEVID_CN10K_RPM, ++ PCI_ANY_ID, PCI_SUBSYS_DEVID_CN10K_A) }, ++ { PCI_DEVICE_SUB(PCI_VENDOR_ID_CAVIUM, PCI_DEVID_CN10K_RPM, ++ PCI_ANY_ID, PCI_SUBSYS_DEVID_CNF10K_A) }, ++ { PCI_DEVICE_SUB(PCI_VENDOR_ID_CAVIUM, PCI_DEVID_CN10K_RPM, ++ PCI_ANY_ID, PCI_SUBSYS_DEVID_CNF10K_B) }, ++ { PCI_DEVICE_SUB(PCI_VENDOR_ID_CAVIUM, PCI_DEVID_CN10KB_RPM, ++ PCI_ANY_ID, PCI_SUBSYS_DEVID_CN10K_B) }, ++ { PCI_DEVICE_SUB(PCI_VENDOR_ID_CAVIUM, PCI_DEVID_CN10KB_RPM, ++ PCI_ANY_ID, PCI_SUBSYS_DEVID_CN20KA) }, ++ { PCI_DEVICE_SUB(PCI_VENDOR_ID_CAVIUM, PCI_DEVID_CN10KB_RPM, ++ PCI_ANY_ID, PCI_SUBSYS_DEVID_CNF20KA) }, + { 0, } /* end of table */ + }; + +diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu.h b/drivers/net/ethernet/marvell/octeontx2/af/rvu.h +index a383b5ef5b2d8..60f085b00a8cc 100644 +--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu.h ++++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu.h +@@ -30,6 +30,8 @@ + #define PCI_SUBSYS_DEVID_CNF10K_A 0xBA00 + #define PCI_SUBSYS_DEVID_CNF10K_B 0xBC00 + #define PCI_SUBSYS_DEVID_CN10K_B 0xBD00 ++#define PCI_SUBSYS_DEVID_CN20KA 0xC220 ++#define PCI_SUBSYS_DEVID_CNF20KA 0xC320 + + /* PCI BAR nos */ + #define PCI_AF_REG_BAR_NUM 0 +-- +2.39.5 + diff --git a/queue-6.14/orangefs-do-not-truncate-file-size.patch b/queue-6.14/orangefs-do-not-truncate-file-size.patch new file mode 100644 index 0000000000..eb357894b0 --- /dev/null +++ b/queue-6.14/orangefs-do-not-truncate-file-size.patch @@ -0,0 +1,50 @@ +From bd50263d29bd1d2cc7804570957f59ac87a60aab Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Mar 2025 20:47:25 +0000 +Subject: orangefs: Do not truncate file size + +From: Matthew Wilcox (Oracle) + +[ Upstream commit 062e8093592fb866b8e016641a8b27feb6ac509d ] + +'len' is used to store the result of i_size_read(), so making 'len' +a size_t results in truncation to 4GiB on 32-bit systems. + +Signed-off-by: "Matthew Wilcox (Oracle)" +Link: https://lore.kernel.org/r/20250305204734.1475264-2-willy@infradead.org +Tested-by: Mike Marshall +Signed-off-by: Christian Brauner +Signed-off-by: Sasha Levin +--- + fs/orangefs/inode.c | 7 +++---- + 1 file changed, 3 insertions(+), 4 deletions(-) + +diff --git a/fs/orangefs/inode.c b/fs/orangefs/inode.c +index aae6d2b8767df..63d7c1ca0dfd3 100644 +--- a/fs/orangefs/inode.c ++++ b/fs/orangefs/inode.c +@@ -23,9 +23,9 @@ static int orangefs_writepage_locked(struct page *page, + struct orangefs_write_range *wr = NULL; + struct iov_iter iter; + struct bio_vec bv; +- size_t len, wlen; ++ size_t wlen; + ssize_t ret; +- loff_t off; ++ loff_t len, off; + + set_page_writeback(page); + +@@ -91,8 +91,7 @@ static int orangefs_writepages_work(struct orangefs_writepages *ow, + struct orangefs_write_range *wrp, wr; + struct iov_iter iter; + ssize_t ret; +- size_t len; +- loff_t off; ++ loff_t len, off; + int i; + + len = i_size_read(inode); +-- +2.39.5 + diff --git a/queue-6.14/pci-brcmstb-add-a-softdep-to-mip-msi-x-driver.patch b/queue-6.14/pci-brcmstb-add-a-softdep-to-mip-msi-x-driver.patch new file mode 100644 index 0000000000..737401a115 --- /dev/null +++ b/queue-6.14/pci-brcmstb-add-a-softdep-to-mip-msi-x-driver.patch @@ -0,0 +1,41 @@ +From e4243d31cf3079f0b67dcdd4e50c2b586e50fb28 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 24 Feb 2025 10:35:56 +0200 +Subject: PCI: brcmstb: Add a softdep to MIP MSI-X driver +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Stanimir Varbanov + +[ Upstream commit 2294059118c550464dd8906286324d90c33b152b ] + +Then the brcmstb PCIe driver and MIP MSI-X interrupt controller +drivers are built as modules there could be a race in probing. + +To avoid this, add a softdep to MIP driver to guarantee that +MIP driver will be load first. + +Signed-off-by: Stanimir Varbanov +Reviewed-by: Florian Fainelli +Tested-by: Ivan T. Ivanov +Link: https://lore.kernel.org/r/20250224083559.47645-5-svarbanov@suse.de +[kwilczynski: commit log] +Signed-off-by: Krzysztof Wilczyński +Signed-off-by: Sasha Levin +--- + drivers/pci/controller/pcie-brcmstb.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/pci/controller/pcie-brcmstb.c b/drivers/pci/controller/pcie-brcmstb.c +index ff217a0b80ad3..bae226c779a50 100644 +--- a/drivers/pci/controller/pcie-brcmstb.c ++++ b/drivers/pci/controller/pcie-brcmstb.c +@@ -1947,3 +1947,4 @@ module_platform_driver(brcm_pcie_driver); + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("Broadcom STB PCIe RC driver"); + MODULE_AUTHOR("Broadcom"); ++MODULE_SOFTDEP("pre: irq_bcm2712_mip"); +-- +2.39.5 + diff --git a/queue-6.14/pci-brcmstb-expand-inbound-window-size-up-to-64gb.patch b/queue-6.14/pci-brcmstb-expand-inbound-window-size-up-to-64gb.patch new file mode 100644 index 0000000000..1229c2a7c9 --- /dev/null +++ b/queue-6.14/pci-brcmstb-expand-inbound-window-size-up-to-64gb.patch @@ -0,0 +1,48 @@ +From 844b5ac3b277a8104143d152ad3fcbd0e055ec1e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 24 Feb 2025 10:35:58 +0200 +Subject: PCI: brcmstb: Expand inbound window size up to 64GB +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Stanimir Varbanov + +[ Upstream commit 25a98c727015638baffcfa236e3f37b70cedcf87 ] + +The BCM2712 memory map can support up to 64GB of system memory, thus +expand the inbound window size in calculation helper function. + +The change is safe for the currently supported SoCs that have smaller +inbound window sizes. + +Signed-off-by: Stanimir Varbanov +Reviewed-by: Florian Fainelli +Reviewed-by: Jim Quinlan +Tested-by: Ivan T. Ivanov +Link: https://lore.kernel.org/r/20250224083559.47645-7-svarbanov@suse.de +[kwilczynski: commit log] +Signed-off-by: Krzysztof Wilczyński +Signed-off-by: Sasha Levin +--- + drivers/pci/controller/pcie-brcmstb.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/pci/controller/pcie-brcmstb.c b/drivers/pci/controller/pcie-brcmstb.c +index 1a3bdc01b0747..ff217a0b80ad3 100644 +--- a/drivers/pci/controller/pcie-brcmstb.c ++++ b/drivers/pci/controller/pcie-brcmstb.c +@@ -309,8 +309,8 @@ static int brcm_pcie_encode_ibar_size(u64 size) + if (log2_in >= 12 && log2_in <= 15) + /* Covers 4KB to 32KB (inclusive) */ + return (log2_in - 12) + 0x1c; +- else if (log2_in >= 16 && log2_in <= 35) +- /* Covers 64KB to 32GB, (inclusive) */ ++ else if (log2_in >= 16 && log2_in <= 36) ++ /* Covers 64KB to 64GB, (inclusive) */ + return log2_in - 15; + /* Something is awry so disable */ + return 0; +-- +2.39.5 + diff --git a/queue-6.14/pci-dwc-ep-ensure-proper-iteration-over-outbound-map.patch b/queue-6.14/pci-dwc-ep-ensure-proper-iteration-over-outbound-map.patch new file mode 100644 index 0000000000..2745da281f --- /dev/null +++ b/queue-6.14/pci-dwc-ep-ensure-proper-iteration-over-outbound-map.patch @@ -0,0 +1,45 @@ +From ac6857755f3ae8e38c6ec0f31e055602598afea0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 15 Mar 2025 15:15:46 -0500 +Subject: PCI: dwc: ep: Ensure proper iteration over outbound map windows + +From: Frank Li + +[ Upstream commit f3e1dccba0a0833fc9a05fb838ebeb6ea4ca0e1a ] + +Most systems' PCIe outbound map windows have non-zero physical addresses, +but the possibility of encountering zero increased after following commit +("PCI: dwc: Use parent_bus_offset"). + +'ep->outbound_addr[n]', representing 'parent_bus_address', might be 0 on +some hardware, which trims high address bits through bus fabric before +sending to the PCIe controller. + +Replace the iteration logic with 'for_each_set_bit()' to ensure only +allocated map windows are iterated when determining the ATU index from a +given address. + +Link: https://lore.kernel.org/r/20250315201548.858189-12-helgaas@kernel.org +Signed-off-by: Frank Li +Signed-off-by: Bjorn Helgaas +Signed-off-by: Sasha Levin +--- + drivers/pci/controller/dwc/pcie-designware-ep.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/pci/controller/dwc/pcie-designware-ep.c b/drivers/pci/controller/dwc/pcie-designware-ep.c +index e41479a9ca027..c91d095024689 100644 +--- a/drivers/pci/controller/dwc/pcie-designware-ep.c ++++ b/drivers/pci/controller/dwc/pcie-designware-ep.c +@@ -282,7 +282,7 @@ static int dw_pcie_find_index(struct dw_pcie_ep *ep, phys_addr_t addr, + u32 index; + struct dw_pcie *pci = to_dw_pcie_from_ep(ep); + +- for (index = 0; index < pci->num_ob_windows; index++) { ++ for_each_set_bit(index, ep->ob_window_map, pci->num_ob_windows) { + if (ep->outbound_addr[index] != addr) + continue; + *atu_index = index; +-- +2.39.5 + diff --git a/queue-6.14/pci-dwc-use-resource-start-as-ioremap-input-in-dw_pc.patch b/queue-6.14/pci-dwc-use-resource-start-as-ioremap-input-in-dw_pc.patch new file mode 100644 index 0000000000..41d236c1e9 --- /dev/null +++ b/queue-6.14/pci-dwc-use-resource-start-as-ioremap-input-in-dw_pc.patch @@ -0,0 +1,46 @@ +From 8108cc60f1fa7f21eab45ac23f33a8f9898e5714 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 15 Mar 2025 15:15:36 -0500 +Subject: PCI: dwc: Use resource start as ioremap() input in + dw_pcie_pme_turn_off() + +From: Frank Li + +[ Upstream commit 8f4a489b370e6612700aa16b9e4373b2d85d7503 ] + +The msg_res region translates writes into PCIe Message TLPs. Previously we +mapped this region using atu.cpu_addr, the input address programmed into +the ATU. + +"cpu_addr" is a misnomer because when a bus fabric translates addresses +between the CPU and the ATU, the ATU input address is different from the +CPU address. A future patch will rename "cpu_addr" and correct the value +to be the ATU input address instead of the CPU physical address. + +Map the msg_res region before writing to it using the msg_res resource +start, a CPU physical address. + +Link: https://lore.kernel.org/r/20250315201548.858189-2-helgaas@kernel.org +Signed-off-by: Frank Li +Signed-off-by: Bjorn Helgaas +Signed-off-by: Sasha Levin +--- + drivers/pci/controller/dwc/pcie-designware-host.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c b/drivers/pci/controller/dwc/pcie-designware-host.c +index ffaded8f2df7b..ae3fd2a5dbf85 100644 +--- a/drivers/pci/controller/dwc/pcie-designware-host.c ++++ b/drivers/pci/controller/dwc/pcie-designware-host.c +@@ -908,7 +908,7 @@ static int dw_pcie_pme_turn_off(struct dw_pcie *pci) + if (ret) + return ret; + +- mem = ioremap(atu.cpu_addr, pci->region_align); ++ mem = ioremap(pci->pp.msg_res->start, pci->region_align); + if (!mem) + return -ENOMEM; + +-- +2.39.5 + diff --git a/queue-6.14/pci-endpoint-pci-epf-test-fix-double-free-that-cause.patch b/queue-6.14/pci-endpoint-pci-epf-test-fix-double-free-that-cause.patch new file mode 100644 index 0000000000..064135e3c8 --- /dev/null +++ b/queue-6.14/pci-endpoint-pci-epf-test-fix-double-free-that-cause.patch @@ -0,0 +1,70 @@ +From d7478a4d98e5ee10d49b16779d3c100ec09bbc90 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 24 Jan 2025 13:30:43 +0100 +Subject: PCI: endpoint: pci-epf-test: Fix double free that causes kernel to + oops +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Christian Bruel + +[ Upstream commit 934e9d137d937706004c325fa1474f9e3f1ba10a ] + +Fix a kernel oops found while testing the stm32_pcie Endpoint driver +with handling of PERST# deassertion: + +During EP initialization, pci_epf_test_alloc_space() allocates all BARs, +which are further freed if epc_set_bar() fails (for instance, due to no +free inbound window). + +However, when pci_epc_set_bar() fails, the error path: + + pci_epc_set_bar() -> + pci_epf_free_space() + +does not clear the previous assignment to epf_test->reg[bar]. + +Then, if the host reboots, the PERST# deassertion restarts the BAR +allocation sequence with the same allocation failure (no free inbound +window), creating a double free situation since epf_test->reg[bar] was +deallocated and is still non-NULL. + +Thus, make sure that pci_epf_alloc_space() and pci_epf_free_space() +invocations are symmetric, and as such, set epf_test->reg[bar] to NULL +when memory is freed. + +Reviewed-by: Niklas Cassel +Reviewed-by: Manivannan Sadhasivam +Signed-off-by: Christian Bruel +Link: https://lore.kernel.org/r/20250124123043.96112-1-christian.bruel@foss.st.com +[kwilczynski: commit log] +Signed-off-by: Krzysztof Wilczyński +Signed-off-by: Sasha Levin +--- + drivers/pci/endpoint/functions/pci-epf-test.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/pci/endpoint/functions/pci-epf-test.c b/drivers/pci/endpoint/functions/pci-epf-test.c +index 2409787cf56d9..bce3ae2c0f652 100644 +--- a/drivers/pci/endpoint/functions/pci-epf-test.c ++++ b/drivers/pci/endpoint/functions/pci-epf-test.c +@@ -738,6 +738,7 @@ static int pci_epf_test_set_bar(struct pci_epf *epf) + if (ret) { + pci_epf_free_space(epf, epf_test->reg[bar], bar, + PRIMARY_INTERFACE); ++ epf_test->reg[bar] = NULL; + dev_err(dev, "Failed to set BAR%d\n", bar); + if (bar == test_reg_bar) + return ret; +@@ -929,6 +930,7 @@ static void pci_epf_test_free_space(struct pci_epf *epf) + + pci_epf_free_space(epf, epf_test->reg[bar], bar, + PRIMARY_INTERFACE); ++ epf_test->reg[bar] = NULL; + } + } + +-- +2.39.5 + diff --git a/queue-6.14/pci-epf-mhi-update-device-id-for-sa8775p.patch b/queue-6.14/pci-epf-mhi-update-device-id-for-sa8775p.patch new file mode 100644 index 0000000000..e83fa7f7de --- /dev/null +++ b/queue-6.14/pci-epf-mhi-update-device-id-for-sa8775p.patch @@ -0,0 +1,39 @@ +From e07b054b70c6932ae139698a8660be2f44c8e78a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 5 Dec 2024 12:24:20 +0530 +Subject: PCI: epf-mhi: Update device ID for SA8775P +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Mrinmay Sarkar + +[ Upstream commit 4f13dd9e2b1d2b317bb36704f8a7bd1d3017f7a2 ] + +Update device ID for the Qcom SA8775P SoC. + +Signed-off-by: Mrinmay Sarkar +Link: https://lore.kernel.org/r/20241205065422.2515086-3-quic_msarkar@quicinc.com +[kwilczynski: commit log] +Signed-off-by: Krzysztof Wilczyński +Signed-off-by: Sasha Levin +--- + drivers/pci/endpoint/functions/pci-epf-mhi.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/pci/endpoint/functions/pci-epf-mhi.c b/drivers/pci/endpoint/functions/pci-epf-mhi.c +index 54286a40bdfbf..6643a88c7a0ce 100644 +--- a/drivers/pci/endpoint/functions/pci-epf-mhi.c ++++ b/drivers/pci/endpoint/functions/pci-epf-mhi.c +@@ -125,7 +125,7 @@ static const struct pci_epf_mhi_ep_info sm8450_info = { + + static struct pci_epf_header sa8775p_header = { + .vendorid = PCI_VENDOR_ID_QCOM, +- .deviceid = 0x0306, /* FIXME: Update deviceid for sa8775p EP */ ++ .deviceid = 0x0116, + .baseclass_code = PCI_CLASS_OTHERS, + .interrupt_pin = PCI_INTERRUPT_INTA, + }; +-- +2.39.5 + diff --git a/queue-6.14/pci-fix-old_size-lower-bound-in-calculate_iosize-too.patch b/queue-6.14/pci-fix-old_size-lower-bound-in-calculate_iosize-too.patch new file mode 100644 index 0000000000..4f59c4f626 --- /dev/null +++ b/queue-6.14/pci-fix-old_size-lower-bound-in-calculate_iosize-too.patch @@ -0,0 +1,48 @@ +From 5c3bb987449ca5bf7a7a674cbe0482d699692ed7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 16 Dec 2024 19:56:12 +0200 +Subject: PCI: Fix old_size lower bound in calculate_iosize() too +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Ilpo Järvinen + +[ Upstream commit ff61f380de5652e723168341480cc7adf1dd6213 ] + +Commit 903534fa7d30 ("PCI: Fix resource double counting on remove & +rescan") fixed double counting of mem resources because of old_size being +applied too early. + +Fix a similar counting bug on the io resource side. + +Link: https://lore.kernel.org/r/20241216175632.4175-6-ilpo.jarvinen@linux.intel.com +Signed-off-by: Ilpo Järvinen +Signed-off-by: Bjorn Helgaas +Tested-by: Xiaochun Lee +Signed-off-by: Sasha Levin +--- + drivers/pci/setup-bus.c | 6 ++---- + 1 file changed, 2 insertions(+), 4 deletions(-) + +diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c +index 8707c5b08cf34..477eb07bfbca9 100644 +--- a/drivers/pci/setup-bus.c ++++ b/drivers/pci/setup-bus.c +@@ -814,11 +814,9 @@ static resource_size_t calculate_iosize(resource_size_t size, + size = (size & 0xff) + ((size & ~0xffUL) << 2); + #endif + size = size + size1; +- if (size < old_size) +- size = old_size; + +- size = ALIGN(max(size, add_size) + children_add_size, align); +- return size; ++ size = max(size, add_size) + children_add_size; ++ return ALIGN(max(size, old_size), align); + } + + static resource_size_t calculate_memsize(resource_size_t size, +-- +2.39.5 + diff --git a/queue-6.14/pci-pwrctrl-move-pci_pwrctrl_unregister-to-pci_destr.patch b/queue-6.14/pci-pwrctrl-move-pci_pwrctrl_unregister-to-pci_destr.patch new file mode 100644 index 0000000000..bce404ccca --- /dev/null +++ b/queue-6.14/pci-pwrctrl-move-pci_pwrctrl_unregister-to-pci_destr.patch @@ -0,0 +1,54 @@ +From 8dbfe01e42616bb68faef98252c74b2ad2f200f5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 16 Jan 2025 19:39:12 +0530 +Subject: PCI/pwrctrl: Move pci_pwrctrl_unregister() to pci_destroy_dev() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Manivannan Sadhasivam + +[ Upstream commit 2d923930f2e3fe1ecf060169f57980da819a191f ] + +The PCI core will try to access the devices even after pci_stop_dev() +for things like Data Object Exchange (DOE), ASPM, etc. + +So, move pci_pwrctrl_unregister() to the near end of pci_destroy_dev() +to make sure that the devices are powered down only after the PCI core +is done with them. + +Suggested-by: Lukas Wunner +Reviewed-by: Lukas Wunner +Tested-by: Bartosz Golaszewski +Signed-off-by: Manivannan Sadhasivam +Link: https://lore.kernel.org/r/20250116-pci-pwrctrl-slot-v3-2-827473c8fbf4@linaro.org +[kwilczynski: commit log] +Signed-off-by: Krzysztof Wilczyński +Signed-off-by: Sasha Levin +--- + drivers/pci/remove.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/pci/remove.c b/drivers/pci/remove.c +index efc37fcb73e24..58859f9d92f73 100644 +--- a/drivers/pci/remove.c ++++ b/drivers/pci/remove.c +@@ -41,7 +41,6 @@ static void pci_stop_dev(struct pci_dev *dev) + if (!pci_dev_test_and_clear_added(dev)) + return; + +- pci_pwrctrl_unregister(&dev->dev); + device_release_driver(&dev->dev); + pci_proc_detach_device(dev); + pci_remove_sysfs_dev_files(dev); +@@ -64,6 +63,7 @@ static void pci_destroy_dev(struct pci_dev *dev) + pci_doe_destroy(dev); + pcie_aspm_exit_link_state(dev); + pci_bridge_d3_update(dev); ++ pci_pwrctrl_unregister(&dev->dev); + pci_free_resources(dev); + put_device(&dev->dev); + } +-- +2.39.5 + diff --git a/queue-6.14/pci-vmd-disable-msi-remapping-bypass-under-xen.patch b/queue-6.14/pci-vmd-disable-msi-remapping-bypass-under-xen.patch new file mode 100644 index 0000000000..3edcb2debc --- /dev/null +++ b/queue-6.14/pci-vmd-disable-msi-remapping-bypass-under-xen.patch @@ -0,0 +1,78 @@ +From a2f79b01e008c0f475e968cf506c35348383b328 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 19 Feb 2025 10:20:56 +0100 +Subject: PCI: vmd: Disable MSI remapping bypass under Xen +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Roger Pau Monne + +[ Upstream commit 6c4d5aadf5df31ea0ac025980670eee9beaf466b ] + +MSI remapping bypass (directly configuring MSI entries for devices on the +VMD bus) won't work under Xen, as Xen is not aware of devices in such bus, +and hence cannot configure the entries using the pIRQ interface in the PV +case, and in the PVH case traps won't be setup for MSI entries for such +devices. + +Until Xen is aware of devices in the VMD bus prevent the +VMD_FEAT_CAN_BYPASS_MSI_REMAP capability from being used when running as +any kind of Xen guest. + +The MSI remapping bypass is an optional feature of VMD bridges, and hence +when running under Xen it will be masked and devices will be forced to +redirect its interrupts from the VMD bridge. That mode of operation must +always be supported by VMD bridges and works when Xen is not aware of +devices behind the VMD bridge. + +Signed-off-by: Roger Pau Monné +Acked-by: Bjorn Helgaas +Message-ID: <20250219092059.90850-3-roger.pau@citrix.com> +Signed-off-by: Juergen Gross +Signed-off-by: Sasha Levin +--- + drivers/pci/controller/vmd.c | 20 ++++++++++++++++++++ + 1 file changed, 20 insertions(+) + +diff --git a/drivers/pci/controller/vmd.c b/drivers/pci/controller/vmd.c +index 94ceec50a2b94..8df064b62a2ff 100644 +--- a/drivers/pci/controller/vmd.c ++++ b/drivers/pci/controller/vmd.c +@@ -17,6 +17,8 @@ + #include + #include + ++#include ++ + #include + + #define VMD_CFGBAR 0 +@@ -970,6 +972,24 @@ static int vmd_probe(struct pci_dev *dev, const struct pci_device_id *id) + struct vmd_dev *vmd; + int err; + ++ if (xen_domain()) { ++ /* ++ * Xen doesn't have knowledge about devices in the VMD bus ++ * because the config space of devices behind the VMD bridge is ++ * not known to Xen, and hence Xen cannot discover or configure ++ * them in any way. ++ * ++ * Bypass of MSI remapping won't work in that case as direct ++ * write by Linux to the MSI entries won't result in functional ++ * interrupts, as Xen is the entity that manages the host ++ * interrupt controller and must configure interrupts. However ++ * multiplexing of interrupts by the VMD bridge will work under ++ * Xen, so force the usage of that mode which must always be ++ * supported by VMD bridges. ++ */ ++ features &= ~VMD_FEAT_CAN_BYPASS_MSI_REMAP; ++ } ++ + if (resource_size(&dev->resource[VMD_CFGBAR]) < (1 << 20)) + return -ENOMEM; + +-- +2.39.5 + diff --git a/queue-6.14/pci-xilinx-cpm-add-cpm_csr-register-mapping-for-cpm5.patch b/queue-6.14/pci-xilinx-cpm-add-cpm_csr-register-mapping-for-cpm5.patch new file mode 100644 index 0000000000..92e8532d02 --- /dev/null +++ b/queue-6.14/pci-xilinx-cpm-add-cpm_csr-register-mapping-for-cpm5.patch @@ -0,0 +1,44 @@ +From 00e35dd69cd5a9e740726e89b57cebae94d365e2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Mar 2025 18:11:36 +0530 +Subject: PCI: xilinx-cpm: Add cpm_csr register mapping for CPM5_HOST1 variant +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Thippeswamy Havalige + +[ Upstream commit 9e141923cf86b2e1c83d21b87fb4de3d14a20c99 ] + +Update the CPM5 check to include CPM5_HOST1 variant. Previously, only +CPM5 was considered when mapping the "cpm_csr" register. + +With this change, CPM5_HOST1 is also supported, ensuring proper +resource mapping for this variant. + +Signed-off-by: Thippeswamy Havalige +[kwilczynski: commit log] +Signed-off-by: Krzysztof Wilczyński +Link: https://lore.kernel.org/r/20250317124136.1317723-1-thippeswamy.havalige@amd.com +Signed-off-by: Sasha Levin +--- + drivers/pci/controller/pcie-xilinx-cpm.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/pci/controller/pcie-xilinx-cpm.c b/drivers/pci/controller/pcie-xilinx-cpm.c +index dc8ecdbee56c8..163d805673d6d 100644 +--- a/drivers/pci/controller/pcie-xilinx-cpm.c ++++ b/drivers/pci/controller/pcie-xilinx-cpm.c +@@ -538,7 +538,8 @@ static int xilinx_cpm_pcie_parse_dt(struct xilinx_cpm_pcie *port, + if (IS_ERR(port->cfg)) + return PTR_ERR(port->cfg); + +- if (port->variant->version == CPM5) { ++ if (port->variant->version == CPM5 || ++ port->variant->version == CPM5_HOST1) { + port->reg_base = devm_platform_ioremap_resource_byname(pdev, + "cpm_csr"); + if (IS_ERR(port->reg_base)) +-- +2.39.5 + diff --git a/queue-6.14/perf-amd-ibs-fix-config-to-sample-period-calculation.patch b/queue-6.14/perf-amd-ibs-fix-config-to-sample-period-calculation.patch new file mode 100644 index 0000000000..6d08819ad2 --- /dev/null +++ b/queue-6.14/perf-amd-ibs-fix-config-to-sample-period-calculation.patch @@ -0,0 +1,74 @@ +From 6101a045693ad3129315a076bfd4721c75e0c533 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 15 Jan 2025 05:44:32 +0000 +Subject: perf/amd/ibs: Fix ->config to sample period calculation for OP PMU + +From: Ravi Bangoria + +[ Upstream commit 598bdf4fefff5af4ce6d26d16f7b2a20808fc4cb ] + +Instead of using standard perf_event_attr->freq=0 and ->sample_period +fields, IBS event in 'sample period mode' can also be opened by setting +period value directly in perf_event_attr->config in a MaxCnt bit-field +format. + +IBS OP MaxCnt bits are defined as: + + (high bits) IbsOpCtl[26:20] = IbsOpMaxCnt[26:20] + (low bits) IbsOpCtl[15:0] = IbsOpMaxCnt[19:4] + +Perf event sample period can be derived from MaxCnt bits as: + + sample_period = (high bits) | ((low_bits) << 4); + +However, current code just masks MaxCnt bits and shifts all of them, +including high bits, which is incorrect. Fix it. + +Signed-off-by: Ravi Bangoria +Signed-off-by: Peter Zijlstra (Intel) +Acked-by: Namhyung Kim +Link: https://lkml.kernel.org/r/20250115054438.1021-4-ravi.bangoria@amd.com +Signed-off-by: Sasha Levin +--- + arch/x86/events/amd/ibs.c | 17 +++++++++++++---- + 1 file changed, 13 insertions(+), 4 deletions(-) + +diff --git a/arch/x86/events/amd/ibs.c b/arch/x86/events/amd/ibs.c +index 5d975c39701cb..58ad23205d59d 100644 +--- a/arch/x86/events/amd/ibs.c ++++ b/arch/x86/events/amd/ibs.c +@@ -274,7 +274,7 @@ static int perf_ibs_init(struct perf_event *event) + { + struct hw_perf_event *hwc = &event->hw; + struct perf_ibs *perf_ibs; +- u64 max_cnt, config; ++ u64 config; + int ret; + + perf_ibs = get_ibs_pmu(event->attr.type); +@@ -321,10 +321,19 @@ static int perf_ibs_init(struct perf_event *event) + if (!hwc->sample_period) + hwc->sample_period = 0x10; + } else { +- max_cnt = config & perf_ibs->cnt_mask; ++ u64 period = 0; ++ ++ if (perf_ibs == &perf_ibs_op) { ++ period = (config & IBS_OP_MAX_CNT) << 4; ++ if (ibs_caps & IBS_CAPS_OPCNTEXT) ++ period |= config & IBS_OP_MAX_CNT_EXT_MASK; ++ } else { ++ period = (config & IBS_FETCH_MAX_CNT) << 4; ++ } ++ + config &= ~perf_ibs->cnt_mask; +- event->attr.sample_period = max_cnt << 4; +- hwc->sample_period = event->attr.sample_period; ++ event->attr.sample_period = period; ++ hwc->sample_period = period; + } + + if (!hwc->sample_period) +-- +2.39.5 + diff --git a/queue-6.14/perf-amd-ibs-fix-perf_ibs_op.cnt_mask-for-curcnt.patch b/queue-6.14/perf-amd-ibs-fix-perf_ibs_op.cnt_mask-for-curcnt.patch new file mode 100644 index 0000000000..f95f136e39 --- /dev/null +++ b/queue-6.14/perf-amd-ibs-fix-perf_ibs_op.cnt_mask-for-curcnt.patch @@ -0,0 +1,63 @@ +From e59057b3746acb661c56170c279b17fef1995e5c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 15 Jan 2025 05:44:33 +0000 +Subject: perf/amd/ibs: Fix perf_ibs_op.cnt_mask for CurCnt + +From: Ravi Bangoria + +[ Upstream commit 46dcf85566170d4528b842bf83ffc350d71771fa ] + +IBS Op uses two counters: MaxCnt and CurCnt. MaxCnt is programmed with +the desired sample period. IBS hw generates sample when CurCnt reaches +to MaxCnt. The size of these counter used to be 20 bits but later they +were extended to 27 bits. The 7 bit extension is indicated by CPUID +Fn8000_001B_EAX[6 / OpCntExt]. + +perf_ibs->cnt_mask variable contains bit masks for MaxCnt and CurCnt. +But IBS driver does not set upper 7 bits of CurCnt in cnt_mask even +when OpCntExt CPUID bit is set. Fix this. + +IBS driver uses cnt_mask[CurCnt] bits only while disabling an event. +Fortunately, CurCnt bits are not read from MSR while re-enabling the +event, instead MaxCnt is programmed with desired period and CurCnt is +set to 0. Hence, we did not see any issues so far. + +Signed-off-by: Ravi Bangoria +Signed-off-by: Peter Zijlstra (Intel) +Acked-by: Namhyung Kim +Link: https://lkml.kernel.org/r/20250115054438.1021-5-ravi.bangoria@amd.com +Signed-off-by: Sasha Levin +--- + arch/x86/events/amd/ibs.c | 3 ++- + arch/x86/include/asm/perf_event.h | 1 + + 2 files changed, 3 insertions(+), 1 deletion(-) + +diff --git a/arch/x86/events/amd/ibs.c b/arch/x86/events/amd/ibs.c +index e36c9c63c97cc..5d975c39701cb 100644 +--- a/arch/x86/events/amd/ibs.c ++++ b/arch/x86/events/amd/ibs.c +@@ -1318,7 +1318,8 @@ static __init int perf_ibs_op_init(void) + if (ibs_caps & IBS_CAPS_OPCNTEXT) { + perf_ibs_op.max_period |= IBS_OP_MAX_CNT_EXT_MASK; + perf_ibs_op.config_mask |= IBS_OP_MAX_CNT_EXT_MASK; +- perf_ibs_op.cnt_mask |= IBS_OP_MAX_CNT_EXT_MASK; ++ perf_ibs_op.cnt_mask |= (IBS_OP_MAX_CNT_EXT_MASK | ++ IBS_OP_CUR_CNT_EXT_MASK); + } + + if (ibs_caps & IBS_CAPS_ZEN4) +diff --git a/arch/x86/include/asm/perf_event.h b/arch/x86/include/asm/perf_event.h +index 0ba8d20f2d1d5..d37c1c32e74b9 100644 +--- a/arch/x86/include/asm/perf_event.h ++++ b/arch/x86/include/asm/perf_event.h +@@ -536,6 +536,7 @@ struct pebs_xmm { + */ + #define IBS_OP_CUR_CNT (0xFFF80ULL<<32) + #define IBS_OP_CUR_CNT_RAND (0x0007FULL<<32) ++#define IBS_OP_CUR_CNT_EXT_MASK (0x7FULL<<52) + #define IBS_OP_CNT_CTL (1ULL<<19) + #define IBS_OP_VAL (1ULL<<18) + #define IBS_OP_ENABLE (1ULL<<17) +-- +2.39.5 + diff --git a/queue-6.14/perf-arm_pmuv3-call-kvm_vcpu_pmu_resync_el0-before-e.patch b/queue-6.14/perf-arm_pmuv3-call-kvm_vcpu_pmu_resync_el0-before-e.patch new file mode 100644 index 0000000000..039d81943d --- /dev/null +++ b/queue-6.14/perf-arm_pmuv3-call-kvm_vcpu_pmu_resync_el0-before-e.patch @@ -0,0 +1,44 @@ +From e3a54607f67db017fbe0214101536a05a825aee5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 18 Feb 2025 14:39:56 -0600 +Subject: perf: arm_pmuv3: Call kvm_vcpu_pmu_resync_el0() before enabling + counters + +From: Rob Herring (Arm) + +[ Upstream commit 04bd15c4cbc3f7bd2399d1baab958c5e738dbfc9 ] + +Counting events related to setup of the PMU is not desired, but +kvm_vcpu_pmu_resync_el0() is called just after the PMU counters have +been enabled. Move the call to before enabling the counters. + +Signed-off-by: Rob Herring (Arm) +Reviewed-by: Anshuman Khandual +Tested-by: James Clark +Link: https://lore.kernel.org/r/20250218-arm-brbe-v19-v20-1-4e9922fc2e8e@kernel.org +Signed-off-by: Will Deacon +Signed-off-by: Sasha Levin +--- + drivers/perf/arm_pmuv3.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/perf/arm_pmuv3.c b/drivers/perf/arm_pmuv3.c +index 0e360feb3432e..9ebc950559c0a 100644 +--- a/drivers/perf/arm_pmuv3.c ++++ b/drivers/perf/arm_pmuv3.c +@@ -825,10 +825,10 @@ static void armv8pmu_start(struct arm_pmu *cpu_pmu) + else + armv8pmu_disable_user_access(); + ++ kvm_vcpu_pmu_resync_el0(); ++ + /* Enable all counters */ + armv8pmu_pmcr_write(armv8pmu_pmcr_read() | ARMV8_PMU_PMCR_E); +- +- kvm_vcpu_pmu_resync_el0(); + } + + static void armv8pmu_stop(struct arm_pmu *cpu_pmu) +-- +2.39.5 + diff --git a/queue-6.14/perf-avoid-the-read-if-the-count-is-already-updated.patch b/queue-6.14/perf-avoid-the-read-if-the-count-is-already-updated.patch new file mode 100644 index 0000000000..8b59a3cc3a --- /dev/null +++ b/queue-6.14/perf-avoid-the-read-if-the-count-is-already-updated.patch @@ -0,0 +1,144 @@ +From f5ec1867499335eeced21c8868f31f27ae804cfb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Jan 2025 07:23:02 -0800 +Subject: perf: Avoid the read if the count is already updated + +From: Peter Zijlstra (Intel) + +[ Upstream commit 8ce939a0fa194939cc1f92dbd8bc1a7806e7d40a ] + +The event may have been updated in the PMU-specific implementation, +e.g., Intel PEBS counters snapshotting. The common code should not +read and overwrite the value. + +The PERF_SAMPLE_READ in the data->sample_type can be used to detect +whether the PMU-specific value is available. If yes, avoid the +pmu->read() in the common code. Add a new flag, skip_read, to track the +case. + +Factor out a perf_pmu_read() to clean up the code. + +Signed-off-by: Peter Zijlstra (Intel) +Signed-off-by: Kan Liang +Signed-off-by: Peter Zijlstra (Intel) +Link: https://lkml.kernel.org/r/20250121152303.3128733-3-kan.liang@linux.intel.com +Signed-off-by: Sasha Levin +--- + include/linux/perf_event.h | 8 +++++++- + kernel/events/core.c | 33 ++++++++++++++++----------------- + kernel/events/ring_buffer.c | 1 + + 3 files changed, 24 insertions(+), 18 deletions(-) + +diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h +index 93ea9c6672f0e..3d5814c6d251c 100644 +--- a/include/linux/perf_event.h ++++ b/include/linux/perf_event.h +@@ -1098,7 +1098,13 @@ struct perf_output_handle { + struct perf_buffer *rb; + unsigned long wakeup; + unsigned long size; +- u64 aux_flags; ++ union { ++ u64 flags; /* perf_output*() */ ++ u64 aux_flags; /* perf_aux_output*() */ ++ struct { ++ u64 skip_read : 1; ++ }; ++ }; + union { + void *addr; + unsigned long head; +diff --git a/kernel/events/core.c b/kernel/events/core.c +index dda1670b3539a..6fa70b3826d0e 100644 +--- a/kernel/events/core.c ++++ b/kernel/events/core.c +@@ -1191,6 +1191,12 @@ static void perf_assert_pmu_disabled(struct pmu *pmu) + WARN_ON_ONCE(*this_cpu_ptr(pmu->pmu_disable_count) == 0); + } + ++static inline void perf_pmu_read(struct perf_event *event) ++{ ++ if (event->state == PERF_EVENT_STATE_ACTIVE) ++ event->pmu->read(event); ++} ++ + static void get_ctx(struct perf_event_context *ctx) + { + refcount_inc(&ctx->refcount); +@@ -3478,8 +3484,7 @@ static void __perf_event_sync_stat(struct perf_event *event, + * we know the event must be on the current CPU, therefore we + * don't need to use it. + */ +- if (event->state == PERF_EVENT_STATE_ACTIVE) +- event->pmu->read(event); ++ perf_pmu_read(event); + + perf_event_update_time(event); + +@@ -4625,15 +4630,8 @@ static void __perf_event_read(void *info) + + pmu->read(event); + +- for_each_sibling_event(sub, event) { +- if (sub->state == PERF_EVENT_STATE_ACTIVE) { +- /* +- * Use sibling's PMU rather than @event's since +- * sibling could be on different (eg: software) PMU. +- */ +- sub->pmu->read(sub); +- } +- } ++ for_each_sibling_event(sub, event) ++ perf_pmu_read(sub); + + data->ret = pmu->commit_txn(pmu); + +@@ -7451,9 +7449,8 @@ static void perf_output_read_group(struct perf_output_handle *handle, + if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING) + values[n++] = running; + +- if ((leader != event) && +- (leader->state == PERF_EVENT_STATE_ACTIVE)) +- leader->pmu->read(leader); ++ if ((leader != event) && !handle->skip_read) ++ perf_pmu_read(leader); + + values[n++] = perf_event_count(leader, self); + if (read_format & PERF_FORMAT_ID) +@@ -7466,9 +7463,8 @@ static void perf_output_read_group(struct perf_output_handle *handle, + for_each_sibling_event(sub, leader) { + n = 0; + +- if ((sub != event) && +- (sub->state == PERF_EVENT_STATE_ACTIVE)) +- sub->pmu->read(sub); ++ if ((sub != event) && !handle->skip_read) ++ perf_pmu_read(sub); + + values[n++] = perf_event_count(sub, self); + if (read_format & PERF_FORMAT_ID) +@@ -7527,6 +7523,9 @@ void perf_output_sample(struct perf_output_handle *handle, + { + u64 sample_type = data->type; + ++ if (data->sample_flags & PERF_SAMPLE_READ) ++ handle->skip_read = 1; ++ + perf_output_put(handle, *header); + + if (sample_type & PERF_SAMPLE_IDENTIFIER) +diff --git a/kernel/events/ring_buffer.c b/kernel/events/ring_buffer.c +index 09459647cb822..5130b119d0ae0 100644 +--- a/kernel/events/ring_buffer.c ++++ b/kernel/events/ring_buffer.c +@@ -185,6 +185,7 @@ __perf_output_begin(struct perf_output_handle *handle, + + handle->rb = rb; + handle->event = event; ++ handle->flags = 0; + + have_lost = local_read(&rb->lost); + if (unlikely(have_lost)) { +-- +2.39.5 + diff --git a/queue-6.14/perf-core-clean-up-perf_try_init_event.patch b/queue-6.14/perf-core-clean-up-perf_try_init_event.patch new file mode 100644 index 0000000000..1fb7cc1ab3 --- /dev/null +++ b/queue-6.14/perf-core-clean-up-perf_try_init_event.patch @@ -0,0 +1,107 @@ +From 8f118752248d31e353d89737e9e059b0987f2d80 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Feb 2025 11:21:28 +0100 +Subject: perf/core: Clean up perf_try_init_event() + +From: Peter Zijlstra + +[ Upstream commit da02f54e81db2f7bf6af9d1d0cfc5b41ec6d0dcb ] + +Make sure that perf_try_init_event() doesn't leave event->pmu nor +event->destroy set on failure. + +Signed-off-by: Peter Zijlstra (Intel) +Signed-off-by: Ingo Molnar +Acked-by: Ravi Bangoria +Link: https://lore.kernel.org/r/20250205102449.110145835@infradead.org +Signed-off-by: Sasha Levin +--- + kernel/events/core.c | 65 ++++++++++++++++++++++++++------------------ + 1 file changed, 38 insertions(+), 27 deletions(-) + +diff --git a/kernel/events/core.c b/kernel/events/core.c +index 93ce810384c92..de838d3819ca7 100644 +--- a/kernel/events/core.c ++++ b/kernel/events/core.c +@@ -12020,40 +12020,51 @@ static int perf_try_init_event(struct pmu *pmu, struct perf_event *event) + if (ctx) + perf_event_ctx_unlock(event->group_leader, ctx); + +- if (!ret) { +- if (!(pmu->capabilities & PERF_PMU_CAP_EXTENDED_REGS) && +- has_extended_regs(event)) +- ret = -EOPNOTSUPP; ++ if (ret) ++ goto err_pmu; + +- if (pmu->capabilities & PERF_PMU_CAP_NO_EXCLUDE && +- event_has_any_exclude_flag(event)) +- ret = -EINVAL; ++ if (!(pmu->capabilities & PERF_PMU_CAP_EXTENDED_REGS) && ++ has_extended_regs(event)) { ++ ret = -EOPNOTSUPP; ++ goto err_destroy; ++ } + +- if (pmu->scope != PERF_PMU_SCOPE_NONE && event->cpu >= 0) { +- const struct cpumask *cpumask = perf_scope_cpu_topology_cpumask(pmu->scope, event->cpu); +- struct cpumask *pmu_cpumask = perf_scope_cpumask(pmu->scope); +- int cpu; +- +- if (pmu_cpumask && cpumask) { +- cpu = cpumask_any_and(pmu_cpumask, cpumask); +- if (cpu >= nr_cpu_ids) +- ret = -ENODEV; +- else +- event->event_caps |= PERF_EV_CAP_READ_SCOPE; +- } else { +- ret = -ENODEV; +- } +- } ++ if (pmu->capabilities & PERF_PMU_CAP_NO_EXCLUDE && ++ event_has_any_exclude_flag(event)) { ++ ret = -EINVAL; ++ goto err_destroy; ++ } + +- if (ret && event->destroy) +- event->destroy(event); ++ if (pmu->scope != PERF_PMU_SCOPE_NONE && event->cpu >= 0) { ++ const struct cpumask *cpumask; ++ struct cpumask *pmu_cpumask; ++ int cpu; ++ ++ cpumask = perf_scope_cpu_topology_cpumask(pmu->scope, event->cpu); ++ pmu_cpumask = perf_scope_cpumask(pmu->scope); ++ ++ ret = -ENODEV; ++ if (!pmu_cpumask || !cpumask) ++ goto err_destroy; ++ ++ cpu = cpumask_any_and(pmu_cpumask, cpumask); ++ if (cpu >= nr_cpu_ids) ++ goto err_destroy; ++ ++ event->event_caps |= PERF_EV_CAP_READ_SCOPE; + } + +- if (ret) { +- event->pmu = NULL; +- module_put(pmu->module); ++ return 0; ++ ++err_destroy: ++ if (event->destroy) { ++ event->destroy(event); ++ event->destroy = NULL; + } + ++err_pmu: ++ event->pmu = NULL; ++ module_put(pmu->module); + return ret; + } + +-- +2.39.5 + diff --git a/queue-6.14/perf-core-fix-perf_mmap-failure-path.patch b/queue-6.14/perf-core-fix-perf_mmap-failure-path.patch new file mode 100644 index 0000000000..9497820fba --- /dev/null +++ b/queue-6.14/perf-core-fix-perf_mmap-failure-path.patch @@ -0,0 +1,37 @@ +From b123b565967bb53f1fc3f958942e885579db6071 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 4 Nov 2024 14:39:24 +0100 +Subject: perf/core: Fix perf_mmap() failure path + +From: Peter Zijlstra + +[ Upstream commit 66477c7230eb1f9b90deb8c0f4da2bac2053c329 ] + +When f_ops->mmap() returns failure, m_ops->close() is *not* called. + +Signed-off-by: Peter Zijlstra (Intel) +Signed-off-by: Ingo Molnar +Acked-by: Lorenzo Stoakes +Reviewed-by: Ravi Bangoria +Link: https://lore.kernel.org/r/20241104135519.248358497@infradead.org +Signed-off-by: Sasha Levin +--- + kernel/events/core.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/kernel/events/core.c b/kernel/events/core.c +index de838d3819ca7..dda1670b3539a 100644 +--- a/kernel/events/core.c ++++ b/kernel/events/core.c +@@ -6834,7 +6834,7 @@ static int perf_mmap(struct file *file, struct vm_area_struct *vma) + if (!ret) + ret = map_range(rb, vma); + +- if (event->pmu->event_mapped) ++ if (!ret && event->pmu->event_mapped) + event->pmu->event_mapped(event, vma->vm_mm); + + return ret; +-- +2.39.5 + diff --git a/queue-6.14/perf-hw_breakpoint-return-eopnotsupp-for-unsupported.patch b/queue-6.14/perf-hw_breakpoint-return-eopnotsupp-for-unsupported.patch new file mode 100644 index 0000000000..94248d045d --- /dev/null +++ b/queue-6.14/perf-hw_breakpoint-return-eopnotsupp-for-unsupported.patch @@ -0,0 +1,54 @@ +From 29b49b94a1cadf233fdb8cb3de089eb1bea0de10 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 3 Mar 2025 14:54:51 +0530 +Subject: perf/hw_breakpoint: Return EOPNOTSUPP for unsupported breakpoint type + +From: Saket Kumar Bhaskar + +[ Upstream commit 061c991697062f3bf87b72ed553d1d33a0e370dd ] + +Currently, __reserve_bp_slot() returns -ENOSPC for unsupported +breakpoint types on the architecture. For example, powerpc +does not support hardware instruction breakpoints. This causes +the perf_skip BPF selftest to fail, as neither ENOENT nor +EOPNOTSUPP is returned by perf_event_open for unsupported +breakpoint types. As a result, the test that should be skipped +for this arch is not correctly identified. + +To resolve this, hw_breakpoint_event_init() should exit early by +checking for unsupported breakpoint types using +hw_breakpoint_slots_cached() and return the appropriate error +(-EOPNOTSUPP). + +Signed-off-by: Saket Kumar Bhaskar +Signed-off-by: Ingo Molnar +Cc: Marco Elver +Cc: Dmitry Vyukov +Cc: Ian Rogers +Cc: Frederic Weisbecker +Link: https://lore.kernel.org/r/20250303092451.1862862-1-skb99@linux.ibm.com +Signed-off-by: Sasha Levin +--- + kernel/events/hw_breakpoint.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/kernel/events/hw_breakpoint.c b/kernel/events/hw_breakpoint.c +index bc4a61029b6dc..8ec2cb6889038 100644 +--- a/kernel/events/hw_breakpoint.c ++++ b/kernel/events/hw_breakpoint.c +@@ -950,9 +950,10 @@ static int hw_breakpoint_event_init(struct perf_event *bp) + return -ENOENT; + + /* +- * no branch sampling for breakpoint events ++ * Check if breakpoint type is supported before proceeding. ++ * Also, no branch sampling for breakpoint events. + */ +- if (has_branch_stack(bp)) ++ if (!hw_breakpoint_slots_cached(find_slot_idx(bp->attr.bp_type)) || has_branch_stack(bp)) + return -EOPNOTSUPP; + + err = register_perf_hw_breakpoint(bp); +-- +2.39.5 + diff --git a/queue-6.14/phy-core-don-t-require-set_mode-callback-for-phy_get.patch b/queue-6.14/phy-core-don-t-require-set_mode-callback-for-phy_get.patch new file mode 100644 index 0000000000..89149bb871 --- /dev/null +++ b/queue-6.14/phy-core-don-t-require-set_mode-callback-for-phy_get.patch @@ -0,0 +1,54 @@ +From 0e2169f9297489799153f868825e90256a9da6a1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 9 Feb 2025 14:31:45 +0200 +Subject: phy: core: don't require set_mode() callback for phy_get_mode() to + work + +From: Dmitry Baryshkov + +[ Upstream commit d58c04e305afbaa9dda7969151f06c4efe2c98b0 ] + +As reported by Damon Ding, the phy_get_mode() call doesn't work as +expected unless the PHY driver has a .set_mode() call. This prompts PHY +drivers to have empty stubs for .set_mode() for the sake of being able +to get the mode. + +Make .set_mode() callback truly optional and update PHY's mode even if +it there is none. + +Cc: Damon Ding +Link: https://lore.kernel.org/r/96f8310f-93f1-4bcb-8637-137e1159ff83@rock-chips.com +Tested-by: Damon Ding +Signed-off-by: Dmitry Baryshkov +Link: https://lore.kernel.org/r/20250209-phy-fix-set-moe-v2-1-76e248503856@linaro.org +Signed-off-by: Vinod Koul +Signed-off-by: Sasha Levin +--- + drivers/phy/phy-core.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c +index 8dfdce605a905..067316dfcd83a 100644 +--- a/drivers/phy/phy-core.c ++++ b/drivers/phy/phy-core.c +@@ -405,13 +405,14 @@ EXPORT_SYMBOL_GPL(phy_power_off); + + int phy_set_mode_ext(struct phy *phy, enum phy_mode mode, int submode) + { +- int ret; ++ int ret = 0; + +- if (!phy || !phy->ops->set_mode) ++ if (!phy) + return 0; + + mutex_lock(&phy->mutex); +- ret = phy->ops->set_mode(phy, mode, submode); ++ if (phy->ops->set_mode) ++ ret = phy->ops->set_mode(phy, mode, submode); + if (!ret) + phy->attrs.mode = mode; + mutex_unlock(&phy->mutex); +-- +2.39.5 + diff --git a/queue-6.14/phy-exynos5-usbdrd-fix-eds-distribution-tuning-gs101.patch b/queue-6.14/phy-exynos5-usbdrd-fix-eds-distribution-tuning-gs101.patch new file mode 100644 index 0000000000..f560aea96c --- /dev/null +++ b/queue-6.14/phy-exynos5-usbdrd-fix-eds-distribution-tuning-gs101.patch @@ -0,0 +1,57 @@ +From efa954707ae2c66c1a49d6b9f0ca558aa22d5512 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 6 Dec 2024 16:31:04 +0000 +Subject: phy: exynos5-usbdrd: fix EDS distribution tuning (gs101) +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: André Draszik + +[ Upstream commit 21860f340ba76ee042e5431ff92537f89bc11476 ] + +This code's intention is to configure lane0 and lane2 tunings, but for +lane2 there is a typo and it ends up tuning something else. + +Fix the typo, as it doesn't appear to make sense to apply different +tunings for lane0 vs lane2. + +The same typo appears to exist in the bootloader, hence we restore the +original value in the typo'd registers as well. This can be removed +once / if the bootloader is updated. + +Note that this is incorrect in the downstream driver as well - the +values had been copied from there. + +Reviewed-by: Peter Griffin +Tested-by: Peter Griffin +Signed-off-by: André Draszik +Tested-by: Will McVicker +Link: https://lore.kernel.org/r/20241206-gs101-phy-lanes-orientation-phy-v4-4-f5961268b149@linaro.org +Signed-off-by: Vinod Koul +Signed-off-by: Sasha Levin +--- + drivers/phy/samsung/phy-exynos5-usbdrd.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/drivers/phy/samsung/phy-exynos5-usbdrd.c b/drivers/phy/samsung/phy-exynos5-usbdrd.c +index 46b8f6987c62c..28d02ae60cc14 100644 +--- a/drivers/phy/samsung/phy-exynos5-usbdrd.c ++++ b/drivers/phy/samsung/phy-exynos5-usbdrd.c +@@ -1513,8 +1513,11 @@ static const struct exynos5_usbdrd_phy_tuning gs101_tunes_pipe3_preinit[] = { + PHY_TUNING_ENTRY_PMA(0x09e0, -1, 0x00), + PHY_TUNING_ENTRY_PMA(0x09e4, -1, 0x36), + PHY_TUNING_ENTRY_PMA(0x1e7c, -1, 0x06), +- PHY_TUNING_ENTRY_PMA(0x1e90, -1, 0x00), +- PHY_TUNING_ENTRY_PMA(0x1e94, -1, 0x36), ++ PHY_TUNING_ENTRY_PMA(0x19e0, -1, 0x00), ++ PHY_TUNING_ENTRY_PMA(0x19e4, -1, 0x36), ++ /* fix bootloader bug */ ++ PHY_TUNING_ENTRY_PMA(0x1e90, -1, 0x02), ++ PHY_TUNING_ENTRY_PMA(0x1e94, -1, 0x0b), + /* improve LVCC */ + PHY_TUNING_ENTRY_PMA(0x08f0, -1, 0x30), + PHY_TUNING_ENTRY_PMA(0x18f0, -1, 0x30), +-- +2.39.5 + diff --git a/queue-6.14/phy-phy-rockchip-samsung-hdptx-swap-the-definitions-.patch b/queue-6.14/phy-phy-rockchip-samsung-hdptx-swap-the-definitions-.patch new file mode 100644 index 0000000000..18b0a527c1 --- /dev/null +++ b/queue-6.14/phy-phy-rockchip-samsung-hdptx-swap-the-definitions-.patch @@ -0,0 +1,41 @@ +From 04209f58dd11c447f57240c7baf24b758d61999b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Feb 2025 18:51:54 +0800 +Subject: phy: phy-rockchip-samsung-hdptx: Swap the definitions of LCPLL_REF + and ROPLL_REF + +From: Damon Ding + +[ Upstream commit 2947c8065e9efdd3b6434d2817dc8896234a3fc0 ] + +According to the datasheet, setting the dig_clk_sel bit of CMN_REG(0097) +to 1'b1 selects LCPLL as the reference clock, while setting it to 1'b0 +selects the ROPLL. + +Signed-off-by: Damon Ding +Reviewed-by: Dmitry Baryshkov +Link: https://lore.kernel.org/r/20250205105157.580060-2-damon.ding@rock-chips.com +Signed-off-by: Vinod Koul +Signed-off-by: Sasha Levin +--- + drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c +index 2fb4f297fda3d..920abf6fa9bdd 100644 +--- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c ++++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c +@@ -94,8 +94,8 @@ + #define LCPLL_ALONE_MODE BIT(1) + /* CMN_REG(0097) */ + #define DIG_CLK_SEL BIT(1) +-#define ROPLL_REF BIT(1) +-#define LCPLL_REF 0 ++#define LCPLL_REF BIT(1) ++#define ROPLL_REF 0 + /* CMN_REG(0099) */ + #define CMN_ROPLL_ALONE_MODE BIT(2) + #define ROPLL_ALONE_MODE BIT(2) +-- +2.39.5 + diff --git a/queue-6.14/phy-renesas-rcar-gen3-usb2-assert-pll-reset-on-phy-p.patch b/queue-6.14/phy-renesas-rcar-gen3-usb2-assert-pll-reset-on-phy-p.patch new file mode 100644 index 0000000000..25ffe68647 --- /dev/null +++ b/queue-6.14/phy-renesas-rcar-gen3-usb2-assert-pll-reset-on-phy-p.patch @@ -0,0 +1,50 @@ +From 107eca439e430631bbbee9c62088a710a974d056 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 7 May 2025 15:50:31 +0300 +Subject: phy: renesas: rcar-gen3-usb2: Assert PLL reset on PHY power off + +From: Claudiu Beznea + +[ Upstream commit 9ce71e85b29eb63e48e294479742e670513f03a0 ] + +Assert PLL reset on PHY power off. This saves power. + +Fixes: f3b5a8d9b50d ("phy: rcar-gen3-usb2: Add R-Car Gen3 USB2 PHY driver") +Cc: stable@vger.kernel.org +Reviewed-by: Yoshihiro Shimoda +Tested-by: Yoshihiro Shimoda +Reviewed-by: Lad Prabhakar +Signed-off-by: Claudiu Beznea +Link: https://lore.kernel.org/r/20250507125032.565017-5-claudiu.beznea.uj@bp.renesas.com +Signed-off-by: Vinod Koul +Signed-off-by: Sasha Levin +--- + drivers/phy/renesas/phy-rcar-gen3-usb2.c | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) + +diff --git a/drivers/phy/renesas/phy-rcar-gen3-usb2.c b/drivers/phy/renesas/phy-rcar-gen3-usb2.c +index 7d18bc549f17e..9fdf17e0848a2 100644 +--- a/drivers/phy/renesas/phy-rcar-gen3-usb2.c ++++ b/drivers/phy/renesas/phy-rcar-gen3-usb2.c +@@ -540,9 +540,17 @@ static int rcar_gen3_phy_usb2_power_off(struct phy *p) + struct rcar_gen3_chan *channel = rphy->ch; + int ret = 0; + +- scoped_guard(spinlock_irqsave, &channel->lock) ++ scoped_guard(spinlock_irqsave, &channel->lock) { + rphy->powered = false; + ++ if (rcar_gen3_are_all_rphys_power_off(channel)) { ++ u32 val = readl(channel->base + USB2_USBCTR); ++ ++ val |= USB2_USBCTR_PLL_RST; ++ writel(val, channel->base + USB2_USBCTR); ++ } ++ } ++ + if (channel->vbus) + ret = regulator_disable(channel->vbus); + +-- +2.39.5 + diff --git a/queue-6.14/phy-renesas-rcar-gen3-usb2-lock-around-hardware-regi.patch b/queue-6.14/phy-renesas-rcar-gen3-usb2-lock-around-hardware-regi.patch new file mode 100644 index 0000000000..d7811a3f3c --- /dev/null +++ b/queue-6.14/phy-renesas-rcar-gen3-usb2-lock-around-hardware-regi.patch @@ -0,0 +1,199 @@ +From dde57b862c75b85e963db85035d0310bcaf6e28b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 7 May 2025 15:50:30 +0300 +Subject: phy: renesas: rcar-gen3-usb2: Lock around hardware registers and + driver data + +From: Claudiu Beznea + +[ Upstream commit 55a387ebb9219cbe4edfa8ba9996ccb0e7ad4932 ] + +The phy-rcar-gen3-usb2 driver exposes four individual PHYs that are +requested and configured by PHY users. The struct phy_ops APIs access the +same set of registers to configure all PHYs. Additionally, PHY settings can +be modified through sysfs or an IRQ handler. While some struct phy_ops APIs +are protected by a driver-wide mutex, others rely on individual +PHY-specific mutexes. + +This approach can lead to various issues, including: +1/ the IRQ handler may interrupt PHY settings in progress, racing with + hardware configuration protected by a mutex lock +2/ due to msleep(20) in rcar_gen3_init_otg(), while a configuration thread + suspends to wait for the delay, another thread may try to configure + another PHY (with phy_init() + phy_power_on()); re-running the + phy_init() goes to the exact same configuration code, re-running the + same hardware configuration on the same set of registers (and bits) + which might impact the result of the msleep for the 1st configuring + thread +3/ sysfs can configure the hardware (though role_store()) and it can + still race with the phy_init()/phy_power_on() APIs calling into the + drivers struct phy_ops + +To address these issues, add a spinlock to protect hardware register access +and driver private data structures (e.g., calls to +rcar_gen3_is_any_rphy_initialized()). Checking driver-specific data remains +necessary as all PHY instances share common settings. With this change, +the existing mutex protection is removed and the cleanup.h helpers are +used. + +While at it, to keep the code simpler, do not skip +regulator_enable()/regulator_disable() APIs in +rcar_gen3_phy_usb2_power_on()/rcar_gen3_phy_usb2_power_off() as the +regulators enable/disable operations are reference counted anyway. + +Fixes: f3b5a8d9b50d ("phy: rcar-gen3-usb2: Add R-Car Gen3 USB2 PHY driver") +Cc: stable@vger.kernel.org +Reviewed-by: Yoshihiro Shimoda +Tested-by: Yoshihiro Shimoda +Reviewed-by: Lad Prabhakar +Signed-off-by: Claudiu Beznea +Link: https://lore.kernel.org/r/20250507125032.565017-4-claudiu.beznea.uj@bp.renesas.com +Signed-off-by: Vinod Koul +Stable-dep-of: 9ce71e85b29e ("phy: renesas: rcar-gen3-usb2: Assert PLL reset on PHY power off") +Signed-off-by: Sasha Levin +--- + drivers/phy/renesas/phy-rcar-gen3-usb2.c | 49 +++++++++++++----------- + 1 file changed, 26 insertions(+), 23 deletions(-) + +diff --git a/drivers/phy/renesas/phy-rcar-gen3-usb2.c b/drivers/phy/renesas/phy-rcar-gen3-usb2.c +index aee33916b9073..7d18bc549f17e 100644 +--- a/drivers/phy/renesas/phy-rcar-gen3-usb2.c ++++ b/drivers/phy/renesas/phy-rcar-gen3-usb2.c +@@ -9,6 +9,7 @@ + * Copyright (C) 2014 Cogent Embedded, Inc. + */ + ++#include + #include + #include + #include +@@ -118,7 +119,7 @@ struct rcar_gen3_chan { + struct regulator *vbus; + struct reset_control *rstc; + struct work_struct work; +- struct mutex lock; /* protects rphys[...].powered */ ++ spinlock_t lock; /* protects access to hardware and driver data structure. */ + enum usb_dr_mode dr_mode; + u32 obint_enable_bits; + bool extcon_host; +@@ -348,6 +349,8 @@ static ssize_t role_store(struct device *dev, struct device_attribute *attr, + bool is_b_device; + enum phy_mode cur_mode, new_mode; + ++ guard(spinlock_irqsave)(&ch->lock); ++ + if (!ch->is_otg_channel || !rcar_gen3_is_any_otg_rphy_initialized(ch)) + return -EIO; + +@@ -415,7 +418,7 @@ static void rcar_gen3_init_otg(struct rcar_gen3_chan *ch) + val = readl(usb2_base + USB2_ADPCTRL); + writel(val | USB2_ADPCTRL_IDPULLUP, usb2_base + USB2_ADPCTRL); + } +- msleep(20); ++ mdelay(20); + + writel(0xffffffff, usb2_base + USB2_OBINTSTA); + writel(ch->obint_enable_bits, usb2_base + USB2_OBINTEN); +@@ -436,12 +439,14 @@ static irqreturn_t rcar_gen3_phy_usb2_irq(int irq, void *_ch) + if (pm_runtime_suspended(dev)) + goto rpm_put; + +- status = readl(usb2_base + USB2_OBINTSTA); +- if (status & ch->obint_enable_bits) { +- dev_vdbg(dev, "%s: %08x\n", __func__, status); +- writel(ch->obint_enable_bits, usb2_base + USB2_OBINTSTA); +- rcar_gen3_device_recognition(ch); +- ret = IRQ_HANDLED; ++ scoped_guard(spinlock, &ch->lock) { ++ status = readl(usb2_base + USB2_OBINTSTA); ++ if (status & ch->obint_enable_bits) { ++ dev_vdbg(dev, "%s: %08x\n", __func__, status); ++ writel(ch->obint_enable_bits, usb2_base + USB2_OBINTSTA); ++ rcar_gen3_device_recognition(ch); ++ ret = IRQ_HANDLED; ++ } + } + + rpm_put: +@@ -456,6 +461,8 @@ static int rcar_gen3_phy_usb2_init(struct phy *p) + void __iomem *usb2_base = channel->base; + u32 val; + ++ guard(spinlock_irqsave)(&channel->lock); ++ + /* Initialize USB2 part */ + val = readl(usb2_base + USB2_INT_ENABLE); + val |= USB2_INT_ENABLE_UCOM_INTEN | rphy->int_enable_bits; +@@ -482,6 +489,8 @@ static int rcar_gen3_phy_usb2_exit(struct phy *p) + void __iomem *usb2_base = channel->base; + u32 val; + ++ guard(spinlock_irqsave)(&channel->lock); ++ + rphy->initialized = false; + + val = readl(usb2_base + USB2_INT_ENABLE); +@@ -501,16 +510,17 @@ static int rcar_gen3_phy_usb2_power_on(struct phy *p) + u32 val; + int ret = 0; + +- mutex_lock(&channel->lock); +- if (!rcar_gen3_are_all_rphys_power_off(channel)) +- goto out; +- + if (channel->vbus) { + ret = regulator_enable(channel->vbus); + if (ret) +- goto out; ++ return ret; + } + ++ guard(spinlock_irqsave)(&channel->lock); ++ ++ if (!rcar_gen3_are_all_rphys_power_off(channel)) ++ goto out; ++ + val = readl(usb2_base + USB2_USBCTR); + val |= USB2_USBCTR_PLL_RST; + writel(val, usb2_base + USB2_USBCTR); +@@ -520,7 +530,6 @@ static int rcar_gen3_phy_usb2_power_on(struct phy *p) + out: + /* The powered flag should be set for any other phys anyway */ + rphy->powered = true; +- mutex_unlock(&channel->lock); + + return 0; + } +@@ -531,18 +540,12 @@ static int rcar_gen3_phy_usb2_power_off(struct phy *p) + struct rcar_gen3_chan *channel = rphy->ch; + int ret = 0; + +- mutex_lock(&channel->lock); +- rphy->powered = false; +- +- if (!rcar_gen3_are_all_rphys_power_off(channel)) +- goto out; ++ scoped_guard(spinlock_irqsave, &channel->lock) ++ rphy->powered = false; + + if (channel->vbus) + ret = regulator_disable(channel->vbus); + +-out: +- mutex_unlock(&channel->lock); +- + return ret; + } + +@@ -753,7 +756,7 @@ static int rcar_gen3_phy_usb2_probe(struct platform_device *pdev) + if (phy_data->no_adp_ctrl) + channel->obint_enable_bits = USB2_OBINT_IDCHG_EN; + +- mutex_init(&channel->lock); ++ spin_lock_init(&channel->lock); + for (i = 0; i < NUM_OF_PHYS; i++) { + channel->rphys[i].phy = devm_phy_create(dev, NULL, + phy_data->phy_usb2_ops); +-- +2.39.5 + diff --git a/queue-6.14/phy-renesas-rcar-gen3-usb2-move-irq-request-in-probe.patch b/queue-6.14/phy-renesas-rcar-gen3-usb2-move-irq-request-in-probe.patch new file mode 100644 index 0000000000..be78797c46 --- /dev/null +++ b/queue-6.14/phy-renesas-rcar-gen3-usb2-move-irq-request-in-probe.patch @@ -0,0 +1,144 @@ +From d70563066ea87c8810d764ab03997616ec9e822d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 7 May 2025 15:50:29 +0300 +Subject: phy: renesas: rcar-gen3-usb2: Move IRQ request in probe + +From: Claudiu Beznea + +[ Upstream commit de76809f60cc938d3580bbbd5b04b7d12af6ce3a ] + +Commit 08b0ad375ca6 ("phy: renesas: rcar-gen3-usb2: move IRQ registration +to init") moved the IRQ request operation from probe to +struct phy_ops::phy_init API to avoid triggering interrupts (which lead to +register accesses) while the PHY clocks (enabled through runtime PM APIs) +are not active. If this happens, it results in a synchronous abort. + +One way to reproduce this issue is by enabling CONFIG_DEBUG_SHIRQ, which +calls free_irq() on driver removal. + +Move the IRQ request and free operations back to probe, and take the +runtime PM state into account in IRQ handler. This commit is preparatory +for the subsequent fixes in this series. + +Reviewed-by: Yoshihiro Shimoda +Tested-by: Yoshihiro Shimoda +Reviewed-by: Lad Prabhakar +Signed-off-by: Claudiu Beznea +Link: https://lore.kernel.org/r/20250507125032.565017-3-claudiu.beznea.uj@bp.renesas.com +Signed-off-by: Vinod Koul +Stable-dep-of: 9ce71e85b29e ("phy: renesas: rcar-gen3-usb2: Assert PLL reset on PHY power off") +Signed-off-by: Sasha Levin +--- + drivers/phy/renesas/phy-rcar-gen3-usb2.c | 46 +++++++++++++----------- + 1 file changed, 26 insertions(+), 20 deletions(-) + +diff --git a/drivers/phy/renesas/phy-rcar-gen3-usb2.c b/drivers/phy/renesas/phy-rcar-gen3-usb2.c +index 946dc2f184e87..aee33916b9073 100644 +--- a/drivers/phy/renesas/phy-rcar-gen3-usb2.c ++++ b/drivers/phy/renesas/phy-rcar-gen3-usb2.c +@@ -120,7 +120,6 @@ struct rcar_gen3_chan { + struct work_struct work; + struct mutex lock; /* protects rphys[...].powered */ + enum usb_dr_mode dr_mode; +- int irq; + u32 obint_enable_bits; + bool extcon_host; + bool is_otg_channel; +@@ -428,16 +427,25 @@ static irqreturn_t rcar_gen3_phy_usb2_irq(int irq, void *_ch) + { + struct rcar_gen3_chan *ch = _ch; + void __iomem *usb2_base = ch->base; +- u32 status = readl(usb2_base + USB2_OBINTSTA); ++ struct device *dev = ch->dev; + irqreturn_t ret = IRQ_NONE; ++ u32 status; + ++ pm_runtime_get_noresume(dev); ++ ++ if (pm_runtime_suspended(dev)) ++ goto rpm_put; ++ ++ status = readl(usb2_base + USB2_OBINTSTA); + if (status & ch->obint_enable_bits) { +- dev_vdbg(ch->dev, "%s: %08x\n", __func__, status); ++ dev_vdbg(dev, "%s: %08x\n", __func__, status); + writel(ch->obint_enable_bits, usb2_base + USB2_OBINTSTA); + rcar_gen3_device_recognition(ch); + ret = IRQ_HANDLED; + } + ++rpm_put: ++ pm_runtime_put_noidle(dev); + return ret; + } + +@@ -447,17 +455,6 @@ static int rcar_gen3_phy_usb2_init(struct phy *p) + struct rcar_gen3_chan *channel = rphy->ch; + void __iomem *usb2_base = channel->base; + u32 val; +- int ret; +- +- if (!rcar_gen3_is_any_rphy_initialized(channel) && channel->irq >= 0) { +- INIT_WORK(&channel->work, rcar_gen3_phy_usb2_work); +- ret = request_irq(channel->irq, rcar_gen3_phy_usb2_irq, +- IRQF_SHARED, dev_name(channel->dev), channel); +- if (ret < 0) { +- dev_err(channel->dev, "No irq handler (%d)\n", channel->irq); +- return ret; +- } +- } + + /* Initialize USB2 part */ + val = readl(usb2_base + USB2_INT_ENABLE); +@@ -493,9 +490,6 @@ static int rcar_gen3_phy_usb2_exit(struct phy *p) + val &= ~USB2_INT_ENABLE_UCOM_INTEN; + writel(val, usb2_base + USB2_INT_ENABLE); + +- if (channel->irq >= 0 && !rcar_gen3_is_any_rphy_initialized(channel)) +- free_irq(channel->irq, channel); +- + return 0; + } + +@@ -701,7 +695,7 @@ static int rcar_gen3_phy_usb2_probe(struct platform_device *pdev) + struct device *dev = &pdev->dev; + struct rcar_gen3_chan *channel; + struct phy_provider *provider; +- int ret = 0, i; ++ int ret = 0, i, irq; + + if (!dev->of_node) { + dev_err(dev, "This driver needs device tree\n"); +@@ -717,8 +711,6 @@ static int rcar_gen3_phy_usb2_probe(struct platform_device *pdev) + return PTR_ERR(channel->base); + + channel->obint_enable_bits = USB2_OBINT_BITS; +- /* get irq number here and request_irq for OTG in phy_init */ +- channel->irq = platform_get_irq_optional(pdev, 0); + channel->dr_mode = rcar_gen3_get_dr_mode(dev->of_node); + if (channel->dr_mode != USB_DR_MODE_UNKNOWN) { + channel->is_otg_channel = true; +@@ -787,6 +779,20 @@ static int rcar_gen3_phy_usb2_probe(struct platform_device *pdev) + channel->vbus = NULL; + } + ++ irq = platform_get_irq_optional(pdev, 0); ++ if (irq < 0 && irq != -ENXIO) { ++ ret = irq; ++ goto error; ++ } else if (irq > 0) { ++ INIT_WORK(&channel->work, rcar_gen3_phy_usb2_work); ++ ret = devm_request_irq(dev, irq, rcar_gen3_phy_usb2_irq, ++ IRQF_SHARED, dev_name(dev), channel); ++ if (ret < 0) { ++ dev_err(dev, "Failed to request irq (%d)\n", irq); ++ goto error; ++ } ++ } ++ + provider = devm_of_phy_provider_register(dev, rcar_gen3_phy_usb2_xlate); + if (IS_ERR(provider)) { + dev_err(dev, "Failed to register PHY provider\n"); +-- +2.39.5 + diff --git a/queue-6.14/phy-rockchip-usbdp-only-verify-link-rates-lanes-volt.patch b/queue-6.14/phy-rockchip-usbdp-only-verify-link-rates-lanes-volt.patch new file mode 100644 index 0000000000..8537207e26 --- /dev/null +++ b/queue-6.14/phy-rockchip-usbdp-only-verify-link-rates-lanes-volt.patch @@ -0,0 +1,175 @@ +From 308a9875a7045a13b16ca3d5c410e11db1b273cf Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 12 Mar 2025 16:00:07 +0800 +Subject: phy: rockchip: usbdp: Only verify link rates/lanes/voltage when the + corresponding set flags are set + +From: Andy Yan + +[ Upstream commit 969a38be437b68dc9e12e3c3f08911c9f9c8be73 ] + +According documentation of phy_configure_opts_dp, at the configure +stage, link rates should only be verify/configure when set_rate +flag is set, the same applies to lanes and voltage. + +So do it as the documentation says. +Because voltage setting depends on the lanes, link rates set +previously, so record the link rates and lanes at it's verify stage. + +Signed-off-by: Andy Yan +Link: https://lore.kernel.org/r/20250312080041.524546-1-andyshrk@163.com +Signed-off-by: Vinod Koul +Signed-off-by: Sasha Levin +--- + drivers/phy/rockchip/phy-rockchip-usbdp.c | 87 ++++++++++++++--------- + 1 file changed, 53 insertions(+), 34 deletions(-) + +diff --git a/drivers/phy/rockchip/phy-rockchip-usbdp.c b/drivers/phy/rockchip/phy-rockchip-usbdp.c +index c04cf64f8a35d..fff04e0fbd800 100644 +--- a/drivers/phy/rockchip/phy-rockchip-usbdp.c ++++ b/drivers/phy/rockchip/phy-rockchip-usbdp.c +@@ -187,6 +187,8 @@ struct rk_udphy { + u32 dp_aux_din_sel; + bool dp_sink_hpd_sel; + bool dp_sink_hpd_cfg; ++ unsigned int link_rate; ++ unsigned int lanes; + u8 bw; + int id; + +@@ -1102,15 +1104,19 @@ static int rk_udphy_dp_phy_power_off(struct phy *phy) + return 0; + } + +-static int rk_udphy_dp_phy_verify_link_rate(unsigned int link_rate) ++/* ++ * Verify link rate ++ */ ++static int rk_udphy_dp_phy_verify_link_rate(struct rk_udphy *udphy, ++ struct phy_configure_opts_dp *dp) + { +- switch (link_rate) { ++ switch (dp->link_rate) { + case 1620: + case 2700: + case 5400: + case 8100: ++ udphy->link_rate = dp->link_rate; + break; +- + default: + return -EINVAL; + } +@@ -1118,45 +1124,44 @@ static int rk_udphy_dp_phy_verify_link_rate(unsigned int link_rate) + return 0; + } + +-static int rk_udphy_dp_phy_verify_config(struct rk_udphy *udphy, +- struct phy_configure_opts_dp *dp) ++static int rk_udphy_dp_phy_verify_lanes(struct rk_udphy *udphy, ++ struct phy_configure_opts_dp *dp) + { +- int i, ret; +- +- /* If changing link rate was required, verify it's supported. */ +- ret = rk_udphy_dp_phy_verify_link_rate(dp->link_rate); +- if (ret) +- return ret; +- +- /* Verify lane count. */ + switch (dp->lanes) { + case 1: + case 2: + case 4: + /* valid lane count. */ ++ udphy->lanes = dp->lanes; + break; + + default: + return -EINVAL; + } + +- /* +- * If changing voltages is required, check swing and pre-emphasis +- * levels, per-lane. +- */ +- if (dp->set_voltages) { +- /* Lane count verified previously. */ +- for (i = 0; i < dp->lanes; i++) { +- if (dp->voltage[i] > 3 || dp->pre[i] > 3) +- return -EINVAL; ++ return 0; ++} + +- /* +- * Sum of voltage swing and pre-emphasis levels cannot +- * exceed 3. +- */ +- if (dp->voltage[i] + dp->pre[i] > 3) +- return -EINVAL; +- } ++/* ++ * If changing voltages is required, check swing and pre-emphasis ++ * levels, per-lane. ++ */ ++static int rk_udphy_dp_phy_verify_voltages(struct rk_udphy *udphy, ++ struct phy_configure_opts_dp *dp) ++{ ++ int i; ++ ++ /* Lane count verified previously. */ ++ for (i = 0; i < udphy->lanes; i++) { ++ if (dp->voltage[i] > 3 || dp->pre[i] > 3) ++ return -EINVAL; ++ ++ /* ++ * Sum of voltage swing and pre-emphasis levels cannot ++ * exceed 3. ++ */ ++ if (dp->voltage[i] + dp->pre[i] > 3) ++ return -EINVAL; + } + + return 0; +@@ -1196,9 +1201,23 @@ static int rk_udphy_dp_phy_configure(struct phy *phy, + u32 i, val, lane; + int ret; + +- ret = rk_udphy_dp_phy_verify_config(udphy, dp); +- if (ret) +- return ret; ++ if (dp->set_rate) { ++ ret = rk_udphy_dp_phy_verify_link_rate(udphy, dp); ++ if (ret) ++ return ret; ++ } ++ ++ if (dp->set_lanes) { ++ ret = rk_udphy_dp_phy_verify_lanes(udphy, dp); ++ if (ret) ++ return ret; ++ } ++ ++ if (dp->set_voltages) { ++ ret = rk_udphy_dp_phy_verify_voltages(udphy, dp); ++ if (ret) ++ return ret; ++ } + + if (dp->set_rate) { + regmap_update_bits(udphy->pma_regmap, CMN_DP_RSTN_OFFSET, +@@ -1243,9 +1262,9 @@ static int rk_udphy_dp_phy_configure(struct phy *phy, + } + + if (dp->set_voltages) { +- for (i = 0; i < dp->lanes; i++) { ++ for (i = 0; i < udphy->lanes; i++) { + lane = udphy->dp_lane_sel[i]; +- switch (dp->link_rate) { ++ switch (udphy->link_rate) { + case 1620: + case 2700: + regmap_update_bits(udphy->pma_regmap, +-- +2.39.5 + diff --git a/queue-6.14/pidfs-improve-multi-threaded-exec-and-premature-thre.patch b/queue-6.14/pidfs-improve-multi-threaded-exec-and-premature-thre.patch new file mode 100644 index 0000000000..933c96703e --- /dev/null +++ b/queue-6.14/pidfs-improve-multi-threaded-exec-and-premature-thre.patch @@ -0,0 +1,129 @@ +From 7bfc577726ebf2db0287215d52947c9b09cd8efb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 20 Mar 2025 14:24:08 +0100 +Subject: pidfs: improve multi-threaded exec and premature thread-group leader + exit polling + +From: Christian Brauner + +[ Upstream commit 0fb482728ba1ee2130eaa461bf551f014447997c ] + +This is another attempt trying to make pidfd polling for multi-threaded +exec and premature thread-group leader exit consistent. + +A quick recap of these two cases: + +(1) During a multi-threaded exec by a subthread, i.e., non-thread-group + leader thread, all other threads in the thread-group including the + thread-group leader are killed and the struct pid of the + thread-group leader will be taken over by the subthread that called + exec. IOW, two tasks change their TIDs. + +(2) A premature thread-group leader exit means that the thread-group + leader exited before all of the other subthreads in the thread-group + have exited. + +Both cases lead to inconsistencies for pidfd polling with PIDFD_THREAD. +Any caller that holds a PIDFD_THREAD pidfd to the current thread-group +leader may or may not see an exit notification on the file descriptor +depending on when poll is performed. If the poll is performed before the +exec of the subthread has concluded an exit notification is generated +for the old thread-group leader. If the poll is performed after the exec +of the subthread has concluded no exit notification is generated for the +old thread-group leader. + +The correct behavior would be to simply not generate an exit +notification on the struct pid of a subhthread exec because the struct +pid is taken over by the subthread and thus remains alive. + +But this is difficult to handle because a thread-group may exit +prematurely as mentioned in (2). In that case an exit notification is +reliably generated but the subthreads may continue to run for an +indeterminate amount of time and thus also may exec at some point. + +So far there was no way to distinguish between (1) and (2) internally. +This tiny series tries to address this problem by discarding +PIDFD_THREAD notification on premature thread-group leader exit. + +If that works correctly then no exit notifications are generated for a +PIDFD_THREAD pidfd for a thread-group leader until all subthreads have +been reaped. If a subthread should exec aftewards no exit notification +will be generated until that task exits or it creates subthreads and +repeates the cycle. + +Co-Developed-by: Oleg Nesterov +Signed-off-by: Oleg Nesterov +Link: https://lore.kernel.org/r/20250320-work-pidfs-thread_group-v4-1-da678ce805bf@kernel.org +Signed-off-by: Christian Brauner +Signed-off-by: Sasha Levin +--- + fs/pidfs.c | 9 +++++---- + kernel/exit.c | 6 +++--- + kernel/signal.c | 3 +-- + 3 files changed, 9 insertions(+), 9 deletions(-) + +diff --git a/fs/pidfs.c b/fs/pidfs.c +index c0478b3c55d9f..9aa4c705776dd 100644 +--- a/fs/pidfs.c ++++ b/fs/pidfs.c +@@ -188,20 +188,21 @@ static void pidfd_show_fdinfo(struct seq_file *m, struct file *f) + static __poll_t pidfd_poll(struct file *file, struct poll_table_struct *pts) + { + struct pid *pid = pidfd_pid(file); +- bool thread = file->f_flags & PIDFD_THREAD; + struct task_struct *task; + __poll_t poll_flags = 0; + + poll_wait(file, &pid->wait_pidfd, pts); + /* +- * Depending on PIDFD_THREAD, inform pollers when the thread +- * or the whole thread-group exits. ++ * Don't wake waiters if the thread-group leader exited ++ * prematurely. They either get notified when the last subthread ++ * exits or not at all if one of the remaining subthreads execs ++ * and assumes the struct pid of the old thread-group leader. + */ + guard(rcu)(); + task = pid_task(pid, PIDTYPE_PID); + if (!task) + poll_flags = EPOLLIN | EPOLLRDNORM | EPOLLHUP; +- else if (task->exit_state && (thread || thread_group_empty(task))) ++ else if (task->exit_state && !delay_group_leader(task)) + poll_flags = EPOLLIN | EPOLLRDNORM; + + return poll_flags; +diff --git a/kernel/exit.c b/kernel/exit.c +index 6bb59b16e33e1..a9960dd6d0aa0 100644 +--- a/kernel/exit.c ++++ b/kernel/exit.c +@@ -744,10 +744,10 @@ static void exit_notify(struct task_struct *tsk, int group_dead) + + tsk->exit_state = EXIT_ZOMBIE; + /* +- * sub-thread or delay_group_leader(), wake up the +- * PIDFD_THREAD waiters. ++ * Ignore thread-group leaders that exited before all ++ * subthreads did. + */ +- if (!thread_group_empty(tsk)) ++ if (!delay_group_leader(tsk)) + do_notify_pidfd(tsk); + + if (unlikely(tsk->ptrace)) { +diff --git a/kernel/signal.c b/kernel/signal.c +index 875e97f6205a2..b2e5c90f29602 100644 +--- a/kernel/signal.c ++++ b/kernel/signal.c +@@ -2180,8 +2180,7 @@ bool do_notify_parent(struct task_struct *tsk, int sig) + WARN_ON_ONCE(!tsk->ptrace && + (tsk->group_leader != tsk || !thread_group_empty(tsk))); + /* +- * tsk is a group leader and has no threads, wake up the +- * non-PIDFD_THREAD waiters. ++ * Notify for thread-group leaders without subthreads. + */ + if (thread_group_empty(tsk)) + do_notify_pidfd(tsk); +-- +2.39.5 + diff --git a/queue-6.14/pinctrl-bcm281xx-use-unsigned-int-instead-of-bare-un.patch b/queue-6.14/pinctrl-bcm281xx-use-unsigned-int-instead-of-bare-un.patch new file mode 100644 index 0000000000..157b89d5a6 --- /dev/null +++ b/queue-6.14/pinctrl-bcm281xx-use-unsigned-int-instead-of-bare-un.patch @@ -0,0 +1,177 @@ +From 49cd97dbe35dc8c73f074741787252d928bd8962 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 3 Mar 2025 21:54:47 +0100 +Subject: pinctrl: bcm281xx: Use "unsigned int" instead of bare "unsigned" + +From: Artur Weber + +[ Upstream commit 07b5a2a13f4704c5eae3be7277ec54ffdba45f72 ] + +Replace uses of bare "unsigned" with "unsigned int" to fix checkpatch +warnings. No functional change. + +Signed-off-by: Artur Weber +Link: https://lore.kernel.org/20250303-bcm21664-pinctrl-v3-2-5f8b80e4ab51@gmail.com +Signed-off-by: Linus Walleij +Signed-off-by: Sasha Levin +--- + drivers/pinctrl/bcm/pinctrl-bcm281xx.c | 44 +++++++++++++------------- + 1 file changed, 22 insertions(+), 22 deletions(-) + +diff --git a/drivers/pinctrl/bcm/pinctrl-bcm281xx.c b/drivers/pinctrl/bcm/pinctrl-bcm281xx.c +index cf6efa9c0364a..a039b490cdb8e 100644 +--- a/drivers/pinctrl/bcm/pinctrl-bcm281xx.c ++++ b/drivers/pinctrl/bcm/pinctrl-bcm281xx.c +@@ -72,7 +72,7 @@ static enum bcm281xx_pin_type hdmi_pin = BCM281XX_PIN_TYPE_HDMI; + struct bcm281xx_pin_function { + const char *name; + const char * const *groups; +- const unsigned ngroups; ++ const unsigned int ngroups; + }; + + /* +@@ -84,10 +84,10 @@ struct bcm281xx_pinctrl_data { + + /* List of all pins */ + const struct pinctrl_pin_desc *pins; +- const unsigned npins; ++ const unsigned int npins; + + const struct bcm281xx_pin_function *functions; +- const unsigned nfunctions; ++ const unsigned int nfunctions; + + struct regmap *regmap; + }; +@@ -941,7 +941,7 @@ static struct bcm281xx_pinctrl_data bcm281xx_pinctrl = { + }; + + static inline enum bcm281xx_pin_type pin_type_get(struct pinctrl_dev *pctldev, +- unsigned pin) ++ unsigned int pin) + { + struct bcm281xx_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev); + +@@ -985,7 +985,7 @@ static int bcm281xx_pinctrl_get_groups_count(struct pinctrl_dev *pctldev) + } + + static const char *bcm281xx_pinctrl_get_group_name(struct pinctrl_dev *pctldev, +- unsigned group) ++ unsigned int group) + { + struct bcm281xx_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev); + +@@ -993,9 +993,9 @@ static const char *bcm281xx_pinctrl_get_group_name(struct pinctrl_dev *pctldev, + } + + static int bcm281xx_pinctrl_get_group_pins(struct pinctrl_dev *pctldev, +- unsigned group, ++ unsigned int group, + const unsigned **pins, +- unsigned *num_pins) ++ unsigned int *num_pins) + { + struct bcm281xx_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev); + +@@ -1007,7 +1007,7 @@ static int bcm281xx_pinctrl_get_group_pins(struct pinctrl_dev *pctldev, + + static void bcm281xx_pinctrl_pin_dbg_show(struct pinctrl_dev *pctldev, + struct seq_file *s, +- unsigned offset) ++ unsigned int offset) + { + seq_printf(s, " %s", dev_name(pctldev->dev)); + } +@@ -1029,7 +1029,7 @@ static int bcm281xx_pinctrl_get_fcns_count(struct pinctrl_dev *pctldev) + } + + static const char *bcm281xx_pinctrl_get_fcn_name(struct pinctrl_dev *pctldev, +- unsigned function) ++ unsigned int function) + { + struct bcm281xx_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev); + +@@ -1037,9 +1037,9 @@ static const char *bcm281xx_pinctrl_get_fcn_name(struct pinctrl_dev *pctldev, + } + + static int bcm281xx_pinctrl_get_fcn_groups(struct pinctrl_dev *pctldev, +- unsigned function, ++ unsigned int function, + const char * const **groups, +- unsigned * const num_groups) ++ unsigned int * const num_groups) + { + struct bcm281xx_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev); + +@@ -1050,8 +1050,8 @@ static int bcm281xx_pinctrl_get_fcn_groups(struct pinctrl_dev *pctldev, + } + + static int bcm281xx_pinmux_set(struct pinctrl_dev *pctldev, +- unsigned function, +- unsigned group) ++ unsigned int function, ++ unsigned int group) + { + struct bcm281xx_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev); + const struct bcm281xx_pin_function *f = &pdata->functions[function]; +@@ -1082,7 +1082,7 @@ static const struct pinmux_ops bcm281xx_pinctrl_pinmux_ops = { + }; + + static int bcm281xx_pinctrl_pin_config_get(struct pinctrl_dev *pctldev, +- unsigned pin, ++ unsigned int pin, + unsigned long *config) + { + return -ENOTSUPP; +@@ -1091,9 +1091,9 @@ static int bcm281xx_pinctrl_pin_config_get(struct pinctrl_dev *pctldev, + + /* Goes through the configs and update register val/mask */ + static int bcm281xx_std_pin_update(struct pinctrl_dev *pctldev, +- unsigned pin, ++ unsigned int pin, + unsigned long *configs, +- unsigned num_configs, ++ unsigned int num_configs, + u32 *val, + u32 *mask) + { +@@ -1207,9 +1207,9 @@ static const u16 bcm281xx_pullup_map[] = { + + /* Goes through the configs and update register val/mask */ + static int bcm281xx_i2c_pin_update(struct pinctrl_dev *pctldev, +- unsigned pin, ++ unsigned int pin, + unsigned long *configs, +- unsigned num_configs, ++ unsigned int num_configs, + u32 *val, + u32 *mask) + { +@@ -1277,9 +1277,9 @@ static int bcm281xx_i2c_pin_update(struct pinctrl_dev *pctldev, + + /* Goes through the configs and update register val/mask */ + static int bcm281xx_hdmi_pin_update(struct pinctrl_dev *pctldev, +- unsigned pin, ++ unsigned int pin, + unsigned long *configs, +- unsigned num_configs, ++ unsigned int num_configs, + u32 *val, + u32 *mask) + { +@@ -1321,9 +1321,9 @@ static int bcm281xx_hdmi_pin_update(struct pinctrl_dev *pctldev, + } + + static int bcm281xx_pinctrl_pin_config_set(struct pinctrl_dev *pctldev, +- unsigned pin, ++ unsigned int pin, + unsigned long *configs, +- unsigned num_configs) ++ unsigned int num_configs) + { + struct bcm281xx_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev); + enum bcm281xx_pin_type pin_type; +-- +2.39.5 + diff --git a/queue-6.14/pinctrl-devicetree-do-not-goto-err-when-probing-hogs.patch b/queue-6.14/pinctrl-devicetree-do-not-goto-err-when-probing-hogs.patch new file mode 100644 index 0000000000..bba900669f --- /dev/null +++ b/queue-6.14/pinctrl-devicetree-do-not-goto-err-when-probing-hogs.patch @@ -0,0 +1,110 @@ +From f64965768b29605f42028d0a655d263225bf8049 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 16 Jan 2025 18:00:09 +0100 +Subject: pinctrl: devicetree: do not goto err when probing hogs in + pinctrl_dt_to_map + +From: Valentin Caron + +[ Upstream commit c98868e816209e568c9d72023ba0bc1e4d96e611 ] + +Cross case in pinctrl framework make impossible to an hogged pin and +another, not hogged, used within the same device-tree node. For example +with this simplified device-tree : + + &pinctrl { + pinctrl_pin_1: pinctrl-pin-1 { + pins = "dummy-pinctrl-pin"; + }; + }; + + &rtc { + pinctrl-names = "default" + pinctrl-0 = <&pinctrl_pin_1 &rtc_pin_1> + + rtc_pin_1: rtc-pin-1 { + pins = "dummy-rtc-pin"; + }; + }; + +"pinctrl_pin_1" configuration is never set. This produces this path in +the code: + + really_probe() + pinctrl_bind_pins() + | devm_pinctrl_get() + | pinctrl_get() + | create_pinctrl() + | pinctrl_dt_to_map() + | // Hog pin create an abort for all pins of the node + | ret = dt_to_map_one_config() + | | /* Do not defer probing of hogs (circular loop) */ + | | if (np_pctldev == p->dev->of_node) + | | return -ENODEV; + | if (ret) + | goto err + | + call_driver_probe() + stm32_rtc_probe() + pinctrl_enable() + pinctrl_claim_hogs() + create_pinctrl() + for_each_maps(maps_node, i, map) + // Not hog pin is skipped + if (pctldev && strcmp(dev_name(pctldev->dev), + map->ctrl_dev_name)) + continue; + +At the first call of create_pinctrl() the hogged pin produces an abort to +avoid a defer of hogged pins. All other pin configurations are trashed. + +At the second call, create_pinctrl is now called with pctldev parameter to +get hogs, but in this context only hogs are set. And other pins are +skipped. + +To handle this, do not produce an abort in the first call of +create_pinctrl(). Classic pin configuration will be set in +pinctrl_bind_pins() context. And the hogged pin configuration will be set +in pinctrl_claim_hogs() context. + +Signed-off-by: Valentin Caron +Link: https://lore.kernel.org/20250116170009.2075544-1-valentin.caron@foss.st.com +Signed-off-by: Linus Walleij +Signed-off-by: Sasha Levin +--- + drivers/pinctrl/devicetree.c | 10 ++++++++-- + 1 file changed, 8 insertions(+), 2 deletions(-) + +diff --git a/drivers/pinctrl/devicetree.c b/drivers/pinctrl/devicetree.c +index 6a94ecd6a8dea..0b7f74beb6a6a 100644 +--- a/drivers/pinctrl/devicetree.c ++++ b/drivers/pinctrl/devicetree.c +@@ -143,10 +143,14 @@ static int dt_to_map_one_config(struct pinctrl *p, + pctldev = get_pinctrl_dev_from_of_node(np_pctldev); + if (pctldev) + break; +- /* Do not defer probing of hogs (circular loop) */ ++ /* ++ * Do not defer probing of hogs (circular loop) ++ * ++ * Return 1 to let the caller catch the case. ++ */ + if (np_pctldev == p->dev->of_node) { + of_node_put(np_pctldev); +- return -ENODEV; ++ return 1; + } + } + of_node_put(np_pctldev); +@@ -265,6 +269,8 @@ int pinctrl_dt_to_map(struct pinctrl *p, struct pinctrl_dev *pctldev) + ret = dt_to_map_one_config(p, pctldev, statename, + np_config); + of_node_put(np_config); ++ if (ret == 1) ++ continue; + if (ret < 0) + goto err; + } +-- +2.39.5 + diff --git a/queue-6.14/pinctrl-meson-define-the-pull-up-down-resistor-value.patch b/queue-6.14/pinctrl-meson-define-the-pull-up-down-resistor-value.patch new file mode 100644 index 0000000000..c39ba3e0fc --- /dev/null +++ b/queue-6.14/pinctrl-meson-define-the-pull-up-down-resistor-value.patch @@ -0,0 +1,53 @@ +From c0b2ee0a75fba3f97c5caeb9f7a314d827311072 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 29 Mar 2025 20:01:32 +0100 +Subject: pinctrl: meson: define the pull up/down resistor value as 60 kOhm + +From: Martin Blumenstingl + +[ Upstream commit e56088a13708757da68ad035269d69b93ac8c389 ] + +The public datasheets of the following Amlogic SoCs describe a typical +resistor value for the built-in pull up/down resistor: +- Meson8/8b/8m2: not documented +- GXBB (S905): 60 kOhm +- GXL (S905X): 60 kOhm +- GXM (S912): 60 kOhm +- G12B (S922X): 60 kOhm +- SM1 (S905D3): 60 kOhm + +The public G12B and SM1 datasheets additionally state min and max +values: +- min value: 50 kOhm for both, pull-up and pull-down +- max value for the pull-up: 70 kOhm +- max value for the pull-down: 130 kOhm + +Use 60 kOhm in the pinctrl-meson driver as well so it's shown in the +debugfs output. It may not be accurate for Meson8/8b/8m2 but in reality +60 kOhm is closer to the actual value than 1 Ohm. + +Signed-off-by: Martin Blumenstingl +Reviewed-by: Neil Armstrong +Link: https://lore.kernel.org/20250329190132.855196-1-martin.blumenstingl@googlemail.com +Signed-off-by: Linus Walleij +Signed-off-by: Sasha Levin +--- + drivers/pinctrl/meson/pinctrl-meson.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/pinctrl/meson/pinctrl-meson.c b/drivers/pinctrl/meson/pinctrl-meson.c +index 253a0cc57e396..e5a32a0532eee 100644 +--- a/drivers/pinctrl/meson/pinctrl-meson.c ++++ b/drivers/pinctrl/meson/pinctrl-meson.c +@@ -487,7 +487,7 @@ static int meson_pinconf_get(struct pinctrl_dev *pcdev, unsigned int pin, + case PIN_CONFIG_BIAS_PULL_DOWN: + case PIN_CONFIG_BIAS_PULL_UP: + if (meson_pinconf_get_pull(pc, pin) == param) +- arg = 1; ++ arg = 60000; + else + return -EINVAL; + break; +-- +2.39.5 + diff --git a/queue-6.14/pinctrl-qcom-msm8917-add-msm8937-wsa_reset-pin.patch b/queue-6.14/pinctrl-qcom-msm8917-add-msm8937-wsa_reset-pin.patch new file mode 100644 index 0000000000..b029276ef6 --- /dev/null +++ b/queue-6.14/pinctrl-qcom-msm8917-add-msm8937-wsa_reset-pin.patch @@ -0,0 +1,83 @@ +From d9a88d89d2c5bac1c3f4ab003c1b5e793e088b32 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 11 Feb 2025 23:37:48 +0100 +Subject: pinctrl: qcom: msm8917: Add MSM8937 wsa_reset pin +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Dang Huynh + +[ Upstream commit 3dd3ab690172b11758e17775cfbf98986ec0cb71 ] + +It looks like both 8917 and 8937 are the same except for one pin +"wsa_reset". + +Signed-off-by: Dang Huynh +Signed-off-by: Barnabás Czémán +Link: https://lore.kernel.org/20250211-msm8937-v1-4-7d27ed67f708@mainlining.org +Signed-off-by: Linus Walleij +Signed-off-by: Sasha Levin +--- + drivers/pinctrl/qcom/Kconfig.msm | 4 ++-- + drivers/pinctrl/qcom/pinctrl-msm8917.c | 8 +++++++- + 2 files changed, 9 insertions(+), 3 deletions(-) + +diff --git a/drivers/pinctrl/qcom/Kconfig.msm b/drivers/pinctrl/qcom/Kconfig.msm +index 35f47660a56b1..a0d63a6725393 100644 +--- a/drivers/pinctrl/qcom/Kconfig.msm ++++ b/drivers/pinctrl/qcom/Kconfig.msm +@@ -138,10 +138,10 @@ config PINCTRL_MSM8916 + Qualcomm TLMM block found on the Qualcomm 8916 platform. + + config PINCTRL_MSM8917 +- tristate "Qualcomm 8917 pin controller driver" ++ tristate "Qualcomm 8917/8937 pin controller driver" + help + This is the pinctrl, pinmux, pinconf and gpiolib driver for the +- Qualcomm TLMM block found on the Qualcomm MSM8917 platform. ++ Qualcomm TLMM block found on the Qualcomm MSM8917, MSM8937 platform. + + config PINCTRL_MSM8953 + tristate "Qualcomm 8953 pin controller driver" +diff --git a/drivers/pinctrl/qcom/pinctrl-msm8917.c b/drivers/pinctrl/qcom/pinctrl-msm8917.c +index cff137bb3b23f..350636807b07d 100644 +--- a/drivers/pinctrl/qcom/pinctrl-msm8917.c ++++ b/drivers/pinctrl/qcom/pinctrl-msm8917.c +@@ -539,6 +539,7 @@ enum msm8917_functions { + msm_mux_webcam_standby, + msm_mux_wsa_io, + msm_mux_wsa_irq, ++ msm_mux_wsa_reset, + msm_mux__, + }; + +@@ -1123,6 +1124,10 @@ static const char * const wsa_io_groups[] = { + "gpio94", "gpio95", + }; + ++static const char * const wsa_reset_groups[] = { ++ "gpio96", ++}; ++ + static const char * const blsp_spi8_groups[] = { + "gpio96", "gpio97", "gpio98", "gpio99", + }; +@@ -1378,6 +1383,7 @@ static const struct pinfunction msm8917_functions[] = { + MSM_PIN_FUNCTION(webcam_standby), + MSM_PIN_FUNCTION(wsa_io), + MSM_PIN_FUNCTION(wsa_irq), ++ MSM_PIN_FUNCTION(wsa_reset), + }; + + static const struct msm_pingroup msm8917_groups[] = { +@@ -1616,5 +1622,5 @@ static void __exit msm8917_pinctrl_exit(void) + } + module_exit(msm8917_pinctrl_exit); + +-MODULE_DESCRIPTION("Qualcomm msm8917 pinctrl driver"); ++MODULE_DESCRIPTION("Qualcomm msm8917/msm8937 pinctrl driver"); + MODULE_LICENSE("GPL"); +-- +2.39.5 + diff --git a/queue-6.14/pinctrl-renesas-rzg2l-add-suspend-resume-support-for.patch b/queue-6.14/pinctrl-renesas-rzg2l-add-suspend-resume-support-for.patch new file mode 100644 index 0000000000..63f12e36a4 --- /dev/null +++ b/queue-6.14/pinctrl-renesas-rzg2l-add-suspend-resume-support-for.patch @@ -0,0 +1,92 @@ +From 324b9d04f699965e3669710b0fa0263fa0ae9fba Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Feb 2025 12:01:16 +0200 +Subject: pinctrl: renesas: rzg2l: Add suspend/resume support for pull up/down + +From: Claudiu Beznea + +[ Upstream commit b2bd65fbb617353e3c46ba5206b3b030fa0f260c ] + +The Renesas RZ/G3S supports a power-saving mode where power to most of +the SoC components is lost, including the PIN controller. Save and +restore the pull-up/pull-down register contents to ensure the +functionality is preserved after a suspend/resume cycle. + +Signed-off-by: Claudiu Beznea +Reviewed-by: Lad Prabhakar +Reviewed-by: Geert Uytterhoeven +Link: https://lore.kernel.org/20250205100116.2032765-1-claudiu.beznea.uj@bp.renesas.com +Signed-off-by: Geert Uytterhoeven +Signed-off-by: Sasha Levin +--- + drivers/pinctrl/renesas/pinctrl-rzg2l.c | 19 ++++++++++++++++++- + 1 file changed, 18 insertions(+), 1 deletion(-) + +diff --git a/drivers/pinctrl/renesas/pinctrl-rzg2l.c b/drivers/pinctrl/renesas/pinctrl-rzg2l.c +index d1da7f53fc600..c72e250f4a154 100644 +--- a/drivers/pinctrl/renesas/pinctrl-rzg2l.c ++++ b/drivers/pinctrl/renesas/pinctrl-rzg2l.c +@@ -318,6 +318,7 @@ struct rzg2l_pinctrl_pin_settings { + * @pmc: PMC registers cache + * @pfc: PFC registers cache + * @iolh: IOLH registers cache ++ * @pupd: PUPD registers cache + * @ien: IEN registers cache + * @sd_ch: SD_CH registers cache + * @eth_poc: ET_POC registers cache +@@ -331,6 +332,7 @@ struct rzg2l_pinctrl_reg_cache { + u32 *pfc; + u32 *iolh[2]; + u32 *ien[2]; ++ u32 *pupd[2]; + u8 sd_ch[2]; + u8 eth_poc[2]; + u8 eth_mode; +@@ -2712,6 +2714,11 @@ static int rzg2l_pinctrl_reg_cache_alloc(struct rzg2l_pinctrl *pctrl) + if (!cache->ien[i]) + return -ENOMEM; + ++ cache->pupd[i] = devm_kcalloc(pctrl->dev, nports, sizeof(*cache->pupd[i]), ++ GFP_KERNEL); ++ if (!cache->pupd[i]) ++ return -ENOMEM; ++ + /* Allocate dedicated cache. */ + dedicated_cache->iolh[i] = devm_kcalloc(pctrl->dev, n_dedicated_pins, + sizeof(*dedicated_cache->iolh[i]), +@@ -2955,7 +2962,7 @@ static void rzg2l_pinctrl_pm_setup_regs(struct rzg2l_pinctrl *pctrl, bool suspen + struct rzg2l_pinctrl_reg_cache *cache = pctrl->cache; + + for (u32 port = 0; port < nports; port++) { +- bool has_iolh, has_ien; ++ bool has_iolh, has_ien, has_pupd; + u32 off, caps; + u8 pincnt; + u64 cfg; +@@ -2967,6 +2974,7 @@ static void rzg2l_pinctrl_pm_setup_regs(struct rzg2l_pinctrl *pctrl, bool suspen + caps = FIELD_GET(PIN_CFG_MASK, cfg); + has_iolh = !!(caps & (PIN_CFG_IOLH_A | PIN_CFG_IOLH_B | PIN_CFG_IOLH_C)); + has_ien = !!(caps & PIN_CFG_IEN); ++ has_pupd = !!(caps & PIN_CFG_PUPD); + + if (suspend) + RZG2L_PCTRL_REG_ACCESS32(suspend, pctrl->base + PFC(off), cache->pfc[port]); +@@ -2985,6 +2993,15 @@ static void rzg2l_pinctrl_pm_setup_regs(struct rzg2l_pinctrl *pctrl, bool suspen + } + } + ++ if (has_pupd) { ++ RZG2L_PCTRL_REG_ACCESS32(suspend, pctrl->base + PUPD(off), ++ cache->pupd[0][port]); ++ if (pincnt >= 4) { ++ RZG2L_PCTRL_REG_ACCESS32(suspend, pctrl->base + PUPD(off), ++ cache->pupd[1][port]); ++ } ++ } ++ + RZG2L_PCTRL_REG_ACCESS16(suspend, pctrl->base + PM(off), cache->pm[port]); + RZG2L_PCTRL_REG_ACCESS8(suspend, pctrl->base + P(off), cache->p[port]); + +-- +2.39.5 + diff --git a/queue-6.14/pinctrl-sophgo-avoid-to-modify-untouched-bit-when-se.patch b/queue-6.14/pinctrl-sophgo-avoid-to-modify-untouched-bit-when-se.patch new file mode 100644 index 0000000000..920e29c915 --- /dev/null +++ b/queue-6.14/pinctrl-sophgo-avoid-to-modify-untouched-bit-when-se.patch @@ -0,0 +1,162 @@ +From db7f0025301d0a8eb36b9879e10fbee41a6565ee Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 11 Feb 2025 13:17:49 +0800 +Subject: pinctrl: sophgo: avoid to modify untouched bit when setting cv1800 + pinconf + +From: Inochi Amaoto + +[ Upstream commit ef1a5121ae3da02372fcb66d9632ed3d47ad5637 ] + +When setting pinconf configuration for cv1800 SoC, the driver just writes +the value. It may zero some bits of the pinconf register and cause some +unexpected error. Add a mask to avoid this. + +Signed-off-by: Inochi Amaoto +Link: https://lore.kernel.org/20250211051801.470800-2-inochiama@gmail.com +Signed-off-by: Linus Walleij +Signed-off-by: Sasha Levin +--- + drivers/pinctrl/sophgo/pinctrl-cv18xx.c | 33 +++++++++++++++++-------- + 1 file changed, 23 insertions(+), 10 deletions(-) + +diff --git a/drivers/pinctrl/sophgo/pinctrl-cv18xx.c b/drivers/pinctrl/sophgo/pinctrl-cv18xx.c +index 57f2674e75d68..84b4850771ce2 100644 +--- a/drivers/pinctrl/sophgo/pinctrl-cv18xx.c ++++ b/drivers/pinctrl/sophgo/pinctrl-cv18xx.c +@@ -574,10 +574,10 @@ static int cv1800_pinconf_compute_config(struct cv1800_pinctrl *pctrl, + struct cv1800_pin *pin, + unsigned long *configs, + unsigned int num_configs, +- u32 *value) ++ u32 *value, u32 *mask) + { + int i; +- u32 v = 0; ++ u32 v = 0, m = 0; + enum cv1800_pin_io_type type; + int ret; + +@@ -596,10 +596,12 @@ static int cv1800_pinconf_compute_config(struct cv1800_pinctrl *pctrl, + case PIN_CONFIG_BIAS_PULL_DOWN: + v &= ~PIN_IO_PULLDOWN; + v |= FIELD_PREP(PIN_IO_PULLDOWN, arg); ++ m |= PIN_IO_PULLDOWN; + break; + case PIN_CONFIG_BIAS_PULL_UP: + v &= ~PIN_IO_PULLUP; + v |= FIELD_PREP(PIN_IO_PULLUP, arg); ++ m |= PIN_IO_PULLUP; + break; + case PIN_CONFIG_DRIVE_STRENGTH_UA: + ret = cv1800_pinctrl_oc2reg(pctrl, pin, arg); +@@ -607,6 +609,7 @@ static int cv1800_pinconf_compute_config(struct cv1800_pinctrl *pctrl, + return ret; + v &= ~PIN_IO_DRIVE; + v |= FIELD_PREP(PIN_IO_DRIVE, ret); ++ m |= PIN_IO_DRIVE; + break; + case PIN_CONFIG_INPUT_SCHMITT_UV: + ret = cv1800_pinctrl_schmitt2reg(pctrl, pin, arg); +@@ -614,6 +617,7 @@ static int cv1800_pinconf_compute_config(struct cv1800_pinctrl *pctrl, + return ret; + v &= ~PIN_IO_SCHMITT; + v |= FIELD_PREP(PIN_IO_SCHMITT, ret); ++ m |= PIN_IO_SCHMITT; + break; + case PIN_CONFIG_POWER_SOURCE: + /* Ignore power source as it is always fixed */ +@@ -621,10 +625,12 @@ static int cv1800_pinconf_compute_config(struct cv1800_pinctrl *pctrl, + case PIN_CONFIG_SLEW_RATE: + v &= ~PIN_IO_OUT_FAST_SLEW; + v |= FIELD_PREP(PIN_IO_OUT_FAST_SLEW, arg); ++ m |= PIN_IO_OUT_FAST_SLEW; + break; + case PIN_CONFIG_BIAS_BUS_HOLD: + v &= ~PIN_IO_BUS_HOLD; + v |= FIELD_PREP(PIN_IO_BUS_HOLD, arg); ++ m |= PIN_IO_BUS_HOLD; + break; + default: + return -ENOTSUPP; +@@ -632,17 +638,19 @@ static int cv1800_pinconf_compute_config(struct cv1800_pinctrl *pctrl, + } + + *value = v; ++ *mask = m; + + return 0; + } + + static int cv1800_pin_set_config(struct cv1800_pinctrl *pctrl, + unsigned int pin_id, +- u32 value) ++ u32 value, u32 mask) + { + struct cv1800_pin *pin = cv1800_get_pin(pctrl, pin_id); + unsigned long flags; + void __iomem *addr; ++ u32 reg; + + if (!pin) + return -EINVAL; +@@ -650,7 +658,10 @@ static int cv1800_pin_set_config(struct cv1800_pinctrl *pctrl, + addr = cv1800_pinctrl_get_component_addr(pctrl, &pin->conf); + + raw_spin_lock_irqsave(&pctrl->lock, flags); +- writel(value, addr); ++ reg = readl(addr); ++ reg &= ~mask; ++ reg |= value; ++ writel(reg, addr); + raw_spin_unlock_irqrestore(&pctrl->lock, flags); + + return 0; +@@ -662,16 +673,17 @@ static int cv1800_pconf_set(struct pinctrl_dev *pctldev, + { + struct cv1800_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); + struct cv1800_pin *pin = cv1800_get_pin(pctrl, pin_id); +- u32 value; ++ u32 value, mask; + + if (!pin) + return -ENODEV; + + if (cv1800_pinconf_compute_config(pctrl, pin, +- configs, num_configs, &value)) ++ configs, num_configs, ++ &value, &mask)) + return -ENOTSUPP; + +- return cv1800_pin_set_config(pctrl, pin_id, value); ++ return cv1800_pin_set_config(pctrl, pin_id, value, mask); + } + + static int cv1800_pconf_group_set(struct pinctrl_dev *pctldev, +@@ -682,7 +694,7 @@ static int cv1800_pconf_group_set(struct pinctrl_dev *pctldev, + struct cv1800_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); + const struct group_desc *group; + const struct cv1800_pin_mux_config *pinmuxs; +- u32 value; ++ u32 value, mask; + int i; + + group = pinctrl_generic_get_group(pctldev, gsel); +@@ -692,11 +704,12 @@ static int cv1800_pconf_group_set(struct pinctrl_dev *pctldev, + pinmuxs = group->data; + + if (cv1800_pinconf_compute_config(pctrl, pinmuxs[0].pin, +- configs, num_configs, &value)) ++ configs, num_configs, ++ &value, &mask)) + return -ENOTSUPP; + + for (i = 0; i < group->grp.npins; i++) +- cv1800_pin_set_config(pctrl, group->grp.pins[i], value); ++ cv1800_pin_set_config(pctrl, group->grp.pins[i], value, mask); + + return 0; + } +-- +2.39.5 + diff --git a/queue-6.14/pinctrl-tegra-fix-off-by-one-in-tegra_pinctrl_get_gr.patch b/queue-6.14/pinctrl-tegra-fix-off-by-one-in-tegra_pinctrl_get_gr.patch new file mode 100644 index 0000000000..838d7b381b --- /dev/null +++ b/queue-6.14/pinctrl-tegra-fix-off-by-one-in-tegra_pinctrl_get_gr.patch @@ -0,0 +1,39 @@ +From e9857d4ebbe88d4499a75b5d2f1ae2a57e279650 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 19 Mar 2025 10:05:47 +0300 +Subject: pinctrl: tegra: Fix off by one in tegra_pinctrl_get_group() + +From: Dan Carpenter + +[ Upstream commit 5a062c3c3b82004766bc3ece82b594d337076152 ] + +This should be >= pmx->soc->ngroups instead of > to avoid an out of +bounds access. The pmx->soc->groups[] array is allocated in +tegra_pinctrl_probe(). + +Fixes: c12bfa0fee65 ("pinctrl-tegra: Restore SFSEL bit when freeing pins") +Signed-off-by: Dan Carpenter +Reviewed-by: Kunwu Chan +Link: https://lore.kernel.org/82b40d9d-b437-42a9-9eb3-2328aa6877ac@stanley.mountain +Signed-off-by: Linus Walleij +Signed-off-by: Sasha Levin +--- + drivers/pinctrl/tegra/pinctrl-tegra.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/pinctrl/tegra/pinctrl-tegra.c b/drivers/pinctrl/tegra/pinctrl-tegra.c +index 27823e4207347..edcc78ebce456 100644 +--- a/drivers/pinctrl/tegra/pinctrl-tegra.c ++++ b/drivers/pinctrl/tegra/pinctrl-tegra.c +@@ -305,7 +305,7 @@ static const struct tegra_pingroup *tegra_pinctrl_get_group(struct pinctrl_dev * + { + struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev); + +- if (group_index < 0 || group_index > pmx->soc->ngroups) ++ if (group_index < 0 || group_index >= pmx->soc->ngroups) + return NULL; + + return &pmx->soc->groups[group_index]; +-- +2.39.5 + diff --git a/queue-6.14/pinctrl-tegra-restore-sfsel-bit-when-freeing-pins.patch b/queue-6.14/pinctrl-tegra-restore-sfsel-bit-when-freeing-pins.patch new file mode 100644 index 0000000000..43f38816f6 --- /dev/null +++ b/queue-6.14/pinctrl-tegra-restore-sfsel-bit-when-freeing-pins.patch @@ -0,0 +1,183 @@ +From 2394c65349756f79eba1aeb1cc111785ea01d10b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Mar 2025 16:19:39 +0530 +Subject: pinctrl-tegra: Restore SFSEL bit when freeing pins + +From: Prathamesh Shete + +[ Upstream commit c12bfa0fee65940b10ff5187349f76c6f6b1df9c ] + +Each pin can be configured as a Special Function IO (SFIO) or GPIO, +where the SFIO enables the pin to operate in alternative modes such as +I2C, SPI, etc. + +The current implementation sets all the pins back to SFIO mode +even if they were initially in GPIO mode. This can cause glitches +on the pins when pinctrl_gpio_free() is called. + +Avoid these undesired glitches by storing the pin's SFIO/GPIO +state on GPIO request and restoring it on GPIO free. + +Signed-off-by: Prathamesh Shete +Link: https://lore.kernel.org/20250305104939.15168-2-pshete@nvidia.com +Signed-off-by: Linus Walleij +Signed-off-by: Sasha Levin +--- + drivers/pinctrl/tegra/pinctrl-tegra.c | 59 +++++++++++++++++++++++---- + drivers/pinctrl/tegra/pinctrl-tegra.h | 6 +++ + 2 files changed, 57 insertions(+), 8 deletions(-) + +diff --git a/drivers/pinctrl/tegra/pinctrl-tegra.c b/drivers/pinctrl/tegra/pinctrl-tegra.c +index 3b046450bd3ff..27823e4207347 100644 +--- a/drivers/pinctrl/tegra/pinctrl-tegra.c ++++ b/drivers/pinctrl/tegra/pinctrl-tegra.c +@@ -278,8 +278,8 @@ static int tegra_pinctrl_set_mux(struct pinctrl_dev *pctldev, + return 0; + } + +-static const struct tegra_pingroup *tegra_pinctrl_get_group(struct pinctrl_dev *pctldev, +- unsigned int offset) ++static int tegra_pinctrl_get_group_index(struct pinctrl_dev *pctldev, ++ unsigned int offset) + { + struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev); + unsigned int group, num_pins, j; +@@ -292,12 +292,35 @@ static const struct tegra_pingroup *tegra_pinctrl_get_group(struct pinctrl_dev * + continue; + for (j = 0; j < num_pins; j++) { + if (offset == pins[j]) +- return &pmx->soc->groups[group]; ++ return group; + } + } + +- dev_err(pctldev->dev, "Pingroup not found for pin %u\n", offset); +- return NULL; ++ return -EINVAL; ++} ++ ++static const struct tegra_pingroup *tegra_pinctrl_get_group(struct pinctrl_dev *pctldev, ++ unsigned int offset, ++ int group_index) ++{ ++ struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev); ++ ++ if (group_index < 0 || group_index > pmx->soc->ngroups) ++ return NULL; ++ ++ return &pmx->soc->groups[group_index]; ++} ++ ++static struct tegra_pingroup_config *tegra_pinctrl_get_group_config(struct pinctrl_dev *pctldev, ++ unsigned int offset, ++ int group_index) ++{ ++ struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev); ++ ++ if (group_index < 0) ++ return NULL; ++ ++ return &pmx->pingroup_configs[group_index]; + } + + static int tegra_pinctrl_gpio_request_enable(struct pinctrl_dev *pctldev, +@@ -306,12 +329,15 @@ static int tegra_pinctrl_gpio_request_enable(struct pinctrl_dev *pctldev, + { + struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev); + const struct tegra_pingroup *group; ++ struct tegra_pingroup_config *config; ++ int group_index; + u32 value; + + if (!pmx->soc->sfsel_in_mux) + return 0; + +- group = tegra_pinctrl_get_group(pctldev, offset); ++ group_index = tegra_pinctrl_get_group_index(pctldev, offset); ++ group = tegra_pinctrl_get_group(pctldev, offset, group_index); + + if (!group) + return -EINVAL; +@@ -319,7 +345,11 @@ static int tegra_pinctrl_gpio_request_enable(struct pinctrl_dev *pctldev, + if (group->mux_reg < 0 || group->sfsel_bit < 0) + return -EINVAL; + ++ config = tegra_pinctrl_get_group_config(pctldev, offset, group_index); ++ if (!config) ++ return -EINVAL; + value = pmx_readl(pmx, group->mux_bank, group->mux_reg); ++ config->is_sfsel = (value & BIT(group->sfsel_bit)) != 0; + value &= ~BIT(group->sfsel_bit); + pmx_writel(pmx, value, group->mux_bank, group->mux_reg); + +@@ -332,12 +362,15 @@ static void tegra_pinctrl_gpio_disable_free(struct pinctrl_dev *pctldev, + { + struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev); + const struct tegra_pingroup *group; ++ struct tegra_pingroup_config *config; ++ int group_index; + u32 value; + + if (!pmx->soc->sfsel_in_mux) + return; + +- group = tegra_pinctrl_get_group(pctldev, offset); ++ group_index = tegra_pinctrl_get_group_index(pctldev, offset); ++ group = tegra_pinctrl_get_group(pctldev, offset, group_index); + + if (!group) + return; +@@ -345,8 +378,12 @@ static void tegra_pinctrl_gpio_disable_free(struct pinctrl_dev *pctldev, + if (group->mux_reg < 0 || group->sfsel_bit < 0) + return; + ++ config = tegra_pinctrl_get_group_config(pctldev, offset, group_index); ++ if (!config) ++ return; + value = pmx_readl(pmx, group->mux_bank, group->mux_reg); +- value |= BIT(group->sfsel_bit); ++ if (config->is_sfsel) ++ value |= BIT(group->sfsel_bit); + pmx_writel(pmx, value, group->mux_bank, group->mux_reg); + } + +@@ -791,6 +828,12 @@ int tegra_pinctrl_probe(struct platform_device *pdev, + pmx->dev = &pdev->dev; + pmx->soc = soc_data; + ++ pmx->pingroup_configs = devm_kcalloc(&pdev->dev, ++ pmx->soc->ngroups, sizeof(*pmx->pingroup_configs), ++ GFP_KERNEL); ++ if (!pmx->pingroup_configs) ++ return -ENOMEM; ++ + /* + * Each mux group will appear in 4 functions' list of groups. + * This over-allocates slightly, since not all groups are mux groups. +diff --git a/drivers/pinctrl/tegra/pinctrl-tegra.h b/drivers/pinctrl/tegra/pinctrl-tegra.h +index b3289bdf727d8..b97136685f7a8 100644 +--- a/drivers/pinctrl/tegra/pinctrl-tegra.h ++++ b/drivers/pinctrl/tegra/pinctrl-tegra.h +@@ -8,6 +8,10 @@ + #ifndef __PINMUX_TEGRA_H__ + #define __PINMUX_TEGRA_H__ + ++struct tegra_pingroup_config { ++ bool is_sfsel; ++}; ++ + struct tegra_pmx { + struct device *dev; + struct pinctrl_dev *pctl; +@@ -21,6 +25,8 @@ struct tegra_pmx { + int nbanks; + void __iomem **regs; + u32 *backup_regs; ++ /* Array of size soc->ngroups */ ++ struct tegra_pingroup_config *pingroup_configs; + }; + + enum tegra_pinconf_param { +-- +2.39.5 + diff --git a/queue-6.14/platform-x86-asus-wmi-disable-oobe-state-after-resum.patch b/queue-6.14/platform-x86-asus-wmi-disable-oobe-state-after-resum.patch new file mode 100644 index 0000000000..d9a85a00b1 --- /dev/null +++ b/queue-6.14/platform-x86-asus-wmi-disable-oobe-state-after-resum.patch @@ -0,0 +1,72 @@ +From 2f6bdbaac46e46f466031836f83dece625380100 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 18 Apr 2025 20:06:08 +0600 +Subject: platform/x86: asus-wmi: Disable OOBE state after resume from + hibernation +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Pavel Nikulin + +[ Upstream commit 77bdac73754e4c0c564c1ca80fe3d9c93b0e715a ] + +ASUS firmware resets OOBE state during S4 suspend, so the keyboard +blinks during resume from hibernation. This patch disables OOBE state +after resume from hibernation. + +Signed-off-by: Pavel Nikulin +Link: https://lore.kernel.org/r/20250418140706.1691-1-pavel@noa-labs.com +Reviewed-by: Ilpo Järvinen +Signed-off-by: Ilpo Järvinen +Signed-off-by: Sasha Levin +--- + drivers/platform/x86/asus-wmi.c | 11 ++++++++++- + 1 file changed, 10 insertions(+), 1 deletion(-) + +diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c +index f66d152e265da..47cc766624d7b 100644 +--- a/drivers/platform/x86/asus-wmi.c ++++ b/drivers/platform/x86/asus-wmi.c +@@ -304,6 +304,7 @@ struct asus_wmi { + + u32 kbd_rgb_dev; + bool kbd_rgb_state_available; ++ bool oobe_state_available; + + u8 throttle_thermal_policy_mode; + u32 throttle_thermal_policy_dev; +@@ -1826,7 +1827,7 @@ static int asus_wmi_led_init(struct asus_wmi *asus) + goto error; + } + +- if (asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_OOBE)) { ++ if (asus->oobe_state_available) { + /* + * Disable OOBE state, so that e.g. the keyboard backlight + * works. +@@ -4723,6 +4724,7 @@ static int asus_wmi_add(struct platform_device *pdev) + asus->egpu_enable_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_EGPU); + asus->dgpu_disable_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_DGPU); + asus->kbd_rgb_state_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_TUF_RGB_STATE); ++ asus->oobe_state_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_OOBE); + asus->ally_mcu_usb_switch = acpi_has_method(NULL, ASUS_USB0_PWR_EC0_CSEE) + && dmi_check_system(asus_ally_mcu_quirk); + +@@ -4971,6 +4973,13 @@ static int asus_hotk_restore(struct device *device) + } + if (!IS_ERR_OR_NULL(asus->kbd_led.dev)) + kbd_led_update(asus); ++ if (asus->oobe_state_available) { ++ /* ++ * Disable OOBE state, so that e.g. the keyboard backlight ++ * works. ++ */ ++ asus_wmi_set_devstate(ASUS_WMI_DEVID_OOBE, 1, NULL); ++ } + + if (asus_wmi_has_fnlock_key(asus)) + asus_wmi_fnlock_update(asus); +-- +2.39.5 + diff --git a/queue-6.14/platform-x86-ideapad-laptop-add-support-for-some-new.patch b/queue-6.14/platform-x86-ideapad-laptop-add-support-for-some-new.patch new file mode 100644 index 0000000000..b5d4ee11a1 --- /dev/null +++ b/queue-6.14/platform-x86-ideapad-laptop-add-support-for-some-new.patch @@ -0,0 +1,63 @@ +From 73866bb954d397a9d516ae528ef345748f8d59cb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 18 Apr 2025 09:07:38 +0200 +Subject: platform/x86: ideapad-laptop: add support for some new buttons +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: GaÅ¡per Nemgar + +[ Upstream commit 02c6e43397c39edd0c172859bf8c851b46be09a8 ] + +Add entries to unsupported WMI codes in ideapad_keymap[] and one +check for WMI code 0x13d to trigger platform_profile_cycle(). + +Signed-off-by: GaÅ¡per Nemgar +Reviewed-by: Hans de Goede +Link: https://lore.kernel.org/r/20250418070738.7171-1-gasper.nemgar@gmail.com +[ij: joined nested if ()s & major tweaks to changelog] +Reviewed-by: Ilpo Järvinen +Signed-off-by: Ilpo Järvinen +Signed-off-by: Sasha Levin +--- + drivers/platform/x86/ideapad-laptop.c | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + +diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c +index 30bd366d7b58a..b740c7bb81015 100644 +--- a/drivers/platform/x86/ideapad-laptop.c ++++ b/drivers/platform/x86/ideapad-laptop.c +@@ -1308,6 +1308,16 @@ static const struct key_entry ideapad_keymap[] = { + /* Specific to some newer models */ + { KE_KEY, 0x3e | IDEAPAD_WMI_KEY, { KEY_MICMUTE } }, + { KE_KEY, 0x3f | IDEAPAD_WMI_KEY, { KEY_RFKILL } }, ++ /* Star- (User Assignable Key) */ ++ { KE_KEY, 0x44 | IDEAPAD_WMI_KEY, { KEY_PROG1 } }, ++ /* Eye */ ++ { KE_KEY, 0x45 | IDEAPAD_WMI_KEY, { KEY_PROG3 } }, ++ /* Performance toggle also Fn+Q, handled inside ideapad_wmi_notify() */ ++ { KE_KEY, 0x3d | IDEAPAD_WMI_KEY, { KEY_PROG4 } }, ++ /* shift + prtsc */ ++ { KE_KEY, 0x2d | IDEAPAD_WMI_KEY, { KEY_CUT } }, ++ { KE_KEY, 0x29 | IDEAPAD_WMI_KEY, { KEY_TOUCHPAD_TOGGLE } }, ++ { KE_KEY, 0x2a | IDEAPAD_WMI_KEY, { KEY_ROOT_MENU } }, + + { KE_END }, + }; +@@ -2094,6 +2104,12 @@ static void ideapad_wmi_notify(struct wmi_device *wdev, union acpi_object *data) + dev_dbg(&wdev->dev, "WMI fn-key event: 0x%llx\n", + data->integer.value); + ++ /* performance button triggered by 0x3d */ ++ if (data->integer.value == 0x3d && priv->dytc) { ++ platform_profile_cycle(); ++ break; ++ } ++ + /* 0x02 FnLock, 0x03 Esc */ + if (data->integer.value == 0x02 || data->integer.value == 0x03) + ideapad_fn_lock_led_notify(priv, data->integer.value == 0x02); +-- +2.39.5 + diff --git a/queue-6.14/platform-x86-intel-hid-add-pantherlake-support.patch b/queue-6.14/platform-x86-intel-hid-add-pantherlake-support.patch new file mode 100644 index 0000000000..f3b149b699 --- /dev/null +++ b/queue-6.14/platform-x86-intel-hid-add-pantherlake-support.patch @@ -0,0 +1,62 @@ +From ad0f5950300153f41b584020458be6fde6ab8dad Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 21 Apr 2025 09:43:32 +0530 +Subject: platform/x86/intel: hid: Add Pantherlake support +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Saranya Gopal + +[ Upstream commit 12df9ec3e1955aed6a0c839f2375cd8e5d5150cf ] + +Add Pantherlake ACPI device ID to the Intel HID driver. + +While there, clean up the device ID table to remove the ", 0" parts. + +Suggested-by: Andy Shevchenko +Signed-off-by: Saranya Gopal +Reviewed-by: Andy Shevchenko +Link: https://lore.kernel.org/r/20250421041332.830136-1-saranya.gopal@intel.com +Reviewed-by: Ilpo Järvinen +Signed-off-by: Ilpo Järvinen +Signed-off-by: Sasha Levin +--- + drivers/platform/x86/intel/hid.c | 21 +++++++++++---------- + 1 file changed, 11 insertions(+), 10 deletions(-) + +diff --git a/drivers/platform/x86/intel/hid.c b/drivers/platform/x86/intel/hid.c +index 88a1a9ff2f344..0b5e43444ed60 100644 +--- a/drivers/platform/x86/intel/hid.c ++++ b/drivers/platform/x86/intel/hid.c +@@ -44,16 +44,17 @@ MODULE_LICENSE("GPL"); + MODULE_AUTHOR("Alex Hung"); + + static const struct acpi_device_id intel_hid_ids[] = { +- {"INT33D5", 0}, +- {"INTC1051", 0}, +- {"INTC1054", 0}, +- {"INTC1070", 0}, +- {"INTC1076", 0}, +- {"INTC1077", 0}, +- {"INTC1078", 0}, +- {"INTC107B", 0}, +- {"INTC10CB", 0}, +- {"", 0}, ++ { "INT33D5" }, ++ { "INTC1051" }, ++ { "INTC1054" }, ++ { "INTC1070" }, ++ { "INTC1076" }, ++ { "INTC1077" }, ++ { "INTC1078" }, ++ { "INTC107B" }, ++ { "INTC10CB" }, ++ { "INTC10CC" }, ++ { } + }; + MODULE_DEVICE_TABLE(acpi, intel_hid_ids); + +-- +2.39.5 + diff --git a/queue-6.14/pm-sleep-suppress-sleeping-parent-warning-in-special.patch b/queue-6.14/pm-sleep-suppress-sleeping-parent-warning-in-special.patch new file mode 100644 index 0000000000..facbeee2b9 --- /dev/null +++ b/queue-6.14/pm-sleep-suppress-sleeping-parent-warning-in-special.patch @@ -0,0 +1,66 @@ +From 0d5d4ef580d5aef2179eaca41a58383da5a39ace Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 24 Feb 2025 15:00:49 +0800 +Subject: PM: sleep: Suppress sleeping parent warning in special case + +From: Xu Yang + +[ Upstream commit e8195f0630f1c4c2465074fe81b5fda19efd3148 ] + +Currently, if power.no_callbacks is set, device_prepare() will also set +power.direct_complete for the device. If power.direct_complete is set +in device_resume(), the clearing of power.is_prepared will be skipped +and if new children appear under the device at that point, a warning +will be printed. + +After commit (f76b168b6f11 PM: Rename dev_pm_info.in_suspend to +is_prepared), power.is_prepared is generally cleared in device_resume() +before invoking the resume callback for the device which allows that +callback to add new children without triggering the warning, but this +does not happen for devices with power.direct_complete set. + +This problem is visible in USB where usb_set_interface() can be called +before device_complete() clears power.is_prepared for interface devices +and since ep devices are added then, the warning is printed: + + usb 1-1: reset high-speed USB device number 3 using ci_hdrc + ep_81: PM: parent 1-1:1.1 should not be sleeping + PM: resume devices took 0.936 seconds + +Since it is legitimate to add the ep devices at that point, the +warning above is not particularly useful, so get rid of it by +clearing power.is_prepared in device_resume() for devices with +power.direct_complete set if they have no PM callbacks, in which +case they need not actually resume for the new children to work. + +Suggested-by: Rafael J. Wysocki +Signed-off-by: Xu Yang +Link: https://patch.msgid.link/20250224070049.3338646-1-xu.yang_2@nxp.com +[ rjw: New subject, changelog edits, rephrased new code comment ] +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Sasha Levin +--- + drivers/base/power/main.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c +index 23be2d1b04079..37fe251b4c591 100644 +--- a/drivers/base/power/main.c ++++ b/drivers/base/power/main.c +@@ -933,6 +933,13 @@ static void device_resume(struct device *dev, pm_message_t state, bool async) + goto Complete; + + if (dev->power.direct_complete) { ++ /* ++ * Allow new children to be added under the device after this ++ * point if it has no PM callbacks. ++ */ ++ if (dev->power.no_pm_callbacks) ++ dev->power.is_prepared = false; ++ + /* Match the pm_runtime_disable() in device_suspend(). */ + pm_runtime_enable(dev); + goto Complete; +-- +2.39.5 + diff --git a/queue-6.14/pmdomain-imx-gpcv2-use-proper-helper-for-property-de.patch b/queue-6.14/pmdomain-imx-gpcv2-use-proper-helper-for-property-de.patch new file mode 100644 index 0000000000..6758d5de31 --- /dev/null +++ b/queue-6.14/pmdomain-imx-gpcv2-use-proper-helper-for-property-de.patch @@ -0,0 +1,40 @@ +From 2c462087fcefe0dc4f1c8b4e92738cf1f6f6817d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 18 Feb 2025 20:18:32 +0100 +Subject: pmdomain: imx: gpcv2: use proper helper for property detection + +From: Ahmad Fatoum + +[ Upstream commit 6568cb40e73163fa25e2779f7234b169b2e1a32e ] + +Starting with commit c141ecc3cecd7 ("of: Warn when of_property_read_bool() +is used on non-boolean properties"), probing the gpcv2 device on i.MX8M +SoCs leads to warnings when LOCKDEP is enabled. + +Fix this by checking property presence with of_property_present as +intended. + +Signed-off-by: Ahmad Fatoum +Link: https://lore.kernel.org/r/20250218-gpcv2-of-property-present-v1-1-3bb1a9789654@pengutronix.de +Signed-off-by: Ulf Hansson +Signed-off-by: Sasha Levin +--- + drivers/pmdomain/imx/gpcv2.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/pmdomain/imx/gpcv2.c b/drivers/pmdomain/imx/gpcv2.c +index 958d34d4821b1..105fcaf13a34c 100644 +--- a/drivers/pmdomain/imx/gpcv2.c ++++ b/drivers/pmdomain/imx/gpcv2.c +@@ -1361,7 +1361,7 @@ static int imx_pgc_domain_probe(struct platform_device *pdev) + } + + if (IS_ENABLED(CONFIG_LOCKDEP) && +- of_property_read_bool(domain->dev->of_node, "power-domains")) ++ of_property_present(domain->dev->of_node, "power-domains")) + lockdep_set_subclass(&domain->genpd.mlock, 1); + + ret = of_genpd_add_provider_simple(domain->dev->of_node, +-- +2.39.5 + diff --git a/queue-6.14/pnfs-flexfiles-report-enetdown-as-a-connection-error.patch b/queue-6.14/pnfs-flexfiles-report-enetdown-as-a-connection-error.patch new file mode 100644 index 0000000000..cbaf5c609b --- /dev/null +++ b/queue-6.14/pnfs-flexfiles-report-enetdown-as-a-connection-error.patch @@ -0,0 +1,37 @@ +From 451ac17b0c01a9c04f2e0cad1cd7eccfb7c230c3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 20 Mar 2025 12:45:01 -0400 +Subject: pNFS/flexfiles: Report ENETDOWN as a connection error + +From: Trond Myklebust + +[ Upstream commit aa42add73ce9b9e3714723d385c254b75814e335 ] + +If the client should see an ENETDOWN when trying to connect to the data +server, it might still be able to talk to the metadata server through +another NIC. If so, report the error. + +Signed-off-by: Trond Myklebust +Reviewed-by: Jeff Layton +Tested-by: Jeff Layton +Acked-by: Chuck Lever +Signed-off-by: Sasha Levin +--- + fs/nfs/flexfilelayout/flexfilelayout.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/fs/nfs/flexfilelayout/flexfilelayout.c b/fs/nfs/flexfilelayout/flexfilelayout.c +index 98b45b636be33..646cda8e2e75b 100644 +--- a/fs/nfs/flexfilelayout/flexfilelayout.c ++++ b/fs/nfs/flexfilelayout/flexfilelayout.c +@@ -1264,6 +1264,7 @@ static void ff_layout_io_track_ds_error(struct pnfs_layout_segment *lseg, + case -ECONNRESET: + case -EHOSTDOWN: + case -EHOSTUNREACH: ++ case -ENETDOWN: + case -ENETUNREACH: + case -EADDRINUSE: + case -ENOBUFS: +-- +2.39.5 + diff --git a/queue-6.14/pnp-expand-length-of-fixup-id-string.patch b/queue-6.14/pnp-expand-length-of-fixup-id-string.patch new file mode 100644 index 0000000000..1c5dce89e8 --- /dev/null +++ b/queue-6.14/pnp-expand-length-of-fixup-id-string.patch @@ -0,0 +1,39 @@ +From a8be94f05a86a3b0c29af4e3485ff9498a9fec01 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 10 Mar 2025 15:24:33 -0700 +Subject: PNP: Expand length of fixup id string + +From: Kees Cook + +[ Upstream commit 425b1c97b07f2290700f708edabef32861e2b2db ] + +GCC 15's -Wunterminated-string-initialization saw that "id" was not +including the required trailing NUL character. Instead of marking "id" +with __nonstring[1], expand the length of the string as it is used in +(debugging) format strings that expect a properly formed C string. + +Link: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=117178 [1] +Signed-off-by: Kees Cook +Link: https://patch.msgid.link/20250310222432.work.826-kees@kernel.org +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Sasha Levin +--- + include/linux/pnp.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/include/linux/pnp.h b/include/linux/pnp.h +index b7a7158aaf65e..23fe3eaf242d6 100644 +--- a/include/linux/pnp.h ++++ b/include/linux/pnp.h +@@ -290,7 +290,7 @@ static inline void pnp_set_drvdata(struct pnp_dev *pdev, void *data) + } + + struct pnp_fixup { +- char id[7]; ++ char id[8]; + void (*quirk_function) (struct pnp_dev *dev); /* fixup function */ + }; + +-- +2.39.5 + diff --git a/queue-6.14/posix-timers-add-cond_resched-to-posix_timer_add-sea.patch b/queue-6.14/posix-timers-add-cond_resched-to-posix_timer_add-sea.patch new file mode 100644 index 0000000000..dbda0e7805 --- /dev/null +++ b/queue-6.14/posix-timers-add-cond_resched-to-posix_timer_add-sea.patch @@ -0,0 +1,41 @@ +From 54f9853297f1f7d76e42a6a92442ef6de2c79a6c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 8 Mar 2025 17:48:17 +0100 +Subject: posix-timers: Add cond_resched() to posix_timer_add() search loop + +From: Eric Dumazet + +[ Upstream commit 5f2909c6cd13564a07ae692a95457f52295c4f22 ] + +With a large number of POSIX timers the search for a valid ID might cause a +soft lockup on PREEMPT_NONE/VOLUNTARY kernels. + +Add cond_resched() to the loop to prevent that. + +[ tglx: Split out from Eric's series ] + +Signed-off-by: Eric Dumazet +Signed-off-by: Thomas Gleixner +Reviewed-by: Frederic Weisbecker +Link: https://lore.kernel.org/all/20250214135911.2037402-2-edumazet@google.com +Link: https://lore.kernel.org/all/20250308155623.635612865@linutronix.de +Signed-off-by: Sasha Levin +--- + kernel/time/posix-timers.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/kernel/time/posix-timers.c b/kernel/time/posix-timers.c +index 1b675aee99a98..7f8644e047558 100644 +--- a/kernel/time/posix-timers.c ++++ b/kernel/time/posix-timers.c +@@ -118,6 +118,7 @@ static int posix_timer_add(struct k_itimer *timer) + return id; + } + spin_unlock(&hash_lock); ++ cond_resched(); + } + /* POSIX return code when no timer ID could be allocated */ + return -EAGAIN; +-- +2.39.5 + diff --git a/queue-6.14/posix-timers-ensure-that-timer-initialization-is-ful.patch b/queue-6.14/posix-timers-ensure-that-timer-initialization-is-ful.patch new file mode 100644 index 0000000000..f0c04c2ccf --- /dev/null +++ b/queue-6.14/posix-timers-ensure-that-timer-initialization-is-ful.patch @@ -0,0 +1,84 @@ +From 5dee821ca1160182f7ecb6573872768443b3f882 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 8 Mar 2025 17:48:10 +0100 +Subject: posix-timers: Ensure that timer initialization is fully visible + +From: Thomas Gleixner + +[ Upstream commit 2389c6efd3ad8edb3bcce0019b4edcc7d9c7de19 ] + +Frederic pointed out that the memory operations to initialize the timer are +not guaranteed to be visible, when __lock_timer() observes timer::it_signal +valid under timer::it_lock: + + T0 T1 + --------- ----------- + do_timer_create() + // A + new_timer->.... = .... + spin_lock(current->sighand) + // B + WRITE_ONCE(new_timer->it_signal, current->signal) + spin_unlock(current->sighand) + sys_timer_*() + t = __lock_timer() + spin_lock(&timr->it_lock) + // observes B + if (timr->it_signal == current->signal) + return timr; + if (!t) + return; + // Is not guaranteed to observe A + +Protect the write of timer::it_signal, which makes the timer valid, with +timer::it_lock as well. This guarantees that T1 must observe the +initialization A completely, when it observes the valid signal pointer +under timer::it_lock. sighand::siglock must still be taken to protect the +signal::posix_timers list. + +Reported-by: Frederic Weisbecker +Suggested-by: Frederic Weisbecker +Signed-off-by: Thomas Gleixner +Reviewed-by: Frederic Weisbecker +Link: https://lore.kernel.org/all/20250308155623.507944489@linutronix.de +Signed-off-by: Sasha Levin +--- + kernel/time/posix-timers.c | 21 ++++++++++++++------- + 1 file changed, 14 insertions(+), 7 deletions(-) + +diff --git a/kernel/time/posix-timers.c b/kernel/time/posix-timers.c +index 7f8644e047558..15ed343693101 100644 +--- a/kernel/time/posix-timers.c ++++ b/kernel/time/posix-timers.c +@@ -463,14 +463,21 @@ static int do_timer_create(clockid_t which_clock, struct sigevent *event, + if (error) + goto out; + +- spin_lock_irq(¤t->sighand->siglock); +- /* This makes the timer valid in the hash table */ +- WRITE_ONCE(new_timer->it_signal, current->signal); +- hlist_add_head(&new_timer->list, ¤t->signal->posix_timers); +- spin_unlock_irq(¤t->sighand->siglock); + /* +- * After unlocking sighand::siglock @new_timer is subject to +- * concurrent removal and cannot be touched anymore ++ * timer::it_lock ensures that __lock_timer() observes a fully ++ * initialized timer when it observes a valid timer::it_signal. ++ * ++ * sighand::siglock is required to protect signal::posix_timers. ++ */ ++ scoped_guard (spinlock_irq, &new_timer->it_lock) { ++ guard(spinlock)(¤t->sighand->siglock); ++ /* This makes the timer valid in the hash table */ ++ WRITE_ONCE(new_timer->it_signal, current->signal); ++ hlist_add_head(&new_timer->list, ¤t->signal->posix_timers); ++ } ++ /* ++ * After unlocking @new_timer is subject to concurrent removal and ++ * cannot be touched anymore + */ + return 0; + out: +-- +2.39.5 + diff --git a/queue-6.14/posix-timers-invoke-cond_resched-during-exit_itimers.patch b/queue-6.14/posix-timers-invoke-cond_resched-during-exit_itimers.patch new file mode 100644 index 0000000000..7f962d8e0a --- /dev/null +++ b/queue-6.14/posix-timers-invoke-cond_resched-during-exit_itimers.patch @@ -0,0 +1,47 @@ +From 4bfbf33bcab0c092bf735a3ff3aed13d13102b70 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 14 Feb 2025 14:12:20 -0800 +Subject: posix-timers: Invoke cond_resched() during exit_itimers() + +From: Benjamin Segall + +[ Upstream commit f99c5bb396b8d1424ed229d1ffa6f596e3b9c36b ] + +exit_itimers() loops through every timer in the process to delete it. This +requires taking the system-wide hash_lock for each of these timers, and +contends with other processes trying to create or delete timers. + +When a process creates hundreds of thousands of timers, and then exits +while other processes contend with it, this can trigger softlockups on +CONFIG_PREEMPT=n. + +Add a cond_resched() invocation into the loop to allow the system to make +progress. + +Signed-off-by: Ben Segall +Signed-off-by: Thomas Gleixner +Link: https://lore.kernel.org/all/xm2634gg2n23.fsf@google.com +Signed-off-by: Sasha Levin +--- + kernel/time/posix-timers.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/kernel/time/posix-timers.c b/kernel/time/posix-timers.c +index 15ed343693101..43b08a04898a8 100644 +--- a/kernel/time/posix-timers.c ++++ b/kernel/time/posix-timers.c +@@ -1107,8 +1107,10 @@ void exit_itimers(struct task_struct *tsk) + spin_unlock_irq(&tsk->sighand->siglock); + + /* The timers are not longer accessible via tsk::signal */ +- while (!hlist_empty(&timers)) ++ while (!hlist_empty(&timers)) { + itimer_delete(hlist_entry(timers.first, struct k_itimer, list)); ++ cond_resched(); ++ } + + /* + * There should be no timers on the ignored list. itimer_delete() has +-- +2.39.5 + diff --git a/queue-6.14/power-supply-axp20x_battery-update-temp-sensor-for-a.patch b/queue-6.14/power-supply-axp20x_battery-update-temp-sensor-for-a.patch new file mode 100644 index 0000000000..ba6b317514 --- /dev/null +++ b/queue-6.14/power-supply-axp20x_battery-update-temp-sensor-for-a.patch @@ -0,0 +1,73 @@ +From 16229371f5b52d4b44551de83221aa3721738460 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 4 Feb 2025 09:58:33 -0600 +Subject: power: supply: axp20x_battery: Update temp sensor for AXP717 from + device tree + +From: Chris Morgan + +[ Upstream commit bbcfe510ecd47f2db4c8653c7dfa9dc7a55b1583 ] + +Allow a boolean property of "x-powers,no-thermistor" to specify devices +where the ts pin is not connected to anything. This works around an +issue found with some devices where the efuse is not programmed +correctly from the factory or when the register gets set erroneously. + +Signed-off-by: Chris Morgan +Tested-by: Philippe Simons +Link: https://lore.kernel.org/r/20250204155835.161973-4-macroalpha82@gmail.com +Signed-off-by: Sebastian Reichel +Signed-off-by: Sasha Levin +--- + drivers/power/supply/axp20x_battery.c | 21 +++++++++++++++++++++ + 1 file changed, 21 insertions(+) + +diff --git a/drivers/power/supply/axp20x_battery.c b/drivers/power/supply/axp20x_battery.c +index 3c3158f31a484..f4cf129a0b683 100644 +--- a/drivers/power/supply/axp20x_battery.c ++++ b/drivers/power/supply/axp20x_battery.c +@@ -89,6 +89,8 @@ + #define AXP717_BAT_CC_MIN_UA 0 + #define AXP717_BAT_CC_MAX_UA 3008000 + ++#define AXP717_TS_PIN_DISABLE BIT(4) ++ + struct axp20x_batt_ps; + + struct axp_data { +@@ -117,6 +119,7 @@ struct axp20x_batt_ps { + /* Maximum constant charge current */ + unsigned int max_ccc; + const struct axp_data *data; ++ bool ts_disable; + }; + + static int axp20x_battery_get_max_voltage(struct axp20x_batt_ps *axp20x_batt, +@@ -984,6 +987,24 @@ static void axp717_set_battery_info(struct platform_device *pdev, + int ccc = info->constant_charge_current_max_ua; + int val; + ++ axp_batt->ts_disable = (device_property_read_bool(axp_batt->dev, ++ "x-powers,no-thermistor")); ++ ++ /* ++ * Under rare conditions an incorrectly programmed efuse for ++ * the temp sensor on the PMIC may trigger a fault condition. ++ * Allow users to hard-code if the ts pin is not used to work ++ * around this problem. Note that this requires the battery ++ * be correctly defined in the device tree with a monitored ++ * battery node. ++ */ ++ if (axp_batt->ts_disable) { ++ regmap_update_bits(axp_batt->regmap, ++ AXP717_TS_PIN_CFG, ++ AXP717_TS_PIN_DISABLE, ++ AXP717_TS_PIN_DISABLE); ++ } ++ + if (vmin > 0 && axp717_set_voltage_min_design(axp_batt, vmin)) + dev_err(&pdev->dev, + "couldn't set voltage_min_design\n"); +-- +2.39.5 + diff --git a/queue-6.14/powerpc-prom_init-fixup-missing-size-cells-on-powerb.patch b/queue-6.14/powerpc-prom_init-fixup-missing-size-cells-on-powerb.patch new file mode 100644 index 0000000000..a39cecc603 --- /dev/null +++ b/queue-6.14/powerpc-prom_init-fixup-missing-size-cells-on-powerb.patch @@ -0,0 +1,44 @@ +From b8e7d25b817a294cc98954a6370e5e165bc9b4d9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 13 Jan 2025 18:19:09 +0100 +Subject: powerpc/prom_init: Fixup missing #size-cells on PowerBook6,7 + +From: Andreas Schwab + +[ Upstream commit 7e67ef889c9ab7246547db73d524459f47403a77 ] + +Similar to the PowerMac3,1, the PowerBook6,7 is missing the #size-cells +property on the i2s node. + +Depends-on: commit 045b14ca5c36 ("of: WARN on deprecated #address-cells/#size-cells handling") +Signed-off-by: Andreas Schwab +Acked-by: Rob Herring (Arm) +[maddy: added "commit" work in depends-on to avoid checkpatch error] +Signed-off-by: Madhavan Srinivasan +Link: https://patch.msgid.link/875xmizl6a.fsf@igel.home +Signed-off-by: Sasha Levin +--- + arch/powerpc/kernel/prom_init.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c +index 57082fac46687..fe4659ba8c22a 100644 +--- a/arch/powerpc/kernel/prom_init.c ++++ b/arch/powerpc/kernel/prom_init.c +@@ -2889,11 +2889,11 @@ static void __init fixup_device_tree_pmac(void) + char type[8]; + phandle node; + +- // Some pmacs are missing #size-cells on escc nodes ++ // Some pmacs are missing #size-cells on escc or i2s nodes + for (node = 0; prom_next_node(&node); ) { + type[0] = '\0'; + prom_getprop(node, "device_type", type, sizeof(type)); +- if (prom_strcmp(type, "escc")) ++ if (prom_strcmp(type, "escc") && prom_strcmp(type, "i2s")) + continue; + + if (prom_getproplen(node, "#size-cells") != PROM_ERROR) +-- +2.39.5 + diff --git a/queue-6.14/powerpc-pseries-iommu-create-ddw-for-devices-with-dm.patch b/queue-6.14/powerpc-pseries-iommu-create-ddw-for-devices-with-dm.patch new file mode 100644 index 0000000000..e861ffe4b5 --- /dev/null +++ b/queue-6.14/powerpc-pseries-iommu-create-ddw-for-devices-with-dm.patch @@ -0,0 +1,254 @@ +From 8358716a4e6e3020214056e372fc7cfed698fcc1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 8 Jan 2025 10:48:14 -0600 +Subject: powerpc/pseries/iommu: create DDW for devices with DMA mask less than + 64-bits + +From: Gaurav Batra + +[ Upstream commit 67dfc11982f7e3c37f0977e74671da2391b29181 ] + +Starting with PAPR level 2.13, platform supports placing PHB in limited +address mode. Devices that support DMA masks less that 64-bit but greater +than 32-bits are placed in limited address mode. In this mode, the +starting DMA address returned by the DDW is 4GB. + +When the device driver calls dma_supported, with mask less then 64-bit, the +PowerPC IOMMU driver places PHB in the Limited Addressing Mode before +creating DDW. + +Signed-off-by: Gaurav Batra +Signed-off-by: Madhavan Srinivasan +Link: https://patch.msgid.link/20250108164814.73250-1-gbatra@linux.ibm.com +Signed-off-by: Sasha Levin +--- + arch/powerpc/platforms/pseries/iommu.c | 110 +++++++++++++++++++++---- + 1 file changed, 94 insertions(+), 16 deletions(-) + +diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c +index 8f32340960e21..d6ebc19fb99c5 100644 +--- a/arch/powerpc/platforms/pseries/iommu.c ++++ b/arch/powerpc/platforms/pseries/iommu.c +@@ -52,7 +52,8 @@ enum { + enum { + DDW_EXT_SIZE = 0, + DDW_EXT_RESET_DMA_WIN = 1, +- DDW_EXT_QUERY_OUT_SIZE = 2 ++ DDW_EXT_QUERY_OUT_SIZE = 2, ++ DDW_EXT_LIMITED_ADDR_MODE = 3 + }; + + static struct iommu_table *iommu_pseries_alloc_table(int node) +@@ -1327,6 +1328,54 @@ static void reset_dma_window(struct pci_dev *dev, struct device_node *par_dn) + ret); + } + ++/* ++ * Platforms support placing PHB in limited address mode starting with LoPAR ++ * level 2.13 implement. In this mode, the DMA address returned by DDW is over ++ * 4GB but, less than 64-bits. This benefits IO adapters that don't support ++ * 64-bits for DMA addresses. ++ */ ++static int limited_dma_window(struct pci_dev *dev, struct device_node *par_dn) ++{ ++ int ret; ++ u32 cfg_addr, reset_dma_win, las_supported; ++ u64 buid; ++ struct device_node *dn; ++ struct pci_dn *pdn; ++ ++ ret = ddw_read_ext(par_dn, DDW_EXT_RESET_DMA_WIN, &reset_dma_win); ++ if (ret) ++ goto out; ++ ++ ret = ddw_read_ext(par_dn, DDW_EXT_LIMITED_ADDR_MODE, &las_supported); ++ ++ /* Limited Address Space extension available on the platform but DDW in ++ * limited addressing mode not supported ++ */ ++ if (!ret && !las_supported) ++ ret = -EPROTO; ++ ++ if (ret) { ++ dev_info(&dev->dev, "Limited Address Space for DDW not Supported, err: %d", ret); ++ goto out; ++ } ++ ++ dn = pci_device_to_OF_node(dev); ++ pdn = PCI_DN(dn); ++ buid = pdn->phb->buid; ++ cfg_addr = (pdn->busno << 16) | (pdn->devfn << 8); ++ ++ ret = rtas_call(reset_dma_win, 4, 1, NULL, cfg_addr, BUID_HI(buid), ++ BUID_LO(buid), 1); ++ if (ret) ++ dev_info(&dev->dev, ++ "ibm,reset-pe-dma-windows(%x) for Limited Addr Support: %x %x %x returned %d ", ++ reset_dma_win, cfg_addr, BUID_HI(buid), BUID_LO(buid), ++ ret); ++ ++out: ++ return ret; ++} ++ + /* Return largest page shift based on "IO Page Sizes" output of ibm,query-pe-dma-window. */ + static int iommu_get_page_shift(u32 query_page_size) + { +@@ -1394,7 +1443,7 @@ static struct property *ddw_property_create(const char *propname, u32 liobn, u64 + * + * returns true if can map all pages (direct mapping), false otherwise.. + */ +-static bool enable_ddw(struct pci_dev *dev, struct device_node *pdn) ++static bool enable_ddw(struct pci_dev *dev, struct device_node *pdn, u64 dma_mask) + { + int len = 0, ret; + int max_ram_len = order_base_2(ddw_memory_hotplug_max()); +@@ -1413,6 +1462,9 @@ static bool enable_ddw(struct pci_dev *dev, struct device_node *pdn) + bool pmem_present; + struct pci_dn *pci = PCI_DN(pdn); + struct property *default_win = NULL; ++ bool limited_addr_req = false, limited_addr_enabled = false; ++ int dev_max_ddw; ++ int ddw_sz; + + dn = of_find_node_by_type(NULL, "ibm,pmemory"); + pmem_present = dn != NULL; +@@ -1439,7 +1491,6 @@ static bool enable_ddw(struct pci_dev *dev, struct device_node *pdn) + * the ibm,ddw-applicable property holds the tokens for: + * ibm,query-pe-dma-window + * ibm,create-pe-dma-window +- * ibm,remove-pe-dma-window + * for the given node in that order. + * the property is actually in the parent, not the PE + */ +@@ -1459,6 +1510,20 @@ static bool enable_ddw(struct pci_dev *dev, struct device_node *pdn) + if (ret != 0) + goto out_failed; + ++ /* DMA Limited Addressing required? This is when the driver has ++ * requested to create DDW but supports mask which is less than 64-bits ++ */ ++ limited_addr_req = (dma_mask != DMA_BIT_MASK(64)); ++ ++ /* place the PHB in Limited Addressing mode */ ++ if (limited_addr_req) { ++ if (limited_dma_window(dev, pdn)) ++ goto out_failed; ++ ++ /* PHB is in Limited address mode */ ++ limited_addr_enabled = true; ++ } ++ + /* + * If there is no window available, remove the default DMA window, + * if it's present. This will make all the resources available to the +@@ -1505,6 +1570,15 @@ static bool enable_ddw(struct pci_dev *dev, struct device_node *pdn) + goto out_failed; + } + ++ /* Maximum DMA window size that the device can address (in log2) */ ++ dev_max_ddw = fls64(dma_mask); ++ ++ /* If the device DMA mask is less than 64-bits, make sure the DMA window ++ * size is not bigger than what the device can access ++ */ ++ ddw_sz = min(order_base_2(query.largest_available_block << page_shift), ++ dev_max_ddw); ++ + /* + * The "ibm,pmemory" can appear anywhere in the address space. + * Assuming it is still backed by page structs, try MAX_PHYSMEM_BITS +@@ -1513,23 +1587,21 @@ static bool enable_ddw(struct pci_dev *dev, struct device_node *pdn) + */ + len = max_ram_len; + if (pmem_present) { +- if (query.largest_available_block >= +- (1ULL << (MAX_PHYSMEM_BITS - page_shift))) ++ if (ddw_sz >= MAX_PHYSMEM_BITS) + len = MAX_PHYSMEM_BITS; + else + dev_info(&dev->dev, "Skipping ibm,pmemory"); + } + + /* check if the available block * number of ptes will map everything */ +- if (query.largest_available_block < (1ULL << (len - page_shift))) { ++ if (ddw_sz < len) { + dev_dbg(&dev->dev, + "can't map partition max 0x%llx with %llu %llu-sized pages\n", + 1ULL << len, + query.largest_available_block, + 1ULL << page_shift); + +- len = order_base_2(query.largest_available_block << page_shift); +- ++ len = ddw_sz; + dynamic_mapping = true; + } else { + direct_mapping = !default_win_removed || +@@ -1543,8 +1615,9 @@ static bool enable_ddw(struct pci_dev *dev, struct device_node *pdn) + */ + if (default_win_removed && pmem_present && !direct_mapping) { + /* DDW is big enough to be split */ +- if ((query.largest_available_block << page_shift) >= +- MIN_DDW_VPMEM_DMA_WINDOW + (1ULL << max_ram_len)) { ++ if ((1ULL << ddw_sz) >= ++ MIN_DDW_VPMEM_DMA_WINDOW + (1ULL << max_ram_len)) { ++ + direct_mapping = true; + + /* offset of the Dynamic part of DDW */ +@@ -1555,8 +1628,7 @@ static bool enable_ddw(struct pci_dev *dev, struct device_node *pdn) + dynamic_mapping = true; + + /* create max size DDW possible */ +- len = order_base_2(query.largest_available_block +- << page_shift); ++ len = ddw_sz; + } + } + +@@ -1685,7 +1757,7 @@ static bool enable_ddw(struct pci_dev *dev, struct device_node *pdn) + __remove_dma_window(pdn, ddw_avail, create.liobn); + + out_failed: +- if (default_win_removed) ++ if (default_win_removed || limited_addr_enabled) + reset_dma_window(dev, pdn); + + fpdn = kzalloc(sizeof(*fpdn), GFP_KERNEL); +@@ -1704,6 +1776,9 @@ static bool enable_ddw(struct pci_dev *dev, struct device_node *pdn) + dev->dev.bus_dma_limit = dev->dev.archdata.dma_offset + + (1ULL << max_ram_len); + ++ dev_info(&dev->dev, "lsa_required: %x, lsa_enabled: %x, direct mapping: %x\n", ++ limited_addr_req, limited_addr_enabled, direct_mapping); ++ + return direct_mapping; + } + +@@ -1829,8 +1904,11 @@ static bool iommu_bypass_supported_pSeriesLP(struct pci_dev *pdev, u64 dma_mask) + { + struct device_node *dn = pci_device_to_OF_node(pdev), *pdn; + +- /* only attempt to use a new window if 64-bit DMA is requested */ +- if (dma_mask < DMA_BIT_MASK(64)) ++ /* For DDW, DMA mask should be more than 32-bits. For mask more then ++ * 32-bits but less then 64-bits, DMA addressing is supported in ++ * Limited Addressing mode. ++ */ ++ if (dma_mask <= DMA_BIT_MASK(32)) + return false; + + dev_dbg(&pdev->dev, "node is %pOF\n", dn); +@@ -1843,7 +1921,7 @@ static bool iommu_bypass_supported_pSeriesLP(struct pci_dev *pdev, u64 dma_mask) + */ + pdn = pci_dma_find(dn, NULL); + if (pdn && PCI_DN(pdn)) +- return enable_ddw(pdev, pdn); ++ return enable_ddw(pdev, pdn, dma_mask); + + return false; + } +-- +2.39.5 + diff --git a/queue-6.14/powerpc-pseries-iommu-memory-notifier-incorrectly-ad.patch b/queue-6.14/powerpc-pseries-iommu-memory-notifier-incorrectly-ad.patch new file mode 100644 index 0000000000..6bb40ad2b6 --- /dev/null +++ b/queue-6.14/powerpc-pseries-iommu-memory-notifier-incorrectly-ad.patch @@ -0,0 +1,138 @@ +From 1fbfc79441ae608a10f614018a4b1ce2437cd04f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 30 Jan 2025 12:38:54 -0600 +Subject: powerpc/pseries/iommu: memory notifier incorrectly adds TCEs for + pmemory + +From: Gaurav Batra + +[ Upstream commit 6aa989ab2bd0d37540c812b4270006ff794662e7 ] + +iommu_mem_notifier() is invoked when RAM is dynamically added/removed. This +notifier call is responsible to add/remove TCEs from the Dynamic DMA Window +(DDW) when TCEs are pre-mapped. TCEs are pre-mapped only for RAM and not +for persistent memory (pmemory). For DMA buffers in pmemory, TCEs are +dynamically mapped when the device driver instructs to do so. + +The issue is 'daxctl' command is capable of adding pmemory as "System RAM" +after LPAR boot. The command to do so is - + +daxctl reconfigure-device --mode=system-ram dax0.0 --force + +This will dynamically add pmemory range to LPAR RAM eventually invoking +iommu_mem_notifier(). The address range of pmemory is way beyond the Max +RAM that the LPAR can have. Which means, this range is beyond the DDW +created for the device, at device initialization time. + +As a result when TCEs are pre-mapped for the pmemory range, by +iommu_mem_notifier(), PHYP HCALL returns H_PARAMETER. This failed the +command, daxctl, to add pmemory as RAM. + +The solution is to not pre-map TCEs for pmemory. + +Signed-off-by: Gaurav Batra +Tested-by: Donet Tom +Reviewed-by: Donet Tom +Signed-off-by: Madhavan Srinivasan +Link: https://patch.msgid.link/20250130183854.92258-1-gbatra@linux.ibm.com +Signed-off-by: Sasha Levin +--- + arch/powerpc/include/asm/mmzone.h | 1 + + arch/powerpc/mm/numa.c | 2 +- + arch/powerpc/platforms/pseries/iommu.c | 29 ++++++++++++++------------ + 3 files changed, 18 insertions(+), 14 deletions(-) + +diff --git a/arch/powerpc/include/asm/mmzone.h b/arch/powerpc/include/asm/mmzone.h +index d99863cd6cde4..049152f8d597a 100644 +--- a/arch/powerpc/include/asm/mmzone.h ++++ b/arch/powerpc/include/asm/mmzone.h +@@ -29,6 +29,7 @@ extern cpumask_var_t node_to_cpumask_map[]; + #ifdef CONFIG_MEMORY_HOTPLUG + extern unsigned long max_pfn; + u64 memory_hotplug_max(void); ++u64 hot_add_drconf_memory_max(void); + #else + #define memory_hotplug_max() memblock_end_of_DRAM() + #endif +diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c +index 3c1da08304d03..603a0f652ba61 100644 +--- a/arch/powerpc/mm/numa.c ++++ b/arch/powerpc/mm/numa.c +@@ -1336,7 +1336,7 @@ int hot_add_scn_to_nid(unsigned long scn_addr) + return nid; + } + +-static u64 hot_add_drconf_memory_max(void) ++u64 hot_add_drconf_memory_max(void) + { + struct device_node *memory = NULL; + struct device_node *dn = NULL; +diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c +index ae6f7a235d8b2..8f32340960e21 100644 +--- a/arch/powerpc/platforms/pseries/iommu.c ++++ b/arch/powerpc/platforms/pseries/iommu.c +@@ -1284,17 +1284,13 @@ static LIST_HEAD(failed_ddw_pdn_list); + + static phys_addr_t ddw_memory_hotplug_max(void) + { +- resource_size_t max_addr = memory_hotplug_max(); +- struct device_node *memory; ++ resource_size_t max_addr; + +- for_each_node_by_type(memory, "memory") { +- struct resource res; +- +- if (of_address_to_resource(memory, 0, &res)) +- continue; +- +- max_addr = max_t(resource_size_t, max_addr, res.end + 1); +- } ++#if defined(CONFIG_NUMA) && defined(CONFIG_MEMORY_HOTPLUG) ++ max_addr = hot_add_drconf_memory_max(); ++#else ++ max_addr = memblock_end_of_DRAM(); ++#endif + + return max_addr; + } +@@ -1600,7 +1596,7 @@ static bool enable_ddw(struct pci_dev *dev, struct device_node *pdn) + + if (direct_mapping) { + /* DDW maps the whole partition, so enable direct DMA mapping */ +- ret = walk_system_ram_range(0, memblock_end_of_DRAM() >> PAGE_SHIFT, ++ ret = walk_system_ram_range(0, ddw_memory_hotplug_max() >> PAGE_SHIFT, + win64->value, tce_setrange_multi_pSeriesLP_walk); + if (ret) { + dev_info(&dev->dev, "failed to map DMA window for %pOF: %d\n", +@@ -2349,11 +2345,17 @@ static int iommu_mem_notifier(struct notifier_block *nb, unsigned long action, + struct memory_notify *arg = data; + int ret = 0; + ++ /* This notifier can get called when onlining persistent memory as well. ++ * TCEs are not pre-mapped for persistent memory. Persistent memory will ++ * always be above ddw_memory_hotplug_max() ++ */ ++ + switch (action) { + case MEM_GOING_ONLINE: + spin_lock(&dma_win_list_lock); + list_for_each_entry(window, &dma_win_list, list) { +- if (window->direct) { ++ if (window->direct && (arg->start_pfn << PAGE_SHIFT) < ++ ddw_memory_hotplug_max()) { + ret |= tce_setrange_multi_pSeriesLP(arg->start_pfn, + arg->nr_pages, window->prop); + } +@@ -2365,7 +2367,8 @@ static int iommu_mem_notifier(struct notifier_block *nb, unsigned long action, + case MEM_OFFLINE: + spin_lock(&dma_win_list_lock); + list_for_each_entry(window, &dma_win_list, list) { +- if (window->direct) { ++ if (window->direct && (arg->start_pfn << PAGE_SHIFT) < ++ ddw_memory_hotplug_max()) { + ret |= tce_clearrange_multi_pSeriesLP(arg->start_pfn, + arg->nr_pages, window->prop); + } +-- +2.39.5 + diff --git a/queue-6.14/pps-generators-replace-copy-of-pps-gen-info-struct-w.patch b/queue-6.14/pps-generators-replace-copy-of-pps-gen-info-struct-w.patch new file mode 100644 index 0000000000..027efdf4b4 --- /dev/null +++ b/queue-6.14/pps-generators-replace-copy-of-pps-gen-info-struct-w.patch @@ -0,0 +1,209 @@ +From 8e6bfa71e2461e583456123e2842878a229aa981 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 19 Feb 2025 09:36:15 +0530 +Subject: pps: generators: replace copy of pps-gen info struct with const + pointer + +From: Subramanian Mohan + +[ Upstream commit ac9c5170a18162d45c6edd1f0fa2d2b2504bc2cb ] + +Some PPS generator drivers may need to retrieve a pointer to their +internal data while executing the PPS generator enable() method. + +During the driver registration the pps_gen_device pointer is returned +from the framework, and for that reason, there is difficulty in +getting generator driver data back in the enable function. We won't be +able to use container_of macro as it results in static assert, and we +might end up in using static pointer. + +To solve the issue and to get back the generator driver data back, we +should not copy the struct pps_gen_source_info within the struct +pps_gen_device during the registration stage, but simply save the +pointer of the driver one. In this manner, driver may get a pointer +to their internal data as shown below: + +struct pps_gen_foo_data_s { + ... + struct pps_gen_source_info gen_info; + struct pps_gen_device *pps_gen; + ... +}; + +static int __init pps_gen_foo_init(void) +{ + struct pps_gen_foo_data_s *foo; + ... + foo->pps_gen = pps_gen_register_source(&foo->gen_info); + ... +} + +Then, in the enable() method, we can retrieve the pointer to the main +struct by using the code below: + +static int pps_gen_foo_enable(struct pps_gen_device *pps_gen, bool enable) +{ + struct pps_gen_foo_data_s *foo = container_of(pps_gen->info, + struct pps_gen_foo_data_s, gen_info); + ... +} + +Signed-off-by: Rodolfo Giometti +Tested-by: Subramanian Mohan +Suggested-by: Andy Shevchenko +Reviewed-by: Andy Shevchenko +Signed-off-by: Subramanian Mohan +Link: https://lore.kernel.org/r/20250219040618.70962-2-subramanian.mohan@intel.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + Documentation/driver-api/pps.rst | 3 +-- + drivers/pps/generators/pps_gen-dummy.c | 2 +- + drivers/pps/generators/pps_gen.c | 14 +++++++------- + drivers/pps/generators/sysfs.c | 6 +++--- + include/linux/pps_gen_kernel.h | 4 ++-- + 5 files changed, 14 insertions(+), 15 deletions(-) + +diff --git a/Documentation/driver-api/pps.rst b/Documentation/driver-api/pps.rst +index 71ad04c82d6cf..04f1b88778fc5 100644 +--- a/Documentation/driver-api/pps.rst ++++ b/Documentation/driver-api/pps.rst +@@ -206,8 +206,7 @@ To do so the class pps-gen has been added. PPS generators can be + registered in the kernel by defining a struct pps_gen_source_info as + follows:: + +- static struct pps_gen_source_info pps_gen_dummy_info = { +- .name = "dummy", ++ static const struct pps_gen_source_info pps_gen_dummy_info = { + .use_system_clock = true, + .get_time = pps_gen_dummy_get_time, + .enable = pps_gen_dummy_enable, +diff --git a/drivers/pps/generators/pps_gen-dummy.c b/drivers/pps/generators/pps_gen-dummy.c +index b284c200cbe50..55de4aecf35ed 100644 +--- a/drivers/pps/generators/pps_gen-dummy.c ++++ b/drivers/pps/generators/pps_gen-dummy.c +@@ -61,7 +61,7 @@ static int pps_gen_dummy_enable(struct pps_gen_device *pps_gen, bool enable) + * The PPS info struct + */ + +-static struct pps_gen_source_info pps_gen_dummy_info = { ++static const struct pps_gen_source_info pps_gen_dummy_info = { + .use_system_clock = true, + .get_time = pps_gen_dummy_get_time, + .enable = pps_gen_dummy_enable, +diff --git a/drivers/pps/generators/pps_gen.c b/drivers/pps/generators/pps_gen.c +index ca592f1736f46..5b8bb454913cd 100644 +--- a/drivers/pps/generators/pps_gen.c ++++ b/drivers/pps/generators/pps_gen.c +@@ -66,7 +66,7 @@ static long pps_gen_cdev_ioctl(struct file *file, + if (ret) + return -EFAULT; + +- ret = pps_gen->info.enable(pps_gen, status); ++ ret = pps_gen->info->enable(pps_gen, status); + if (ret) + return ret; + pps_gen->enabled = status; +@@ -76,7 +76,7 @@ static long pps_gen_cdev_ioctl(struct file *file, + case PPS_GEN_USESYSTEMCLOCK: + dev_dbg(pps_gen->dev, "PPS_GEN_USESYSTEMCLOCK\n"); + +- ret = put_user(pps_gen->info.use_system_clock, uiuarg); ++ ret = put_user(pps_gen->info->use_system_clock, uiuarg); + if (ret) + return -EFAULT; + +@@ -175,7 +175,7 @@ static int pps_gen_register_cdev(struct pps_gen_device *pps_gen) + devt = MKDEV(MAJOR(pps_gen_devt), pps_gen->id); + + cdev_init(&pps_gen->cdev, &pps_gen_cdev_fops); +- pps_gen->cdev.owner = pps_gen->info.owner; ++ pps_gen->cdev.owner = pps_gen->info->owner; + + err = cdev_add(&pps_gen->cdev, devt, 1); + if (err) { +@@ -183,8 +183,8 @@ static int pps_gen_register_cdev(struct pps_gen_device *pps_gen) + MAJOR(pps_gen_devt), pps_gen->id); + goto free_ida; + } +- pps_gen->dev = device_create(pps_gen_class, pps_gen->info.parent, devt, +- pps_gen, "pps-gen%d", pps_gen->id); ++ pps_gen->dev = device_create(pps_gen_class, pps_gen->info->parent, devt, ++ pps_gen, "pps-gen%d", pps_gen->id); + if (IS_ERR(pps_gen->dev)) { + err = PTR_ERR(pps_gen->dev); + goto del_cdev; +@@ -225,7 +225,7 @@ static void pps_gen_unregister_cdev(struct pps_gen_device *pps_gen) + * Return: the PPS generator device in case of success, and ERR_PTR(errno) + * otherwise. + */ +-struct pps_gen_device *pps_gen_register_source(struct pps_gen_source_info *info) ++struct pps_gen_device *pps_gen_register_source(const struct pps_gen_source_info *info) + { + struct pps_gen_device *pps_gen; + int err; +@@ -235,7 +235,7 @@ struct pps_gen_device *pps_gen_register_source(struct pps_gen_source_info *info) + err = -ENOMEM; + goto pps_gen_register_source_exit; + } +- pps_gen->info = *info; ++ pps_gen->info = info; + pps_gen->enabled = false; + + init_waitqueue_head(&pps_gen->queue); +diff --git a/drivers/pps/generators/sysfs.c b/drivers/pps/generators/sysfs.c +index faf8b1c6d2026..6d6bc0006feae 100644 +--- a/drivers/pps/generators/sysfs.c ++++ b/drivers/pps/generators/sysfs.c +@@ -19,7 +19,7 @@ static ssize_t system_show(struct device *dev, struct device_attribute *attr, + { + struct pps_gen_device *pps_gen = dev_get_drvdata(dev); + +- return sysfs_emit(buf, "%d\n", pps_gen->info.use_system_clock); ++ return sysfs_emit(buf, "%d\n", pps_gen->info->use_system_clock); + } + static DEVICE_ATTR_RO(system); + +@@ -30,7 +30,7 @@ static ssize_t time_show(struct device *dev, struct device_attribute *attr, + struct timespec64 time; + int ret; + +- ret = pps_gen->info.get_time(pps_gen, &time); ++ ret = pps_gen->info->get_time(pps_gen, &time); + if (ret) + return ret; + +@@ -49,7 +49,7 @@ static ssize_t enable_store(struct device *dev, struct device_attribute *attr, + if (ret) + return ret; + +- ret = pps_gen->info.enable(pps_gen, status); ++ ret = pps_gen->info->enable(pps_gen, status); + if (ret) + return ret; + pps_gen->enabled = status; +diff --git a/include/linux/pps_gen_kernel.h b/include/linux/pps_gen_kernel.h +index 022ea0ac44402..6214c8aa2e020 100644 +--- a/include/linux/pps_gen_kernel.h ++++ b/include/linux/pps_gen_kernel.h +@@ -43,7 +43,7 @@ struct pps_gen_source_info { + + /* The main struct */ + struct pps_gen_device { +- struct pps_gen_source_info info; /* PSS generator info */ ++ const struct pps_gen_source_info *info; /* PSS generator info */ + bool enabled; /* PSS generator status */ + + unsigned int event; +@@ -70,7 +70,7 @@ extern const struct attribute_group *pps_gen_groups[]; + */ + + extern struct pps_gen_device *pps_gen_register_source( +- struct pps_gen_source_info *info); ++ const struct pps_gen_source_info *info); + extern void pps_gen_unregister_source(struct pps_gen_device *pps_gen); + extern void pps_gen_event(struct pps_gen_device *pps_gen, + unsigned int event, void *data); +-- +2.39.5 + diff --git a/queue-6.14/printk-check-con_suspend-when-unblanking-a-console.patch b/queue-6.14/printk-check-con_suspend-when-unblanking-a-console.patch new file mode 100644 index 0000000000..cecaef0c86 --- /dev/null +++ b/queue-6.14/printk-check-con_suspend-when-unblanking-a-console.patch @@ -0,0 +1,59 @@ +From 0ba11f5899d2bcc85999ef2570fbc5e8aaa57ee1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 26 Feb 2025 16:59:05 -0300 +Subject: printk: Check CON_SUSPEND when unblanking a console + +From: Marcos Paulo de Souza + +[ Upstream commit 72c96a2dacc0fb056d13a5f02b0845c4c910fe54 ] + +The commit 9e70a5e109a4 ("printk: Add per-console suspended state") +introduced the CON_SUSPENDED flag for consoles. The suspended consoles +will stop receiving messages, so don't unblank suspended consoles +because it won't be showing anything either way. + +Signed-off-by: Marcos Paulo de Souza +Reviewed-by: Petr Mladek +Reviewed-by: John Ogness +Link: https://lore.kernel.org/r/20250226-printk-renaming-v1-5-0b878577f2e6@suse.com +Signed-off-by: Petr Mladek +Signed-off-by: Sasha Levin +--- + kernel/printk/printk.c | 14 ++++++++++++-- + 1 file changed, 12 insertions(+), 2 deletions(-) + +diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c +index 057db78876cd9..13d4210d8862f 100644 +--- a/kernel/printk/printk.c ++++ b/kernel/printk/printk.c +@@ -3340,7 +3340,12 @@ void console_unblank(void) + */ + cookie = console_srcu_read_lock(); + for_each_console_srcu(c) { +- if ((console_srcu_read_flags(c) & CON_ENABLED) && c->unblank) { ++ short flags = console_srcu_read_flags(c); ++ ++ if (flags & CON_SUSPENDED) ++ continue; ++ ++ if ((flags & CON_ENABLED) && c->unblank) { + found_unblank = true; + break; + } +@@ -3377,7 +3382,12 @@ void console_unblank(void) + + cookie = console_srcu_read_lock(); + for_each_console_srcu(c) { +- if ((console_srcu_read_flags(c) & CON_ENABLED) && c->unblank) ++ short flags = console_srcu_read_flags(c); ++ ++ if (flags & CON_SUSPENDED) ++ continue; ++ ++ if ((flags & CON_ENABLED) && c->unblank) + c->unblank(); + } + console_srcu_read_unlock(cookie); +-- +2.39.5 + diff --git a/queue-6.14/pstore-change-kmsg_bytes-storage-size-to-u32.patch b/queue-6.14/pstore-change-kmsg_bytes-storage-size-to-u32.patch new file mode 100644 index 0000000000..aa301a7229 --- /dev/null +++ b/queue-6.14/pstore-change-kmsg_bytes-storage-size-to-u32.patch @@ -0,0 +1,108 @@ +From f5fe211102d16dff51d226f87b041ee567092341 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Feb 2025 11:16:59 -0800 +Subject: pstore: Change kmsg_bytes storage size to u32 + +From: Kees Cook + +[ Upstream commit 5674609535bafa834ab014d90d9bbe8e89223a0b ] + +The types around kmsg_bytes were inconsistent. The global was unsigned +long, the argument to pstore_set_kmsg_bytes() was int, and the filesystem +option was u32. Given other internal limits, there's not much sense +in making a single pstore record larger than INT_MAX and it can't be +negative, so use u32 everywhere. Additionally, use READ/WRITE_ONCE and a +local variable in pstore_dump() to avoid kmsg_bytes changing during a +dump. + +Link: https://lore.kernel.org/r/20250206191655.work.798-kees@kernel.org +Signed-off-by: Kees Cook +Signed-off-by: Sasha Levin +--- + fs/pstore/inode.c | 2 +- + fs/pstore/internal.h | 4 ++-- + fs/pstore/platform.c | 11 ++++++----- + 3 files changed, 9 insertions(+), 8 deletions(-) + +diff --git a/fs/pstore/inode.c b/fs/pstore/inode.c +index 56815799ce798..9de6b280c4f41 100644 +--- a/fs/pstore/inode.c ++++ b/fs/pstore/inode.c +@@ -265,7 +265,7 @@ static void parse_options(char *options) + static int pstore_show_options(struct seq_file *m, struct dentry *root) + { + if (kmsg_bytes != CONFIG_PSTORE_DEFAULT_KMSG_BYTES) +- seq_printf(m, ",kmsg_bytes=%lu", kmsg_bytes); ++ seq_printf(m, ",kmsg_bytes=%u", kmsg_bytes); + return 0; + } + +diff --git a/fs/pstore/internal.h b/fs/pstore/internal.h +index 801d6c0b170c3..a0fc511969100 100644 +--- a/fs/pstore/internal.h ++++ b/fs/pstore/internal.h +@@ -6,7 +6,7 @@ + #include + #include + +-extern unsigned long kmsg_bytes; ++extern unsigned int kmsg_bytes; + + #ifdef CONFIG_PSTORE_FTRACE + extern void pstore_register_ftrace(void); +@@ -35,7 +35,7 @@ static inline void pstore_unregister_pmsg(void) {} + + extern struct pstore_info *psinfo; + +-extern void pstore_set_kmsg_bytes(int); ++extern void pstore_set_kmsg_bytes(unsigned int bytes); + extern void pstore_get_records(int); + extern void pstore_get_backend_records(struct pstore_info *psi, + struct dentry *root, int quiet); +diff --git a/fs/pstore/platform.c b/fs/pstore/platform.c +index f56b066ab80ce..557cf9d40177f 100644 +--- a/fs/pstore/platform.c ++++ b/fs/pstore/platform.c +@@ -92,8 +92,8 @@ module_param(compress, charp, 0444); + MODULE_PARM_DESC(compress, "compression to use"); + + /* How much of the kernel log to snapshot */ +-unsigned long kmsg_bytes = CONFIG_PSTORE_DEFAULT_KMSG_BYTES; +-module_param(kmsg_bytes, ulong, 0444); ++unsigned int kmsg_bytes = CONFIG_PSTORE_DEFAULT_KMSG_BYTES; ++module_param(kmsg_bytes, uint, 0444); + MODULE_PARM_DESC(kmsg_bytes, "amount of kernel log to snapshot (in bytes)"); + + static void *compress_workspace; +@@ -107,9 +107,9 @@ static void *compress_workspace; + static char *big_oops_buf; + static size_t max_compressed_size; + +-void pstore_set_kmsg_bytes(int bytes) ++void pstore_set_kmsg_bytes(unsigned int bytes) + { +- kmsg_bytes = bytes; ++ WRITE_ONCE(kmsg_bytes, bytes); + } + + /* Tag each group of saved records with a sequence number */ +@@ -278,6 +278,7 @@ static void pstore_dump(struct kmsg_dumper *dumper, + struct kmsg_dump_detail *detail) + { + struct kmsg_dump_iter iter; ++ unsigned int remaining = READ_ONCE(kmsg_bytes); + unsigned long total = 0; + const char *why; + unsigned int part = 1; +@@ -300,7 +301,7 @@ static void pstore_dump(struct kmsg_dumper *dumper, + kmsg_dump_rewind(&iter); + + oopscount++; +- while (total < kmsg_bytes) { ++ while (total < remaining) { + char *dst; + size_t dst_size; + int header_size; +-- +2.39.5 + diff --git a/queue-6.14/r8152-add-vendor-device-id-pair-for-dell-alienware-a.patch b/queue-6.14/r8152-add-vendor-device-id-pair-for-dell-alienware-a.patch new file mode 100644 index 0000000000..4a0570f0d8 --- /dev/null +++ b/queue-6.14/r8152-add-vendor-device-id-pair-for-dell-alienware-a.patch @@ -0,0 +1,50 @@ +From 6466f721e5b1a5650bb9ce23f1fe7cb3f9195c6f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Feb 2025 23:40:33 +0100 +Subject: r8152: add vendor/device ID pair for Dell Alienware AW1022z + +From: Aleksander Jan Bajkowski + +[ Upstream commit 848b09d53d923b4caee5491f57a5c5b22d81febc ] + +The Dell AW1022z is an RTL8156B based 2.5G Ethernet controller. + +Add the vendor and product ID values to the driver. This makes Ethernet +work with the adapter. + +Signed-off-by: Aleksander Jan Bajkowski +Link: https://patch.msgid.link/20250206224033.980115-1-olek2@wp.pl +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/usb/r8152.c | 1 + + include/linux/usb/r8152.h | 1 + + 2 files changed, 2 insertions(+) + +diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c +index 96fa3857d8e25..2cab046749a92 100644 +--- a/drivers/net/usb/r8152.c ++++ b/drivers/net/usb/r8152.c +@@ -10085,6 +10085,7 @@ static const struct usb_device_id rtl8152_table[] = { + { USB_DEVICE(VENDOR_ID_NVIDIA, 0x09ff) }, + { USB_DEVICE(VENDOR_ID_TPLINK, 0x0601) }, + { USB_DEVICE(VENDOR_ID_DLINK, 0xb301) }, ++ { USB_DEVICE(VENDOR_ID_DELL, 0xb097) }, + { USB_DEVICE(VENDOR_ID_ASUS, 0x1976) }, + {} + }; +diff --git a/include/linux/usb/r8152.h b/include/linux/usb/r8152.h +index 33a4c146dc19c..2ca60828f28bb 100644 +--- a/include/linux/usb/r8152.h ++++ b/include/linux/usb/r8152.h +@@ -30,6 +30,7 @@ + #define VENDOR_ID_NVIDIA 0x0955 + #define VENDOR_ID_TPLINK 0x2357 + #define VENDOR_ID_DLINK 0x2001 ++#define VENDOR_ID_DELL 0x413c + #define VENDOR_ID_ASUS 0x0b05 + + #if IS_REACHABLE(CONFIG_USB_RTL8152) +-- +2.39.5 + diff --git a/queue-6.14/r8169-disable-rtl8126-zrx-dc-timeout.patch b/queue-6.14/r8169-disable-rtl8126-zrx-dc-timeout.patch new file mode 100644 index 0000000000..bd9c2cd833 --- /dev/null +++ b/queue-6.14/r8169-disable-rtl8126-zrx-dc-timeout.patch @@ -0,0 +1,70 @@ +From e86d8b777dd87d4ee563313e27eadc7a72a287e2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 18 Mar 2025 16:37:21 +0800 +Subject: r8169: disable RTL8126 ZRX-DC timeout + +From: ChunHao Lin + +[ Upstream commit b48688ea3c9ac8d5d910c6e91fb7f80d846581f0 ] + +Disable it due to it dose not meet ZRX-DC specification. If it is enabled, +device will exit L1 substate every 100ms. Disable it for saving more power +in L1 substate. + +Signed-off-by: ChunHao Lin +Reviewed-by: Heiner Kallweit +Link: https://patch.msgid.link/20250318083721.4127-3-hau@realtek.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/realtek/r8169_main.c | 27 +++++++++++++++++++++++ + 1 file changed, 27 insertions(+) + +diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethernet/realtek/r8169_main.c +index 5a5eba49c6515..4ead966727734 100644 +--- a/drivers/net/ethernet/realtek/r8169_main.c ++++ b/drivers/net/ethernet/realtek/r8169_main.c +@@ -2850,6 +2850,32 @@ static u32 rtl_csi_read(struct rtl8169_private *tp, int addr) + RTL_R32(tp, CSIDR) : ~0; + } + ++static void rtl_disable_zrxdc_timeout(struct rtl8169_private *tp) ++{ ++ struct pci_dev *pdev = tp->pci_dev; ++ u32 csi; ++ int rc; ++ u8 val; ++ ++#define RTL_GEN3_RELATED_OFF 0x0890 ++#define RTL_GEN3_ZRXDC_NONCOMPL 0x1 ++ if (pdev->cfg_size > RTL_GEN3_RELATED_OFF) { ++ rc = pci_read_config_byte(pdev, RTL_GEN3_RELATED_OFF, &val); ++ if (rc == PCIBIOS_SUCCESSFUL) { ++ val &= ~RTL_GEN3_ZRXDC_NONCOMPL; ++ rc = pci_write_config_byte(pdev, RTL_GEN3_RELATED_OFF, ++ val); ++ if (rc == PCIBIOS_SUCCESSFUL) ++ return; ++ } ++ } ++ ++ netdev_notice_once(tp->dev, ++ "No native access to PCI extended config space, falling back to CSI\n"); ++ csi = rtl_csi_read(tp, RTL_GEN3_RELATED_OFF); ++ rtl_csi_write(tp, RTL_GEN3_RELATED_OFF, csi & ~RTL_GEN3_ZRXDC_NONCOMPL); ++} ++ + static void rtl_set_aspm_entry_latency(struct rtl8169_private *tp, u8 val) + { + struct pci_dev *pdev = tp->pci_dev; +@@ -3822,6 +3848,7 @@ static void rtl_hw_start_8125d(struct rtl8169_private *tp) + + static void rtl_hw_start_8126a(struct rtl8169_private *tp) + { ++ rtl_disable_zrxdc_timeout(tp); + rtl_set_def_aspm_entry_latency(tp); + rtl_hw_start_8125_common(tp); + } +-- +2.39.5 + diff --git a/queue-6.14/r8169-don-t-scan-phy-addresses-0.patch b/queue-6.14/r8169-don-t-scan-phy-addresses-0.patch new file mode 100644 index 0000000000..051b5cae5f --- /dev/null +++ b/queue-6.14/r8169-don-t-scan-phy-addresses-0.patch @@ -0,0 +1,36 @@ +From 38c499a39c23b72200322570626cfa1002876b08 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 4 Feb 2025 07:58:17 +0100 +Subject: r8169: don't scan PHY addresses > 0 + +From: Heiner Kallweit + +[ Upstream commit faac69a4ae5abb49e62c79c66b51bb905c9aa5ec ] + +The PHY address is a dummy, because r8169 PHY access registers +don't support a PHY address. Therefore scan address 0 only. + +Signed-off-by: Heiner Kallweit +Reviewed-by: Andrew Lunn +Link: https://patch.msgid.link/830637dd-4016-4a68-92b3-618fcac6589d@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/realtek/r8169_main.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethernet/realtek/r8169_main.c +index 485ecd62e585d..267105ba92744 100644 +--- a/drivers/net/ethernet/realtek/r8169_main.c ++++ b/drivers/net/ethernet/realtek/r8169_main.c +@@ -5250,6 +5250,7 @@ static int r8169_mdio_register(struct rtl8169_private *tp) + new_bus->priv = tp; + new_bus->parent = &pdev->dev; + new_bus->irq[0] = PHY_MAC_INTERRUPT; ++ new_bus->phy_mask = GENMASK(31, 1); + snprintf(new_bus->id, MII_BUS_ID_SIZE, "r8169-%x-%x", + pci_domain_nr(pdev->bus), pci_dev_id(pdev)); + +-- +2.39.5 + diff --git a/queue-6.14/r8169-increase-max-jumbo-packet-size-on-rtl8125-rtl8.patch b/queue-6.14/r8169-increase-max-jumbo-packet-size-on-rtl8125-rtl8.patch new file mode 100644 index 0000000000..dbb57665c5 --- /dev/null +++ b/queue-6.14/r8169-increase-max-jumbo-packet-size-on-rtl8125-rtl8.patch @@ -0,0 +1,50 @@ +From a7e800108e7c4499d31b3cbee30e398a8ed4ae1f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 7 Mar 2025 08:29:47 +0100 +Subject: r8169: increase max jumbo packet size on RTL8125/RTL8126 + +From: Heiner Kallweit + +[ Upstream commit 473367a5ffe1607a61be481e2feda684eb5faea9 ] + +Realtek confirmed that all RTL8125/RTL8126 chip versions support up to +16K jumbo packets. Reflect this in the driver. + +Tested by Rui on RTL8125B with 12K jumbo packets. + +Suggested-by: Rui Salvaterra +Tested-by: Rui Salvaterra +Signed-off-by: Heiner Kallweit +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/396762ad-cc65-4e60-b01e-8847db89e98b@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/realtek/r8169_main.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethernet/realtek/r8169_main.c +index 4ead966727734..485ecd62e585d 100644 +--- a/drivers/net/ethernet/realtek/r8169_main.c ++++ b/drivers/net/ethernet/realtek/r8169_main.c +@@ -89,6 +89,7 @@ + #define JUMBO_6K (6 * SZ_1K - VLAN_ETH_HLEN - ETH_FCS_LEN) + #define JUMBO_7K (7 * SZ_1K - VLAN_ETH_HLEN - ETH_FCS_LEN) + #define JUMBO_9K (9 * SZ_1K - VLAN_ETH_HLEN - ETH_FCS_LEN) ++#define JUMBO_16K (SZ_16K - VLAN_ETH_HLEN - ETH_FCS_LEN) + + static const struct { + const char *name; +@@ -5353,6 +5354,9 @@ static int rtl_jumbo_max(struct rtl8169_private *tp) + /* RTL8168c */ + case RTL_GIGA_MAC_VER_18 ... RTL_GIGA_MAC_VER_24: + return JUMBO_6K; ++ /* RTL8125/8126 */ ++ case RTL_GIGA_MAC_VER_61 ... RTL_GIGA_MAC_VER_71: ++ return JUMBO_16K; + default: + return JUMBO_9K; + } +-- +2.39.5 + diff --git a/queue-6.14/rcu-fix-get_state_synchronize_rcu_full-gp-start-dete.patch b/queue-6.14/rcu-fix-get_state_synchronize_rcu_full-gp-start-dete.patch new file mode 100644 index 0000000000..a4a257ba9f --- /dev/null +++ b/queue-6.14/rcu-fix-get_state_synchronize_rcu_full-gp-start-dete.patch @@ -0,0 +1,248 @@ +From 8d22e22abaad92094a73b91327cb61d91923f17e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 12 Dec 2024 14:15:07 -0800 +Subject: rcu: Fix get_state_synchronize_rcu_full() GP-start detection +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Paul E. McKenney + +[ Upstream commit 85aad7cc417877054c65bd490dc037b087ef21b4 ] + +The get_state_synchronize_rcu_full() and poll_state_synchronize_rcu_full() +functions use the root rcu_node structure's ->gp_seq field to detect +the beginnings and ends of grace periods, respectively. This choice is +necessary for the poll_state_synchronize_rcu_full() function because +(give or take counter wrap), the following sequence is guaranteed not +to trigger: + + get_state_synchronize_rcu_full(&rgos); + synchronize_rcu(); + WARN_ON_ONCE(!poll_state_synchronize_rcu_full(&rgos)); + +The RCU callbacks that awaken synchronize_rcu() instances are +guaranteed not to be invoked before the root rcu_node structure's +->gp_seq field is updated to indicate the end of the grace period. +However, these callbacks might start being invoked immediately +thereafter, in particular, before rcu_state.gp_seq has been updated. +Therefore, poll_state_synchronize_rcu_full() must refer to the +root rcu_node structure's ->gp_seq field. Because this field is +updated under this structure's ->lock, any code following a call to +poll_state_synchronize_rcu_full() will be fully ordered after the +full grace-period computation, as is required by RCU's memory-ordering +semantics. + +By symmetry, the get_state_synchronize_rcu_full() function should also +use this same root rcu_node structure's ->gp_seq field. But it turns out +that symmetry is profoundly (though extremely infrequently) destructive +in this case. To see this, consider the following sequence of events: + +1. CPU 0 starts a new grace period, and updates rcu_state.gp_seq + accordingly. + +2. As its first step of grace-period initialization, CPU 0 examines + the current CPU hotplug state and decides that it need not wait + for CPU 1, which is currently offline. + +3. CPU 1 comes online, and updates its state. But this does not + affect the current grace period, but rather the one after that. + After all, CPU 1 was offline when the current grace period + started, so all pre-existing RCU readers on CPU 1 must have + completed or been preempted before it last went offline. + The current grace period therefore has nothing it needs to wait + for on CPU 1. + +4. CPU 1 switches to an rcutorture kthread which is running + rcutorture's rcu_torture_reader() function, which starts a new + RCU reader. + +5. CPU 2 is running rcutorture's rcu_torture_writer() function + and collects a new polled grace-period "cookie" using + get_state_synchronize_rcu_full(). Because the newly started + grace period has not completed initialization, the root rcu_node + structure's ->gp_seq field has not yet been updated to indicate + that this new grace period has already started. + + This cookie is therefore set up for the end of the current grace + period (rather than the end of the following grace period). + +6. CPU 0 finishes grace-period initialization. + +7. If CPU 1’s rcutorture reader is preempted, it will be added to + the ->blkd_tasks list, but because CPU 1’s ->qsmask bit is not + set in CPU 1's leaf rcu_node structure, the ->gp_tasks pointer + will not be updated.  Thus, this grace period will not wait on + it.  Which is only fair, given that the CPU did not come online + until after the grace period officially started. + +8. CPUs 0 and 2 then detect the new grace period and then report + a quiescent state to the RCU core. + +9. Because CPU 1 was offline at the start of the current grace + period, CPUs 0 and 2 are the only CPUs that this grace period + needs to wait on. So the grace period ends and post-grace-period + cleanup starts. In particular, the root rcu_node structure's + ->gp_seq field is updated to indicate that this grace period + has now ended. + +10. CPU 2 continues running rcu_torture_writer() and sees that, + from the viewpoint of the root rcu_node structure consulted by + the poll_state_synchronize_rcu_full() function, the grace period + has ended.  It therefore updates state accordingly. + +11. CPU 1 is still running the same RCU reader, which notices this + update and thus complains about the too-short grace period. + +The fix is for the get_state_synchronize_rcu_full() function to use +rcu_state.gp_seq instead of the root rcu_node structure's ->gp_seq field. +With this change in place, if step 5's cookie indicates that the grace +period has not yet started, then any prior code executed by CPU 2 must +have happened before CPU 1 came online. This will in turn prevent CPU +1's code in steps 3 and 11 from spanning CPU 2's grace-period wait, +thus preventing CPU 1 from being subjected to a too-short grace period. + +This commit therefore makes this change. Note that there is no change to +the poll_state_synchronize_rcu_full() function, which as noted above, +must continue to use the root rcu_node structure's ->gp_seq field. +This is of course an asymmetry between these two functions, but is an +asymmetry that is absolutely required for correct operation. It is a +common human tendency to greatly value symmetry, and sometimes symmetry +is a wonderful thing. Other times, symmetry results in poor performance. +But in this case, symmetry is just plain wrong. + +Nevertheless, the asymmetry does require an additional adjustment. +It is possible for get_state_synchronize_rcu_full() to see a given +grace period as having started, but for an immediately following +poll_state_synchronize_rcu_full() to see it as having not yet started. +Given the current rcu_seq_done_exact() implementation, this will +result in a false-positive indication that the grace period is done +from poll_state_synchronize_rcu_full(). This is dealt with by making +rcu_seq_done_exact() reach back three grace periods rather than just +two of them. + +However, simply changing get_state_synchronize_rcu_full() function to +use rcu_state.gp_seq instead of the root rcu_node structure's ->gp_seq +field results in a theoretical bug in kernels booted with +rcutree.rcu_normal_wake_from_gp=1 due to the following sequence of +events: + +o The rcu_gp_init() function invokes rcu_seq_start() to officially + start a new grace period. + +o A new RCU reader begins, referencing X from some RCU-protected + list. The new grace period is not obligated to wait for this + reader. + +o An updater removes X, then calls synchronize_rcu(), which queues + a wait element. + +o The grace period ends, awakening the updater, which frees X + while the reader is still referencing it. + +The reason that this is theoretical is that although the grace period +has officially started, none of the CPUs are officially aware of this, +and thus will have to assume that the RCU reader pre-dated the start of +the grace period. Detailed explanation can be found at [2] and [3]. + +Except for kernels built with CONFIG_PROVE_RCU=y, which use the polled +grace-period APIs, which can and do complain bitterly when this sequence +of events occurs. Not only that, there might be some future RCU +grace-period mechanism that pulls this sequence of events from theory +into practice. This commit therefore also pulls the call to +rcu_sr_normal_gp_init() to precede that to rcu_seq_start(). + +Although this fixes commit 91a967fd6934 ("rcu: Add full-sized polling +for get_completed*() and poll_state*()"), it is not clear that it is +worth backporting this commit. First, it took me many weeks to convince +rcutorture to reproduce this more frequently than once per year. +Second, this cannot be reproduced at all without frequent CPU-hotplug +operations, as in waiting all of 50 milliseconds from the end of the +previous operation until starting the next one. Third, the TREE03.boot +settings cause multi-millisecond delays during RCU grace-period +initialization, which greatly increase the probability of the above +sequence of events. (Don't do this in production workloads!) Fourth, +the TREE03 rcutorture scenario was modified to use four-CPU guest OSes, +to have a single-rcu_node combining tree, no testing of RCU priority +boosting, and no random preemption, and these modifications were +necessary to reproduce this issue in a reasonable timeframe. Fifth, +extremely heavy use of get_state_synchronize_rcu_full() and/or +poll_state_synchronize_rcu_full() is required to reproduce this, and as +of v6.12, only kfree_rcu() uses it, and even then not particularly +heavily. + +[boqun: Apply the fix [1], and add the comment before the moved +rcu_sr_normal_gp_init(). Additional links are added for explanation.] + +Signed-off-by: Paul E. McKenney +Reviewed-by: Frederic Weisbecker +Reviewed-by: Joel Fernandes (Google) +Tested-by: Uladzislau Rezki (Sony) +Link: https://lore.kernel.org/rcu/d90bd6d9-d15c-4b9b-8a69-95336e74e8f4@paulmck-laptop/ [1] +Link: https://lore.kernel.org/rcu/20250303001507.GA3994772@joelnvbox/ [2] +Link: https://lore.kernel.org/rcu/Z8bcUsZ9IpRi1QoP@pc636/ [3] +Reviewed-by: Joel Fernandes +Signed-off-by: Boqun Feng +Signed-off-by: Sasha Levin +--- + kernel/rcu/rcu.h | 2 +- + kernel/rcu/tree.c | 15 +++++++++++---- + 2 files changed, 12 insertions(+), 5 deletions(-) + +diff --git a/kernel/rcu/rcu.h b/kernel/rcu/rcu.h +index feb3ac1dc5d59..f87c9d6d36fcb 100644 +--- a/kernel/rcu/rcu.h ++++ b/kernel/rcu/rcu.h +@@ -162,7 +162,7 @@ static inline bool rcu_seq_done_exact(unsigned long *sp, unsigned long s) + { + unsigned long cur_s = READ_ONCE(*sp); + +- return ULONG_CMP_GE(cur_s, s) || ULONG_CMP_LT(cur_s, s - (2 * RCU_SEQ_STATE_MASK + 1)); ++ return ULONG_CMP_GE(cur_s, s) || ULONG_CMP_LT(cur_s, s - (3 * RCU_SEQ_STATE_MASK + 1)); + } + + /* +diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c +index 475f31deed141..b7bf9db9bb461 100644 +--- a/kernel/rcu/tree.c ++++ b/kernel/rcu/tree.c +@@ -1801,10 +1801,14 @@ static noinline_for_stack bool rcu_gp_init(void) + + /* Advance to a new grace period and initialize state. */ + record_gp_stall_check_time(); ++ /* ++ * A new wait segment must be started before gp_seq advanced, so ++ * that previous gp waiters won't observe the new gp_seq. ++ */ ++ start_new_poll = rcu_sr_normal_gp_init(); + /* Record GP times before starting GP, hence rcu_seq_start(). */ + rcu_seq_start(&rcu_state.gp_seq); + ASSERT_EXCLUSIVE_WRITER(rcu_state.gp_seq); +- start_new_poll = rcu_sr_normal_gp_init(); + trace_rcu_grace_period(rcu_state.name, rcu_state.gp_seq, TPS("start")); + rcu_poll_gp_seq_start(&rcu_state.gp_seq_polled_snap); + raw_spin_unlock_irq_rcu_node(rnp); +@@ -3357,14 +3361,17 @@ EXPORT_SYMBOL_GPL(get_state_synchronize_rcu); + */ + void get_state_synchronize_rcu_full(struct rcu_gp_oldstate *rgosp) + { +- struct rcu_node *rnp = rcu_get_root(); +- + /* + * Any prior manipulation of RCU-protected data must happen + * before the loads from ->gp_seq and ->expedited_sequence. + */ + smp_mb(); /* ^^^ */ +- rgosp->rgos_norm = rcu_seq_snap(&rnp->gp_seq); ++ ++ // Yes, rcu_state.gp_seq, not rnp_root->gp_seq, the latter's use ++ // in poll_state_synchronize_rcu_full() notwithstanding. Use of ++ // the latter here would result in too-short grace periods due to ++ // interactions with newly onlined CPUs. ++ rgosp->rgos_norm = rcu_seq_snap(&rcu_state.gp_seq); + rgosp->rgos_exp = rcu_seq_snap(&rcu_state.expedited_sequence); + } + EXPORT_SYMBOL_GPL(get_state_synchronize_rcu_full); +-- +2.39.5 + diff --git a/queue-6.14/rcu-fix-header-guard-for-rcu_all_qs.patch b/queue-6.14/rcu-fix-header-guard-for-rcu_all_qs.patch new file mode 100644 index 0000000000..c6ad7616ce --- /dev/null +++ b/queue-6.14/rcu-fix-header-guard-for-rcu_all_qs.patch @@ -0,0 +1,44 @@ +From ce4bc94a69f774d11aec8804f7db6152a3173471 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 12 Dec 2024 20:06:52 -0800 +Subject: rcu: fix header guard for rcu_all_qs() + +From: Ankur Arora + +[ Upstream commit ad6b5b73ff565e88aca7a7d1286788d80c97ba71 ] + +rcu_all_qs() is defined for !CONFIG_PREEMPT_RCU but the declaration +is conditioned on CONFIG_PREEMPTION. + +With CONFIG_PREEMPT_LAZY, CONFIG_PREEMPTION=y does not imply +CONFIG_PREEMPT_RCU=y. + +Decouple the two. + +Cc: Paul E. McKenney +Reviewed-by: Frederic Weisbecker +Reviewed-by: Sebastian Andrzej Siewior +Signed-off-by: Ankur Arora +Signed-off-by: Paul E. McKenney +Signed-off-by: Boqun Feng +Signed-off-by: Sasha Levin +--- + include/linux/rcutree.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/include/linux/rcutree.h b/include/linux/rcutree.h +index 27d86d9127817..aad586f15ed0c 100644 +--- a/include/linux/rcutree.h ++++ b/include/linux/rcutree.h +@@ -103,7 +103,7 @@ extern int rcu_scheduler_active; + void rcu_end_inkernel_boot(void); + bool rcu_inkernel_boot_has_ended(void); + bool rcu_is_watching(void); +-#ifndef CONFIG_PREEMPTION ++#ifndef CONFIG_PREEMPT_RCU + void rcu_all_qs(void); + #endif + +-- +2.39.5 + diff --git a/queue-6.14/rcu-handle-quiescent-states-for-preempt_rcu-n-preemp.patch b/queue-6.14/rcu-handle-quiescent-states-for-preempt_rcu-n-preemp.patch new file mode 100644 index 0000000000..5a234c3cae --- /dev/null +++ b/queue-6.14/rcu-handle-quiescent-states-for-preempt_rcu-n-preemp.patch @@ -0,0 +1,63 @@ +From cdc8f290dcc3e04807b018e254ca07510bf3d087 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 12 Dec 2024 20:06:56 -0800 +Subject: rcu: handle quiescent states for PREEMPT_RCU=n, PREEMPT_COUNT=y + +From: Ankur Arora + +[ Upstream commit 83b28cfe796464ebbde1cf7916c126da6d572685 ] + +With PREEMPT_RCU=n, cond_resched() provides urgently needed quiescent +states for read-side critical sections via rcu_all_qs(). +One reason why this was needed: lacking preempt-count, the tick +handler has no way of knowing whether it is executing in a +read-side critical section or not. + +With (PREEMPT_LAZY=y, PREEMPT_DYNAMIC=n), we get (PREEMPT_COUNT=y, +PREEMPT_RCU=n). In this configuration cond_resched() is a stub and +does not provide quiescent states via rcu_all_qs(). +(PREEMPT_RCU=y provides this information via rcu_read_unlock() and +its nesting counter.) + +So, use the availability of preempt_count() to report quiescent states +in rcu_flavor_sched_clock_irq(). + +Suggested-by: Paul E. McKenney +Reviewed-by: Sebastian Andrzej Siewior +Signed-off-by: Ankur Arora +Reviewed-by: Frederic Weisbecker +Signed-off-by: Paul E. McKenney +Signed-off-by: Boqun Feng +Signed-off-by: Sasha Levin +--- + kernel/rcu/tree_plugin.h | 11 +++++++---- + 1 file changed, 7 insertions(+), 4 deletions(-) + +diff --git a/kernel/rcu/tree_plugin.h b/kernel/rcu/tree_plugin.h +index 3600152b858e8..4328ff3252a35 100644 +--- a/kernel/rcu/tree_plugin.h ++++ b/kernel/rcu/tree_plugin.h +@@ -975,13 +975,16 @@ static void rcu_preempt_check_blocked_tasks(struct rcu_node *rnp) + */ + static void rcu_flavor_sched_clock_irq(int user) + { +- if (user || rcu_is_cpu_rrupt_from_idle()) { ++ if (user || rcu_is_cpu_rrupt_from_idle() || ++ (IS_ENABLED(CONFIG_PREEMPT_COUNT) && ++ (preempt_count() == HARDIRQ_OFFSET))) { + + /* + * Get here if this CPU took its interrupt from user +- * mode or from the idle loop, and if this is not a +- * nested interrupt. In this case, the CPU is in +- * a quiescent state, so note it. ++ * mode, from the idle loop without this being a nested ++ * interrupt, or while not holding the task preempt count ++ * (with PREEMPT_COUNT=y). In this case, the CPU is in a ++ * quiescent state, so note it. + * + * No memory barrier is required here because rcu_qs() + * references only CPU-local variables that other CPUs +-- +2.39.5 + diff --git a/queue-6.14/rcu-handle-unstable-rdp-in-rcu_read_unlock_strict.patch b/queue-6.14/rcu-handle-unstable-rdp-in-rcu_read_unlock_strict.patch new file mode 100644 index 0000000000..36bcffde7e --- /dev/null +++ b/queue-6.14/rcu-handle-unstable-rdp-in-rcu_read_unlock_strict.patch @@ -0,0 +1,68 @@ +From a5b0fc1e2557608d72ee4328033ddc7eb3c001c2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 12 Dec 2024 20:06:55 -0800 +Subject: rcu: handle unstable rdp in rcu_read_unlock_strict() + +From: Ankur Arora + +[ Upstream commit fcf0e25ad4c8d14d2faab4d9a17040f31efce205 ] + +rcu_read_unlock_strict() can be called with preemption enabled +which can make for an unstable rdp and a racy norm value. + +Fix this by dropping the preempt-count in __rcu_read_unlock() +after the call to rcu_read_unlock_strict(), adjusting the +preempt-count check appropriately. + +Suggested-by: Frederic Weisbecker +Signed-off-by: Ankur Arora +Reviewed-by: Frederic Weisbecker +Signed-off-by: Paul E. McKenney +Signed-off-by: Boqun Feng +Signed-off-by: Sasha Levin +--- + include/linux/rcupdate.h | 2 +- + kernel/rcu/tree_plugin.h | 11 ++++++++++- + 2 files changed, 11 insertions(+), 2 deletions(-) + +diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h +index bd69ddc102fbc..0844ab3288519 100644 +--- a/include/linux/rcupdate.h ++++ b/include/linux/rcupdate.h +@@ -95,9 +95,9 @@ static inline void __rcu_read_lock(void) + + static inline void __rcu_read_unlock(void) + { +- preempt_enable(); + if (IS_ENABLED(CONFIG_RCU_STRICT_GRACE_PERIOD)) + rcu_read_unlock_strict(); ++ preempt_enable(); + } + + static inline int rcu_preempt_depth(void) +diff --git a/kernel/rcu/tree_plugin.h b/kernel/rcu/tree_plugin.h +index 4328ff3252a35..3c0bbbbb686fe 100644 +--- a/kernel/rcu/tree_plugin.h ++++ b/kernel/rcu/tree_plugin.h +@@ -833,8 +833,17 @@ void rcu_read_unlock_strict(void) + { + struct rcu_data *rdp; + +- if (irqs_disabled() || preempt_count() || !rcu_state.gp_kthread) ++ if (irqs_disabled() || in_atomic_preempt_off() || !rcu_state.gp_kthread) + return; ++ ++ /* ++ * rcu_report_qs_rdp() can only be invoked with a stable rdp and ++ * from the local CPU. ++ * ++ * The in_atomic_preempt_off() check ensures that we come here holding ++ * the last preempt_count (which will get dropped once we return to ++ * __rcu_read_unlock(). ++ */ + rdp = this_cpu_ptr(&rcu_data); + rdp->cpu_no_qs.b.norm = false; + rcu_report_qs_rdp(rdp); +-- +2.39.5 + diff --git a/queue-6.14/rdma-core-fix-best-page-size-finding-when-it-can-cro.patch b/queue-6.14/rdma-core-fix-best-page-size-finding-when-it-can-cro.patch new file mode 100644 index 0000000000..ac42945600 --- /dev/null +++ b/queue-6.14/rdma-core-fix-best-page-size-finding-when-it-can-cro.patch @@ -0,0 +1,139 @@ +From 91959f035883f7bb4401aa40b78824d19f67761a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Feb 2025 14:16:23 +0000 +Subject: RDMA/core: Fix best page size finding when it can cross SG entries + +From: Michael Margolin + +[ Upstream commit 486055f5e09df959ad4e3aa4ee75b5c91ddeec2e ] + +A single scatter-gather entry is limited by a 32 bits "length" field +that is practically 4GB - PAGE_SIZE. This means that even when the +memory is physically contiguous, we might need more than one entry to +represent it. Additionally when using dmabuf, the sg_table might be +originated outside the subsystem and optimized for other needs. + +For instance an SGT of 16GB GPU continuous memory might look like this: +(a real life example) + +dma_address 34401400000, length fffff000 +dma_address 345013ff000, length fffff000 +dma_address 346013fe000, length fffff000 +dma_address 347013fd000, length fffff000 +dma_address 348013fc000, length 4000 + +Since ib_umem_find_best_pgsz works within SG entries, in the above case +we will result with the worst possible 4KB page size. + +Fix this by taking into consideration only the alignment of addresses of +real discontinuity points rather than treating SG entries as such, and +adjust the page iterator to correctly handle cross SG entry pages. + +There is currently an assumption that drivers do not ask for pages +bigger than maximal DMA size supported by their devices. + +Reviewed-by: Firas Jahjah +Reviewed-by: Yonatan Nachum +Signed-off-by: Michael Margolin +Link: https://patch.msgid.link/20250217141623.12428-1-mrgolin@amazon.com +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + drivers/infiniband/core/umem.c | 36 ++++++++++++++++++++++++--------- + drivers/infiniband/core/verbs.c | 11 +++++----- + 2 files changed, 32 insertions(+), 15 deletions(-) + +diff --git a/drivers/infiniband/core/umem.c b/drivers/infiniband/core/umem.c +index 07c571c7b6999..c5b6863947605 100644 +--- a/drivers/infiniband/core/umem.c ++++ b/drivers/infiniband/core/umem.c +@@ -80,9 +80,12 @@ unsigned long ib_umem_find_best_pgsz(struct ib_umem *umem, + unsigned long pgsz_bitmap, + unsigned long virt) + { +- struct scatterlist *sg; ++ unsigned long curr_len = 0; ++ dma_addr_t curr_base = ~0; + unsigned long va, pgoff; ++ struct scatterlist *sg; + dma_addr_t mask; ++ dma_addr_t end; + int i; + + umem->iova = va = virt; +@@ -107,17 +110,30 @@ unsigned long ib_umem_find_best_pgsz(struct ib_umem *umem, + pgoff = umem->address & ~PAGE_MASK; + + for_each_sgtable_dma_sg(&umem->sgt_append.sgt, sg, i) { +- /* Walk SGL and reduce max page size if VA/PA bits differ +- * for any address. ++ /* If the current entry is physically contiguous with the previous ++ * one, no need to take its start addresses into consideration. + */ +- mask |= (sg_dma_address(sg) + pgoff) ^ va; ++ if (check_add_overflow(curr_base, curr_len, &end) || ++ end != sg_dma_address(sg)) { ++ ++ curr_base = sg_dma_address(sg); ++ curr_len = 0; ++ ++ /* Reduce max page size if VA/PA bits differ */ ++ mask |= (curr_base + pgoff) ^ va; ++ ++ /* The alignment of any VA matching a discontinuity point ++ * in the physical memory sets the maximum possible page ++ * size as this must be a starting point of a new page that ++ * needs to be aligned. ++ */ ++ if (i != 0) ++ mask |= va; ++ } ++ ++ curr_len += sg_dma_len(sg); + va += sg_dma_len(sg) - pgoff; +- /* Except for the last entry, the ending iova alignment sets +- * the maximum possible page size as the low bits of the iova +- * must be zero when starting the next chunk. +- */ +- if (i != (umem->sgt_append.sgt.nents - 1)) +- mask |= va; ++ + pgoff = 0; + } + +diff --git a/drivers/infiniband/core/verbs.c b/drivers/infiniband/core/verbs.c +index 473ee0831307c..dc40001072a5e 100644 +--- a/drivers/infiniband/core/verbs.c ++++ b/drivers/infiniband/core/verbs.c +@@ -3109,22 +3109,23 @@ EXPORT_SYMBOL(__rdma_block_iter_start); + bool __rdma_block_iter_next(struct ib_block_iter *biter) + { + unsigned int block_offset; +- unsigned int sg_delta; ++ unsigned int delta; + + if (!biter->__sg_nents || !biter->__sg) + return false; + + biter->__dma_addr = sg_dma_address(biter->__sg) + biter->__sg_advance; + block_offset = biter->__dma_addr & (BIT_ULL(biter->__pg_bit) - 1); +- sg_delta = BIT_ULL(biter->__pg_bit) - block_offset; ++ delta = BIT_ULL(biter->__pg_bit) - block_offset; + +- if (sg_dma_len(biter->__sg) - biter->__sg_advance > sg_delta) { +- biter->__sg_advance += sg_delta; +- } else { ++ while (biter->__sg_nents && biter->__sg && ++ sg_dma_len(biter->__sg) - biter->__sg_advance <= delta) { ++ delta -= sg_dma_len(biter->__sg) - biter->__sg_advance; + biter->__sg_advance = 0; + biter->__sg = sg_next(biter->__sg); + biter->__sg_nents--; + } ++ biter->__sg_advance += delta; + + return true; + } +-- +2.39.5 + diff --git a/queue-6.14/rdma-uverbs-propagate-errors-from-rdma_lookup_get_uo.patch b/queue-6.14/rdma-uverbs-propagate-errors-from-rdma_lookup_get_uo.patch new file mode 100644 index 0000000000..8419e275f8 --- /dev/null +++ b/queue-6.14/rdma-uverbs-propagate-errors-from-rdma_lookup_get_uo.patch @@ -0,0 +1,432 @@ +From fbc0e117ab41b2ae3b76bfed430dc6db5d7be472 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 26 Feb 2025 15:54:13 +0200 +Subject: RDMA/uverbs: Propagate errors from rdma_lookup_get_uobject() + +From: Maher Sanalla + +[ Upstream commit 81f8f7454ad9e0bf95efdec6542afdc9a6ab1e24 ] + +Currently, the IB uverbs API calls uobj_get_uobj_read(), which in turn +uses the rdma_lookup_get_uobject() helper to retrieve user objects. +In case of failure, uobj_get_uobj_read() returns NULL, overriding the +error code from rdma_lookup_get_uobject(). The IB uverbs API then +translates this NULL to -EINVAL, masking the actual error and +complicating debugging. For example, applications calling ibv_modify_qp +that fails with EBUSY when retrieving the QP uobject will see the +overridden error code EINVAL instead, masking the actual error. + +Furthermore, based on rdma-core commit: +"2a22f1ced5f3 ("Merge pull request #1568 from jakemoroni/master")" +Kernel's IB uverbs return values are either ignored and passed on as is +to application or overridden with other errnos in a few cases. + +Thus, to improve error reporting and debuggability, propagate the +original error from rdma_lookup_get_uobject() instead of replacing it +with EINVAL. + +Signed-off-by: Maher Sanalla +Link: https://patch.msgid.link/64f9d3711b183984e939962c2f83383904f97dfb.1740577869.git.leon@kernel.org +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + drivers/infiniband/core/uverbs_cmd.c | 144 ++++++++++++++------------- + include/rdma/uverbs_std_types.h | 2 +- + 2 files changed, 77 insertions(+), 69 deletions(-) + +diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c +index 5ad14c39d48c9..de75dcc0947c7 100644 +--- a/drivers/infiniband/core/uverbs_cmd.c ++++ b/drivers/infiniband/core/uverbs_cmd.c +@@ -716,8 +716,8 @@ static int ib_uverbs_reg_mr(struct uverbs_attr_bundle *attrs) + goto err_free; + + pd = uobj_get_obj_read(pd, UVERBS_OBJECT_PD, cmd.pd_handle, attrs); +- if (!pd) { +- ret = -EINVAL; ++ if (IS_ERR(pd)) { ++ ret = PTR_ERR(pd); + goto err_free; + } + +@@ -807,8 +807,8 @@ static int ib_uverbs_rereg_mr(struct uverbs_attr_bundle *attrs) + if (cmd.flags & IB_MR_REREG_PD) { + new_pd = uobj_get_obj_read(pd, UVERBS_OBJECT_PD, cmd.pd_handle, + attrs); +- if (!new_pd) { +- ret = -EINVAL; ++ if (IS_ERR(new_pd)) { ++ ret = PTR_ERR(new_pd); + goto put_uobjs; + } + } else { +@@ -917,8 +917,8 @@ static int ib_uverbs_alloc_mw(struct uverbs_attr_bundle *attrs) + return PTR_ERR(uobj); + + pd = uobj_get_obj_read(pd, UVERBS_OBJECT_PD, cmd.pd_handle, attrs); +- if (!pd) { +- ret = -EINVAL; ++ if (IS_ERR(pd)) { ++ ret = PTR_ERR(pd); + goto err_free; + } + +@@ -1125,8 +1125,8 @@ static int ib_uverbs_resize_cq(struct uverbs_attr_bundle *attrs) + return ret; + + cq = uobj_get_obj_read(cq, UVERBS_OBJECT_CQ, cmd.cq_handle, attrs); +- if (!cq) +- return -EINVAL; ++ if (IS_ERR(cq)) ++ return PTR_ERR(cq); + + ret = cq->device->ops.resize_cq(cq, cmd.cqe, &attrs->driver_udata); + if (ret) +@@ -1187,8 +1187,8 @@ static int ib_uverbs_poll_cq(struct uverbs_attr_bundle *attrs) + return ret; + + cq = uobj_get_obj_read(cq, UVERBS_OBJECT_CQ, cmd.cq_handle, attrs); +- if (!cq) +- return -EINVAL; ++ if (IS_ERR(cq)) ++ return PTR_ERR(cq); + + /* we copy a struct ib_uverbs_poll_cq_resp to user space */ + header_ptr = attrs->ucore.outbuf; +@@ -1236,8 +1236,8 @@ static int ib_uverbs_req_notify_cq(struct uverbs_attr_bundle *attrs) + return ret; + + cq = uobj_get_obj_read(cq, UVERBS_OBJECT_CQ, cmd.cq_handle, attrs); +- if (!cq) +- return -EINVAL; ++ if (IS_ERR(cq)) ++ return PTR_ERR(cq); + + ib_req_notify_cq(cq, cmd.solicited_only ? + IB_CQ_SOLICITED : IB_CQ_NEXT_COMP); +@@ -1319,8 +1319,8 @@ static int create_qp(struct uverbs_attr_bundle *attrs, + ind_tbl = uobj_get_obj_read(rwq_ind_table, + UVERBS_OBJECT_RWQ_IND_TBL, + cmd->rwq_ind_tbl_handle, attrs); +- if (!ind_tbl) { +- ret = -EINVAL; ++ if (IS_ERR(ind_tbl)) { ++ ret = PTR_ERR(ind_tbl); + goto err_put; + } + +@@ -1358,8 +1358,10 @@ static int create_qp(struct uverbs_attr_bundle *attrs, + if (cmd->is_srq) { + srq = uobj_get_obj_read(srq, UVERBS_OBJECT_SRQ, + cmd->srq_handle, attrs); +- if (!srq || srq->srq_type == IB_SRQT_XRC) { +- ret = -EINVAL; ++ if (IS_ERR(srq) || ++ srq->srq_type == IB_SRQT_XRC) { ++ ret = IS_ERR(srq) ? PTR_ERR(srq) : ++ -EINVAL; + goto err_put; + } + } +@@ -1369,23 +1371,29 @@ static int create_qp(struct uverbs_attr_bundle *attrs, + rcq = uobj_get_obj_read( + cq, UVERBS_OBJECT_CQ, + cmd->recv_cq_handle, attrs); +- if (!rcq) { +- ret = -EINVAL; ++ if (IS_ERR(rcq)) { ++ ret = PTR_ERR(rcq); + goto err_put; + } + } + } + } + +- if (has_sq) ++ if (has_sq) { + scq = uobj_get_obj_read(cq, UVERBS_OBJECT_CQ, + cmd->send_cq_handle, attrs); ++ if (IS_ERR(scq)) { ++ ret = PTR_ERR(scq); ++ goto err_put; ++ } ++ } ++ + if (!ind_tbl && cmd->qp_type != IB_QPT_XRC_INI) + rcq = rcq ?: scq; + pd = uobj_get_obj_read(pd, UVERBS_OBJECT_PD, cmd->pd_handle, + attrs); +- if (!pd || (!scq && has_sq)) { +- ret = -EINVAL; ++ if (IS_ERR(pd)) { ++ ret = PTR_ERR(pd); + goto err_put; + } + +@@ -1480,18 +1488,18 @@ static int create_qp(struct uverbs_attr_bundle *attrs, + err_put: + if (!IS_ERR(xrcd_uobj)) + uobj_put_read(xrcd_uobj); +- if (pd) ++ if (!IS_ERR_OR_NULL(pd)) + uobj_put_obj_read(pd); +- if (scq) ++ if (!IS_ERR_OR_NULL(scq)) + rdma_lookup_put_uobject(&scq->uobject->uevent.uobject, + UVERBS_LOOKUP_READ); +- if (rcq && rcq != scq) ++ if (!IS_ERR_OR_NULL(rcq) && rcq != scq) + rdma_lookup_put_uobject(&rcq->uobject->uevent.uobject, + UVERBS_LOOKUP_READ); +- if (srq) ++ if (!IS_ERR_OR_NULL(srq)) + rdma_lookup_put_uobject(&srq->uobject->uevent.uobject, + UVERBS_LOOKUP_READ); +- if (ind_tbl) ++ if (!IS_ERR_OR_NULL(ind_tbl)) + uobj_put_obj_read(ind_tbl); + + uobj_alloc_abort(&obj->uevent.uobject, attrs); +@@ -1653,8 +1661,8 @@ static int ib_uverbs_query_qp(struct uverbs_attr_bundle *attrs) + } + + qp = uobj_get_obj_read(qp, UVERBS_OBJECT_QP, cmd.qp_handle, attrs); +- if (!qp) { +- ret = -EINVAL; ++ if (IS_ERR(qp)) { ++ ret = PTR_ERR(qp); + goto out; + } + +@@ -1759,8 +1767,8 @@ static int modify_qp(struct uverbs_attr_bundle *attrs, + + qp = uobj_get_obj_read(qp, UVERBS_OBJECT_QP, cmd->base.qp_handle, + attrs); +- if (!qp) { +- ret = -EINVAL; ++ if (IS_ERR(qp)) { ++ ret = PTR_ERR(qp); + goto out; + } + +@@ -2026,8 +2034,8 @@ static int ib_uverbs_post_send(struct uverbs_attr_bundle *attrs) + return -ENOMEM; + + qp = uobj_get_obj_read(qp, UVERBS_OBJECT_QP, cmd.qp_handle, attrs); +- if (!qp) { +- ret = -EINVAL; ++ if (IS_ERR(qp)) { ++ ret = PTR_ERR(qp); + goto out; + } + +@@ -2064,9 +2072,9 @@ static int ib_uverbs_post_send(struct uverbs_attr_bundle *attrs) + + ud->ah = uobj_get_obj_read(ah, UVERBS_OBJECT_AH, + user_wr->wr.ud.ah, attrs); +- if (!ud->ah) { ++ if (IS_ERR(ud->ah)) { ++ ret = PTR_ERR(ud->ah); + kfree(ud); +- ret = -EINVAL; + goto out_put; + } + ud->remote_qpn = user_wr->wr.ud.remote_qpn; +@@ -2303,8 +2311,8 @@ static int ib_uverbs_post_recv(struct uverbs_attr_bundle *attrs) + return PTR_ERR(wr); + + qp = uobj_get_obj_read(qp, UVERBS_OBJECT_QP, cmd.qp_handle, attrs); +- if (!qp) { +- ret = -EINVAL; ++ if (IS_ERR(qp)) { ++ ret = PTR_ERR(qp); + goto out; + } + +@@ -2354,8 +2362,8 @@ static int ib_uverbs_post_srq_recv(struct uverbs_attr_bundle *attrs) + return PTR_ERR(wr); + + srq = uobj_get_obj_read(srq, UVERBS_OBJECT_SRQ, cmd.srq_handle, attrs); +- if (!srq) { +- ret = -EINVAL; ++ if (IS_ERR(srq)) { ++ ret = PTR_ERR(srq); + goto out; + } + +@@ -2411,8 +2419,8 @@ static int ib_uverbs_create_ah(struct uverbs_attr_bundle *attrs) + } + + pd = uobj_get_obj_read(pd, UVERBS_OBJECT_PD, cmd.pd_handle, attrs); +- if (!pd) { +- ret = -EINVAL; ++ if (IS_ERR(pd)) { ++ ret = PTR_ERR(pd); + goto err; + } + +@@ -2481,8 +2489,8 @@ static int ib_uverbs_attach_mcast(struct uverbs_attr_bundle *attrs) + return ret; + + qp = uobj_get_obj_read(qp, UVERBS_OBJECT_QP, cmd.qp_handle, attrs); +- if (!qp) +- return -EINVAL; ++ if (IS_ERR(qp)) ++ return PTR_ERR(qp); + + obj = qp->uobject; + +@@ -2531,8 +2539,8 @@ static int ib_uverbs_detach_mcast(struct uverbs_attr_bundle *attrs) + return ret; + + qp = uobj_get_obj_read(qp, UVERBS_OBJECT_QP, cmd.qp_handle, attrs); +- if (!qp) +- return -EINVAL; ++ if (IS_ERR(qp)) ++ return PTR_ERR(qp); + + obj = qp->uobject; + mutex_lock(&obj->mcast_lock); +@@ -2666,8 +2674,8 @@ static int kern_spec_to_ib_spec_action(struct uverbs_attr_bundle *attrs, + UVERBS_OBJECT_FLOW_ACTION, + kern_spec->action.handle, + attrs); +- if (!ib_spec->action.act) +- return -EINVAL; ++ if (IS_ERR(ib_spec->action.act)) ++ return PTR_ERR(ib_spec->action.act); + ib_spec->action.size = + sizeof(struct ib_flow_spec_action_handle); + flow_resources_add(uflow_res, +@@ -2684,8 +2692,8 @@ static int kern_spec_to_ib_spec_action(struct uverbs_attr_bundle *attrs, + UVERBS_OBJECT_COUNTERS, + kern_spec->flow_count.handle, + attrs); +- if (!ib_spec->flow_count.counters) +- return -EINVAL; ++ if (IS_ERR(ib_spec->flow_count.counters)) ++ return PTR_ERR(ib_spec->flow_count.counters); + ib_spec->flow_count.size = + sizeof(struct ib_flow_spec_action_count); + flow_resources_add(uflow_res, +@@ -2903,14 +2911,14 @@ static int ib_uverbs_ex_create_wq(struct uverbs_attr_bundle *attrs) + return PTR_ERR(obj); + + pd = uobj_get_obj_read(pd, UVERBS_OBJECT_PD, cmd.pd_handle, attrs); +- if (!pd) { +- err = -EINVAL; ++ if (IS_ERR(pd)) { ++ err = PTR_ERR(pd); + goto err_uobj; + } + + cq = uobj_get_obj_read(cq, UVERBS_OBJECT_CQ, cmd.cq_handle, attrs); +- if (!cq) { +- err = -EINVAL; ++ if (IS_ERR(cq)) { ++ err = PTR_ERR(cq); + goto err_put_pd; + } + +@@ -3011,8 +3019,8 @@ static int ib_uverbs_ex_modify_wq(struct uverbs_attr_bundle *attrs) + return -EINVAL; + + wq = uobj_get_obj_read(wq, UVERBS_OBJECT_WQ, cmd.wq_handle, attrs); +- if (!wq) +- return -EINVAL; ++ if (IS_ERR(wq)) ++ return PTR_ERR(wq); + + if (cmd.attr_mask & IB_WQ_FLAGS) { + wq_attr.flags = cmd.flags; +@@ -3095,8 +3103,8 @@ static int ib_uverbs_ex_create_rwq_ind_table(struct uverbs_attr_bundle *attrs) + num_read_wqs++) { + wq = uobj_get_obj_read(wq, UVERBS_OBJECT_WQ, + wqs_handles[num_read_wqs], attrs); +- if (!wq) { +- err = -EINVAL; ++ if (IS_ERR(wq)) { ++ err = PTR_ERR(wq); + goto put_wqs; + } + +@@ -3251,8 +3259,8 @@ static int ib_uverbs_ex_create_flow(struct uverbs_attr_bundle *attrs) + } + + qp = uobj_get_obj_read(qp, UVERBS_OBJECT_QP, cmd.qp_handle, attrs); +- if (!qp) { +- err = -EINVAL; ++ if (IS_ERR(qp)) { ++ err = PTR_ERR(qp); + goto err_uobj; + } + +@@ -3398,15 +3406,15 @@ static int __uverbs_create_xsrq(struct uverbs_attr_bundle *attrs, + if (ib_srq_has_cq(cmd->srq_type)) { + attr.ext.cq = uobj_get_obj_read(cq, UVERBS_OBJECT_CQ, + cmd->cq_handle, attrs); +- if (!attr.ext.cq) { +- ret = -EINVAL; ++ if (IS_ERR(attr.ext.cq)) { ++ ret = PTR_ERR(attr.ext.cq); + goto err_put_xrcd; + } + } + + pd = uobj_get_obj_read(pd, UVERBS_OBJECT_PD, cmd->pd_handle, attrs); +- if (!pd) { +- ret = -EINVAL; ++ if (IS_ERR(pd)) { ++ ret = PTR_ERR(pd); + goto err_put_cq; + } + +@@ -3513,8 +3521,8 @@ static int ib_uverbs_modify_srq(struct uverbs_attr_bundle *attrs) + return ret; + + srq = uobj_get_obj_read(srq, UVERBS_OBJECT_SRQ, cmd.srq_handle, attrs); +- if (!srq) +- return -EINVAL; ++ if (IS_ERR(srq)) ++ return PTR_ERR(srq); + + attr.max_wr = cmd.max_wr; + attr.srq_limit = cmd.srq_limit; +@@ -3541,8 +3549,8 @@ static int ib_uverbs_query_srq(struct uverbs_attr_bundle *attrs) + return ret; + + srq = uobj_get_obj_read(srq, UVERBS_OBJECT_SRQ, cmd.srq_handle, attrs); +- if (!srq) +- return -EINVAL; ++ if (IS_ERR(srq)) ++ return PTR_ERR(srq); + + ret = ib_query_srq(srq, &attr); + +@@ -3667,8 +3675,8 @@ static int ib_uverbs_ex_modify_cq(struct uverbs_attr_bundle *attrs) + return -EOPNOTSUPP; + + cq = uobj_get_obj_read(cq, UVERBS_OBJECT_CQ, cmd.cq_handle, attrs); +- if (!cq) +- return -EINVAL; ++ if (IS_ERR(cq)) ++ return PTR_ERR(cq); + + ret = rdma_set_cq_moderation(cq, cmd.attr.cq_count, cmd.attr.cq_period); + +diff --git a/include/rdma/uverbs_std_types.h b/include/rdma/uverbs_std_types.h +index fe05121169589..555ea3d142a46 100644 +--- a/include/rdma/uverbs_std_types.h ++++ b/include/rdma/uverbs_std_types.h +@@ -34,7 +34,7 @@ + static inline void *_uobj_get_obj_read(struct ib_uobject *uobj) + { + if (IS_ERR(uobj)) +- return NULL; ++ return ERR_CAST(uobj); + return uobj->object; + } + #define uobj_get_obj_read(_object, _type, _id, _attrs) \ +-- +2.39.5 + diff --git a/queue-6.14/regulator-ad5398-add-device-tree-support.patch b/queue-6.14/regulator-ad5398-add-device-tree-support.patch new file mode 100644 index 0000000000..2be45dda10 --- /dev/null +++ b/queue-6.14/regulator-ad5398-add-device-tree-support.patch @@ -0,0 +1,63 @@ +From 88d1e94e5eaedcb1e8338d755d3299d208e8a87a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 28 Jan 2025 17:31:43 +0000 +Subject: regulator: ad5398: Add device tree support + +From: Isaac Scott + +[ Upstream commit 5a6a461079decea452fdcae955bccecf92e07e97 ] + +Previously, the ad5398 driver used only platform_data, which is +deprecated in favour of device tree. This caused the AD5398 to fail to +probe as it could not load its init_data. If the AD5398 has a device +tree node, pull the init_data from there using +of_get_regulator_init_data. + +Signed-off-by: Isaac Scott +Acked-by: Michael Hennerich +Link: https://patch.msgid.link/20250128173143.959600-4-isaac.scott@ideasonboard.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + drivers/regulator/ad5398.c | 12 +++++++++--- + 1 file changed, 9 insertions(+), 3 deletions(-) + +diff --git a/drivers/regulator/ad5398.c b/drivers/regulator/ad5398.c +index 40f7dba42b5ad..404cbe32711e7 100644 +--- a/drivers/regulator/ad5398.c ++++ b/drivers/regulator/ad5398.c +@@ -14,6 +14,7 @@ + #include + #include + #include ++#include + + #define AD5398_CURRENT_EN_MASK 0x8000 + +@@ -221,15 +222,20 @@ static int ad5398_probe(struct i2c_client *client) + const struct ad5398_current_data_format *df = + (struct ad5398_current_data_format *)id->driver_data; + +- if (!init_data) +- return -EINVAL; +- + chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL); + if (!chip) + return -ENOMEM; + + config.dev = &client->dev; ++ if (client->dev.of_node) ++ init_data = of_get_regulator_init_data(&client->dev, ++ client->dev.of_node, ++ &ad5398_reg); ++ if (!init_data) ++ return -EINVAL; ++ + config.init_data = init_data; ++ config.of_node = client->dev.of_node; + config.driver_data = chip; + + chip->client = client; +-- +2.39.5 + diff --git a/queue-6.14/remoteproc-qcom_wcnss-handle-platforms-with-only-sin.patch b/queue-6.14/remoteproc-qcom_wcnss-handle-platforms-with-only-sin.patch new file mode 100644 index 0000000000..14ea8aa4cf --- /dev/null +++ b/queue-6.14/remoteproc-qcom_wcnss-handle-platforms-with-only-sin.patch @@ -0,0 +1,113 @@ +From 79ae2d6e2ec622378c2f50a17e337b9d487afb54 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Feb 2025 20:56:48 +0100 +Subject: remoteproc: qcom_wcnss: Handle platforms with only single power + domain +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Matti Lehtimäki + +[ Upstream commit 65991ea8a6d1e68effdc01d95ebe39f1653f7b71 ] + +Both MSM8974 and MSM8226 have only CX as power domain with MX & PX being +handled as regulators. Handle this case by reodering pd_names to have CX +first, and handling that the driver core will already attach a single +power domain internally. + +Signed-off-by: Matti Lehtimäki +[luca: minor changes] +Signed-off-by: Luca Weiss +Link: https://lore.kernel.org/r/20250206-wcnss-singlepd-v2-2-9a53ee953dee@lucaweiss.eu +[bjorn: Added missing braces to else after multi-statement if] +Signed-off-by: Bjorn Andersson +Signed-off-by: Sasha Levin +--- + drivers/remoteproc/qcom_wcnss.c | 33 ++++++++++++++++++++++++++------- + 1 file changed, 26 insertions(+), 7 deletions(-) + +diff --git a/drivers/remoteproc/qcom_wcnss.c b/drivers/remoteproc/qcom_wcnss.c +index 5b5664603eed2..775b056d795a8 100644 +--- a/drivers/remoteproc/qcom_wcnss.c ++++ b/drivers/remoteproc/qcom_wcnss.c +@@ -117,10 +117,10 @@ static const struct wcnss_data pronto_v1_data = { + .pmu_offset = 0x1004, + .spare_offset = 0x1088, + +- .pd_names = { "mx", "cx" }, ++ .pd_names = { "cx", "mx" }, + .vregs = (struct wcnss_vreg_info[]) { +- { "vddmx", 950000, 1150000, 0 }, + { "vddcx", .super_turbo = true}, ++ { "vddmx", 950000, 1150000, 0 }, + { "vddpx", 1800000, 1800000, 0 }, + }, + .num_pd_vregs = 2, +@@ -131,10 +131,10 @@ static const struct wcnss_data pronto_v2_data = { + .pmu_offset = 0x1004, + .spare_offset = 0x1088, + +- .pd_names = { "mx", "cx" }, ++ .pd_names = { "cx", "mx" }, + .vregs = (struct wcnss_vreg_info[]) { +- { "vddmx", 1287500, 1287500, 0 }, + { "vddcx", .super_turbo = true }, ++ { "vddmx", 1287500, 1287500, 0 }, + { "vddpx", 1800000, 1800000, 0 }, + }, + .num_pd_vregs = 2, +@@ -397,8 +397,17 @@ static irqreturn_t wcnss_stop_ack_interrupt(int irq, void *dev) + static int wcnss_init_pds(struct qcom_wcnss *wcnss, + const char * const pd_names[WCNSS_MAX_PDS]) + { ++ struct device *dev = wcnss->dev; + int i, ret; + ++ /* Handle single power domain */ ++ if (dev->pm_domain) { ++ wcnss->pds[0] = dev; ++ wcnss->num_pds = 1; ++ pm_runtime_enable(dev); ++ return 0; ++ } ++ + for (i = 0; i < WCNSS_MAX_PDS; i++) { + if (!pd_names[i]) + break; +@@ -418,8 +427,15 @@ static int wcnss_init_pds(struct qcom_wcnss *wcnss, + + static void wcnss_release_pds(struct qcom_wcnss *wcnss) + { ++ struct device *dev = wcnss->dev; + int i; + ++ /* Handle single power domain */ ++ if (wcnss->num_pds == 1 && dev->pm_domain) { ++ pm_runtime_disable(dev); ++ return; ++ } ++ + for (i = 0; i < wcnss->num_pds; i++) + dev_pm_domain_detach(wcnss->pds[i], false); + } +@@ -437,10 +453,13 @@ static int wcnss_init_regulators(struct qcom_wcnss *wcnss, + * the regulators for the power domains. For old device trees we need to + * reserve extra space to manage them through the regulator interface. + */ +- if (wcnss->num_pds) +- info += num_pd_vregs; +- else ++ if (wcnss->num_pds) { ++ info += wcnss->num_pds; ++ /* Handle single power domain case */ ++ num_vregs += num_pd_vregs - wcnss->num_pds; ++ } else { + num_vregs += num_pd_vregs; ++ } + + bulk = devm_kcalloc(wcnss->dev, + num_vregs, sizeof(struct regulator_bulk_data), +-- +2.39.5 + diff --git a/queue-6.14/revert-drm-amd-display-exit-idle-optimizations-befor.patch b/queue-6.14/revert-drm-amd-display-exit-idle-optimizations-befor.patch new file mode 100644 index 0000000000..604c980cc2 --- /dev/null +++ b/queue-6.14/revert-drm-amd-display-exit-idle-optimizations-befor.patch @@ -0,0 +1,58 @@ +From b7eaabcbc077d065af9776dc08dc9929bd0d2a72 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Jan 2025 13:29:51 +0800 +Subject: Revert "drm/amd/display: Exit idle optimizations before attempt to + access PHY" + +From: Brandon Syu + +[ Upstream commit be704e5ef4bd66dee9bb3f876964327e3a247d31 ] + +This reverts commit de612738e9771bd66aeb20044486c457c512f684. + +Reason to revert: screen flashes or gray screen appeared half of the +screen after resume from S4/S5. + +Reviewed-by: Charlene Liu +Signed-off-by: Brandon Syu +Signed-off-by: Alex Hung +Tested-by: Daniel Wheeler +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c | 5 ----- + 1 file changed, 5 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c +index 94ceccfc04982..2f5f3e749a1ab 100644 +--- a/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c ++++ b/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c +@@ -1889,7 +1889,6 @@ void dce110_enable_accelerated_mode(struct dc *dc, struct dc_state *context) + bool can_apply_edp_fast_boot = false; + bool can_apply_seamless_boot = false; + bool keep_edp_vdd_on = false; +- struct dc_bios *dcb = dc->ctx->dc_bios; + DC_LOGGER_INIT(); + + +@@ -1966,8 +1965,6 @@ void dce110_enable_accelerated_mode(struct dc *dc, struct dc_state *context) + hws->funcs.edp_backlight_control(edp_link_with_sink, false); + } + /*resume from S3, no vbios posting, no need to power down again*/ +- if (dcb && dcb->funcs && !dcb->funcs->is_accelerated_mode(dcb)) +- clk_mgr_exit_optimized_pwr_state(dc, dc->clk_mgr); + + power_down_all_hw_blocks(dc); + +@@ -1980,8 +1977,6 @@ void dce110_enable_accelerated_mode(struct dc *dc, struct dc_state *context) + disable_vga_and_power_gate_all_controllers(dc); + if (edp_link_with_sink && !keep_edp_vdd_on) + dc->hwss.edp_power_control(edp_link_with_sink, false); +- if (dcb && dcb->funcs && !dcb->funcs->is_accelerated_mode(dcb)) +- clk_mgr_optimize_pwr_state(dc, dc->clk_mgr); + } + bios_set_scratch_acc_mode_change(dc->ctx->dc_bios, 1); + } +-- +2.39.5 + diff --git a/queue-6.14/revert-drm-amd-display-request-hw-cursor-on-dcn3.2-w.patch b/queue-6.14/revert-drm-amd-display-request-hw-cursor-on-dcn3.2-w.patch new file mode 100644 index 0000000000..5e81cafd2f --- /dev/null +++ b/queue-6.14/revert-drm-amd-display-request-hw-cursor-on-dcn3.2-w.patch @@ -0,0 +1,38 @@ +From 86c8fd69f744a04040ad5c0faf672c06c248ba94 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 31 Jan 2025 11:46:52 -0500 +Subject: Revert "drm/amd/display: Request HW cursor on DCN3.2 with SubVP" + +From: Leo Zeng + +[ Upstream commit 8ae6dfc0b61b170cf13832d4cfe2a0c744e621a7 ] + +This reverts commit 13437c91606c9232c747475e202fe3827cd53264. + +Reason to revert: idle power regression found in testing. + +Reviewed-by: Dillon Varone +Signed-off-by: Leo Zeng +Signed-off-by: Roman Li +Tested-by: Daniel Wheeler +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c +index 56dda686e2992..6f490d8d7038c 100644 +--- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c ++++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c +@@ -626,7 +626,6 @@ static bool dcn32_assign_subvp_pipe(struct dc *dc, + * - Not TMZ surface + */ + if (pipe->plane_state && !pipe->top_pipe && !pipe->prev_odm_pipe && !dcn32_is_center_timing(pipe) && +- !pipe->stream->hw_cursor_req && + !(pipe->stream->timing.pix_clk_100hz / 10000 > DCN3_2_MAX_SUBVP_PIXEL_RATE_MHZ) && + (!dcn32_is_psr_capable(pipe) || (context->stream_count == 1 && dc->caps.dmub_caps.subvp_psr)) && + dc_state_get_pipe_subvp_type(context, pipe) == SUBVP_NONE && +-- +2.39.5 + diff --git a/queue-6.14/ring-buffer-use-kaslr-address-instead-of-text-delta.patch b/queue-6.14/ring-buffer-use-kaslr-address-instead-of-text-delta.patch new file mode 100644 index 0000000000..8ad7ba8c3e --- /dev/null +++ b/queue-6.14/ring-buffer-use-kaslr-address-instead-of-text-delta.patch @@ -0,0 +1,254 @@ +From 46f1d6670a502013aae3f53ca5cd000a55b78d65 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Mar 2025 11:45:40 -0500 +Subject: ring-buffer: Use kaslr address instead of text delta + +From: Steven Rostedt + +[ Upstream commit bcba8d4dbe6880ce9883409df486de35d3946704 ] + +Instead of saving off the text and data pointers and using them to compare +with the current boot's text and data pointers, just save off the KASLR +offset. Then that can be used to figure out how to read the previous boots +buffer. + +The last_boot_info will now show this offset, but only if it is for a +previous boot: + + ~# cat instances/boot_mapped/last_boot_info + 39000000 [kernel] + + ~# echo function > instances/boot_mapped/current_tracer + ~# cat instances/boot_mapped/last_boot_info + # Current + +If the KASLR offset saved is for the current boot, the last_boot_info will +show the value of "current". + +Cc: Mark Rutland +Cc: Mathieu Desnoyers +Cc: Andrew Morton +Link: https://lore.kernel.org/20250305164608.274956504@goodmis.org +Reviewed-by: Masami Hiramatsu (Google) +Signed-off-by: Steven Rostedt (Google) +Signed-off-by: Sasha Levin +--- + include/linux/ring_buffer.h | 3 +-- + kernel/trace/ring_buffer.c | 31 ++++++++++++------------------- + kernel/trace/trace.c | 30 +++++++++++++++++++++--------- + kernel/trace/trace.h | 9 +++++---- + 4 files changed, 39 insertions(+), 34 deletions(-) + +diff --git a/include/linux/ring_buffer.h b/include/linux/ring_buffer.h +index 17fbb78552952..8de035f4f0d9a 100644 +--- a/include/linux/ring_buffer.h ++++ b/include/linux/ring_buffer.h +@@ -94,8 +94,7 @@ struct trace_buffer *__ring_buffer_alloc_range(unsigned long size, unsigned flag + unsigned long range_size, + struct lock_class_key *key); + +-bool ring_buffer_last_boot_delta(struct trace_buffer *buffer, long *text, +- long *data); ++bool ring_buffer_last_boot_delta(struct trace_buffer *buffer, unsigned long *kaslr_addr); + + /* + * Because the ring buffer is generic, if other users of the ring buffer get +diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c +index f76bee67a792c..9b1db04c74e25 100644 +--- a/kernel/trace/ring_buffer.c ++++ b/kernel/trace/ring_buffer.c +@@ -31,6 +31,7 @@ + + #include + #include ++#include + + #include "trace.h" + +@@ -49,8 +50,7 @@ static void update_pages_handler(struct work_struct *work); + struct ring_buffer_meta { + int magic; + int struct_size; +- unsigned long text_addr; +- unsigned long data_addr; ++ unsigned long kaslr_addr; + unsigned long first_buffer; + unsigned long head_buffer; + unsigned long commit_buffer; +@@ -550,8 +550,7 @@ struct trace_buffer { + unsigned long range_addr_start; + unsigned long range_addr_end; + +- long last_text_delta; +- long last_data_delta; ++ unsigned long kaslr_addr; + + unsigned int subbuf_size; + unsigned int subbuf_order; +@@ -1893,16 +1892,13 @@ static void rb_meta_validate_events(struct ring_buffer_per_cpu *cpu_buffer) + } + } + +-/* Used to calculate data delta */ +-static char rb_data_ptr[] = ""; +- +-#define THIS_TEXT_PTR ((unsigned long)rb_meta_init_text_addr) +-#define THIS_DATA_PTR ((unsigned long)rb_data_ptr) +- + static void rb_meta_init_text_addr(struct ring_buffer_meta *meta) + { +- meta->text_addr = THIS_TEXT_PTR; +- meta->data_addr = THIS_DATA_PTR; ++#ifdef CONFIG_RANDOMIZE_BASE ++ meta->kaslr_addr = kaslr_offset(); ++#else ++ meta->kaslr_addr = 0; ++#endif + } + + static void rb_range_meta_init(struct trace_buffer *buffer, int nr_pages) +@@ -1930,8 +1926,7 @@ static void rb_range_meta_init(struct trace_buffer *buffer, int nr_pages) + meta->first_buffer += delta; + meta->head_buffer += delta; + meta->commit_buffer += delta; +- buffer->last_text_delta = THIS_TEXT_PTR - meta->text_addr; +- buffer->last_data_delta = THIS_DATA_PTR - meta->data_addr; ++ buffer->kaslr_addr = meta->kaslr_addr; + continue; + } + +@@ -2484,17 +2479,15 @@ struct trace_buffer *__ring_buffer_alloc_range(unsigned long size, unsigned flag + * + * Returns: The true if the delta is non zero + */ +-bool ring_buffer_last_boot_delta(struct trace_buffer *buffer, long *text, +- long *data) ++bool ring_buffer_last_boot_delta(struct trace_buffer *buffer, unsigned long *kaslr_addr) + { + if (!buffer) + return false; + +- if (!buffer->last_text_delta) ++ if (!buffer->kaslr_addr) + return false; + +- *text = buffer->last_text_delta; +- *data = buffer->last_data_delta; ++ *kaslr_addr = buffer->kaslr_addr; + + return true; + } +diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c +index 814626bb410b2..c3f1365ec9609 100644 +--- a/kernel/trace/trace.c ++++ b/kernel/trace/trace.c +@@ -50,7 +50,7 @@ + #include + #include + +-#include /* COMMAND_LINE_SIZE */ ++#include /* COMMAND_LINE_SIZE and kaslr_offset() */ + + #include "trace.h" + #include "trace_output.h" +@@ -4193,7 +4193,7 @@ static enum print_line_t print_trace_fmt(struct trace_iterator *iter) + * safe to use if the array has delta offsets + * Force printing via the fields. + */ +- if ((tr->text_delta || tr->data_delta) && ++ if ((tr->text_delta) && + event->type > __TRACE_LAST_TYPE) + return print_event_fields(iter, event); + +@@ -5990,7 +5990,7 @@ ssize_t tracing_resize_ring_buffer(struct trace_array *tr, + + static void update_last_data(struct trace_array *tr) + { +- if (!tr->text_delta && !tr->data_delta) ++ if (!(tr->flags & TRACE_ARRAY_FL_LAST_BOOT)) + return; + + /* +@@ -6003,7 +6003,8 @@ static void update_last_data(struct trace_array *tr) + + /* Using current data now */ + tr->text_delta = 0; +- tr->data_delta = 0; ++ ++ tr->flags &= ~TRACE_ARRAY_FL_LAST_BOOT; + } + + /** +@@ -6822,8 +6823,17 @@ tracing_last_boot_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t + + seq_buf_init(&seq, buf, 64); + +- seq_buf_printf(&seq, "text delta:\t%ld\n", tr->text_delta); +- seq_buf_printf(&seq, "data delta:\t%ld\n", tr->data_delta); ++ /* ++ * Do not leak KASLR address. This only shows the KASLR address of ++ * the last boot. When the ring buffer is started, the LAST_BOOT ++ * flag gets cleared, and this should only report "current". ++ * Otherwise it shows the KASLR address from the previous boot which ++ * should not be the same as the current boot. ++ */ ++ if (tr->flags & TRACE_ARRAY_FL_LAST_BOOT) ++ seq_buf_printf(&seq, "%lx\t[kernel]\n", tr->kaslr_addr); ++ else ++ seq_buf_puts(&seq, "# Current\n"); + + return simple_read_from_buffer(ubuf, cnt, ppos, buf, seq_buf_used(&seq)); + } +@@ -9211,8 +9221,10 @@ allocate_trace_buffer(struct trace_array *tr, struct array_buffer *buf, int size + tr->range_addr_start, + tr->range_addr_size); + +- ring_buffer_last_boot_delta(buf->buffer, +- &tr->text_delta, &tr->data_delta); ++#ifdef CONFIG_RANDOMIZE_BASE ++ if (ring_buffer_last_boot_delta(buf->buffer, &tr->kaslr_addr)) ++ tr->text_delta = kaslr_offset() - tr->kaslr_addr; ++#endif + /* + * This is basically the same as a mapped buffer, + * with the same restrictions. +@@ -10470,7 +10482,7 @@ __init static void enable_instances(void) + * to it. + */ + if (start) { +- tr->flags |= TRACE_ARRAY_FL_BOOT; ++ tr->flags |= TRACE_ARRAY_FL_BOOT | TRACE_ARRAY_FL_LAST_BOOT; + tr->ref++; + } + +diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h +index 9c21ba45b7af6..abe8169c3e879 100644 +--- a/kernel/trace/trace.h ++++ b/kernel/trace/trace.h +@@ -348,8 +348,8 @@ struct trace_array { + unsigned int mapped; + unsigned long range_addr_start; + unsigned long range_addr_size; ++ unsigned long kaslr_addr; + long text_delta; +- long data_delta; + + struct trace_pid_list __rcu *filtered_pids; + struct trace_pid_list __rcu *filtered_no_pids; +@@ -433,9 +433,10 @@ struct trace_array { + }; + + enum { +- TRACE_ARRAY_FL_GLOBAL = BIT(0), +- TRACE_ARRAY_FL_BOOT = BIT(1), +- TRACE_ARRAY_FL_MOD_INIT = BIT(2), ++ TRACE_ARRAY_FL_GLOBAL = BIT(0), ++ TRACE_ARRAY_FL_BOOT = BIT(1), ++ TRACE_ARRAY_FL_LAST_BOOT = BIT(2), ++ TRACE_ARRAY_FL_MOD_INIT = BIT(3), + }; + + #ifdef CONFIG_MODULES +-- +2.39.5 + diff --git a/queue-6.14/risc-v-add-vector-extension-validation-checks.patch b/queue-6.14/risc-v-add-vector-extension-validation-checks.patch new file mode 100644 index 0000000000..7ada74a77b --- /dev/null +++ b/queue-6.14/risc-v-add-vector-extension-validation-checks.patch @@ -0,0 +1,140 @@ +From 83c3b01bf2256da135b68ca5367043c784d171b9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 12 Mar 2025 13:11:44 +0000 +Subject: RISC-V: add vector extension validation checks + +From: Conor Dooley + +[ Upstream commit 9324571e9eea231321acf0a3d0fbc85a6e0f6ff6 ] + +Using Clement's new validation callbacks, support checking that +dependencies have been satisfied for the vector extensions. From the +kernel's perfective, it's not required to differentiate between the +conditions for all the various vector subsets - it's the firmware's job +to not report impossible combinations. Instead, the kernel only has to +check that the correct config options are enabled and to enforce its +requirement of the d extension being present for FPU support. + +Since vector will now be disabled proactively, there's no need to clear +the bit in elf_hwcap in riscv_fill_hwcap() any longer. + +Signed-off-by: Conor Dooley +Reviewed-by: Alexandre Ghiti +Link: https://lore.kernel.org/r/20250312-eclair-affluent-55b098c3602b@spud +Signed-off-by: Alexandre Ghiti +Signed-off-by: Sasha Levin +--- + arch/riscv/include/asm/cpufeature.h | 3 ++ + arch/riscv/kernel/cpufeature.c | 60 +++++++++++++++++++---------- + 2 files changed, 43 insertions(+), 20 deletions(-) + +diff --git a/arch/riscv/include/asm/cpufeature.h b/arch/riscv/include/asm/cpufeature.h +index 19defdc2002d8..f56b409361fbe 100644 +--- a/arch/riscv/include/asm/cpufeature.h ++++ b/arch/riscv/include/asm/cpufeature.h +@@ -56,6 +56,9 @@ void __init riscv_user_isa_enable(void); + #define __RISCV_ISA_EXT_BUNDLE(_name, _bundled_exts) \ + _RISCV_ISA_EXT_DATA(_name, RISCV_ISA_EXT_INVALID, _bundled_exts, \ + ARRAY_SIZE(_bundled_exts), NULL) ++#define __RISCV_ISA_EXT_BUNDLE_VALIDATE(_name, _bundled_exts, _validate) \ ++ _RISCV_ISA_EXT_DATA(_name, RISCV_ISA_EXT_INVALID, _bundled_exts, \ ++ ARRAY_SIZE(_bundled_exts), _validate) + + /* Used to declare extensions that are a superset of other extensions (Zvbb for instance) */ + #define __RISCV_ISA_EXT_SUPERSET(_name, _id, _sub_exts) \ +diff --git a/arch/riscv/kernel/cpufeature.c b/arch/riscv/kernel/cpufeature.c +index 40ac72e407b68..76a3b34d7a707 100644 +--- a/arch/riscv/kernel/cpufeature.c ++++ b/arch/riscv/kernel/cpufeature.c +@@ -109,6 +109,38 @@ static int riscv_ext_zicboz_validate(const struct riscv_isa_ext_data *data, + return 0; + } + ++static int riscv_ext_vector_x_validate(const struct riscv_isa_ext_data *data, ++ const unsigned long *isa_bitmap) ++{ ++ if (!IS_ENABLED(CONFIG_RISCV_ISA_V)) ++ return -EINVAL; ++ ++ return 0; ++} ++ ++static int riscv_ext_vector_float_validate(const struct riscv_isa_ext_data *data, ++ const unsigned long *isa_bitmap) ++{ ++ if (!IS_ENABLED(CONFIG_RISCV_ISA_V)) ++ return -EINVAL; ++ ++ if (!IS_ENABLED(CONFIG_FPU)) ++ return -EINVAL; ++ ++ /* ++ * The kernel doesn't support systems that don't implement both of ++ * F and D, so if any of the vector extensions that do floating point ++ * are to be usable, both floating point extensions need to be usable. ++ * ++ * Since this function validates vector only, and v/Zve* are probed ++ * after f/d, there's no need for a deferral here. ++ */ ++ if (!__riscv_isa_extension_available(isa_bitmap, RISCV_ISA_EXT_d)) ++ return -EINVAL; ++ ++ return 0; ++} ++ + static int riscv_ext_zca_depends(const struct riscv_isa_ext_data *data, + const unsigned long *isa_bitmap) + { +@@ -326,12 +358,10 @@ const struct riscv_isa_ext_data riscv_isa_ext[] = { + __RISCV_ISA_EXT_DATA(d, RISCV_ISA_EXT_d), + __RISCV_ISA_EXT_DATA(q, RISCV_ISA_EXT_q), + __RISCV_ISA_EXT_SUPERSET(c, RISCV_ISA_EXT_c, riscv_c_exts), +- __RISCV_ISA_EXT_SUPERSET(v, RISCV_ISA_EXT_v, riscv_v_exts), ++ __RISCV_ISA_EXT_SUPERSET_VALIDATE(v, RISCV_ISA_EXT_v, riscv_v_exts, riscv_ext_vector_float_validate), + __RISCV_ISA_EXT_DATA(h, RISCV_ISA_EXT_h), +- __RISCV_ISA_EXT_SUPERSET_VALIDATE(zicbom, RISCV_ISA_EXT_ZICBOM, riscv_xlinuxenvcfg_exts, +- riscv_ext_zicbom_validate), +- __RISCV_ISA_EXT_SUPERSET_VALIDATE(zicboz, RISCV_ISA_EXT_ZICBOZ, riscv_xlinuxenvcfg_exts, +- riscv_ext_zicboz_validate), ++ __RISCV_ISA_EXT_SUPERSET_VALIDATE(zicbom, RISCV_ISA_EXT_ZICBOM, riscv_xlinuxenvcfg_exts, riscv_ext_zicbom_validate), ++ __RISCV_ISA_EXT_SUPERSET_VALIDATE(zicboz, RISCV_ISA_EXT_ZICBOZ, riscv_xlinuxenvcfg_exts, riscv_ext_zicboz_validate), + __RISCV_ISA_EXT_DATA(ziccrse, RISCV_ISA_EXT_ZICCRSE), + __RISCV_ISA_EXT_DATA(zicntr, RISCV_ISA_EXT_ZICNTR), + __RISCV_ISA_EXT_DATA(zicond, RISCV_ISA_EXT_ZICOND), +@@ -372,11 +402,11 @@ const struct riscv_isa_ext_data riscv_isa_ext[] = { + __RISCV_ISA_EXT_DATA(ztso, RISCV_ISA_EXT_ZTSO), + __RISCV_ISA_EXT_SUPERSET(zvbb, RISCV_ISA_EXT_ZVBB, riscv_zvbb_exts), + __RISCV_ISA_EXT_DATA(zvbc, RISCV_ISA_EXT_ZVBC), +- __RISCV_ISA_EXT_SUPERSET(zve32f, RISCV_ISA_EXT_ZVE32F, riscv_zve32f_exts), +- __RISCV_ISA_EXT_DATA(zve32x, RISCV_ISA_EXT_ZVE32X), +- __RISCV_ISA_EXT_SUPERSET(zve64d, RISCV_ISA_EXT_ZVE64D, riscv_zve64d_exts), +- __RISCV_ISA_EXT_SUPERSET(zve64f, RISCV_ISA_EXT_ZVE64F, riscv_zve64f_exts), +- __RISCV_ISA_EXT_SUPERSET(zve64x, RISCV_ISA_EXT_ZVE64X, riscv_zve64x_exts), ++ __RISCV_ISA_EXT_SUPERSET_VALIDATE(zve32f, RISCV_ISA_EXT_ZVE32F, riscv_zve32f_exts, riscv_ext_vector_float_validate), ++ __RISCV_ISA_EXT_DATA_VALIDATE(zve32x, RISCV_ISA_EXT_ZVE32X, riscv_ext_vector_x_validate), ++ __RISCV_ISA_EXT_SUPERSET_VALIDATE(zve64d, RISCV_ISA_EXT_ZVE64D, riscv_zve64d_exts, riscv_ext_vector_float_validate), ++ __RISCV_ISA_EXT_SUPERSET_VALIDATE(zve64f, RISCV_ISA_EXT_ZVE64F, riscv_zve64f_exts, riscv_ext_vector_float_validate), ++ __RISCV_ISA_EXT_SUPERSET_VALIDATE(zve64x, RISCV_ISA_EXT_ZVE64X, riscv_zve64x_exts, riscv_ext_vector_x_validate), + __RISCV_ISA_EXT_DATA(zvfh, RISCV_ISA_EXT_ZVFH), + __RISCV_ISA_EXT_DATA(zvfhmin, RISCV_ISA_EXT_ZVFHMIN), + __RISCV_ISA_EXT_DATA(zvkb, RISCV_ISA_EXT_ZVKB), +@@ -960,16 +990,6 @@ void __init riscv_fill_hwcap(void) + riscv_v_setup_vsize(); + } + +- if (elf_hwcap & COMPAT_HWCAP_ISA_V) { +- /* +- * ISA string in device tree might have 'v' flag, but +- * CONFIG_RISCV_ISA_V is disabled in kernel. +- * Clear V flag in elf_hwcap if CONFIG_RISCV_ISA_V is disabled. +- */ +- if (!IS_ENABLED(CONFIG_RISCV_ISA_V)) +- elf_hwcap &= ~COMPAT_HWCAP_ISA_V; +- } +- + memset(print_str, 0, sizeof(print_str)); + for (i = 0, j = 0; i < NUM_ALPHA_EXTS; i++) + if (riscv_isa[0] & BIT_MASK(i)) +-- +2.39.5 + diff --git a/queue-6.14/riscv-allow-nommu-kernels-to-access-all-of-ram.patch b/queue-6.14/riscv-allow-nommu-kernels-to-access-all-of-ram.patch new file mode 100644 index 0000000000..183cc2b5ab --- /dev/null +++ b/queue-6.14/riscv-allow-nommu-kernels-to-access-all-of-ram.patch @@ -0,0 +1,80 @@ +From e06c1f5291f6398765f253c344e846364a828dfc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 26 Oct 2024 10:13:54 -0700 +Subject: riscv: Allow NOMMU kernels to access all of RAM + +From: Samuel Holland + +[ Upstream commit 2c0391b29b27f315c1b4c29ffde66f50b29fab99 ] + +NOMMU kernels currently cannot access memory below the kernel link +address. Remove this restriction by setting PAGE_OFFSET to the actual +start of RAM, as determined from the devicetree. The kernel link address +must be a constant, so keep using CONFIG_PAGE_OFFSET for that purpose. + +Signed-off-by: Samuel Holland +Reviewed-by: Jesse Taube +Link: https://lore.kernel.org/r/20241026171441.3047904-3-samuel.holland@sifive.com +Signed-off-by: Palmer Dabbelt +Signed-off-by: Sasha Levin +--- + arch/riscv/include/asm/page.h | 12 ++++-------- + arch/riscv/include/asm/pgtable.h | 2 +- + 2 files changed, 5 insertions(+), 9 deletions(-) + +diff --git a/arch/riscv/include/asm/page.h b/arch/riscv/include/asm/page.h +index 125f5ecd95652..6409fd78ae6fa 100644 +--- a/arch/riscv/include/asm/page.h ++++ b/arch/riscv/include/asm/page.h +@@ -24,12 +24,9 @@ + * When not using MMU this corresponds to the first free page in + * physical memory (aligned on a page boundary). + */ +-#ifdef CONFIG_64BIT + #ifdef CONFIG_MMU ++#ifdef CONFIG_64BIT + #define PAGE_OFFSET kernel_map.page_offset +-#else +-#define PAGE_OFFSET _AC(CONFIG_PAGE_OFFSET, UL) +-#endif + /* + * By default, CONFIG_PAGE_OFFSET value corresponds to SV57 address space so + * define the PAGE_OFFSET value for SV48 and SV39. +@@ -39,6 +36,9 @@ + #else + #define PAGE_OFFSET _AC(CONFIG_PAGE_OFFSET, UL) + #endif /* CONFIG_64BIT */ ++#else ++#define PAGE_OFFSET ((unsigned long)phys_ram_base) ++#endif /* CONFIG_MMU */ + + #ifndef __ASSEMBLY__ + +@@ -95,11 +95,7 @@ typedef struct page *pgtable_t; + #define MIN_MEMBLOCK_ADDR 0 + #endif + +-#ifdef CONFIG_MMU + #define ARCH_PFN_OFFSET (PFN_DOWN((unsigned long)phys_ram_base)) +-#else +-#define ARCH_PFN_OFFSET (PAGE_OFFSET >> PAGE_SHIFT) +-#endif /* CONFIG_MMU */ + + struct kernel_mapping { + unsigned long page_offset; +diff --git a/arch/riscv/include/asm/pgtable.h b/arch/riscv/include/asm/pgtable.h +index 050fdc49b5ad7..eb7b25ef556ec 100644 +--- a/arch/riscv/include/asm/pgtable.h ++++ b/arch/riscv/include/asm/pgtable.h +@@ -12,7 +12,7 @@ + #include + + #ifndef CONFIG_MMU +-#define KERNEL_LINK_ADDR PAGE_OFFSET ++#define KERNEL_LINK_ADDR _AC(CONFIG_PAGE_OFFSET, UL) + #define KERN_VIRT_SIZE (UL(-1)) + #else + +-- +2.39.5 + diff --git a/queue-6.14/riscv-call-secondary-mmu-notifier-when-flushing-the-.patch b/queue-6.14/riscv-call-secondary-mmu-notifier-when-flushing-the-.patch new file mode 100644 index 0000000000..5eb944c61c --- /dev/null +++ b/queue-6.14/riscv-call-secondary-mmu-notifier-when-flushing-the-.patch @@ -0,0 +1,140 @@ +From fccd8283797d4dd02c472d4bbe8c82fae4b1c405 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 13 Jan 2025 15:24:24 +0100 +Subject: riscv: Call secondary mmu notifier when flushing the tlb +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Alexandre Ghiti + +[ Upstream commit d9be2b9b60497a82aeceec3a98d8b37fdd2960f2 ] + +This is required to allow the IOMMU driver to correctly flush its own +TLB. + +Reviewed-by: Clément Léger +Reviewed-by: Samuel Holland +Link: https://lore.kernel.org/r/20250113142424.30487-1-alexghiti@rivosinc.com +Signed-off-by: Alexandre Ghiti +Signed-off-by: Sasha Levin +--- + arch/riscv/mm/tlbflush.c | 37 ++++++++++++++++++++++--------------- + 1 file changed, 22 insertions(+), 15 deletions(-) + +diff --git a/arch/riscv/mm/tlbflush.c b/arch/riscv/mm/tlbflush.c +index 9b6e86ce38674..bb77607c87aa2 100644 +--- a/arch/riscv/mm/tlbflush.c ++++ b/arch/riscv/mm/tlbflush.c +@@ -4,6 +4,7 @@ + #include + #include + #include ++#include + #include + #include + +@@ -78,10 +79,17 @@ static void __ipi_flush_tlb_range_asid(void *info) + local_flush_tlb_range_asid(d->start, d->size, d->stride, d->asid); + } + +-static void __flush_tlb_range(const struct cpumask *cmask, unsigned long asid, ++static inline unsigned long get_mm_asid(struct mm_struct *mm) ++{ ++ return mm ? cntx2asid(atomic_long_read(&mm->context.id)) : FLUSH_TLB_NO_ASID; ++} ++ ++static void __flush_tlb_range(struct mm_struct *mm, ++ const struct cpumask *cmask, + unsigned long start, unsigned long size, + unsigned long stride) + { ++ unsigned long asid = get_mm_asid(mm); + unsigned int cpu; + + if (cpumask_empty(cmask)) +@@ -105,30 +113,26 @@ static void __flush_tlb_range(const struct cpumask *cmask, unsigned long asid, + } + + put_cpu(); +-} + +-static inline unsigned long get_mm_asid(struct mm_struct *mm) +-{ +- return cntx2asid(atomic_long_read(&mm->context.id)); ++ if (mm) ++ mmu_notifier_arch_invalidate_secondary_tlbs(mm, start, start + size); + } + + void flush_tlb_mm(struct mm_struct *mm) + { +- __flush_tlb_range(mm_cpumask(mm), get_mm_asid(mm), +- 0, FLUSH_TLB_MAX_SIZE, PAGE_SIZE); ++ __flush_tlb_range(mm, mm_cpumask(mm), 0, FLUSH_TLB_MAX_SIZE, PAGE_SIZE); + } + + void flush_tlb_mm_range(struct mm_struct *mm, + unsigned long start, unsigned long end, + unsigned int page_size) + { +- __flush_tlb_range(mm_cpumask(mm), get_mm_asid(mm), +- start, end - start, page_size); ++ __flush_tlb_range(mm, mm_cpumask(mm), start, end - start, page_size); + } + + void flush_tlb_page(struct vm_area_struct *vma, unsigned long addr) + { +- __flush_tlb_range(mm_cpumask(vma->vm_mm), get_mm_asid(vma->vm_mm), ++ __flush_tlb_range(vma->vm_mm, mm_cpumask(vma->vm_mm), + addr, PAGE_SIZE, PAGE_SIZE); + } + +@@ -161,13 +165,13 @@ void flush_tlb_range(struct vm_area_struct *vma, unsigned long start, + } + } + +- __flush_tlb_range(mm_cpumask(vma->vm_mm), get_mm_asid(vma->vm_mm), ++ __flush_tlb_range(vma->vm_mm, mm_cpumask(vma->vm_mm), + start, end - start, stride_size); + } + + void flush_tlb_kernel_range(unsigned long start, unsigned long end) + { +- __flush_tlb_range(cpu_online_mask, FLUSH_TLB_NO_ASID, ++ __flush_tlb_range(NULL, cpu_online_mask, + start, end - start, PAGE_SIZE); + } + +@@ -175,7 +179,7 @@ void flush_tlb_kernel_range(unsigned long start, unsigned long end) + void flush_pmd_tlb_range(struct vm_area_struct *vma, unsigned long start, + unsigned long end) + { +- __flush_tlb_range(mm_cpumask(vma->vm_mm), get_mm_asid(vma->vm_mm), ++ __flush_tlb_range(vma->vm_mm, mm_cpumask(vma->vm_mm), + start, end - start, PMD_SIZE); + } + #endif +@@ -189,7 +193,10 @@ void arch_tlbbatch_add_pending(struct arch_tlbflush_unmap_batch *batch, + struct mm_struct *mm, + unsigned long uaddr) + { ++ unsigned long start = uaddr & PAGE_MASK; ++ + cpumask_or(&batch->cpumask, &batch->cpumask, mm_cpumask(mm)); ++ mmu_notifier_arch_invalidate_secondary_tlbs(mm, start, start + PAGE_SIZE); + } + + void arch_flush_tlb_batched_pending(struct mm_struct *mm) +@@ -199,7 +206,7 @@ void arch_flush_tlb_batched_pending(struct mm_struct *mm) + + void arch_tlbbatch_flush(struct arch_tlbflush_unmap_batch *batch) + { +- __flush_tlb_range(&batch->cpumask, FLUSH_TLB_NO_ASID, 0, +- FLUSH_TLB_MAX_SIZE, PAGE_SIZE); ++ __flush_tlb_range(NULL, &batch->cpumask, ++ 0, FLUSH_TLB_MAX_SIZE, PAGE_SIZE); + cpumask_clear(&batch->cpumask); + } +-- +2.39.5 + diff --git a/queue-6.14/rseq-fix-segfault-on-registration-when-rseq_cs-is-no.patch b/queue-6.14/rseq-fix-segfault-on-registration-when-rseq_cs-is-no.patch new file mode 100644 index 0000000000..0f3b08a2ac --- /dev/null +++ b/queue-6.14/rseq-fix-segfault-on-registration-when-rseq_cs-is-no.patch @@ -0,0 +1,161 @@ +From 51d343033e69cdff34b7480312c2954d1f23ee99 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Mar 2025 16:12:21 -0500 +Subject: rseq: Fix segfault on registration when rseq_cs is non-zero + +From: Michael Jeanson + +[ Upstream commit fd881d0a085fc54354414aed990ccf05f282ba53 ] + +The rseq_cs field is documented as being set to 0 by user-space prior to +registration, however this is not currently enforced by the kernel. This +can result in a segfault on return to user-space if the value stored in +the rseq_cs field doesn't point to a valid struct rseq_cs. + +The correct solution to this would be to fail the rseq registration when +the rseq_cs field is non-zero. However, some older versions of glibc +will reuse the rseq area of previous threads without clearing the +rseq_cs field and will also terminate the process if the rseq +registration fails in a secondary thread. This wasn't caught in testing +because in this case the leftover rseq_cs does point to a valid struct +rseq_cs. + +What we can do is clear the rseq_cs field on registration when it's +non-zero which will prevent segfaults on registration and won't break +the glibc versions that reuse rseq areas on thread creation. + +Signed-off-by: Michael Jeanson +Signed-off-by: Ingo Molnar +Reviewed-by: Mathieu Desnoyers +Cc: Peter Zijlstra +Cc: Linus Torvalds +Link: https://lore.kernel.org/r/20250306211223.109455-1-mjeanson@efficios.com +Signed-off-by: Sasha Levin +--- + kernel/rseq.c | 60 ++++++++++++++++++++++++++++++++++++++++----------- + 1 file changed, 48 insertions(+), 12 deletions(-) + +diff --git a/kernel/rseq.c b/kernel/rseq.c +index a7d81229eda04..b7a1ec327e811 100644 +--- a/kernel/rseq.c ++++ b/kernel/rseq.c +@@ -236,6 +236,29 @@ static int rseq_reset_rseq_cpu_node_id(struct task_struct *t) + return -EFAULT; + } + ++/* ++ * Get the user-space pointer value stored in the 'rseq_cs' field. ++ */ ++static int rseq_get_rseq_cs_ptr_val(struct rseq __user *rseq, u64 *rseq_cs) ++{ ++ if (!rseq_cs) ++ return -EFAULT; ++ ++#ifdef CONFIG_64BIT ++ if (get_user(*rseq_cs, &rseq->rseq_cs)) ++ return -EFAULT; ++#else ++ if (copy_from_user(rseq_cs, &rseq->rseq_cs, sizeof(*rseq_cs))) ++ return -EFAULT; ++#endif ++ ++ return 0; ++} ++ ++/* ++ * If the rseq_cs field of 'struct rseq' contains a valid pointer to ++ * user-space, copy 'struct rseq_cs' from user-space and validate its fields. ++ */ + static int rseq_get_rseq_cs(struct task_struct *t, struct rseq_cs *rseq_cs) + { + struct rseq_cs __user *urseq_cs; +@@ -244,17 +267,16 @@ static int rseq_get_rseq_cs(struct task_struct *t, struct rseq_cs *rseq_cs) + u32 sig; + int ret; + +-#ifdef CONFIG_64BIT +- if (get_user(ptr, &t->rseq->rseq_cs)) +- return -EFAULT; +-#else +- if (copy_from_user(&ptr, &t->rseq->rseq_cs, sizeof(ptr))) +- return -EFAULT; +-#endif ++ ret = rseq_get_rseq_cs_ptr_val(t->rseq, &ptr); ++ if (ret) ++ return ret; ++ ++ /* If the rseq_cs pointer is NULL, return a cleared struct rseq_cs. */ + if (!ptr) { + memset(rseq_cs, 0, sizeof(*rseq_cs)); + return 0; + } ++ /* Check that the pointer value fits in the user-space process space. */ + if (ptr >= TASK_SIZE) + return -EINVAL; + urseq_cs = (struct rseq_cs __user *)(unsigned long)ptr; +@@ -330,7 +352,7 @@ static int rseq_need_restart(struct task_struct *t, u32 cs_flags) + return !!event_mask; + } + +-static int clear_rseq_cs(struct task_struct *t) ++static int clear_rseq_cs(struct rseq __user *rseq) + { + /* + * The rseq_cs field is set to NULL on preemption or signal +@@ -341,9 +363,9 @@ static int clear_rseq_cs(struct task_struct *t) + * Set rseq_cs to NULL. + */ + #ifdef CONFIG_64BIT +- return put_user(0UL, &t->rseq->rseq_cs); ++ return put_user(0UL, &rseq->rseq_cs); + #else +- if (clear_user(&t->rseq->rseq_cs, sizeof(t->rseq->rseq_cs))) ++ if (clear_user(&rseq->rseq_cs, sizeof(rseq->rseq_cs))) + return -EFAULT; + return 0; + #endif +@@ -375,11 +397,11 @@ static int rseq_ip_fixup(struct pt_regs *regs) + * Clear the rseq_cs pointer and return. + */ + if (!in_rseq_cs(ip, &rseq_cs)) +- return clear_rseq_cs(t); ++ return clear_rseq_cs(t->rseq); + ret = rseq_need_restart(t, rseq_cs.flags); + if (ret <= 0) + return ret; +- ret = clear_rseq_cs(t); ++ ret = clear_rseq_cs(t->rseq); + if (ret) + return ret; + trace_rseq_ip_fixup(ip, rseq_cs.start_ip, rseq_cs.post_commit_offset, +@@ -453,6 +475,7 @@ SYSCALL_DEFINE4(rseq, struct rseq __user *, rseq, u32, rseq_len, + int, flags, u32, sig) + { + int ret; ++ u64 rseq_cs; + + if (flags & RSEQ_FLAG_UNREGISTER) { + if (flags & ~RSEQ_FLAG_UNREGISTER) +@@ -507,6 +530,19 @@ SYSCALL_DEFINE4(rseq, struct rseq __user *, rseq, u32, rseq_len, + return -EINVAL; + if (!access_ok(rseq, rseq_len)) + return -EFAULT; ++ ++ /* ++ * If the rseq_cs pointer is non-NULL on registration, clear it to ++ * avoid a potential segfault on return to user-space. The proper thing ++ * to do would have been to fail the registration but this would break ++ * older libcs that reuse the rseq area for new threads without ++ * clearing the fields. ++ */ ++ if (rseq_get_rseq_cs_ptr_val(rseq, &rseq_cs)) ++ return -EFAULT; ++ if (rseq_cs && clear_rseq_cs(rseq)) ++ return -EFAULT; ++ + #ifdef CONFIG_DEBUG_RSEQ + /* + * Initialize the in-kernel rseq fields copy for validation of +-- +2.39.5 + diff --git a/queue-6.14/rtc-ds1307-stop-disabling-alarms-on-probe.patch b/queue-6.14/rtc-ds1307-stop-disabling-alarms-on-probe.patch new file mode 100644 index 0000000000..95a0b60da6 --- /dev/null +++ b/queue-6.14/rtc-ds1307-stop-disabling-alarms-on-probe.patch @@ -0,0 +1,38 @@ +From 4920866c0e2669b07cac195255ce76a224c7c105 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 3 Mar 2025 23:37:44 +0100 +Subject: rtc: ds1307: stop disabling alarms on probe + +From: Alexandre Belloni + +[ Upstream commit dcec12617ee61beed928e889607bf37e145bf86b ] + +It is a bad practice to disable alarms on probe or remove as this will +prevent alarms across reboots. + +Link: https://lore.kernel.org/r/20250303223744.1135672-1-alexandre.belloni@bootlin.com +Signed-off-by: Alexandre Belloni +Signed-off-by: Sasha Levin +--- + drivers/rtc/rtc-ds1307.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c +index 872e0b679be48..5efbe69bf5ca8 100644 +--- a/drivers/rtc/rtc-ds1307.c ++++ b/drivers/rtc/rtc-ds1307.c +@@ -1807,10 +1807,8 @@ static int ds1307_probe(struct i2c_client *client) + * For some variants, be sure alarms can trigger when we're + * running on Vbackup (BBSQI/BBSQW) + */ +- if (want_irq || ds1307_can_wakeup_device) { ++ if (want_irq || ds1307_can_wakeup_device) + regs[0] |= DS1337_BIT_INTCN | chip->bbsqi_bit; +- regs[0] &= ~(DS1337_BIT_A2IE | DS1337_BIT_A1IE); +- } + + regmap_write(ds1307->regmap, DS1337_REG_CONTROL, + regs[0]); +-- +2.39.5 + diff --git a/queue-6.14/rtc-rv3032-fix-eerd-location.patch b/queue-6.14/rtc-rv3032-fix-eerd-location.patch new file mode 100644 index 0000000000..7689f08d2b --- /dev/null +++ b/queue-6.14/rtc-rv3032-fix-eerd-location.patch @@ -0,0 +1,34 @@ +From 3608956bb2054f168710482e04601310f4d90da6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Mar 2025 22:42:41 +0100 +Subject: rtc: rv3032: fix EERD location + +From: Alexandre Belloni + +[ Upstream commit b0f9cb4a0706b0356e84d67e48500b77b343debe ] + +EERD is bit 2 in CTRL1 + +Link: https://lore.kernel.org/r/20250306214243.1167692-1-alexandre.belloni@bootlin.com +Signed-off-by: Alexandre Belloni +Signed-off-by: Sasha Levin +--- + drivers/rtc/rtc-rv3032.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/rtc/rtc-rv3032.c b/drivers/rtc/rtc-rv3032.c +index 35b2e36b426a0..cb01038a2e27f 100644 +--- a/drivers/rtc/rtc-rv3032.c ++++ b/drivers/rtc/rtc-rv3032.c +@@ -69,7 +69,7 @@ + #define RV3032_CLKOUT2_FD_MSK GENMASK(6, 5) + #define RV3032_CLKOUT2_OS BIT(7) + +-#define RV3032_CTRL1_EERD BIT(3) ++#define RV3032_CTRL1_EERD BIT(2) + #define RV3032_CTRL1_WADA BIT(5) + + #define RV3032_CTRL2_STOP BIT(0) +-- +2.39.5 + diff --git a/queue-6.14/rtnetlink-lookup-device-in-target-netns-when-creatin.patch b/queue-6.14/rtnetlink-lookup-device-in-target-netns-when-creatin.patch new file mode 100644 index 0000000000..8758c3b269 --- /dev/null +++ b/queue-6.14/rtnetlink-lookup-device-in-target-netns-when-creatin.patch @@ -0,0 +1,63 @@ +From 529fbec7212ca6e2c639189fb16dabea4440f42a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 19 Feb 2025 20:50:27 +0800 +Subject: rtnetlink: Lookup device in target netns when creating link + +From: Xiao Liang + +[ Upstream commit ec061546c6cffbb8929495bba3953f0cc5e177fa ] + +When creating link, lookup for existing device in target net namespace +instead of current one. +For example, two links created by: + + # ip link add dummy1 type dummy + # ip link add netns ns1 dummy1 type dummy + +should have no conflict since they are in different namespaces. + +Signed-off-by: Xiao Liang +Reviewed-by: Kuniyuki Iwashima +Link: https://patch.msgid.link/20250219125039.18024-2-shaw.leon@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/core/rtnetlink.c | 10 ++++++++-- + 1 file changed, 8 insertions(+), 2 deletions(-) + +diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c +index 80e006940f51a..ab7041150f295 100644 +--- a/net/core/rtnetlink.c ++++ b/net/core/rtnetlink.c +@@ -3865,20 +3865,26 @@ static int __rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh, + { + struct nlattr ** const tb = tbs->tb; + struct net *net = sock_net(skb->sk); ++ struct net *device_net; + struct net_device *dev; + struct ifinfomsg *ifm; + bool link_specified; + ++ /* When creating, lookup for existing device in target net namespace */ ++ device_net = (nlh->nlmsg_flags & NLM_F_CREATE) && ++ (nlh->nlmsg_flags & NLM_F_EXCL) ? ++ tgt_net : net; ++ + ifm = nlmsg_data(nlh); + if (ifm->ifi_index > 0) { + link_specified = true; +- dev = __dev_get_by_index(net, ifm->ifi_index); ++ dev = __dev_get_by_index(device_net, ifm->ifi_index); + } else if (ifm->ifi_index < 0) { + NL_SET_ERR_MSG(extack, "ifindex can't be negative"); + return -EINVAL; + } else if (tb[IFLA_IFNAME] || tb[IFLA_ALT_IFNAME]) { + link_specified = true; +- dev = rtnl_dev_get(net, tb); ++ dev = rtnl_dev_get(device_net, tb); + } else { + link_specified = false; + dev = NULL; +-- +2.39.5 + diff --git a/queue-6.14/rust-faux-add-missing-parent-argument-to-registratio.patch b/queue-6.14/rust-faux-add-missing-parent-argument-to-registratio.patch new file mode 100644 index 0000000000..72f3de3bf5 --- /dev/null +++ b/queue-6.14/rust-faux-add-missing-parent-argument-to-registratio.patch @@ -0,0 +1,67 @@ +From 9a37f90cdd12a3ba078d2becf1555cc16205f694 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 27 Feb 2025 14:35:06 -0500 +Subject: rust/faux: Add missing parent argument to Registration::new() + +From: Lyude Paul + +[ Upstream commit 95cb0cb546c2892b7a31ff2fce6573f201a214b8 ] + +A little late in the review of the faux device interface, we added the +ability to specify a parent device when creating new faux devices - but +this never got ported over to the rust bindings. So, let's add the missing +argument now so we don't have to convert other users later down the line. + +Signed-off-by: Lyude Paul +Cc: Greg Kroah-Hartman +Link: https://lore.kernel.org/r/20250227193522.198344-1-lyude@redhat.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + rust/kernel/faux.rs | 13 +++++++++++-- + samples/rust/rust_driver_faux.rs | 2 +- + 2 files changed, 12 insertions(+), 3 deletions(-) + +diff --git a/rust/kernel/faux.rs b/rust/kernel/faux.rs +index 5acc0c02d451f..68f53edf05d70 100644 +--- a/rust/kernel/faux.rs ++++ b/rust/kernel/faux.rs +@@ -24,11 +24,20 @@ + + impl Registration { + /// Create and register a new faux device with the given name. +- pub fn new(name: &CStr) -> Result { ++ pub fn new(name: &CStr, parent: Option<&device::Device>) -> Result { + // SAFETY: + // - `name` is copied by this function into its own storage + // - `faux_ops` is safe to leave NULL according to the C API +- let dev = unsafe { bindings::faux_device_create(name.as_char_ptr(), null_mut(), null()) }; ++ // - `parent` can be either NULL or a pointer to a `struct device`, and `faux_device_create` ++ // will take a reference to `parent` using `device_add` - ensuring that it remains valid ++ // for the lifetime of the faux device. ++ let dev = unsafe { ++ bindings::faux_device_create( ++ name.as_char_ptr(), ++ parent.map_or(null_mut(), |p| p.as_raw()), ++ null(), ++ ) ++ }; + + // The above function will return either a valid device, or NULL on failure + // INVARIANT: The device will remain registered until faux_device_destroy() is called, which +diff --git a/samples/rust/rust_driver_faux.rs b/samples/rust/rust_driver_faux.rs +index 048c6cb98b29a..58a3a94121bff 100644 +--- a/samples/rust/rust_driver_faux.rs ++++ b/samples/rust/rust_driver_faux.rs +@@ -20,7 +20,7 @@ impl Module for SampleModule { + fn init(_module: &'static ThisModule) -> Result { + pr_info!("Initialising Rust Faux Device Sample\n"); + +- let reg = faux::Registration::new(c_str!("rust-faux-sample-device"))?; ++ let reg = faux::Registration::new(c_str!("rust-faux-sample-device"), None)?; + + dev_info!(reg.as_ref(), "Hello from faux device!\n"); + +-- +2.39.5 + diff --git a/queue-6.14/s390-crash-use-note-name-macros.patch b/queue-6.14/s390-crash-use-note-name-macros.patch new file mode 100644 index 0000000000..e7310cd5bb --- /dev/null +++ b/queue-6.14/s390-crash-use-note-name-macros.patch @@ -0,0 +1,141 @@ +From 76eb1508bbf45ef15ff2ffdce7a82c1f0ccb1621 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 15 Jan 2025 14:48:02 +0900 +Subject: s390/crash: Use note name macros + +From: Akihiko Odaki + +[ Upstream commit d4a760fb77fdac07efa3da4fa4a18f49f178d048 ] + +Use note name macros to match with the userspace's expectation. + +Signed-off-by: Akihiko Odaki +Acked-by: Heiko Carstens +Reviewed-by: Dave Martin +Link: https://lore.kernel.org/r/20250115-elf-v5-5-0f9e55bbb2fc@daynix.com +Signed-off-by: Kees Cook +Signed-off-by: Sasha Levin +--- + arch/s390/kernel/crash_dump.c | 62 +++++++++++++---------------------- + 1 file changed, 23 insertions(+), 39 deletions(-) + +diff --git a/arch/s390/kernel/crash_dump.c b/arch/s390/kernel/crash_dump.c +index 276cb4c1e11be..4a981266b4833 100644 +--- a/arch/s390/kernel/crash_dump.c ++++ b/arch/s390/kernel/crash_dump.c +@@ -246,15 +246,6 @@ bool is_kdump_kernel(void) + } + EXPORT_SYMBOL_GPL(is_kdump_kernel); + +-static const char *nt_name(Elf64_Word type) +-{ +- const char *name = "LINUX"; +- +- if (type == NT_PRPSINFO || type == NT_PRSTATUS || type == NT_PRFPREG) +- name = KEXEC_CORE_NOTE_NAME; +- return name; +-} +- + /* + * Initialize ELF note + */ +@@ -279,10 +270,8 @@ static void *nt_init_name(void *buf, Elf64_Word type, void *desc, int d_len, + return PTR_ADD(buf, len); + } + +-static inline void *nt_init(void *buf, Elf64_Word type, void *desc, int d_len) +-{ +- return nt_init_name(buf, type, desc, d_len, nt_name(type)); +-} ++#define nt_init(buf, type, desc) \ ++ nt_init_name(buf, NT_ ## type, &(desc), sizeof(desc), NN_ ## type) + + /* + * Calculate the size of ELF note +@@ -298,10 +287,7 @@ static size_t nt_size_name(int d_len, const char *name) + return size; + } + +-static inline size_t nt_size(Elf64_Word type, int d_len) +-{ +- return nt_size_name(d_len, nt_name(type)); +-} ++#define nt_size(type, desc) nt_size_name(sizeof(desc), NN_ ## type) + + /* + * Fill ELF notes for one CPU with save area registers +@@ -322,18 +308,16 @@ static void *fill_cpu_elf_notes(void *ptr, int cpu, struct save_area *sa) + memcpy(&nt_fpregset.fpc, &sa->fpc, sizeof(sa->fpc)); + memcpy(&nt_fpregset.fprs, &sa->fprs, sizeof(sa->fprs)); + /* Create ELF notes for the CPU */ +- ptr = nt_init(ptr, NT_PRSTATUS, &nt_prstatus, sizeof(nt_prstatus)); +- ptr = nt_init(ptr, NT_PRFPREG, &nt_fpregset, sizeof(nt_fpregset)); +- ptr = nt_init(ptr, NT_S390_TIMER, &sa->timer, sizeof(sa->timer)); +- ptr = nt_init(ptr, NT_S390_TODCMP, &sa->todcmp, sizeof(sa->todcmp)); +- ptr = nt_init(ptr, NT_S390_TODPREG, &sa->todpreg, sizeof(sa->todpreg)); +- ptr = nt_init(ptr, NT_S390_CTRS, &sa->ctrs, sizeof(sa->ctrs)); +- ptr = nt_init(ptr, NT_S390_PREFIX, &sa->prefix, sizeof(sa->prefix)); ++ ptr = nt_init(ptr, PRSTATUS, nt_prstatus); ++ ptr = nt_init(ptr, PRFPREG, nt_fpregset); ++ ptr = nt_init(ptr, S390_TIMER, sa->timer); ++ ptr = nt_init(ptr, S390_TODCMP, sa->todcmp); ++ ptr = nt_init(ptr, S390_TODPREG, sa->todpreg); ++ ptr = nt_init(ptr, S390_CTRS, sa->ctrs); ++ ptr = nt_init(ptr, S390_PREFIX, sa->prefix); + if (cpu_has_vx()) { +- ptr = nt_init(ptr, NT_S390_VXRS_HIGH, +- &sa->vxrs_high, sizeof(sa->vxrs_high)); +- ptr = nt_init(ptr, NT_S390_VXRS_LOW, +- &sa->vxrs_low, sizeof(sa->vxrs_low)); ++ ptr = nt_init(ptr, S390_VXRS_HIGH, sa->vxrs_high); ++ ptr = nt_init(ptr, S390_VXRS_LOW, sa->vxrs_low); + } + return ptr; + } +@@ -346,16 +330,16 @@ static size_t get_cpu_elf_notes_size(void) + struct save_area *sa = NULL; + size_t size; + +- size = nt_size(NT_PRSTATUS, sizeof(struct elf_prstatus)); +- size += nt_size(NT_PRFPREG, sizeof(elf_fpregset_t)); +- size += nt_size(NT_S390_TIMER, sizeof(sa->timer)); +- size += nt_size(NT_S390_TODCMP, sizeof(sa->todcmp)); +- size += nt_size(NT_S390_TODPREG, sizeof(sa->todpreg)); +- size += nt_size(NT_S390_CTRS, sizeof(sa->ctrs)); +- size += nt_size(NT_S390_PREFIX, sizeof(sa->prefix)); ++ size = nt_size(PRSTATUS, struct elf_prstatus); ++ size += nt_size(PRFPREG, elf_fpregset_t); ++ size += nt_size(S390_TIMER, sa->timer); ++ size += nt_size(S390_TODCMP, sa->todcmp); ++ size += nt_size(S390_TODPREG, sa->todpreg); ++ size += nt_size(S390_CTRS, sa->ctrs); ++ size += nt_size(S390_PREFIX, sa->prefix); + if (cpu_has_vx()) { +- size += nt_size(NT_S390_VXRS_HIGH, sizeof(sa->vxrs_high)); +- size += nt_size(NT_S390_VXRS_LOW, sizeof(sa->vxrs_low)); ++ size += nt_size(S390_VXRS_HIGH, sa->vxrs_high); ++ size += nt_size(S390_VXRS_LOW, sa->vxrs_low); + } + + return size; +@@ -371,7 +355,7 @@ static void *nt_prpsinfo(void *ptr) + memset(&prpsinfo, 0, sizeof(prpsinfo)); + prpsinfo.pr_sname = 'R'; + strcpy(prpsinfo.pr_fname, "vmlinux"); +- return nt_init(ptr, NT_PRPSINFO, &prpsinfo, sizeof(prpsinfo)); ++ return nt_init(ptr, PRPSINFO, prpsinfo); + } + + /* +@@ -610,7 +594,7 @@ static size_t get_elfcorehdr_size(int phdr_count) + /* PT_NOTES */ + size += sizeof(Elf64_Phdr); + /* nt_prpsinfo */ +- size += nt_size(NT_PRPSINFO, sizeof(struct elf_prpsinfo)); ++ size += nt_size(PRPSINFO, struct elf_prpsinfo); + /* regsets */ + size += get_cpu_cnt() * get_cpu_elf_notes_size(); + /* nt_vmcoreinfo */ +-- +2.39.5 + diff --git a/queue-6.14/s390-tlb-use-mm_has_pgste-instead-of-mm_alloc_pgste.patch b/queue-6.14/s390-tlb-use-mm_has_pgste-instead-of-mm_alloc_pgste.patch new file mode 100644 index 0000000000..24a83730b9 --- /dev/null +++ b/queue-6.14/s390-tlb-use-mm_has_pgste-instead-of-mm_alloc_pgste.patch @@ -0,0 +1,39 @@ +From 6a1a4501ddab653b5244471ad692dfcaa653a77e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 10 Mar 2025 12:42:59 +0100 +Subject: s390/tlb: Use mm_has_pgste() instead of mm_alloc_pgste() + +From: Heiko Carstens + +[ Upstream commit 9291ea091b29bb3e37c4b3416c7c1e49e472c7d5 ] + +An mm has pgstes only after s390_enable_sie() has been called, while +mm_alloc_pgste() may be always true (e.g. via sysctl setting). + +Limit the calls to gmap_unlink() in pte_free_tlb() to those cases +where there might be something to unlink. + +Reviewed-by: Alexander Gordeev +Signed-off-by: Heiko Carstens +Signed-off-by: Vasily Gorbik +Signed-off-by: Sasha Levin +--- + arch/s390/include/asm/tlb.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/s390/include/asm/tlb.h b/arch/s390/include/asm/tlb.h +index 72655fd2d867c..f20601995bb0e 100644 +--- a/arch/s390/include/asm/tlb.h ++++ b/arch/s390/include/asm/tlb.h +@@ -84,7 +84,7 @@ static inline void pte_free_tlb(struct mmu_gather *tlb, pgtable_t pte, + tlb->mm->context.flush_mm = 1; + tlb->freed_tables = 1; + tlb->cleared_pmds = 1; +- if (mm_alloc_pgste(tlb->mm)) ++ if (mm_has_pgste(tlb->mm)) + gmap_unlink(tlb->mm, (unsigned long *)pte, address); + tlb_remove_ptdesc(tlb, virt_to_ptdesc(pte)); + } +-- +2.39.5 + diff --git a/queue-6.14/s390-vfio-ap-fix-no-ap-queue-sharing-allowed-message.patch b/queue-6.14/s390-vfio-ap-fix-no-ap-queue-sharing-allowed-message.patch new file mode 100644 index 0000000000..2e00fe3981 --- /dev/null +++ b/queue-6.14/s390-vfio-ap-fix-no-ap-queue-sharing-allowed-message.patch @@ -0,0 +1,192 @@ +From 216a6bda4ef0108cd928704691075d5c0dea6807 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 11 Mar 2025 06:32:57 -0400 +Subject: s390/vfio-ap: Fix no AP queue sharing allowed message written to + kernel log + +From: Anthony Krowiak + +[ Upstream commit d33d729afcc8ad2148d99f9bc499b33fd0c0d73b ] + +An erroneous message is written to the kernel log when either of the +following actions are taken by a user: + +1. Assign an adapter or domain to a vfio_ap mediated device via its sysfs + assign_adapter or assign_domain attributes that would result in one or + more AP queues being assigned that are already assigned to a different + mediated device. Sharing of queues between mdevs is not allowed. + +2. Reserve an adapter or domain for the host device driver via the AP bus + driver's sysfs apmask or aqmask attribute that would result in providing + host access to an AP queue that is in use by a vfio_ap mediated device. + Reserving a queue for a host driver that is in use by an mdev is not + allowed. + +In both cases, the assignment will return an error; however, a message like +the following is written to the kernel log: + +vfio_ap_mdev e1839397-51a0-4e3c-91e0-c3b9c3d3047d: Userspace may not +re-assign queue 00.0028 already assigned to \ +e1839397-51a0-4e3c-91e0-c3b9c3d3047d + +Notice the mdev reporting the error is the same as the mdev identified +in the message as the one to which the queue is being assigned. +It is perfectly okay to assign a queue to an mdev to which it is +already assigned; the assignment is simply ignored by the vfio_ap device +driver. + +This patch logs more descriptive and accurate messages for both 1 and 2 +above to the kernel log: + +Example for 1: +vfio_ap_mdev 0fe903a0-a323-44db-9daf-134c68627d61: Userspace may not assign +queue 00.0033 to mdev: already assigned to \ +62177883-f1bb-47f0-914d-32a22e3a8804 + +Example for 2: +vfio_ap_mdev 62177883-f1bb-47f0-914d-32a22e3a8804: Can not reserve queue +00.0033 for host driver: in use by mdev + +Signed-off-by: Anthony Krowiak +Link: https://lore.kernel.org/r/20250311103304.1539188-1-akrowiak@linux.ibm.com +Signed-off-by: Heiko Carstens +Signed-off-by: Vasily Gorbik +Signed-off-by: Sasha Levin +--- + drivers/s390/crypto/vfio_ap_ops.c | 72 ++++++++++++++++++++----------- + 1 file changed, 46 insertions(+), 26 deletions(-) + +diff --git a/drivers/s390/crypto/vfio_ap_ops.c b/drivers/s390/crypto/vfio_ap_ops.c +index a52c2690933fd..a6a0628979555 100644 +--- a/drivers/s390/crypto/vfio_ap_ops.c ++++ b/drivers/s390/crypto/vfio_ap_ops.c +@@ -863,48 +863,66 @@ static void vfio_ap_mdev_remove(struct mdev_device *mdev) + vfio_put_device(&matrix_mdev->vdev); + } + +-#define MDEV_SHARING_ERR "Userspace may not re-assign queue %02lx.%04lx " \ +- "already assigned to %s" ++#define MDEV_SHARING_ERR "Userspace may not assign queue %02lx.%04lx to mdev: already assigned to %s" + +-static void vfio_ap_mdev_log_sharing_err(struct ap_matrix_mdev *matrix_mdev, +- unsigned long *apm, +- unsigned long *aqm) ++#define MDEV_IN_USE_ERR "Can not reserve queue %02lx.%04lx for host driver: in use by mdev" ++ ++static void vfio_ap_mdev_log_sharing_err(struct ap_matrix_mdev *assignee, ++ struct ap_matrix_mdev *assigned_to, ++ unsigned long *apm, unsigned long *aqm) + { + unsigned long apid, apqi; +- const struct device *dev = mdev_dev(matrix_mdev->mdev); +- const char *mdev_name = dev_name(dev); + +- for_each_set_bit_inv(apid, apm, AP_DEVICES) ++ for_each_set_bit_inv(apid, apm, AP_DEVICES) { ++ for_each_set_bit_inv(apqi, aqm, AP_DOMAINS) { ++ dev_warn(mdev_dev(assignee->mdev), MDEV_SHARING_ERR, ++ apid, apqi, dev_name(mdev_dev(assigned_to->mdev))); ++ } ++ } ++} ++ ++static void vfio_ap_mdev_log_in_use_err(struct ap_matrix_mdev *assignee, ++ unsigned long *apm, unsigned long *aqm) ++{ ++ unsigned long apid, apqi; ++ ++ for_each_set_bit_inv(apid, apm, AP_DEVICES) { + for_each_set_bit_inv(apqi, aqm, AP_DOMAINS) +- dev_warn(dev, MDEV_SHARING_ERR, apid, apqi, mdev_name); ++ dev_warn(mdev_dev(assignee->mdev), MDEV_IN_USE_ERR, apid, apqi); ++ } + } + + /** + * vfio_ap_mdev_verify_no_sharing - verify APQNs are not shared by matrix mdevs + * ++ * @assignee: the matrix mdev to which @mdev_apm and @mdev_aqm are being ++ * assigned; or, NULL if this function was called by the AP bus ++ * driver in_use callback to verify none of the APQNs being reserved ++ * for the host device driver are in use by a vfio_ap mediated device + * @mdev_apm: mask indicating the APIDs of the APQNs to be verified + * @mdev_aqm: mask indicating the APQIs of the APQNs to be verified + * +- * Verifies that each APQN derived from the Cartesian product of a bitmap of +- * AP adapter IDs and AP queue indexes is not configured for any matrix +- * mediated device. AP queue sharing is not allowed. ++ * Verifies that each APQN derived from the Cartesian product of APIDs ++ * represented by the bits set in @mdev_apm and the APQIs of the bits set in ++ * @mdev_aqm is not assigned to a mediated device other than the mdev to which ++ * the APQN is being assigned (@assignee). AP queue sharing is not allowed. + * + * Return: 0 if the APQNs are not shared; otherwise return -EADDRINUSE. + */ +-static int vfio_ap_mdev_verify_no_sharing(unsigned long *mdev_apm, ++static int vfio_ap_mdev_verify_no_sharing(struct ap_matrix_mdev *assignee, ++ unsigned long *mdev_apm, + unsigned long *mdev_aqm) + { +- struct ap_matrix_mdev *matrix_mdev; ++ struct ap_matrix_mdev *assigned_to; + DECLARE_BITMAP(apm, AP_DEVICES); + DECLARE_BITMAP(aqm, AP_DOMAINS); + +- list_for_each_entry(matrix_mdev, &matrix_dev->mdev_list, node) { ++ list_for_each_entry(assigned_to, &matrix_dev->mdev_list, node) { + /* +- * If the input apm and aqm are fields of the matrix_mdev +- * object, then move on to the next matrix_mdev. ++ * If the mdev to which the mdev_apm and mdev_aqm is being ++ * assigned is the same as the mdev being verified + */ +- if (mdev_apm == matrix_mdev->matrix.apm && +- mdev_aqm == matrix_mdev->matrix.aqm) ++ if (assignee == assigned_to) + continue; + + memset(apm, 0, sizeof(apm)); +@@ -914,15 +932,16 @@ static int vfio_ap_mdev_verify_no_sharing(unsigned long *mdev_apm, + * We work on full longs, as we can only exclude the leftover + * bits in non-inverse order. The leftover is all zeros. + */ +- if (!bitmap_and(apm, mdev_apm, matrix_mdev->matrix.apm, +- AP_DEVICES)) ++ if (!bitmap_and(apm, mdev_apm, assigned_to->matrix.apm, AP_DEVICES)) + continue; + +- if (!bitmap_and(aqm, mdev_aqm, matrix_mdev->matrix.aqm, +- AP_DOMAINS)) ++ if (!bitmap_and(aqm, mdev_aqm, assigned_to->matrix.aqm, AP_DOMAINS)) + continue; + +- vfio_ap_mdev_log_sharing_err(matrix_mdev, apm, aqm); ++ if (assignee) ++ vfio_ap_mdev_log_sharing_err(assignee, assigned_to, apm, aqm); ++ else ++ vfio_ap_mdev_log_in_use_err(assigned_to, apm, aqm); + + return -EADDRINUSE; + } +@@ -951,7 +970,8 @@ static int vfio_ap_mdev_validate_masks(struct ap_matrix_mdev *matrix_mdev) + matrix_mdev->matrix.aqm)) + return -EADDRNOTAVAIL; + +- return vfio_ap_mdev_verify_no_sharing(matrix_mdev->matrix.apm, ++ return vfio_ap_mdev_verify_no_sharing(matrix_mdev, ++ matrix_mdev->matrix.apm, + matrix_mdev->matrix.aqm); + } + +@@ -2458,7 +2478,7 @@ int vfio_ap_mdev_resource_in_use(unsigned long *apm, unsigned long *aqm) + + mutex_lock(&matrix_dev->guests_lock); + mutex_lock(&matrix_dev->mdevs_lock); +- ret = vfio_ap_mdev_verify_no_sharing(apm, aqm); ++ ret = vfio_ap_mdev_verify_no_sharing(NULL, apm, aqm); + mutex_unlock(&matrix_dev->mdevs_lock); + mutex_unlock(&matrix_dev->guests_lock); + +-- +2.39.5 + diff --git a/queue-6.14/samples-bpf-fix-compilation-failure-for-samples-bpf-.patch b/queue-6.14/samples-bpf-fix-compilation-failure-for-samples-bpf-.patch new file mode 100644 index 0000000000..23b7deda0f --- /dev/null +++ b/queue-6.14/samples-bpf-fix-compilation-failure-for-samples-bpf-.patch @@ -0,0 +1,59 @@ +From 2491dbed04d3b86d6d1058feb5a9361798da4a99 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 25 Apr 2025 17:50:42 +0800 +Subject: samples/bpf: Fix compilation failure for samples/bpf on LoongArch + Fedora + +From: Haoran Jiang + +[ Upstream commit 548762f05d19c5542db7590bcdfb9be1fb928376 ] + +When building the latest samples/bpf on LoongArch Fedora + + make M=samples/bpf + +There are compilation errors as follows: + +In file included from ./linux/samples/bpf/sockex2_kern.c:2: +In file included from ./include/uapi/linux/in.h:25: +In file included from ./include/linux/socket.h:8: +In file included from ./include/linux/uio.h:9: +In file included from ./include/linux/thread_info.h:60: +In file included from ./arch/loongarch/include/asm/thread_info.h:15: +In file included from ./arch/loongarch/include/asm/processor.h:13: +In file included from ./arch/loongarch/include/asm/cpu-info.h:11: +./arch/loongarch/include/asm/loongarch.h:13:10: fatal error: 'larchintrin.h' file not found + ^~~~~~~~~~~~~~~ +1 error generated. + +larchintrin.h is included in /usr/lib64/clang/14.0.6/include, +and the header file location is specified at compile time. + +Test on LoongArch Fedora: +https://github.com/fedora-remix-loongarch/releases-info + +Signed-off-by: Haoran Jiang +Signed-off-by: zhangxi +Signed-off-by: Andrii Nakryiko +Link: https://lore.kernel.org/bpf/20250425095042.838824-1-jianghaoran@kylinos.cn +Signed-off-by: Sasha Levin +--- + samples/bpf/Makefile | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/samples/bpf/Makefile b/samples/bpf/Makefile +index 5b632635e00dd..95a4fa1f1e447 100644 +--- a/samples/bpf/Makefile ++++ b/samples/bpf/Makefile +@@ -376,7 +376,7 @@ $(obj)/%.o: $(src)/%.c + @echo " CLANG-bpf " $@ + $(Q)$(CLANG) $(NOSTDINC_FLAGS) $(LINUXINCLUDE) $(BPF_EXTRA_CFLAGS) \ + -I$(obj) -I$(srctree)/tools/testing/selftests/bpf/ \ +- -I$(LIBBPF_INCLUDE) \ ++ -I$(LIBBPF_INCLUDE) $(CLANG_SYS_INCLUDES) \ + -D__KERNEL__ -D__BPF_TRACING__ -Wno-unused-value -Wno-pointer-sign \ + -D__TARGET_ARCH_$(SRCARCH) -Wno-compare-distinct-pointer-types \ + -Wno-gnu-variable-sized-type-not-at-end \ +-- +2.39.5 + diff --git a/queue-6.14/sched-reduce-the-default-slice-to-avoid-tasks-gettin.patch b/queue-6.14/sched-reduce-the-default-slice-to-avoid-tasks-gettin.patch new file mode 100644 index 0000000000..9fb33793ac --- /dev/null +++ b/queue-6.14/sched-reduce-the-default-slice-to-avoid-tasks-gettin.patch @@ -0,0 +1,80 @@ +From 5ae1a1e66028187aab4714efafe78ab24acb2fcb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 8 Feb 2025 15:53:23 +0800 +Subject: sched: Reduce the default slice to avoid tasks getting an extra tick + +From: zihan zhou <15645113830zzh@gmail.com> + +[ Upstream commit 2ae891b826958b60919ea21c727f77bcd6ffcc2c ] + +The old default value for slice is 0.75 msec * (1 + ilog(ncpus)) which +means that we have a default slice of: + + 0.75 for 1 cpu + 1.50 up to 3 cpus + 2.25 up to 7 cpus + 3.00 for 8 cpus and above. + +For HZ=250 and HZ=100, because of the tick accuracy, the runtime of +tasks is far higher than their slice. + +For HZ=1000 with 8 cpus or more, the accuracy of tick is already +satisfactory, but there is still an issue that tasks will get an extra +tick because the tick often arrives a little faster than expected. In +this case, the task can only wait until the next tick to consider that it +has reached its deadline, and will run 1ms longer. + +vruntime + sysctl_sched_base_slice = deadline + |-----------|-----------|-----------|-----------| + 1ms 1ms 1ms 1ms + ^ ^ ^ ^ + tick1 tick2 tick3 tick4(nearly 4ms) + +There are two reasons for tick error: clockevent precision and the +CONFIG_IRQ_TIME_ACCOUNTING/CONFIG_PARAVIRT_TIME_ACCOUNTING. with +CONFIG_IRQ_TIME_ACCOUNTING every tick will be less than 1ms, but even +without it, because of clockevent precision, tick still often less than +1ms. + +In order to make scheduling more precise, we changed 0.75 to 0.70, +Using 0.70 instead of 0.75 should not change much for other configs +and would fix this issue: + + 0.70 for 1 cpu + 1.40 up to 3 cpus + 2.10 up to 7 cpus + 2.8 for 8 cpus and above. + +This does not guarantee that tasks can run the slice time accurately +every time, but occasionally running an extra tick has little impact. + +Signed-off-by: zihan zhou <15645113830zzh@gmail.com> +Signed-off-by: Peter Zijlstra (Intel) +Reviewed-by: Vincent Guittot +Link: https://lkml.kernel.org/r/20250208075322.13139-1-15645113830zzh@gmail.com +Signed-off-by: Sasha Levin +--- + kernel/sched/fair.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c +index 3d9b68a347b76..eb11650160f7e 100644 +--- a/kernel/sched/fair.c ++++ b/kernel/sched/fair.c +@@ -74,10 +74,10 @@ unsigned int sysctl_sched_tunable_scaling = SCHED_TUNABLESCALING_LOG; + /* + * Minimal preemption granularity for CPU-bound tasks: + * +- * (default: 0.75 msec * (1 + ilog(ncpus)), units: nanoseconds) ++ * (default: 0.70 msec * (1 + ilog(ncpus)), units: nanoseconds) + */ +-unsigned int sysctl_sched_base_slice = 750000ULL; +-static unsigned int normalized_sysctl_sched_base_slice = 750000ULL; ++unsigned int sysctl_sched_base_slice = 700000ULL; ++static unsigned int normalized_sysctl_sched_base_slice = 700000ULL; + + const_debug unsigned int sysctl_sched_migration_cost = 500000UL; + +-- +2.39.5 + diff --git a/queue-6.14/scsi-logging-fix-scsi_logging_level-bounds.patch b/queue-6.14/scsi-logging-fix-scsi_logging_level-bounds.patch new file mode 100644 index 0000000000..6a5752f4fe --- /dev/null +++ b/queue-6.14/scsi-logging-fix-scsi_logging_level-bounds.patch @@ -0,0 +1,41 @@ +From 6a10f607c820e875f42f27508980d00da533e5b2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 24 Feb 2025 10:58:19 +0100 +Subject: scsi: logging: Fix scsi_logging_level bounds + +From: Nicolas Bouchinet + +[ Upstream commit 2cef5b4472c602e6c5a119aca869d9d4050586f3 ] + +Bound scsi_logging_level sysctl writings between SYSCTL_ZERO and +SYSCTL_INT_MAX. + +The proc_handler has thus been updated to proc_dointvec_minmax. + +Signed-off-by: Nicolas Bouchinet +Link: https://lore.kernel.org/r/20250224095826.16458-5-nicolas.bouchinet@clip-os.org +Reviewed-by: Joel Granados +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + drivers/scsi/scsi_sysctl.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/scsi/scsi_sysctl.c b/drivers/scsi/scsi_sysctl.c +index be4aef0f4f996..055a03a83ad68 100644 +--- a/drivers/scsi/scsi_sysctl.c ++++ b/drivers/scsi/scsi_sysctl.c +@@ -17,7 +17,9 @@ static const struct ctl_table scsi_table[] = { + .data = &scsi_logging_level, + .maxlen = sizeof(scsi_logging_level), + .mode = 0644, +- .proc_handler = proc_dointvec }, ++ .proc_handler = proc_dointvec_minmax, ++ .extra1 = SYSCTL_ZERO, ++ .extra2 = SYSCTL_INT_MAX }, + }; + + static struct ctl_table_header *scsi_table_header; +-- +2.39.5 + diff --git a/queue-6.14/scsi-lpfc-free-phba-irq-in-lpfc_sli4_enable_msi-when.patch b/queue-6.14/scsi-lpfc-free-phba-irq-in-lpfc_sli4_enable_msi-when.patch new file mode 100644 index 0000000000..e7b2037f61 --- /dev/null +++ b/queue-6.14/scsi-lpfc-free-phba-irq-in-lpfc_sli4_enable_msi-when.patch @@ -0,0 +1,47 @@ +From 67f7fcd9a8b70dfc4fd496133ac03411b5a33776 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 30 Jan 2025 16:05:20 -0800 +Subject: scsi: lpfc: Free phba irq in lpfc_sli4_enable_msi() when + pci_irq_vector() fails + +From: Justin Tee + +[ Upstream commit f0842902b383982d1f72c490996aa8fc29a7aa0d ] + +Fix smatch warning regarding missed calls to free_irq(). Free the phba IRQ +in the failed pci_irq_vector cases. + +lpfc_init.c: lpfc_sli4_enable_msi() warn: 'phba->pcidev->irq' from + request_irq() not released. + +Signed-off-by: Justin Tee +Link: https://lore.kernel.org/r/20250131000524.163662-3-justintee8345@gmail.com +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + drivers/scsi/lpfc/lpfc_init.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c +index bcadf11414c8a..411a6b927c5b0 100644 +--- a/drivers/scsi/lpfc/lpfc_init.c ++++ b/drivers/scsi/lpfc/lpfc_init.c +@@ -13170,6 +13170,7 @@ lpfc_sli4_enable_msi(struct lpfc_hba *phba) + eqhdl = lpfc_get_eq_hdl(0); + rc = pci_irq_vector(phba->pcidev, 0); + if (rc < 0) { ++ free_irq(phba->pcidev->irq, phba); + pci_free_irq_vectors(phba->pcidev); + lpfc_printf_log(phba, KERN_WARNING, LOG_INIT, + "0496 MSI pci_irq_vec failed (%d)\n", rc); +@@ -13250,6 +13251,7 @@ lpfc_sli4_enable_intr(struct lpfc_hba *phba, uint32_t cfg_mode) + eqhdl = lpfc_get_eq_hdl(0); + retval = pci_irq_vector(phba->pcidev, 0); + if (retval < 0) { ++ free_irq(phba->pcidev->irq, phba); + lpfc_printf_log(phba, KERN_WARNING, LOG_INIT, + "0502 INTR pci_irq_vec failed (%d)\n", + retval); +-- +2.39.5 + diff --git a/queue-6.14/scsi-lpfc-handle-duplicate-d_ids-in-ndlp-search-by-d.patch b/queue-6.14/scsi-lpfc-handle-duplicate-d_ids-in-ndlp-search-by-d.patch new file mode 100644 index 0000000000..7181211b61 --- /dev/null +++ b/queue-6.14/scsi-lpfc-handle-duplicate-d_ids-in-ndlp-search-by-d.patch @@ -0,0 +1,66 @@ +From 2bcd181d84cafa22b641905255f78dc209074903 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 30 Jan 2025 16:05:22 -0800 +Subject: scsi: lpfc: Handle duplicate D_IDs in ndlp search-by D_ID routine + +From: Justin Tee + +[ Upstream commit 56c3d809b7b450379162d0b8a70bbe71ab8db706 ] + +After a port swap between separate fabrics, there may be multiple nodes in +the vport's fc_nodes list with the same fabric well known address. +Duplication is temporary and eventually resolves itself after dev_loss_tmo +expires, but nameserver queries may still occur before dev_loss_tmo. This +possibly results in returning stale fabric ndlp objects. Fix by adding an +nlp_state check to ensure the ndlp search routine returns the correct newer +allocated ndlp fabric object. + +Signed-off-by: Justin Tee +Link: https://lore.kernel.org/r/20250131000524.163662-5-justintee8345@gmail.com +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + drivers/scsi/lpfc/lpfc_hbadisc.c | 17 ++++++++++++----- + 1 file changed, 12 insertions(+), 5 deletions(-) + +diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c +index 36e66df36a18c..45d268d49060e 100644 +--- a/drivers/scsi/lpfc/lpfc_hbadisc.c ++++ b/drivers/scsi/lpfc/lpfc_hbadisc.c +@@ -5564,6 +5564,7 @@ static struct lpfc_nodelist * + __lpfc_findnode_did(struct lpfc_vport *vport, uint32_t did) + { + struct lpfc_nodelist *ndlp; ++ struct lpfc_nodelist *np = NULL; + uint32_t data1; + + list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) { +@@ -5578,14 +5579,20 @@ __lpfc_findnode_did(struct lpfc_vport *vport, uint32_t did) + ndlp, ndlp->nlp_DID, + ndlp->nlp_flag, data1, ndlp->nlp_rpi, + ndlp->active_rrqs_xri_bitmap); +- return ndlp; ++ ++ /* Check for new or potentially stale node */ ++ if (ndlp->nlp_state != NLP_STE_UNUSED_NODE) ++ return ndlp; ++ np = ndlp; + } + } + +- /* FIND node did NOT FOUND */ +- lpfc_printf_vlog(vport, KERN_INFO, LOG_NODE, +- "0932 FIND node did x%x NOT FOUND.\n", did); +- return NULL; ++ if (!np) ++ /* FIND node did NOT FOUND */ ++ lpfc_printf_vlog(vport, KERN_INFO, LOG_NODE, ++ "0932 FIND node did x%x NOT FOUND.\n", did); ++ ++ return np; + } + + struct lpfc_nodelist * +-- +2.39.5 + diff --git a/queue-6.14/scsi-lpfc-ignore-ndlp-rport-mismatch-in-dev_loss_tmo.patch b/queue-6.14/scsi-lpfc-ignore-ndlp-rport-mismatch-in-dev_loss_tmo.patch new file mode 100644 index 0000000000..a10f66dcc0 --- /dev/null +++ b/queue-6.14/scsi-lpfc-ignore-ndlp-rport-mismatch-in-dev_loss_tmo.patch @@ -0,0 +1,58 @@ +From 2549fb59f3fa1a96ae2c0538cf0c427ab6212e46 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 30 Jan 2025 16:05:21 -0800 +Subject: scsi: lpfc: Ignore ndlp rport mismatch in dev_loss_tmo callbk + +From: Justin Tee + +[ Upstream commit 23ed62897746f49f195d819ce6edeb1db27d1b72 ] + +With repeated port swaps between separate fabrics, there can be multiple +registrations for fabric well known address 0xfffffe. This can cause ndlp +reference confusion due to the usage of a single ndlp ptr that stores the +rport object in fc_rport struct private storage during transport +registration. Subsequent registrations update the ndlp->rport field with +the newer rport, so when transport layer triggers dev_loss_tmo for the +earlier registered rport the ndlp->rport private storage is referencing the +newer rport instead of the older rport in dev_loss_tmo callbk. + +Because the older ndlp->rport object is already cleaned up elsewhere in +driver code during the time of fabric swap, check that the rport provided +in dev_loss_tmo callbk actually matches the rport stored in the LLDD's +ndlp->rport field. Otherwise, skip dev_loss_tmo work on a stale rport. + +Signed-off-by: Justin Tee +Link: https://lore.kernel.org/r/20250131000524.163662-4-justintee8345@gmail.com +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + drivers/scsi/lpfc/lpfc_hbadisc.c | 12 +++++++++--- + 1 file changed, 9 insertions(+), 3 deletions(-) + +diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c +index 45d268d49060e..07cd611f34bd5 100644 +--- a/drivers/scsi/lpfc/lpfc_hbadisc.c ++++ b/drivers/scsi/lpfc/lpfc_hbadisc.c +@@ -228,10 +228,16 @@ lpfc_dev_loss_tmo_callbk(struct fc_rport *rport) + if (ndlp->nlp_state == NLP_STE_MAPPED_NODE) + return; + +- /* check for recovered fabric node */ +- if (ndlp->nlp_state == NLP_STE_UNMAPPED_NODE && +- ndlp->nlp_DID == Fabric_DID) ++ /* Ignore callback for a mismatched (stale) rport */ ++ if (ndlp->rport != rport) { ++ lpfc_vlog_msg(vport, KERN_WARNING, LOG_NODE, ++ "6788 fc rport mismatch: d_id x%06x ndlp x%px " ++ "fc rport x%px node rport x%px state x%x " ++ "refcnt %u\n", ++ ndlp->nlp_DID, ndlp, rport, ndlp->rport, ++ ndlp->nlp_state, kref_read(&ndlp->kref)); + return; ++ } + + if (rport->port_name != wwn_to_u64(ndlp->nlp_portname.u.wwn)) + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, +-- +2.39.5 + diff --git a/queue-6.14/scsi-lpfc-reduce-log-message-generation-during-els-r.patch b/queue-6.14/scsi-lpfc-reduce-log-message-generation-during-els-r.patch new file mode 100644 index 0000000000..4554ace721 --- /dev/null +++ b/queue-6.14/scsi-lpfc-reduce-log-message-generation-during-els-r.patch @@ -0,0 +1,52 @@ +From 2fbd2345b6beeb6341af27e44c9c16facb03665b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 30 Jan 2025 16:05:19 -0800 +Subject: scsi: lpfc: Reduce log message generation during ELS ring clean up + +From: Justin Tee + +[ Upstream commit 8eccc58d71eafbd2635077916b68fda15791d270 ] + +A clean up log message is output from lpfc_els_flush_cmd() for each +outstanding ELS I/O and repeated for every NPIV instance. The log message +should only be generated for active I/Os matching the NPIV vport. Thus, +move the vport check to before logging the message. + +Signed-off-by: Justin Tee +Link: https://lore.kernel.org/r/20250131000524.163662-2-justintee8345@gmail.com +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + drivers/scsi/lpfc/lpfc_els.c | 10 ++++------ + 1 file changed, 4 insertions(+), 6 deletions(-) + +diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c +index 1d7db49a8fe45..318dc83e9a2ac 100644 +--- a/drivers/scsi/lpfc/lpfc_els.c ++++ b/drivers/scsi/lpfc/lpfc_els.c +@@ -9569,18 +9569,16 @@ lpfc_els_flush_cmd(struct lpfc_vport *vport) + mbx_tmo_err = test_bit(MBX_TMO_ERR, &phba->bit_flags); + /* First we need to issue aborts to outstanding cmds on txcmpl */ + list_for_each_entry_safe(piocb, tmp_iocb, &pring->txcmplq, list) { ++ if (piocb->vport != vport) ++ continue; ++ + lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, + "2243 iotag = 0x%x cmd_flag = 0x%x " +- "ulp_command = 0x%x this_vport %x " +- "sli_flag = 0x%x\n", ++ "ulp_command = 0x%x sli_flag = 0x%x\n", + piocb->iotag, piocb->cmd_flag, + get_job_cmnd(phba, piocb), +- (piocb->vport == vport), + phba->sli.sli_flag); + +- if (piocb->vport != vport) +- continue; +- + if ((phba->sli.sli_flag & LPFC_SLI_ACTIVE) && !mbx_tmo_err) { + if (piocb->cmd_flag & LPFC_IO_LIBDFC) + continue; +-- +2.39.5 + diff --git a/queue-6.14/scsi-mpi3mr-add-level-check-to-control-event-logging.patch b/queue-6.14/scsi-mpi3mr-add-level-check-to-control-event-logging.patch new file mode 100644 index 0000000000..7095888bfb --- /dev/null +++ b/queue-6.14/scsi-mpi3mr-add-level-check-to-control-event-logging.patch @@ -0,0 +1,37 @@ +From 5ae8c0d6ebe01766916d09d55af7a2d32fd2a7a3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 15 Apr 2025 15:45:46 +0530 +Subject: scsi: mpi3mr: Add level check to control event logging + +From: Ranjan Kumar + +[ Upstream commit b0b7ee3b574a72283399b9232f6190be07f220c0 ] + +Ensure event logs are only generated when the debug logging level +MPI3_DEBUG_EVENT is enabled. This prevents unnecessary logging. + +Signed-off-by: Ranjan Kumar +Link: https://lore.kernel.org/r/20250415101546.204018-1-ranjan.kumar@broadcom.com +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + drivers/scsi/mpi3mr/mpi3mr_fw.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/scsi/mpi3mr/mpi3mr_fw.c b/drivers/scsi/mpi3mr/mpi3mr_fw.c +index c0a372868e1d7..f6d3db3fd0d8e 100644 +--- a/drivers/scsi/mpi3mr/mpi3mr_fw.c ++++ b/drivers/scsi/mpi3mr/mpi3mr_fw.c +@@ -174,6 +174,9 @@ static void mpi3mr_print_event_data(struct mpi3mr_ioc *mrioc, + char *desc = NULL; + u16 event; + ++ if (!(mrioc->logging_level & MPI3_DEBUG_EVENT)) ++ return; ++ + event = event_reply->event; + + switch (event) { +-- +2.39.5 + diff --git a/queue-6.14/scsi-mpi3mr-update-timestamp-only-for-supervisor-ioc.patch b/queue-6.14/scsi-mpi3mr-update-timestamp-only-for-supervisor-ioc.patch new file mode 100644 index 0000000000..3374145fb8 --- /dev/null +++ b/queue-6.14/scsi-mpi3mr-update-timestamp-only-for-supervisor-ioc.patch @@ -0,0 +1,44 @@ +From b8e2cf1cb565e0fbf937e451afe72f80cdb9bffd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 20 Feb 2025 19:55:26 +0530 +Subject: scsi: mpi3mr: Update timestamp only for supervisor IOCs + +From: Ranjan Kumar + +[ Upstream commit 83a9d30d29f275571f6e8f879f04b2379be7eb6c ] + +The driver issues the time stamp update command periodically. Even if the +command fails with supervisor only IOC Status. + +Instead check the Non-Supervisor capability bit reported by IOC as part of +IOC Facts. + +Co-developed-by: Sumit Saxena +Signed-off-by: Sumit Saxena +Signed-off-by: Ranjan Kumar +Link: https://lore.kernel.org/r/20250220142528.20837-3-ranjan.kumar@broadcom.com +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + drivers/scsi/mpi3mr/mpi3mr_fw.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/drivers/scsi/mpi3mr/mpi3mr_fw.c b/drivers/scsi/mpi3mr/mpi3mr_fw.c +index f6d3db3fd0d8e..604f37e5c0c35 100644 +--- a/drivers/scsi/mpi3mr/mpi3mr_fw.c ++++ b/drivers/scsi/mpi3mr/mpi3mr_fw.c +@@ -2747,7 +2747,10 @@ static void mpi3mr_watchdog_work(struct work_struct *work) + return; + } + +- if (mrioc->ts_update_counter++ >= mrioc->ts_update_interval) { ++ if (!(mrioc->facts.ioc_capabilities & ++ MPI3_IOCFACTS_CAPABILITY_NON_SUPERVISOR_IOC) && ++ (mrioc->ts_update_counter++ >= mrioc->ts_update_interval)) { ++ + mrioc->ts_update_counter = 0; + mpi3mr_sync_timestamp(mrioc); + } +-- +2.39.5 + diff --git a/queue-6.14/scsi-mpt3sas-send-a-diag-reset-if-target-reset-fails.patch b/queue-6.14/scsi-mpt3sas-send-a-diag-reset-if-target-reset-fails.patch new file mode 100644 index 0000000000..5fd558d9e2 --- /dev/null +++ b/queue-6.14/scsi-mpt3sas-send-a-diag-reset-if-target-reset-fails.patch @@ -0,0 +1,64 @@ +From c89f00af24aebf4184eebc1d71310dead3ad35cc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 12 Feb 2025 17:26:55 -0800 +Subject: scsi: mpt3sas: Send a diag reset if target reset fails + +From: Shivasharan S + +[ Upstream commit 5612d6d51ed2634a033c95de2edec7449409cbb9 ] + +When an IOCTL times out and driver issues a target reset, if firmware +fails the task management elevate the recovery by issuing a diag reset to +controller. + +Signed-off-by: Shivasharan S +Link: https://lore.kernel.org/r/1739410016-27503-5-git-send-email-shivasharan.srikanteshwara@broadcom.com +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + drivers/scsi/mpt3sas/mpt3sas_ctl.c | 12 ++++++++++-- + 1 file changed, 10 insertions(+), 2 deletions(-) + +diff --git a/drivers/scsi/mpt3sas/mpt3sas_ctl.c b/drivers/scsi/mpt3sas/mpt3sas_ctl.c +index 87784c96249a7..47faa27bc3559 100644 +--- a/drivers/scsi/mpt3sas/mpt3sas_ctl.c ++++ b/drivers/scsi/mpt3sas/mpt3sas_ctl.c +@@ -679,6 +679,7 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg, + size_t data_in_sz = 0; + long ret; + u16 device_handle = MPT3SAS_INVALID_DEVICE_HANDLE; ++ int tm_ret; + + issue_reset = 0; + +@@ -1120,18 +1121,25 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg, + if (pcie_device && (!ioc->tm_custom_handling) && + (!(mpt3sas_scsih_is_pcie_scsi_device( + pcie_device->device_info)))) +- mpt3sas_scsih_issue_locked_tm(ioc, ++ tm_ret = mpt3sas_scsih_issue_locked_tm(ioc, + le16_to_cpu(mpi_request->FunctionDependent1), + 0, 0, 0, + MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET, 0, + 0, pcie_device->reset_timeout, + MPI26_SCSITASKMGMT_MSGFLAGS_PROTOCOL_LVL_RST_PCIE); + else +- mpt3sas_scsih_issue_locked_tm(ioc, ++ tm_ret = mpt3sas_scsih_issue_locked_tm(ioc, + le16_to_cpu(mpi_request->FunctionDependent1), + 0, 0, 0, + MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET, 0, + 0, 30, MPI2_SCSITASKMGMT_MSGFLAGS_LINK_RESET); ++ ++ if (tm_ret != SUCCESS) { ++ ioc_info(ioc, ++ "target reset failed, issue hard reset: handle (0x%04x)\n", ++ le16_to_cpu(mpi_request->FunctionDependent1)); ++ mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER); ++ } + } else + mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER); + } +-- +2.39.5 + diff --git a/queue-6.14/scsi-scsi_debug-first-fixes-for-tapes.patch b/queue-6.14/scsi-scsi_debug-first-fixes-for-tapes.patch new file mode 100644 index 0000000000..97ac31cf46 --- /dev/null +++ b/queue-6.14/scsi-scsi_debug-first-fixes-for-tapes.patch @@ -0,0 +1,165 @@ +From 792bfc8af9675067316f5d4e6562c1774e577f0f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 13 Feb 2025 11:26:30 +0200 +Subject: scsi: scsi_debug: First fixes for tapes +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Kai Mäkisara + +[ Upstream commit f69da85d5d5cc5b7dfb963a6c6c1ac0dd9002341 ] + +Patch includes the following: + + - Enable MODE SENSE/SELECT without actual page (to read/write only the + Block Descriptor) + + - Store the density code and block size in the Block Descriptor (only + short version for tapes) + + - Fix REWIND not to use the wrong page filling function + +Signed-off-by: Kai Mäkisara +Link: https://lore.kernel.org/r/20250213092636.2510-2-Kai.Makisara@kolumbus.fi +Reviewed-by: John Meneghini +Tested-by: John Meneghini +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + drivers/scsi/scsi_debug.c | 55 ++++++++++++++++++++++++++++++++++----- + 1 file changed, 49 insertions(+), 6 deletions(-) + +diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c +index 5ceaa4665e5df..4da0c259390b5 100644 +--- a/drivers/scsi/scsi_debug.c ++++ b/drivers/scsi/scsi_debug.c +@@ -173,6 +173,10 @@ static const char *sdebug_version_date = "20210520"; + #define DEF_ZBC_MAX_OPEN_ZONES 8 + #define DEF_ZBC_NR_CONV_ZONES 1 + ++/* Default parameters for tape drives */ ++#define TAPE_DEF_DENSITY 0x0 ++#define TAPE_DEF_BLKSIZE 0 ++ + #define SDEBUG_LUN_0_VAL 0 + + /* bit mask values for sdebug_opts */ +@@ -363,6 +367,10 @@ struct sdebug_dev_info { + ktime_t create_ts; /* time since bootup that this device was created */ + struct sdeb_zone_state *zstate; + ++ /* For tapes */ ++ unsigned int tape_blksize; ++ unsigned int tape_density; ++ + struct dentry *debugfs_entry; + struct spinlock list_lock; + struct list_head inject_err_list; +@@ -773,7 +781,7 @@ static const struct opcode_info_t opcode_info_arr[SDEB_I_LAST_ELEM_P1 + 1] = { + /* 20 */ + {0, 0x1e, 0, 0, NULL, NULL, /* ALLOW REMOVAL */ + {6, 0, 0, 0, 0x3, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +- {0, 0x1, 0, 0, resp_start_stop, NULL, /* REWIND ?? */ ++ {0, 0x1, 0, 0, NULL, NULL, /* REWIND ?? */ + {6, 0x1, 0, 0, 0, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, + {0, 0, 0, F_INV_OP | FF_RESPOND, NULL, NULL, /* ATA_PT */ + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, +@@ -2742,7 +2750,7 @@ static int resp_mode_sense(struct scsi_cmnd *scp, + unsigned char *ap; + unsigned char *arr __free(kfree); + unsigned char *cmd = scp->cmnd; +- bool dbd, llbaa, msense_6, is_disk, is_zbc; ++ bool dbd, llbaa, msense_6, is_disk, is_zbc, is_tape; + + arr = kzalloc(SDEBUG_MAX_MSENSE_SZ, GFP_ATOMIC); + if (!arr) +@@ -2755,7 +2763,8 @@ static int resp_mode_sense(struct scsi_cmnd *scp, + llbaa = msense_6 ? false : !!(cmd[1] & 0x10); + is_disk = (sdebug_ptype == TYPE_DISK); + is_zbc = devip->zoned; +- if ((is_disk || is_zbc) && !dbd) ++ is_tape = (sdebug_ptype == TYPE_TAPE); ++ if ((is_disk || is_zbc || is_tape) && !dbd) + bd_len = llbaa ? 16 : 8; + else + bd_len = 0; +@@ -2793,15 +2802,25 @@ static int resp_mode_sense(struct scsi_cmnd *scp, + put_unaligned_be32(0xffffffff, ap + 0); + else + put_unaligned_be32(sdebug_capacity, ap + 0); +- put_unaligned_be16(sdebug_sector_size, ap + 6); ++ if (is_tape) { ++ ap[0] = devip->tape_density; ++ put_unaligned_be16(devip->tape_blksize, ap + 6); ++ } else ++ put_unaligned_be16(sdebug_sector_size, ap + 6); + offset += bd_len; + ap = arr + offset; + } else if (16 == bd_len) { ++ if (is_tape) { ++ mk_sense_invalid_fld(scp, SDEB_IN_DATA, 1, 4); ++ return check_condition_result; ++ } + put_unaligned_be64((u64)sdebug_capacity, ap + 0); + put_unaligned_be32(sdebug_sector_size, ap + 12); + offset += bd_len; + ap = arr + offset; + } ++ if (cmd[2] == 0) ++ goto only_bd; /* Only block descriptor requested */ + + /* + * N.B. If len>0 before resp_*_pg() call, then form of that call should be: +@@ -2902,6 +2921,7 @@ static int resp_mode_sense(struct scsi_cmnd *scp, + default: + goto bad_pcode; + } ++only_bd: + if (msense_6) + arr[0] = offset - 1; + else +@@ -2945,8 +2965,27 @@ static int resp_mode_select(struct scsi_cmnd *scp, + __func__, param_len, res); + md_len = mselect6 ? (arr[0] + 1) : (get_unaligned_be16(arr + 0) + 2); + bd_len = mselect6 ? arr[3] : get_unaligned_be16(arr + 6); +- off = bd_len + (mselect6 ? 4 : 8); +- if (md_len > 2 || off >= res) { ++ off = (mselect6 ? 4 : 8); ++ if (sdebug_ptype == TYPE_TAPE) { ++ int blksize; ++ ++ if (bd_len != 8) { ++ mk_sense_invalid_fld(scp, SDEB_IN_DATA, ++ mselect6 ? 3 : 6, -1); ++ return check_condition_result; ++ } ++ blksize = get_unaligned_be16(arr + off + 6); ++ if ((blksize % 4) != 0) { ++ mk_sense_invalid_fld(scp, SDEB_IN_DATA, off + 6, -1); ++ return check_condition_result; ++ } ++ devip->tape_density = arr[off]; ++ devip->tape_blksize = blksize; ++ } ++ off += bd_len; ++ if (off >= res) ++ return 0; /* No page written, just descriptors */ ++ if (md_len > 2) { + mk_sense_invalid_fld(scp, SDEB_IN_DATA, 0, -1); + return check_condition_result; + } +@@ -5835,6 +5874,10 @@ static struct sdebug_dev_info *sdebug_device_create( + } else { + devip->zoned = false; + } ++ if (sdebug_ptype == TYPE_TAPE) { ++ devip->tape_density = TAPE_DEF_DENSITY; ++ devip->tape_blksize = TAPE_DEF_BLKSIZE; ++ } + devip->create_ts = ktime_get_boottime(); + atomic_set(&devip->stopped, (sdeb_tur_ms_to_ready > 0 ? 2 : 0)); + spin_lock_init(&devip->list_lock); +-- +2.39.5 + diff --git a/queue-6.14/scsi-st-erase-does-not-change-tape-location.patch b/queue-6.14/scsi-st-erase-does-not-change-tape-location.patch new file mode 100644 index 0000000000..c7a82b163b --- /dev/null +++ b/queue-6.14/scsi-st-erase-does-not-change-tape-location.patch @@ -0,0 +1,38 @@ +From 9e2bf56c01ffcf4aea4a9e620ee9b0e59625ff52 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 11 Mar 2025 13:25:15 +0200 +Subject: scsi: st: ERASE does not change tape location +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Kai Mäkisara + +[ Upstream commit ad77cebf97bd42c93ab4e3bffd09f2b905c1959a ] + +The SCSI ERASE command erases from the current position onwards. Don't +clear the position variables. + +Signed-off-by: Kai Mäkisara +Link: https://lore.kernel.org/r/20250311112516.5548-3-Kai.Makisara@kolumbus.fi +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + drivers/scsi/st.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c +index 2a18ba51427ac..4add423f2f415 100644 +--- a/drivers/scsi/st.c ++++ b/drivers/scsi/st.c +@@ -2897,7 +2897,6 @@ static int st_int_ioctl(struct scsi_tape *STp, unsigned int cmd_in, unsigned lon + timeout = STp->long_timeout * 8; + + DEBC_printk(STp, "Erasing tape.\n"); +- fileno = blkno = at_sm = 0; + break; + case MTSETBLK: /* Set block length */ + case MTSETDENSITY: /* Set tape density */ +-- +2.39.5 + diff --git a/queue-6.14/scsi-st-restore-some-drive-settings-after-reset.patch b/queue-6.14/scsi-st-restore-some-drive-settings-after-reset.patch new file mode 100644 index 0000000000..c278ba0014 --- /dev/null +++ b/queue-6.14/scsi-st-restore-some-drive-settings-after-reset.patch @@ -0,0 +1,113 @@ +From afa12d7a9be5c878ad8b1f5c381d1296977f0e20 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 20 Jan 2025 21:49:22 +0200 +Subject: scsi: st: Restore some drive settings after reset +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Kai Mäkisara + +[ Upstream commit 7081dc75df79696d8322d01821c28e53416c932c ] + +Some of the allowed operations put the tape into a known position to +continue operation assuming only the tape position has changed. But reset +sets partition, density and block size to drive default values. These +should be restored to the values before reset. + +Normally the current block size and density are stored by the drive. If +the settings have been changed, the changed values have to be saved by the +driver across reset. + +Signed-off-by: Kai Mäkisara +Link: https://lore.kernel.org/r/20250120194925.44432-2-Kai.Makisara@kolumbus.fi +Reviewed-by: John Meneghini +Tested-by: John Meneghini +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + drivers/scsi/st.c | 24 +++++++++++++++++++++--- + drivers/scsi/st.h | 2 ++ + 2 files changed, 23 insertions(+), 3 deletions(-) + +diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c +index 4add423f2f415..7dec7958344ea 100644 +--- a/drivers/scsi/st.c ++++ b/drivers/scsi/st.c +@@ -952,7 +952,6 @@ static void reset_state(struct scsi_tape *STp) + STp->partition = find_partition(STp); + if (STp->partition < 0) + STp->partition = 0; +- STp->new_partition = STp->partition; + } + } + +@@ -2929,14 +2928,17 @@ static int st_int_ioctl(struct scsi_tape *STp, unsigned int cmd_in, unsigned lon + if (cmd_in == MTSETDENSITY) { + (STp->buffer)->b_data[4] = arg; + STp->density_changed = 1; /* At least we tried ;-) */ ++ STp->changed_density = arg; + } else if (cmd_in == SET_DENS_AND_BLK) + (STp->buffer)->b_data[4] = arg >> 24; + else + (STp->buffer)->b_data[4] = STp->density; + if (cmd_in == MTSETBLK || cmd_in == SET_DENS_AND_BLK) { + ltmp = arg & MT_ST_BLKSIZE_MASK; +- if (cmd_in == MTSETBLK) ++ if (cmd_in == MTSETBLK) { + STp->blksize_changed = 1; /* At least we tried ;-) */ ++ STp->changed_blksize = arg; ++ } + } else + ltmp = STp->block_size; + (STp->buffer)->b_data[9] = (ltmp >> 16); +@@ -3637,9 +3639,25 @@ static long st_ioctl(struct file *file, unsigned int cmd_in, unsigned long arg) + retval = (-EIO); + goto out; + } +- reset_state(STp); ++ reset_state(STp); /* Clears pos_unknown */ + /* remove this when the midlevel properly clears was_reset */ + STp->device->was_reset = 0; ++ ++ /* Fix the device settings after reset, ignore errors */ ++ if (mtc.mt_op == MTREW || mtc.mt_op == MTSEEK || ++ mtc.mt_op == MTEOM) { ++ if (STp->can_partitions) { ++ /* STp->new_partition contains the ++ * latest partition set ++ */ ++ STp->partition = 0; ++ switch_partition(STp); ++ } ++ if (STp->density_changed) ++ st_int_ioctl(STp, MTSETDENSITY, STp->changed_density); ++ if (STp->blksize_changed) ++ st_int_ioctl(STp, MTSETBLK, STp->changed_blksize); ++ } + } + + if (mtc.mt_op != MTNOP && mtc.mt_op != MTSETBLK && +diff --git a/drivers/scsi/st.h b/drivers/scsi/st.h +index 1aaaf5369a40f..6d31b894ee84c 100644 +--- a/drivers/scsi/st.h ++++ b/drivers/scsi/st.h +@@ -165,6 +165,7 @@ struct scsi_tape { + unsigned char compression_changed; + unsigned char drv_buffer; + unsigned char density; ++ unsigned char changed_density; + unsigned char door_locked; + unsigned char autorew_dev; /* auto-rewind device */ + unsigned char rew_at_close; /* rewind necessary at close */ +@@ -172,6 +173,7 @@ struct scsi_tape { + unsigned char cleaning_req; /* cleaning requested? */ + unsigned char first_tur; /* first TEST UNIT READY */ + int block_size; ++ int changed_blksize; + int min_block; + int max_block; + int recover_count; /* From tape opening */ +-- +2.39.5 + diff --git a/queue-6.14/scsi-st-tighten-the-page-format-heuristics-with-mode.patch b/queue-6.14/scsi-st-tighten-the-page-format-heuristics-with-mode.patch new file mode 100644 index 0000000000..d18f78e596 --- /dev/null +++ b/queue-6.14/scsi-st-tighten-the-page-format-heuristics-with-mode.patch @@ -0,0 +1,47 @@ +From f9cb5b2d9b2cc32d88e24f2fcf6e3c7a383bf2c1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 11 Mar 2025 13:25:16 +0200 +Subject: scsi: st: Tighten the page format heuristics with MODE SELECT +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Kai Mäkisara + +[ Upstream commit 8db816c6f176321e42254badd5c1a8df8bfcfdb4 ] + +In the days when SCSI-2 was emerging, some drives did claim SCSI-2 but did +not correctly implement it. The st driver first tries MODE SELECT with the +page format bit set to set the block descriptor. If not successful, the +non-page format is tried. + +The test only tests the sense code and this triggers also from illegal +parameter in the parameter list. The test is limited to "old" devices and +made more strict to remove false alarms. + +Signed-off-by: Kai Mäkisara +Link: https://lore.kernel.org/r/20250311112516.5548-4-Kai.Makisara@kolumbus.fi +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + drivers/scsi/st.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c +index 344e4da336bb5..2a18ba51427ac 100644 +--- a/drivers/scsi/st.c ++++ b/drivers/scsi/st.c +@@ -3084,7 +3084,9 @@ static int st_int_ioctl(struct scsi_tape *STp, unsigned int cmd_in, unsigned lon + cmd_in == MTSETDRVBUFFER || + cmd_in == SET_DENS_AND_BLK) { + if (cmdstatp->sense_hdr.sense_key == ILLEGAL_REQUEST && +- !(STp->use_pf & PF_TESTED)) { ++ cmdstatp->sense_hdr.asc == 0x24 && ++ (STp->device)->scsi_level <= SCSI_2 && ++ !(STp->use_pf & PF_TESTED)) { + /* Try the other possible state of Page Format if not + already tried */ + STp->use_pf = (STp->use_pf ^ USE_PF) | PF_TESTED; +-- +2.39.5 + diff --git a/queue-6.14/scsi-target-iscsi-fix-timeout-on-deleted-connection.patch b/queue-6.14/scsi-target-iscsi-fix-timeout-on-deleted-connection.patch new file mode 100644 index 0000000000..e902766d5e --- /dev/null +++ b/queue-6.14/scsi-target-iscsi-fix-timeout-on-deleted-connection.patch @@ -0,0 +1,57 @@ +From 09752586d5163ed29291e775c06725c464775578 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 24 Dec 2024 13:17:57 +0300 +Subject: scsi: target: iscsi: Fix timeout on deleted connection + +From: Dmitry Bogdanov + +[ Upstream commit 7f533cc5ee4c4436cee51dc58e81dfd9c3384418 ] + +NOPIN response timer may expire on a deleted connection and crash with +such logs: + +Did not receive response to NOPIN on CID: 0, failing connection for I_T Nexus (null),i,0x00023d000125,iqn.2017-01.com.iscsi.target,t,0x3d + +BUG: Kernel NULL pointer dereference on read at 0x00000000 +NIP strlcpy+0x8/0xb0 +LR iscsit_fill_cxn_timeout_err_stats+0x5c/0xc0 [iscsi_target_mod] +Call Trace: + iscsit_handle_nopin_response_timeout+0xfc/0x120 [iscsi_target_mod] + call_timer_fn+0x58/0x1f0 + run_timer_softirq+0x740/0x860 + __do_softirq+0x16c/0x420 + irq_exit+0x188/0x1c0 + timer_interrupt+0x184/0x410 + +That is because nopin response timer may be re-started on nopin timer +expiration. + +Stop nopin timer before stopping the nopin response timer to be sure +that no one of them will be re-started. + +Signed-off-by: Dmitry Bogdanov +Link: https://lore.kernel.org/r/20241224101757.32300-1-d.bogdanov@yadro.com +Reviewed-by: Maurizio Lombardi +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + drivers/target/iscsi/iscsi_target.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c +index 1244ef3aa86c1..620ba6e0ab075 100644 +--- a/drivers/target/iscsi/iscsi_target.c ++++ b/drivers/target/iscsi/iscsi_target.c +@@ -4263,8 +4263,8 @@ int iscsit_close_connection( + spin_unlock(&iscsit_global->ts_bitmap_lock); + + iscsit_stop_timers_for_cmds(conn); +- iscsit_stop_nopin_response_timer(conn); + iscsit_stop_nopin_timer(conn); ++ iscsit_stop_nopin_response_timer(conn); + + if (conn->conn_transport->iscsit_wait_conn) + conn->conn_transport->iscsit_wait_conn(conn); +-- +2.39.5 + diff --git a/queue-6.14/scsi-target-spc-fix-loop-traversal-in-spc_rsoc_get_d.patch b/queue-6.14/scsi-target-spc-fix-loop-traversal-in-spc_rsoc_get_d.patch new file mode 100644 index 0000000000..66d740e276 --- /dev/null +++ b/queue-6.14/scsi-target-spc-fix-loop-traversal-in-spc_rsoc_get_d.patch @@ -0,0 +1,68 @@ +From 5a51a10eebb01733ae72da730437befe806910f0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 24 Jan 2025 16:55:42 +0800 +Subject: scsi: target: spc: Fix loop traversal in spc_rsoc_get_descr() + +From: Chaohai Chen + +[ Upstream commit 04ad06e41d1c74cc323b20a7bd023c47bd0e0c38 ] + +Stop traversing after finding the appropriate descriptor. + +Signed-off-by: Chaohai Chen +Link: https://lore.kernel.org/r/20250124085542.109088-1-wdhh66@163.com +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + drivers/target/target_core_spc.c | 14 ++++++++++---- + 1 file changed, 10 insertions(+), 4 deletions(-) + +diff --git a/drivers/target/target_core_spc.c b/drivers/target/target_core_spc.c +index 785a97536212b..0a02492bef701 100644 +--- a/drivers/target/target_core_spc.c ++++ b/drivers/target/target_core_spc.c +@@ -2151,8 +2151,10 @@ spc_rsoc_get_descr(struct se_cmd *cmd, struct target_opcode_descriptor **opcode) + if (descr->serv_action_valid) + return TCM_INVALID_CDB_FIELD; + +- if (!descr->enabled || descr->enabled(descr, cmd)) ++ if (!descr->enabled || descr->enabled(descr, cmd)) { + *opcode = descr; ++ return TCM_NO_SENSE; ++ } + break; + case 0x2: + /* +@@ -2166,8 +2168,10 @@ spc_rsoc_get_descr(struct se_cmd *cmd, struct target_opcode_descriptor **opcode) + if (descr->serv_action_valid && + descr->service_action == requested_sa) { + if (!descr->enabled || descr->enabled(descr, +- cmd)) ++ cmd)) { + *opcode = descr; ++ return TCM_NO_SENSE; ++ } + } else if (!descr->serv_action_valid) + return TCM_INVALID_CDB_FIELD; + break; +@@ -2180,13 +2184,15 @@ spc_rsoc_get_descr(struct se_cmd *cmd, struct target_opcode_descriptor **opcode) + */ + if (descr->service_action == requested_sa) + if (!descr->enabled || descr->enabled(descr, +- cmd)) ++ cmd)) { + *opcode = descr; ++ return TCM_NO_SENSE; ++ } + break; + } + } + +- return 0; ++ return TCM_NO_SENSE; + } + + static sense_reason_t +-- +2.39.5 + diff --git a/queue-6.14/scsi-ufs-introduce-quirk-to-extend-pa_hibern8time-fo.patch b/queue-6.14/scsi-ufs-introduce-quirk-to-extend-pa_hibern8time-fo.patch new file mode 100644 index 0000000000..ef9b297533 --- /dev/null +++ b/queue-6.14/scsi-ufs-introduce-quirk-to-extend-pa_hibern8time-fo.patch @@ -0,0 +1,101 @@ +From 41dc5afed7cce0c7edefd76200794dbec5314f1d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 11 Apr 2025 17:46:30 +0530 +Subject: scsi: ufs: Introduce quirk to extend PA_HIBERN8TIME for UFS devices +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Manish Pandey + +[ Upstream commit 569330a34a31a52c904239439984a59972c11d28 ] + +Samsung UFS devices require additional time in hibern8 mode before +exiting, beyond the negotiated handshaking phase between the host and +device. Introduce a quirk to increase the PA_HIBERN8TIME parameter by +100 µs, a value derived from experiments, to ensure a proper hibernation +process. + +Signed-off-by: Manish Pandey +Link: https://lore.kernel.org/r/20250411121630.21330-3-quic_mapa@quicinc.com +Reviewed-by: Bean Huo +Reviewed-by: Manivannan Sadhasivam +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + drivers/ufs/core/ufshcd.c | 29 +++++++++++++++++++++++++++++ + include/ufs/ufs_quirks.h | 6 ++++++ + 2 files changed, 35 insertions(+) + +diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c +index 99e7e4a570f0e..47ec4e4e4a2a0 100644 +--- a/drivers/ufs/core/ufshcd.c ++++ b/drivers/ufs/core/ufshcd.c +@@ -278,6 +278,7 @@ static const struct ufs_dev_quirk ufs_fixups[] = { + .model = UFS_ANY_MODEL, + .quirk = UFS_DEVICE_QUIRK_DELAY_BEFORE_LPM | + UFS_DEVICE_QUIRK_HOST_PA_TACTIVATE | ++ UFS_DEVICE_QUIRK_PA_HIBER8TIME | + UFS_DEVICE_QUIRK_RECOVERY_FROM_DL_NAC_ERRORS }, + { .wmanufacturerid = UFS_VENDOR_SKHYNIX, + .model = UFS_ANY_MODEL, +@@ -8384,6 +8385,31 @@ static int ufshcd_quirk_tune_host_pa_tactivate(struct ufs_hba *hba) + return ret; + } + ++/** ++ * ufshcd_quirk_override_pa_h8time - Ensures proper adjustment of PA_HIBERN8TIME. ++ * @hba: per-adapter instance ++ * ++ * Some UFS devices require specific adjustments to the PA_HIBERN8TIME parameter ++ * to ensure proper hibernation timing. This function retrieves the current ++ * PA_HIBERN8TIME value and increments it by 100us. ++ */ ++static void ufshcd_quirk_override_pa_h8time(struct ufs_hba *hba) ++{ ++ u32 pa_h8time; ++ int ret; ++ ++ ret = ufshcd_dme_get(hba, UIC_ARG_MIB(PA_HIBERN8TIME), &pa_h8time); ++ if (ret) { ++ dev_err(hba->dev, "Failed to get PA_HIBERN8TIME: %d\n", ret); ++ return; ++ } ++ ++ /* Increment by 1 to increase hibernation time by 100 µs */ ++ ret = ufshcd_dme_set(hba, UIC_ARG_MIB(PA_HIBERN8TIME), pa_h8time + 1); ++ if (ret) ++ dev_err(hba->dev, "Failed updating PA_HIBERN8TIME: %d\n", ret); ++} ++ + static void ufshcd_tune_unipro_params(struct ufs_hba *hba) + { + ufshcd_vops_apply_dev_quirks(hba); +@@ -8394,6 +8420,9 @@ static void ufshcd_tune_unipro_params(struct ufs_hba *hba) + + if (hba->dev_quirks & UFS_DEVICE_QUIRK_HOST_PA_TACTIVATE) + ufshcd_quirk_tune_host_pa_tactivate(hba); ++ ++ if (hba->dev_quirks & UFS_DEVICE_QUIRK_PA_HIBER8TIME) ++ ufshcd_quirk_override_pa_h8time(hba); + } + + static void ufshcd_clear_dbg_ufs_stats(struct ufs_hba *hba) +diff --git a/include/ufs/ufs_quirks.h b/include/ufs/ufs_quirks.h +index 41ff44dfa1db3..f52de5ed1b3b6 100644 +--- a/include/ufs/ufs_quirks.h ++++ b/include/ufs/ufs_quirks.h +@@ -107,4 +107,10 @@ struct ufs_dev_quirk { + */ + #define UFS_DEVICE_QUIRK_DELAY_AFTER_LPM (1 << 11) + ++/* ++ * Some ufs devices may need more time to be in hibern8 before exiting. ++ * Enable this quirk to give it an additional 100us. ++ */ ++#define UFS_DEVICE_QUIRK_PA_HIBER8TIME (1 << 12) ++ + #endif /* UFS_QUIRKS_H_ */ +-- +2.39.5 + diff --git a/queue-6.14/scsi-usb-rename-the-reserve-and-release-constants.patch b/queue-6.14/scsi-usb-rename-the-reserve-and-release-constants.patch new file mode 100644 index 0000000000..77c007ae67 --- /dev/null +++ b/queue-6.14/scsi-usb-rename-the-reserve-and-release-constants.patch @@ -0,0 +1,399 @@ +From 788e11ad62a36f5e6245d3813b187bceaa43b613 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 10 Feb 2025 12:50:09 -0800 +Subject: scsi: usb: Rename the RESERVE and RELEASE constants + +From: Bart Van Assche + +[ Upstream commit 0ea163a18b17f9e0f8350bb348ae69c4a376be66 ] + +The names RESERVE and RELEASE are not only used in but +also elsewhere in the kernel: + +$ git grep -nHE 'define[[:blank:]]*(RESERVE|RELEASE)[[:blank:]]' +drivers/input/joystick/walkera0701.c:13:#define RESERVE 20000 +drivers/s390/char/tape_std.h:56:#define RELEASE 0xD4 /* 3420 NOP, 3480 REJECT */ +drivers/s390/char/tape_std.h:58:#define RESERVE 0xF4 /* 3420 NOP, 3480 REJECT */ + +Additionally, while the names of the symbolic constants RESERVE_10 and +RELEASE_10 include the command length, the command length is not included +in the RESERVE and RELEASE names. Address both issues by renaming the +RESERVE and RELEASE constants into RESERVE_6 and RELEASE_6 respectively. + +Reviewed-by: Christoph Hellwig +Cc: Greg Kroah-Hartman +Signed-off-by: Bart Van Assche +Link: https://lore.kernel.org/r/20250210205031.2970833-1-bvanassche@acm.org +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + drivers/message/fusion/mptscsih.c | 4 ++-- + drivers/scsi/aacraid/aachba.c | 4 ++-- + drivers/scsi/arm/acornscsi.c | 2 +- + drivers/scsi/ips.c | 8 ++++---- + drivers/scsi/megaraid.c | 10 +++++----- + drivers/scsi/megaraid/megaraid_mbox.c | 10 +++++----- + drivers/target/target_core_device.c | 8 ++++---- + drivers/target/target_core_pr.c | 6 +++--- + drivers/target/target_core_spc.c | 20 ++++++++++---------- + drivers/usb/gadget/function/f_mass_storage.c | 4 ++-- + drivers/usb/storage/debug.c | 4 ++-- + include/scsi/scsi_proto.h | 4 ++-- + include/trace/events/scsi.h | 4 ++-- + include/trace/events/target.h | 4 ++-- + 14 files changed, 46 insertions(+), 46 deletions(-) + +diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c +index a9604ba3c8058..f0746db92ca61 100644 +--- a/drivers/message/fusion/mptscsih.c ++++ b/drivers/message/fusion/mptscsih.c +@@ -2915,14 +2915,14 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io) + timeout = 10; + break; + +- case RESERVE: ++ case RESERVE_6: + cmdLen = 6; + dir = MPI_SCSIIO_CONTROL_READ; + CDB[0] = cmd; + timeout = 10; + break; + +- case RELEASE: ++ case RELEASE_6: + cmdLen = 6; + dir = MPI_SCSIIO_CONTROL_READ; + CDB[0] = cmd; +diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c +index abf6a82b74af3..0be719f383770 100644 +--- a/drivers/scsi/aacraid/aachba.c ++++ b/drivers/scsi/aacraid/aachba.c +@@ -3221,8 +3221,8 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) + break; + } + fallthrough; +- case RESERVE: +- case RELEASE: ++ case RESERVE_6: ++ case RELEASE_6: + case REZERO_UNIT: + case REASSIGN_BLOCKS: + case SEEK_10: +diff --git a/drivers/scsi/arm/acornscsi.c b/drivers/scsi/arm/acornscsi.c +index e50a3dbf9de3e..ef21b85cf0146 100644 +--- a/drivers/scsi/arm/acornscsi.c ++++ b/drivers/scsi/arm/acornscsi.c +@@ -591,7 +591,7 @@ datadir_t acornscsi_datadirection(int command) + case CHANGE_DEFINITION: case COMPARE: case COPY: + case COPY_VERIFY: case LOG_SELECT: case MODE_SELECT: + case MODE_SELECT_10: case SEND_DIAGNOSTIC: case WRITE_BUFFER: +- case FORMAT_UNIT: case REASSIGN_BLOCKS: case RESERVE: ++ case FORMAT_UNIT: case REASSIGN_BLOCKS: case RESERVE_6: + case SEARCH_EQUAL: case SEARCH_HIGH: case SEARCH_LOW: + case WRITE_6: case WRITE_10: case WRITE_VERIFY: + case UPDATE_BLOCK: case WRITE_LONG: case WRITE_SAME: +diff --git a/drivers/scsi/ips.c b/drivers/scsi/ips.c +index cce6c6b409ad5..94adb6ac02a4e 100644 +--- a/drivers/scsi/ips.c ++++ b/drivers/scsi/ips.c +@@ -3631,8 +3631,8 @@ ips_send_cmd(ips_ha_t * ha, ips_scb_t * scb) + + break; + +- case RESERVE: +- case RELEASE: ++ case RESERVE_6: ++ case RELEASE_6: + scb->scsi_cmd->result = DID_OK << 16; + break; + +@@ -3899,8 +3899,8 @@ ips_chkstatus(ips_ha_t * ha, IPS_STATUS * pstatus) + case WRITE_6: + case READ_10: + case WRITE_10: +- case RESERVE: +- case RELEASE: ++ case RESERVE_6: ++ case RELEASE_6: + break; + + case MODE_SENSE: +diff --git a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c +index adab151663dd8..2006094af4189 100644 +--- a/drivers/scsi/megaraid.c ++++ b/drivers/scsi/megaraid.c +@@ -855,8 +855,8 @@ mega_build_cmd(adapter_t *adapter, struct scsi_cmnd *cmd, int *busy) + return scb; + + #if MEGA_HAVE_CLUSTERING +- case RESERVE: +- case RELEASE: ++ case RESERVE_6: ++ case RELEASE_6: + + /* + * Do we support clustering and is the support enabled +@@ -875,7 +875,7 @@ mega_build_cmd(adapter_t *adapter, struct scsi_cmnd *cmd, int *busy) + } + + scb->raw_mbox[0] = MEGA_CLUSTER_CMD; +- scb->raw_mbox[2] = ( *cmd->cmnd == RESERVE ) ? ++ scb->raw_mbox[2] = *cmd->cmnd == RESERVE_6 ? + MEGA_RESERVE_LD : MEGA_RELEASE_LD; + + scb->raw_mbox[3] = ldrv_num; +@@ -1618,8 +1618,8 @@ mega_cmd_done(adapter_t *adapter, u8 completed[], int nstatus, int status) + * failed or the input parameter is invalid + */ + if( status == 1 && +- (cmd->cmnd[0] == RESERVE || +- cmd->cmnd[0] == RELEASE) ) { ++ (cmd->cmnd[0] == RESERVE_6 || ++ cmd->cmnd[0] == RELEASE_6) ) { + + cmd->result |= (DID_ERROR << 16) | + SAM_STAT_RESERVATION_CONFLICT; +diff --git a/drivers/scsi/megaraid/megaraid_mbox.c b/drivers/scsi/megaraid/megaraid_mbox.c +index 60cc3372991fd..3ba837b3093f8 100644 +--- a/drivers/scsi/megaraid/megaraid_mbox.c ++++ b/drivers/scsi/megaraid/megaraid_mbox.c +@@ -1725,8 +1725,8 @@ megaraid_mbox_build_cmd(adapter_t *adapter, struct scsi_cmnd *scp, int *busy) + + return scb; + +- case RESERVE: +- case RELEASE: ++ case RESERVE_6: ++ case RELEASE_6: + /* + * Do we support clustering and is the support enabled + */ +@@ -1748,7 +1748,7 @@ megaraid_mbox_build_cmd(adapter_t *adapter, struct scsi_cmnd *scp, int *busy) + scb->dev_channel = 0xFF; + scb->dev_target = target; + ccb->raw_mbox[0] = CLUSTER_CMD; +- ccb->raw_mbox[2] = (scp->cmnd[0] == RESERVE) ? ++ ccb->raw_mbox[2] = scp->cmnd[0] == RESERVE_6 ? + RESERVE_LD : RELEASE_LD; + + ccb->raw_mbox[3] = target; +@@ -2334,8 +2334,8 @@ megaraid_mbox_dpc(unsigned long devp) + * Error code returned is 1 if Reserve or Release + * failed or the input parameter is invalid + */ +- if (status == 1 && (scp->cmnd[0] == RESERVE || +- scp->cmnd[0] == RELEASE)) { ++ if (status == 1 && (scp->cmnd[0] == RESERVE_6 || ++ scp->cmnd[0] == RELEASE_6)) { + + scp->result = DID_ERROR << 16 | + SAM_STAT_RESERVATION_CONFLICT; +diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c +index d1ae3df069a4f..cc2da086f96e2 100644 +--- a/drivers/target/target_core_device.c ++++ b/drivers/target/target_core_device.c +@@ -1078,8 +1078,8 @@ passthrough_parse_cdb(struct se_cmd *cmd, + if (!dev->dev_attrib.emulate_pr && + ((cdb[0] == PERSISTENT_RESERVE_IN) || + (cdb[0] == PERSISTENT_RESERVE_OUT) || +- (cdb[0] == RELEASE || cdb[0] == RELEASE_10) || +- (cdb[0] == RESERVE || cdb[0] == RESERVE_10))) { ++ (cdb[0] == RELEASE_6 || cdb[0] == RELEASE_10) || ++ (cdb[0] == RESERVE_6 || cdb[0] == RESERVE_10))) { + return TCM_UNSUPPORTED_SCSI_OPCODE; + } + +@@ -1101,7 +1101,7 @@ passthrough_parse_cdb(struct se_cmd *cmd, + return target_cmd_size_check(cmd, size); + } + +- if (cdb[0] == RELEASE || cdb[0] == RELEASE_10) { ++ if (cdb[0] == RELEASE_6 || cdb[0] == RELEASE_10) { + cmd->execute_cmd = target_scsi2_reservation_release; + if (cdb[0] == RELEASE_10) + size = get_unaligned_be16(&cdb[7]); +@@ -1109,7 +1109,7 @@ passthrough_parse_cdb(struct se_cmd *cmd, + size = cmd->data_length; + return target_cmd_size_check(cmd, size); + } +- if (cdb[0] == RESERVE || cdb[0] == RESERVE_10) { ++ if (cdb[0] == RESERVE_6 || cdb[0] == RESERVE_10) { + cmd->execute_cmd = target_scsi2_reservation_reserve; + if (cdb[0] == RESERVE_10) + size = get_unaligned_be16(&cdb[7]); +diff --git a/drivers/target/target_core_pr.c b/drivers/target/target_core_pr.c +index 4f4ad6af416c8..34cf2c399b399 100644 +--- a/drivers/target/target_core_pr.c ++++ b/drivers/target/target_core_pr.c +@@ -91,7 +91,7 @@ target_scsi2_reservation_check(struct se_cmd *cmd) + + switch (cmd->t_task_cdb[0]) { + case INQUIRY: +- case RELEASE: ++ case RELEASE_6: + case RELEASE_10: + return 0; + default: +@@ -418,12 +418,12 @@ static int core_scsi3_pr_seq_non_holder(struct se_cmd *cmd, u32 pr_reg_type, + return -EINVAL; + } + break; +- case RELEASE: ++ case RELEASE_6: + case RELEASE_10: + /* Handled by CRH=1 in target_scsi2_reservation_release() */ + ret = 0; + break; +- case RESERVE: ++ case RESERVE_6: + case RESERVE_10: + /* Handled by CRH=1 in target_scsi2_reservation_reserve() */ + ret = 0; +diff --git a/drivers/target/target_core_spc.c b/drivers/target/target_core_spc.c +index 61c065702350e..785a97536212b 100644 +--- a/drivers/target/target_core_spc.c ++++ b/drivers/target/target_core_spc.c +@@ -1674,9 +1674,9 @@ static bool tcm_is_pr_enabled(struct target_opcode_descriptor *descr, + return true; + + switch (descr->opcode) { +- case RESERVE: ++ case RESERVE_6: + case RESERVE_10: +- case RELEASE: ++ case RELEASE_6: + case RELEASE_10: + /* + * The pr_ops which are used by the backend modules don't +@@ -1828,9 +1828,9 @@ static struct target_opcode_descriptor tcm_opcode_pro_register_move = { + + static struct target_opcode_descriptor tcm_opcode_release = { + .support = SCSI_SUPPORT_FULL, +- .opcode = RELEASE, ++ .opcode = RELEASE_6, + .cdb_size = 6, +- .usage_bits = {RELEASE, 0x00, 0x00, 0x00, ++ .usage_bits = {RELEASE_6, 0x00, 0x00, 0x00, + 0x00, SCSI_CONTROL_MASK}, + .enabled = tcm_is_pr_enabled, + }; +@@ -1847,9 +1847,9 @@ static struct target_opcode_descriptor tcm_opcode_release10 = { + + static struct target_opcode_descriptor tcm_opcode_reserve = { + .support = SCSI_SUPPORT_FULL, +- .opcode = RESERVE, ++ .opcode = RESERVE_6, + .cdb_size = 6, +- .usage_bits = {RESERVE, 0x00, 0x00, 0x00, ++ .usage_bits = {RESERVE_6, 0x00, 0x00, 0x00, + 0x00, SCSI_CONTROL_MASK}, + .enabled = tcm_is_pr_enabled, + }; +@@ -2267,9 +2267,9 @@ spc_parse_cdb(struct se_cmd *cmd, unsigned int *size) + unsigned char *cdb = cmd->t_task_cdb; + + switch (cdb[0]) { +- case RESERVE: ++ case RESERVE_6: + case RESERVE_10: +- case RELEASE: ++ case RELEASE_6: + case RELEASE_10: + if (!dev->dev_attrib.emulate_pr) + return TCM_UNSUPPORTED_SCSI_OPCODE; +@@ -2313,7 +2313,7 @@ spc_parse_cdb(struct se_cmd *cmd, unsigned int *size) + *size = get_unaligned_be32(&cdb[5]); + cmd->execute_cmd = target_scsi3_emulate_pr_out; + break; +- case RELEASE: ++ case RELEASE_6: + case RELEASE_10: + if (cdb[0] == RELEASE_10) + *size = get_unaligned_be16(&cdb[7]); +@@ -2322,7 +2322,7 @@ spc_parse_cdb(struct se_cmd *cmd, unsigned int *size) + + cmd->execute_cmd = target_scsi2_reservation_release; + break; +- case RESERVE: ++ case RESERVE_6: + case RESERVE_10: + /* + * The SPC-2 RESERVE does not contain a size in the SCSI CDB. +diff --git a/drivers/usb/gadget/function/f_mass_storage.c b/drivers/usb/gadget/function/f_mass_storage.c +index 2eae8fc2e0db7..94d478b6bcd3d 100644 +--- a/drivers/usb/gadget/function/f_mass_storage.c ++++ b/drivers/usb/gadget/function/f_mass_storage.c +@@ -2142,8 +2142,8 @@ static int do_scsi_command(struct fsg_common *common) + * of Posix locks. + */ + case FORMAT_UNIT: +- case RELEASE: +- case RESERVE: ++ case RELEASE_6: ++ case RESERVE_6: + case SEND_DIAGNOSTIC: + + default: +diff --git a/drivers/usb/storage/debug.c b/drivers/usb/storage/debug.c +index 576be66ad9627..dda610f689b73 100644 +--- a/drivers/usb/storage/debug.c ++++ b/drivers/usb/storage/debug.c +@@ -58,8 +58,8 @@ void usb_stor_show_command(const struct us_data *us, struct scsi_cmnd *srb) + case INQUIRY: what = "INQUIRY"; break; + case RECOVER_BUFFERED_DATA: what = "RECOVER_BUFFERED_DATA"; break; + case MODE_SELECT: what = "MODE_SELECT"; break; +- case RESERVE: what = "RESERVE"; break; +- case RELEASE: what = "RELEASE"; break; ++ case RESERVE_6: what = "RESERVE"; break; ++ case RELEASE_6: what = "RELEASE"; break; + case COPY: what = "COPY"; break; + case ERASE: what = "ERASE"; break; + case MODE_SENSE: what = "MODE_SENSE"; break; +diff --git a/include/scsi/scsi_proto.h b/include/scsi/scsi_proto.h +index 70e1262b2e202..aeca37816506d 100644 +--- a/include/scsi/scsi_proto.h ++++ b/include/scsi/scsi_proto.h +@@ -33,8 +33,8 @@ + #define INQUIRY 0x12 + #define RECOVER_BUFFERED_DATA 0x14 + #define MODE_SELECT 0x15 +-#define RESERVE 0x16 +-#define RELEASE 0x17 ++#define RESERVE_6 0x16 ++#define RELEASE_6 0x17 + #define COPY 0x18 + #define ERASE 0x19 + #define MODE_SENSE 0x1a +diff --git a/include/trace/events/scsi.h b/include/trace/events/scsi.h +index 05f1945ed204e..bf6cc98d91228 100644 +--- a/include/trace/events/scsi.h ++++ b/include/trace/events/scsi.h +@@ -29,8 +29,8 @@ + scsi_opcode_name(INQUIRY), \ + scsi_opcode_name(RECOVER_BUFFERED_DATA), \ + scsi_opcode_name(MODE_SELECT), \ +- scsi_opcode_name(RESERVE), \ +- scsi_opcode_name(RELEASE), \ ++ scsi_opcode_name(RESERVE_6), \ ++ scsi_opcode_name(RELEASE_6), \ + scsi_opcode_name(COPY), \ + scsi_opcode_name(ERASE), \ + scsi_opcode_name(MODE_SENSE), \ +diff --git a/include/trace/events/target.h b/include/trace/events/target.h +index a13cbf2b34050..7e2e20ba26f1c 100644 +--- a/include/trace/events/target.h ++++ b/include/trace/events/target.h +@@ -31,8 +31,8 @@ + scsi_opcode_name(INQUIRY), \ + scsi_opcode_name(RECOVER_BUFFERED_DATA), \ + scsi_opcode_name(MODE_SELECT), \ +- scsi_opcode_name(RESERVE), \ +- scsi_opcode_name(RELEASE), \ ++ scsi_opcode_name(RESERVE_6), \ ++ scsi_opcode_name(RELEASE_6), \ + scsi_opcode_name(COPY), \ + scsi_opcode_name(ERASE), \ + scsi_opcode_name(MODE_SENSE), \ +-- +2.39.5 + diff --git a/queue-6.14/selftests-bpf-mitigate-sockmap_ktls-disconnect_after.patch b/queue-6.14/selftests-bpf-mitigate-sockmap_ktls-disconnect_after.patch new file mode 100644 index 0000000000..df2ff41752 --- /dev/null +++ b/queue-6.14/selftests-bpf-mitigate-sockmap_ktls-disconnect_after.patch @@ -0,0 +1,50 @@ +From 539912a96c595eb83a70956aac495523f5a26ccd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 16 Apr 2025 10:02:46 -0700 +Subject: selftests/bpf: Mitigate sockmap_ktls disconnect_after_delete failure + +From: Ihor Solodrai + +[ Upstream commit f2858f308131a09e33afb766cd70119b5b900569 ] + +"sockmap_ktls disconnect_after_delete" test has been failing on BPF CI +after recent merges from netdev: +* https://github.com/kernel-patches/bpf/actions/runs/14458537639 +* https://github.com/kernel-patches/bpf/actions/runs/14457178732 + +It happens because disconnect has been disabled for TLS [1], and it +renders the test case invalid. + +Removing all the test code creates a conflict between bpf and +bpf-next, so for now only remove the offending assert [2]. + +The test will be removed later on bpf-next. + +[1] https://lore.kernel.org/netdev/20250404180334.3224206-1-kuba@kernel.org/ +[2] https://lore.kernel.org/bpf/cfc371285323e1a3f3b006bfcf74e6cf7ad65258@linux.dev/ + +Signed-off-by: Ihor Solodrai +Signed-off-by: Andrii Nakryiko +Reviewed-by: Jiayuan Chen +Link: https://lore.kernel.org/bpf/20250416170246.2438524-1-ihor.solodrai@linux.dev +Signed-off-by: Alexei Starovoitov +Signed-off-by: Sasha Levin +--- + tools/testing/selftests/bpf/prog_tests/sockmap_ktls.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/tools/testing/selftests/bpf/prog_tests/sockmap_ktls.c b/tools/testing/selftests/bpf/prog_tests/sockmap_ktls.c +index 2d0796314862a..0a99fd404f6dc 100644 +--- a/tools/testing/selftests/bpf/prog_tests/sockmap_ktls.c ++++ b/tools/testing/selftests/bpf/prog_tests/sockmap_ktls.c +@@ -68,7 +68,6 @@ static void test_sockmap_ktls_disconnect_after_delete(int family, int map) + goto close_cli; + + err = disconnect(cli); +- ASSERT_OK(err, "disconnect"); + + close_cli: + close(cli); +-- +2.39.5 + diff --git a/queue-6.14/selftests-net-have-gro.sh-t-return-a-correct-exit-co.patch b/queue-6.14/selftests-net-have-gro.sh-t-return-a-correct-exit-co.patch new file mode 100644 index 0000000000..af78659d29 --- /dev/null +++ b/queue-6.14/selftests-net-have-gro.sh-t-return-a-correct-exit-co.patch @@ -0,0 +1,37 @@ +From aff23d470addbd4fb70cc7b534d79a78d4074e0b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 26 Feb 2025 11:27:23 -0800 +Subject: selftests/net: have `gro.sh -t` return a correct exit code + +From: Kevin Krakauer + +[ Upstream commit 784e6abd99f24024a8998b5916795f0bec9d2fd9 ] + +Modify gro.sh to return a useful exit code when the -t flag is used. It +formerly returned 0 no matter what. + +Tested: Ran `gro.sh -t large` and verified that test failures return 1. +Signed-off-by: Kevin Krakauer +Reviewed-by: Willem de Bruijn +Link: https://patch.msgid.link/20250226192725.621969-2-krakauer@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + tools/testing/selftests/net/gro.sh | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/tools/testing/selftests/net/gro.sh b/tools/testing/selftests/net/gro.sh +index 02c21ff4ca81f..aabd6e5480b8e 100755 +--- a/tools/testing/selftests/net/gro.sh ++++ b/tools/testing/selftests/net/gro.sh +@@ -100,5 +100,6 @@ trap cleanup EXIT + if [[ "${test}" == "all" ]]; then + run_all_tests + else +- run_test "${proto}" "${test}" ++ exit_code=$(run_test "${proto}" "${test}") ++ exit $exit_code + fi; +-- +2.39.5 + diff --git a/queue-6.14/selftests-pci_endpoint-skip-disabled-bars.patch b/queue-6.14/selftests-pci_endpoint-skip-disabled-bars.patch new file mode 100644 index 0000000000..e32cea3a64 --- /dev/null +++ b/queue-6.14/selftests-pci_endpoint-skip-disabled-bars.patch @@ -0,0 +1,57 @@ +From 2c2e2fd5dec9940a0740ccf38424636432451767 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 23 Jan 2025 13:01:49 +0100 +Subject: selftests: pci_endpoint: Skip disabled BARs +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Niklas Cassel + +[ Upstream commit af1451b6738ec7cf91f2914f53845424959ec4ee ] + +Currently BARs that have been disabled by the endpoint controller driver +will result in a test FAIL. + +Returning FAIL for a BAR that is disabled seems overly pessimistic. + +There are EPC that disables one or more BARs intentionally. + +One reason for this is that there are certain EPCs that are hardwired to +expose internal PCIe controller registers over a certain BAR, so the EPC +driver disables such a BAR, such that the host will not overwrite random +registers during testing. + +Such a BAR will be disabled by the EPC driver's init function, and the +BAR will be marked as BAR_RESERVED, such that it will be unavailable to +endpoint function drivers. + +Let's return FAIL only for BARs that are actually enabled and failed the +test, and let's return skip for BARs that are not even enabled. + +Signed-off-by: Niklas Cassel +Reviewed-by: Manivannan Sadhasivam +Link: https://lore.kernel.org/r/20250123120147.3603409-4-cassel@kernel.org +Signed-off-by: Manivannan Sadhasivam +Signed-off-by: Krzysztof Wilczyński +Signed-off-by: Sasha Levin +--- + tools/testing/selftests/pci_endpoint/pci_endpoint_test.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/tools/testing/selftests/pci_endpoint/pci_endpoint_test.c b/tools/testing/selftests/pci_endpoint/pci_endpoint_test.c +index c267b822c1081..576c590b277b1 100644 +--- a/tools/testing/selftests/pci_endpoint/pci_endpoint_test.c ++++ b/tools/testing/selftests/pci_endpoint/pci_endpoint_test.c +@@ -65,6 +65,8 @@ TEST_F(pci_ep_bar, BAR_TEST) + int ret; + + pci_ep_ioctl(PCITEST_BAR, variant->barno); ++ if (ret == -ENODATA) ++ SKIP(return, "BAR is disabled"); + EXPECT_FALSE(ret) TH_LOG("Test failed for BAR%d", variant->barno); + } + +-- +2.39.5 + diff --git a/queue-6.14/serial-mctrl_gpio-split-disable_ms-into-sync-and-no_.patch b/queue-6.14/serial-mctrl_gpio-split-disable_ms-into-sync-and-no_.patch new file mode 100644 index 0000000000..7d2abc6349 --- /dev/null +++ b/queue-6.14/serial-mctrl_gpio-split-disable_ms-into-sync-and-no_.patch @@ -0,0 +1,247 @@ +From 35f3d93ba01a301382b33705f3bb4c6b8c51e28a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Feb 2025 07:21:53 +0100 +Subject: serial: mctrl_gpio: split disable_ms into sync and no_sync APIs +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Alexis Lothoré + +[ Upstream commit 1bd2aad57da95f7f2d2bb52f7ad15c0f4993a685 ] + +The following splat has been observed on a SAMA5D27 platform using +atmel_serial: + +BUG: sleeping function called from invalid context at kernel/irq/manage.c:738 +in_atomic(): 1, irqs_disabled(): 128, non_block: 0, pid: 27, name: kworker/u5:0 +preempt_count: 1, expected: 0 +INFO: lockdep is turned off. +irq event stamp: 0 +hardirqs last enabled at (0): [<00000000>] 0x0 +hardirqs last disabled at (0): [] copy_process+0x1c4c/0x7bec +softirqs last enabled at (0): [] copy_process+0x1ca0/0x7bec +softirqs last disabled at (0): [<00000000>] 0x0 +CPU: 0 UID: 0 PID: 27 Comm: kworker/u5:0 Not tainted 6.13.0-rc7+ #74 +Hardware name: Atmel SAMA5 +Workqueue: hci0 hci_power_on [bluetooth] +Call trace: + unwind_backtrace from show_stack+0x18/0x1c + show_stack from dump_stack_lvl+0x44/0x70 + dump_stack_lvl from __might_resched+0x38c/0x598 + __might_resched from disable_irq+0x1c/0x48 + disable_irq from mctrl_gpio_disable_ms+0x74/0xc0 + mctrl_gpio_disable_ms from atmel_disable_ms.part.0+0x80/0x1f4 + atmel_disable_ms.part.0 from atmel_set_termios+0x764/0x11e8 + atmel_set_termios from uart_change_line_settings+0x15c/0x994 + uart_change_line_settings from uart_set_termios+0x2b0/0x668 + uart_set_termios from tty_set_termios+0x600/0x8ec + tty_set_termios from ttyport_set_flow_control+0x188/0x1e0 + ttyport_set_flow_control from wilc_setup+0xd0/0x524 [hci_wilc] + wilc_setup [hci_wilc] from hci_dev_open_sync+0x330/0x203c [bluetooth] + hci_dev_open_sync [bluetooth] from hci_dev_do_open+0x40/0xb0 [bluetooth] + hci_dev_do_open [bluetooth] from hci_power_on+0x12c/0x664 [bluetooth] + hci_power_on [bluetooth] from process_one_work+0x998/0x1a38 + process_one_work from worker_thread+0x6e0/0xfb4 + worker_thread from kthread+0x3d4/0x484 + kthread from ret_from_fork+0x14/0x28 + +This warning is emitted when trying to toggle, at the highest level, +some flow control (with serdev_device_set_flow_control) in a device +driver. At the lowest level, the atmel_serial driver is using +serial_mctrl_gpio lib to enable/disable the corresponding IRQs +accordingly. The warning emitted by CONFIG_DEBUG_ATOMIC_SLEEP is due to +disable_irq (called in mctrl_gpio_disable_ms) being possibly called in +some atomic context (some tty drivers perform modem lines configuration +in regions protected by port lock). + +Split mctrl_gpio_disable_ms into two differents APIs, a non-blocking one +and a blocking one. Replace mctrl_gpio_disable_ms calls with the +relevant version depending on whether the call is protected by some port +lock. + +Suggested-by: Jiri Slaby +Signed-off-by: Alexis Lothoré +Acked-by: Richard Genoud +Link: https://lore.kernel.org/r/20250217-atomic_sleep_mctrl_serial_gpio-v3-1-59324b313eef@bootlin.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + Documentation/driver-api/serial/driver.rst | 2 +- + drivers/tty/serial/8250/8250_port.c | 2 +- + drivers/tty/serial/atmel_serial.c | 2 +- + drivers/tty/serial/imx.c | 2 +- + drivers/tty/serial/serial_mctrl_gpio.c | 34 +++++++++++++++++----- + drivers/tty/serial/serial_mctrl_gpio.h | 17 +++++++++-- + drivers/tty/serial/sh-sci.c | 2 +- + drivers/tty/serial/stm32-usart.c | 2 +- + 8 files changed, 47 insertions(+), 16 deletions(-) + +diff --git a/Documentation/driver-api/serial/driver.rst b/Documentation/driver-api/serial/driver.rst +index 84b43061c11be..60434f2b02863 100644 +--- a/Documentation/driver-api/serial/driver.rst ++++ b/Documentation/driver-api/serial/driver.rst +@@ -103,4 +103,4 @@ Some helpers are provided in order to set/get modem control lines via GPIO. + .. kernel-doc:: drivers/tty/serial/serial_mctrl_gpio.c + :identifiers: mctrl_gpio_init mctrl_gpio_free mctrl_gpio_to_gpiod + mctrl_gpio_set mctrl_gpio_get mctrl_gpio_enable_ms +- mctrl_gpio_disable_ms ++ mctrl_gpio_disable_ms_sync mctrl_gpio_disable_ms_no_sync +diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c +index 442967a6cd52d..886e40f680d45 100644 +--- a/drivers/tty/serial/8250/8250_port.c ++++ b/drivers/tty/serial/8250/8250_port.c +@@ -1680,7 +1680,7 @@ static void serial8250_disable_ms(struct uart_port *port) + if (up->bugs & UART_BUG_NOMSR) + return; + +- mctrl_gpio_disable_ms(up->gpios); ++ mctrl_gpio_disable_ms_no_sync(up->gpios); + + up->ier &= ~UART_IER_MSI; + serial_port_out(port, UART_IER, up->ier); +diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c +index f44f9d20a9744..8918fbd4bddd5 100644 +--- a/drivers/tty/serial/atmel_serial.c ++++ b/drivers/tty/serial/atmel_serial.c +@@ -700,7 +700,7 @@ static void atmel_disable_ms(struct uart_port *port) + + atmel_port->ms_irq_enabled = false; + +- mctrl_gpio_disable_ms(atmel_port->gpios); ++ mctrl_gpio_disable_ms_no_sync(atmel_port->gpios); + + if (!mctrl_gpio_to_gpiod(atmel_port->gpios, UART_GPIO_CTS)) + idr |= ATMEL_US_CTSIC; +diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c +index 9c59ec128bb4f..cfeb3f8cf45ea 100644 +--- a/drivers/tty/serial/imx.c ++++ b/drivers/tty/serial/imx.c +@@ -1608,7 +1608,7 @@ static void imx_uart_shutdown(struct uart_port *port) + imx_uart_dma_exit(sport); + } + +- mctrl_gpio_disable_ms(sport->gpios); ++ mctrl_gpio_disable_ms_sync(sport->gpios); + + uart_port_lock_irqsave(&sport->port, &flags); + ucr2 = imx_uart_readl(sport, UCR2); +diff --git a/drivers/tty/serial/serial_mctrl_gpio.c b/drivers/tty/serial/serial_mctrl_gpio.c +index 8855688a5b6c0..ca55bcc0b6111 100644 +--- a/drivers/tty/serial/serial_mctrl_gpio.c ++++ b/drivers/tty/serial/serial_mctrl_gpio.c +@@ -322,11 +322,7 @@ void mctrl_gpio_enable_ms(struct mctrl_gpios *gpios) + } + EXPORT_SYMBOL_GPL(mctrl_gpio_enable_ms); + +-/** +- * mctrl_gpio_disable_ms - disable irqs and handling of changes to the ms lines +- * @gpios: gpios to disable +- */ +-void mctrl_gpio_disable_ms(struct mctrl_gpios *gpios) ++static void mctrl_gpio_disable_ms(struct mctrl_gpios *gpios, bool sync) + { + enum mctrl_gpio_idx i; + +@@ -342,10 +338,34 @@ void mctrl_gpio_disable_ms(struct mctrl_gpios *gpios) + if (!gpios->irq[i]) + continue; + +- disable_irq(gpios->irq[i]); ++ if (sync) ++ disable_irq(gpios->irq[i]); ++ else ++ disable_irq_nosync(gpios->irq[i]); + } + } +-EXPORT_SYMBOL_GPL(mctrl_gpio_disable_ms); ++ ++/** ++ * mctrl_gpio_disable_ms_sync - disable irqs and handling of changes to the ms ++ * lines, and wait for any pending IRQ to be processed ++ * @gpios: gpios to disable ++ */ ++void mctrl_gpio_disable_ms_sync(struct mctrl_gpios *gpios) ++{ ++ mctrl_gpio_disable_ms(gpios, true); ++} ++EXPORT_SYMBOL_GPL(mctrl_gpio_disable_ms_sync); ++ ++/** ++ * mctrl_gpio_disable_ms_no_sync - disable irqs and handling of changes to the ++ * ms lines, and return immediately ++ * @gpios: gpios to disable ++ */ ++void mctrl_gpio_disable_ms_no_sync(struct mctrl_gpios *gpios) ++{ ++ mctrl_gpio_disable_ms(gpios, false); ++} ++EXPORT_SYMBOL_GPL(mctrl_gpio_disable_ms_no_sync); + + void mctrl_gpio_enable_irq_wake(struct mctrl_gpios *gpios) + { +diff --git a/drivers/tty/serial/serial_mctrl_gpio.h b/drivers/tty/serial/serial_mctrl_gpio.h +index fc76910fb105a..79e97838ebe56 100644 +--- a/drivers/tty/serial/serial_mctrl_gpio.h ++++ b/drivers/tty/serial/serial_mctrl_gpio.h +@@ -87,9 +87,16 @@ void mctrl_gpio_free(struct device *dev, struct mctrl_gpios *gpios); + void mctrl_gpio_enable_ms(struct mctrl_gpios *gpios); + + /* +- * Disable gpio interrupts to report status line changes. ++ * Disable gpio interrupts to report status line changes, and block until ++ * any corresponding IRQ is processed + */ +-void mctrl_gpio_disable_ms(struct mctrl_gpios *gpios); ++void mctrl_gpio_disable_ms_sync(struct mctrl_gpios *gpios); ++ ++/* ++ * Disable gpio interrupts to report status line changes, and return ++ * immediately ++ */ ++void mctrl_gpio_disable_ms_no_sync(struct mctrl_gpios *gpios); + + /* + * Enable gpio wakeup interrupts to enable wake up source. +@@ -148,7 +155,11 @@ static inline void mctrl_gpio_enable_ms(struct mctrl_gpios *gpios) + { + } + +-static inline void mctrl_gpio_disable_ms(struct mctrl_gpios *gpios) ++static inline void mctrl_gpio_disable_ms_sync(struct mctrl_gpios *gpios) ++{ ++} ++ ++static inline void mctrl_gpio_disable_ms_no_sync(struct mctrl_gpios *gpios) + { + } + +diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c +index b1ea48f38248e..41f987632bce8 100644 +--- a/drivers/tty/serial/sh-sci.c ++++ b/drivers/tty/serial/sh-sci.c +@@ -2298,7 +2298,7 @@ static void sci_shutdown(struct uart_port *port) + dev_dbg(port->dev, "%s(%d)\n", __func__, port->line); + + s->autorts = false; +- mctrl_gpio_disable_ms(to_sci_port(port)->gpios); ++ mctrl_gpio_disable_ms_sync(to_sci_port(port)->gpios); + + uart_port_lock_irqsave(port, &flags); + sci_stop_rx(port); +diff --git a/drivers/tty/serial/stm32-usart.c b/drivers/tty/serial/stm32-usart.c +index 0854ad8c90cd2..ad06b760cfca7 100644 +--- a/drivers/tty/serial/stm32-usart.c ++++ b/drivers/tty/serial/stm32-usart.c +@@ -944,7 +944,7 @@ static void stm32_usart_enable_ms(struct uart_port *port) + + static void stm32_usart_disable_ms(struct uart_port *port) + { +- mctrl_gpio_disable_ms(to_stm32_port(port)->gpios); ++ mctrl_gpio_disable_ms_sync(to_stm32_port(port)->gpios); + } + + /* Transmit stop */ +-- +2.39.5 + diff --git a/queue-6.14/serial-sh-sci-save-and-restore-more-registers.patch b/queue-6.14/serial-sh-sci-save-and-restore-more-registers.patch new file mode 100644 index 0000000000..d427d7b452 --- /dev/null +++ b/queue-6.14/serial-sh-sci-save-and-restore-more-registers.patch @@ -0,0 +1,113 @@ +From 196e0ef38957a44142a4bf71f2ceac9690b64d57 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 4 Mar 2025 20:06:11 +0100 +Subject: serial: sh-sci: Save and restore more registers + +From: Geert Uytterhoeven + +[ Upstream commit 81100b9a7b0515132996d62a7a676a77676cb6e3 ] + +On (H)SCIF with a Baud Rate Generator for External Clock (BRG), there +are multiple ways to configure the requested serial speed. If firmware +uses a different method than Linux, and if any debug info is printed +after the Bit Rate Register (SCBRR) is restored, but before termios is +reconfigured (which configures the alternative method), the system may +lock-up during resume. + +Fix this by saving and restoring the contents of the BRG Frequency +Division (SCDL) and Clock Select (SCCKS) registers as well. + +Also save and restore the HSCIF's Sampling Rate Register (HSSRR), which +configures the sampling point, and the SCIFA/SCIFB's Serial Port Control +and Data Registers (SCPCR/SCPDR), which configure the optional control +flow signals. + +After this, all registers that are not saved/restored are either: + - read-only, + - write-only, + - status registers containing flags with clear-after-set semantics, + - FIFO Data Count Trigger registers, which do not matter much for + the serial console. + +Fixes: 22a6984c5b5df8ea ("serial: sh-sci: Update the suspend/resume support") +Signed-off-by: Geert Uytterhoeven +Tested-by: Claudiu Beznea +Reviewed-by: Claudiu Beznea +Link: https://lore.kernel.org/r/11c2eab45d48211e75d8b8202cce60400880fe55.1741114989.git.geert+renesas@glider.be +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/tty/serial/sh-sci.c | 25 +++++++++++++++++++++++++ + 1 file changed, 25 insertions(+) + +diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c +index e0ead0147bfe0..0219135caafa4 100644 +--- a/drivers/tty/serial/sh-sci.c ++++ b/drivers/tty/serial/sh-sci.c +@@ -105,10 +105,15 @@ struct plat_sci_reg { + }; + + struct sci_suspend_regs { ++ u16 scdl; ++ u16 sccks; + u16 scsmr; + u16 scscr; + u16 scfcr; + u16 scsptr; ++ u16 hssrr; ++ u16 scpcr; ++ u16 scpdr; + u8 scbrr; + u8 semr; + }; +@@ -3564,6 +3569,10 @@ static void sci_console_save(struct sci_port *s) + struct sci_suspend_regs *regs = &s->suspend_regs; + struct uart_port *port = &s->port; + ++ if (sci_getreg(port, SCDL)->size) ++ regs->scdl = sci_serial_in(port, SCDL); ++ if (sci_getreg(port, SCCKS)->size) ++ regs->sccks = sci_serial_in(port, SCCKS); + if (sci_getreg(port, SCSMR)->size) + regs->scsmr = sci_serial_in(port, SCSMR); + if (sci_getreg(port, SCSCR)->size) +@@ -3574,6 +3583,12 @@ static void sci_console_save(struct sci_port *s) + regs->scsptr = sci_serial_in(port, SCSPTR); + if (sci_getreg(port, SCBRR)->size) + regs->scbrr = sci_serial_in(port, SCBRR); ++ if (sci_getreg(port, HSSRR)->size) ++ regs->hssrr = sci_serial_in(port, HSSRR); ++ if (sci_getreg(port, SCPCR)->size) ++ regs->scpcr = sci_serial_in(port, SCPCR); ++ if (sci_getreg(port, SCPDR)->size) ++ regs->scpdr = sci_serial_in(port, SCPDR); + if (sci_getreg(port, SEMR)->size) + regs->semr = sci_serial_in(port, SEMR); + } +@@ -3583,6 +3598,10 @@ static void sci_console_restore(struct sci_port *s) + struct sci_suspend_regs *regs = &s->suspend_regs; + struct uart_port *port = &s->port; + ++ if (sci_getreg(port, SCDL)->size) ++ sci_serial_out(port, SCDL, regs->scdl); ++ if (sci_getreg(port, SCCKS)->size) ++ sci_serial_out(port, SCCKS, regs->sccks); + if (sci_getreg(port, SCSMR)->size) + sci_serial_out(port, SCSMR, regs->scsmr); + if (sci_getreg(port, SCSCR)->size) +@@ -3593,6 +3612,12 @@ static void sci_console_restore(struct sci_port *s) + sci_serial_out(port, SCSPTR, regs->scsptr); + if (sci_getreg(port, SCBRR)->size) + sci_serial_out(port, SCBRR, regs->scbrr); ++ if (sci_getreg(port, HSSRR)->size) ++ sci_serial_out(port, HSSRR, regs->hssrr); ++ if (sci_getreg(port, SCPCR)->size) ++ sci_serial_out(port, SCPCR, regs->scpcr); ++ if (sci_getreg(port, SCPDR)->size) ++ sci_serial_out(port, SCPDR, regs->scpdr); + if (sci_getreg(port, SEMR)->size) + sci_serial_out(port, SEMR, regs->semr); + } +-- +2.39.5 + diff --git a/queue-6.14/serial-sh-sci-update-the-suspend-resume-support.patch b/queue-6.14/serial-sh-sci-update-the-suspend-resume-support.patch new file mode 100644 index 0000000000..d1cda77735 --- /dev/null +++ b/queue-6.14/serial-sh-sci-update-the-suspend-resume-support.patch @@ -0,0 +1,164 @@ +From 8cbb933ccd8aba342e267b224429a02e19608db7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 7 Feb 2025 13:33:13 +0200 +Subject: serial: sh-sci: Update the suspend/resume support + +From: Claudiu Beznea + +[ Upstream commit 22a6984c5b5df8eab864d7f3e8b94d5a554d31ab ] + +The Renesas RZ/G3S supports a power saving mode where power to most of the +SoC components is turned off. When returning from this power saving mode, +SoC components need to be re-configured. + +The SCIFs on the Renesas RZ/G3S need to be re-configured as well when +returning from this power saving mode. The sh-sci code already configures +the SCIF clocks, power domain and registers by calling uart_resume_port() +in sci_resume(). On suspend path the SCIF UART ports are suspended +accordingly (by calling uart_suspend_port() in sci_suspend()). The only +missing setting is the reset signal. For this assert/de-assert the reset +signal on driver suspend/resume. + +In case the no_console_suspend is specified by the user, the registers need +to be saved on suspend path and restore on resume path. To do this the +sci_console_save()/sci_console_restore() functions were added. There is no +need to cache/restore the status or FIFO registers. Only the control +registers. The registers that will be saved/restored on suspend/resume are +specified by the struct sci_suspend_regs data structure. + +Signed-off-by: Claudiu Beznea +Reviewed-by: Geert Uytterhoeven +Link: https://lore.kernel.org/r/20250207113313.545432-1-claudiu.beznea.uj@bp.renesas.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/tty/serial/sh-sci.c | 71 +++++++++++++++++++++++++++++++++++-- + 1 file changed, 69 insertions(+), 2 deletions(-) + +diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c +index 41f987632bce8..e0ead0147bfe0 100644 +--- a/drivers/tty/serial/sh-sci.c ++++ b/drivers/tty/serial/sh-sci.c +@@ -104,6 +104,15 @@ struct plat_sci_reg { + u8 offset, size; + }; + ++struct sci_suspend_regs { ++ u16 scsmr; ++ u16 scscr; ++ u16 scfcr; ++ u16 scsptr; ++ u8 scbrr; ++ u8 semr; ++}; ++ + struct sci_port_params { + const struct plat_sci_reg regs[SCIx_NR_REGS]; + unsigned int fifosize; +@@ -134,6 +143,8 @@ struct sci_port { + struct dma_chan *chan_tx; + struct dma_chan *chan_rx; + ++ struct reset_control *rstc; ++ + #ifdef CONFIG_SERIAL_SH_SCI_DMA + struct dma_chan *chan_tx_saved; + struct dma_chan *chan_rx_saved; +@@ -153,6 +164,7 @@ struct sci_port { + int rx_trigger; + struct timer_list rx_fifo_timer; + int rx_fifo_timeout; ++ struct sci_suspend_regs suspend_regs; + u16 hscif_tot; + + bool has_rtscts; +@@ -3374,6 +3386,7 @@ static struct plat_sci_port *sci_parse_dt(struct platform_device *pdev, + } + + sp = &sci_ports[id]; ++ sp->rstc = rstc; + *dev_id = id; + + p->type = SCI_OF_TYPE(data); +@@ -3546,13 +3559,57 @@ static int sci_probe(struct platform_device *dev) + return 0; + } + ++static void sci_console_save(struct sci_port *s) ++{ ++ struct sci_suspend_regs *regs = &s->suspend_regs; ++ struct uart_port *port = &s->port; ++ ++ if (sci_getreg(port, SCSMR)->size) ++ regs->scsmr = sci_serial_in(port, SCSMR); ++ if (sci_getreg(port, SCSCR)->size) ++ regs->scscr = sci_serial_in(port, SCSCR); ++ if (sci_getreg(port, SCFCR)->size) ++ regs->scfcr = sci_serial_in(port, SCFCR); ++ if (sci_getreg(port, SCSPTR)->size) ++ regs->scsptr = sci_serial_in(port, SCSPTR); ++ if (sci_getreg(port, SCBRR)->size) ++ regs->scbrr = sci_serial_in(port, SCBRR); ++ if (sci_getreg(port, SEMR)->size) ++ regs->semr = sci_serial_in(port, SEMR); ++} ++ ++static void sci_console_restore(struct sci_port *s) ++{ ++ struct sci_suspend_regs *regs = &s->suspend_regs; ++ struct uart_port *port = &s->port; ++ ++ if (sci_getreg(port, SCSMR)->size) ++ sci_serial_out(port, SCSMR, regs->scsmr); ++ if (sci_getreg(port, SCSCR)->size) ++ sci_serial_out(port, SCSCR, regs->scscr); ++ if (sci_getreg(port, SCFCR)->size) ++ sci_serial_out(port, SCFCR, regs->scfcr); ++ if (sci_getreg(port, SCSPTR)->size) ++ sci_serial_out(port, SCSPTR, regs->scsptr); ++ if (sci_getreg(port, SCBRR)->size) ++ sci_serial_out(port, SCBRR, regs->scbrr); ++ if (sci_getreg(port, SEMR)->size) ++ sci_serial_out(port, SEMR, regs->semr); ++} ++ + static __maybe_unused int sci_suspend(struct device *dev) + { + struct sci_port *sport = dev_get_drvdata(dev); + +- if (sport) ++ if (sport) { + uart_suspend_port(&sci_uart_driver, &sport->port); + ++ if (!console_suspend_enabled && uart_console(&sport->port)) ++ sci_console_save(sport); ++ else ++ return reset_control_assert(sport->rstc); ++ } ++ + return 0; + } + +@@ -3560,8 +3617,18 @@ static __maybe_unused int sci_resume(struct device *dev) + { + struct sci_port *sport = dev_get_drvdata(dev); + +- if (sport) ++ if (sport) { ++ if (!console_suspend_enabled && uart_console(&sport->port)) { ++ sci_console_restore(sport); ++ } else { ++ int ret = reset_control_deassert(sport->rstc); ++ ++ if (ret) ++ return ret; ++ } ++ + uart_resume_port(&sci_uart_driver, &sport->port); ++ } + + return 0; + } +-- +2.39.5 + diff --git a/queue-6.14/series b/queue-6.14/series new file mode 100644 index 0000000000..ac13001f9b --- /dev/null +++ b/queue-6.14/series @@ -0,0 +1,705 @@ +drm-amd-display-do-not-enable-replay-when-vtotal-upd.patch +drm-amd-display-correct-timing_adjust_pending-flag-s.patch +drm-amd-display-defer-bw-optimization-blocked-drr-ad.patch +phy-renesas-rcar-gen3-usb2-move-irq-request-in-probe.patch +phy-renesas-rcar-gen3-usb2-lock-around-hardware-regi.patch +phy-renesas-rcar-gen3-usb2-assert-pll-reset-on-phy-p.patch +nvmet-pci-epf-keep-completion-queues-mapped.patch +nvmet-pci-epf-clear-completion-queue-irq-flag-on-del.patch +cpufreq-add-sm8650-to-cpufreq-dt-platdev-blocklist.patch +nvmem-rockchip-otp-move-read-offset-into-variant-dat.patch +nvmem-rockchip-otp-add-rk3576-variant-data.patch +nvmem-core-fix-bit-offsets-of-more-than-one-byte.patch +nvmem-core-verify-cell-s-raw_len.patch +nvmem-core-update-raw_len-if-the-bit-reading-is-requ.patch +nvmem-qfprom-switch-to-4-byte-aligned-reads.patch +scsi-target-iscsi-fix-timeout-on-deleted-connection.patch +scsi-ufs-introduce-quirk-to-extend-pa_hibern8time-fo.patch +virtio_ring-fix-data-race-by-tagging-event_triggered.patch +dma-mapping.c-dev_dbg-support-for-dma_addressing_lim.patch +intel_th-avoid-using-deprecated-page-mapping-index-f.patch +mei-vsc-use-struct-vsc_tp_packet-as-vsc-tp-tx_buf-an.patch +dma-mapping-avoid-potential-unused-data-compilation-.patch +btrfs-tree-checker-adjust-error-code-for-header-leve.patch +cgroup-fix-compilation-issue-due-to-cgroup_mutex-not.patch +vhost_task-fix-vhost_task_create-documentation.patch +vhost-scsi-protect-vq-log_used-with-vq-mutex.patch +scsi-mpi3mr-add-level-check-to-control-event-logging.patch +dma-mapping-fix-warning-reported-for-missing-prototy.patch +ima-process_measurement-needlessly-takes-inode_lock-.patch +fs-buffer-split-locking-for-pagecache-lookups.patch +fs-buffer-introduce-sleeping-flavors-for-pagecache-l.patch +fs-buffer-use-sleeping-version-of-__find_get_block.patch +fs-ocfs2-use-sleeping-version-of-__find_get_block.patch +fs-jbd2-use-sleeping-version-of-__find_get_block.patch +fs-ext4-use-sleeping-version-of-sb_find_get_block.patch +drm-amd-display-enable-urgent-latency-adjustment-on-.patch +drm-amdgpu-allow-p2p-access-through-xgmi.patch +selftests-bpf-mitigate-sockmap_ktls-disconnect_after.patch +block-fix-race-between-set_blocksize-and-read-paths.patch +block-hoist-block-size-validation-code-to-a-separate.patch +io_uring-don-t-duplicate-flushing-in-io_req_post_cqe.patch +bpf-fix-possible-endless-loop-in-bpf-map-iteration.patch +samples-bpf-fix-compilation-failure-for-samples-bpf-.patch +kconfig-merge_config-use-an-empty-file-as-initfile.patch +x86-fred-fix-system-hang-during-s4-resume-with-fred-.patch +s390-vfio-ap-fix-no-ap-queue-sharing-allowed-message.patch +cifs-add-fallback-for-smb2-create-without-file_read_.patch +cifs-fix-querying-and-creating-mf-symlinks-over-smb1.patch +cifs-fix-access_flags_to_smbopen_mode.patch +cifs-fix-negotiate-retry-functionality.patch +smb-client-store-original-io-parameters-and-prevent-.patch +fuse-return-eperm-rather-than-enosys-from-link.patch +exfat-call-bh_read-in-get_block-only-when-necessary.patch +io_uring-msg-initialise-msg-request-opcode.patch +nfsv4-check-for-delegation-validity-in-nfs_start_del.patch +nfs-don-t-allow-waiting-for-exiting-tasks.patch +sunrpc-don-t-allow-waiting-for-exiting-tasks.patch +arm64-add-support-for-hip09-spectre-bhb-mitigation.patch +iommufd-extend-iommu_get_hw_info-to-report-pasid-cap.patch +ring-buffer-use-kaslr-address-instead-of-text-delta.patch +tracing-mark-binary-printing-functions-with-__printf.patch +acpi-pnp-add-intel-oc-watchdog-ids-to-non-pnp-device.patch +tpm-convert-warn-to-dbg-in-tpm2_start_auth_session.patch +mailbox-pcc-use-acpi_os_ioremap-instead-of-ioremap.patch +mailbox-use-error-ret-code-of-of_parse_phandle_with_.patch +riscv-allow-nommu-kernels-to-access-all-of-ram.patch +fbdev-fsl-diu-fb-add-missing-device_remove_file.patch +fbcon-use-correct-erase-colour-for-clearing-in-fbcon.patch +fbdev-core-tileblit-implement-missing-margin-clearin.patch +cifs-set-default-netbios-rfc1001-server-name-to-host.patch +cifs-add-validation-check-for-the-fields-in-smb_aces.patch +cifs-fix-establishing-netbios-session-for-smb2-conne.patch +cifs-fix-getting-dacl-only-xattr-system.cifs_acl-and.patch +cifs-check-if-server-supports-reparse-points-before-.patch +nfsv4-treat-enetunreach-errors-as-fatal-for-state-re.patch +sunrpc-rpc_clnt_set_transport-must-not-change-the-au.patch +sunrpc-rpcbind-should-never-reset-the-port-to-the-va.patch +spi-rockchip-fix-register-out-of-bounds-access.patch +asoc-codecs-wsa884x-correct-vi-sense-channel-mask.patch +asoc-codecs-wsa883x-correct-vi-sense-channel-mask.patch +mctp-fix-incorrect-tx-flow-invalidation-condition-in.patch +net-tn40xx-add-pci-id-of-the-aqr105-based-tehuti-tn4.patch +net-tn40xx-create-swnode-for-mdio-and-aqr105-phy-and.patch +thermal-drivers-mediatek-lvts-start-sensor-interrupt.patch +thermal-drivers-qoriq-power-down-tmu-on-system-suspe.patch +bluetooth-btmtksdio-prevent-enabling-interrupts-afte.patch +bluetooth-disable-sco-support-if-read_voice_setting-.patch +exit-fix-the-usage-of-delay_group_leader-exit_code-i.patch +risc-v-add-vector-extension-validation-checks.patch +dql-fix-dql-limit-value-when-reset.patch +lockdep-fix-wait-context-check-on-softirq-for-preemp.patch +objtool-properly-disable-uaccess-validation.patch +net-mlx5e-use-right-api-to-free-bitmap-memory.patch +pci-dwc-ep-ensure-proper-iteration-over-outbound-map.patch +r8169-disable-rtl8126-zrx-dc-timeout.patch +tools-build-don-t-pass-test-log-files-to-linker.patch +pci-xilinx-cpm-add-cpm_csr-register-mapping-for-cpm5.patch +i2c-qcom-geni-update-i2c-frequency-table-to-match-ha.patch +pnfs-flexfiles-report-enetdown-as-a-connection-error.patch +drm-amdgpu-discovery-check-ip_discovery-fw-file-avai.patch +drm-amdgpu-rework-how-the-cleaner-shader-is-emitted-.patch +drm-amdgpu-rework-how-isolation-is-enforced-v2.patch +drm-amdgpu-use-gfp_nowait-for-memory-allocations.patch +drm-amdkfd-set-precise-mem-ops-caps-to-disabled-for-.patch +pci-vmd-disable-msi-remapping-bypass-under-xen.patch +xen-pci-do-not-register-devices-with-segments-0x1000.patch +ext4-on-a-remount-only-log-the-ro-or-r-w-state-when-.patch +libnvdimm-labels-fix-divide-error-in-nd_label_data_i.patch +pidfs-improve-multi-threaded-exec-and-premature-thre.patch +staging-vchiq_arm-create-keep-alive-thread-during-pr.patch +mmc-host-wait-for-vdd-to-settle-on-card-power-off.patch +drm-amdgpu-skip-pcie_replay_count-sysfs-creation-for.patch +cgroup-rstat-avoid-disabling-irqs-for-o-num_cpu.patch +wifi-mt76-check-link_conf-pointer-in-mt76_connac_mcu.patch +wifi-mt76-scan-fix-setting-tx_info-fields.patch +wifi-mt76-mt7996-implement-driver-specific-get_txpow.patch +wifi-mt76-only-mark-tx-status-failed-frames-as-acked.patch +wifi-mt76-mt7996-use-the-correct-vif-link-for-scanni.patch +wifi-mt76-scan-set-vif-offchannel-link-for-scanning-.patch +wifi-mt76-mt7996-fix-ser-reset-trigger-on-wed-reset.patch +wifi-mt76-mt7996-revise-txs-size.patch +wifi-mt76-mt7925-load-the-appropriate-clc-data-based.patch +wifi-mt76-mt7925-simplify-hif-suspend-handling-to-av.patch +wifi-mt76-mt7925-fix-fails-to-enter-low-power-mode-i.patch +x86-headers-replace-__assembly__-with-__assembler__-.patch +x86-headers-replace-__assembly__-with-__assembler__-.patch-7903 +x86-stackprotector-64-only-export-__ref_stack_chk_gu.patch +x86-smpboot-fix-init-delay-assignment-for-extended-i.patch +x86-microcode-update-the-intel-processor-flag-scan-c.patch +x86-amd_node-add-smn-offsets-to-exclusive-region-acc.patch +x86-mm-check-return-value-from-memblock_phys_alloc_r.patch +i2c-qup-vote-for-interconnect-bandwidth-to-dram.patch +i2c-amd-asf-set-cmd-variable-when-encountering-an-er.patch +i2c-pxa-fix-call-balance-of-i2c-clk-handling-routine.patch +btrfs-make-btrfs_discard_workfn-block_group-ref-expl.patch +btrfs-avoid-linker-error-in-btrfs_find_create_tree_b.patch +btrfs-run-btrfs_error_commit_super-early.patch +btrfs-fix-non-empty-delayed-iputs-list-on-unmount-du.patch +btrfs-properly-limit-inline-data-extent-according-to.patch +btrfs-allow-buffered-write-to-avoid-full-page-read-i.patch +btrfs-prevent-inline-data-extents-read-from-touching.patch +btrfs-get-zone-unusable-bytes-while-holding-lock-at-.patch +btrfs-send-return-enametoolong-when-attempting-a-pat.patch +btrfs-zoned-exit-btrfs_can_activate_zone-if-btrfs_fs.patch +blk-cgroup-improve-policy-registration-error-handlin.patch +drm-amdgpu-release-xcp_mgr-on-exit.patch +drm-amd-display-guard-against-setting-dispclk-low-fo.patch +drm-amdgpu-don-t-free-conflicting-apertures-for-non-.patch +drm-amdgpu-adjust-drm_firmware_drivers_only-handling.patch +i3c-master-svc-fix-missing-stop-for-master-request.patch +s390-tlb-use-mm_has_pgste-instead-of-mm_alloc_pgste.patch +dlm-make-tcp-still-work-in-multi-link-env.patch +loop-move-vfs_fsync-out-of-loop_update_dio.patch +clocksource-drivers-timer-riscv-stop-stimecmp-when-c.patch +um-store-full-csgsfs-and-ss-register-from-mcontext.patch +um-update-min_low_pfn-to-match-changes-in-uml_reserv.patch +net-mlx5-preserve-rate-settings-when-creating-a-rate.patch +wifi-mwifiex-fix-ht40-bandwidth-issue.patch +bnxt_en-query-fw-parameters-when-the-caps_change-bit.patch +ixgbe-add-support-for-thermal-sensor-event-reception.patch +riscv-call-secondary-mmu-notifier-when-flushing-the-.patch +ext4-reorder-capability-check-last.patch +hypfs_create_cpu_files-add-missing-check-for-hypfs_m.patch +scsi-st-tighten-the-page-format-heuristics-with-mode.patch +scsi-st-erase-does-not-change-tape-location.patch +vfio-pci-handle-intx-irq_notconnected.patch +bpftool-using-the-right-format-specifiers.patch +libbpf-pass-bpf-token-from-find_prog_btf_id-to-bpf_b.patch +bpf-return-prog-btf_id-without-capable-check.patch +pci-dwc-use-resource-start-as-ioremap-input-in-dw_pc.patch +jbd2-do-not-try-to-recover-wiped-journal.patch +tcp-reorganize-tcp_in_ack_event-and-tcp_count_delive.patch +rtc-rv3032-fix-eerd-location.patch +objtool-fix-error-handling-inconsistencies-in-check.patch +thunderbolt-do-not-add-non-active-nvm-if-nvm-upgrade.patch +erofs-initialize-decompression-early.patch +spi-spi-mux-fix-coverity-issue-unchecked-return-valu.patch +asoc-sma1307-add-null-check-in-sma1307_setting_loade.patch +asoc-pcm6240-drop-bogus-code-handling-irq-as-gpio.patch +asoc-mediatek-mt6359-add-stub-for-mt6359_accdet_enab.patch +kunit-tool-fix-bug-in-parsing-test-plan.patch +bpf-allow-pre-ordering-for-bpf-cgroup-progs.patch +kbuild-fix-argument-parsing-in-scripts-config.patch +kconfig-do-not-clear-symbol_valid-when-reading-inclu.patch +crypto-octeontx2-suppress-auth-failure-screaming-due.patch +dm-restrict-dm-device-size-to-2-63-512-bytes.patch +net-smc-use-the-correct-ndev-to-find-pnetid-by-pneti.patch +xen-add-support-for-xenserver-6.1-platform-device.patch +pinctrl-tegra-restore-sfsel-bit-when-freeing-pins.patch +mfd-syscon-add-check-for-invalid-resource-size.patch +mfd-tps65219-remove-tps65219_reg_ti_dev_id-check.patch +drm-amdgpu-gfx12-don-t-read-registers-in-mqd-init.patch +drm-amdgpu-gfx11-don-t-read-registers-in-mqd-init.patch +drm-amdgpu-update-sriov-video-codec-caps.patch +asoc-sun4i-codec-support-hp-det-gpios-property.patch +asoc-sun4i-codec-correct-dapm-widgets-and-controls-f.patch +clk-qcom-lpassaudiocc-sc7280-add-support-for-lpass-r.patch +f2fs-defer-readonly-check-vs-norecovery.patch +leds-kconfig-leds-st1202-add-select-for-required-led.patch +leds-leds-st1202-initialize-hardware-before-dt-node-.patch +ext4-reject-the-data_err-abort-option-in-nojournal-m.patch +ext4-do-not-convert-the-unwritten-extents-if-data-wr.patch +rdma-uverbs-propagate-errors-from-rdma_lookup_get_uo.patch +posix-timers-add-cond_resched-to-posix_timer_add-sea.patch +posix-timers-ensure-that-timer-initialization-is-ful.patch +net-stmmac-dwmac-rk-validate-grf-and-peripheral-grf-.patch +net-hsr-fix-prp-duplicate-detection.patch +timer_list-don-t-use-pk-through-printk.patch +wifi-rtw89-coex-fix-coexistence-report-not-show-as-e.patch +wifi-rtw89-set-force-he-tb-mode-when-connecting-to-1.patch +netfilter-conntrack-bound-nf_conntrack-sysctl-writes.patch +pnp-expand-length-of-fixup-id-string.patch +phy-rockchip-usbdp-only-verify-link-rates-lanes-volt.patch +arm64-mm-check-pmd_table-in-pmd_trans_huge.patch +arm64-mm-check-pud_type_table-in-pud_bad.patch +mmc-dw_mmc-add-exynos7870-dw-mmc-support.patch +mmc-sdhci-disable-sd-card-clock-before-changing-para.patch +usb-xhci-don-t-change-the-status-of-stalled-tds-on-f.patch +wifi-iwlwifi-mvm-fix-setting-the-tk-when-associated.patch +hwmon-dell-smm-increment-the-number-of-fans.patch +iommu-keep-dev-iommu-state-consistent.patch +printk-check-con_suspend-when-unblanking-a-console.patch +wifi-iwlwifi-don-t-warn-when-if-there-is-a-fw-error.patch +wifi-iwlwifi-w-a-fw-smps-mode-selection.patch +wifi-iwlwifi-fix-debug-actions-order.patch +wifi-iwlwifi-mark-br-device-not-integrated.patch +wifi-iwlwifi-fix-the-eckv-uefi-variable-name.patch +wifi-mac80211-don-t-include-mle-in-ml-reconf-per-sta.patch +wifi-cfg80211-update-the-link-address-when-a-link-is.patch +wifi-mac80211-fix-warning-on-disconnect-during-faile.patch +wifi-mac80211_hwsim-fix-mld-address-translation.patch +wifi-mac80211-fix-u-apsd-check-in-ml-reconfiguration.patch +wifi-cfg80211-allow-ir-in-20-mhz-configurations.patch +r8169-increase-max-jumbo-packet-size-on-rtl8125-rtl8.patch +ipv6-save-dontfrag-in-cork.patch +drm-amd-display-remove-minimum-dispclk-and-apply-oem.patch +drm-amd-display-calculate-the-remain-segments-for-al.patch +drm-amd-display-not-abort-link-train-when-bw-is-low.patch +drm-amd-display-fix-incorrect-dpcd-configs-while-rep.patch +gfs2-check-for-empty-queue-in-run_queue.patch +auxdisplay-charlcd-partially-revert-move-hwidth-and-.patch +asoc-qcom-sm8250-explicitly-set-format-in-sm8250_be_.patch +badblocks-fix-a-nonsense-warn_on-which-checks-whethe.patch +block-acquire-q-limits_lock-while-reading-sysfs-attr.patch +coresight-etb10-change-etb_drvdata-spinlock-s-type-t.patch +coresight-change-coresight_trace_id_map-s-lock-type-.patch +iommu-vt-d-move-scalable-mode-ats-enablement-to-prob.patch +iommu-vt-d-check-if-sva-is-supported-when-attaching-.patch +iommu-amd-pgtbl_v2-improve-error-handling.patch +fs-pipe-limit-the-slots-in-pipe_resize_ring.patch +cpufreq-tegra186-share-policy-per-cluster.patch +watchdog-s3c2410_wdt-fix-pmu-register-bits-for-exyno.patch +watchdog-aspeed-update-bootstatus-handling.patch +pci-endpoint-pci-epf-test-fix-double-free-that-cause.patch +misc-pci_endpoint_test-give-disabled-bars-a-distinct.patch +selftests-pci_endpoint-skip-disabled-bars.patch +crypto-lzo-fix-compression-buffer-overrun.patch +crypto-mxs-dcp-only-set-otp_key-bit-for-otp-key.patch +drm-amdkfd-set-per-process-flags-only-once-for-gfx9-.patch +drm-amdkfd-set-per-process-flags-only-once-cik-vi.patch +drm-amdkfd-clear-f8_mode-for-gfx950.patch +drm-amdgpu-increase-ras-bad-page-threshold.patch +drm-amdgpu-fix-missing-drain-retry-fault-the-last-en.patch +arm64-tegra-p2597-fix-gpio-for-vdd-1v8-dis-regulator.patch +arm64-tegra-resize-aperture-for-the-igx-pcie-c5-slot.patch +powerpc-prom_init-fixup-missing-size-cells-on-powerb.patch +alsa-seq-improve-data-consistency-at-polling.patch +tcp-bring-back-numa-dispersion-in-inet_ehash_locks_a.patch +rseq-fix-segfault-on-registration-when-rseq_cs-is-no.patch +rtc-ds1307-stop-disabling-alarms-on-probe.patch +ieee802154-ca8210-use-proper-setters-and-getters-for.patch +drm-xe-nuke-vm-s-mapping-upon-close.patch +drm-xe-retry-bo-allocation.patch +soc-samsung-include-linux-array_size.h-where-needed.patch +arm-tegra-switch-dsi-b-clock-parent-to-plld-on-tegra.patch +media-c8sectpfe-call-of_node_put-i2c_bus-only-once-i.patch +media-cec-use-us_to_ktime-where-appropriate.patch +usb-xhci-set-page-size-to-the-xhci-supported-size.patch +dm-cache-prevent-bug_on-by-blocking-retries-on-faile.patch +soc-mediatek-mtk-mutex-add-dpi1-sof-eof-to-mt8188-mu.patch +orangefs-do-not-truncate-file-size.patch +drm-gem-test-for-imported-gem-buffers-with-helper.patch +net-phylink-use-pl-link_interface-in-phylink_expects.patch +blk-throttle-don-t-take-carryover-for-prioritized-pr.patch +remoteproc-qcom_wcnss-handle-platforms-with-only-sin.patch +drm-xe-disambiguate-gmdid-based-ip-names.patch +drm-amdgpu-do-not-program-agp-bar-regs-under-sriov-i.patch +drm-amdgpu-reinit-fw-shared-flags-on-vcn-v5.0.1.patch +drm-amdgpu-add-dce_v6_0_soft_reset-to-dce6.patch +drm-amd-display-ensure-dmcub-idle-before-reset-on-dc.patch +drm-amd-display-skip-checking-frl_mode-bit-for-pcon-.patch +drm-amd-display-fix-dmub-reset-sequence-for-dcn401.patch +drm-amd-display-fix-p-state-type-when-p-state-is-uns.patch +drm-amd-display-request-hw-cursor-on-dcn3.2-with-sub.patch +drm-amdgpu-avoid-hdp-flush-on-jpeg-v5.0.1.patch +drm-amdgpu-add-offset-normalization-in-vcn-v5.0.1.patch +perf-core-clean-up-perf_try_init_event.patch +media-cx231xx-set-device_caps-for-417.patch +pinctrl-bcm281xx-use-unsigned-int-instead-of-bare-un.patch +rcu-fix-get_state_synchronize_rcu_full-gp-start-dete.patch +drm-msm-dpu-set-possible-clones-for-all-encoders.patch +net-ethernet-ti-cpsw_new-populate-netdev-of_node.patch +eth-fbnic-prepend-tsene-fw-fields-with-fbnic_fw.patch +net-phy-nxp-c45-tja11xx-add-match_phy_device-to-tja1.patch +dpll-add-an-assertion-to-check-freq_supported_num.patch +ublk-enforce-ublks_max-only-for-unprivileged-devices.patch +iommufd-disallow-allocating-nested-parent-domain-wit.patch +media-imx335-set-vblank-immediately.patch +net-pktgen-fix-mpls-maximum-labels-list-parsing.patch +perf-core-fix-perf_mmap-failure-path.patch +perf-hw_breakpoint-return-eopnotsupp-for-unsupported.patch +alsa-hda-realtek-enable-pc-beep-passthrough-for-hp-e.patch +scsi-logging-fix-scsi_logging_level-bounds.patch +ipv4-fib-move-fib_valid_key_len-to-rtm_to_fib_config.patch +ipv4-fib-hold-rtnl_net_lock-in-ip_rt_ioctl.patch +drm-rockchip-vop2-add-uv-swap-for-cluster-window.patch +block-mark-bounce-buffering-as-incompatible-with-int.patch +null_blk-generate-null_blk-configfs-features-string.patch +ublk-complete-command-synchronously-on-error.patch +media-uvcvideo-add-sanity-check-to-uvc_ioctl_xu_ctrl.patch +media-uvcvideo-handle-uvc-menu-translation-inside-uv.patch +clk-imx8mp-inform-ccf-of-maximum-frequency-of-clocks.patch +pm-sleep-suppress-sleeping-parent-warning-in-special.patch +x86-bugs-make-spectre-user-default-depend-on-mitigat.patch +hwmon-acpi_power_meter-fix-the-fake-power-alarm-repo.patch +hwmon-gpio-fan-add-missing-mutex-locks.patch +arm-at91-pm-fix-at91_suspend_finish-for-zq-calibrati.patch +drm-mediatek-mtk_dpi-add-checks-for-reg_h_fre_con-ex.patch +fpga-altera-cvp-increase-credit-timeout.patch +perf-arm_pmuv3-call-kvm_vcpu_pmu_resync_el0-before-e.patch +soc-apple-rtkit-use-high-prio-work-queue.patch +soc-apple-rtkit-implement-oslog-buffers-properly.patch +wifi-ath12k-report-proper-tx-completion-status-to-ma.patch +pci-brcmstb-expand-inbound-window-size-up-to-64gb.patch +pci-brcmstb-add-a-softdep-to-mip-msi-x-driver.patch +nvme-map-uring_cmd-data-even-if-address-is-0.patch +firmware-arm_ffa-set-dma_mask-for-ffa-devices.patch +drm-xe-vf-retry-sending-mmio-request-to-guc-on-timeo.patch +drm-xe-pf-create-a-link-between-pf-and-vf-devices.patch +net-mlx5-avoid-report-two-health-errors-on-same-synd.patch +selftests-net-have-gro.sh-t-return-a-correct-exit-co.patch +driver-core-faux-only-create-the-device-if-probe-suc.patch +rust-faux-add-missing-parent-argument-to-registratio.patch +pinctrl-sophgo-avoid-to-modify-untouched-bit-when-se.patch +drm-amdkfd-kfd-release_work-possible-circular-lockin.patch +drm-xe-xe_gen_wa_oob-replace-program_invocation_shor.patch +leds-pwm-multicolor-add-check-for-fwnode_property_re.patch +accel-amdxdna-check-interrupt-register-before-mailbo.patch +net-ethernet-mtk_ppe_offload-allow-qinq-double-eth_p.patch +net-xgene-v2-remove-incorrect-acpi_ptr-annotation.patch +dmaengine-ti-k3-udma-glue-drop-skip_fdq-argument-fro.patch +wifi-rtw89-parse-channel-from-ie-to-correct-invalid-.patch +bonding-report-duplicate-mac-address-in-all-situatio.patch +tcp-be-less-liberal-in-tsecr-received-while-in-syn_r.patch +pinctrl-qcom-msm8917-add-msm8937-wsa_reset-pin.patch +wifi-ath12k-improve-bss-discovery-with-hidden-ssid-i.patch +soc-ti-k3-socinfo-do-not-use-syscon-helper-to-build-.patch +x86-bugs-kvm-add-support-for-srso_msr_fix.patch +bpf-search-and-add-kfuncs-in-struct_ops-prologue-and.patch +octeontx2-af-rpm-register-driver-with-pci-subsys-ids.patch +x86-build-fix-broken-copy-command-in-genimage.sh-whe.patch +drm-amd-display-handle-max_downscale_src_width-fail-.patch +drm-amd-display-fix-dcn4x-init-failed.patch +drm-amd-display-fix-check-for-identity-ratio.patch +drm-amd-display-fix-mismatch-type-comparison.patch +drm-amd-display-add-opp-recout-adjustment.patch +drm-amd-display-fix-mismatch-type-comparison-in-cust.patch +asoc-mediatek-mt8188-treat-dmic_gainx_cur-as-non-vol.patch +asoc-mediatek-mt8188-add-reference-for-dmic-clocks.patch +x86-nmi-add-an-emergency-handler-in-nmi_desc-use-it-.patch +vhost-scsi-return-queue-full-for-page-alloc-failures.patch +vdpa-mlx5-fix-mlx5_vdpa_get_config-endianness-on-big.patch +cpuidle-menu-avoid-discarding-useful-information.patch +media-adv7180-disable-test-pattern-control-on-adv718.patch +media-tc358746-improve-calculation-of-the-d-phy-timi.patch +net-mlx5e-add-correct-match-to-check-ipsec-syndromes.patch +scsi-mpi3mr-update-timestamp-only-for-supervisor-ioc.patch +loop-check-in-lo_flags_direct_io-in-loop_default_blo.patch +net-stmmac-correct-usage-of-maximum-queue-number-mac.patch +libbpf-fix-out-of-bound-read.patch +virtio-break-and-reset-virtio-devices-on-device_shut.patch +dm-fix-unconditional-io-throttle-caused-by-req_prefl.patch +fs-mpage-avoid-negative-shift-for-large-blocksize.patch +gpiolib-sanitize-the-return-value-of-gpio_chip-set_c.patch +scsi-scsi_debug-first-fixes-for-tapes.patch +bpf-arm64-silence-ubsan-negation-overflow-warning.patch +clk-sunxi-ng-h616-reparent-gpu-clock-during-frequenc.patch +net-mlx5-change-pool_next_size-define-value-and-make.patch +x86-kaslr-reduce-kaslr-entropy-on-most-x86-systems.patch +crypto-ahash-set-default-reqsize-from-ahash_alg.patch +crypto-skcipher-zap-type-in-crypto_alloc_sync_skciph.patch +net-ipv6-init-tunnel-link-netns-before-registering-d.patch +rtnetlink-lookup-device-in-target-netns-when-creatin.patch +drm-xe-oa-ensure-that-polled-read-returns-latest-dat.patch +mips-use-arch-specific-syscall-name-match-function.patch +drm-amdgpu-remove-all-kfd-fences-from-the-bo-on-rele.patch +x86-mm-make-mmu_gather_rcu_table_free-unconditional.patch +x86-locking-use-alt_output_sp-for-percpu_-try_-cmpxc.patch +genirq-msi-store-the-iommu-iova-directly-in-msi_desc.patch +pps-generators-replace-copy-of-pps-gen-info-struct-w.patch +mips-pm-cps-use-per-cpu-variables-as-per-cpu-not-per.patch +clocksource-mips-gic-timer-enable-counter-when-cpus-.patch +pci-epf-mhi-update-device-id-for-sa8775p.patch +scsi-mpt3sas-send-a-diag-reset-if-target-reset-fails.patch +wifi-rtw88-fix-rtw_init_vht_cap-for-rtl8814au.patch +wifi-rtw88-fix-rtw_init_ht_cap-for-rtl8814au.patch +wifi-rtw88-fix-rtw_desc_to_mcsrate-to-handle-mcs16-3.patch +wifi-rtw88-fix-rtw_mac_power_switch-for-rtl8814au.patch +wifi-rtw89-fw-propagate-error-code-from-rtw89_h2c_tx.patch +wifi-rtw89-fw-get-sb_sel_ver-via-get_unaligned_le32.patch +wifi-rtw89-fw-add-blacklist-to-avoid-obsolete-secure.patch +wifi-rtw89-8922a-fix-incorrect-sta-id-in-eht-mu-ppdu.patch +net-pktgen-fix-access-outside-of-user-given-buffer-i.patch +power-supply-axp20x_battery-update-temp-sensor-for-a.patch +edac-ie31200-work-around-false-positive-build-warnin.patch +bpf-prevent-unsafe-access-to-the-sock-fields-in-the-.patch +i3c-master-svc-flush-fifo-before-sending-dynamic-add.patch +netdevsim-call-napi_schedule-from-a-timer-context.patch +mfd-axp20x-axp717-add-axp717_ts_pin_cfg-to-writeable.patch +eeprom-ee1004-check-chip-before-probing.patch +irqchip-riscv-imsic-separate-next-and-previous-point.patch +drm-xe-client-skip-show_run_ticks-if-unable-to-read-.patch +pci-pwrctrl-move-pci_pwrctrl_unregister-to-pci_destr.patch +drm-amd-pm-fetch-current-power-limit-from-pmfw.patch +drm-amd-display-add-support-for-disconnected-edp-str.patch +drm-amd-display-guard-against-setting-dispclk-low-wh.patch +drm-amd-display-fix-bt2020-ycbcr-limited-full-range-.patch +drm-amd-display-read-lttpr-alpm-caps-during-link-cap.patch +revert-drm-amd-display-request-hw-cursor-on-dcn3.2-w.patch +drm-amd-display-don-t-treat-wb-connector-as-physical.patch +serial-mctrl_gpio-split-disable_ms-into-sync-and-no_.patch +rdma-core-fix-best-page-size-finding-when-it-can-cro.patch +pmdomain-imx-gpcv2-use-proper-helper-for-property-de.patch +can-c_can-use-of_property_present-to-test-existence-.patch +bpf-don-t-do-clean_live_states-when-state-loop_entry.patch +bpf-copy_verifier_state-should-copy-loop_entry-field.patch +eth-mlx4-don-t-try-to-complete-xdp-frames-in-netpoll.patch +pci-fix-old_size-lower-bound-in-calculate_iosize-too.patch +acpi-hed-always-initialize-before-evged.patch +vxlan-join-leave-mc-group-after-remote-changes.patch +x86-relocs-handle-r_x86_64_rex_gotpcrelx-relocations.patch +x86-boot-disable-stack-protector-for-early-boot-code.patch +posix-timers-invoke-cond_resched-during-exit_itimers.patch +hrtimers-replace-hrtimer_clock_to_base_table-with-sw.patch +irqchip-riscv-imsic-set-irq_set_affinity-for-imsic-b.patch +media-test-drivers-vivid-don-t-call-schedule-in-loop.patch +bpf-make-every-prog-keep-a-copy-of-ctx_arg_info.patch +net-mlx5-modify-lsb-bitmask-in-temperature-event-to-.patch +net-mlx5-apply-rate-limiting-to-high-temperature-war.patch +firmware-arm_ffa-reject-higher-major-version-as-inco.patch +firmware-arm_ffa-handle-the-presence-of-host-partiti.patch +firmware-xilinx-dont-send-linux-address-to-get-fpga-.patch +io_uring-use-io_req_link_flags-more.patch +io_uring-sanitise-ring-params-earlier.patch +asoc-ops-enforce-platform-maximum-on-initial-value.patch +asoc-tas2764-add-reg-defaults-for-tas2764_int_clk_cf.patch +asoc-tas2764-mark-sw_reset-as-volatile.patch +asoc-tas2764-power-up-down-amp-on-mute-ops.patch +asoc-soc-dai-check-return-value-at-snd_soc_dai_set_t.patch +pinctrl-devicetree-do-not-goto-err-when-probing-hogs.patch +smack-recognize-ipv4-cipso-w-o-categories.patch +drm-xe-pf-release-all-vfs-configs-on-device-removal.patch +smack-revert-smackfs-added-check-catlen.patch +kunit-tool-use-qboot-on-qemu-x86_64.patch +kernfs-don-t-re-lock-kernfs_root-kernfs_rwsem-in-ker.patch +kernfs-acquire-kernfs_rwsem-in-kernfs_node_dentry.patch +kernfs-acquire-kernfs_rwsem-in-kernfs_get_parent_den.patch +kernfs-acquire-kernfs_rwsem-in-kernfs_notify_workfn.patch +media-i2c-imx219-correct-the-minimum-vblanking-value.patch +media-v4l-memset-argument-to-0-before-calling-get_mb.patch +media-stm32-csi-use-array_size-to-search-d-phy-table.patch +media-stm32-csi-add-missing-pm_runtime_put-on-error.patch +media-i2c-ov2740-free-control-handler-on-error-path.patch +libbpf-fix-ldx-stx-st-co-re-relocation-size-adjustme.patch +bnxt_en-set-npar-1.2-support-when-registering-with-f.patch +net-mlx4_core-avoid-impossible-mlx4_db_alloc-order-v.patch +drm-xe-stop-ignoring-errors-from-xe_ttm_stolen_mgr_i.patch +drm-xe-fix-xe_tile_init_noalloc-error-propagation.patch +clk-qcom-ipq5018-allow-it-to-be-bulid-on-arm32.patch +accel-amdxdna-refactor-hardware-context-destroy-rout.patch +clk-qcom-clk-alpha-pll-do-not-use-random-stack-value.patch +drm-xe-debugfs-fixed-the-return-value-of-wedged_mode.patch +drm-xe-debugfs-add-missing-xe_pm_runtime_put-in-wedg.patch +x86-ibt-handle-fineibt-in-handle_cfi_failure.patch +x86-traps-cleanup-and-robustify-decode_bug.patch +x86-boot-mark-start_secondary-with-__noendbr.patch +sched-reduce-the-default-slice-to-avoid-tasks-gettin.patch +serial-sh-sci-update-the-suspend-resume-support.patch +pinctrl-renesas-rzg2l-add-suspend-resume-support-for.patch +drm-xe-display-remove-hpd-cancel-work-sync-from-runt.patch +phy-phy-rockchip-samsung-hdptx-swap-the-definitions-.patch +phy-core-don-t-require-set_mode-callback-for-phy_get.patch +phy-exynos5-usbdrd-fix-eds-distribution-tuning-gs101.patch +soundwire-amd-change-the-soundwire-wake-enable-disab.patch +soundwire-cadence_master-set-frame-shape-and-divider.patch +jbd2-avoid-long-replay-times-due-to-high-number-or-r.patch +net-stmmac-dwmac-loongson-set-correct-tx-rx-_fifo_si.patch +scsi-usb-rename-the-reserve-and-release-constants.patch +drm-amdgpu-mes11-fix-set_hw_resources_1-calculation.patch +drm-amdkfd-fix-missing-l2-cache-info-in-topology.patch +drm-amdgpu-set-snoop-bit-for-sdma-for-mi-series.patch +drm-amd-display-pass-calculated-dram_speed_mts-to-dm.patch +drm-amd-display-remove-tf-check-for-lls-policy.patch +drm-amd-display-don-t-try-aux-transactions-on-discon.patch +drm-amdgpu-reset-psp-cmd-to-null-after-releasing-the.patch +drm-amd-pm-skip-p2s-load-for-smu-v13.0.12.patch +drm-amd-display-support-multiple-options-during-psr-.patch +revert-drm-amd-display-exit-idle-optimizations-befor.patch +drm-amd-display-fixes-for-mcache-programming-in-dml2.patch +drm-amd-display-ammend-dcpg-ip-control-sequences-to-.patch +drm-amd-display-account-for-oto-prefetch-bandwidth-w.patch +drm-amd-display-update-cr-aux-rd-interval-interpreta.patch +drm-amd-display-initial-psr_version-with-correct-set.patch +drm-amdgpu-gfx10-add-cleaner-shader-for-gfx10.1.10.patch +drm-amdgpu-skip-err_count-sysfs-creation-on-vf-unsup.patch +amdgpu-soc15-enable-asic-reset-for-dgpu-in-case-of-s.patch +drm-amd-display-reverse-the-visual-confirm-recouts.patch +drm-amd-display-increase-block_sequence-array-size.patch +drm-amd-display-use-nominal-vblank-if-provided-inste.patch +drm-amd-display-populate-register-address-for-dentis.patch +drm-amdgpu-use-active-umc-info-from-discovery.patch +drm-amdgpu-enlarge-the-vbios-binary-size-limit.patch +drm-amdkfd-have-kfd-driver-use-same-pasid-values-fro.patch +drm-amd-display-dm-drop-hw_support-check-in-amdgpu_d.patch +scsi-target-spc-fix-loop-traversal-in-spc_rsoc_get_d.patch +net-mlx5-xdp-enable-tx-side-xdp-multi-buffer-support.patch +net-mlx5-extend-ethtool-loopback-selftest-to-support.patch +net-mlx5e-set-the-tx_queue_len-for-pfifo_fast.patch +net-mlx5e-reduce-rep-rxq-depth-to-256-for-ecpf.patch +net-mlx5e-reduce-the-max-log-mpwrq-sz-for-ecpf-and-r.patch +drm-v3d-add-clock-handling.patch +xfrm-prevent-high-seq-input-in-non-esn-mode.patch +iio-adc-ad7606-protect-register-access.patch +wifi-ath12k-enable-mlo-setup-ready-and-teardown-comm.patch +wifi-ath12k-use-arvif-instead-of-link_conf-in-ath12k.patch +wifi-ath12k-fix-the-ampdu-id-fetch-in-the-hal_rx_mpd.patch +wifi-ath12k-update-the-peer-id-in-ppdu-end-user-stat.patch +mptcp-pm-userspace-flags-clearer-msg-if-no-remote-ad.patch +wifi-iwlwifi-use-correct-imr-dump-variable.patch +wifi-iwlwifi-don-t-warn-during-reprobe.patch +wifi-mac80211-always-send-max-agg-subframe-num-in-st.patch +wifi-mac80211-don-t-unconditionally-call-drv_mgd_com.patch +wifi-mac80211-remove-misplaced-drv_mgd_complete_tx-c.patch +wifi-mac80211-set-ieee80211_prep_tx_info-link_id-upo.patch +wifi-mac80211-add-ht-and-vht-basic-set-verification.patch +wifi-mac80211-drop-cooked-monitor-support.patch +net-fec-refactor-mac-reset-to-function.patch +powerpc-pseries-iommu-memory-notifier-incorrectly-ad.patch +powerpc-pseries-iommu-create-ddw-for-devices-with-dm.patch +arch-powerpc-perf-check-the-instruction-type-before-.patch +ip-fib_rules-fetch-net-from-fib_rule-in-fib-46-_rule.patch +r8152-add-vendor-device-id-pair-for-dell-alienware-a.patch +s390-crash-use-note-name-macros.patch +iio-adc-ad7944-don-t-use-storagebits-for-sizing.patch +igc-avoid-unnecessary-link-down-event-in-xdp_setup_p.patch +pstore-change-kmsg_bytes-storage-size-to-u32.patch +leds-trigger-netdev-configure-led-blink-interval-for.patch +net-ethtool-prevent-flow-steering-to-rss-contexts-wh.patch +ext4-don-t-write-back-data-before-punch-hole-in-nojo.patch +ext4-remove-writable-userspace-mappings-before-trunc.patch +wifi-rtw88-fix-rtw_update_sta_info-for-rtl8814au.patch +wifi-rtw88-extend-rtw_fw_send_ra_info-for-rtl8814au.patch +wifi-rtw88-fix-download_firmware_validate-for-rtl881.patch +wifi-rtw88-fix-__rtw_download_firmware-for-rtl8814au.patch +wifi-rtw89-coex-assign-value-over-than-0-to-avoid-fi.patch +wifi-rtw89-fw-validate-multi-firmware-header-before-.patch +wifi-rtw89-fw-validate-multi-firmware-header-before-.patch-7297 +wifi-rtw89-call-power_on-ahead-before-selecting-firm.patch +iio-dac-ad3552r-hs-use-instruction-mode-for-configur.patch +iio-dac-adi-axi-dac-add-bus-mode-setup.patch +clk-qcom-camcc-sm8250-use-clk_rcg2_shared_ops-for-so.patch +netdevsim-allow-normal-queue-reset-while-down.patch +net-page_pool-avoid-false-positive-warning-if-napi-w.patch +tools-power-turbostat-clustered-uncore-mhz-counters-.patch +hwmon-xgene-hwmon-use-appropriate-type-for-the-laten.patch +drm-xe-fix-pvc-rpe-and-rpa-information.patch +f2fs-introduce-f2fs_base_attr-for-global-sysfs-entri.patch +media-qcom-camss-csid-only-add-tpg-v4l2-ctrl-if-tpg-.patch +media-qcom-camss-add-default-case-in-vfe_src_pad_cod.patch +drm-rockchip-vop2-improve-display-modes-handling-on-.patch +eth-fbnic-set-iff_unicast_flt-to-avoid-enabling-prom.patch +tools-ynl-gen-don-t-output-external-constants.patch +net-mlx5e-avoid-warn_on-when-configuring-mqprio-with.patch +cpufreq-amd-pstate-remove-unnecessary-driver_lock-in.patch +vxlan-annotate-fdb-data-races.patch +ipv4-ip_gre-fix-set-but-not-used-warning-in-ipgre_er.patch +r8169-don-t-scan-phy-addresses-0.patch +net-flush_backlog-small-changes.patch +bridge-mdb-allow-replace-of-a-host-joined-group.patch +ice-init-flow-director-before-rdma.patch +ice-treat-dyn_allowed-only-as-suggestion.patch +rcu-handle-quiescent-states-for-preempt_rcu-n-preemp.patch +rcu-handle-unstable-rdp-in-rcu_read_unlock_strict.patch +rcu-fix-header-guard-for-rcu_all_qs.patch +perf-avoid-the-read-if-the-count-is-already-updated.patch +ice-count-combined-queues-using-rx-tx-count.patch +drm-xe-relay-don-t-use-gfp_kernel-for-new-transactio.patch +net-mana-fix-warning-in-the-writer-of-client-oob.patch +scsi-lpfc-handle-duplicate-d_ids-in-ndlp-search-by-d.patch +scsi-lpfc-ignore-ndlp-rport-mismatch-in-dev_loss_tmo.patch +scsi-lpfc-free-phba-irq-in-lpfc_sli4_enable_msi-when.patch +scsi-lpfc-reduce-log-message-generation-during-els-r.patch +scsi-st-restore-some-drive-settings-after-reset.patch +wifi-ath12k-avoid-napi_sync-before-napi_enable.patch +hid-usbkbd-fix-the-bit-shift-number-for-led_kana.patch +arm64-zynqmp-add-clock-output-names-property-in-cloc.patch +asoc-codecs-pcm3168a-allow-for-24-bit-in-provider-mo.patch +asoc-rt722-sdca-add-some-missing-readable-registers.patch +irqchip-riscv-aplic-add-support-for-hart-indexes.patch +dm-vdo-vio-pool-allow-variable-sized-metadata-vios.patch +dm-vdo-indexer-prevent-unterminated-string-warning.patch +dm-vdo-use-a-short-static-string-for-thread-name-pre.patch +drm-ast-find-vbios-mode-from-regular-display-size.patch +bpf-use-kallsyms-to-find-the-function-name-of-a-stru.patch +bpftool-fix-readlink-usage-in-get_fd_type.patch +firmware-arm_scmi-relax-duplicate-name-constraint-ac.patch +perf-amd-ibs-fix-perf_ibs_op.cnt_mask-for-curcnt.patch +perf-amd-ibs-fix-config-to-sample-period-calculation.patch +clk-renesas-rzg2l-cpg-refactor-runtime-pm-clock-vali.patch +wifi-rtl8xxxu-retry-firmware-download-on-error.patch +wifi-rtw88-don-t-use-static-local-variable-in-rtw882.patch +wifi-rtw89-add-wiphy_lock-to-work-that-isn-t-held-wi.patch +spi-zynqmp-gqspi-always-acknowledge-interrupts.patch +regulator-ad5398-add-device-tree-support.patch +wifi-ath12k-fix-ath12k_hal_tx_cmd_ext_desc_setup-inf.patch +accel-qaic-mask-out-sr-iov-pci-resources.patch +drm-xe-pf-reset-guc-vf-config-when-unprovisioning-cr.patch +wifi-ath9k-return-by-of_get_mac_address.patch +wifi-ath12k-fetch-regdb.bin-file-from-board-2.bin.patch +drm-xe-pf-move-vfs-reprovisioning-to-worker.patch +wifi-ath12k-fix-end-offset-bit-definition-in-monitor.patch +wifi-ath12k-report-station-mode-receive-rate-for-iee.patch +wifi-ath12k-report-station-mode-transmit-rate.patch +drm-bridge-adv7511-fill-stream-capabilities.patch +drm-nouveau-fix-the-broken-marco-gsp_msg_max_size.patch +wifi-ath11k-use-dma_alloc_noncoherent-for-rx_tid-buf.patch +drm-ast-hide-gens-1-to-3-tx-detection-in-branch.patch +drm-xe-move-suballocator-init-to-after-display-init.patch +drm-xe-do-not-attempt-to-bootstrap-vf-in-execlists-m.patch +wifi-rtw89-coex-separated-wi-fi-connecting-event-fro.patch +wifi-rtw89-coex-add-protect-to-avoid-a2dp-lag-while-.patch +drm-xe-sa-always-call-drm_suballoc_manager_fini.patch +drm-xe-vf-perform-early-gt-mmio-initialization-to-re.patch +drm-xe-always-setup-gt-mmio-adjustment-data.patch +drm-xe-guc-drop-error-messages-about-missing-guc-log.patch +drm-xe-reject-bo-eviction-if-bo-is-bound-to-current-.patch +drm-atomic-clarify-the-rules-around-drm_atomic_state.patch +drm-buddy-fix-issue-that-force_merge-cannot-free-all.patch +drm-xe-add-locks-in-gtidle-code.patch +drm-panel-edp-add-starry-116khd024006.patch +drm-add-valid-clones-check.patch +i3c-master-svc-fix-implicit-fallthrough-in-svc_i3c_m.patch +asoc-sma1307-fix-error-handling-in-sma1307_setting_l.patch +pinctrl-tegra-fix-off-by-one-in-tegra_pinctrl_get_gr.patch +watchdog-aspeed-fix-64-bit-division.patch +drm-amdkfd-correct-f8_mode-for-gfx950.patch +drm-gem-internally-test-import_attach-for-imported-o.patch +virtgpu-don-t-reset-on-shutdown.patch +x86-mm-init-handle-the-special-case-of-device-privat.patch +bpf-abort-verification-if-env-cur_state-loop_entry-n.patch +ipv6-remove-leftover-ip6-cookie-initializer.patch +kernfs-use-rcu-to-access-kernfs_node-parent.patch +kernfs-use-rcu-to-access-kernfs_node-name.patch +kernfs-drop-kernfs_rwsem-while-invoking-lookup_posit.patch +serial-sh-sci-save-and-restore-more-registers.patch +drm-amd-display-exit-idle-optimizations-before-acces.patch +drm-amdkfd-fix-error-handling-for-missing-pasid-in-k.patch +drm-amdkfd-fix-pasid-value-leak.patch +wifi-mac80211-add-counter-for-all-monitor-interfaces.patch +hid-kconfig-add-leds_class_multicolor-dependency-to-.patch +net-sysfs-restore-behavior-for-not-running-devices.patch +asoc-imx-card-adjust-over-allocation-of-memory-in-im.patch +book3s64-radix-fix-compile-errors-when-config_arch_w.patch +pinctrl-meson-define-the-pull-up-down-resistor-value.patch +smb-server-smb2pdu-check-return-value-of-xa_store.patch +platform-x86-intel-hid-add-pantherlake-support.patch +platform-x86-asus-wmi-disable-oobe-state-after-resum.patch +platform-x86-ideapad-laptop-add-support-for-some-new.patch +asoc-cs42l43-disable-headphone-clamps-during-type-de.patch +asoc-intel-bytcr_rt5640-add-dmi-quirk-for-acer-aspir.patch +alsa-hda-realtek-add-quirk-for-hp-spectre-x360-15-df.patch +drm-ttm-fix-the-warning-for-hit_low-and-evict_low.patch +nvme-pci-add-quirks-for-device-126f-1001.patch +nvme-pci-add-quirks-for-wdc-blue-sn550-15b7-5009.patch +alsa-usb-audio-fix-duplicated-name-in-midi-substream.patch +nvmet-tcp-don-t-restore-null-sk_state_change.patch +io_uring-fdinfo-annotate-racy-sq-cq-head-tail-reads.patch +cifs-fix-and-improve-cifs_query_path_info-and-cifs_q.patch +cifs-fix-changing-times-and-read-only-attr-over-smb1.patch +asoc-intel-sdw_utils-add-volume-limit-to-cs42l43-spe.patch +asoc-intel-sdw_utils-add-volume-limit-to-cs35l56-spe.patch +iio-accel-fxls8962af-fix-wakeup-source-leaks-on-devi.patch +iio-adc-qcom-spmi-iadc-fix-wakeup-source-leaks-on-de.patch +iio-imu-st_lsm6dsx-fix-wakeup-source-leaks-on-device.patch +btrfs-compression-adjust-cb-compressed_folios-alloca.patch +btrfs-correct-the-order-of-prelim_ref-arguments-in-b.patch +btrfs-handle-empty-eb-folios-in-num_extent_folios.patch +btrfs-avoid-null-pointer-dereference-if-no-valid-csu.patch +tools-ynl-gen-validate-0-len-strings-from-kernel.patch +block-only-update-request-sector-if-needed.patch +wifi-iwlwifi-add-support-for-killer-on-mtl.patch +x86-kconfig-make-cfi_auto_default-depend-on-rust-or-.patch +xenbus-allow-pvh-dom0-a-non-local-xenstore.patch +drm-amd-display-call-fp-protect-before-mode-programm.patch +__legitimize_mnt-check-for-mnt_sync_umount-should-be.patch diff --git a/queue-6.14/smack-recognize-ipv4-cipso-w-o-categories.patch b/queue-6.14/smack-recognize-ipv4-cipso-w-o-categories.patch new file mode 100644 index 0000000000..5925820532 --- /dev/null +++ b/queue-6.14/smack-recognize-ipv4-cipso-w-o-categories.patch @@ -0,0 +1,75 @@ +From 58bcca60bee859857e868dc29ab80b343f64e609 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 17 Jan 2025 02:40:34 +0300 +Subject: smack: recognize ipv4 CIPSO w/o categories + +From: Konstantin Andreev + +[ Upstream commit a158a937d864d0034fea14913c1f09c6d5f574b8 ] + +If SMACK label has CIPSO representation w/o categories, e.g.: + +| # cat /smack/cipso2 +| foo 10 +| @ 250/2 +| ... + +then SMACK does not recognize such CIPSO in input ipv4 packets +and substitues '*' label instead. Audit records may look like + +| lsm=SMACK fn=smack_socket_sock_rcv_skb action=denied +| subject="*" object="_" requested=w pid=0 comm="swapper/1" ... + +This happens in two steps: + +1) security/smack/smackfs.c`smk_set_cipso + does not clear NETLBL_SECATTR_MLS_CAT + from (struct smack_known *)skp->smk_netlabel.flags + on assigning CIPSO w/o categories: + +| rcu_assign_pointer(skp->smk_netlabel.attr.mls.cat, ncats.attr.mls.cat); +| skp->smk_netlabel.attr.mls.lvl = ncats.attr.mls.lvl; + +2) security/smack/smack_lsm.c`smack_from_secattr + can not match skp->smk_netlabel with input packet's + struct netlbl_lsm_secattr *sap + because sap->flags have not NETLBL_SECATTR_MLS_CAT (what is correct) + but skp->smk_netlabel.flags have (what is incorrect): + +| if ((sap->flags & NETLBL_SECATTR_MLS_CAT) == 0) { +| if ((skp->smk_netlabel.flags & +| NETLBL_SECATTR_MLS_CAT) == 0) +| found = 1; +| break; +| } + +This commit sets/clears NETLBL_SECATTR_MLS_CAT in +skp->smk_netlabel.flags according to the presense of CIPSO categories. +The update of smk_netlabel is not atomic, so input packets processing +still may be incorrect during short time while update proceeds. + +Signed-off-by: Konstantin Andreev +Signed-off-by: Casey Schaufler +Signed-off-by: Sasha Levin +--- + security/smack/smackfs.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c +index 357188f764ce1..d8f9922804974 100644 +--- a/security/smack/smackfs.c ++++ b/security/smack/smackfs.c +@@ -915,6 +915,10 @@ static ssize_t smk_set_cipso(struct file *file, const char __user *buf, + if (rc >= 0) { + old_cat = skp->smk_netlabel.attr.mls.cat; + rcu_assign_pointer(skp->smk_netlabel.attr.mls.cat, ncats.attr.mls.cat); ++ if (ncats.attr.mls.cat) ++ skp->smk_netlabel.flags |= NETLBL_SECATTR_MLS_CAT; ++ else ++ skp->smk_netlabel.flags &= ~(u32)NETLBL_SECATTR_MLS_CAT; + skp->smk_netlabel.attr.mls.lvl = ncats.attr.mls.lvl; + synchronize_rcu(); + netlbl_catmap_free(old_cat); +-- +2.39.5 + diff --git a/queue-6.14/smack-revert-smackfs-added-check-catlen.patch b/queue-6.14/smack-revert-smackfs-added-check-catlen.patch new file mode 100644 index 0000000000..34b39f28ce --- /dev/null +++ b/queue-6.14/smack-revert-smackfs-added-check-catlen.patch @@ -0,0 +1,64 @@ +From 284ccaa27fe76bf1b326429b71014a6e8029361b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 17 Jan 2025 02:40:33 +0300 +Subject: smack: Revert "smackfs: Added check catlen" + +From: Konstantin Andreev + +[ Upstream commit c7fb50cecff9cad19fdac5b37337eae4e42b94c7 ] + +This reverts commit ccfd889acb06eab10b98deb4b5eef0ec74157ea0 + +The indicated commit +* does not describe the problem that change tries to solve +* has programming issues +* introduces a bug: forever clears NETLBL_SECATTR_MLS_CAT + in (struct smack_known *)skp->smk_netlabel.flags + +Reverting the commit to reapproach original problem + +Signed-off-by: Konstantin Andreev +Signed-off-by: Casey Schaufler +Signed-off-by: Sasha Levin +--- + security/smack/smackfs.c | 17 +++-------------- + 1 file changed, 3 insertions(+), 14 deletions(-) + +diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c +index d8f9922804974..a7886cfc9dc3a 100644 +--- a/security/smack/smackfs.c ++++ b/security/smack/smackfs.c +@@ -812,7 +812,7 @@ static int smk_open_cipso(struct inode *inode, struct file *file) + static ssize_t smk_set_cipso(struct file *file, const char __user *buf, + size_t count, loff_t *ppos, int format) + { +- struct netlbl_lsm_catmap *old_cat, *new_cat = NULL; ++ struct netlbl_lsm_catmap *old_cat; + struct smack_known *skp; + struct netlbl_lsm_secattr ncats; + char mapcatset[SMK_CIPSOLEN]; +@@ -899,19 +899,8 @@ static ssize_t smk_set_cipso(struct file *file, const char __user *buf, + + smack_catset_bit(cat, mapcatset); + } +- ncats.flags = 0; +- if (catlen == 0) { +- ncats.attr.mls.cat = NULL; +- ncats.attr.mls.lvl = maplevel; +- new_cat = netlbl_catmap_alloc(GFP_ATOMIC); +- if (new_cat) +- new_cat->next = ncats.attr.mls.cat; +- ncats.attr.mls.cat = new_cat; +- skp->smk_netlabel.flags &= ~(1U << 3); +- rc = 0; +- } else { +- rc = smk_netlbl_mls(maplevel, mapcatset, &ncats, SMK_CIPSOLEN); +- } ++ ++ rc = smk_netlbl_mls(maplevel, mapcatset, &ncats, SMK_CIPSOLEN); + if (rc >= 0) { + old_cat = skp->smk_netlabel.attr.mls.cat; + rcu_assign_pointer(skp->smk_netlabel.attr.mls.cat, ncats.attr.mls.cat); +-- +2.39.5 + diff --git a/queue-6.14/smb-client-store-original-io-parameters-and-prevent-.patch b/queue-6.14/smb-client-store-original-io-parameters-and-prevent-.patch new file mode 100644 index 0000000000..6a43c1a0ad --- /dev/null +++ b/queue-6.14/smb-client-store-original-io-parameters-and-prevent-.patch @@ -0,0 +1,211 @@ +From c7211a2fdb101bc160fe645622db54ba67bf2a52 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 31 Mar 2025 21:33:14 +0800 +Subject: smb: client: Store original IO parameters and prevent zero IO sizes + +From: Wang Zhaolong + +[ Upstream commit 287906b20035a04a234d1a3c64f760a5678387be ] + +During mount option processing and negotiation with the server, the +original user-specified rsize/wsize values were being modified directly. +This makes it impossible to recover these values after a connection +reset, leading to potential degraded performance after reconnection. + +The other problem is that When negotiating read and write sizes, there are +cases where the negotiated values might calculate to zero, especially +during reconnection when server->max_read or server->max_write might be +reset. In general, these values come from the negotiation response. +According to MS-SMB2 specification, these values should be at least 65536 +bytes. + +This patch improves IO parameter handling: + +1. Adds vol_rsize and vol_wsize fields to store the original user-specified + values separately from the negotiated values +2. Uses got_rsize/got_wsize flags to determine if values were + user-specified rather than checking for non-zero values, which is more + reliable +3. Adds a prevent_zero_iosize() helper function to ensure IO sizes are + never negotiated down to zero, which could happen in edge cases like + when server->max_read/write is zero + +The changes make the CIFS client more resilient to unusual server +responses and reconnection scenarios, preventing potential failures +when IO sizes are calculated to be zero. + +Signed-off-by: Wang Zhaolong +Signed-off-by: Steve French +Signed-off-by: Sasha Levin +--- + fs/smb/client/fs_context.c | 2 ++ + fs/smb/client/fs_context.h | 3 +++ + fs/smb/client/smb1ops.c | 6 +++--- + fs/smb/client/smb2ops.c | 27 +++++++++++++++++++-------- + fs/smb/common/smb2pdu.h | 3 +++ + 5 files changed, 30 insertions(+), 11 deletions(-) + +diff --git a/fs/smb/client/fs_context.c b/fs/smb/client/fs_context.c +index e38521a713a6b..00af8dd5aa689 100644 +--- a/fs/smb/client/fs_context.c ++++ b/fs/smb/client/fs_context.c +@@ -1327,6 +1327,7 @@ static int smb3_fs_context_parse_param(struct fs_context *fc, + case Opt_rsize: + ctx->rsize = result.uint_32; + ctx->got_rsize = true; ++ ctx->vol_rsize = ctx->rsize; + break; + case Opt_wsize: + ctx->wsize = result.uint_32; +@@ -1342,6 +1343,7 @@ static int smb3_fs_context_parse_param(struct fs_context *fc, + ctx->wsize, PAGE_SIZE); + } + } ++ ctx->vol_wsize = ctx->wsize; + break; + case Opt_acregmax: + if (result.uint_32 > CIFS_MAX_ACTIMEO / HZ) { +diff --git a/fs/smb/client/fs_context.h b/fs/smb/client/fs_context.h +index 881bfc08667e7..7516ccdc69c71 100644 +--- a/fs/smb/client/fs_context.h ++++ b/fs/smb/client/fs_context.h +@@ -279,6 +279,9 @@ struct smb3_fs_context { + bool use_client_guid:1; + /* reuse existing guid for multichannel */ + u8 client_guid[SMB2_CLIENT_GUID_SIZE]; ++ /* User-specified original r/wsize value */ ++ unsigned int vol_rsize; ++ unsigned int vol_wsize; + unsigned int bsize; + unsigned int rasize; + unsigned int rsize; +diff --git a/fs/smb/client/smb1ops.c b/fs/smb/client/smb1ops.c +index e28cdaca47e12..73a689b4ccdff 100644 +--- a/fs/smb/client/smb1ops.c ++++ b/fs/smb/client/smb1ops.c +@@ -437,8 +437,8 @@ cifs_negotiate_wsize(struct cifs_tcon *tcon, struct smb3_fs_context *ctx) + unsigned int wsize; + + /* start with specified wsize, or default */ +- if (ctx->wsize) +- wsize = ctx->wsize; ++ if (ctx->got_wsize) ++ wsize = ctx->vol_wsize; + else if (tcon->unix_ext && (unix_cap & CIFS_UNIX_LARGE_WRITE_CAP)) + wsize = CIFS_DEFAULT_IOSIZE; + else +@@ -490,7 +490,7 @@ cifs_negotiate_rsize(struct cifs_tcon *tcon, struct smb3_fs_context *ctx) + else + defsize = server->maxBuf - sizeof(READ_RSP); + +- rsize = ctx->rsize ? ctx->rsize : defsize; ++ rsize = ctx->got_rsize ? ctx->vol_rsize : defsize; + + /* + * no CAP_LARGE_READ_X? Then MS-CIFS states that we must limit this to +diff --git a/fs/smb/client/smb2ops.c b/fs/smb/client/smb2ops.c +index 6f89e087629fe..6795970d4de6e 100644 +--- a/fs/smb/client/smb2ops.c ++++ b/fs/smb/client/smb2ops.c +@@ -467,6 +467,17 @@ smb2_negotiate(const unsigned int xid, + return rc; + } + ++static inline unsigned int ++prevent_zero_iosize(unsigned int size, const char *type) ++{ ++ if (size == 0) { ++ cifs_dbg(VFS, "SMB: Zero %ssize calculated, using minimum value %u\n", ++ type, CIFS_MIN_DEFAULT_IOSIZE); ++ return CIFS_MIN_DEFAULT_IOSIZE; ++ } ++ return size; ++} ++ + static unsigned int + smb2_negotiate_wsize(struct cifs_tcon *tcon, struct smb3_fs_context *ctx) + { +@@ -474,12 +485,12 @@ smb2_negotiate_wsize(struct cifs_tcon *tcon, struct smb3_fs_context *ctx) + unsigned int wsize; + + /* start with specified wsize, or default */ +- wsize = ctx->wsize ? ctx->wsize : CIFS_DEFAULT_IOSIZE; ++ wsize = ctx->got_wsize ? ctx->vol_wsize : CIFS_DEFAULT_IOSIZE; + wsize = min_t(unsigned int, wsize, server->max_write); + if (!(server->capabilities & SMB2_GLOBAL_CAP_LARGE_MTU)) + wsize = min_t(unsigned int, wsize, SMB2_MAX_BUFFER_SIZE); + +- return wsize; ++ return prevent_zero_iosize(wsize, "w"); + } + + static unsigned int +@@ -489,7 +500,7 @@ smb3_negotiate_wsize(struct cifs_tcon *tcon, struct smb3_fs_context *ctx) + unsigned int wsize; + + /* start with specified wsize, or default */ +- wsize = ctx->wsize ? ctx->wsize : SMB3_DEFAULT_IOSIZE; ++ wsize = ctx->got_wsize ? ctx->vol_wsize : SMB3_DEFAULT_IOSIZE; + wsize = min_t(unsigned int, wsize, server->max_write); + #ifdef CONFIG_CIFS_SMB_DIRECT + if (server->rdma) { +@@ -511,7 +522,7 @@ smb3_negotiate_wsize(struct cifs_tcon *tcon, struct smb3_fs_context *ctx) + if (!(server->capabilities & SMB2_GLOBAL_CAP_LARGE_MTU)) + wsize = min_t(unsigned int, wsize, SMB2_MAX_BUFFER_SIZE); + +- return wsize; ++ return prevent_zero_iosize(wsize, "w"); + } + + static unsigned int +@@ -521,13 +532,13 @@ smb2_negotiate_rsize(struct cifs_tcon *tcon, struct smb3_fs_context *ctx) + unsigned int rsize; + + /* start with specified rsize, or default */ +- rsize = ctx->rsize ? ctx->rsize : CIFS_DEFAULT_IOSIZE; ++ rsize = ctx->got_rsize ? ctx->vol_rsize : CIFS_DEFAULT_IOSIZE; + rsize = min_t(unsigned int, rsize, server->max_read); + + if (!(server->capabilities & SMB2_GLOBAL_CAP_LARGE_MTU)) + rsize = min_t(unsigned int, rsize, SMB2_MAX_BUFFER_SIZE); + +- return rsize; ++ return prevent_zero_iosize(rsize, "r"); + } + + static unsigned int +@@ -537,7 +548,7 @@ smb3_negotiate_rsize(struct cifs_tcon *tcon, struct smb3_fs_context *ctx) + unsigned int rsize; + + /* start with specified rsize, or default */ +- rsize = ctx->rsize ? ctx->rsize : SMB3_DEFAULT_IOSIZE; ++ rsize = ctx->got_rsize ? ctx->vol_rsize : SMB3_DEFAULT_IOSIZE; + rsize = min_t(unsigned int, rsize, server->max_read); + #ifdef CONFIG_CIFS_SMB_DIRECT + if (server->rdma) { +@@ -560,7 +571,7 @@ smb3_negotiate_rsize(struct cifs_tcon *tcon, struct smb3_fs_context *ctx) + if (!(server->capabilities & SMB2_GLOBAL_CAP_LARGE_MTU)) + rsize = min_t(unsigned int, rsize, SMB2_MAX_BUFFER_SIZE); + +- return rsize; ++ return prevent_zero_iosize(rsize, "r"); + } + + /* +diff --git a/fs/smb/common/smb2pdu.h b/fs/smb/common/smb2pdu.h +index 12f0013334057..f79a5165a7cc6 100644 +--- a/fs/smb/common/smb2pdu.h ++++ b/fs/smb/common/smb2pdu.h +@@ -95,6 +95,9 @@ + */ + #define SMB3_DEFAULT_IOSIZE (4 * 1024 * 1024) + ++/* According to MS-SMB2 specification The minimum recommended value is 65536.*/ ++#define CIFS_MIN_DEFAULT_IOSIZE (65536) ++ + /* + * SMB2 Header Definition + * +-- +2.39.5 + diff --git a/queue-6.14/smb-server-smb2pdu-check-return-value-of-xa_store.patch b/queue-6.14/smb-server-smb2pdu-check-return-value-of-xa_store.patch new file mode 100644 index 0000000000..7e9201dc43 --- /dev/null +++ b/queue-6.14/smb-server-smb2pdu-check-return-value-of-xa_store.patch @@ -0,0 +1,50 @@ +From ae258004247523f3ca610dda51f9843c2c707423 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 16 Apr 2025 20:26:25 +0100 +Subject: smb: server: smb2pdu: check return value of xa_store() + +From: Salah Triki + +[ Upstream commit af5226abb40cae959f424f7ca614787a1c87ce48 ] + +xa_store() may fail so check its return value and return error code if +error occurred. + +Signed-off-by: Salah Triki +Acked-by: Namjae Jeon +Signed-off-by: Steve French +Signed-off-by: Sasha Levin +--- + fs/smb/server/smb2pdu.c | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +diff --git a/fs/smb/server/smb2pdu.c b/fs/smb/server/smb2pdu.c +index c2603c398a467..f2a2be8467c66 100644 +--- a/fs/smb/server/smb2pdu.c ++++ b/fs/smb/server/smb2pdu.c +@@ -1450,7 +1450,7 @@ static int ntlm_authenticate(struct ksmbd_work *work, + { + struct ksmbd_conn *conn = work->conn; + struct ksmbd_session *sess = work->sess; +- struct channel *chann = NULL; ++ struct channel *chann = NULL, *old; + struct ksmbd_user *user; + u64 prev_id; + int sz, rc; +@@ -1562,7 +1562,12 @@ static int ntlm_authenticate(struct ksmbd_work *work, + return -ENOMEM; + + chann->conn = conn; +- xa_store(&sess->ksmbd_chann_list, (long)conn, chann, KSMBD_DEFAULT_GFP); ++ old = xa_store(&sess->ksmbd_chann_list, (long)conn, chann, ++ KSMBD_DEFAULT_GFP); ++ if (xa_is_err(old)) { ++ kfree(chann); ++ return xa_err(old); ++ } + } + } + +-- +2.39.5 + diff --git a/queue-6.14/soc-apple-rtkit-implement-oslog-buffers-properly.patch b/queue-6.14/soc-apple-rtkit-implement-oslog-buffers-properly.patch new file mode 100644 index 0000000000..13493222ba --- /dev/null +++ b/queue-6.14/soc-apple-rtkit-implement-oslog-buffers-properly.patch @@ -0,0 +1,156 @@ +From fc1272c4bfbd85d8b8f503ff4856fd0e525bfe5a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 26 Feb 2025 19:00:04 +0000 +Subject: soc: apple: rtkit: Implement OSLog buffers properly + +From: Hector Martin + +[ Upstream commit a06398687065e0c334dc5fc4d2778b5b87292e43 ] + +Apparently nobody can figure out where the old logic came from, but it +seems like it has never been actually used on any supported firmware to +this day. OSLog buffers were apparently never requested. + +But starting with 13.3, we actually need this implemented properly for +MTP (and later AOP) to work, so let's actually do that. + +Signed-off-by: Hector Martin +Reviewed-by: Alyssa Rosenzweig +Link: https://lore.kernel.org/r/20250226-apple-soc-misc-v2-2-c3ec37f9021b@svenpeter.dev +Signed-off-by: Sven Peter +Signed-off-by: Sasha Levin +--- + drivers/soc/apple/rtkit-internal.h | 1 + + drivers/soc/apple/rtkit.c | 56 ++++++++++++++++++------------ + 2 files changed, 35 insertions(+), 22 deletions(-) + +diff --git a/drivers/soc/apple/rtkit-internal.h b/drivers/soc/apple/rtkit-internal.h +index 27c9fa745fd52..b8d5244678f01 100644 +--- a/drivers/soc/apple/rtkit-internal.h ++++ b/drivers/soc/apple/rtkit-internal.h +@@ -44,6 +44,7 @@ struct apple_rtkit { + + struct apple_rtkit_shmem ioreport_buffer; + struct apple_rtkit_shmem crashlog_buffer; ++ struct apple_rtkit_shmem oslog_buffer; + + struct apple_rtkit_shmem syslog_buffer; + char *syslog_msg_buffer; +diff --git a/drivers/soc/apple/rtkit.c b/drivers/soc/apple/rtkit.c +index 00d59a81db88b..45ccbe2cbcd63 100644 +--- a/drivers/soc/apple/rtkit.c ++++ b/drivers/soc/apple/rtkit.c +@@ -66,8 +66,9 @@ enum { + #define APPLE_RTKIT_SYSLOG_MSG_SIZE GENMASK_ULL(31, 24) + + #define APPLE_RTKIT_OSLOG_TYPE GENMASK_ULL(63, 56) +-#define APPLE_RTKIT_OSLOG_INIT 1 +-#define APPLE_RTKIT_OSLOG_ACK 3 ++#define APPLE_RTKIT_OSLOG_BUFFER_REQUEST 1 ++#define APPLE_RTKIT_OSLOG_SIZE GENMASK_ULL(55, 36) ++#define APPLE_RTKIT_OSLOG_IOVA GENMASK_ULL(35, 0) + + #define APPLE_RTKIT_MIN_SUPPORTED_VERSION 11 + #define APPLE_RTKIT_MAX_SUPPORTED_VERSION 12 +@@ -251,15 +252,21 @@ static int apple_rtkit_common_rx_get_buffer(struct apple_rtkit *rtk, + struct apple_rtkit_shmem *buffer, + u8 ep, u64 msg) + { +- size_t n_4kpages = FIELD_GET(APPLE_RTKIT_BUFFER_REQUEST_SIZE, msg); + u64 reply; + int err; + ++ /* The different size vs. IOVA shifts look odd but are indeed correct this way */ ++ if (ep == APPLE_RTKIT_EP_OSLOG) { ++ buffer->size = FIELD_GET(APPLE_RTKIT_OSLOG_SIZE, msg); ++ buffer->iova = FIELD_GET(APPLE_RTKIT_OSLOG_IOVA, msg) << 12; ++ } else { ++ buffer->size = FIELD_GET(APPLE_RTKIT_BUFFER_REQUEST_SIZE, msg) << 12; ++ buffer->iova = FIELD_GET(APPLE_RTKIT_BUFFER_REQUEST_IOVA, msg); ++ } ++ + buffer->buffer = NULL; + buffer->iomem = NULL; + buffer->is_mapped = false; +- buffer->iova = FIELD_GET(APPLE_RTKIT_BUFFER_REQUEST_IOVA, msg); +- buffer->size = n_4kpages << 12; + + dev_dbg(rtk->dev, "RTKit: buffer request for 0x%zx bytes at %pad\n", + buffer->size, &buffer->iova); +@@ -284,11 +291,21 @@ static int apple_rtkit_common_rx_get_buffer(struct apple_rtkit *rtk, + } + + if (!buffer->is_mapped) { +- reply = FIELD_PREP(APPLE_RTKIT_SYSLOG_TYPE, +- APPLE_RTKIT_BUFFER_REQUEST); +- reply |= FIELD_PREP(APPLE_RTKIT_BUFFER_REQUEST_SIZE, n_4kpages); +- reply |= FIELD_PREP(APPLE_RTKIT_BUFFER_REQUEST_IOVA, +- buffer->iova); ++ /* oslog uses different fields and needs a shifted IOVA instead of size */ ++ if (ep == APPLE_RTKIT_EP_OSLOG) { ++ reply = FIELD_PREP(APPLE_RTKIT_OSLOG_TYPE, ++ APPLE_RTKIT_OSLOG_BUFFER_REQUEST); ++ reply |= FIELD_PREP(APPLE_RTKIT_OSLOG_SIZE, buffer->size); ++ reply |= FIELD_PREP(APPLE_RTKIT_OSLOG_IOVA, ++ buffer->iova >> 12); ++ } else { ++ reply = FIELD_PREP(APPLE_RTKIT_SYSLOG_TYPE, ++ APPLE_RTKIT_BUFFER_REQUEST); ++ reply |= FIELD_PREP(APPLE_RTKIT_BUFFER_REQUEST_SIZE, ++ buffer->size >> 12); ++ reply |= FIELD_PREP(APPLE_RTKIT_BUFFER_REQUEST_IOVA, ++ buffer->iova); ++ } + apple_rtkit_send_message(rtk, ep, reply, NULL, false); + } + +@@ -482,25 +499,18 @@ static void apple_rtkit_syslog_rx(struct apple_rtkit *rtk, u64 msg) + } + } + +-static void apple_rtkit_oslog_rx_init(struct apple_rtkit *rtk, u64 msg) +-{ +- u64 ack; +- +- dev_dbg(rtk->dev, "RTKit: oslog init: msg: 0x%llx\n", msg); +- ack = FIELD_PREP(APPLE_RTKIT_OSLOG_TYPE, APPLE_RTKIT_OSLOG_ACK); +- apple_rtkit_send_message(rtk, APPLE_RTKIT_EP_OSLOG, ack, NULL, false); +-} +- + static void apple_rtkit_oslog_rx(struct apple_rtkit *rtk, u64 msg) + { + u8 type = FIELD_GET(APPLE_RTKIT_OSLOG_TYPE, msg); + + switch (type) { +- case APPLE_RTKIT_OSLOG_INIT: +- apple_rtkit_oslog_rx_init(rtk, msg); ++ case APPLE_RTKIT_OSLOG_BUFFER_REQUEST: ++ apple_rtkit_common_rx_get_buffer(rtk, &rtk->oslog_buffer, ++ APPLE_RTKIT_EP_OSLOG, msg); + break; + default: +- dev_warn(rtk->dev, "RTKit: Unknown oslog message: %llx\n", msg); ++ dev_warn(rtk->dev, "RTKit: Unknown oslog message: %llx\n", ++ msg); + } + } + +@@ -710,6 +720,7 @@ int apple_rtkit_reinit(struct apple_rtkit *rtk) + + apple_rtkit_free_buffer(rtk, &rtk->ioreport_buffer); + apple_rtkit_free_buffer(rtk, &rtk->crashlog_buffer); ++ apple_rtkit_free_buffer(rtk, &rtk->oslog_buffer); + apple_rtkit_free_buffer(rtk, &rtk->syslog_buffer); + + kfree(rtk->syslog_msg_buffer); +@@ -890,6 +901,7 @@ void apple_rtkit_free(struct apple_rtkit *rtk) + + apple_rtkit_free_buffer(rtk, &rtk->ioreport_buffer); + apple_rtkit_free_buffer(rtk, &rtk->crashlog_buffer); ++ apple_rtkit_free_buffer(rtk, &rtk->oslog_buffer); + apple_rtkit_free_buffer(rtk, &rtk->syslog_buffer); + + kfree(rtk->syslog_msg_buffer); +-- +2.39.5 + diff --git a/queue-6.14/soc-apple-rtkit-use-high-prio-work-queue.patch b/queue-6.14/soc-apple-rtkit-use-high-prio-work-queue.patch new file mode 100644 index 0000000000..f29d80beaa --- /dev/null +++ b/queue-6.14/soc-apple-rtkit-use-high-prio-work-queue.patch @@ -0,0 +1,42 @@ +From 34b8dd29a5a549d67d0ac42ce528e375a9a03624 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 26 Feb 2025 19:00:05 +0000 +Subject: soc: apple: rtkit: Use high prio work queue + +From: Janne Grunau + +[ Upstream commit 22af2fac88fa5dbc310bfe7d0b66d4de3ac47305 ] + +rtkit messages as communication with the DCP firmware for framebuffer +swaps or input events are time critical so use WQ_HIGHPRI to prevent +user space CPU load to increase latency. +With kwin_wayland 6's explicit sync mode user space load was able to +delay the IOMFB rtkit communication enough to miss vsync for surface +swaps. Minimal test scenario is constantly resizing a glxgears +Xwayland window. + +Signed-off-by: Janne Grunau +Reviewed-by: Alyssa Rosenzweig +Link: https://lore.kernel.org/r/20250226-apple-soc-misc-v2-3-c3ec37f9021b@svenpeter.dev +Signed-off-by: Sven Peter +Signed-off-by: Sasha Levin +--- + drivers/soc/apple/rtkit.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/soc/apple/rtkit.c b/drivers/soc/apple/rtkit.c +index e6d940292c9fb..00d59a81db88b 100644 +--- a/drivers/soc/apple/rtkit.c ++++ b/drivers/soc/apple/rtkit.c +@@ -667,7 +667,7 @@ struct apple_rtkit *apple_rtkit_init(struct device *dev, void *cookie, + rtk->mbox->rx = apple_rtkit_rx; + rtk->mbox->cookie = rtk; + +- rtk->wq = alloc_ordered_workqueue("rtkit-%s", WQ_MEM_RECLAIM, ++ rtk->wq = alloc_ordered_workqueue("rtkit-%s", WQ_HIGHPRI | WQ_MEM_RECLAIM, + dev_name(rtk->dev)); + if (!rtk->wq) { + ret = -ENOMEM; +-- +2.39.5 + diff --git a/queue-6.14/soc-mediatek-mtk-mutex-add-dpi1-sof-eof-to-mt8188-mu.patch b/queue-6.14/soc-mediatek-mtk-mutex-add-dpi1-sof-eof-to-mt8188-mu.patch new file mode 100644 index 0000000000..8b5995da58 --- /dev/null +++ b/queue-6.14/soc-mediatek-mtk-mutex-add-dpi1-sof-eof-to-mt8188-mu.patch @@ -0,0 +1,69 @@ +From 5fe9cd124c1d33c31e4ac0f5f202049f6a9dff8d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 12 Feb 2025 11:00:05 +0100 +Subject: soc: mediatek: mtk-mutex: Add DPI1 SOF/EOF to MT8188 mutex tables + +From: AngeloGioacchino Del Regno + +[ Upstream commit 694e0b7c1747603243da874de9cbbf8cb806ca44 ] + +MT8188 uses DPI1 to output to the HDMI controller: add the +Start of Frame and End of Frame configuration for the DPI1 +IP to the tables to unblock generation and sending of these +signals to the GCE. + +Link: https://lore.kernel.org/r/20250212100012.33001-2-angelogioacchino.delregno@collabora.com +Signed-off-by: AngeloGioacchino Del Regno +Signed-off-by: Sasha Levin +--- + drivers/soc/mediatek/mtk-mutex.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/drivers/soc/mediatek/mtk-mutex.c b/drivers/soc/mediatek/mtk-mutex.c +index 5250c1d702eb9..aaa965d4b050a 100644 +--- a/drivers/soc/mediatek/mtk-mutex.c ++++ b/drivers/soc/mediatek/mtk-mutex.c +@@ -155,6 +155,7 @@ + #define MT8188_MUTEX_MOD_DISP1_VPP_MERGE3 23 + #define MT8188_MUTEX_MOD_DISP1_VPP_MERGE4 24 + #define MT8188_MUTEX_MOD_DISP1_DISP_MIXER 30 ++#define MT8188_MUTEX_MOD_DISP1_DPI1 38 + #define MT8188_MUTEX_MOD_DISP1_DP_INTF1 39 + + #define MT8195_MUTEX_MOD_DISP_OVL0 0 +@@ -289,6 +290,7 @@ + #define MT8188_MUTEX_SOF_DSI0 1 + #define MT8188_MUTEX_SOF_DP_INTF0 3 + #define MT8188_MUTEX_SOF_DP_INTF1 4 ++#define MT8188_MUTEX_SOF_DPI1 5 + #define MT8195_MUTEX_SOF_DSI0 1 + #define MT8195_MUTEX_SOF_DSI1 2 + #define MT8195_MUTEX_SOF_DP_INTF0 3 +@@ -301,6 +303,7 @@ + #define MT8188_MUTEX_EOF_DSI0 (MT8188_MUTEX_SOF_DSI0 << 7) + #define MT8188_MUTEX_EOF_DP_INTF0 (MT8188_MUTEX_SOF_DP_INTF0 << 7) + #define MT8188_MUTEX_EOF_DP_INTF1 (MT8188_MUTEX_SOF_DP_INTF1 << 7) ++#define MT8188_MUTEX_EOF_DPI1 (MT8188_MUTEX_SOF_DPI1 << 7) + #define MT8195_MUTEX_EOF_DSI0 (MT8195_MUTEX_SOF_DSI0 << 7) + #define MT8195_MUTEX_EOF_DSI1 (MT8195_MUTEX_SOF_DSI1 << 7) + #define MT8195_MUTEX_EOF_DP_INTF0 (MT8195_MUTEX_SOF_DP_INTF0 << 7) +@@ -472,6 +475,7 @@ static const u8 mt8188_mutex_mod[DDP_COMPONENT_ID_MAX] = { + [DDP_COMPONENT_PWM0] = MT8188_MUTEX_MOD2_DISP_PWM0, + [DDP_COMPONENT_DP_INTF0] = MT8188_MUTEX_MOD_DISP_DP_INTF0, + [DDP_COMPONENT_DP_INTF1] = MT8188_MUTEX_MOD_DISP1_DP_INTF1, ++ [DDP_COMPONENT_DPI1] = MT8188_MUTEX_MOD_DISP1_DPI1, + [DDP_COMPONENT_ETHDR_MIXER] = MT8188_MUTEX_MOD_DISP1_DISP_MIXER, + [DDP_COMPONENT_MDP_RDMA0] = MT8188_MUTEX_MOD_DISP1_MDP_RDMA0, + [DDP_COMPONENT_MDP_RDMA1] = MT8188_MUTEX_MOD_DISP1_MDP_RDMA1, +@@ -686,6 +690,8 @@ static const u16 mt8188_mutex_sof[DDP_MUTEX_SOF_MAX] = { + [MUTEX_SOF_SINGLE_MODE] = MUTEX_SOF_SINGLE_MODE, + [MUTEX_SOF_DSI0] = + MT8188_MUTEX_SOF_DSI0 | MT8188_MUTEX_EOF_DSI0, ++ [MUTEX_SOF_DPI1] = ++ MT8188_MUTEX_SOF_DPI1 | MT8188_MUTEX_EOF_DPI1, + [MUTEX_SOF_DP_INTF0] = + MT8188_MUTEX_SOF_DP_INTF0 | MT8188_MUTEX_EOF_DP_INTF0, + [MUTEX_SOF_DP_INTF1] = +-- +2.39.5 + diff --git a/queue-6.14/soc-samsung-include-linux-array_size.h-where-needed.patch b/queue-6.14/soc-samsung-include-linux-array_size.h-where-needed.patch new file mode 100644 index 0000000000..86b0bdac20 --- /dev/null +++ b/queue-6.14/soc-samsung-include-linux-array_size.h-where-needed.patch @@ -0,0 +1,119 @@ +From f3f824d2c65f83635a233b62c44debef63dac507 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Mar 2025 22:14:02 +0100 +Subject: soc: samsung: include linux/array_size.h where needed + +From: Arnd Bergmann + +[ Upstream commit 4c57930f68d90e0d52c396d058cfa9ed8447a6c4 ] + +This does not necessarily get included through asm/io.h: + +drivers/soc/samsung/exynos3250-pmu.c:120:18: error: use of undeclared identifier 'ARRAY_SIZE' + 120 | for (i = 0; i < ARRAY_SIZE(exynos3250_list_feed); i++) { + | ^ +drivers/soc/samsung/exynos5250-pmu.c:162:18: error: use of undeclared identifier 'ARRAY_SIZE' + 162 | for (i = 0; i < ARRAY_SIZE(exynos5_list_both_cnt_feed); i++) { + | ^ + +Signed-off-by: Arnd Bergmann +Link: https://lore.kernel.org/r/20250305211446.43772-1-arnd@kernel.org +Signed-off-by: Krzysztof Kozlowski +Signed-off-by: Sasha Levin +--- + drivers/soc/samsung/exynos-asv.c | 1 + + drivers/soc/samsung/exynos-chipid.c | 1 + + drivers/soc/samsung/exynos-pmu.c | 1 + + drivers/soc/samsung/exynos-usi.c | 1 + + drivers/soc/samsung/exynos3250-pmu.c | 1 + + drivers/soc/samsung/exynos5250-pmu.c | 1 + + drivers/soc/samsung/exynos5420-pmu.c | 1 + + 7 files changed, 7 insertions(+) + +diff --git a/drivers/soc/samsung/exynos-asv.c b/drivers/soc/samsung/exynos-asv.c +index 97006cc3b9461..8e681f5195264 100644 +--- a/drivers/soc/samsung/exynos-asv.c ++++ b/drivers/soc/samsung/exynos-asv.c +@@ -9,6 +9,7 @@ + * Samsung Exynos SoC Adaptive Supply Voltage support + */ + ++#include + #include + #include + #include +diff --git a/drivers/soc/samsung/exynos-chipid.c b/drivers/soc/samsung/exynos-chipid.c +index 95294462ff211..99c5f9c80101b 100644 +--- a/drivers/soc/samsung/exynos-chipid.c ++++ b/drivers/soc/samsung/exynos-chipid.c +@@ -12,6 +12,7 @@ + * Samsung Exynos SoC Adaptive Supply Voltage and Chip ID support + */ + ++#include + #include + #include + #include +diff --git a/drivers/soc/samsung/exynos-pmu.c b/drivers/soc/samsung/exynos-pmu.c +index dd5256e5aae1a..c40313886a012 100644 +--- a/drivers/soc/samsung/exynos-pmu.c ++++ b/drivers/soc/samsung/exynos-pmu.c +@@ -5,6 +5,7 @@ + // + // Exynos - CPU PMU(Power Management Unit) support + ++#include + #include + #include + #include +diff --git a/drivers/soc/samsung/exynos-usi.c b/drivers/soc/samsung/exynos-usi.c +index 114352695ac2b..5a93a68dba87f 100644 +--- a/drivers/soc/samsung/exynos-usi.c ++++ b/drivers/soc/samsung/exynos-usi.c +@@ -6,6 +6,7 @@ + * Samsung Exynos USI driver (Universal Serial Interface). + */ + ++#include + #include + #include + #include +diff --git a/drivers/soc/samsung/exynos3250-pmu.c b/drivers/soc/samsung/exynos3250-pmu.c +index 30f230ed1769c..4bad12a995422 100644 +--- a/drivers/soc/samsung/exynos3250-pmu.c ++++ b/drivers/soc/samsung/exynos3250-pmu.c +@@ -5,6 +5,7 @@ + // + // Exynos3250 - CPU PMU (Power Management Unit) support + ++#include + #include + #include + +diff --git a/drivers/soc/samsung/exynos5250-pmu.c b/drivers/soc/samsung/exynos5250-pmu.c +index 7a2d50be6b4ac..2ae5c3e1b07a3 100644 +--- a/drivers/soc/samsung/exynos5250-pmu.c ++++ b/drivers/soc/samsung/exynos5250-pmu.c +@@ -5,6 +5,7 @@ + // + // Exynos5250 - CPU PMU (Power Management Unit) support + ++#include + #include + #include + +diff --git a/drivers/soc/samsung/exynos5420-pmu.c b/drivers/soc/samsung/exynos5420-pmu.c +index 6fedcd78cb451..58a2209795f78 100644 +--- a/drivers/soc/samsung/exynos5420-pmu.c ++++ b/drivers/soc/samsung/exynos5420-pmu.c +@@ -5,6 +5,7 @@ + // + // Exynos5420 - CPU PMU (Power Management Unit) support + ++#include + #include + #include + #include +-- +2.39.5 + diff --git a/queue-6.14/soc-ti-k3-socinfo-do-not-use-syscon-helper-to-build-.patch b/queue-6.14/soc-ti-k3-socinfo-do-not-use-syscon-helper-to-build-.patch new file mode 100644 index 0000000000..ff4fcad106 --- /dev/null +++ b/queue-6.14/soc-ti-k3-socinfo-do-not-use-syscon-helper-to-build-.patch @@ -0,0 +1,68 @@ +From 044546713993cae525426a110675a0e1e0efbcf0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 23 Jan 2025 12:17:26 -0600 +Subject: soc: ti: k3-socinfo: Do not use syscon helper to build regmap + +From: Andrew Davis + +[ Upstream commit a5caf03188e44388e8c618dcbe5fffad1a249385 ] + +The syscon helper device_node_to_regmap() is used to fetch a regmap +registered to a device node. It also currently creates this regmap +if the node did not already have a regmap associated with it. This +should only be used on "syscon" nodes. This driver is not such a +device and instead uses device_node_to_regmap() on its own node as +a hacky way to create a regmap for itself. + +This will not work going forward and so we should create our regmap +the normal way by defining our regmap_config, fetching our memory +resource, then using the normal regmap_init_mmio() function. + +Signed-off-by: Andrew Davis +Link: https://lore.kernel.org/r/20250123181726.597144-1-afd@ti.com +Signed-off-by: Nishanth Menon +Signed-off-by: Sasha Levin +--- + drivers/soc/ti/k3-socinfo.c | 13 ++++++++++++- + 1 file changed, 12 insertions(+), 1 deletion(-) + +diff --git a/drivers/soc/ti/k3-socinfo.c b/drivers/soc/ti/k3-socinfo.c +index 4fb0f0a248288..704039eb3c078 100644 +--- a/drivers/soc/ti/k3-socinfo.c ++++ b/drivers/soc/ti/k3-socinfo.c +@@ -105,6 +105,12 @@ k3_chipinfo_variant_to_sr(unsigned int partno, unsigned int variant, + return -ENODEV; + } + ++static const struct regmap_config k3_chipinfo_regmap_cfg = { ++ .reg_bits = 32, ++ .val_bits = 32, ++ .reg_stride = 4, ++}; ++ + static int k3_chipinfo_probe(struct platform_device *pdev) + { + struct device_node *node = pdev->dev.of_node; +@@ -112,13 +118,18 @@ static int k3_chipinfo_probe(struct platform_device *pdev) + struct device *dev = &pdev->dev; + struct soc_device *soc_dev; + struct regmap *regmap; ++ void __iomem *base; + u32 partno_id; + u32 variant; + u32 jtag_id; + u32 mfg; + int ret; + +- regmap = device_node_to_regmap(node); ++ base = devm_platform_ioremap_resource(pdev, 0); ++ if (IS_ERR(base)) ++ return PTR_ERR(base); ++ ++ regmap = regmap_init_mmio(dev, base, &k3_chipinfo_regmap_cfg); + if (IS_ERR(regmap)) + return PTR_ERR(regmap); + +-- +2.39.5 + diff --git a/queue-6.14/soundwire-amd-change-the-soundwire-wake-enable-disab.patch b/queue-6.14/soundwire-amd-change-the-soundwire-wake-enable-disab.patch new file mode 100644 index 0000000000..f14eb7fff5 --- /dev/null +++ b/queue-6.14/soundwire-amd-change-the-soundwire-wake-enable-disab.patch @@ -0,0 +1,46 @@ +From 030465ee8f32777ecab8afed05276722b9aa4301 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 7 Feb 2025 12:28:36 +0530 +Subject: soundwire: amd: change the soundwire wake enable/disable sequence + +From: Vijendar Mukunda + +[ Upstream commit dcc48a73eae7f791b1a6856ea1bcc4079282c88d ] + +During runtime suspend scenario, SoundWire wake should be enabled and +during system level suspend scenario SoundWire wake should be disabled. + +Implement the SoundWire wake enable/disable sequence as per design flow +for SoundWire poweroff mode. + +Signed-off-by: Vijendar Mukunda +Link: https://lore.kernel.org/r/20250207065841.4718-2-Vijendar.Mukunda@amd.com +Signed-off-by: Vinod Koul +Signed-off-by: Sasha Levin +--- + drivers/soundwire/amd_manager.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/soundwire/amd_manager.c b/drivers/soundwire/amd_manager.c +index 5a54b10daf77a..9d80623787247 100644 +--- a/drivers/soundwire/amd_manager.c ++++ b/drivers/soundwire/amd_manager.c +@@ -1139,6 +1139,7 @@ static int __maybe_unused amd_suspend(struct device *dev) + amd_sdw_wake_enable(amd_manager, false); + return amd_sdw_clock_stop(amd_manager); + } else if (amd_manager->power_mode_mask & AMD_SDW_POWER_OFF_MODE) { ++ amd_sdw_wake_enable(amd_manager, false); + /* + * As per hardware programming sequence on AMD platforms, + * clock stop should be invoked first before powering-off +@@ -1166,6 +1167,7 @@ static int __maybe_unused amd_suspend_runtime(struct device *dev) + amd_sdw_wake_enable(amd_manager, true); + return amd_sdw_clock_stop(amd_manager); + } else if (amd_manager->power_mode_mask & AMD_SDW_POWER_OFF_MODE) { ++ amd_sdw_wake_enable(amd_manager, true); + ret = amd_sdw_clock_stop(amd_manager); + if (ret) + return ret; +-- +2.39.5 + diff --git a/queue-6.14/soundwire-cadence_master-set-frame-shape-and-divider.patch b/queue-6.14/soundwire-cadence_master-set-frame-shape-and-divider.patch new file mode 100644 index 0000000000..2341f55cd4 --- /dev/null +++ b/queue-6.14/soundwire-cadence_master-set-frame-shape-and-divider.patch @@ -0,0 +1,95 @@ +From d74c8b051d08e61b7ba38588a472886b9e4d698d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Feb 2025 15:42:31 +0800 +Subject: soundwire: cadence_master: set frame shape and divider based on + actual clk freq +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Bard Liao + +[ Upstream commit e738d77f78b3ac085dfb51be414e93464abba7ec ] + +Frame shape and curr_dr_freq could be updated by sdw_compute_bus_params(). +Peripherals will set curr_dr_freq as their frequency. Managers +should do the same. Then update frame shape according to the actual +bus frequency. + +Signed-off-by: Bard Liao +Reviewed-by: Ranjani Sridharan +Reviewed-by: Péter Ujfalusi +Reviewed-by: Pierre-Louis Bossart +Link: https://lore.kernel.org/r/20250205074232.87537-2-yung-chuan.liao@linux.intel.com +Signed-off-by: Vinod Koul +Signed-off-by: Sasha Levin +--- + drivers/soundwire/cadence_master.c | 22 +++++++++++++++++++--- + 1 file changed, 19 insertions(+), 3 deletions(-) + +diff --git a/drivers/soundwire/cadence_master.c b/drivers/soundwire/cadence_master.c +index f367670ea991b..68be8ff3f02b1 100644 +--- a/drivers/soundwire/cadence_master.c ++++ b/drivers/soundwire/cadence_master.c +@@ -1341,7 +1341,7 @@ static u32 cdns_set_initial_frame_shape(int n_rows, int n_cols) + return val; + } + +-static void cdns_init_clock_ctrl(struct sdw_cdns *cdns) ++static int cdns_init_clock_ctrl(struct sdw_cdns *cdns) + { + struct sdw_bus *bus = &cdns->bus; + struct sdw_master_prop *prop = &bus->prop; +@@ -1355,14 +1355,25 @@ static void cdns_init_clock_ctrl(struct sdw_cdns *cdns) + prop->default_row, + prop->default_col); + ++ if (!prop->default_frame_rate || !prop->default_row) { ++ dev_err(cdns->dev, "Default frame_rate %d or row %d is invalid\n", ++ prop->default_frame_rate, prop->default_row); ++ return -EINVAL; ++ } ++ + /* Set clock divider */ +- divider = (prop->mclk_freq / prop->max_clk_freq) - 1; ++ divider = (prop->mclk_freq * SDW_DOUBLE_RATE_FACTOR / ++ bus->params.curr_dr_freq) - 1; + + cdns_updatel(cdns, CDNS_MCP_CLK_CTRL0, + CDNS_MCP_CLK_MCLKD_MASK, divider); + cdns_updatel(cdns, CDNS_MCP_CLK_CTRL1, + CDNS_MCP_CLK_MCLKD_MASK, divider); + ++ /* Set frame shape base on the actual bus frequency. */ ++ prop->default_col = bus->params.curr_dr_freq / ++ prop->default_frame_rate / prop->default_row; ++ + /* + * Frame shape changes after initialization have to be done + * with the bank switch mechanism +@@ -1375,6 +1386,8 @@ static void cdns_init_clock_ctrl(struct sdw_cdns *cdns) + ssp_interval = prop->default_frame_rate / SDW_CADENCE_GSYNC_HZ; + cdns_writel(cdns, CDNS_MCP_SSP_CTRL0, ssp_interval); + cdns_writel(cdns, CDNS_MCP_SSP_CTRL1, ssp_interval); ++ ++ return 0; + } + + /** +@@ -1408,9 +1421,12 @@ EXPORT_SYMBOL(sdw_cdns_soft_reset); + */ + int sdw_cdns_init(struct sdw_cdns *cdns) + { ++ int ret; + u32 val; + +- cdns_init_clock_ctrl(cdns); ++ ret = cdns_init_clock_ctrl(cdns); ++ if (ret) ++ return ret; + + sdw_cdns_check_self_clearing_bits(cdns, __func__, false, 0); + +-- +2.39.5 + diff --git a/queue-6.14/spi-rockchip-fix-register-out-of-bounds-access.patch b/queue-6.14/spi-rockchip-fix-register-out-of-bounds-access.patch new file mode 100644 index 0000000000..a7a2263f34 --- /dev/null +++ b/queue-6.14/spi-rockchip-fix-register-out-of-bounds-access.patch @@ -0,0 +1,37 @@ +From a71ccf7ad66d3afab204314af235f8cf57ffa479 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 21 Mar 2025 13:57:53 +0100 +Subject: spi-rockchip: Fix register out of bounds access + +From: Luis de Arquer + +[ Upstream commit 7a874e8b54ea21094f7fd2d428b164394c6cb316 ] + +Do not write native chip select stuff for GPIO chip selects. +GPIOs can be numbered much higher than native CS. +Also, it makes no sense. + +Signed-off-by: Luis de Arquer +Link: https://patch.msgid.link/365ccddfba110549202b3520f4401a6a936e82a8.camel@gmail.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + drivers/spi/spi-rockchip.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/spi/spi-rockchip.c b/drivers/spi/spi-rockchip.c +index 1bc012fce7cb8..1a6381de6f33d 100644 +--- a/drivers/spi/spi-rockchip.c ++++ b/drivers/spi/spi-rockchip.c +@@ -547,7 +547,7 @@ static int rockchip_spi_config(struct rockchip_spi *rs, + cr0 |= (spi->mode & 0x3U) << CR0_SCPH_OFFSET; + if (spi->mode & SPI_LSB_FIRST) + cr0 |= CR0_FBM_LSB << CR0_FBM_OFFSET; +- if (spi->mode & SPI_CS_HIGH) ++ if ((spi->mode & SPI_CS_HIGH) && !(spi_get_csgpiod(spi, 0))) + cr0 |= BIT(spi_get_chipselect(spi, 0)) << CR0_SOI_OFFSET; + + if (xfer->rx_buf && xfer->tx_buf) +-- +2.39.5 + diff --git a/queue-6.14/spi-spi-mux-fix-coverity-issue-unchecked-return-valu.patch b/queue-6.14/spi-spi-mux-fix-coverity-issue-unchecked-return-valu.patch new file mode 100644 index 0000000000..8d6b15f134 --- /dev/null +++ b/queue-6.14/spi-spi-mux-fix-coverity-issue-unchecked-return-valu.patch @@ -0,0 +1,40 @@ +From d06c9ea2ff7977f7dffb3a252398f7757d8259a0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 15 Mar 2025 23:46:06 -0600 +Subject: spi: spi-mux: Fix coverity issue, unchecked return value + +From: Sergio Perez Gonzalez + +[ Upstream commit 5a5fc308418aca275a898d638bc38c093d101855 ] + +The return value of spi_setup() is not captured within +spi_mux_select() and it is assumed to be always success. + +CID: 1638374 + +Signed-off-by: Sergio Perez Gonzalez +Link: https://patch.msgid.link/20250316054651.13242-1-sperezglz@gmail.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + drivers/spi/spi-mux.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +diff --git a/drivers/spi/spi-mux.c b/drivers/spi/spi-mux.c +index c02c4204442f5..0eb35c4e3987e 100644 +--- a/drivers/spi/spi-mux.c ++++ b/drivers/spi/spi-mux.c +@@ -68,9 +68,7 @@ static int spi_mux_select(struct spi_device *spi) + + priv->current_cs = spi_get_chipselect(spi, 0); + +- spi_setup(priv->spi); +- +- return 0; ++ return spi_setup(priv->spi); + } + + static int spi_mux_setup(struct spi_device *spi) +-- +2.39.5 + diff --git a/queue-6.14/spi-zynqmp-gqspi-always-acknowledge-interrupts.patch b/queue-6.14/spi-zynqmp-gqspi-always-acknowledge-interrupts.patch new file mode 100644 index 0000000000..bf711a3d54 --- /dev/null +++ b/queue-6.14/spi-zynqmp-gqspi-always-acknowledge-interrupts.patch @@ -0,0 +1,72 @@ +From c67a4d9191b2fcef51ddb89abb3d7c1ae2eaa383 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 16 Jan 2025 17:41:30 -0500 +Subject: spi: zynqmp-gqspi: Always acknowledge interrupts + +From: Sean Anderson + +[ Upstream commit 89785306453ce6d949e783f6936821a0b7649ee2 ] + +RXEMPTY can cause an IRQ, even though we may not do anything about it +(such as if we are waiting for more received data). We must still handle +these IRQs because we can tell they were caused by the device. + +Signed-off-by: Sean Anderson +Link: https://patch.msgid.link/20250116224130.2684544-6-sean.anderson@linux.dev +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + drivers/spi/spi-zynqmp-gqspi.c | 20 ++++++++------------ + 1 file changed, 8 insertions(+), 12 deletions(-) + +diff --git a/drivers/spi/spi-zynqmp-gqspi.c b/drivers/spi/spi-zynqmp-gqspi.c +index d800d79f62a70..12ab13edab543 100644 +--- a/drivers/spi/spi-zynqmp-gqspi.c ++++ b/drivers/spi/spi-zynqmp-gqspi.c +@@ -799,7 +799,6 @@ static void zynqmp_process_dma_irq(struct zynqmp_qspi *xqspi) + static irqreturn_t zynqmp_qspi_irq(int irq, void *dev_id) + { + struct zynqmp_qspi *xqspi = (struct zynqmp_qspi *)dev_id; +- irqreturn_t ret = IRQ_NONE; + u32 status, mask, dma_status = 0; + + status = zynqmp_gqspi_read(xqspi, GQSPI_ISR_OFST); +@@ -814,27 +813,24 @@ static irqreturn_t zynqmp_qspi_irq(int irq, void *dev_id) + dma_status); + } + +- if (mask & GQSPI_ISR_TXNOT_FULL_MASK) { ++ if (!mask && !dma_status) ++ return IRQ_NONE; ++ ++ if (mask & GQSPI_ISR_TXNOT_FULL_MASK) + zynqmp_qspi_filltxfifo(xqspi, GQSPI_TX_FIFO_FILL); +- ret = IRQ_HANDLED; +- } + +- if (dma_status & GQSPI_QSPIDMA_DST_I_STS_DONE_MASK) { ++ if (dma_status & GQSPI_QSPIDMA_DST_I_STS_DONE_MASK) + zynqmp_process_dma_irq(xqspi); +- ret = IRQ_HANDLED; +- } else if (!(mask & GQSPI_IER_RXEMPTY_MASK) && +- (mask & GQSPI_IER_GENFIFOEMPTY_MASK)) { ++ else if (!(mask & GQSPI_IER_RXEMPTY_MASK) && ++ (mask & GQSPI_IER_GENFIFOEMPTY_MASK)) + zynqmp_qspi_readrxfifo(xqspi, GQSPI_RX_FIFO_FILL); +- ret = IRQ_HANDLED; +- } + + if (xqspi->bytes_to_receive == 0 && xqspi->bytes_to_transfer == 0 && + ((status & GQSPI_IRQ_MASK) == GQSPI_IRQ_MASK)) { + zynqmp_gqspi_write(xqspi, GQSPI_IDR_OFST, GQSPI_ISR_IDR_MASK); + complete(&xqspi->data_completion); +- ret = IRQ_HANDLED; + } +- return ret; ++ return IRQ_HANDLED; + } + + /** +-- +2.39.5 + diff --git a/queue-6.14/staging-vchiq_arm-create-keep-alive-thread-during-pr.patch b/queue-6.14/staging-vchiq_arm-create-keep-alive-thread-during-pr.patch new file mode 100644 index 0000000000..35248286c3 --- /dev/null +++ b/queue-6.14/staging-vchiq_arm-create-keep-alive-thread-during-pr.patch @@ -0,0 +1,129 @@ +From a5d566b380b376a8e1512ff4f8ebb395ccba63e6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 9 Mar 2025 13:50:13 +0100 +Subject: staging: vchiq_arm: Create keep-alive thread during probe + +From: Stefan Wahren + +[ Upstream commit 86bc8821700665ad3962f3ef0d93667f59cf7031 ] + +Creating the keep-alive thread in vchiq_platform_init_state have +the following advantages: +- abort driver probe if kthread_create fails (more consistent behavior) +- make resource release process easier + +Since vchiq_keepalive_thread_func is defined below +vchiq_platform_init_state, the latter must be moved. + +Signed-off-by: Stefan Wahren +Link: https://lore.kernel.org/r/20250309125014.37166-5-wahrenst@gmx.net +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + .../interface/vchiq_arm/vchiq_arm.c | 69 +++++++++---------- + 1 file changed, 34 insertions(+), 35 deletions(-) + +diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c +index 0c7ea2d0ee85e..64f9536f12329 100644 +--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c ++++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c +@@ -280,29 +280,6 @@ static int vchiq_platform_init(struct platform_device *pdev, struct vchiq_state + return 0; + } + +-int +-vchiq_platform_init_state(struct vchiq_state *state) +-{ +- struct vchiq_arm_state *platform_state; +- +- platform_state = devm_kzalloc(state->dev, sizeof(*platform_state), GFP_KERNEL); +- if (!platform_state) +- return -ENOMEM; +- +- rwlock_init(&platform_state->susp_res_lock); +- +- init_completion(&platform_state->ka_evt); +- atomic_set(&platform_state->ka_use_count, 0); +- atomic_set(&platform_state->ka_use_ack_count, 0); +- atomic_set(&platform_state->ka_release_count, 0); +- +- platform_state->state = state; +- +- state->platform_state = (struct opaque_platform_state *)platform_state; +- +- return 0; +-} +- + static struct vchiq_arm_state *vchiq_platform_get_arm_state(struct vchiq_state *state) + { + return (struct vchiq_arm_state *)state->platform_state; +@@ -1011,6 +988,39 @@ vchiq_keepalive_thread_func(void *v) + return 0; + } + ++int ++vchiq_platform_init_state(struct vchiq_state *state) ++{ ++ struct vchiq_arm_state *platform_state; ++ char threadname[16]; ++ ++ platform_state = devm_kzalloc(state->dev, sizeof(*platform_state), GFP_KERNEL); ++ if (!platform_state) ++ return -ENOMEM; ++ ++ snprintf(threadname, sizeof(threadname), "vchiq-keep/%d", ++ state->id); ++ platform_state->ka_thread = kthread_create(&vchiq_keepalive_thread_func, ++ (void *)state, threadname); ++ if (IS_ERR(platform_state->ka_thread)) { ++ dev_err(state->dev, "couldn't create thread %s\n", threadname); ++ return PTR_ERR(platform_state->ka_thread); ++ } ++ ++ rwlock_init(&platform_state->susp_res_lock); ++ ++ init_completion(&platform_state->ka_evt); ++ atomic_set(&platform_state->ka_use_count, 0); ++ atomic_set(&platform_state->ka_use_ack_count, 0); ++ atomic_set(&platform_state->ka_release_count, 0); ++ ++ platform_state->state = state; ++ ++ state->platform_state = (struct opaque_platform_state *)platform_state; ++ ++ return 0; ++} ++ + int + vchiq_use_internal(struct vchiq_state *state, struct vchiq_service *service, + enum USE_TYPE_E use_type) +@@ -1331,7 +1341,6 @@ void vchiq_platform_conn_state_changed(struct vchiq_state *state, + enum vchiq_connstate newstate) + { + struct vchiq_arm_state *arm_state = vchiq_platform_get_arm_state(state); +- char threadname[16]; + + dev_dbg(state->dev, "suspend: %d: %s->%s\n", + state->id, get_conn_state_name(oldstate), get_conn_state_name(newstate)); +@@ -1346,17 +1355,7 @@ void vchiq_platform_conn_state_changed(struct vchiq_state *state, + + arm_state->first_connect = 1; + write_unlock_bh(&arm_state->susp_res_lock); +- snprintf(threadname, sizeof(threadname), "vchiq-keep/%d", +- state->id); +- arm_state->ka_thread = kthread_create(&vchiq_keepalive_thread_func, +- (void *)state, +- threadname); +- if (IS_ERR(arm_state->ka_thread)) { +- dev_err(state->dev, "suspend: Couldn't create thread %s\n", +- threadname); +- } else { +- wake_up_process(arm_state->ka_thread); +- } ++ wake_up_process(arm_state->ka_thread); + } + + static const struct of_device_id vchiq_of_match[] = { +-- +2.39.5 + diff --git a/queue-6.14/sunrpc-don-t-allow-waiting-for-exiting-tasks.patch b/queue-6.14/sunrpc-don-t-allow-waiting-for-exiting-tasks.patch new file mode 100644 index 0000000000..72925cad75 --- /dev/null +++ b/queue-6.14/sunrpc-don-t-allow-waiting-for-exiting-tasks.patch @@ -0,0 +1,35 @@ +From f5df841ba4f419db4b8a9c4bb14fc2a85c4f9dc8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 28 Mar 2025 12:52:52 -0400 +Subject: SUNRPC: Don't allow waiting for exiting tasks + +From: Trond Myklebust + +[ Upstream commit 14e41b16e8cb677bb440dca2edba8b041646c742 ] + +Once a task calls exit_signals() it can no longer be signalled. So do +not allow it to do killable waits. + +Reviewed-by: Jeff Layton +Signed-off-by: Trond Myklebust +Signed-off-by: Sasha Levin +--- + net/sunrpc/sched.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c +index 9b45fbdc90cab..73bc39281ef5f 100644 +--- a/net/sunrpc/sched.c ++++ b/net/sunrpc/sched.c +@@ -276,6 +276,8 @@ EXPORT_SYMBOL_GPL(rpc_destroy_wait_queue); + + static int rpc_wait_bit_killable(struct wait_bit_key *key, int mode) + { ++ if (unlikely(current->flags & PF_EXITING)) ++ return -EINTR; + schedule(); + if (signal_pending_state(mode, current)) + return -ERESTARTSYS; +-- +2.39.5 + diff --git a/queue-6.14/sunrpc-rpc_clnt_set_transport-must-not-change-the-au.patch b/queue-6.14/sunrpc-rpc_clnt_set_transport-must-not-change-the-au.patch new file mode 100644 index 0000000000..ccdaf2c1fa --- /dev/null +++ b/queue-6.14/sunrpc-rpc_clnt_set_transport-must-not-change-the-au.patch @@ -0,0 +1,38 @@ +From 0c0e47b2eaee2ab1167168cded054c1715e87c2e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 24 Mar 2025 19:35:01 -0400 +Subject: SUNRPC: rpc_clnt_set_transport() must not change the autobind setting + +From: Trond Myklebust + +[ Upstream commit bf9be373b830a3e48117da5d89bb6145a575f880 ] + +The autobind setting was supposed to be determined in rpc_create(), +since commit c2866763b402 ("SUNRPC: use sockaddr + size when creating +remote transport endpoints"). + +Reviewed-by: Jeff Layton +Reviewed-by: Benjamin Coddington +Signed-off-by: Trond Myklebust +Signed-off-by: Sasha Levin +--- + net/sunrpc/clnt.c | 3 --- + 1 file changed, 3 deletions(-) + +diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c +index 2fe88ea79a70c..c9c5f0caef6bd 100644 +--- a/net/sunrpc/clnt.c ++++ b/net/sunrpc/clnt.c +@@ -270,9 +270,6 @@ static struct rpc_xprt *rpc_clnt_set_transport(struct rpc_clnt *clnt, + old = rcu_dereference_protected(clnt->cl_xprt, + lockdep_is_held(&clnt->cl_lock)); + +- if (!xprt_bound(xprt)) +- clnt->cl_autobind = 1; +- + clnt->cl_timeout = timeout; + rcu_assign_pointer(clnt->cl_xprt, xprt); + spin_unlock(&clnt->cl_lock); +-- +2.39.5 + diff --git a/queue-6.14/sunrpc-rpcbind-should-never-reset-the-port-to-the-va.patch b/queue-6.14/sunrpc-rpcbind-should-never-reset-the-port-to-the-va.patch new file mode 100644 index 0000000000..523c5993f7 --- /dev/null +++ b/queue-6.14/sunrpc-rpcbind-should-never-reset-the-port-to-the-va.patch @@ -0,0 +1,40 @@ +From 978e47a3d11e5c2d7b3abaf81ba0036a62ea3d27 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 24 Mar 2025 19:05:48 -0400 +Subject: SUNRPC: rpcbind should never reset the port to the value '0' + +From: Trond Myklebust + +[ Upstream commit 214c13e380ad7636631279f426387f9c4e3c14d9 ] + +If we already had a valid port number for the RPC service, then we +should not allow the rpcbind client to set it to the invalid value '0'. + +Reviewed-by: Jeff Layton +Reviewed-by: Benjamin Coddington +Signed-off-by: Trond Myklebust +Signed-off-by: Sasha Levin +--- + net/sunrpc/rpcb_clnt.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/net/sunrpc/rpcb_clnt.c b/net/sunrpc/rpcb_clnt.c +index 102c3818bc54d..53bcca365fb1c 100644 +--- a/net/sunrpc/rpcb_clnt.c ++++ b/net/sunrpc/rpcb_clnt.c +@@ -820,9 +820,10 @@ static void rpcb_getport_done(struct rpc_task *child, void *data) + } + + trace_rpcb_setport(child, map->r_status, map->r_port); +- xprt->ops->set_port(xprt, map->r_port); +- if (map->r_port) ++ if (map->r_port) { ++ xprt->ops->set_port(xprt, map->r_port); + xprt_set_bound(xprt); ++ } + } + + /* +-- +2.39.5 + diff --git a/queue-6.14/tcp-be-less-liberal-in-tsecr-received-while-in-syn_r.patch b/queue-6.14/tcp-be-less-liberal-in-tsecr-received-while-in-syn_r.patch new file mode 100644 index 0000000000..cc20cfeb78 --- /dev/null +++ b/queue-6.14/tcp-be-less-liberal-in-tsecr-received-while-in-syn_r.patch @@ -0,0 +1,209 @@ +From 476d8290816075cc72ee51959d802d3af2683301 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 25 Feb 2025 17:10:48 +0000 +Subject: tcp: be less liberal in TSEcr received while in SYN_RECV state + +From: Eric Dumazet + +[ Upstream commit 3ba075278c11cdb19e2dbb80362042f1b0c08f74 ] + +Yong-Hao Zou mentioned that linux was not strict as other OS in 3WHS, +for flows using TCP TS option (RFC 7323) + +As hinted by an old comment in tcp_check_req(), +we can check the TSEcr value in the incoming packet corresponds +to one of the SYNACK TSval values we have sent. + +In this patch, I record the oldest and most recent values +that SYNACK packets have used. + +Send a challenge ACK if we receive a TSEcr outside +of this range, and increase a new SNMP counter. + +nstat -az | grep TSEcrRejected +TcpExtTSEcrRejected 0 0.0 + +Due to TCP fastopen implementation, do not apply yet these checks +for fastopen flows. + +v2: No longer use req->num_timeout, but treq->snt_tsval_first + to detect when first SYNACK is prepared. This means + we make sure to not send an initial zero TSval. + Make sure MPTCP and TCP selftests are passing. + Change MIB name to TcpExtTSEcrRejected + +v1: https://lore.kernel.org/netdev/CADVnQykD8i4ArpSZaPKaoNxLJ2if2ts9m4As+=Jvdkrgx1qMHw@mail.gmail.com/T/ + +Reported-by: Yong-Hao Zou +Signed-off-by: Eric Dumazet +Reviewed-by: Matthieu Baerts (NGI0) +Reviewed-by: Neal Cardwell +Reviewed-by: Kuniyuki Iwashima +Link: https://patch.msgid.link/20250225171048.3105061-1-edumazet@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + .../networking/net_cachelines/snmp.rst | 1 + + include/linux/tcp.h | 2 ++ + include/uapi/linux/snmp.h | 1 + + net/ipv4/proc.c | 1 + + net/ipv4/syncookies.c | 1 + + net/ipv4/tcp_input.c | 1 + + net/ipv4/tcp_minisocks.c | 26 +++++++++++-------- + net/ipv4/tcp_output.c | 6 +++++ + 8 files changed, 28 insertions(+), 11 deletions(-) + +diff --git a/Documentation/networking/net_cachelines/snmp.rst b/Documentation/networking/net_cachelines/snmp.rst +index 90ca2d92547d4..bc96efc92cf5b 100644 +--- a/Documentation/networking/net_cachelines/snmp.rst ++++ b/Documentation/networking/net_cachelines/snmp.rst +@@ -36,6 +36,7 @@ unsigned_long LINUX_MIB_TIMEWAITRECYCLED + unsigned_long LINUX_MIB_TIMEWAITKILLED + unsigned_long LINUX_MIB_PAWSACTIVEREJECTED + unsigned_long LINUX_MIB_PAWSESTABREJECTED ++unsigned_long LINUX_MIB_TSECR_REJECTED + unsigned_long LINUX_MIB_DELAYEDACKLOST + unsigned_long LINUX_MIB_LISTENOVERFLOWS + unsigned_long LINUX_MIB_LISTENDROPS +diff --git a/include/linux/tcp.h b/include/linux/tcp.h +index f88daaa76d836..159b2c59eb627 100644 +--- a/include/linux/tcp.h ++++ b/include/linux/tcp.h +@@ -160,6 +160,8 @@ struct tcp_request_sock { + u32 rcv_isn; + u32 snt_isn; + u32 ts_off; ++ u32 snt_tsval_first; ++ u32 snt_tsval_last; + u32 last_oow_ack_time; /* last SYNACK */ + u32 rcv_nxt; /* the ack # by SYNACK. For + * FastOpen it's the seq# +diff --git a/include/uapi/linux/snmp.h b/include/uapi/linux/snmp.h +index 848c7784e684c..eb9fb776fdc3e 100644 +--- a/include/uapi/linux/snmp.h ++++ b/include/uapi/linux/snmp.h +@@ -186,6 +186,7 @@ enum + LINUX_MIB_TIMEWAITKILLED, /* TimeWaitKilled */ + LINUX_MIB_PAWSACTIVEREJECTED, /* PAWSActiveRejected */ + LINUX_MIB_PAWSESTABREJECTED, /* PAWSEstabRejected */ ++ LINUX_MIB_TSECRREJECTED, /* TSEcrRejected */ + LINUX_MIB_PAWS_OLD_ACK, /* PAWSOldAck */ + LINUX_MIB_DELAYEDACKS, /* DelayedACKs */ + LINUX_MIB_DELAYEDACKLOCKED, /* DelayedACKLocked */ +diff --git a/net/ipv4/proc.c b/net/ipv4/proc.c +index affd21a0f5728..10cbeb76c2745 100644 +--- a/net/ipv4/proc.c ++++ b/net/ipv4/proc.c +@@ -189,6 +189,7 @@ static const struct snmp_mib snmp4_net_list[] = { + SNMP_MIB_ITEM("TWKilled", LINUX_MIB_TIMEWAITKILLED), + SNMP_MIB_ITEM("PAWSActive", LINUX_MIB_PAWSACTIVEREJECTED), + SNMP_MIB_ITEM("PAWSEstab", LINUX_MIB_PAWSESTABREJECTED), ++ SNMP_MIB_ITEM("TSEcrRejected", LINUX_MIB_TSECRREJECTED), + SNMP_MIB_ITEM("PAWSOldAck", LINUX_MIB_PAWS_OLD_ACK), + SNMP_MIB_ITEM("DelayedACKs", LINUX_MIB_DELAYEDACKS), + SNMP_MIB_ITEM("DelayedACKLocked", LINUX_MIB_DELAYEDACKLOCKED), +diff --git a/net/ipv4/syncookies.c b/net/ipv4/syncookies.c +index 1948d15f1f281..25976fa7768c9 100644 +--- a/net/ipv4/syncookies.c ++++ b/net/ipv4/syncookies.c +@@ -279,6 +279,7 @@ static int cookie_tcp_reqsk_init(struct sock *sk, struct sk_buff *skb, + ireq->smc_ok = 0; + + treq->snt_synack = 0; ++ treq->snt_tsval_first = 0; + treq->tfo_listener = false; + treq->txhash = net_tx_rndhash(); + treq->rcv_isn = ntohl(th->seq) - 1; +diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c +index 23cf8f4a37214..1b09b4d76c296 100644 +--- a/net/ipv4/tcp_input.c ++++ b/net/ipv4/tcp_input.c +@@ -7089,6 +7089,7 @@ static void tcp_openreq_init(struct request_sock *req, + tcp_rsk(req)->rcv_isn = TCP_SKB_CB(skb)->seq; + tcp_rsk(req)->rcv_nxt = TCP_SKB_CB(skb)->seq + 1; + tcp_rsk(req)->snt_synack = 0; ++ tcp_rsk(req)->snt_tsval_first = 0; + tcp_rsk(req)->last_oow_ack_time = 0; + req->mss = rx_opt->mss_clamp; + req->ts_recent = rx_opt->saw_tstamp ? rx_opt->rcv_tsval : 0; +diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c +index dfdb7a4608a85..0d4ff5f2352f8 100644 +--- a/net/ipv4/tcp_minisocks.c ++++ b/net/ipv4/tcp_minisocks.c +@@ -665,6 +665,7 @@ struct sock *tcp_check_req(struct sock *sk, struct sk_buff *skb, + struct sock *child; + const struct tcphdr *th = tcp_hdr(skb); + __be32 flg = tcp_flag_word(th) & (TCP_FLAG_RST|TCP_FLAG_SYN|TCP_FLAG_ACK); ++ bool tsecr_reject = false; + bool paws_reject = false; + bool own_req; + +@@ -674,8 +675,13 @@ struct sock *tcp_check_req(struct sock *sk, struct sk_buff *skb, + + if (tmp_opt.saw_tstamp) { + tmp_opt.ts_recent = READ_ONCE(req->ts_recent); +- if (tmp_opt.rcv_tsecr) ++ if (tmp_opt.rcv_tsecr) { ++ if (inet_rsk(req)->tstamp_ok && !fastopen) ++ tsecr_reject = !between(tmp_opt.rcv_tsecr, ++ tcp_rsk(req)->snt_tsval_first, ++ READ_ONCE(tcp_rsk(req)->snt_tsval_last)); + tmp_opt.rcv_tsecr -= tcp_rsk(req)->ts_off; ++ } + /* We do not store true stamp, but it is not required, + * it can be estimated (approximately) + * from another data. +@@ -790,18 +796,14 @@ struct sock *tcp_check_req(struct sock *sk, struct sk_buff *skb, + tcp_rsk(req)->snt_isn + 1)) + return sk; + +- /* Also, it would be not so bad idea to check rcv_tsecr, which +- * is essentially ACK extension and too early or too late values +- * should cause reset in unsynchronized states. +- */ +- + /* RFC793: "first check sequence number". */ + +- if (paws_reject || !tcp_in_window(TCP_SKB_CB(skb)->seq, +- TCP_SKB_CB(skb)->end_seq, +- tcp_rsk(req)->rcv_nxt, +- tcp_rsk(req)->rcv_nxt + +- tcp_synack_window(req))) { ++ if (paws_reject || tsecr_reject || ++ !tcp_in_window(TCP_SKB_CB(skb)->seq, ++ TCP_SKB_CB(skb)->end_seq, ++ tcp_rsk(req)->rcv_nxt, ++ tcp_rsk(req)->rcv_nxt + ++ tcp_synack_window(req))) { + /* Out of window: send ACK and drop. */ + if (!(flg & TCP_FLAG_RST) && + !tcp_oow_rate_limited(sock_net(sk), skb, +@@ -810,6 +812,8 @@ struct sock *tcp_check_req(struct sock *sk, struct sk_buff *skb, + req->rsk_ops->send_ack(sk, skb, req); + if (paws_reject) + NET_INC_STATS(sock_net(sk), LINUX_MIB_PAWSESTABREJECTED); ++ else if (tsecr_reject) ++ NET_INC_STATS(sock_net(sk), LINUX_MIB_TSECRREJECTED); + return NULL; + } + +diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c +index bc95d2a5924fd..6031d7f7f5198 100644 +--- a/net/ipv4/tcp_output.c ++++ b/net/ipv4/tcp_output.c +@@ -941,6 +941,12 @@ static unsigned int tcp_synack_options(const struct sock *sk, + opts->options |= OPTION_TS; + opts->tsval = tcp_skb_timestamp_ts(tcp_rsk(req)->req_usec_ts, skb) + + tcp_rsk(req)->ts_off; ++ if (!tcp_rsk(req)->snt_tsval_first) { ++ if (!opts->tsval) ++ opts->tsval = ~0U; ++ tcp_rsk(req)->snt_tsval_first = opts->tsval; ++ } ++ WRITE_ONCE(tcp_rsk(req)->snt_tsval_last, opts->tsval); + opts->tsecr = READ_ONCE(req->ts_recent); + remaining -= TCPOLEN_TSTAMP_ALIGNED; + } +-- +2.39.5 + diff --git a/queue-6.14/tcp-bring-back-numa-dispersion-in-inet_ehash_locks_a.patch b/queue-6.14/tcp-bring-back-numa-dispersion-in-inet_ehash_locks_a.patch new file mode 100644 index 0000000000..6b7e2534e0 --- /dev/null +++ b/queue-6.14/tcp-bring-back-numa-dispersion-in-inet_ehash_locks_a.patch @@ -0,0 +1,105 @@ +From 7e11b230d7a40473c3c68b4a8bfd38efaa35c5e0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Mar 2025 13:05:50 +0000 +Subject: tcp: bring back NUMA dispersion in inet_ehash_locks_alloc() + +From: Eric Dumazet + +[ Upstream commit f8ece40786c9342249aa0a1b55e148ee23b2a746 ] + +We have platforms with 6 NUMA nodes and 480 cpus. + +inet_ehash_locks_alloc() currently allocates a single 64KB page +to hold all ehash spinlocks. This adds more pressure on a single node. + +Change inet_ehash_locks_alloc() to use vmalloc() to spread +the spinlocks on all online nodes, driven by NUMA policies. + +At boot time, NUMA policy is interleave=all, meaning that +tcp_hashinfo.ehash_locks gets hash dispersion on all nodes. + +Tested: + +lack5:~# grep inet_ehash_locks_alloc /proc/vmallocinfo +0x00000000d9aec4d1-0x00000000a828b652 69632 inet_ehash_locks_alloc+0x90/0x100 pages=16 vmalloc N0=2 N1=3 N2=3 N3=3 N4=3 N5=2 + +lack5:~# echo 8192 >/proc/sys/net/ipv4/tcp_child_ehash_entries +lack5:~# numactl --interleave=all unshare -n bash -c "grep inet_ehash_locks_alloc /proc/vmallocinfo" +0x000000004e99d30c-0x00000000763f3279 36864 inet_ehash_locks_alloc+0x90/0x100 pages=8 vmalloc N0=1 N1=2 N2=2 N3=1 N4=1 N5=1 +0x00000000d9aec4d1-0x00000000a828b652 69632 inet_ehash_locks_alloc+0x90/0x100 pages=16 vmalloc N0=2 N1=3 N2=3 N3=3 N4=3 N5=2 + +lack5:~# numactl --interleave=0,5 unshare -n bash -c "grep inet_ehash_locks_alloc /proc/vmallocinfo" +0x00000000fd73a33e-0x0000000004b9a177 36864 inet_ehash_locks_alloc+0x90/0x100 pages=8 vmalloc N0=4 N5=4 +0x00000000d9aec4d1-0x00000000a828b652 69632 inet_ehash_locks_alloc+0x90/0x100 pages=16 vmalloc N0=2 N1=3 N2=3 N3=3 N4=3 N5=2 + +lack5:~# echo 1024 >/proc/sys/net/ipv4/tcp_child_ehash_entries +lack5:~# numactl --interleave=all unshare -n bash -c "grep inet_ehash_locks_alloc /proc/vmallocinfo" +0x00000000db07d7a2-0x00000000ad697d29 8192 inet_ehash_locks_alloc+0x90/0x100 pages=1 vmalloc N2=1 +0x00000000d9aec4d1-0x00000000a828b652 69632 inet_ehash_locks_alloc+0x90/0x100 pages=16 vmalloc N0=2 N1=3 N2=3 N3=3 N4=3 N5=2 + +Signed-off-by: Eric Dumazet +Tested-by: Jason Xing +Reviewed-by: Kuniyuki Iwashima +Link: https://patch.msgid.link/20250305130550.1865988-1-edumazet@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/ipv4/inet_hashtables.c | 37 ++++++++++++++++++++++++++----------- + 1 file changed, 26 insertions(+), 11 deletions(-) + +diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c +index 9bfcfd016e182..2b4a588247639 100644 +--- a/net/ipv4/inet_hashtables.c ++++ b/net/ipv4/inet_hashtables.c +@@ -1230,22 +1230,37 @@ int inet_ehash_locks_alloc(struct inet_hashinfo *hashinfo) + { + unsigned int locksz = sizeof(spinlock_t); + unsigned int i, nblocks = 1; ++ spinlock_t *ptr = NULL; + +- if (locksz != 0) { +- /* allocate 2 cache lines or at least one spinlock per cpu */ +- nblocks = max(2U * L1_CACHE_BYTES / locksz, 1U); +- nblocks = roundup_pow_of_two(nblocks * num_possible_cpus()); ++ if (locksz == 0) ++ goto set_mask; + +- /* no more locks than number of hash buckets */ +- nblocks = min(nblocks, hashinfo->ehash_mask + 1); ++ /* Allocate 2 cache lines or at least one spinlock per cpu. */ ++ nblocks = max(2U * L1_CACHE_BYTES / locksz, 1U) * num_possible_cpus(); + +- hashinfo->ehash_locks = kvmalloc_array(nblocks, locksz, GFP_KERNEL); +- if (!hashinfo->ehash_locks) +- return -ENOMEM; ++ /* At least one page per NUMA node. */ ++ nblocks = max(nblocks, num_online_nodes() * PAGE_SIZE / locksz); ++ ++ nblocks = roundup_pow_of_two(nblocks); ++ ++ /* No more locks than number of hash buckets. */ ++ nblocks = min(nblocks, hashinfo->ehash_mask + 1); + +- for (i = 0; i < nblocks; i++) +- spin_lock_init(&hashinfo->ehash_locks[i]); ++ if (num_online_nodes() > 1) { ++ /* Use vmalloc() to allow NUMA policy to spread pages ++ * on all available nodes if desired. ++ */ ++ ptr = vmalloc_array(nblocks, locksz); ++ } ++ if (!ptr) { ++ ptr = kvmalloc_array(nblocks, locksz, GFP_KERNEL); ++ if (!ptr) ++ return -ENOMEM; + } ++ for (i = 0; i < nblocks; i++) ++ spin_lock_init(&ptr[i]); ++ hashinfo->ehash_locks = ptr; ++set_mask: + hashinfo->ehash_locks_mask = nblocks - 1; + return 0; + } +-- +2.39.5 + diff --git a/queue-6.14/tcp-reorganize-tcp_in_ack_event-and-tcp_count_delive.patch b/queue-6.14/tcp-reorganize-tcp_in_ack_event-and-tcp_count_delive.patch new file mode 100644 index 0000000000..85fc7881e5 --- /dev/null +++ b/queue-6.14/tcp-reorganize-tcp_in_ack_event-and-tcp_count_delive.patch @@ -0,0 +1,155 @@ +From 017111cf65afee4b6f344cfc56272251f7bff005 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Mar 2025 23:38:41 +0100 +Subject: tcp: reorganize tcp_in_ack_event() and tcp_count_delivered() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Ilpo Järvinen + +[ Upstream commit 149dfb31615e22271d2525f078c95ea49bc4db24 ] + +- Move tcp_count_delivered() earlier and split tcp_count_delivered_ce() + out of it +- Move tcp_in_ack_event() later +- While at it, remove the inline from tcp_in_ack_event() and let + the compiler to decide + +Accurate ECN's heuristics does not know if there is going +to be ACE field based CE counter increase or not until after +rtx queue has been processed. Only then the number of ACKed +bytes/pkts is available. As CE or not affects presence of +FLAG_ECE, that information for tcp_in_ack_event is not yet +available in the old location of the call to tcp_in_ack_event(). + +Signed-off-by: Ilpo Järvinen +Signed-off-by: Chia-Yu Chang +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + net/ipv4/tcp_input.c | 56 +++++++++++++++++++++++++------------------- + 1 file changed, 32 insertions(+), 24 deletions(-) + +diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c +index 0cbf81bf3d451..23cf8f4a37214 100644 +--- a/net/ipv4/tcp_input.c ++++ b/net/ipv4/tcp_input.c +@@ -419,6 +419,20 @@ static bool tcp_ecn_rcv_ecn_echo(const struct tcp_sock *tp, const struct tcphdr + return false; + } + ++static void tcp_count_delivered_ce(struct tcp_sock *tp, u32 ecn_count) ++{ ++ tp->delivered_ce += ecn_count; ++} ++ ++/* Updates the delivered and delivered_ce counts */ ++static void tcp_count_delivered(struct tcp_sock *tp, u32 delivered, ++ bool ece_ack) ++{ ++ tp->delivered += delivered; ++ if (ece_ack) ++ tcp_count_delivered_ce(tp, delivered); ++} ++ + /* Buffer size and advertised window tuning. + * + * 1. Tuning sk->sk_sndbuf, when connection enters established state. +@@ -1154,15 +1168,6 @@ void tcp_mark_skb_lost(struct sock *sk, struct sk_buff *skb) + } + } + +-/* Updates the delivered and delivered_ce counts */ +-static void tcp_count_delivered(struct tcp_sock *tp, u32 delivered, +- bool ece_ack) +-{ +- tp->delivered += delivered; +- if (ece_ack) +- tp->delivered_ce += delivered; +-} +- + /* This procedure tags the retransmission queue when SACKs arrive. + * + * We have three tag bits: SACKED(S), RETRANS(R) and LOST(L). +@@ -3862,12 +3867,23 @@ static void tcp_process_tlp_ack(struct sock *sk, u32 ack, int flag) + } + } + +-static inline void tcp_in_ack_event(struct sock *sk, u32 flags) ++static void tcp_in_ack_event(struct sock *sk, int flag) + { + const struct inet_connection_sock *icsk = inet_csk(sk); + +- if (icsk->icsk_ca_ops->in_ack_event) +- icsk->icsk_ca_ops->in_ack_event(sk, flags); ++ if (icsk->icsk_ca_ops->in_ack_event) { ++ u32 ack_ev_flags = 0; ++ ++ if (flag & FLAG_WIN_UPDATE) ++ ack_ev_flags |= CA_ACK_WIN_UPDATE; ++ if (flag & FLAG_SLOWPATH) { ++ ack_ev_flags |= CA_ACK_SLOWPATH; ++ if (flag & FLAG_ECE) ++ ack_ev_flags |= CA_ACK_ECE; ++ } ++ ++ icsk->icsk_ca_ops->in_ack_event(sk, ack_ev_flags); ++ } + } + + /* Congestion control has updated the cwnd already. So if we're in +@@ -3984,12 +4000,8 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag) + tcp_snd_una_update(tp, ack); + flag |= FLAG_WIN_UPDATE; + +- tcp_in_ack_event(sk, CA_ACK_WIN_UPDATE); +- + NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPHPACKS); + } else { +- u32 ack_ev_flags = CA_ACK_SLOWPATH; +- + if (ack_seq != TCP_SKB_CB(skb)->end_seq) + flag |= FLAG_DATA; + else +@@ -4001,19 +4013,12 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag) + flag |= tcp_sacktag_write_queue(sk, skb, prior_snd_una, + &sack_state); + +- if (tcp_ecn_rcv_ecn_echo(tp, tcp_hdr(skb))) { ++ if (tcp_ecn_rcv_ecn_echo(tp, tcp_hdr(skb))) + flag |= FLAG_ECE; +- ack_ev_flags |= CA_ACK_ECE; +- } + + if (sack_state.sack_delivered) + tcp_count_delivered(tp, sack_state.sack_delivered, + flag & FLAG_ECE); +- +- if (flag & FLAG_WIN_UPDATE) +- ack_ev_flags |= CA_ACK_WIN_UPDATE; +- +- tcp_in_ack_event(sk, ack_ev_flags); + } + + /* This is a deviation from RFC3168 since it states that: +@@ -4040,6 +4045,8 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag) + + tcp_rack_update_reo_wnd(sk, &rs); + ++ tcp_in_ack_event(sk, flag); ++ + if (tp->tlp_high_seq) + tcp_process_tlp_ack(sk, ack, flag); + +@@ -4071,6 +4078,7 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag) + return 1; + + no_queue: ++ tcp_in_ack_event(sk, flag); + /* If data was DSACKed, see if we can undo a cwnd reduction. */ + if (flag & FLAG_DSACKING_ACK) { + tcp_fastretrans_alert(sk, prior_snd_una, num_dupack, &flag, +-- +2.39.5 + diff --git a/queue-6.14/thermal-drivers-mediatek-lvts-start-sensor-interrupt.patch b/queue-6.14/thermal-drivers-mediatek-lvts-start-sensor-interrupt.patch new file mode 100644 index 0000000000..86b53641a7 --- /dev/null +++ b/queue-6.14/thermal-drivers-mediatek-lvts-start-sensor-interrupt.patch @@ -0,0 +1,50 @@ +From 1823e72fd611e1a99be6b5a5d2ffe77d57d5d711 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 13 Jan 2025 10:27:15 -0300 +Subject: thermal/drivers/mediatek/lvts: Start sensor interrupts disabled +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Nícolas F. R. A. Prado + +[ Upstream commit 2738fb3ec6838a10d2c4ce65cefdb3b90b11bd61 ] + +Interrupts are enabled per sensor in lvts_update_irq_mask() as needed, +there's no point in enabling all of them during initialization. Change +the MONINT register initial value so all sensor interrupts start +disabled. + +Reviewed-by: AngeloGioacchino Del Regno +Signed-off-by: Nícolas F. R. A. Prado +Link: https://lore.kernel.org/r/20250113-mt8192-lvts-filtered-suspend-fix-v2-4-07a25200c7c6@collabora.com +Signed-off-by: Daniel Lezcano +Signed-off-by: Sasha Levin +--- + drivers/thermal/mediatek/lvts_thermal.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/drivers/thermal/mediatek/lvts_thermal.c b/drivers/thermal/mediatek/lvts_thermal.c +index 0aaa44b734ca4..d0901d8ac85da 100644 +--- a/drivers/thermal/mediatek/lvts_thermal.c ++++ b/drivers/thermal/mediatek/lvts_thermal.c +@@ -65,7 +65,6 @@ + #define LVTS_HW_FILTER 0x0 + #define LVTS_TSSEL_CONF 0x13121110 + #define LVTS_CALSCALE_CONF 0x300 +-#define LVTS_MONINT_CONF 0x0300318C + + #define LVTS_MONINT_OFFSET_SENSOR0 0xC + #define LVTS_MONINT_OFFSET_SENSOR1 0x180 +@@ -929,7 +928,7 @@ static int lvts_irq_init(struct lvts_ctrl *lvts_ctrl) + * The LVTS_MONINT register layout is the same as the LVTS_MONINTSTS + * register, except we set the bits to enable the interrupt. + */ +- writel(LVTS_MONINT_CONF, LVTS_MONINT(lvts_ctrl->base)); ++ writel(0, LVTS_MONINT(lvts_ctrl->base)); + + return 0; + } +-- +2.39.5 + diff --git a/queue-6.14/thermal-drivers-qoriq-power-down-tmu-on-system-suspe.patch b/queue-6.14/thermal-drivers-qoriq-power-down-tmu-on-system-suspe.patch new file mode 100644 index 0000000000..c2bfafcac4 --- /dev/null +++ b/queue-6.14/thermal-drivers-qoriq-power-down-tmu-on-system-suspe.patch @@ -0,0 +1,63 @@ +From 6c437eb9b183aefd4934624385eb7701f13c20b5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 9 Dec 2024 11:48:59 -0500 +Subject: thermal/drivers/qoriq: Power down TMU on system suspend + +From: Alice Guo + +[ Upstream commit 229f3feb4b0442835b27d519679168bea2de96c2 ] + +Enable power-down of TMU (Thermal Management Unit) for TMU version 2 during +system suspend to save power. Save approximately 4.3mW on VDD_ANA_1P8 on +i.MX93 platforms. + +Signed-off-by: Alice Guo +Signed-off-by: Frank Li +Link: https://lore.kernel.org/r/20241209164859.3758906-2-Frank.Li@nxp.com +Signed-off-by: Daniel Lezcano +Signed-off-by: Sasha Levin +--- + drivers/thermal/qoriq_thermal.c | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +diff --git a/drivers/thermal/qoriq_thermal.c b/drivers/thermal/qoriq_thermal.c +index 52e26be8c53df..aed2729f63d06 100644 +--- a/drivers/thermal/qoriq_thermal.c ++++ b/drivers/thermal/qoriq_thermal.c +@@ -18,6 +18,7 @@ + #define SITES_MAX 16 + #define TMR_DISABLE 0x0 + #define TMR_ME 0x80000000 ++#define TMR_CMD BIT(29) + #define TMR_ALPF 0x0c000000 + #define TMR_ALPF_V2 0x03000000 + #define TMTMIR_DEFAULT 0x0000000f +@@ -356,6 +357,12 @@ static int qoriq_tmu_suspend(struct device *dev) + if (ret) + return ret; + ++ if (data->ver > TMU_VER1) { ++ ret = regmap_set_bits(data->regmap, REGS_TMR, TMR_CMD); ++ if (ret) ++ return ret; ++ } ++ + clk_disable_unprepare(data->clk); + + return 0; +@@ -370,6 +377,12 @@ static int qoriq_tmu_resume(struct device *dev) + if (ret) + return ret; + ++ if (data->ver > TMU_VER1) { ++ ret = regmap_clear_bits(data->regmap, REGS_TMR, TMR_CMD); ++ if (ret) ++ return ret; ++ } ++ + /* Enable monitoring */ + return regmap_update_bits(data->regmap, REGS_TMR, TMR_ME, TMR_ME); + } +-- +2.39.5 + diff --git a/queue-6.14/thunderbolt-do-not-add-non-active-nvm-if-nvm-upgrade.patch b/queue-6.14/thunderbolt-do-not-add-non-active-nvm-if-nvm-upgrade.patch new file mode 100644 index 0000000000..c03c2823d1 --- /dev/null +++ b/queue-6.14/thunderbolt-do-not-add-non-active-nvm-if-nvm-upgrade.patch @@ -0,0 +1,42 @@ +From 52173ff99a637d0b433ffbd256dd27ccdf4d1bf3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Mar 2025 14:56:20 +0200 +Subject: thunderbolt: Do not add non-active NVM if NVM upgrade is disabled for + retimer + +From: Mika Westerberg + +[ Upstream commit ad79c278e478ca8c1a3bf8e7a0afba8f862a48a1 ] + +This is only used to write a new NVM in order to upgrade the retimer +firmware. It does not make sense to expose it if upgrade is disabled. +This also makes it consistent with the router NVM upgrade. + +Signed-off-by: Mika Westerberg +Signed-off-by: Sasha Levin +--- + drivers/thunderbolt/retimer.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +diff --git a/drivers/thunderbolt/retimer.c b/drivers/thunderbolt/retimer.c +index 1f25529fe05da..361fece3d8188 100644 +--- a/drivers/thunderbolt/retimer.c ++++ b/drivers/thunderbolt/retimer.c +@@ -93,9 +93,11 @@ static int tb_retimer_nvm_add(struct tb_retimer *rt) + if (ret) + goto err_nvm; + +- ret = tb_nvm_add_non_active(nvm, nvm_write); +- if (ret) +- goto err_nvm; ++ if (!rt->no_nvm_upgrade) { ++ ret = tb_nvm_add_non_active(nvm, nvm_write); ++ if (ret) ++ goto err_nvm; ++ } + + rt->nvm = nvm; + dev_dbg(&rt->dev, "NVM version %x.%x\n", nvm->major, nvm->minor); +-- +2.39.5 + diff --git a/queue-6.14/timer_list-don-t-use-pk-through-printk.patch b/queue-6.14/timer_list-don-t-use-pk-through-printk.patch new file mode 100644 index 0000000000..e12c4d9611 --- /dev/null +++ b/queue-6.14/timer_list-don-t-use-pk-through-printk.patch @@ -0,0 +1,65 @@ +From e2775bc4f1bfe8e9dc65b105c19d8a0b20f7a633 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 11 Mar 2025 10:54:47 +0100 +Subject: timer_list: Don't use %pK through printk() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Thomas Weißschuh + +[ Upstream commit a52067c24ccf6ee4c85acffa0f155e9714f9adce ] + +This reverts commit f590308536db ("timer debug: Hide kernel addresses via +%pK in /proc/timer_list") + +The timer list helper SEQ_printf() uses either the real seq_printf() for +procfs output or vprintk() to print to the kernel log, when invoked from +SysRq-q. It uses %pK for printing pointers. + +In the past %pK was prefered over %p as it would not leak raw pointer +values into the kernel log. Since commit ad67b74d2469 ("printk: hash +addresses printed with %p") the regular %p has been improved to avoid this +issue. + +Furthermore, restricted pointers ("%pK") were never meant to be used +through printk(). They can still unintentionally leak raw pointers or +acquire sleeping looks in atomic contexts. + +Switch to the regular pointer formatting which is safer, easier to reason +about and sufficient here. + +Signed-off-by: Thomas Weißschuh +Signed-off-by: Thomas Gleixner +Link: https://lore.kernel.org/lkml/20250113171731-dc10e3c1-da64-4af0-b767-7c7070468023@linutronix.de/ +Link: https://lore.kernel.org/all/20250311-restricted-pointers-timer-v1-1-6626b91e54ab@linutronix.de +Signed-off-by: Sasha Levin +--- + kernel/time/timer_list.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/kernel/time/timer_list.c b/kernel/time/timer_list.c +index 1c311c46da507..cfbb46cc4e761 100644 +--- a/kernel/time/timer_list.c ++++ b/kernel/time/timer_list.c +@@ -46,7 +46,7 @@ static void + print_timer(struct seq_file *m, struct hrtimer *taddr, struct hrtimer *timer, + int idx, u64 now) + { +- SEQ_printf(m, " #%d: <%pK>, %ps", idx, taddr, timer->function); ++ SEQ_printf(m, " #%d: <%p>, %ps", idx, taddr, timer->function); + SEQ_printf(m, ", S:%02x", timer->state); + SEQ_printf(m, "\n"); + SEQ_printf(m, " # expires at %Lu-%Lu nsecs [in %Ld to %Ld nsecs]\n", +@@ -98,7 +98,7 @@ print_active_timers(struct seq_file *m, struct hrtimer_clock_base *base, + static void + print_base(struct seq_file *m, struct hrtimer_clock_base *base, u64 now) + { +- SEQ_printf(m, " .base: %pK\n", base); ++ SEQ_printf(m, " .base: %p\n", base); + SEQ_printf(m, " .index: %d\n", base->index); + + SEQ_printf(m, " .resolution: %u nsecs\n", hrtimer_resolution); +-- +2.39.5 + diff --git a/queue-6.14/tools-build-don-t-pass-test-log-files-to-linker.patch b/queue-6.14/tools-build-don-t-pass-test-log-files-to-linker.patch new file mode 100644 index 0000000000..925aac124b --- /dev/null +++ b/queue-6.14/tools-build-don-t-pass-test-log-files-to-linker.patch @@ -0,0 +1,48 @@ +From 3d702b4757066eac0638436630fbbd660fcc09e3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 11 Mar 2025 14:36:23 -0700 +Subject: tools/build: Don't pass test log files to linker + +From: Ian Rogers + +[ Upstream commit 935e7cb5bb80106ff4f2fe39640f430134ef8cd8 ] + +Separate test log files from object files. Depend on test log output +but don't pass to the linker. + +Reviewed-by: James Clark +Signed-off-by: Ian Rogers +Link: https://lore.kernel.org/r/20250311213628.569562-2-irogers@google.com +Signed-off-by: Namhyung Kim +Signed-off-by: Sasha Levin +--- + tools/build/Makefile.build | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/tools/build/Makefile.build b/tools/build/Makefile.build +index e710ed67a1b49..3584ff3086078 100644 +--- a/tools/build/Makefile.build ++++ b/tools/build/Makefile.build +@@ -129,6 +129,10 @@ objprefix := $(subst ./,,$(OUTPUT)$(dir)/) + obj-y := $(addprefix $(objprefix),$(obj-y)) + subdir-obj-y := $(addprefix $(objprefix),$(subdir-obj-y)) + ++# Separate out test log files from real build objects. ++test-y := $(filter %_log, $(obj-y)) ++obj-y := $(filter-out %_log, $(obj-y)) ++ + # Final '$(obj)-in.o' object + in-target := $(objprefix)$(obj)-in.o + +@@ -139,7 +143,7 @@ $(subdir-y): + + $(sort $(subdir-obj-y)): $(subdir-y) ; + +-$(in-target): $(obj-y) FORCE ++$(in-target): $(obj-y) $(test-y) FORCE + $(call rule_mkdir) + $(call if_changed,$(host)ld_multi) + +-- +2.39.5 + diff --git a/queue-6.14/tools-power-turbostat-clustered-uncore-mhz-counters-.patch b/queue-6.14/tools-power-turbostat-clustered-uncore-mhz-counters-.patch new file mode 100644 index 0000000000..cdaf393ab5 --- /dev/null +++ b/queue-6.14/tools-power-turbostat-clustered-uncore-mhz-counters-.patch @@ -0,0 +1,84 @@ +From a6b4419ce4f9ee417ae4493d86428febdfc58aac Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Feb 2025 21:46:24 -0600 +Subject: tools/power turbostat: Clustered Uncore MHz counters should honor + show/hide options +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Len Brown + +[ Upstream commit 1c7c7388e6c31f46b26a884d80b45efbad8237b2 ] + +The clustered uncore frequency counters, UMHz*.* +should honor the --show and --hide options. + +All non-specified counters should be implicityly hidden. +But when --show was used, UMHz*.* showed up anyway: + +$ sudo turbostat -q -S --show Busy% +Busy%  UMHz0.0  UMHz1.0  UMHz2.0  UMHz3.0  UMHz4.0 + +Indeed, there was no string that can be used to explicitly +show or hide clustered uncore counters. + +Even through they are dynamically probed and added, +group the clustered UMHz*.* counters with the legacy +built-in-counter "UncMHz" for show/hide. + +turbostat --show Busy% + does not show UMHz*.*. +turbostat --show UncMHz + shows either UncMHz or UMHz*.*, if present +turbostat --hide UncMHz + hides either UncMHz or UMHz*.*, if present + +Reported-by: Artem Bityutskiy +Signed-off-by: Len Brown +Tested-by: Artem Bityutskiy +Signed-off-by: Sasha Levin +--- + tools/power/x86/turbostat/turbostat.8 | 1 + + tools/power/x86/turbostat/turbostat.c | 13 ++++++++++++- + 2 files changed, 13 insertions(+), 1 deletion(-) + +diff --git a/tools/power/x86/turbostat/turbostat.8 b/tools/power/x86/turbostat/turbostat.8 +index e4f9f93c123a2..abee03ddc7f09 100644 +--- a/tools/power/x86/turbostat/turbostat.8 ++++ b/tools/power/x86/turbostat/turbostat.8 +@@ -201,6 +201,7 @@ The system configuration dump (if --quiet is not used) is followed by statistics + \fBUncMHz\fP per-package uncore MHz, instantaneous sample. + .PP + \fBUMHz1.0\fP per-package uncore MHz for domain=1 and fabric_cluster=0, instantaneous sample. System summary is the average of all packages. ++For the "--show" and "--hide" options, use "UncMHz" to operate on all UMHz*.* as a group. + .SH TOO MUCH INFORMATION EXAMPLE + By default, turbostat dumps all possible information -- a system configuration header, followed by columns for all counters. + This is ideal for remote debugging, use the "--out" option to save everything to a text file, and get that file to the expert helping you debug. +diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c +index 4155d9bfcfc6d..505b07b5be19b 100644 +--- a/tools/power/x86/turbostat/turbostat.c ++++ b/tools/power/x86/turbostat/turbostat.c +@@ -6713,7 +6713,18 @@ static void probe_intel_uncore_frequency_cluster(void) + sprintf(path, "%s/current_freq_khz", path_base); + sprintf(name_buf, "UMHz%d.%d", domain_id, cluster_id); + +- add_counter(0, path, name_buf, 0, SCOPE_PACKAGE, COUNTER_K2M, FORMAT_AVERAGE, 0, package_id); ++ /* ++ * Once add_couter() is called, that counter is always read ++ * and reported -- So it is effectively (enabled & present). ++ * Only call add_counter() here if legacy BIC_UNCORE_MHZ (UncMHz) ++ * is (enabled). Since we are in this routine, we ++ * know we will not probe and set (present) the legacy counter. ++ * ++ * This allows "--show/--hide UncMHz" to be effective for ++ * the clustered MHz counters, as a group. ++ */ ++ if BIC_IS_ENABLED(BIC_UNCORE_MHZ) ++ add_counter(0, path, name_buf, 0, SCOPE_PACKAGE, COUNTER_K2M, FORMAT_AVERAGE, 0, package_id); + + if (quiet) + continue; +-- +2.39.5 + diff --git a/queue-6.14/tools-ynl-gen-don-t-output-external-constants.patch b/queue-6.14/tools-ynl-gen-don-t-output-external-constants.patch new file mode 100644 index 0000000000..9321e0c237 --- /dev/null +++ b/queue-6.14/tools-ynl-gen-don-t-output-external-constants.patch @@ -0,0 +1,40 @@ +From dbab61b04f2e2ce57a47353afb6661207173fad8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 3 Feb 2025 13:55:09 -0800 +Subject: tools: ynl-gen: don't output external constants + +From: Jakub Kicinski + +[ Upstream commit 7e8b24e24ac46038e48c9a042e7d9b31855cbca5 ] + +A definition with a "header" property is an "external" definition +for C code, as in it is defined already in another C header file. +Other languages will need the exact value but C codegen should +not recreate it. So don't output those definitions in the uAPI +header. + +Signed-off-by: Jakub Kicinski +Link: https://patch.msgid.link/20250203215510.1288728-1-kuba@kernel.org +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + tools/net/ynl/pyynl/ynl_gen_c.py | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/tools/net/ynl/pyynl/ynl_gen_c.py b/tools/net/ynl/pyynl/ynl_gen_c.py +index c2eabc90dce8c..aa08b8b1463d0 100755 +--- a/tools/net/ynl/pyynl/ynl_gen_c.py ++++ b/tools/net/ynl/pyynl/ynl_gen_c.py +@@ -2549,6 +2549,9 @@ def render_uapi(family, cw): + + defines = [] + for const in family['definitions']: ++ if const.get('header'): ++ continue ++ + if const['type'] != 'const': + cw.writes_defines(defines) + defines = [] +-- +2.39.5 + diff --git a/queue-6.14/tools-ynl-gen-validate-0-len-strings-from-kernel.patch b/queue-6.14/tools-ynl-gen-validate-0-len-strings-from-kernel.patch new file mode 100644 index 0000000000..06322f3d8d --- /dev/null +++ b/queue-6.14/tools-ynl-gen-validate-0-len-strings-from-kernel.patch @@ -0,0 +1,38 @@ +From 892a1a58dfb108bf55e41fd74c09dca63b7d1f0f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 2 May 2025 21:30:50 -0700 +Subject: tools: ynl-gen: validate 0 len strings from kernel + +From: David Wei + +[ Upstream commit 4720f9707c783f642332dee3d56dccaefa850e42 ] + +Strings from the kernel are guaranteed to be null terminated and +ynl_attr_validate() checks for this. But it doesn't check if the string +has a len of 0, which would cause problems when trying to access +data[len - 1]. Fix this by checking that len is positive. + +Signed-off-by: David Wei +Link: https://patch.msgid.link/20250503043050.861238-1-dw@davidwei.uk +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + tools/net/ynl/lib/ynl.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tools/net/ynl/lib/ynl.c b/tools/net/ynl/lib/ynl.c +index ce32cb35007d6..c4da34048ef85 100644 +--- a/tools/net/ynl/lib/ynl.c ++++ b/tools/net/ynl/lib/ynl.c +@@ -364,7 +364,7 @@ int ynl_attr_validate(struct ynl_parse_arg *yarg, const struct nlattr *attr) + "Invalid attribute (binary %s)", policy->name); + return -1; + case YNL_PT_NUL_STR: +- if ((!policy->len || len <= policy->len) && !data[len - 1]) ++ if (len && (!policy->len || len <= policy->len) && !data[len - 1]) + break; + yerr(yarg->ys, YNL_ERROR_ATTR_INVALID, + "Invalid attribute (string %s)", policy->name); +-- +2.39.5 + diff --git a/queue-6.14/tpm-convert-warn-to-dbg-in-tpm2_start_auth_session.patch b/queue-6.14/tpm-convert-warn-to-dbg-in-tpm2_start_auth_session.patch new file mode 100644 index 0000000000..9c5d4d3bf8 --- /dev/null +++ b/queue-6.14/tpm-convert-warn-to-dbg-in-tpm2_start_auth_session.patch @@ -0,0 +1,47 @@ +From 0fe5d7ef69b3e0748045d57a7287a4b952946056 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 7 Mar 2025 10:56:44 +0000 +Subject: tpm: Convert warn to dbg in tpm2_start_auth_session() + +From: Jonathan McDowell + +[ Upstream commit 6359691b4fbcaf3ed86f53043a1f7c6cc54c09be ] + +TPM2 sessions have been flushed lazily since commit df745e25098dc ("tpm: +Lazily flush the auth session"). If /dev/tpm{rm}0 is not accessed +in-between two in-kernel calls, it is possible that a TPM2 session is +re-started before the previous one has been completed. + +This causes a spurios warning in a legit run-time condition, which is also +correctly addressed with a fast return path: + +[ 2.944047] tpm tpm0: auth session is active + +Address the issue by changing dev_warn_once() call to a dev_dbg_once() +call. + +[jarkko: Rewrote the commit message, and instead of dropping converted + to a debug message.] +Signed-off-by: Jonathan McDowell +Signed-off-by: Jarkko Sakkinen +Signed-off-by: Sasha Levin +--- + drivers/char/tpm/tpm2-sessions.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/char/tpm/tpm2-sessions.c b/drivers/char/tpm/tpm2-sessions.c +index a894dbc40e43b..7b5049b3d476e 100644 +--- a/drivers/char/tpm/tpm2-sessions.c ++++ b/drivers/char/tpm/tpm2-sessions.c +@@ -974,7 +974,7 @@ int tpm2_start_auth_session(struct tpm_chip *chip) + int rc; + + if (chip->auth) { +- dev_warn_once(&chip->dev, "auth session is active\n"); ++ dev_dbg_once(&chip->dev, "auth session is active\n"); + return 0; + } + +-- +2.39.5 + diff --git a/queue-6.14/tracing-mark-binary-printing-functions-with-__printf.patch b/queue-6.14/tracing-mark-binary-printing-functions-with-__printf.patch new file mode 100644 index 0000000000..fe2c683470 --- /dev/null +++ b/queue-6.14/tracing-mark-binary-printing-functions-with-__printf.patch @@ -0,0 +1,158 @@ +From c426debe58a60bdd4eb36a9d9c0ece447f7889a4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 21 Mar 2025 16:40:49 +0200 +Subject: tracing: Mark binary printing functions with __printf() attribute +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Andy Shevchenko + +[ Upstream commit 196a062641fe68d9bfe0ad36b6cd7628c99ad22c ] + +Binary printing functions are using printf() type of format, and compiler +is not happy about them as is: + +kernel/trace/trace.c:3292:9: error: function ‘trace_vbprintk’ might be a candidate for ‘gnu_printf’ format attribute [-Werror=suggest-attribute=format] +kernel/trace/trace_seq.c:182:9: error: function ‘trace_seq_bprintf’ might be a candidate for ‘gnu_printf’ format attribute [-Werror=suggest-attribute=format] + +Fix the compilation errors by adding __printf() attribute. + +While at it, move existing __printf() attributes from the implementations +to the declarations. IT also fixes incorrect attribute parameters that are +used for trace_array_printk(). + +Signed-off-by: Andy Shevchenko +Reviewed-by: Kees Cook +Reviewed-by: Petr Mladek +Link: https://lore.kernel.org/r/20250321144822.324050-4-andriy.shevchenko@linux.intel.com +Signed-off-by: Petr Mladek +Signed-off-by: Sasha Levin +--- + include/linux/trace.h | 4 ++-- + include/linux/trace_seq.h | 8 ++++---- + kernel/trace/trace.c | 11 +++-------- + kernel/trace/trace.h | 16 +++++++++------- + 4 files changed, 18 insertions(+), 21 deletions(-) + +diff --git a/include/linux/trace.h b/include/linux/trace.h +index fdcd76b7be83d..7eaad857dee04 100644 +--- a/include/linux/trace.h ++++ b/include/linux/trace.h +@@ -72,8 +72,8 @@ static inline int unregister_ftrace_export(struct trace_export *export) + static inline void trace_printk_init_buffers(void) + { + } +-static inline int trace_array_printk(struct trace_array *tr, unsigned long ip, +- const char *fmt, ...) ++static inline __printf(3, 4) ++int trace_array_printk(struct trace_array *tr, unsigned long ip, const char *fmt, ...) + { + return 0; + } +diff --git a/include/linux/trace_seq.h b/include/linux/trace_seq.h +index 1ef95c0287f05..a93ed5ac32265 100644 +--- a/include/linux/trace_seq.h ++++ b/include/linux/trace_seq.h +@@ -88,8 +88,8 @@ extern __printf(2, 3) + void trace_seq_printf(struct trace_seq *s, const char *fmt, ...); + extern __printf(2, 0) + void trace_seq_vprintf(struct trace_seq *s, const char *fmt, va_list args); +-extern void +-trace_seq_bprintf(struct trace_seq *s, const char *fmt, const u32 *binary); ++extern __printf(2, 0) ++void trace_seq_bprintf(struct trace_seq *s, const char *fmt, const u32 *binary); + extern int trace_print_seq(struct seq_file *m, struct trace_seq *s); + extern int trace_seq_to_user(struct trace_seq *s, char __user *ubuf, + int cnt); +@@ -113,8 +113,8 @@ static inline __printf(2, 3) + void trace_seq_printf(struct trace_seq *s, const char *fmt, ...) + { + } +-static inline void +-trace_seq_bprintf(struct trace_seq *s, const char *fmt, const u32 *binary) ++static inline __printf(2, 0) ++void trace_seq_bprintf(struct trace_seq *s, const char *fmt, const u32 *binary) + { + } + +diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c +index c3f1365ec9609..b1738563bdc3b 100644 +--- a/kernel/trace/trace.c ++++ b/kernel/trace/trace.c +@@ -3322,10 +3322,9 @@ int trace_vbprintk(unsigned long ip, const char *fmt, va_list args) + } + EXPORT_SYMBOL_GPL(trace_vbprintk); + +-__printf(3, 0) +-static int +-__trace_array_vprintk(struct trace_buffer *buffer, +- unsigned long ip, const char *fmt, va_list args) ++static __printf(3, 0) ++int __trace_array_vprintk(struct trace_buffer *buffer, ++ unsigned long ip, const char *fmt, va_list args) + { + struct ring_buffer_event *event; + int len = 0, size; +@@ -3375,7 +3374,6 @@ __trace_array_vprintk(struct trace_buffer *buffer, + return len; + } + +-__printf(3, 0) + int trace_array_vprintk(struct trace_array *tr, + unsigned long ip, const char *fmt, va_list args) + { +@@ -3405,7 +3403,6 @@ int trace_array_vprintk(struct trace_array *tr, + * Note, trace_array_init_printk() must be called on @tr before this + * can be used. + */ +-__printf(3, 0) + int trace_array_printk(struct trace_array *tr, + unsigned long ip, const char *fmt, ...) + { +@@ -3450,7 +3447,6 @@ int trace_array_init_printk(struct trace_array *tr) + } + EXPORT_SYMBOL_GPL(trace_array_init_printk); + +-__printf(3, 4) + int trace_array_printk_buf(struct trace_buffer *buffer, + unsigned long ip, const char *fmt, ...) + { +@@ -3466,7 +3462,6 @@ int trace_array_printk_buf(struct trace_buffer *buffer, + return ret; + } + +-__printf(2, 0) + int trace_vprintk(unsigned long ip, const char *fmt, va_list args) + { + return trace_array_vprintk(printk_trace, ip, fmt, args); +diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h +index abe8169c3e879..ccf3874823f5f 100644 +--- a/kernel/trace/trace.h ++++ b/kernel/trace/trace.h +@@ -837,13 +837,15 @@ static inline void __init disable_tracing_selftest(const char *reason) + + extern void *head_page(struct trace_array_cpu *data); + extern unsigned long long ns2usecs(u64 nsec); +-extern int +-trace_vbprintk(unsigned long ip, const char *fmt, va_list args); +-extern int +-trace_vprintk(unsigned long ip, const char *fmt, va_list args); +-extern int +-trace_array_vprintk(struct trace_array *tr, +- unsigned long ip, const char *fmt, va_list args); ++ ++__printf(2, 0) ++int trace_vbprintk(unsigned long ip, const char *fmt, va_list args); ++__printf(2, 0) ++int trace_vprintk(unsigned long ip, const char *fmt, va_list args); ++__printf(3, 0) ++int trace_array_vprintk(struct trace_array *tr, ++ unsigned long ip, const char *fmt, va_list args); ++__printf(3, 4) + int trace_array_printk_buf(struct trace_buffer *buffer, + unsigned long ip, const char *fmt, ...); + void trace_printk_seq(struct trace_seq *s); +-- +2.39.5 + diff --git a/queue-6.14/ublk-complete-command-synchronously-on-error.patch b/queue-6.14/ublk-complete-command-synchronously-on-error.patch new file mode 100644 index 0000000000..95069eeb7a --- /dev/null +++ b/queue-6.14/ublk-complete-command-synchronously-on-error.patch @@ -0,0 +1,74 @@ +From 0399853a460c8aab3b99358b51653516c9b22553 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 25 Feb 2025 14:24:55 -0700 +Subject: ublk: complete command synchronously on error + +From: Caleb Sander Mateos + +[ Upstream commit 603f9be21c1894e462416e3324962d6c9c2b95f8 ] + +In case of an error, ublk's ->uring_cmd() functions currently return +-EIOCBQUEUED and immediately call io_uring_cmd_done(). -EIOCBQUEUED and +io_uring_cmd_done() are intended for asynchronous completions. For +synchronous completions, the ->uring_cmd() function can just return the +negative return code directly. This skips io_uring_cmd_del_cancelable(), +and deferring the completion to task work. So return the error code +directly from __ublk_ch_uring_cmd() and ublk_ctrl_uring_cmd(). + +Update ublk_ch_uring_cmd_cb(), which currently ignores the return value +from __ublk_ch_uring_cmd(), to call io_uring_cmd_done() for synchronous +completions. + +Signed-off-by: Caleb Sander Mateos +Reviewed-by: Ming Lei +Reviewed-by: Keith Busch +Link: https://lore.kernel.org/r/20250225212456.2902549-1-csander@purestorage.com +Signed-off-by: Jens Axboe +Signed-off-by: Sasha Levin +--- + drivers/block/ublk_drv.c | 11 ++++++----- + 1 file changed, 6 insertions(+), 5 deletions(-) + +diff --git a/drivers/block/ublk_drv.c b/drivers/block/ublk_drv.c +index b462f7d16ee55..08694d7d18db4 100644 +--- a/drivers/block/ublk_drv.c ++++ b/drivers/block/ublk_drv.c +@@ -2053,10 +2053,9 @@ static int __ublk_ch_uring_cmd(struct io_uring_cmd *cmd, + return -EIOCBQUEUED; + + out: +- io_uring_cmd_done(cmd, ret, 0, issue_flags); + pr_devel("%s: complete: cmd op %d, tag %d ret %x io_flags %x\n", + __func__, cmd_op, tag, ret, io->flags); +- return -EIOCBQUEUED; ++ return ret; + } + + static inline struct request *__ublk_check_and_get_req(struct ublk_device *ub, +@@ -2112,7 +2111,10 @@ static inline int ublk_ch_uring_cmd_local(struct io_uring_cmd *cmd, + static void ublk_ch_uring_cmd_cb(struct io_uring_cmd *cmd, + unsigned int issue_flags) + { +- ublk_ch_uring_cmd_local(cmd, issue_flags); ++ int ret = ublk_ch_uring_cmd_local(cmd, issue_flags); ++ ++ if (ret != -EIOCBQUEUED) ++ io_uring_cmd_done(cmd, ret, 0, issue_flags); + } + + static int ublk_ch_uring_cmd(struct io_uring_cmd *cmd, unsigned int issue_flags) +@@ -3201,10 +3203,9 @@ static int ublk_ctrl_uring_cmd(struct io_uring_cmd *cmd, + if (ub) + ublk_put_device(ub); + out: +- io_uring_cmd_done(cmd, ret, 0, issue_flags); + pr_devel("%s: cmd done ret %d cmd_op %x, dev id %d qid %d\n", + __func__, ret, cmd->cmd_op, header->dev_id, header->queue_id); +- return -EIOCBQUEUED; ++ return ret; + } + + static const struct file_operations ublk_ctl_fops = { +-- +2.39.5 + diff --git a/queue-6.14/ublk-enforce-ublks_max-only-for-unprivileged-devices.patch b/queue-6.14/ublk-enforce-ublks_max-only-for-unprivileged-devices.patch new file mode 100644 index 0000000000..2d61cc2692 --- /dev/null +++ b/queue-6.14/ublk-enforce-ublks_max-only-for-unprivileged-devices.patch @@ -0,0 +1,134 @@ +From 9513bae680bc9a57ce79630337e7582e3d3ab88b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 28 Feb 2025 21:31:48 -0700 +Subject: ublk: enforce ublks_max only for unprivileged devices + +From: Uday Shankar + +[ Upstream commit 80bdfbb3545b6f16680a72c825063d08a6b44c7a ] + +Commit 403ebc877832 ("ublk_drv: add module parameter of ublks_max for +limiting max allowed ublk dev"), claimed ublks_max was added to prevent +a DoS situation with an untrusted user creating too many ublk devices. +If that's the case, ublks_max should only restrict the number of +unprivileged ublk devices in the system. Enforce the limit only for +unprivileged ublk devices, and rename variables accordingly. Leave the +external-facing parameter name unchanged, since changing it may break +systems which use it (but still update its documentation to reflect its +new meaning). + +As a result of this change, in a system where there are only normal +(non-unprivileged) devices, the maximum number of such devices is +increased to 1 << MINORBITS, or 1048576. That ought to be enough for +anyone, right? + +Signed-off-by: Uday Shankar +Reviewed-by: Ming Lei +Link: https://lore.kernel.org/r/20250228-ublks_max-v1-1-04b7379190c0@purestorage.com +Signed-off-by: Jens Axboe +Signed-off-by: Sasha Levin +--- + drivers/block/ublk_drv.c | 42 ++++++++++++++++++++++++++-------------- + 1 file changed, 27 insertions(+), 15 deletions(-) + +diff --git a/drivers/block/ublk_drv.c b/drivers/block/ublk_drv.c +index 7bbfc20f116a4..b462f7d16ee55 100644 +--- a/drivers/block/ublk_drv.c ++++ b/drivers/block/ublk_drv.c +@@ -490,15 +490,17 @@ static wait_queue_head_t ublk_idr_wq; /* wait until one idr is freed */ + + static DEFINE_MUTEX(ublk_ctl_mutex); + ++ ++#define UBLK_MAX_UBLKS UBLK_MINORS ++ + /* +- * Max ublk devices allowed to add ++ * Max unprivileged ublk devices allowed to add + * + * It can be extended to one per-user limit in future or even controlled + * by cgroup. + */ +-#define UBLK_MAX_UBLKS UBLK_MINORS +-static unsigned int ublks_max = 64; +-static unsigned int ublks_added; /* protected by ublk_ctl_mutex */ ++static unsigned int unprivileged_ublks_max = 64; ++static unsigned int unprivileged_ublks_added; /* protected by ublk_ctl_mutex */ + + static struct miscdevice ublk_misc; + +@@ -2375,7 +2377,8 @@ static int ublk_add_chdev(struct ublk_device *ub) + if (ret) + goto fail; + +- ublks_added++; ++ if (ub->dev_info.flags & UBLK_F_UNPRIVILEGED_DEV) ++ unprivileged_ublks_added++; + return 0; + fail: + put_device(dev); +@@ -2404,10 +2407,15 @@ static int ublk_add_tag_set(struct ublk_device *ub) + + static void ublk_remove(struct ublk_device *ub) + { ++ bool unprivileged; ++ + ublk_stop_dev(ub); + cdev_device_del(&ub->cdev, &ub->cdev_dev); ++ unprivileged = ub->dev_info.flags & UBLK_F_UNPRIVILEGED_DEV; + ublk_put_device(ub); +- ublks_added--; ++ ++ if (unprivileged) ++ unprivileged_ublks_added--; + } + + static struct ublk_device *ublk_get_device_from_id(int idx) +@@ -2669,7 +2677,8 @@ static int ublk_ctrl_add_dev(struct io_uring_cmd *cmd) + return ret; + + ret = -EACCES; +- if (ublks_added >= ublks_max) ++ if ((info.flags & UBLK_F_UNPRIVILEGED_DEV) && ++ unprivileged_ublks_added >= unprivileged_ublks_max) + goto out_unlock; + + ret = -ENOMEM; +@@ -3259,23 +3268,26 @@ static void __exit ublk_exit(void) + module_init(ublk_init); + module_exit(ublk_exit); + +-static int ublk_set_max_ublks(const char *buf, const struct kernel_param *kp) ++static int ublk_set_max_unprivileged_ublks(const char *buf, ++ const struct kernel_param *kp) + { + return param_set_uint_minmax(buf, kp, 0, UBLK_MAX_UBLKS); + } + +-static int ublk_get_max_ublks(char *buf, const struct kernel_param *kp) ++static int ublk_get_max_unprivileged_ublks(char *buf, ++ const struct kernel_param *kp) + { +- return sysfs_emit(buf, "%u\n", ublks_max); ++ return sysfs_emit(buf, "%u\n", unprivileged_ublks_max); + } + +-static const struct kernel_param_ops ublk_max_ublks_ops = { +- .set = ublk_set_max_ublks, +- .get = ublk_get_max_ublks, ++static const struct kernel_param_ops ublk_max_unprivileged_ublks_ops = { ++ .set = ublk_set_max_unprivileged_ublks, ++ .get = ublk_get_max_unprivileged_ublks, + }; + +-module_param_cb(ublks_max, &ublk_max_ublks_ops, &ublks_max, 0644); +-MODULE_PARM_DESC(ublks_max, "max number of ublk devices allowed to add(default: 64)"); ++module_param_cb(ublks_max, &ublk_max_unprivileged_ublks_ops, ++ &unprivileged_ublks_max, 0644); ++MODULE_PARM_DESC(ublks_max, "max number of unprivileged ublk devices allowed to add(default: 64)"); + + MODULE_AUTHOR("Ming Lei "); + MODULE_DESCRIPTION("Userspace block device"); +-- +2.39.5 + diff --git a/queue-6.14/um-store-full-csgsfs-and-ss-register-from-mcontext.patch b/queue-6.14/um-store-full-csgsfs-and-ss-register-from-mcontext.patch new file mode 100644 index 0000000000..f6c07b48e7 --- /dev/null +++ b/queue-6.14/um-store-full-csgsfs-and-ss-register-from-mcontext.patch @@ -0,0 +1,40 @@ +From 28d4fa564c8a2230a490b23404bd5b8e64c60060 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 24 Feb 2025 19:18:19 +0100 +Subject: um: Store full CSGSFS and SS register from mcontext + +From: Benjamin Berg + +[ Upstream commit cef721e0d53d2b64f2ba177c63a0dfdd7c0daf17 ] + +Doing this allows using registers as retrieved from an mcontext to be +pushed to a process using PTRACE_SETREGS. + +It is not entirely clear to me why CSGSFS was masked. Doing so creates +issues when using the mcontext as process state in seccomp and simply +copying the register appears to work perfectly fine for ptrace. + +Signed-off-by: Benjamin Berg +Link: https://patch.msgid.link/20250224181827.647129-2-benjamin@sipsolutions.net +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + arch/x86/um/os-Linux/mcontext.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/arch/x86/um/os-Linux/mcontext.c b/arch/x86/um/os-Linux/mcontext.c +index e80ab7d281177..1b0d95328b2c7 100644 +--- a/arch/x86/um/os-Linux/mcontext.c ++++ b/arch/x86/um/os-Linux/mcontext.c +@@ -27,7 +27,6 @@ void get_regs_from_mc(struct uml_pt_regs *regs, mcontext_t *mc) + COPY(RIP); + COPY2(EFLAGS, EFL); + COPY2(CS, CSGSFS); +- regs->gp[CS / sizeof(unsigned long)] &= 0xffff; +- regs->gp[CS / sizeof(unsigned long)] |= 3; ++ regs->gp[SS / sizeof(unsigned long)] = mc->gregs[REG_CSGSFS] >> 48; + #endif + } +-- +2.39.5 + diff --git a/queue-6.14/um-update-min_low_pfn-to-match-changes-in-uml_reserv.patch b/queue-6.14/um-update-min_low_pfn-to-match-changes-in-uml_reserv.patch new file mode 100644 index 0000000000..a082a4a564 --- /dev/null +++ b/queue-6.14/um-update-min_low_pfn-to-match-changes-in-uml_reserv.patch @@ -0,0 +1,36 @@ +From e6c08b7a852846704105ca8dd647ce3b858c1506 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 21 Feb 2025 12:18:55 +0800 +Subject: um: Update min_low_pfn to match changes in uml_reserved + +From: Tiwei Bie + +[ Upstream commit e82cf3051e6193f61e03898f8dba035199064d36 ] + +When uml_reserved is updated, min_low_pfn must also be updated +accordingly. Otherwise, min_low_pfn will not accurately reflect +the lowest available PFN. + +Signed-off-by: Tiwei Bie +Link: https://patch.msgid.link/20250221041855.1156109-1-tiwei.btw@antgroup.com +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + arch/um/kernel/mem.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/arch/um/kernel/mem.c b/arch/um/kernel/mem.c +index befed230aac28..91b7710c0a5f4 100644 +--- a/arch/um/kernel/mem.c ++++ b/arch/um/kernel/mem.c +@@ -66,6 +66,7 @@ void __init mem_init(void) + map_memory(brk_end, __pa(brk_end), uml_reserved - brk_end, 1, 1, 0); + memblock_free((void *)brk_end, uml_reserved - brk_end); + uml_reserved = brk_end; ++ min_low_pfn = PFN_UP(__pa(uml_reserved)); + + /* this will put all low memory onto the freelists */ + memblock_free_all(); +-- +2.39.5 + diff --git a/queue-6.14/usb-xhci-don-t-change-the-status-of-stalled-tds-on-f.patch b/queue-6.14/usb-xhci-don-t-change-the-status-of-stalled-tds-on-f.patch new file mode 100644 index 0000000000..c5c36321df --- /dev/null +++ b/queue-6.14/usb-xhci-don-t-change-the-status-of-stalled-tds-on-f.patch @@ -0,0 +1,68 @@ +From 65f3e90097ec2d8929254e482e75be5f563f7e6d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 11 Mar 2025 17:45:50 +0200 +Subject: usb: xhci: Don't change the status of stalled TDs on failed Stop EP + +From: Michal Pecio + +[ Upstream commit dfc88357b6b6356dadea06b2c0bc8041f5e11720 ] + +When the device stalls an endpoint, current TD is assigned -EPIPE +status and Reset Endpoint is queued. If a Stop Endpoint is pending +at the time, it will run before Reset Endpoint and fail due to the +stall. Its handler will change TD's status to -EPROTO before Reset +Endpoint handler runs and initiates giveback. + +Check if the stall has already been handled and don't try to do it +again. Since xhci_handle_halted_endpoint() performs this check too, +not overwriting td->status is the only difference. + +I haven't seen this case yet, but I have seen a related one where +the xHC has already executed Reset Endpoint, EP Context state is +now Stopped and EP_HALTED is set. If the xHC took a bit longer to +execute Reset Endpoint, said case would become this one. + +Signed-off-by: Michal Pecio +Signed-off-by: Mathias Nyman +Link: https://lore.kernel.org/r/20250311154551.4035726-3-mathias.nyman@linux.intel.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/usb/host/xhci-ring.c | 12 +++++++++++- + 1 file changed, 11 insertions(+), 1 deletion(-) + +diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c +index 5a0e361818c27..073b0acd8a742 100644 +--- a/drivers/usb/host/xhci-ring.c ++++ b/drivers/usb/host/xhci-ring.c +@@ -1164,7 +1164,14 @@ static void xhci_handle_cmd_stop_ep(struct xhci_hcd *xhci, int slot_id, + */ + switch (GET_EP_CTX_STATE(ep_ctx)) { + case EP_STATE_HALTED: +- xhci_dbg(xhci, "Stop ep completion raced with stall, reset ep\n"); ++ xhci_dbg(xhci, "Stop ep completion raced with stall\n"); ++ /* ++ * If the halt happened before Stop Endpoint failed, its transfer event ++ * should have already been handled and Reset Endpoint should be pending. ++ */ ++ if (ep->ep_state & EP_HALTED) ++ goto reset_done; ++ + if (ep->ep_state & EP_HAS_STREAMS) { + reset_type = EP_SOFT_RESET; + } else { +@@ -1175,8 +1182,11 @@ static void xhci_handle_cmd_stop_ep(struct xhci_hcd *xhci, int slot_id, + } + /* reset ep, reset handler cleans up cancelled tds */ + err = xhci_handle_halted_endpoint(xhci, ep, td, reset_type); ++ xhci_dbg(xhci, "Stop ep completion resetting ep, status %d\n", err); + if (err) + break; ++reset_done: ++ /* Reset EP handler will clean up cancelled TDs */ + ep->ep_state &= ~EP_STOP_CMD_PENDING; + return; + case EP_STATE_STOPPED: +-- +2.39.5 + diff --git a/queue-6.14/usb-xhci-set-page-size-to-the-xhci-supported-size.patch b/queue-6.14/usb-xhci-set-page-size-to-the-xhci-supported-size.patch new file mode 100644 index 0000000000..19f741ec78 --- /dev/null +++ b/queue-6.14/usb-xhci-set-page-size-to-the-xhci-supported-size.patch @@ -0,0 +1,126 @@ +From ddf28dfef649686bf9578b0fa1ff7c66fe7d5451 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Mar 2025 16:49:48 +0200 +Subject: usb: xhci: set page size to the xHCI-supported size + +From: Niklas Neronin + +[ Upstream commit 68c1f1671650b49bbd26e6a65ddcf33f2565efa3 ] + +The current xHCI driver does not validate whether a page size of 4096 +bytes is supported. Address the issue by setting the page size to the +value supported by the xHCI controller, as read from the Page Size +register. In the event of an unexpected value; default to a 4K page size. + +Additionally, this commit removes unnecessary debug messages and instead +prints the supported and used page size once. + +The xHCI controller supports page sizes of (2^{(n+12)}) bytes, where 'n' +is the Page Size Bit. Only one page size is supported, with a maximum +page size of 128 KB. + +Signed-off-by: Niklas Neronin +Signed-off-by: Mathias Nyman +Link: https://lore.kernel.org/r/20250306144954.3507700-10-mathias.nyman@linux.intel.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/usb/host/xhci-mem.c | 34 ++++++++++++++++++---------------- + drivers/usb/host/xhci.h | 8 ++++---- + 2 files changed, 22 insertions(+), 20 deletions(-) + +diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c +index 9aa7e2a876ec1..d698095fc88d3 100644 +--- a/drivers/usb/host/xhci-mem.c ++++ b/drivers/usb/host/xhci-mem.c +@@ -1953,7 +1953,6 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci) + xhci->interrupters = NULL; + + xhci->page_size = 0; +- xhci->page_shift = 0; + xhci->usb2_rhub.bus_state.bus_suspended = 0; + xhci->usb3_rhub.bus_state.bus_suspended = 0; + } +@@ -2372,6 +2371,22 @@ xhci_create_secondary_interrupter(struct usb_hcd *hcd, unsigned int segs, + } + EXPORT_SYMBOL_GPL(xhci_create_secondary_interrupter); + ++static void xhci_hcd_page_size(struct xhci_hcd *xhci) ++{ ++ u32 page_size; ++ ++ page_size = readl(&xhci->op_regs->page_size) & XHCI_PAGE_SIZE_MASK; ++ if (!is_power_of_2(page_size)) { ++ xhci_warn(xhci, "Invalid page size register = 0x%x\n", page_size); ++ /* Fallback to 4K page size, since that's common */ ++ page_size = 1; ++ } ++ ++ xhci->page_size = page_size << 12; ++ xhci_dbg_trace(xhci, trace_xhci_dbg_init, "HCD page size set to %iK", ++ xhci->page_size >> 10); ++} ++ + int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) + { + struct xhci_interrupter *ir; +@@ -2379,7 +2394,7 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) + dma_addr_t dma; + unsigned int val, val2; + u64 val_64; +- u32 page_size, temp; ++ u32 temp; + int i; + + INIT_LIST_HEAD(&xhci->cmd_list); +@@ -2388,20 +2403,7 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) + INIT_DELAYED_WORK(&xhci->cmd_timer, xhci_handle_command_timeout); + init_completion(&xhci->cmd_ring_stop_completion); + +- page_size = readl(&xhci->op_regs->page_size); +- xhci_dbg_trace(xhci, trace_xhci_dbg_init, +- "Supported page size register = 0x%x", page_size); +- val = ffs(page_size) - 1; +- if (val < 16) +- xhci_dbg_trace(xhci, trace_xhci_dbg_init, +- "Supported page size of %iK", (1 << (val + 12)) / 1024); +- else +- xhci_warn(xhci, "WARN: no supported page size\n"); +- /* Use 4K pages, since that's common and the minimum the HC supports */ +- xhci->page_shift = 12; +- xhci->page_size = 1 << xhci->page_shift; +- xhci_dbg_trace(xhci, trace_xhci_dbg_init, +- "HCD page size set to %iK", xhci->page_size / 1024); ++ xhci_hcd_page_size(xhci); + + /* + * Program the Number of Device Slots Enabled field in the CONFIG +diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h +index 2c394cba120f1..7d22617417fe0 100644 +--- a/drivers/usb/host/xhci.h ++++ b/drivers/usb/host/xhci.h +@@ -211,6 +211,9 @@ struct xhci_op_regs { + #define CONFIG_CIE (1 << 9) + /* bits 10:31 - reserved and should be preserved */ + ++/* bits 15:0 - HCD page shift bit */ ++#define XHCI_PAGE_SIZE_MASK 0xffff ++ + /** + * struct xhci_intr_reg - Interrupt Register Set + * @irq_pending: IMAN - Interrupt Management Register. Used to enable +@@ -1514,10 +1517,7 @@ struct xhci_hcd { + u16 max_interrupters; + /* imod_interval in ns (I * 250ns) */ + u32 imod_interval; +- /* 4KB min, 128MB max */ +- int page_size; +- /* Valid values are 12 to 20, inclusive */ +- int page_shift; ++ u32 page_size; + /* MSI-X/MSI vectors */ + int nvecs; + /* optional clocks */ +-- +2.39.5 + diff --git a/queue-6.14/vdpa-mlx5-fix-mlx5_vdpa_get_config-endianness-on-big.patch b/queue-6.14/vdpa-mlx5-fix-mlx5_vdpa_get_config-endianness-on-big.patch new file mode 100644 index 0000000000..379731a481 --- /dev/null +++ b/queue-6.14/vdpa-mlx5-fix-mlx5_vdpa_get_config-endianness-on-big.patch @@ -0,0 +1,52 @@ +From 6b463aa15b2287c2faa911e3719635f2f26732c6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 4 Feb 2025 11:31:27 -0600 +Subject: vdpa/mlx5: Fix mlx5_vdpa_get_config() endianness on big-endian + machines +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Konstantin Shkolnyy + +[ Upstream commit 439252e167ac45a5d46f573aac1da7d8f3e051ad ] + +mlx5_vdpa_dev_add() doesn’t initialize mvdev->actual_features. It’s +initialized later by mlx5_vdpa_set_driver_features(). However, +mlx5_vdpa_get_config() depends on the VIRTIO_F_VERSION_1 flag in +actual_features, to return data with correct endianness. When it’s called +before mlx5_vdpa_set_driver_features(), the data are incorrectly returned +as big-endian on big-endian machines, while QEMU then interprets them as +little-endian. + +The fix is to initialize this VIRTIO_F_VERSION_1 as early as possible, +especially considering that mlx5_vdpa_dev_add() insists on this flag to +always be set anyway. + +Signed-off-by: Konstantin Shkolnyy +Message-Id: <20250204173127.166673-1-kshk@linux.ibm.com> +Signed-off-by: Michael S. Tsirkin +Reviewed-by: Dragos Tatulea +Acked-by: Jason Wang +Signed-off-by: Sasha Levin +--- + drivers/vdpa/mlx5/net/mlx5_vnet.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/vdpa/mlx5/net/mlx5_vnet.c b/drivers/vdpa/mlx5/net/mlx5_vnet.c +index 36099047560df..cccc49a08a1ab 100644 +--- a/drivers/vdpa/mlx5/net/mlx5_vnet.c ++++ b/drivers/vdpa/mlx5/net/mlx5_vnet.c +@@ -3884,6 +3884,9 @@ static int mlx5_vdpa_dev_add(struct vdpa_mgmt_dev *v_mdev, const char *name, + ndev->mvdev.max_vqs = max_vqs; + mvdev = &ndev->mvdev; + mvdev->mdev = mdev; ++ /* cpu_to_mlx5vdpa16() below depends on this flag */ ++ mvdev->actual_features = ++ (device_features & BIT_ULL(VIRTIO_F_VERSION_1)); + + ndev->vqs = kcalloc(max_vqs, sizeof(*ndev->vqs), GFP_KERNEL); + ndev->event_cbs = kcalloc(max_vqs + 1, sizeof(*ndev->event_cbs), GFP_KERNEL); +-- +2.39.5 + diff --git a/queue-6.14/vfio-pci-handle-intx-irq_notconnected.patch b/queue-6.14/vfio-pci-handle-intx-irq_notconnected.patch new file mode 100644 index 0000000000..be230be6b3 --- /dev/null +++ b/queue-6.14/vfio-pci-handle-intx-irq_notconnected.patch @@ -0,0 +1,84 @@ +From ecd65b6a38ccf5cf27922b6af3234307e76005cb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 11 Mar 2025 17:06:21 -0600 +Subject: vfio/pci: Handle INTx IRQ_NOTCONNECTED + +From: Alex Williamson + +[ Upstream commit 860be250fc32de9cb24154bf21b4e36f40925707 ] + +Some systems report INTx as not routed by setting pdev->irq to +IRQ_NOTCONNECTED, resulting in a -ENOTCONN error when trying to +setup eventfd signaling. Include this in the set of conditions +for which the PIN register is virtualized to zero. + +Additionally consolidate vfio_pci_get_irq_count() to use this +virtualized value in reporting INTx support via ioctl and sanity +checking ioctl paths since pdev->irq is re-used when the device +is in MSI mode. + +The combination of these results in both the config space of the +device and the ioctl interface behaving as if the device does not +support INTx. + +Reviewed-by: Kevin Tian +Link: https://lore.kernel.org/r/20250311230623.1264283-1-alex.williamson@redhat.com +Signed-off-by: Alex Williamson +Signed-off-by: Sasha Levin +--- + drivers/vfio/pci/vfio_pci_config.c | 3 ++- + drivers/vfio/pci/vfio_pci_core.c | 10 +--------- + drivers/vfio/pci/vfio_pci_intrs.c | 2 +- + 3 files changed, 4 insertions(+), 11 deletions(-) + +diff --git a/drivers/vfio/pci/vfio_pci_config.c b/drivers/vfio/pci/vfio_pci_config.c +index 94142581c98ce..14437396d7211 100644 +--- a/drivers/vfio/pci/vfio_pci_config.c ++++ b/drivers/vfio/pci/vfio_pci_config.c +@@ -1814,7 +1814,8 @@ int vfio_config_init(struct vfio_pci_core_device *vdev) + cpu_to_le16(PCI_COMMAND_MEMORY); + } + +- if (!IS_ENABLED(CONFIG_VFIO_PCI_INTX) || vdev->nointx) ++ if (!IS_ENABLED(CONFIG_VFIO_PCI_INTX) || vdev->nointx || ++ vdev->pdev->irq == IRQ_NOTCONNECTED) + vconfig[PCI_INTERRUPT_PIN] = 0; + + ret = vfio_cap_init(vdev); +diff --git a/drivers/vfio/pci/vfio_pci_core.c b/drivers/vfio/pci/vfio_pci_core.c +index a071f42511d3b..b8bfc909fd5d8 100644 +--- a/drivers/vfio/pci/vfio_pci_core.c ++++ b/drivers/vfio/pci/vfio_pci_core.c +@@ -727,15 +727,7 @@ EXPORT_SYMBOL_GPL(vfio_pci_core_finish_enable); + static int vfio_pci_get_irq_count(struct vfio_pci_core_device *vdev, int irq_type) + { + if (irq_type == VFIO_PCI_INTX_IRQ_INDEX) { +- u8 pin; +- +- if (!IS_ENABLED(CONFIG_VFIO_PCI_INTX) || +- vdev->nointx || vdev->pdev->is_virtfn) +- return 0; +- +- pci_read_config_byte(vdev->pdev, PCI_INTERRUPT_PIN, &pin); +- +- return pin ? 1 : 0; ++ return vdev->vconfig[PCI_INTERRUPT_PIN] ? 1 : 0; + } else if (irq_type == VFIO_PCI_MSI_IRQ_INDEX) { + u8 pos; + u16 flags; +diff --git a/drivers/vfio/pci/vfio_pci_intrs.c b/drivers/vfio/pci/vfio_pci_intrs.c +index 8382c58343356..565966351dfad 100644 +--- a/drivers/vfio/pci/vfio_pci_intrs.c ++++ b/drivers/vfio/pci/vfio_pci_intrs.c +@@ -259,7 +259,7 @@ static int vfio_intx_enable(struct vfio_pci_core_device *vdev, + if (!is_irq_none(vdev)) + return -EINVAL; + +- if (!pdev->irq) ++ if (!pdev->irq || pdev->irq == IRQ_NOTCONNECTED) + return -ENODEV; + + name = kasprintf(GFP_KERNEL_ACCOUNT, "vfio-intx(%s)", pci_name(pdev)); +-- +2.39.5 + diff --git a/queue-6.14/vhost-scsi-protect-vq-log_used-with-vq-mutex.patch b/queue-6.14/vhost-scsi-protect-vq-log_used-with-vq-mutex.patch new file mode 100644 index 0000000000..6c098438cf --- /dev/null +++ b/queue-6.14/vhost-scsi-protect-vq-log_used-with-vq-mutex.patch @@ -0,0 +1,82 @@ +From ed89a4834307c5fd985c90b6365a58d114530a50 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 2 Apr 2025 23:29:46 -0700 +Subject: vhost-scsi: protect vq->log_used with vq->mutex + +From: Dongli Zhang + +[ Upstream commit f591cf9fce724e5075cc67488c43c6e39e8cbe27 ] + +The vhost-scsi completion path may access vq->log_base when vq->log_used is +already set to false. + + vhost-thread QEMU-thread + +vhost_scsi_complete_cmd_work() +-> vhost_add_used() + -> vhost_add_used_n() + if (unlikely(vq->log_used)) + QEMU disables vq->log_used + via VHOST_SET_VRING_ADDR. + mutex_lock(&vq->mutex); + vq->log_used = false now! + mutex_unlock(&vq->mutex); + + QEMU gfree(vq->log_base) + log_used() + -> log_write(vq->log_base) + +Assuming the VMM is QEMU. The vq->log_base is from QEMU userpace and can be +reclaimed via gfree(). As a result, this causes invalid memory writes to +QEMU userspace. + +The control queue path has the same issue. + +Signed-off-by: Dongli Zhang +Acked-by: Jason Wang +Reviewed-by: Mike Christie +Message-Id: <20250403063028.16045-2-dongli.zhang@oracle.com> +Signed-off-by: Michael S. Tsirkin +Signed-off-by: Sasha Levin +--- + drivers/vhost/scsi.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c +index 35a03306d1345..ecad2f53b7635 100644 +--- a/drivers/vhost/scsi.c ++++ b/drivers/vhost/scsi.c +@@ -571,6 +571,9 @@ static void vhost_scsi_complete_cmd_work(struct vhost_work *work) + int ret; + + llnode = llist_del_all(&svq->completion_list); ++ ++ mutex_lock(&svq->vq.mutex); ++ + llist_for_each_entry_safe(cmd, t, llnode, tvc_completion_list) { + se_cmd = &cmd->tvc_se_cmd; + +@@ -604,6 +607,8 @@ static void vhost_scsi_complete_cmd_work(struct vhost_work *work) + vhost_scsi_release_cmd_res(se_cmd); + } + ++ mutex_unlock(&svq->vq.mutex); ++ + if (signal) + vhost_signal(&svq->vs->dev, &svq->vq); + } +@@ -1346,8 +1351,11 @@ static void vhost_scsi_tmf_resp_work(struct vhost_work *work) + else + resp_code = VIRTIO_SCSI_S_FUNCTION_REJECTED; + ++ mutex_lock(&tmf->svq->vq.mutex); + vhost_scsi_send_tmf_resp(tmf->vhost, &tmf->svq->vq, tmf->in_iovs, + tmf->vq_desc, &tmf->resp_iov, resp_code); ++ mutex_unlock(&tmf->svq->vq.mutex); ++ + vhost_scsi_release_tmf_res(tmf); + } + +-- +2.39.5 + diff --git a/queue-6.14/vhost-scsi-return-queue-full-for-page-alloc-failures.patch b/queue-6.14/vhost-scsi-return-queue-full-for-page-alloc-failures.patch new file mode 100644 index 0000000000..eca43f9c43 --- /dev/null +++ b/queue-6.14/vhost-scsi-return-queue-full-for-page-alloc-failures.patch @@ -0,0 +1,79 @@ +From 5db376431d39798fc8157327eff23d899cc20b2c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 3 Dec 2024 13:15:11 -0600 +Subject: vhost-scsi: Return queue full for page alloc failures during copy + +From: Mike Christie + +[ Upstream commit 891b99eab0f89dbe08d216f4ab71acbeaf7a3102 ] + +This has us return queue full if we can't allocate a page during the +copy operation so the initiator can retry. + +Signed-off-by: Mike Christie +Message-Id: <20241203191705.19431-5-michael.christie@oracle.com> +Signed-off-by: Michael S. Tsirkin +Acked-by: Stefan Hajnoczi +Signed-off-by: Sasha Levin +--- + drivers/vhost/scsi.c | 15 +++++++++------ + 1 file changed, 9 insertions(+), 6 deletions(-) + +diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c +index ecad2f53b7635..38d243d914d00 100644 +--- a/drivers/vhost/scsi.c ++++ b/drivers/vhost/scsi.c +@@ -762,7 +762,7 @@ vhost_scsi_copy_iov_to_sgl(struct vhost_scsi_cmd *cmd, struct iov_iter *iter, + size_t len = iov_iter_count(iter); + unsigned int nbytes = 0; + struct page *page; +- int i; ++ int i, ret; + + if (cmd->tvc_data_direction == DMA_FROM_DEVICE) { + cmd->saved_iter_addr = dup_iter(&cmd->saved_iter, iter, +@@ -775,6 +775,7 @@ vhost_scsi_copy_iov_to_sgl(struct vhost_scsi_cmd *cmd, struct iov_iter *iter, + page = alloc_page(GFP_KERNEL); + if (!page) { + i--; ++ ret = -ENOMEM; + goto err; + } + +@@ -782,8 +783,10 @@ vhost_scsi_copy_iov_to_sgl(struct vhost_scsi_cmd *cmd, struct iov_iter *iter, + sg_set_page(&sg[i], page, nbytes, 0); + + if (cmd->tvc_data_direction == DMA_TO_DEVICE && +- copy_page_from_iter(page, 0, nbytes, iter) != nbytes) ++ copy_page_from_iter(page, 0, nbytes, iter) != nbytes) { ++ ret = -EFAULT; + goto err; ++ } + + len -= nbytes; + } +@@ -798,7 +801,7 @@ vhost_scsi_copy_iov_to_sgl(struct vhost_scsi_cmd *cmd, struct iov_iter *iter, + for (; i >= 0; i--) + __free_page(sg_page(&sg[i])); + kfree(cmd->saved_iter_addr); +- return -ENOMEM; ++ return ret; + } + + static int +@@ -1282,9 +1285,9 @@ vhost_scsi_handle_vq(struct vhost_scsi *vs, struct vhost_virtqueue *vq) + " %d\n", cmd, exp_data_len, prot_bytes, data_direction); + + if (data_direction != DMA_NONE) { +- if (unlikely(vhost_scsi_mapal(cmd, prot_bytes, +- &prot_iter, exp_data_len, +- &data_iter))) { ++ ret = vhost_scsi_mapal(cmd, prot_bytes, &prot_iter, ++ exp_data_len, &data_iter); ++ if (unlikely(ret)) { + vq_err(vq, "Failed to map iov to sgl\n"); + vhost_scsi_release_cmd_res(&cmd->tvc_se_cmd); + goto err; +-- +2.39.5 + diff --git a/queue-6.14/vhost_task-fix-vhost_task_create-documentation.patch b/queue-6.14/vhost_task-fix-vhost_task_create-documentation.patch new file mode 100644 index 0000000000..884c3d6649 --- /dev/null +++ b/queue-6.14/vhost_task-fix-vhost_task_create-documentation.patch @@ -0,0 +1,40 @@ +From 44ffd8b64006a7eed800ec7c6ed6f85209a941df Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 27 Mar 2025 13:44:35 +0100 +Subject: vhost_task: fix vhost_task_create() documentation + +From: Stefano Garzarella + +[ Upstream commit fec0abf52609c20279243699d08b660c142ce0aa ] + +Commit cb380909ae3b ("vhost: return task creation error instead of NULL") +changed the return value of vhost_task_create(), but did not update the +documentation. + +Reflect the change in the documentation: on an error, vhost_task_create() +returns an ERR_PTR() and no longer NULL. + +Signed-off-by: Stefano Garzarella +Message-Id: <20250327124435.142831-1-sgarzare@redhat.com> +Signed-off-by: Michael S. Tsirkin +Signed-off-by: Sasha Levin +--- + kernel/vhost_task.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/kernel/vhost_task.c b/kernel/vhost_task.c +index 2ef2e1b800916..2f844c279a3e0 100644 +--- a/kernel/vhost_task.c ++++ b/kernel/vhost_task.c +@@ -111,7 +111,7 @@ EXPORT_SYMBOL_GPL(vhost_task_stop); + * @arg: data to be passed to fn and handled_kill + * @name: the thread's name + * +- * This returns a specialized task for use by the vhost layer or NULL on ++ * This returns a specialized task for use by the vhost layer or ERR_PTR() on + * failure. The returned task is inactive, and the caller must fire it up + * through vhost_task_start(). + */ +-- +2.39.5 + diff --git a/queue-6.14/virtgpu-don-t-reset-on-shutdown.patch b/queue-6.14/virtgpu-don-t-reset-on-shutdown.patch new file mode 100644 index 0000000000..161d28254b --- /dev/null +++ b/queue-6.14/virtgpu-don-t-reset-on-shutdown.patch @@ -0,0 +1,157 @@ +From 8efa7286e3e47d1da3d7b89c2198e5a413acdd52 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 10 Apr 2025 03:16:26 -0400 +Subject: virtgpu: don't reset on shutdown + +From: Michael S. Tsirkin + +[ Upstream commit 183a08715af1491d381b4e22efd61578fbe05fa5 ] + +It looks like GPUs are used after shutdown is invoked. +Thus, breaking virtio gpu in the shutdown callback is not a good idea - +guest hangs attempting to finish console drawing, with these warnings: + +[ 20.504464] WARNING: CPU: 0 PID: 568 at drivers/gpu/drm/virtio/virtgpu_vq.c:358 virtio_gpu_queue_ctrl_sgs+0x236/0x290 [virtio_gpu] +[ 20.505685] Modules linked in: nft_fib_inet nft_fib_ipv4 nft_fib_ipv6 nft_fib nft_reject_inet nf_reject_ipv4 nf_reject_ipv6 nft_reject nft_ct nft_chain_nat nf_nat nf_conntrack nf_defrag_ipv6 nf_defrag_ipv4 rfkill ip_set nf_tables nfnetlink vfat fat intel_rapl_msr intel_rapl_common intel_uncore_frequency_common nfit libnvdimm kvm_intel kvm rapl iTCO_wdt iTCO_vendor_support virtio_gpu virtio_dma_buf pcspkr drm_shmem_helper i2c_i801 drm_kms_helper lpc_ich i2c_smbus virtio_balloon joydev drm fuse xfs libcrc32c ahci libahci crct10dif_pclmul crc32_pclmul crc32c_intel libata virtio_net ghash_clmulni_intel net_failover virtio_blk failover serio_raw dm_mirror dm_region_hash dm_log dm_mod +[ 20.511847] CPU: 0 PID: 568 Comm: kworker/0:3 Kdump: loaded Tainted: G W ------- --- 5.14.0-578.6675_1757216455.el9.x86_64 #1 +[ 20.513157] Hardware name: Red Hat KVM/RHEL, BIOS edk2-20241117-3.el9 11/17/2024 +[ 20.513918] Workqueue: events drm_fb_helper_damage_work [drm_kms_helper] +[ 20.514626] RIP: 0010:virtio_gpu_queue_ctrl_sgs+0x236/0x290 [virtio_gpu] +[ 20.515332] Code: 00 00 48 85 c0 74 0c 48 8b 78 08 48 89 ee e8 51 50 00 00 65 ff 0d 42 e3 74 3f 0f 85 69 ff ff ff 0f 1f 44 00 00 e9 5f ff ff ff <0f> 0b e9 3f ff ff ff 48 83 3c 24 00 74 0e 49 8b 7f 40 48 85 ff 74 +[ 20.517272] RSP: 0018:ff34f0a8c0787ad8 EFLAGS: 00010282 +[ 20.517820] RAX: 00000000fffffffb RBX: 0000000000000000 RCX: 0000000000000820 +[ 20.518565] RDX: 0000000000000000 RSI: ff34f0a8c0787be0 RDI: ff218bef03a26300 +[ 20.519308] RBP: ff218bef03a26300 R08: 0000000000000001 R09: ff218bef07224360 +[ 20.520059] R10: 0000000000008dc0 R11: 0000000000000002 R12: ff218bef02630028 +[ 20.520806] R13: ff218bef0263fb48 R14: ff218bef00cb8000 R15: ff218bef07224360 +[ 20.521555] FS: 0000000000000000(0000) GS:ff218bef7ba00000(0000) knlGS:0000000000000000 +[ 20.522397] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +[ 20.522996] CR2: 000055ac4f7871c0 CR3: 000000010b9f2002 CR4: 0000000000771ef0 +[ 20.523740] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 +[ 20.524477] DR3: 0000000000000000 DR6: 00000000fffe07f0 DR7: 0000000000000400 +[ 20.525223] PKRU: 55555554 +[ 20.525515] Call Trace: +[ 20.525777] +[ 20.526003] ? show_trace_log_lvl+0x1c4/0x2df +[ 20.526464] ? show_trace_log_lvl+0x1c4/0x2df +[ 20.526925] ? virtio_gpu_queue_fenced_ctrl_buffer+0x82/0x2c0 [virtio_gpu] +[ 20.527643] ? virtio_gpu_queue_ctrl_sgs+0x236/0x290 [virtio_gpu] +[ 20.528282] ? __warn+0x7e/0xd0 +[ 20.528621] ? virtio_gpu_queue_ctrl_sgs+0x236/0x290 [virtio_gpu] +[ 20.529256] ? report_bug+0x100/0x140 +[ 20.529643] ? handle_bug+0x3c/0x70 +[ 20.530010] ? exc_invalid_op+0x14/0x70 +[ 20.530421] ? asm_exc_invalid_op+0x16/0x20 +[ 20.530862] ? virtio_gpu_queue_ctrl_sgs+0x236/0x290 [virtio_gpu] +[ 20.531506] ? virtio_gpu_queue_ctrl_sgs+0x174/0x290 [virtio_gpu] +[ 20.532148] virtio_gpu_queue_fenced_ctrl_buffer+0x82/0x2c0 [virtio_gpu] +[ 20.532843] virtio_gpu_primary_plane_update+0x3e2/0x460 [virtio_gpu] +[ 20.533520] drm_atomic_helper_commit_planes+0x108/0x320 [drm_kms_helper] +[ 20.534233] drm_atomic_helper_commit_tail+0x45/0x80 [drm_kms_helper] +[ 20.534914] commit_tail+0xd2/0x130 [drm_kms_helper] +[ 20.535446] drm_atomic_helper_commit+0x11b/0x140 [drm_kms_helper] +[ 20.536097] drm_atomic_commit+0xa4/0xe0 [drm] +[ 20.536588] ? __pfx___drm_printfn_info+0x10/0x10 [drm] +[ 20.537162] drm_atomic_helper_dirtyfb+0x192/0x270 [drm_kms_helper] +[ 20.537823] drm_fbdev_shmem_helper_fb_dirty+0x43/0xa0 [drm_shmem_helper] +[ 20.538536] drm_fb_helper_damage_work+0x87/0x160 [drm_kms_helper] +[ 20.539188] process_one_work+0x194/0x380 +[ 20.539612] worker_thread+0x2fe/0x410 +[ 20.540007] ? __pfx_worker_thread+0x10/0x10 +[ 20.540456] kthread+0xdd/0x100 +[ 20.540791] ? __pfx_kthread+0x10/0x10 +[ 20.541190] ret_from_fork+0x29/0x50 +[ 20.541566] +[ 20.541802] ---[ end trace 0000000000000000 ]--- + +It looks like the shutdown is called in the middle of console drawing, so +we should either wait for it to finish, or let drm handle the shutdown. + +This patch implements this second option: + +Add an option for drivers to bypass the common break+reset handling. +As DRM is careful to flush/synchronize outstanding buffers, it looks like +GPU can just have a NOP there. + +Reviewed-by: Eric Auger +Tested-by: Eric Auger +Fixes: 8bd2fa086a04 ("virtio: break and reset virtio devices on device_shutdown()") +Cc: Eric Auger +Cc: Jocelyn Falempe +Signed-off-by: Michael S. Tsirkin +Message-Id: <8490dbeb6f79ed039e6c11d121002618972538a3.1744293540.git.mst@redhat.com> +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/virtio/virtgpu_drv.c | 9 +++++++++ + drivers/virtio/virtio.c | 6 ++++++ + include/linux/virtio.h | 3 +++ + 3 files changed, 18 insertions(+) + +diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.c b/drivers/gpu/drm/virtio/virtgpu_drv.c +index 6a67c6297d583..8719b778a1ff0 100644 +--- a/drivers/gpu/drm/virtio/virtgpu_drv.c ++++ b/drivers/gpu/drm/virtio/virtgpu_drv.c +@@ -125,6 +125,14 @@ static void virtio_gpu_remove(struct virtio_device *vdev) + drm_dev_put(dev); + } + ++static void virtio_gpu_shutdown(struct virtio_device *vdev) ++{ ++ /* ++ * drm does its own synchronization on shutdown. ++ * Do nothing here, opt out of device reset. ++ */ ++} ++ + static void virtio_gpu_config_changed(struct virtio_device *vdev) + { + struct drm_device *dev = vdev->priv; +@@ -159,6 +167,7 @@ static struct virtio_driver virtio_gpu_driver = { + .id_table = id_table, + .probe = virtio_gpu_probe, + .remove = virtio_gpu_remove, ++ .shutdown = virtio_gpu_shutdown, + .config_changed = virtio_gpu_config_changed + }; + +diff --git a/drivers/virtio/virtio.c b/drivers/virtio/virtio.c +index 150753c3b5782..95d5d7993e5b1 100644 +--- a/drivers/virtio/virtio.c ++++ b/drivers/virtio/virtio.c +@@ -407,6 +407,12 @@ static void virtio_dev_shutdown(struct device *_d) + if (!drv) + return; + ++ /* If the driver has its own shutdown method, use that. */ ++ if (drv->shutdown) { ++ drv->shutdown(dev); ++ return; ++ } ++ + /* + * Some devices get wedged if you kick them after they are + * reset. Mark all vqs as broken to make sure we don't. +diff --git a/include/linux/virtio.h b/include/linux/virtio.h +index 4d16c13d0df58..64cb4b04be7ad 100644 +--- a/include/linux/virtio.h ++++ b/include/linux/virtio.h +@@ -220,6 +220,8 @@ size_t virtio_max_dma_size(const struct virtio_device *vdev); + * occurs. + * @reset_done: optional function to call after transport specific reset + * operation has finished. ++ * @shutdown: synchronize with the device on shutdown. If provided, replaces ++ * the virtio core implementation. + */ + struct virtio_driver { + struct device_driver driver; +@@ -237,6 +239,7 @@ struct virtio_driver { + int (*restore)(struct virtio_device *dev); + int (*reset_prepare)(struct virtio_device *dev); + int (*reset_done)(struct virtio_device *dev); ++ void (*shutdown)(struct virtio_device *dev); + }; + + #define drv_to_virtio(__drv) container_of_const(__drv, struct virtio_driver, driver) +-- +2.39.5 + diff --git a/queue-6.14/virtio-break-and-reset-virtio-devices-on-device_shut.patch b/queue-6.14/virtio-break-and-reset-virtio-devices-on-device_shut.patch new file mode 100644 index 0000000000..ba964114b4 --- /dev/null +++ b/queue-6.14/virtio-break-and-reset-virtio-devices-on-device_shut.patch @@ -0,0 +1,90 @@ +From 092b389e506f3fdf21f656026301480396135817 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 8 Aug 2024 10:51:41 +0300 +Subject: virtio: break and reset virtio devices on device_shutdown() + +From: Michael S. Tsirkin + +[ Upstream commit 8bd2fa086a04886798b505f28db4002525895203 ] + +Hongyu reported a hang on kexec in a VM. QEMU reported invalid memory +accesses during the hang. + + Invalid read at addr 0x102877002, size 2, region '(null)', reason: rejected + Invalid write at addr 0x102877A44, size 2, region '(null)', reason: rejected + ... + +It was traced down to virtio-console. Kexec works fine if virtio-console +is not in use. + +The issue is that virtio-console continues to write to the MMIO even after +underlying virtio-pci device is reset. + +Additionally, Eric noticed that IOMMUs are reset before devices, if +devices are not reset on shutdown they continue to poke at guest memory +and get errors from the IOMMU. Some devices get wedged then. + +The problem can be solved by breaking all virtio devices on virtio +bus shutdown, then resetting them. + +Reported-by: Eric Auger +Reported-by: Hongyu Ning +Message-ID: +Tested-by: Eric Auger +Acked-by: Jason Wang +Signed-off-by: Michael S. Tsirkin +Signed-off-by: Sasha Levin +--- + drivers/virtio/virtio.c | 29 +++++++++++++++++++++++++++++ + 1 file changed, 29 insertions(+) + +diff --git a/drivers/virtio/virtio.c b/drivers/virtio/virtio.c +index ba37665188b51..150753c3b5782 100644 +--- a/drivers/virtio/virtio.c ++++ b/drivers/virtio/virtio.c +@@ -395,6 +395,34 @@ static const struct cpumask *virtio_irq_get_affinity(struct device *_d, + return dev->config->get_vq_affinity(dev, irq_vec); + } + ++static void virtio_dev_shutdown(struct device *_d) ++{ ++ struct virtio_device *dev = dev_to_virtio(_d); ++ struct virtio_driver *drv = drv_to_virtio(dev->dev.driver); ++ ++ /* ++ * Stop accesses to or from the device. ++ * We only need to do it if there's a driver - no accesses otherwise. ++ */ ++ if (!drv) ++ return; ++ ++ /* ++ * Some devices get wedged if you kick them after they are ++ * reset. Mark all vqs as broken to make sure we don't. ++ */ ++ virtio_break_device(dev); ++ /* ++ * Guarantee that any callback will see vq->broken as true. ++ */ ++ virtio_synchronize_cbs(dev); ++ /* ++ * As IOMMUs are reset on shutdown, this will block device access to memory. ++ * Some devices get wedged if this happens, so reset to make sure it does not. ++ */ ++ dev->config->reset(dev); ++} ++ + static const struct bus_type virtio_bus = { + .name = "virtio", + .match = virtio_dev_match, +@@ -403,6 +431,7 @@ static const struct bus_type virtio_bus = { + .probe = virtio_dev_probe, + .remove = virtio_dev_remove, + .irq_get_affinity = virtio_irq_get_affinity, ++ .shutdown = virtio_dev_shutdown, + }; + + int __register_virtio_driver(struct virtio_driver *driver, struct module *owner) +-- +2.39.5 + diff --git a/queue-6.14/virtio_ring-fix-data-race-by-tagging-event_triggered.patch b/queue-6.14/virtio_ring-fix-data-race-by-tagging-event_triggered.patch new file mode 100644 index 0000000000..907014adcd --- /dev/null +++ b/queue-6.14/virtio_ring-fix-data-race-by-tagging-event_triggered.patch @@ -0,0 +1,71 @@ +From ccb1a74ef5907ff47bbadba64c560dc6d1e6eff5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 12 Mar 2025 21:04:12 +0800 +Subject: virtio_ring: Fix data race by tagging event_triggered as racy for + KCSAN + +From: Zhongqiu Han + +[ Upstream commit 2e2f925fe737576df2373931c95e1a2b66efdfef ] + +syzbot reports a data-race when accessing the event_triggered, here is the +simplified stack when the issue occurred: + +================================================================== +BUG: KCSAN: data-race in virtqueue_disable_cb / virtqueue_enable_cb_delayed + +write to 0xffff8881025bc452 of 1 bytes by task 3288 on cpu 0: + virtqueue_enable_cb_delayed+0x42/0x3c0 drivers/virtio/virtio_ring.c:2653 + start_xmit+0x230/0x1310 drivers/net/virtio_net.c:3264 + __netdev_start_xmit include/linux/netdevice.h:5151 [inline] + netdev_start_xmit include/linux/netdevice.h:5160 [inline] + xmit_one net/core/dev.c:3800 [inline] + +read to 0xffff8881025bc452 of 1 bytes by interrupt on cpu 1: + virtqueue_disable_cb_split drivers/virtio/virtio_ring.c:880 [inline] + virtqueue_disable_cb+0x92/0x180 drivers/virtio/virtio_ring.c:2566 + skb_xmit_done+0x5f/0x140 drivers/net/virtio_net.c:777 + vring_interrupt+0x161/0x190 drivers/virtio/virtio_ring.c:2715 + __handle_irq_event_percpu+0x95/0x490 kernel/irq/handle.c:158 + handle_irq_event_percpu kernel/irq/handle.c:193 [inline] + +value changed: 0x01 -> 0x00 +================================================================== + +When the data race occurs, the function virtqueue_enable_cb_delayed() sets +event_triggered to false, and virtqueue_disable_cb_split/packed() reads it +as false due to the race condition. Since event_triggered is an unreliable +hint used for optimization, this should only cause the driver temporarily +suggest that the device not send an interrupt notification when the event +index is used. + +Fix this KCSAN reported data-race issue by explicitly tagging the access as +data_racy. + +Reported-by: syzbot+efe683d57990864b8c8e@syzkaller.appspotmail.com +Closes: https://lore.kernel.org/all/67c7761a.050a0220.15b4b9.0018.GAE@google.com/ +Signed-off-by: Zhongqiu Han +Message-Id: <20250312130412.3516307-1-quic_zhonhan@quicinc.com> +Signed-off-by: Michael S. Tsirkin +Acked-by: Jason Wang +Signed-off-by: Sasha Levin +--- + drivers/virtio/virtio_ring.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c +index fdd2d2b07b5a2..b784aab668670 100644 +--- a/drivers/virtio/virtio_ring.c ++++ b/drivers/virtio/virtio_ring.c +@@ -2650,7 +2650,7 @@ bool virtqueue_enable_cb_delayed(struct virtqueue *_vq) + struct vring_virtqueue *vq = to_vvq(_vq); + + if (vq->event_triggered) +- vq->event_triggered = false; ++ data_race(vq->event_triggered = false); + + return vq->packed_ring ? virtqueue_enable_cb_delayed_packed(_vq) : + virtqueue_enable_cb_delayed_split(_vq); +-- +2.39.5 + diff --git a/queue-6.14/vxlan-annotate-fdb-data-races.patch b/queue-6.14/vxlan-annotate-fdb-data-races.patch new file mode 100644 index 0000000000..e0414fa6b0 --- /dev/null +++ b/queue-6.14/vxlan-annotate-fdb-data-races.patch @@ -0,0 +1,144 @@ +From 458ad6523828350ce83cd8c7f0662dceb4c926bc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 4 Feb 2025 16:55:42 +0200 +Subject: vxlan: Annotate FDB data races + +From: Ido Schimmel + +[ Upstream commit f6205f8215f12a96518ac9469ff76294ae7bd612 ] + +The 'used' and 'updated' fields in the FDB entry structure can be +accessed concurrently by multiple threads, leading to reports such as +[1]. Can be reproduced using [2]. + +Suppress these reports by annotating these accesses using +READ_ONCE() / WRITE_ONCE(). + +[1] +BUG: KCSAN: data-race in vxlan_xmit / vxlan_xmit + +write to 0xffff942604d263a8 of 8 bytes by task 286 on cpu 0: + vxlan_xmit+0xb29/0x2380 + dev_hard_start_xmit+0x84/0x2f0 + __dev_queue_xmit+0x45a/0x1650 + packet_xmit+0x100/0x150 + packet_sendmsg+0x2114/0x2ac0 + __sys_sendto+0x318/0x330 + __x64_sys_sendto+0x76/0x90 + x64_sys_call+0x14e8/0x1c00 + do_syscall_64+0x9e/0x1a0 + entry_SYSCALL_64_after_hwframe+0x77/0x7f + +read to 0xffff942604d263a8 of 8 bytes by task 287 on cpu 2: + vxlan_xmit+0xadf/0x2380 + dev_hard_start_xmit+0x84/0x2f0 + __dev_queue_xmit+0x45a/0x1650 + packet_xmit+0x100/0x150 + packet_sendmsg+0x2114/0x2ac0 + __sys_sendto+0x318/0x330 + __x64_sys_sendto+0x76/0x90 + x64_sys_call+0x14e8/0x1c00 + do_syscall_64+0x9e/0x1a0 + entry_SYSCALL_64_after_hwframe+0x77/0x7f + +value changed: 0x00000000fffbac6e -> 0x00000000fffbac6f + +Reported by Kernel Concurrency Sanitizer on: +CPU: 2 UID: 0 PID: 287 Comm: mausezahn Not tainted 6.13.0-rc7-01544-gb4b270f11a02 #5 +Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.16.3-3.fc41 04/01/2014 + +[2] + #!/bin/bash + + set +H + echo whitelist > /sys/kernel/debug/kcsan + echo !vxlan_xmit > /sys/kernel/debug/kcsan + + ip link add name vx0 up type vxlan id 10010 dstport 4789 local 192.0.2.1 + bridge fdb add 00:11:22:33:44:55 dev vx0 self static dst 198.51.100.1 + taskset -c 0 mausezahn vx0 -a own -b 00:11:22:33:44:55 -c 0 -q & + taskset -c 2 mausezahn vx0 -a own -b 00:11:22:33:44:55 -c 0 -q & + +Reviewed-by: Petr Machata +Signed-off-by: Ido Schimmel +Reviewed-by: Eric Dumazet +Reviewed-by: Nikolay Aleksandrov +Link: https://patch.msgid.link/20250204145549.1216254-2-idosch@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/vxlan/vxlan_core.c | 18 +++++++++--------- + 1 file changed, 9 insertions(+), 9 deletions(-) + +diff --git a/drivers/net/vxlan/vxlan_core.c b/drivers/net/vxlan/vxlan_core.c +index ae0e2edfde1aa..cdd2a78badf55 100644 +--- a/drivers/net/vxlan/vxlan_core.c ++++ b/drivers/net/vxlan/vxlan_core.c +@@ -227,9 +227,9 @@ static int vxlan_fdb_info(struct sk_buff *skb, struct vxlan_dev *vxlan, + be32_to_cpu(fdb->vni))) + goto nla_put_failure; + +- ci.ndm_used = jiffies_to_clock_t(now - fdb->used); ++ ci.ndm_used = jiffies_to_clock_t(now - READ_ONCE(fdb->used)); + ci.ndm_confirmed = 0; +- ci.ndm_updated = jiffies_to_clock_t(now - fdb->updated); ++ ci.ndm_updated = jiffies_to_clock_t(now - READ_ONCE(fdb->updated)); + ci.ndm_refcnt = 0; + + if (nla_put(skb, NDA_CACHEINFO, sizeof(ci), &ci)) +@@ -434,8 +434,8 @@ static struct vxlan_fdb *vxlan_find_mac(struct vxlan_dev *vxlan, + struct vxlan_fdb *f; + + f = __vxlan_find_mac(vxlan, mac, vni); +- if (f && f->used != jiffies) +- f->used = jiffies; ++ if (f && READ_ONCE(f->used) != jiffies) ++ WRITE_ONCE(f->used, jiffies); + + return f; + } +@@ -1009,12 +1009,12 @@ static int vxlan_fdb_update_existing(struct vxlan_dev *vxlan, + !(f->flags & NTF_VXLAN_ADDED_BY_USER)) { + if (f->state != state) { + f->state = state; +- f->updated = jiffies; ++ WRITE_ONCE(f->updated, jiffies); + notify = 1; + } + if (f->flags != fdb_flags) { + f->flags = fdb_flags; +- f->updated = jiffies; ++ WRITE_ONCE(f->updated, jiffies); + notify = 1; + } + } +@@ -1048,7 +1048,7 @@ static int vxlan_fdb_update_existing(struct vxlan_dev *vxlan, + } + + if (ndm_flags & NTF_USE) +- f->used = jiffies; ++ WRITE_ONCE(f->used, jiffies); + + if (notify) { + if (rd == NULL) +@@ -1481,7 +1481,7 @@ static enum skb_drop_reason vxlan_snoop(struct net_device *dev, + src_mac, &rdst->remote_ip.sa, &src_ip->sa); + + rdst->remote_ip = *src_ip; +- f->updated = jiffies; ++ WRITE_ONCE(f->updated, jiffies); + vxlan_fdb_notify(vxlan, f, rdst, RTM_NEWNEIGH, true, NULL); + } else { + u32 hash_index = fdb_head_index(vxlan, src_mac, vni); +@@ -2852,7 +2852,7 @@ static void vxlan_cleanup(struct timer_list *t) + if (f->flags & NTF_EXT_LEARNED) + continue; + +- timeout = f->used + vxlan->cfg.age_interval * HZ; ++ timeout = READ_ONCE(f->used) + vxlan->cfg.age_interval * HZ; + if (time_before_eq(timeout, jiffies)) { + netdev_dbg(vxlan->dev, + "garbage collect %pM\n", +-- +2.39.5 + diff --git a/queue-6.14/vxlan-join-leave-mc-group-after-remote-changes.patch b/queue-6.14/vxlan-join-leave-mc-group-after-remote-changes.patch new file mode 100644 index 0000000000..ed1289b8ab --- /dev/null +++ b/queue-6.14/vxlan-join-leave-mc-group-after-remote-changes.patch @@ -0,0 +1,113 @@ +From 3e036b1af282b3b0e0142912bf0b3dde7aa7e16e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 14 Feb 2025 17:18:21 +0100 +Subject: vxlan: Join / leave MC group after remote changes + +From: Petr Machata + +[ Upstream commit d42d543368343c0449a4e433b5f02e063a86209c ] + +When a vxlan netdevice is brought up, if its default remote is a multicast +address, the device joins the indicated group. + +Therefore when the multicast remote address changes, the device should +leave the current group and subscribe to the new one. Similarly when the +interface used for endpoint communication is changed in a situation when +multicast remote is configured. This is currently not done. + +Both vxlan_igmp_join() and vxlan_igmp_leave() can however fail. So it is +possible that with such fix, the netdevice will end up in an inconsistent +situation where the old group is not joined anymore, but joining the new +group fails. Should we join the new group first, and leave the old one +second, we might end up in the opposite situation, where both groups are +joined. Undoing any of this during rollback is going to be similarly +problematic. + +One solution would be to just forbid the change when the netdevice is up. +However in vnifilter mode, changing the group address is allowed, and these +problems are simply ignored (see vxlan_vni_update_group()): + + # ip link add name br up type bridge vlan_filtering 1 + # ip link add vx1 up master br type vxlan external vnifilter local 192.0.2.1 dev lo dstport 4789 + # bridge vni add dev vx1 vni 200 group 224.0.0.1 + # tcpdump -i lo & + # bridge vni add dev vx1 vni 200 group 224.0.0.2 + 18:55:46.523438 IP 0.0.0.0 > 224.0.0.22: igmp v3 report, 1 group record(s) + 18:55:46.943447 IP 0.0.0.0 > 224.0.0.22: igmp v3 report, 1 group record(s) + # bridge vni + dev vni group/remote + vx1 200 224.0.0.2 + +Having two different modes of operation for conceptually the same interface +is silly, so in this patch, just do what the vnifilter code does and deal +with the errors by crossing fingers real hard. + +The vnifilter code leaves old before joining new, and in case of join / +leave failures does not roll back the configuration changes that have +already been applied, but bails out of joining if it could not leave. Do +the same here: leave before join, apply changes unconditionally and do not +attempt to join if we couldn't leave. + +Signed-off-by: Petr Machata +Reviewed-by: Ido Schimmel +Reviewed-by: Nikolay Aleksandrov +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/vxlan/vxlan_core.c | 18 ++++++++++++++++-- + 1 file changed, 16 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/vxlan/vxlan_core.c b/drivers/net/vxlan/vxlan_core.c +index 92516189e792f..ae0e2edfde1aa 100644 +--- a/drivers/net/vxlan/vxlan_core.c ++++ b/drivers/net/vxlan/vxlan_core.c +@@ -4415,6 +4415,7 @@ static int vxlan_changelink(struct net_device *dev, struct nlattr *tb[], + struct netlink_ext_ack *extack) + { + struct vxlan_dev *vxlan = netdev_priv(dev); ++ bool rem_ip_changed, change_igmp; + struct net_device *lowerdev; + struct vxlan_config conf; + struct vxlan_rdst *dst; +@@ -4438,8 +4439,13 @@ static int vxlan_changelink(struct net_device *dev, struct nlattr *tb[], + if (err) + return err; + ++ rem_ip_changed = !vxlan_addr_equal(&conf.remote_ip, &dst->remote_ip); ++ change_igmp = vxlan->dev->flags & IFF_UP && ++ (rem_ip_changed || ++ dst->remote_ifindex != conf.remote_ifindex); ++ + /* handle default dst entry */ +- if (!vxlan_addr_equal(&conf.remote_ip, &dst->remote_ip)) { ++ if (rem_ip_changed) { + u32 hash_index = fdb_head_index(vxlan, all_zeros_mac, conf.vni); + + spin_lock_bh(&vxlan->hash_lock[hash_index]); +@@ -4483,6 +4489,9 @@ static int vxlan_changelink(struct net_device *dev, struct nlattr *tb[], + } + } + ++ if (change_igmp && vxlan_addr_multicast(&dst->remote_ip)) ++ err = vxlan_multicast_leave(vxlan); ++ + if (conf.age_interval != vxlan->cfg.age_interval) + mod_timer(&vxlan->age_timer, jiffies); + +@@ -4490,7 +4499,12 @@ static int vxlan_changelink(struct net_device *dev, struct nlattr *tb[], + if (lowerdev && lowerdev != dst->remote_dev) + dst->remote_dev = lowerdev; + vxlan_config_apply(dev, &conf, lowerdev, vxlan->net, true); +- return 0; ++ ++ if (!err && change_igmp && ++ vxlan_addr_multicast(&dst->remote_ip)) ++ err = vxlan_multicast_join(vxlan); ++ ++ return err; + } + + static void vxlan_dellink(struct net_device *dev, struct list_head *head) +-- +2.39.5 + diff --git a/queue-6.14/watchdog-aspeed-fix-64-bit-division.patch b/queue-6.14/watchdog-aspeed-fix-64-bit-division.patch new file mode 100644 index 0000000000..dacc282ea9 --- /dev/null +++ b/queue-6.14/watchdog-aspeed-fix-64-bit-division.patch @@ -0,0 +1,43 @@ +From 6bd60675b9e44a821db0fac6d88070247d8d750d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 14 Mar 2025 17:02:44 +0100 +Subject: watchdog: aspeed: fix 64-bit division + +From: Arnd Bergmann + +[ Upstream commit 48a136639ec233614a61653e19f559977d5da2b5 ] + +On 32-bit architectures, the new calculation causes a build failure: + +ld.lld-21: error: undefined symbol: __aeabi_uldivmod + +Since neither value is ever larger than a register, cast both +sides into a uintptr_t. + +Fixes: 5c03f9f4d362 ("watchdog: aspeed: Update bootstatus handling") +Signed-off-by: Arnd Bergmann +Reviewed-by: Guenter Roeck +Link: https://lore.kernel.org/r/20250314160248.502324-1-arnd@kernel.org +Signed-off-by: Guenter Roeck +Signed-off-by: Wim Van Sebroeck +Signed-off-by: Sasha Levin +--- + drivers/watchdog/aspeed_wdt.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/watchdog/aspeed_wdt.c b/drivers/watchdog/aspeed_wdt.c +index 369635b38ca0e..837e15701c0e2 100644 +--- a/drivers/watchdog/aspeed_wdt.c ++++ b/drivers/watchdog/aspeed_wdt.c +@@ -254,7 +254,7 @@ static void aspeed_wdt_update_bootstatus(struct platform_device *pdev, + + if (!of_device_is_compatible(pdev->dev.of_node, "aspeed,ast2400-wdt")) { + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); +- idx = ((intptr_t)wdt->base & 0x00000fff) / resource_size(res); ++ idx = ((intptr_t)wdt->base & 0x00000fff) / (uintptr_t)resource_size(res); + } + + scu_base = syscon_regmap_lookup_by_compatible(scu.compatible); +-- +2.39.5 + diff --git a/queue-6.14/watchdog-aspeed-update-bootstatus-handling.patch b/queue-6.14/watchdog-aspeed-update-bootstatus-handling.patch new file mode 100644 index 0000000000..df67e1ebae --- /dev/null +++ b/queue-6.14/watchdog-aspeed-update-bootstatus-handling.patch @@ -0,0 +1,182 @@ +From c3803ca0190f3d22bb546577f7fd9022404f6689 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 13 Jan 2025 17:37:37 +0800 +Subject: watchdog: aspeed: Update bootstatus handling + +From: Chin-Ting Kuo + +[ Upstream commit 5c03f9f4d36292150c14ebd90788c4d3273ed9dc ] + +The boot status in the watchdog device struct is updated during +controller probe stage. Application layer can get the boot status +through the command, cat /sys/class/watchdog/watchdogX/bootstatus. +The bootstatus can be, +WDIOF_CARDRESET => System is reset due to WDT timeout occurs. +Others => Other reset events, e.g., power on reset. + +On ASPEED platforms, boot status is recorded in the SCU registers. +- AST2400: Only a bit is used to represent system reset triggered by + any WDT controller. +- AST2500/AST2600: System reset triggered by different WDT controllers + can be distinguished by different SCU bits. + +Besides, on AST2400 and AST2500, since alternating boot event is +also triggered by using WDT timeout mechanism, it is classified +as WDIOF_CARDRESET. + +Signed-off-by: Chin-Ting Kuo +Reviewed-by: Andrew Jeffery +Reviewed-by: Guenter Roeck +Link: https://lore.kernel.org/r/20250113093737.845097-2-chin-ting_kuo@aspeedtech.com +Signed-off-by: Guenter Roeck +Signed-off-by: Wim Van Sebroeck +Signed-off-by: Sasha Levin +--- + drivers/watchdog/aspeed_wdt.c | 81 ++++++++++++++++++++++++++++++++++- + 1 file changed, 79 insertions(+), 2 deletions(-) + +diff --git a/drivers/watchdog/aspeed_wdt.c b/drivers/watchdog/aspeed_wdt.c +index b4773a6aaf8cc..369635b38ca0e 100644 +--- a/drivers/watchdog/aspeed_wdt.c ++++ b/drivers/watchdog/aspeed_wdt.c +@@ -11,21 +11,30 @@ + #include + #include + #include ++#include + #include + #include + #include + #include ++#include + #include + + static bool nowayout = WATCHDOG_NOWAYOUT; + module_param(nowayout, bool, 0); + MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" + __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); ++struct aspeed_wdt_scu { ++ const char *compatible; ++ u32 reset_status_reg; ++ u32 wdt_reset_mask; ++ u32 wdt_reset_mask_shift; ++}; + + struct aspeed_wdt_config { + u32 ext_pulse_width_mask; + u32 irq_shift; + u32 irq_mask; ++ struct aspeed_wdt_scu scu; + }; + + struct aspeed_wdt { +@@ -39,18 +48,36 @@ static const struct aspeed_wdt_config ast2400_config = { + .ext_pulse_width_mask = 0xff, + .irq_shift = 0, + .irq_mask = 0, ++ .scu = { ++ .compatible = "aspeed,ast2400-scu", ++ .reset_status_reg = 0x3c, ++ .wdt_reset_mask = 0x1, ++ .wdt_reset_mask_shift = 1, ++ }, + }; + + static const struct aspeed_wdt_config ast2500_config = { + .ext_pulse_width_mask = 0xfffff, + .irq_shift = 12, + .irq_mask = GENMASK(31, 12), ++ .scu = { ++ .compatible = "aspeed,ast2500-scu", ++ .reset_status_reg = 0x3c, ++ .wdt_reset_mask = 0x1, ++ .wdt_reset_mask_shift = 2, ++ }, + }; + + static const struct aspeed_wdt_config ast2600_config = { + .ext_pulse_width_mask = 0xfffff, + .irq_shift = 0, + .irq_mask = GENMASK(31, 10), ++ .scu = { ++ .compatible = "aspeed,ast2600-scu", ++ .reset_status_reg = 0x74, ++ .wdt_reset_mask = 0xf, ++ .wdt_reset_mask_shift = 16, ++ }, + }; + + static const struct of_device_id aspeed_wdt_of_table[] = { +@@ -213,6 +240,56 @@ static int aspeed_wdt_restart(struct watchdog_device *wdd, + return 0; + } + ++static void aspeed_wdt_update_bootstatus(struct platform_device *pdev, ++ struct aspeed_wdt *wdt) ++{ ++ const struct resource *res; ++ struct aspeed_wdt_scu scu = wdt->cfg->scu; ++ struct regmap *scu_base; ++ u32 reset_mask_width; ++ u32 reset_mask_shift; ++ u32 idx = 0; ++ u32 status; ++ int ret; ++ ++ if (!of_device_is_compatible(pdev->dev.of_node, "aspeed,ast2400-wdt")) { ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ idx = ((intptr_t)wdt->base & 0x00000fff) / resource_size(res); ++ } ++ ++ scu_base = syscon_regmap_lookup_by_compatible(scu.compatible); ++ if (IS_ERR(scu_base)) { ++ wdt->wdd.bootstatus = WDIOS_UNKNOWN; ++ return; ++ } ++ ++ ret = regmap_read(scu_base, scu.reset_status_reg, &status); ++ if (ret) { ++ wdt->wdd.bootstatus = WDIOS_UNKNOWN; ++ return; ++ } ++ ++ reset_mask_width = hweight32(scu.wdt_reset_mask); ++ reset_mask_shift = scu.wdt_reset_mask_shift + ++ reset_mask_width * idx; ++ ++ if (status & (scu.wdt_reset_mask << reset_mask_shift)) ++ wdt->wdd.bootstatus = WDIOF_CARDRESET; ++ ++ /* clear wdt reset event flag */ ++ if (of_device_is_compatible(pdev->dev.of_node, "aspeed,ast2400-wdt") || ++ of_device_is_compatible(pdev->dev.of_node, "aspeed,ast2500-wdt")) { ++ ret = regmap_read(scu_base, scu.reset_status_reg, &status); ++ if (!ret) { ++ status &= ~(scu.wdt_reset_mask << reset_mask_shift); ++ regmap_write(scu_base, scu.reset_status_reg, status); ++ } ++ } else { ++ regmap_write(scu_base, scu.reset_status_reg, ++ scu.wdt_reset_mask << reset_mask_shift); ++ } ++} ++ + /* access_cs0 shows if cs0 is accessible, hence the reverted bit */ + static ssize_t access_cs0_show(struct device *dev, + struct device_attribute *attr, char *buf) +@@ -458,10 +535,10 @@ static int aspeed_wdt_probe(struct platform_device *pdev) + writel(duration - 1, wdt->base + WDT_RESET_WIDTH); + } + ++ aspeed_wdt_update_bootstatus(pdev, wdt); ++ + status = readl(wdt->base + WDT_TIMEOUT_STATUS); + if (status & WDT_TIMEOUT_STATUS_BOOT_SECONDARY) { +- wdt->wdd.bootstatus = WDIOF_CARDRESET; +- + if (of_device_is_compatible(np, "aspeed,ast2400-wdt") || + of_device_is_compatible(np, "aspeed,ast2500-wdt")) + wdt->wdd.groups = bswitch_groups; +-- +2.39.5 + diff --git a/queue-6.14/watchdog-s3c2410_wdt-fix-pmu-register-bits-for-exyno.patch b/queue-6.14/watchdog-s3c2410_wdt-fix-pmu-register-bits-for-exyno.patch new file mode 100644 index 0000000000..d8604c26fe --- /dev/null +++ b/queue-6.14/watchdog-s3c2410_wdt-fix-pmu-register-bits-for-exyno.patch @@ -0,0 +1,73 @@ +From a49cc6c5e7eb71e02fcf9b7c62b25b5a705542ba Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 13 Feb 2025 09:41:04 +0900 +Subject: watchdog: s3c2410_wdt: Fix PMU register bits for ExynosAutoV920 SoC + +From: Kyunghwan Seo + +[ Upstream commit 480ee8a260e6f87cbcdaff77ac2cbf6dc03f0f4f ] + +Fix the PMU register bits for the ExynosAutoV920 SoC. +This SoC has different bit information compared to its previous +version, ExynosAutoV9, and we have made the necessary adjustments. + +rst_stat_bit: + - ExynosAutoV920 cl0 : 0 + - ExynosAutoV920 cl1 : 1 + +cnt_en_bit: + - ExynosAutoV920 cl0 : 8 + - ExynosAutoV920 cl1 : 8 + +Signed-off-by: Kyunghwan Seo +Signed-off-by: Sangwook Shin +Reviewed-by: Alim Akhtar +Reviewed-by: Guenter Roeck +Link: https://lore.kernel.org/r/20250213004104.3881711-1-sw617.shin@samsung.com +Signed-off-by: Guenter Roeck +Signed-off-by: Wim Van Sebroeck +Signed-off-by: Sasha Levin +--- + drivers/watchdog/s3c2410_wdt.c | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +diff --git a/drivers/watchdog/s3c2410_wdt.c b/drivers/watchdog/s3c2410_wdt.c +index 30450e99e5e9d..bdd81d8074b24 100644 +--- a/drivers/watchdog/s3c2410_wdt.c ++++ b/drivers/watchdog/s3c2410_wdt.c +@@ -72,6 +72,8 @@ + #define EXYNOS850_CLUSTER1_WDTRESET_BIT 23 + #define EXYNOSAUTOV9_CLUSTER0_WDTRESET_BIT 25 + #define EXYNOSAUTOV9_CLUSTER1_WDTRESET_BIT 24 ++#define EXYNOSAUTOV920_CLUSTER0_WDTRESET_BIT 0 ++#define EXYNOSAUTOV920_CLUSTER1_WDTRESET_BIT 1 + + #define GS_CLUSTER0_NONCPU_OUT 0x1220 + #define GS_CLUSTER1_NONCPU_OUT 0x1420 +@@ -312,9 +314,9 @@ static const struct s3c2410_wdt_variant drv_data_exynosautov920_cl0 = { + .mask_bit = 2, + .mask_reset_inv = true, + .rst_stat_reg = EXYNOS5_RST_STAT_REG_OFFSET, +- .rst_stat_bit = EXYNOSAUTOV9_CLUSTER0_WDTRESET_BIT, ++ .rst_stat_bit = EXYNOSAUTOV920_CLUSTER0_WDTRESET_BIT, + .cnt_en_reg = EXYNOSAUTOV920_CLUSTER0_NONCPU_OUT, +- .cnt_en_bit = 7, ++ .cnt_en_bit = 8, + .quirks = QUIRK_HAS_WTCLRINT_REG | QUIRK_HAS_PMU_MASK_RESET | + QUIRK_HAS_PMU_RST_STAT | QUIRK_HAS_PMU_CNT_EN | + QUIRK_HAS_DBGACK_BIT, +@@ -325,9 +327,9 @@ static const struct s3c2410_wdt_variant drv_data_exynosautov920_cl1 = { + .mask_bit = 2, + .mask_reset_inv = true, + .rst_stat_reg = EXYNOS5_RST_STAT_REG_OFFSET, +- .rst_stat_bit = EXYNOSAUTOV9_CLUSTER1_WDTRESET_BIT, ++ .rst_stat_bit = EXYNOSAUTOV920_CLUSTER1_WDTRESET_BIT, + .cnt_en_reg = EXYNOSAUTOV920_CLUSTER1_NONCPU_OUT, +- .cnt_en_bit = 7, ++ .cnt_en_bit = 8, + .quirks = QUIRK_HAS_WTCLRINT_REG | QUIRK_HAS_PMU_MASK_RESET | + QUIRK_HAS_PMU_RST_STAT | QUIRK_HAS_PMU_CNT_EN | + QUIRK_HAS_DBGACK_BIT, +-- +2.39.5 + diff --git a/queue-6.14/wifi-ath11k-use-dma_alloc_noncoherent-for-rx_tid-buf.patch b/queue-6.14/wifi-ath11k-use-dma_alloc_noncoherent-for-rx_tid-buf.patch new file mode 100644 index 0000000000..eddc7f09cf --- /dev/null +++ b/queue-6.14/wifi-ath11k-use-dma_alloc_noncoherent-for-rx_tid-buf.patch @@ -0,0 +1,277 @@ +From a535644548aecf29d355fb6bec779f186a19723c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 19 Jan 2025 22:12:19 +0530 +Subject: wifi: ath11k: Use dma_alloc_noncoherent for rx_tid buffer allocation + +From: P Praneesh + +[ Upstream commit eeadc6baf8b3dcd32787cc84f0473dc2a2850370 ] + +Currently, the driver allocates cacheable DMA buffers for the rx_tid +structure using kzalloc() and dma_map_single(). These buffers are +long-lived and can persist for the lifetime of the peer, which is not +advisable. Instead of using kzalloc() and dma_map_single() for allocating +cacheable DMA buffers, utilize the dma_alloc_noncoherent() helper for the +allocation of long-lived cacheable DMA buffers, such as the peer's rx_tid. +Since dma_alloc_noncoherent() returns unaligned physical and virtual +addresses, align them internally before use within the driver. This +ensures proper allocation of non-coherent memory through the kernel +helper. + +Tested-on: QCN9074 hw1.0 PCI WLAN.HK.2.7.0.1-01744-QCAHKSWPL_SILICONZ-1 +Tested-on: WCN6855 hw2.0 PCI WLAN.HSP.1.1-03125-QCAHSPSWPL_V1_V2_SILICONZ_LITE-3 + +Signed-off-by: P Praneesh +Tested-by: Tim Harvey +Link: https://patch.msgid.link/20250119164219.647059-3-quic_ppranees@quicinc.com +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath11k/dp.h | 6 +- + drivers/net/wireless/ath/ath11k/dp_rx.c | 117 +++++++++++------------- + 2 files changed, 58 insertions(+), 65 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath11k/dp.h b/drivers/net/wireless/ath/ath11k/dp.h +index f777314db8b36..7a55afd33be82 100644 +--- a/drivers/net/wireless/ath/ath11k/dp.h ++++ b/drivers/net/wireless/ath/ath11k/dp.h +@@ -1,7 +1,7 @@ + /* SPDX-License-Identifier: BSD-3-Clause-Clear */ + /* + * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved. +- * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved. ++ * Copyright (c) 2021-2023, 2025 Qualcomm Innovation Center, Inc. All rights reserved. + */ + + #ifndef ATH11K_DP_H +@@ -20,7 +20,6 @@ struct ath11k_ext_irq_grp; + + struct dp_rx_tid { + u8 tid; +- u32 *vaddr; + dma_addr_t paddr; + u32 size; + u32 ba_win_sz; +@@ -37,6 +36,9 @@ struct dp_rx_tid { + /* Timer info related to fragments */ + struct timer_list frag_timer; + struct ath11k_base *ab; ++ u32 *vaddr_unaligned; ++ dma_addr_t paddr_unaligned; ++ u32 unaligned_size; + }; + + #define DP_REO_DESC_FREE_THRESHOLD 64 +diff --git a/drivers/net/wireless/ath/ath11k/dp_rx.c b/drivers/net/wireless/ath/ath11k/dp_rx.c +index b8b3dce9cdb53..a7a484a9ba7fb 100644 +--- a/drivers/net/wireless/ath/ath11k/dp_rx.c ++++ b/drivers/net/wireless/ath/ath11k/dp_rx.c +@@ -1,7 +1,7 @@ + // SPDX-License-Identifier: BSD-3-Clause-Clear + /* + * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved. +- * Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved. ++ * Copyright (c) 2021-2025 Qualcomm Innovation Center, Inc. All rights reserved. + */ + + #include +@@ -675,11 +675,11 @@ void ath11k_dp_reo_cmd_list_cleanup(struct ath11k_base *ab) + list_for_each_entry_safe(cmd, tmp, &dp->reo_cmd_list, list) { + list_del(&cmd->list); + rx_tid = &cmd->data; +- if (rx_tid->vaddr) { +- dma_unmap_single(ab->dev, rx_tid->paddr, +- rx_tid->size, DMA_BIDIRECTIONAL); +- kfree(rx_tid->vaddr); +- rx_tid->vaddr = NULL; ++ if (rx_tid->vaddr_unaligned) { ++ dma_free_noncoherent(ab->dev, rx_tid->unaligned_size, ++ rx_tid->vaddr_unaligned, ++ rx_tid->paddr_unaligned, DMA_BIDIRECTIONAL); ++ rx_tid->vaddr_unaligned = NULL; + } + kfree(cmd); + } +@@ -689,11 +689,11 @@ void ath11k_dp_reo_cmd_list_cleanup(struct ath11k_base *ab) + list_del(&cmd_cache->list); + dp->reo_cmd_cache_flush_count--; + rx_tid = &cmd_cache->data; +- if (rx_tid->vaddr) { +- dma_unmap_single(ab->dev, rx_tid->paddr, +- rx_tid->size, DMA_BIDIRECTIONAL); +- kfree(rx_tid->vaddr); +- rx_tid->vaddr = NULL; ++ if (rx_tid->vaddr_unaligned) { ++ dma_free_noncoherent(ab->dev, rx_tid->unaligned_size, ++ rx_tid->vaddr_unaligned, ++ rx_tid->paddr_unaligned, DMA_BIDIRECTIONAL); ++ rx_tid->vaddr_unaligned = NULL; + } + kfree(cmd_cache); + } +@@ -708,11 +708,11 @@ static void ath11k_dp_reo_cmd_free(struct ath11k_dp *dp, void *ctx, + if (status != HAL_REO_CMD_SUCCESS) + ath11k_warn(dp->ab, "failed to flush rx tid hw desc, tid %d status %d\n", + rx_tid->tid, status); +- if (rx_tid->vaddr) { +- dma_unmap_single(dp->ab->dev, rx_tid->paddr, rx_tid->size, +- DMA_BIDIRECTIONAL); +- kfree(rx_tid->vaddr); +- rx_tid->vaddr = NULL; ++ if (rx_tid->vaddr_unaligned) { ++ dma_free_noncoherent(dp->ab->dev, rx_tid->unaligned_size, ++ rx_tid->vaddr_unaligned, ++ rx_tid->paddr_unaligned, DMA_BIDIRECTIONAL); ++ rx_tid->vaddr_unaligned = NULL; + } + } + +@@ -749,10 +749,10 @@ static void ath11k_dp_reo_cache_flush(struct ath11k_base *ab, + if (ret) { + ath11k_err(ab, "failed to send HAL_REO_CMD_FLUSH_CACHE cmd, tid %d (%d)\n", + rx_tid->tid, ret); +- dma_unmap_single(ab->dev, rx_tid->paddr, rx_tid->size, +- DMA_BIDIRECTIONAL); +- kfree(rx_tid->vaddr); +- rx_tid->vaddr = NULL; ++ dma_free_noncoherent(ab->dev, rx_tid->unaligned_size, ++ rx_tid->vaddr_unaligned, ++ rx_tid->paddr_unaligned, DMA_BIDIRECTIONAL); ++ rx_tid->vaddr_unaligned = NULL; + } + } + +@@ -802,10 +802,10 @@ static void ath11k_dp_rx_tid_del_func(struct ath11k_dp *dp, void *ctx, + + return; + free_desc: +- dma_unmap_single(ab->dev, rx_tid->paddr, rx_tid->size, +- DMA_BIDIRECTIONAL); +- kfree(rx_tid->vaddr); +- rx_tid->vaddr = NULL; ++ dma_free_noncoherent(ab->dev, rx_tid->unaligned_size, ++ rx_tid->vaddr_unaligned, ++ rx_tid->paddr_unaligned, DMA_BIDIRECTIONAL); ++ rx_tid->vaddr_unaligned = NULL; + } + + void ath11k_peer_rx_tid_delete(struct ath11k *ar, +@@ -831,14 +831,16 @@ void ath11k_peer_rx_tid_delete(struct ath11k *ar, + if (ret != -ESHUTDOWN) + ath11k_err(ar->ab, "failed to send HAL_REO_CMD_UPDATE_RX_QUEUE cmd, tid %d (%d)\n", + tid, ret); +- dma_unmap_single(ar->ab->dev, rx_tid->paddr, rx_tid->size, +- DMA_BIDIRECTIONAL); +- kfree(rx_tid->vaddr); +- rx_tid->vaddr = NULL; ++ dma_free_noncoherent(ar->ab->dev, rx_tid->unaligned_size, ++ rx_tid->vaddr_unaligned, ++ rx_tid->paddr_unaligned, DMA_BIDIRECTIONAL); ++ rx_tid->vaddr_unaligned = NULL; + } + + rx_tid->paddr = 0; ++ rx_tid->paddr_unaligned = 0; + rx_tid->size = 0; ++ rx_tid->unaligned_size = 0; + } + + static int ath11k_dp_rx_link_desc_return(struct ath11k_base *ab, +@@ -982,10 +984,9 @@ static void ath11k_dp_rx_tid_mem_free(struct ath11k_base *ab, + if (!rx_tid->active) + goto unlock_exit; + +- dma_unmap_single(ab->dev, rx_tid->paddr, rx_tid->size, +- DMA_BIDIRECTIONAL); +- kfree(rx_tid->vaddr); +- rx_tid->vaddr = NULL; ++ dma_free_noncoherent(ab->dev, rx_tid->unaligned_size, rx_tid->vaddr_unaligned, ++ rx_tid->paddr_unaligned, DMA_BIDIRECTIONAL); ++ rx_tid->vaddr_unaligned = NULL; + + rx_tid->active = false; + +@@ -1000,9 +1001,8 @@ int ath11k_peer_rx_tid_setup(struct ath11k *ar, const u8 *peer_mac, int vdev_id, + struct ath11k_base *ab = ar->ab; + struct ath11k_peer *peer; + struct dp_rx_tid *rx_tid; +- u32 hw_desc_sz; +- u32 *addr_aligned; +- void *vaddr; ++ u32 hw_desc_sz, *vaddr; ++ void *vaddr_unaligned; + dma_addr_t paddr; + int ret; + +@@ -1050,49 +1050,40 @@ int ath11k_peer_rx_tid_setup(struct ath11k *ar, const u8 *peer_mac, int vdev_id, + else + hw_desc_sz = ath11k_hal_reo_qdesc_size(DP_BA_WIN_SZ_MAX, tid); + +- vaddr = kzalloc(hw_desc_sz + HAL_LINK_DESC_ALIGN - 1, GFP_ATOMIC); +- if (!vaddr) { ++ rx_tid->unaligned_size = hw_desc_sz + HAL_LINK_DESC_ALIGN - 1; ++ vaddr_unaligned = dma_alloc_noncoherent(ab->dev, rx_tid->unaligned_size, &paddr, ++ DMA_BIDIRECTIONAL, GFP_ATOMIC); ++ if (!vaddr_unaligned) { + spin_unlock_bh(&ab->base_lock); + return -ENOMEM; + } + +- addr_aligned = PTR_ALIGN(vaddr, HAL_LINK_DESC_ALIGN); +- +- ath11k_hal_reo_qdesc_setup(addr_aligned, tid, ba_win_sz, +- ssn, pn_type); +- +- paddr = dma_map_single(ab->dev, addr_aligned, hw_desc_sz, +- DMA_BIDIRECTIONAL); +- +- ret = dma_mapping_error(ab->dev, paddr); +- if (ret) { +- spin_unlock_bh(&ab->base_lock); +- ath11k_warn(ab, "failed to setup dma map for peer %pM rx tid %d: %d\n", +- peer_mac, tid, ret); +- goto err_mem_free; +- } +- +- rx_tid->vaddr = vaddr; +- rx_tid->paddr = paddr; ++ rx_tid->vaddr_unaligned = vaddr_unaligned; ++ vaddr = PTR_ALIGN(vaddr_unaligned, HAL_LINK_DESC_ALIGN); ++ rx_tid->paddr_unaligned = paddr; ++ rx_tid->paddr = rx_tid->paddr_unaligned + ((unsigned long)vaddr - ++ (unsigned long)rx_tid->vaddr_unaligned); ++ ath11k_hal_reo_qdesc_setup(vaddr, tid, ba_win_sz, ssn, pn_type); + rx_tid->size = hw_desc_sz; + rx_tid->active = true; + ++ /* After dma_alloc_noncoherent, vaddr is being modified for reo qdesc setup. ++ * Since these changes are not reflected in the device, driver now needs to ++ * explicitly call dma_sync_single_for_device. ++ */ ++ dma_sync_single_for_device(ab->dev, rx_tid->paddr, ++ rx_tid->size, ++ DMA_TO_DEVICE); + spin_unlock_bh(&ab->base_lock); + +- ret = ath11k_wmi_peer_rx_reorder_queue_setup(ar, vdev_id, peer_mac, +- paddr, tid, 1, ba_win_sz); ++ ret = ath11k_wmi_peer_rx_reorder_queue_setup(ar, vdev_id, peer_mac, rx_tid->paddr, ++ tid, 1, ba_win_sz); + if (ret) { + ath11k_warn(ar->ab, "failed to setup rx reorder queue for peer %pM tid %d: %d\n", + peer_mac, tid, ret); + ath11k_dp_rx_tid_mem_free(ab, peer_mac, vdev_id, tid); + } + +- return ret; +- +-err_mem_free: +- kfree(rx_tid->vaddr); +- rx_tid->vaddr = NULL; +- + return ret; + } + +-- +2.39.5 + diff --git a/queue-6.14/wifi-ath12k-avoid-napi_sync-before-napi_enable.patch b/queue-6.14/wifi-ath12k-avoid-napi_sync-before-napi_enable.patch new file mode 100644 index 0000000000..db2b3e6658 --- /dev/null +++ b/queue-6.14/wifi-ath12k-avoid-napi_sync-before-napi_enable.patch @@ -0,0 +1,78 @@ +From 1b06e3d70050de0615ca810193fd3259059b8547 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 24 Jan 2025 14:30:58 +0530 +Subject: wifi: ath12k: Avoid napi_sync() before napi_enable() + +From: Avula Sri Charan + +[ Upstream commit 268c73d470a5790a492a2fc2ded084b909d144f3 ] + +In case of MHI error a reset work will be queued which will try +napi_disable() after napi_synchronize(). + +As the napi will be only enabled after qmi_firmware_ready event, +trying napi_synchronize() before napi_enable() will result in +indefinite sleep in case of a firmware crash in QMI init sequence. + +To avoid this, introduce napi_enabled flag to check if napi is enabled +or not before calling napi_synchronize(). + +Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.3.1-00173-QCAHKSWPL_SILICONZ-1 + +Signed-off-by: Avula Sri Charan +Signed-off-by: Tamizh Chelvam Raja +Reviewed-by: Aditya Kumar Singh +Link: https://patch.msgid.link/20250124090058.3194299-1-quic_tamizhr@quicinc.com +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath12k/core.h | 1 + + drivers/net/wireless/ath/ath12k/pci.c | 13 ++++++++++--- + 2 files changed, 11 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h +index 6325ac493f82c..2699c383fc4c9 100644 +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h +@@ -166,6 +166,7 @@ struct ath12k_ext_irq_grp { + u32 num_irq; + u32 grp_id; + u64 timestamp; ++ bool napi_enabled; + struct napi_struct napi; + struct net_device *napi_ndev; + }; +diff --git a/drivers/net/wireless/ath/ath12k/pci.c b/drivers/net/wireless/ath/ath12k/pci.c +index ee14b84845487..895b2314d1d58 100644 +--- a/drivers/net/wireless/ath/ath12k/pci.c ++++ b/drivers/net/wireless/ath/ath12k/pci.c +@@ -483,8 +483,11 @@ static void __ath12k_pci_ext_irq_disable(struct ath12k_base *ab) + + ath12k_pci_ext_grp_disable(irq_grp); + +- napi_synchronize(&irq_grp->napi); +- napi_disable(&irq_grp->napi); ++ if (irq_grp->napi_enabled) { ++ napi_synchronize(&irq_grp->napi); ++ napi_disable(&irq_grp->napi); ++ irq_grp->napi_enabled = false; ++ } + } + } + +@@ -1114,7 +1117,11 @@ void ath12k_pci_ext_irq_enable(struct ath12k_base *ab) + for (i = 0; i < ATH12K_EXT_IRQ_GRP_NUM_MAX; i++) { + struct ath12k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i]; + +- napi_enable(&irq_grp->napi); ++ if (!irq_grp->napi_enabled) { ++ napi_enable(&irq_grp->napi); ++ irq_grp->napi_enabled = true; ++ } ++ + ath12k_pci_ext_grp_enable(irq_grp); + } + +-- +2.39.5 + diff --git a/queue-6.14/wifi-ath12k-enable-mlo-setup-ready-and-teardown-comm.patch b/queue-6.14/wifi-ath12k-enable-mlo-setup-ready-and-teardown-comm.patch new file mode 100644 index 0000000000..233d30871c --- /dev/null +++ b/queue-6.14/wifi-ath12k-enable-mlo-setup-ready-and-teardown-comm.patch @@ -0,0 +1,137 @@ +From 85f91df4ece637c376a2a944a0ba38247f5f4772 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 7 Feb 2025 10:33:25 +0530 +Subject: wifi: ath12k: Enable MLO setup ready and teardown commands for single + split-phy device + +From: Aaradhana Sahu + +[ Upstream commit 5cec2d86c7f4242fb30a696d8e6fd48109bf3e8f ] + +When multi-link operation(MLO) is enabled through follow-up patches in +the single split-phy device, the firmware expects hardware links +(hw_links) information from the driver. + +If driver does not send WMI multi-link setup and ready command to the +firmware during MLO setup for single split-phy device, the firmware will +be unaware of the hw_links component of the multi-link operation. This may +lead to firmware assert during multi-link association. + +Therefore, enable WMI setup, ready and teardown commands for single +split-phy PCI device. + +Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.3.1-00173-QCAHKSWPL_SILICONZ-1 +Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0.c5-00481-QCAHMTSWPL_V1.0_V2.0_SILICONZ-3 + +Signed-off-by: Aaradhana Sahu +Reviewed-by: Vasanthakumar Thiagarajan +Link: https://patch.msgid.link/20250207050327.360987-2-quic_aarasahu@quicinc.com +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath12k/core.c | 33 +++++++++++++++++++++++++- + drivers/net/wireless/ath/ath12k/core.h | 1 + + drivers/net/wireless/ath/ath12k/mac.c | 9 +++++++ + 3 files changed, 42 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/ath/ath12k/core.c b/drivers/net/wireless/ath/ath12k/core.c +index 212cd935e60a0..ffd173ff7b08c 100644 +--- a/drivers/net/wireless/ath/ath12k/core.c ++++ b/drivers/net/wireless/ath/ath12k/core.c +@@ -887,10 +887,41 @@ static void ath12k_core_hw_group_stop(struct ath12k_hw_group *ag) + ath12k_mac_destroy(ag); + } + ++u8 ath12k_get_num_partner_link(struct ath12k *ar) ++{ ++ struct ath12k_base *partner_ab, *ab = ar->ab; ++ struct ath12k_hw_group *ag = ab->ag; ++ struct ath12k_pdev *pdev; ++ u8 num_link = 0; ++ int i, j; ++ ++ lockdep_assert_held(&ag->mutex); ++ ++ for (i = 0; i < ag->num_devices; i++) { ++ partner_ab = ag->ab[i]; ++ ++ for (j = 0; j < partner_ab->num_radios; j++) { ++ pdev = &partner_ab->pdevs[j]; ++ ++ /* Avoid the self link */ ++ if (ar == pdev->ar) ++ continue; ++ ++ num_link++; ++ } ++ } ++ ++ return num_link; ++} ++ + static int __ath12k_mac_mlo_ready(struct ath12k *ar) + { ++ u8 num_link = ath12k_get_num_partner_link(ar); + int ret; + ++ if (num_link == 0) ++ return 0; ++ + ret = ath12k_wmi_mlo_ready(ar); + if (ret) { + ath12k_err(ar->ab, "MLO ready failed for pdev %d: %d\n", +@@ -932,7 +963,7 @@ static int ath12k_core_mlo_setup(struct ath12k_hw_group *ag) + { + int ret, i; + +- if (!ag->mlo_capable || ag->num_devices == 1) ++ if (!ag->mlo_capable) + return 0; + + ret = ath12k_mac_mlo_setup(ag); +diff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h +index ee595794a7aee..6325ac493f82c 100644 +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h +@@ -1084,6 +1084,7 @@ int ath12k_core_resume(struct ath12k_base *ab); + int ath12k_core_suspend(struct ath12k_base *ab); + int ath12k_core_suspend_late(struct ath12k_base *ab); + void ath12k_core_hw_group_unassign(struct ath12k_base *ab); ++u8 ath12k_get_num_partner_link(struct ath12k *ar); + + const struct firmware *ath12k_core_firmware_request(struct ath12k_base *ab, + const char *filename); +diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c +index 9c3e66dbe0c3b..9123ffab55b52 100644 +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -11140,6 +11140,9 @@ static int __ath12k_mac_mlo_setup(struct ath12k *ar) + } + } + ++ if (num_link == 0) ++ return 0; ++ + mlo.group_id = cpu_to_le32(ag->id); + mlo.partner_link_id = partner_link_id; + mlo.num_partner_links = num_link; +@@ -11169,10 +11172,16 @@ static int __ath12k_mac_mlo_teardown(struct ath12k *ar) + { + struct ath12k_base *ab = ar->ab; + int ret; ++ u8 num_link; + + if (test_bit(ATH12K_FLAG_RECOVERY, &ab->dev_flags)) + return 0; + ++ num_link = ath12k_get_num_partner_link(ar); ++ ++ if (num_link == 0) ++ return 0; ++ + ret = ath12k_wmi_mlo_teardown(ar); + if (ret) { + ath12k_warn(ab, "failed to send MLO teardown WMI command for pdev %d: %d\n", +-- +2.39.5 + diff --git a/queue-6.14/wifi-ath12k-fetch-regdb.bin-file-from-board-2.bin.patch b/queue-6.14/wifi-ath12k-fetch-regdb.bin-file-from-board-2.bin.patch new file mode 100644 index 0000000000..616ef04a1f --- /dev/null +++ b/queue-6.14/wifi-ath12k-fetch-regdb.bin-file-from-board-2.bin.patch @@ -0,0 +1,77 @@ +From d35663feacb955bdfb2769b04231c0172af119b3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 16 Jan 2025 08:58:35 +0530 +Subject: wifi: ath12k: Fetch regdb.bin file from board-2.bin + +From: Aaradhana Sahu + +[ Upstream commit 24f587572acf7509127dbdfcbf1b681ef84eeba0 ] + +Currently, ath12k_core_fetch_regdb() finds regdb.bin file through +board id's but in board-2.bin file regdb.bin file is present with +default board id because of which regdb.bin is not fetched. + +Add support to fetch regdb.bin file from board-2.bin through +default board id. + +Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.3.1-00173-QCAHKSWPL_SILICONZ-1 + +Signed-off-by: Aaradhana Sahu +Reviewed-by: Aditya Kumar Singh +Link: https://patch.msgid.link/20250116032835.118397-1-quic_aarasahu@quicinc.com +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath12k/core.c | 12 +++++++----- + 1 file changed, 7 insertions(+), 5 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath12k/core.c b/drivers/net/wireless/ath/ath12k/core.c +index ffd173ff7b08c..d0aed4c56050d 100644 +--- a/drivers/net/wireless/ath/ath12k/core.c ++++ b/drivers/net/wireless/ath/ath12k/core.c +@@ -173,7 +173,7 @@ EXPORT_SYMBOL(ath12k_core_resume); + + static int __ath12k_core_create_board_name(struct ath12k_base *ab, char *name, + size_t name_len, bool with_variant, +- bool bus_type_mode) ++ bool bus_type_mode, bool with_default) + { + /* strlen(',variant=') + strlen(ab->qmi.target.bdf_ext) */ + char variant[9 + ATH12K_QMI_BDF_EXT_STR_LENGTH] = { 0 }; +@@ -204,7 +204,9 @@ static int __ath12k_core_create_board_name(struct ath12k_base *ab, char *name, + "bus=%s,qmi-chip-id=%d,qmi-board-id=%d%s", + ath12k_bus_str(ab->hif.bus), + ab->qmi.target.chip_id, +- ab->qmi.target.board_id, variant); ++ with_default ? ++ ATH12K_BOARD_ID_DEFAULT : ab->qmi.target.board_id, ++ variant); + break; + } + +@@ -216,19 +218,19 @@ static int __ath12k_core_create_board_name(struct ath12k_base *ab, char *name, + static int ath12k_core_create_board_name(struct ath12k_base *ab, char *name, + size_t name_len) + { +- return __ath12k_core_create_board_name(ab, name, name_len, true, false); ++ return __ath12k_core_create_board_name(ab, name, name_len, true, false, false); + } + + static int ath12k_core_create_fallback_board_name(struct ath12k_base *ab, char *name, + size_t name_len) + { +- return __ath12k_core_create_board_name(ab, name, name_len, false, false); ++ return __ath12k_core_create_board_name(ab, name, name_len, false, false, true); + } + + static int ath12k_core_create_bus_type_board_name(struct ath12k_base *ab, char *name, + size_t name_len) + { +- return __ath12k_core_create_board_name(ab, name, name_len, false, true); ++ return __ath12k_core_create_board_name(ab, name, name_len, false, true, true); + } + + const struct firmware *ath12k_core_firmware_request(struct ath12k_base *ab, +-- +2.39.5 + diff --git a/queue-6.14/wifi-ath12k-fix-ath12k_hal_tx_cmd_ext_desc_setup-inf.patch b/queue-6.14/wifi-ath12k-fix-ath12k_hal_tx_cmd_ext_desc_setup-inf.patch new file mode 100644 index 0000000000..716a2d9616 --- /dev/null +++ b/queue-6.14/wifi-ath12k-fix-ath12k_hal_tx_cmd_ext_desc_setup-inf.patch @@ -0,0 +1,41 @@ +From 2e21d5fa7b90cd290907de47b44aa0cb25a95ee2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 27 Jan 2025 08:13:06 +0100 +Subject: wifi: ath12k: fix ath12k_hal_tx_cmd_ext_desc_setup() info1 override + +From: Nicolas Escande + +[ Upstream commit df11edfba49e5fb69f4c9e7cb76082b89c417f78 ] + +Since inception there is an obvious typo laying around in +ath12k_hal_tx_cmd_ext_desc_setup(). Instead of initializing + adding +flags to tcl_ext_cmd->info1, we initialize + override. This will be needed +in the future to make broadcast frames work with ethernet encapsulation. + +Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.4.1-00199-QCAHKSWPL_SILICONZ-1 + +Signed-off-by: Nicolas Escande +Reviewed-by: Vasanthakumar Thiagarajan +Link: https://patch.msgid.link/20250127071306.1454699-1-nico.escande@gmail.com +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath12k/dp_tx.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/ath/ath12k/dp_tx.c b/drivers/net/wireless/ath/ath12k/dp_tx.c +index 75608ae027afe..a39bfb959797a 100644 +--- a/drivers/net/wireless/ath/ath12k/dp_tx.c ++++ b/drivers/net/wireless/ath/ath12k/dp_tx.c +@@ -117,7 +117,7 @@ static void ath12k_hal_tx_cmd_ext_desc_setup(struct ath12k_base *ab, + le32_encode_bits(ti->data_len, + HAL_TX_MSDU_EXT_INFO1_BUF_LEN); + +- tcl_ext_cmd->info1 = le32_encode_bits(1, HAL_TX_MSDU_EXT_INFO1_EXTN_OVERRIDE) | ++ tcl_ext_cmd->info1 |= le32_encode_bits(1, HAL_TX_MSDU_EXT_INFO1_EXTN_OVERRIDE) | + le32_encode_bits(ti->encap_type, + HAL_TX_MSDU_EXT_INFO1_ENCAP_TYPE) | + le32_encode_bits(ti->encrypt_type, +-- +2.39.5 + diff --git a/queue-6.14/wifi-ath12k-fix-end-offset-bit-definition-in-monitor.patch b/queue-6.14/wifi-ath12k-fix-end-offset-bit-definition-in-monitor.patch new file mode 100644 index 0000000000..6410b9804a --- /dev/null +++ b/queue-6.14/wifi-ath12k-fix-end-offset-bit-definition-in-monitor.patch @@ -0,0 +1,43 @@ +From db321df1c4513a1a8ebe618ba9e9e093cd26cb94 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 23 Dec 2024 11:31:25 +0530 +Subject: wifi: ath12k: Fix end offset bit definition in monitor ring + descriptor + +From: P Praneesh + +[ Upstream commit 6788a666000d600bd8f2e9f991cad9cc805e7f01 ] + +End offset for the monitor destination ring descriptor is defined as +16 bits, while the firmware definition specifies only 12 bits. +The remaining bits (bit 12 to bit 15) are reserved and may contain +junk values, leading to invalid information retrieval. Fix this issue +by updating the correct genmask values. + +Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.3.1-00173-QCAHKSWPL_SILICONZ-1 +Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0.c5-00481-QCAHMTSWPL_V1.0_V2.0_SILICONZ-3 + +Signed-off-by: P Praneesh +Link: https://patch.msgid.link/20241223060132.3506372-8-quic_ppranees@quicinc.com +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath12k/hal_desc.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/ath/ath12k/hal_desc.h b/drivers/net/wireless/ath/ath12k/hal_desc.h +index 7b0403d245e59..a102d27e5785f 100644 +--- a/drivers/net/wireless/ath/ath12k/hal_desc.h ++++ b/drivers/net/wireless/ath/ath12k/hal_desc.h +@@ -2968,7 +2968,7 @@ struct hal_mon_buf_ring { + + #define HAL_MON_DEST_COOKIE_BUF_ID GENMASK(17, 0) + +-#define HAL_MON_DEST_INFO0_END_OFFSET GENMASK(15, 0) ++#define HAL_MON_DEST_INFO0_END_OFFSET GENMASK(11, 0) + #define HAL_MON_DEST_INFO0_FLUSH_DETECTED BIT(16) + #define HAL_MON_DEST_INFO0_END_OF_PPDU BIT(17) + #define HAL_MON_DEST_INFO0_INITIATOR BIT(18) +-- +2.39.5 + diff --git a/queue-6.14/wifi-ath12k-fix-the-ampdu-id-fetch-in-the-hal_rx_mpd.patch b/queue-6.14/wifi-ath12k-fix-the-ampdu-id-fetch-in-the-hal_rx_mpd.patch new file mode 100644 index 0000000000..b17ee77ff3 --- /dev/null +++ b/queue-6.14/wifi-ath12k-fix-the-ampdu-id-fetch-in-the-hal_rx_mpd.patch @@ -0,0 +1,106 @@ +From c9cec9ed440ecd27ad77da9bb0f7cd48b642caf5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Feb 2025 07:08:51 +0530 +Subject: wifi: ath12k: fix the ampdu id fetch in the HAL_RX_MPDU_START TLV + +From: P Praneesh + +[ Upstream commit dff4f278ee1ef12d822b7ed2a1048d27037209bb ] + +Currently, ampdu id is update with peer id mask which is incorrect. +Therefore, update the ampdu id with PPDU id mask value. Also move +the ampdu_id field inside the user stats since it is a user id based +statistics. + +Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.3.1-00173-QCAHKSWPL_SILICONZ-1 +Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0.c5-00481-QCAHMTSWPL_V1.0_V2.0_SILICONZ-3 + +Signed-off-by: P Praneesh +Reviewed-by: Vasanthakumar Thiagarajan +Signed-off-by: Karthikeyan Periyasamy +Link: https://patch.msgid.link/20250206013854.174765-7-quic_periyasa@quicinc.com +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath12k/dp_mon.c | 16 ++++++++++------ + drivers/net/wireless/ath/ath12k/hal_rx.h | 3 ++- + 2 files changed, 12 insertions(+), 7 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath12k/dp_mon.c b/drivers/net/wireless/ath/ath12k/dp_mon.c +index b952e79179d01..f23fee7055abc 100644 +--- a/drivers/net/wireless/ath/ath12k/dp_mon.c ++++ b/drivers/net/wireless/ath/ath12k/dp_mon.c +@@ -1,7 +1,7 @@ + // SPDX-License-Identifier: BSD-3-Clause-Clear + /* + * Copyright (c) 2019-2021 The Linux Foundation. All rights reserved. +- * Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved. ++ * Copyright (c) 2021-2025 Qualcomm Innovation Center, Inc. All rights reserved. + */ + + #include "dp_mon.h" +@@ -655,6 +655,11 @@ ath12k_dp_mon_rx_parse_status_tlv(struct ath12k_base *ab, + if (userid < HAL_MAX_UL_MU_USERS) { + struct hal_rx_user_status *rxuser_stats = + &ppdu_info->userstats[userid]; ++ ++ if (ppdu_info->num_mpdu_fcs_ok > 1 || ++ ppdu_info->num_mpdu_fcs_err > 1) ++ ppdu_info->userstats[userid].ampdu_present = true; ++ + ppdu_info->num_users += 1; + + ath12k_dp_mon_rx_handle_ofdma_info(eu_stats, rxuser_stats); +@@ -755,8 +760,8 @@ ath12k_dp_mon_rx_parse_status_tlv(struct ath12k_base *ab, + if (userid < HAL_MAX_UL_MU_USERS) { + info[0] = __le32_to_cpu(mpdu_start->info0); + ppdu_info->userid = userid; +- ppdu_info->ampdu_id[userid] = +- u32_get_bits(info[0], HAL_RX_MPDU_START_INFO1_PEERID); ++ ppdu_info->userstats[userid].ampdu_id = ++ u32_get_bits(info[0], HAL_RX_MPDU_START_INFO0_PPDU_ID); + } + + break; +@@ -956,15 +961,14 @@ static void ath12k_dp_mon_update_radiotap(struct ath12k *ar, + { + struct ieee80211_supported_band *sband; + u8 *ptr = NULL; +- u16 ampdu_id = ppduinfo->ampdu_id[ppduinfo->userid]; + + rxs->flag |= RX_FLAG_MACTIME_START; + rxs->signal = ppduinfo->rssi_comb + ATH12K_DEFAULT_NOISE_FLOOR; + rxs->nss = ppduinfo->nss + 1; + +- if (ampdu_id) { ++ if (ppduinfo->userstats[ppduinfo->userid].ampdu_present) { + rxs->flag |= RX_FLAG_AMPDU_DETAILS; +- rxs->ampdu_reference = ampdu_id; ++ rxs->ampdu_reference = ppduinfo->userstats[ppduinfo->userid].ampdu_id; + } + + if (ppduinfo->he_mu_flags) { +diff --git a/drivers/net/wireless/ath/ath12k/hal_rx.h b/drivers/net/wireless/ath/ath12k/hal_rx.h +index 54f3eaeca8bb9..55b2dd5b76f6b 100644 +--- a/drivers/net/wireless/ath/ath12k/hal_rx.h ++++ b/drivers/net/wireless/ath/ath12k/hal_rx.h +@@ -146,6 +146,8 @@ struct hal_rx_user_status { + u32 mpdu_fcs_ok_bitmap[HAL_RX_NUM_WORDS_PER_PPDU_BITMAP]; + u32 mpdu_ok_byte_count; + u32 mpdu_err_byte_count; ++ bool ampdu_present; ++ u16 ampdu_id; + }; + + #define HAL_MAX_UL_MU_USERS 37 +@@ -230,7 +232,6 @@ struct hal_rx_mon_ppdu_info { + u8 addr4[ETH_ALEN]; + struct hal_rx_user_status userstats[HAL_MAX_UL_MU_USERS]; + u8 userid; +- u16 ampdu_id[HAL_MAX_UL_MU_USERS]; + bool first_msdu_in_mpdu; + bool is_ampdu; + u8 medium_prot_type; +-- +2.39.5 + diff --git a/queue-6.14/wifi-ath12k-improve-bss-discovery-with-hidden-ssid-i.patch b/queue-6.14/wifi-ath12k-improve-bss-discovery-with-hidden-ssid-i.patch new file mode 100644 index 0000000000..32b0c42dba --- /dev/null +++ b/queue-6.14/wifi-ath12k-improve-bss-discovery-with-hidden-ssid-i.patch @@ -0,0 +1,59 @@ +From 8a36034f765975fabc00b1de0d5eb4a01c522dcb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 7 Feb 2025 11:30:05 +0530 +Subject: wifi: ath12k: Improve BSS discovery with hidden SSID in 6 GHz band + +From: Ramasamy Kaliappan + +[ Upstream commit 27d38bdfd416f4db70e09c3bef3b030c86fd235a ] + +Currently, sometimes, the station is unable to identify the configured +AP SSID in its scan results when the AP is not broadcasting its name +publicly and has a hidden SSID. + +Currently, channel dwell time for an ath12k station is 30 ms. Sometimes, +station can send broadcast probe request to AP close to the end of dwell +time. In some of these cases, before AP sends a response to the received +probe request, the dwell time on the station side would come to an end. +So, the station will move to scan next channel and will not be able to +acknowledge the unicast probe response. + +Resolve this issue by increasing station's channel dwell time to 70 ms, +so that the it remains on the same channel for a longer period. This +would increase the station's chance of receiving probe response from the +AP. The station will then send a response acknowledgment back to the AP, +thus leading to successful scan and BSS discovery. + +With an increased dwell time, scan would take longer than it takes now. +But, this fix is an improvement for hidden SSID scan issue. + +Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.4.1-00199-QCAHKSWPL_SILICONZ-1 + +Signed-off-by: Ramasamy Kaliappan +Signed-off-by: Roopni Devanathan +Reviewed-by: Vasanthakumar Thiagarajan +Link: https://patch.msgid.link/20250207060005.153835-1-quic_rdevanat@quicinc.com +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath12k/wmi.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c +index 7a87777e0a047..9cd7ceae5a4f8 100644 +--- a/drivers/net/wireless/ath/ath12k/wmi.c ++++ b/drivers/net/wireless/ath/ath12k/wmi.c +@@ -2373,8 +2373,8 @@ void ath12k_wmi_start_scan_init(struct ath12k *ar, + arg->dwell_time_active = 50; + arg->dwell_time_active_2g = 0; + arg->dwell_time_passive = 150; +- arg->dwell_time_active_6g = 40; +- arg->dwell_time_passive_6g = 30; ++ arg->dwell_time_active_6g = 70; ++ arg->dwell_time_passive_6g = 70; + arg->min_rest_time = 50; + arg->max_rest_time = 500; + arg->repeat_probe_time = 0; +-- +2.39.5 + diff --git a/queue-6.14/wifi-ath12k-report-proper-tx-completion-status-to-ma.patch b/queue-6.14/wifi-ath12k-report-proper-tx-completion-status-to-ma.patch new file mode 100644 index 0000000000..de69b50e56 --- /dev/null +++ b/queue-6.14/wifi-ath12k-report-proper-tx-completion-status-to-ma.patch @@ -0,0 +1,56 @@ +From 66186ba383d93d524caa4a2abac7a88ce9aee5b9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 22 Nov 2024 23:04:32 +0530 +Subject: wifi: ath12k: Report proper tx completion status to mac80211 + +From: Vinith Kumar R + +[ Upstream commit d2d9c9b8de725e1006d3aa3d18678a732f5d3584 ] + +Currently Tx completion for few exception packets are received from +firmware and the tx status updated to mac80211. The tx status values of +HAL_WBM_REL_HTT_TX_COMP_STATUS_DROP and HAL_WBM_REL_HTT_TX_COMP_STATUS_TTL +are considered as tx failure and reported as tx failure to mac80211. +But these failure status is due to internal firmware tx drop and these +packets were not tried to transmit in the air. +In case of mesh this invalid tx status report might trigger mpath broken +issue due to increase in mpath fail average. +So do not report these tx status as tx failure instead free the skb +by calling ieee80211_free_txskb(), and that will be accounted as dropped +frame. + +Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.3.1-00173-QCAHKSWPL_SILICONZ-1 + +Signed-off-by: Vinith Kumar R +Signed-off-by: Tamizh Chelvam Raja +Acked-by: Jeff Johnson +Link: https://patch.msgid.link/20241122173432.2064858-1-quic_tamizhr@quicinc.com +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath12k/dp_tx.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath12k/dp_tx.c b/drivers/net/wireless/ath/ath12k/dp_tx.c +index 1fffabaca527a..75608ae027afe 100644 +--- a/drivers/net/wireless/ath/ath12k/dp_tx.c ++++ b/drivers/net/wireless/ath/ath12k/dp_tx.c +@@ -560,13 +560,13 @@ ath12k_dp_tx_process_htt_tx_complete(struct ath12k_base *ab, + + switch (wbm_status) { + case HAL_WBM_REL_HTT_TX_COMP_STATUS_OK: +- case HAL_WBM_REL_HTT_TX_COMP_STATUS_DROP: +- case HAL_WBM_REL_HTT_TX_COMP_STATUS_TTL: + ts.acked = (wbm_status == HAL_WBM_REL_HTT_TX_COMP_STATUS_OK); + ts.ack_rssi = le32_get_bits(status_desc->info2, + HTT_TX_WBM_COMP_INFO2_ACK_RSSI); + ath12k_dp_tx_htt_tx_complete_buf(ab, msdu, tx_ring, &ts); + break; ++ case HAL_WBM_REL_HTT_TX_COMP_STATUS_DROP: ++ case HAL_WBM_REL_HTT_TX_COMP_STATUS_TTL: + case HAL_WBM_REL_HTT_TX_COMP_STATUS_REINJ: + case HAL_WBM_REL_HTT_TX_COMP_STATUS_INSPECT: + ath12k_dp_tx_free_txbuf(ab, msdu, mac_id, tx_ring); +-- +2.39.5 + diff --git a/queue-6.14/wifi-ath12k-report-station-mode-receive-rate-for-iee.patch b/queue-6.14/wifi-ath12k-report-station-mode-receive-rate-for-iee.patch new file mode 100644 index 0000000000..986429c1bc --- /dev/null +++ b/queue-6.14/wifi-ath12k-report-station-mode-receive-rate-for-iee.patch @@ -0,0 +1,123 @@ +From dd3ba246e6556b447753b6a462e0ab45c18adc15 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 15 Jan 2025 14:35:36 +0800 +Subject: wifi: ath12k: report station mode receive rate for IEEE 802.11be + +From: Lingbo Kong + +[ Upstream commit 5e73276c814fc1a5a1bce6be743e1a07baa6d4bc ] + +Currently, the receive rate of EHT of "iw dev xxx station dump" command +always show an invalid value. + +This is because ath12k does not pass information about the rx_status of EHT +to mac80211. So, mac80211 not calculate the receive rate. + +To address this issue, add logic for handling rx_status of EHT to the +ath12k_dp_rx_h_rate() function. + +After that, "iw dev xxx station dump" show the correct receive rate. +Such as: + +Station 00:03:7f:12:03:03 (on wlo1) + inactive time: 48 ms + rx bytes: 59226 + rx packets: 320 + tx bytes: 26556 + tx packets: 191 + tx retries: 99 + tx failed: 0 + beacon loss: 0 + beacon rx: 79 + rx drop misc: 68 + signal: -95 dBm + beacon signal avg: -20 dBm + tx bitrate: 688.2 MBit/s 40MHz EHT-MCS 13 EHT-NSS 2 EHT-GI 0 + tx duration: 0 us + rx bitrate: 619.5 MBit/s 40MHz EHT-MCS 8 EHT-NSS 3 EHT-GI 0 + +This patch affects the station mode of WCN7850 and QCN9274. + +Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0.c5-00481-QCAHMTSWPL_V1.0_V2.0_SILICONZ-3 +Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.1.1-00214-QCAHKSWPL_SILICONZ-1 + +Signed-off-by: Lingbo Kong +Closes: https://bugzilla.kernel.org/show_bug.cgi?id=219715 +Link: https://patch.msgid.link/20250115063537.35797-3-quic_lingbok@quicinc.com +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath12k/dp_rx.c | 22 ++++++++++++++++++++-- + drivers/net/wireless/ath/ath12k/rx_desc.h | 2 ++ + 2 files changed, 22 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath12k/dp_rx.c b/drivers/net/wireless/ath/ath12k/dp_rx.c +index ae6608b10bb57..ff6a709b5042c 100644 +--- a/drivers/net/wireless/ath/ath12k/dp_rx.c ++++ b/drivers/net/wireless/ath/ath12k/dp_rx.c +@@ -1,7 +1,7 @@ + // SPDX-License-Identifier: BSD-3-Clause-Clear + /* + * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved. +- * Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved. ++ * Copyright (c) 2021-2025 Qualcomm Innovation Center, Inc. All rights reserved. + */ + + #include +@@ -2392,6 +2392,23 @@ static void ath12k_dp_rx_h_rate(struct ath12k *ar, struct hal_rx_desc *rx_desc, + rx_status->he_gi = ath12k_he_gi_to_nl80211_he_gi(sgi); + rx_status->bw = ath12k_mac_bw_to_mac80211_bw(bw); + break; ++ case RX_MSDU_START_PKT_TYPE_11BE: ++ rx_status->rate_idx = rate_mcs; ++ ++ if (rate_mcs > ATH12K_EHT_MCS_MAX) { ++ ath12k_warn(ar->ab, ++ "Received with invalid mcs in EHT mode %d\n", ++ rate_mcs); ++ break; ++ } ++ ++ rx_status->encoding = RX_ENC_EHT; ++ rx_status->nss = nss; ++ rx_status->eht.gi = ath12k_mac_eht_gi_to_nl80211_eht_gi(sgi); ++ rx_status->bw = ath12k_mac_bw_to_mac80211_bw(bw); ++ break; ++ default: ++ break; + } + } + +@@ -2486,7 +2503,7 @@ static void ath12k_dp_rx_deliver_msdu(struct ath12k *ar, struct napi_struct *nap + spin_unlock_bh(&ab->base_lock); + + ath12k_dbg(ab, ATH12K_DBG_DATA, +- "rx skb %p len %u peer %pM %d %s sn %u %s%s%s%s%s%s%s%s%s rate_idx %u vht_nss %u freq %u band %u flag 0x%x fcs-err %i mic-err %i amsdu-more %i\n", ++ "rx skb %p len %u peer %pM %d %s sn %u %s%s%s%s%s%s%s%s%s%s rate_idx %u vht_nss %u freq %u band %u flag 0x%x fcs-err %i mic-err %i amsdu-more %i\n", + msdu, + msdu->len, + peer ? peer->addr : NULL, +@@ -2497,6 +2514,7 @@ static void ath12k_dp_rx_deliver_msdu(struct ath12k *ar, struct napi_struct *nap + (status->encoding == RX_ENC_HT) ? "ht" : "", + (status->encoding == RX_ENC_VHT) ? "vht" : "", + (status->encoding == RX_ENC_HE) ? "he" : "", ++ (status->encoding == RX_ENC_EHT) ? "eht" : "", + (status->bw == RATE_INFO_BW_40) ? "40" : "", + (status->bw == RATE_INFO_BW_80) ? "80" : "", + (status->bw == RATE_INFO_BW_160) ? "160" : "", +diff --git a/drivers/net/wireless/ath/ath12k/rx_desc.h b/drivers/net/wireless/ath/ath12k/rx_desc.h +index 10366bbe99999..fc1eceb2d99bb 100644 +--- a/drivers/net/wireless/ath/ath12k/rx_desc.h ++++ b/drivers/net/wireless/ath/ath12k/rx_desc.h +@@ -637,6 +637,8 @@ enum rx_msdu_start_pkt_type { + RX_MSDU_START_PKT_TYPE_11N, + RX_MSDU_START_PKT_TYPE_11AC, + RX_MSDU_START_PKT_TYPE_11AX, ++ RX_MSDU_START_PKT_TYPE_11BA, ++ RX_MSDU_START_PKT_TYPE_11BE, + }; + + enum rx_msdu_start_sgi { +-- +2.39.5 + diff --git a/queue-6.14/wifi-ath12k-report-station-mode-transmit-rate.patch b/queue-6.14/wifi-ath12k-report-station-mode-transmit-rate.patch new file mode 100644 index 0000000000..4f1c0c373c --- /dev/null +++ b/queue-6.14/wifi-ath12k-report-station-mode-transmit-rate.patch @@ -0,0 +1,475 @@ +From 3f401c76ca6891897ff4ad67df9d4cd1bd3119bc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 15 Jan 2025 14:35:35 +0800 +Subject: wifi: ath12k: report station mode transmit rate + +From: Lingbo Kong + +[ Upstream commit 8a9c06b40882ebea45563059ddc5d57acdec9dda ] + +Currently, the transmit rate of "iw dev xxx station dump" command +always show an invalid value. + +To address this issue, ath12k parse the info of transmit complete +report from firmware and indicate the transmit rate to mac80211. + +This patch affects the station mode of WCN7850 and QCN9274. + +After that, "iw dev xxx station dump" show the correct transmit rate. +Such as: + +Station 00:03:7f:12:03:03 (on wlo1) + inactive time: 872 ms + rx bytes: 219111 + rx packets: 1133 + tx bytes: 53767 + tx packets: 462 + tx retries: 51 + tx failed: 0 + beacon loss: 0 + beacon rx: 403 + rx drop misc: 74 + signal: -95 dBm + beacon signal avg: -18 dBm + tx bitrate: 1441.1 MBit/s 80MHz EHT-MCS 13 EHT-NSS 2 EHT-GI 0 + +Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0.c5-00481-QCAHMTSWPL_V1.0_V2.0_SILICONZ-3 +Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.1.1-00214-QCAHKSWPL_SILICONZ-1 + +Signed-off-by: Lingbo Kong +Closes: https://bugzilla.kernel.org/show_bug.cgi?id=219715 +Link: https://patch.msgid.link/20250115063537.35797-2-quic_lingbok@quicinc.com +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath12k/core.h | 2 + + drivers/net/wireless/ath/ath12k/dp_rx.h | 5 +- + drivers/net/wireless/ath/ath12k/dp_tx.c | 139 +++++++++++++++++++++- + drivers/net/wireless/ath/ath12k/hal_rx.h | 5 +- + drivers/net/wireless/ath/ath12k/hal_tx.h | 10 +- + drivers/net/wireless/ath/ath12k/mac.c | 79 ++++++++++++ + drivers/net/wireless/ath/ath12k/mac.h | 5 +- + drivers/net/wireless/ath/ath12k/rx_desc.h | 3 +- + 8 files changed, 238 insertions(+), 10 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h +index 2699c383fc4c9..96b2830e891bd 100644 +--- a/drivers/net/wireless/ath/ath12k/core.h ++++ b/drivers/net/wireless/ath/ath12k/core.h +@@ -87,6 +87,7 @@ enum wme_ac { + #define ATH12K_HT_MCS_MAX 7 + #define ATH12K_VHT_MCS_MAX 9 + #define ATH12K_HE_MCS_MAX 11 ++#define ATH12K_EHT_MCS_MAX 15 + + enum ath12k_crypt_mode { + /* Only use hardware crypto engine */ +@@ -501,6 +502,7 @@ struct ath12k_link_sta { + struct ath12k_rx_peer_stats *rx_stats; + struct ath12k_wbm_tx_stats *wbm_tx_stats; + u32 bw_prev; ++ u32 peer_nss; + + /* For now the assoc link will be considered primary */ + bool is_assoc_link; +diff --git a/drivers/net/wireless/ath/ath12k/dp_rx.h b/drivers/net/wireless/ath/ath12k/dp_rx.h +index 1ce82088c9540..c0aa965f47e77 100644 +--- a/drivers/net/wireless/ath/ath12k/dp_rx.h ++++ b/drivers/net/wireless/ath/ath12k/dp_rx.h +@@ -1,7 +1,7 @@ + /* SPDX-License-Identifier: BSD-3-Clause-Clear */ + /* + * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved. +- * Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved. ++ * Copyright (c) 2021-2025 Qualcomm Innovation Center, Inc. All rights reserved. + */ + #ifndef ATH12K_DP_RX_H + #define ATH12K_DP_RX_H +@@ -79,6 +79,9 @@ static inline u32 ath12k_he_gi_to_nl80211_he_gi(u8 sgi) + case RX_MSDU_START_SGI_3_2_US: + ret = NL80211_RATE_INFO_HE_GI_3_2; + break; ++ default: ++ ret = NL80211_RATE_INFO_HE_GI_0_8; ++ break; + } + + return ret; +diff --git a/drivers/net/wireless/ath/ath12k/dp_tx.c b/drivers/net/wireless/ath/ath12k/dp_tx.c +index a39bfb959797a..7dc3576287850 100644 +--- a/drivers/net/wireless/ath/ath12k/dp_tx.c ++++ b/drivers/net/wireless/ath/ath12k/dp_tx.c +@@ -8,6 +8,8 @@ + #include "dp_tx.h" + #include "debug.h" + #include "hw.h" ++#include "peer.h" ++#include "mac.h" + + static enum hal_tcl_encap_type + ath12k_dp_tx_get_encap_type(struct ath12k_link_vif *arvif, struct sk_buff *skb) +@@ -582,6 +584,124 @@ ath12k_dp_tx_process_htt_tx_complete(struct ath12k_base *ab, + } + } + ++static void ath12k_dp_tx_update_txcompl(struct ath12k *ar, struct hal_tx_status *ts) ++{ ++ struct ath12k_base *ab = ar->ab; ++ struct ath12k_peer *peer; ++ struct ieee80211_sta *sta; ++ struct ath12k_sta *ahsta; ++ struct ath12k_link_sta *arsta; ++ struct rate_info txrate = {0}; ++ u16 rate, ru_tones; ++ u8 rate_idx = 0; ++ int ret; ++ ++ spin_lock_bh(&ab->base_lock); ++ peer = ath12k_peer_find_by_id(ab, ts->peer_id); ++ if (!peer || !peer->sta) { ++ ath12k_dbg(ab, ATH12K_DBG_DP_TX, ++ "failed to find the peer by id %u\n", ts->peer_id); ++ spin_unlock_bh(&ab->base_lock); ++ return; ++ } ++ sta = peer->sta; ++ ahsta = ath12k_sta_to_ahsta(sta); ++ arsta = &ahsta->deflink; ++ ++ /* This is to prefer choose the real NSS value arsta->last_txrate.nss, ++ * if it is invalid, then choose the NSS value while assoc. ++ */ ++ if (arsta->last_txrate.nss) ++ txrate.nss = arsta->last_txrate.nss; ++ else ++ txrate.nss = arsta->peer_nss; ++ spin_unlock_bh(&ab->base_lock); ++ ++ switch (ts->pkt_type) { ++ case HAL_TX_RATE_STATS_PKT_TYPE_11A: ++ case HAL_TX_RATE_STATS_PKT_TYPE_11B: ++ ret = ath12k_mac_hw_ratecode_to_legacy_rate(ts->mcs, ++ ts->pkt_type, ++ &rate_idx, ++ &rate); ++ if (ret < 0) { ++ ath12k_warn(ab, "Invalid tx legacy rate %d\n", ret); ++ return; ++ } ++ ++ txrate.legacy = rate; ++ break; ++ case HAL_TX_RATE_STATS_PKT_TYPE_11N: ++ if (ts->mcs > ATH12K_HT_MCS_MAX) { ++ ath12k_warn(ab, "Invalid HT mcs index %d\n", ts->mcs); ++ return; ++ } ++ ++ if (txrate.nss != 0) ++ txrate.mcs = ts->mcs + 8 * (txrate.nss - 1); ++ ++ txrate.flags = RATE_INFO_FLAGS_MCS; ++ ++ if (ts->sgi) ++ txrate.flags |= RATE_INFO_FLAGS_SHORT_GI; ++ break; ++ case HAL_TX_RATE_STATS_PKT_TYPE_11AC: ++ if (ts->mcs > ATH12K_VHT_MCS_MAX) { ++ ath12k_warn(ab, "Invalid VHT mcs index %d\n", ts->mcs); ++ return; ++ } ++ ++ txrate.mcs = ts->mcs; ++ txrate.flags = RATE_INFO_FLAGS_VHT_MCS; ++ ++ if (ts->sgi) ++ txrate.flags |= RATE_INFO_FLAGS_SHORT_GI; ++ break; ++ case HAL_TX_RATE_STATS_PKT_TYPE_11AX: ++ if (ts->mcs > ATH12K_HE_MCS_MAX) { ++ ath12k_warn(ab, "Invalid HE mcs index %d\n", ts->mcs); ++ return; ++ } ++ ++ txrate.mcs = ts->mcs; ++ txrate.flags = RATE_INFO_FLAGS_HE_MCS; ++ txrate.he_gi = ath12k_he_gi_to_nl80211_he_gi(ts->sgi); ++ break; ++ case HAL_TX_RATE_STATS_PKT_TYPE_11BE: ++ if (ts->mcs > ATH12K_EHT_MCS_MAX) { ++ ath12k_warn(ab, "Invalid EHT mcs index %d\n", ts->mcs); ++ return; ++ } ++ ++ txrate.mcs = ts->mcs; ++ txrate.flags = RATE_INFO_FLAGS_EHT_MCS; ++ txrate.eht_gi = ath12k_mac_eht_gi_to_nl80211_eht_gi(ts->sgi); ++ break; ++ default: ++ ath12k_warn(ab, "Invalid tx pkt type: %d\n", ts->pkt_type); ++ return; ++ } ++ ++ txrate.bw = ath12k_mac_bw_to_mac80211_bw(ts->bw); ++ ++ if (ts->ofdma && ts->pkt_type == HAL_TX_RATE_STATS_PKT_TYPE_11AX) { ++ txrate.bw = RATE_INFO_BW_HE_RU; ++ ru_tones = ath12k_mac_he_convert_tones_to_ru_tones(ts->tones); ++ txrate.he_ru_alloc = ++ ath12k_he_ru_tones_to_nl80211_he_ru_alloc(ru_tones); ++ } ++ ++ if (ts->ofdma && ts->pkt_type == HAL_TX_RATE_STATS_PKT_TYPE_11BE) { ++ txrate.bw = RATE_INFO_BW_EHT_RU; ++ txrate.eht_ru_alloc = ++ ath12k_mac_eht_ru_tones_to_nl80211_eht_ru_alloc(ts->tones); ++ } ++ ++ spin_lock_bh(&ab->base_lock); ++ arsta->txrate = txrate; ++ spin_unlock_bh(&ab->base_lock); ++} ++ + static void ath12k_dp_tx_complete_msdu(struct ath12k *ar, + struct sk_buff *msdu, + struct hal_tx_status *ts) +@@ -660,6 +780,8 @@ static void ath12k_dp_tx_complete_msdu(struct ath12k *ar, + * Might end up reporting it out-of-band from HTT stats. + */ + ++ ath12k_dp_tx_update_txcompl(ar, ts); ++ + ieee80211_tx_status_skb(ath12k_ar_to_hw(ar), msdu); + + exit: +@@ -670,6 +792,8 @@ static void ath12k_dp_tx_status_parse(struct ath12k_base *ab, + struct hal_wbm_completion_ring_tx *desc, + struct hal_tx_status *ts) + { ++ u32 info0 = le32_to_cpu(desc->rate_stats.info0); ++ + ts->buf_rel_source = + le32_get_bits(desc->info0, HAL_WBM_COMPL_TX_INFO0_REL_SRC_MODULE); + if (ts->buf_rel_source != HAL_WBM_REL_SRC_MODULE_FW && +@@ -684,10 +808,17 @@ static void ath12k_dp_tx_status_parse(struct ath12k_base *ab, + + ts->ppdu_id = le32_get_bits(desc->info1, + HAL_WBM_COMPL_TX_INFO1_TQM_STATUS_NUMBER); +- if (le32_to_cpu(desc->rate_stats.info0) & HAL_TX_RATE_STATS_INFO0_VALID) +- ts->rate_stats = le32_to_cpu(desc->rate_stats.info0); +- else +- ts->rate_stats = 0; ++ ++ ts->peer_id = le32_get_bits(desc->info3, HAL_WBM_COMPL_TX_INFO3_PEER_ID); ++ ++ if (info0 & HAL_TX_RATE_STATS_INFO0_VALID) { ++ ts->pkt_type = u32_get_bits(info0, HAL_TX_RATE_STATS_INFO0_PKT_TYPE); ++ ts->mcs = u32_get_bits(info0, HAL_TX_RATE_STATS_INFO0_MCS); ++ ts->sgi = u32_get_bits(info0, HAL_TX_RATE_STATS_INFO0_SGI); ++ ts->bw = u32_get_bits(info0, HAL_TX_RATE_STATS_INFO0_BW); ++ ts->tones = u32_get_bits(info0, HAL_TX_RATE_STATS_INFO0_TONES_IN_RU); ++ ts->ofdma = u32_get_bits(info0, HAL_TX_RATE_STATS_INFO0_OFDMA_TX); ++ } + } + + void ath12k_dp_tx_completion_handler(struct ath12k_base *ab, int ring_id) +diff --git a/drivers/net/wireless/ath/ath12k/hal_rx.h b/drivers/net/wireless/ath/ath12k/hal_rx.h +index 55b2dd5b76f6b..ac3b3f17ec2c8 100644 +--- a/drivers/net/wireless/ath/ath12k/hal_rx.h ++++ b/drivers/net/wireless/ath/ath12k/hal_rx.h +@@ -1,7 +1,7 @@ + /* SPDX-License-Identifier: BSD-3-Clause-Clear */ + /* + * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved. +- * Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved. ++ * Copyright (c) 2021-2025 Qualcomm Innovation Center, Inc. All rights reserved. + */ + + #ifndef ATH12K_HAL_RX_H +@@ -666,6 +666,9 @@ enum nl80211_he_ru_alloc ath12k_he_ru_tones_to_nl80211_he_ru_alloc(u16 ru_tones) + case RU_996: + ret = NL80211_RATE_INFO_HE_RU_ALLOC_996; + break; ++ case RU_2X996: ++ ret = NL80211_RATE_INFO_HE_RU_ALLOC_2x996; ++ break; + case RU_26: + fallthrough; + default: +diff --git a/drivers/net/wireless/ath/ath12k/hal_tx.h b/drivers/net/wireless/ath/ath12k/hal_tx.h +index 3cf5973771d78..eb065a79f6c64 100644 +--- a/drivers/net/wireless/ath/ath12k/hal_tx.h ++++ b/drivers/net/wireless/ath/ath12k/hal_tx.h +@@ -1,7 +1,8 @@ + /* SPDX-License-Identifier: BSD-3-Clause-Clear */ + /* + * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved. +- * Copyright (c) 2021-2022, 2024 Qualcomm Innovation Center, Inc. All rights reserved. ++ * Copyright (c) 2021-2022, 2024-2025 Qualcomm Innovation Center, Inc. ++ * All rights reserved. + */ + + #ifndef ATH12K_HAL_TX_H +@@ -63,7 +64,12 @@ struct hal_tx_status { + u8 try_cnt; + u8 tid; + u16 peer_id; +- u32 rate_stats; ++ enum hal_tx_rate_stats_pkt_type pkt_type; ++ enum hal_tx_rate_stats_sgi sgi; ++ enum ath12k_supported_bw bw; ++ u8 mcs; ++ u16 tones; ++ u8 ofdma; + }; + + #define HAL_TX_PHY_DESC_INFO0_BF_TYPE GENMASK(17, 16) +diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c +index 95ad9fefbdfcd..5f6d9896ef613 100644 +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -337,6 +337,82 @@ static const char *ath12k_mac_phymode_str(enum wmi_phy_mode mode) + return ""; + } + ++u16 ath12k_mac_he_convert_tones_to_ru_tones(u16 tones) ++{ ++ switch (tones) { ++ case 26: ++ return RU_26; ++ case 52: ++ return RU_52; ++ case 106: ++ return RU_106; ++ case 242: ++ return RU_242; ++ case 484: ++ return RU_484; ++ case 996: ++ return RU_996; ++ case (996 * 2): ++ return RU_2X996; ++ default: ++ return RU_26; ++ } ++} ++ ++enum nl80211_eht_gi ath12k_mac_eht_gi_to_nl80211_eht_gi(u8 sgi) ++{ ++ switch (sgi) { ++ case RX_MSDU_START_SGI_0_8_US: ++ return NL80211_RATE_INFO_EHT_GI_0_8; ++ case RX_MSDU_START_SGI_1_6_US: ++ return NL80211_RATE_INFO_EHT_GI_1_6; ++ case RX_MSDU_START_SGI_3_2_US: ++ return NL80211_RATE_INFO_EHT_GI_3_2; ++ default: ++ return NL80211_RATE_INFO_EHT_GI_0_8; ++ } ++} ++ ++enum nl80211_eht_ru_alloc ath12k_mac_eht_ru_tones_to_nl80211_eht_ru_alloc(u16 ru_tones) ++{ ++ switch (ru_tones) { ++ case 26: ++ return NL80211_RATE_INFO_EHT_RU_ALLOC_26; ++ case 52: ++ return NL80211_RATE_INFO_EHT_RU_ALLOC_52; ++ case (52 + 26): ++ return NL80211_RATE_INFO_EHT_RU_ALLOC_52P26; ++ case 106: ++ return NL80211_RATE_INFO_EHT_RU_ALLOC_106; ++ case (106 + 26): ++ return NL80211_RATE_INFO_EHT_RU_ALLOC_106P26; ++ case 242: ++ return NL80211_RATE_INFO_EHT_RU_ALLOC_242; ++ case 484: ++ return NL80211_RATE_INFO_EHT_RU_ALLOC_484; ++ case (484 + 242): ++ return NL80211_RATE_INFO_EHT_RU_ALLOC_484P242; ++ case 996: ++ return NL80211_RATE_INFO_EHT_RU_ALLOC_996; ++ case (996 + 484): ++ return NL80211_RATE_INFO_EHT_RU_ALLOC_996P484; ++ case (996 + 484 + 242): ++ return NL80211_RATE_INFO_EHT_RU_ALLOC_996P484P242; ++ case (2 * 996): ++ return NL80211_RATE_INFO_EHT_RU_ALLOC_2x996; ++ case (2 * 996 + 484): ++ return NL80211_RATE_INFO_EHT_RU_ALLOC_2x996P484; ++ case (3 * 996): ++ return NL80211_RATE_INFO_EHT_RU_ALLOC_3x996; ++ case (3 * 996 + 484): ++ return NL80211_RATE_INFO_EHT_RU_ALLOC_3x996P484; ++ case (4 * 996): ++ return NL80211_RATE_INFO_EHT_RU_ALLOC_4x996; ++ default: ++ return NL80211_RATE_INFO_EHT_RU_ALLOC_26; ++ } ++} ++ + enum rate_info_bw + ath12k_mac_bw_to_mac80211_bw(enum ath12k_supported_bw bw) + { +@@ -3116,6 +3192,7 @@ static void ath12k_peer_assoc_prepare(struct ath12k *ar, + ath12k_peer_assoc_h_smps(arsta, arg); + ath12k_peer_assoc_h_mlo(arsta, arg); + ++ arsta->peer_nss = arg->peer_nss; + /* TODO: amsdu_disable req? */ + } + +@@ -10042,6 +10119,8 @@ static void ath12k_mac_op_sta_statistics(struct ieee80211_hw *hw, + sinfo->txrate.he_gi = arsta->txrate.he_gi; + sinfo->txrate.he_dcm = arsta->txrate.he_dcm; + sinfo->txrate.he_ru_alloc = arsta->txrate.he_ru_alloc; ++ sinfo->txrate.eht_gi = arsta->txrate.eht_gi; ++ sinfo->txrate.eht_ru_alloc = arsta->txrate.eht_ru_alloc; + } + sinfo->txrate.flags = arsta->txrate.flags; + sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE); +diff --git a/drivers/net/wireless/ath/ath12k/mac.h b/drivers/net/wireless/ath/ath12k/mac.h +index 3594729b63974..1acaf3f68292c 100644 +--- a/drivers/net/wireless/ath/ath12k/mac.h ++++ b/drivers/net/wireless/ath/ath12k/mac.h +@@ -1,7 +1,7 @@ + /* SPDX-License-Identifier: BSD-3-Clause-Clear */ + /* + * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved. +- * Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved. ++ * Copyright (c) 2021-2025 Qualcomm Innovation Center, Inc. All rights reserved. + */ + + #ifndef ATH12K_MAC_H +@@ -108,5 +108,8 @@ int ath12k_mac_vdev_stop(struct ath12k_link_vif *arvif); + void ath12k_mac_get_any_chanctx_conf_iter(struct ieee80211_hw *hw, + struct ieee80211_chanctx_conf *conf, + void *data); ++u16 ath12k_mac_he_convert_tones_to_ru_tones(u16 tones); ++enum nl80211_eht_ru_alloc ath12k_mac_eht_ru_tones_to_nl80211_eht_ru_alloc(u16 ru_tones); ++enum nl80211_eht_gi ath12k_mac_eht_gi_to_nl80211_eht_gi(u8 sgi); + + #endif +diff --git a/drivers/net/wireless/ath/ath12k/rx_desc.h b/drivers/net/wireless/ath/ath12k/rx_desc.h +index fc1eceb2d99bb..7367935ee68b3 100644 +--- a/drivers/net/wireless/ath/ath12k/rx_desc.h ++++ b/drivers/net/wireless/ath/ath12k/rx_desc.h +@@ -1,7 +1,7 @@ + /* SPDX-License-Identifier: BSD-3-Clause-Clear */ + /* + * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved. +- * Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved. ++ * Copyright (c) 2021-2025 Qualcomm Innovation Center, Inc. All rights reserved. + */ + #ifndef ATH12K_RX_DESC_H + #define ATH12K_RX_DESC_H +@@ -1548,5 +1548,6 @@ struct hal_rx_desc { + #define RU_242 9 + #define RU_484 18 + #define RU_996 37 ++#define RU_2X996 74 + + #endif /* ATH12K_RX_DESC_H */ +-- +2.39.5 + diff --git a/queue-6.14/wifi-ath12k-update-the-peer-id-in-ppdu-end-user-stat.patch b/queue-6.14/wifi-ath12k-update-the-peer-id-in-ppdu-end-user-stat.patch new file mode 100644 index 0000000000..44c12ee9e8 --- /dev/null +++ b/queue-6.14/wifi-ath12k-update-the-peer-id-in-ppdu-end-user-stat.patch @@ -0,0 +1,47 @@ +From 6f8d7ec1e8e6e2b55cc5cc3b40841e380dbd401f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Feb 2025 07:08:50 +0530 +Subject: wifi: ath12k: Update the peer id in PPDU end user stats TLV + +From: Karthikeyan Periyasamy + +[ Upstream commit 0cded0e413468183a3b2dd445ab3bdc4d4375967 ] + +Currently, peer id get reported in the PPDU end user TLV tag. But the +monitor status handler is inherited from ath11k, but it was not updated +to incorporate the changes made to ath12k 802.11be hardware architecture. +Therefore, update the peer id from the PPDU end user TLV data to get latest +peer id update, it helps to populate accurate peer information on the +statistics data. + +Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.3.1-00173-QCAHKSWPL_SILICONZ-1 +Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0.c5-00481-QCAHMTSWPL_V1.0_V2.0_SILICONZ-3 + +Co-developed-by: P Praneesh +Signed-off-by: P Praneesh +Reviewed-by: Vasanthakumar Thiagarajan +Signed-off-by: Karthikeyan Periyasamy +Link: https://patch.msgid.link/20250206013854.174765-6-quic_periyasa@quicinc.com +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath12k/dp_mon.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/net/wireless/ath/ath12k/dp_mon.c b/drivers/net/wireless/ath/ath12k/dp_mon.c +index f23fee7055abc..8737dc8fea354 100644 +--- a/drivers/net/wireless/ath/ath12k/dp_mon.c ++++ b/drivers/net/wireless/ath/ath12k/dp_mon.c +@@ -638,6 +638,9 @@ ath12k_dp_mon_rx_parse_status_tlv(struct ath12k_base *ab, + ppdu_info->num_mpdu_fcs_err = + u32_get_bits(info[0], + HAL_RX_PPDU_END_USER_STATS_INFO0_MPDU_CNT_FCS_ERR); ++ ppdu_info->peer_id = ++ u32_get_bits(info[0], HAL_RX_PPDU_END_USER_STATS_INFO0_PEER_ID); ++ + switch (ppdu_info->preamble_type) { + case HAL_RX_PREAMBLE_11N: + ppdu_info->ht_flags = 1; +-- +2.39.5 + diff --git a/queue-6.14/wifi-ath12k-use-arvif-instead-of-link_conf-in-ath12k.patch b/queue-6.14/wifi-ath12k-use-arvif-instead-of-link_conf-in-ath12k.patch new file mode 100644 index 0000000000..a5b3c0fee3 --- /dev/null +++ b/queue-6.14/wifi-ath12k-use-arvif-instead-of-link_conf-in-ath12k.patch @@ -0,0 +1,78 @@ +From 4052e2258bb75371a736c03b044eade3673006e1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 4 Feb 2025 22:35:11 +0530 +Subject: wifi: ath12k: use arvif instead of link_conf in ath12k_mac_set_key() + +From: Aditya Kumar Singh + +[ Upstream commit 00e4dc11695d48322780812b503314682659e98b ] + +Currently, in ath12k_mac_set_key(), if sta is not present, the address is +retrieved from link_conf's bssid or addr member, depending on the interface +type. + +When operating as an ML station and during shutdown, link_conf will not be +available. This can result in the following error: + +ath12k_pci 0004:01:00.0: unable to access bss link conf in set key for vif AA:BB:CC:DD:EE:FF link 1 + +The primary purpose of accessing link_conf is to obtain the address for +finding the peer. However, since arvif is always valid in this call, it can +be used instead. + +Add change to use arvif instead of link_conf. + +A subsequent change will expose this issue but since tear down will give +error, this is included first. + +Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.3.1-00173-QCAHKSWPL_SILICONZ-1 +Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.3.1-00130-QCAHKSWPL_SILICONZ-1.97421.5 # Nicolas Escande + +Reviewed-by: Vasanthakumar Thiagarajan +Signed-off-by: Aditya Kumar Singh +Tested-by: Nicolas Escande +Link: https://patch.msgid.link/20250204-unlink_link_arvif_from_chanctx-v2-5-764fb5973c1a@oss.qualcomm.com +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath12k/mac.c | 14 +------------- + 1 file changed, 1 insertion(+), 13 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c +index 9123ffab55b52..95ad9fefbdfcd 100644 +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -4534,9 +4534,6 @@ static int ath12k_mac_set_key(struct ath12k *ar, enum set_key_cmd cmd, + struct ath12k_link_sta *arsta, + struct ieee80211_key_conf *key) + { +- struct ath12k_vif *ahvif = arvif->ahvif; +- struct ieee80211_vif *vif = ath12k_ahvif_to_vif(ahvif); +- struct ieee80211_bss_conf *link_conf; + struct ieee80211_sta *sta = NULL; + struct ath12k_base *ab = ar->ab; + struct ath12k_peer *peer; +@@ -4553,19 +4550,10 @@ static int ath12k_mac_set_key(struct ath12k *ar, enum set_key_cmd cmd, + if (test_bit(ATH12K_FLAG_HW_CRYPTO_DISABLED, &ab->dev_flags)) + return 1; + +- link_conf = ath12k_mac_get_link_bss_conf(arvif); +- if (!link_conf) { +- ath12k_warn(ab, "unable to access bss link conf in set key for vif %pM link %u\n", +- vif->addr, arvif->link_id); +- return -ENOLINK; +- } +- + if (sta) + peer_addr = arsta->addr; +- else if (ahvif->vdev_type == WMI_VDEV_TYPE_STA) +- peer_addr = link_conf->bssid; + else +- peer_addr = link_conf->addr; ++ peer_addr = arvif->bssid; + + key->hw_key_idx = key->keyidx; + +-- +2.39.5 + diff --git a/queue-6.14/wifi-ath9k-return-by-of_get_mac_address.patch b/queue-6.14/wifi-ath9k-return-by-of_get_mac_address.patch new file mode 100644 index 0000000000..32e4885cba --- /dev/null +++ b/queue-6.14/wifi-ath9k-return-by-of_get_mac_address.patch @@ -0,0 +1,46 @@ +From c4a233db1593e40856ca3076724341a0857a6d9b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 5 Nov 2024 14:23:26 -0800 +Subject: wifi: ath9k: return by of_get_mac_address +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Rosen Penev + +[ Upstream commit dfffb317519f88534bb82797f055f0a2fd867e7b ] + +When using nvmem, ath9k could potentially be loaded before nvmem, which +loads after mtd. This is an issue if DT contains an nvmem mac address. + +If nvmem is not ready in time for ath9k, -EPROBE_DEFER is returned. Pass +it to _probe so that ath9k can properly grab a potentially present MAC +address. + +Signed-off-by: Rosen Penev +Acked-by: Toke Høiland-Jørgensen +Link: https://patch.msgid.link/20241105222326.194417-1-rosenp@gmail.com +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath9k/init.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c +index f9e77c4624d99..01e0dffbf57ed 100644 +--- a/drivers/net/wireless/ath/ath9k/init.c ++++ b/drivers/net/wireless/ath/ath9k/init.c +@@ -647,7 +647,9 @@ static int ath9k_of_init(struct ath_softc *sc) + ah->ah_flags |= AH_NO_EEP_SWAP; + } + +- of_get_mac_address(np, common->macaddr); ++ ret = of_get_mac_address(np, common->macaddr); ++ if (ret == -EPROBE_DEFER) ++ return ret; + + return 0; + } +-- +2.39.5 + diff --git a/queue-6.14/wifi-cfg80211-allow-ir-in-20-mhz-configurations.patch b/queue-6.14/wifi-cfg80211-allow-ir-in-20-mhz-configurations.patch new file mode 100644 index 0000000000..82dbd3bded --- /dev/null +++ b/queue-6.14/wifi-cfg80211-allow-ir-in-20-mhz-configurations.patch @@ -0,0 +1,199 @@ +From f55a70556ff3dd4b6d98c3d9dba9fc3fd28bdc2b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 8 Mar 2025 23:03:30 +0200 +Subject: wifi: cfg80211: allow IR in 20 MHz configurations + +From: Anjaneyulu + +[ Upstream commit cf4bd1608882792d4742e27a819493312904a680 ] + +Some regulatory bodies doesn't allow IR (initiate radioation) on a +specific subband, but allows it for channels with a bandwidth of 20 MHz. +Add a channel flag that indicates that, and consider it in +cfg80211_reg_check_beaconing. + +While on it, fix the kernel doc of enum nl80211_reg_rule_flags and +change it to use BIT(). + +Signed-off-by: Anjaneyulu +Co-developed-by: Somashekhar Puttagangaiah +Signed-off-by: Somashekhar Puttagangaiah +Signed-off-by: Miri Korenblit +Link: https://patch.msgid.link/20250308225541.d3ab352a73ff.I8a8f79e1c9eb74936929463960ee2a324712fe51@changeid +[fix typo] +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + include/net/cfg80211.h | 3 +++ + include/uapi/linux/nl80211.h | 52 ++++++++++++++++++++---------------- + net/wireless/chan.c | 8 +++++- + net/wireless/nl80211.c | 4 +++ + net/wireless/reg.c | 4 ++- + 5 files changed, 46 insertions(+), 25 deletions(-) + +diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h +index c168b0e89b79d..b000f6a59a030 100644 +--- a/include/net/cfg80211.h ++++ b/include/net/cfg80211.h +@@ -127,6 +127,8 @@ struct wiphy; + * even if it is otherwise disabled. + * @IEEE80211_CHAN_ALLOW_6GHZ_VLP_AP: Allow using this channel for AP operation + * with very low power (VLP), even if otherwise set to NO_IR. ++ * @IEEE80211_CHAN_ALLOW_20MHZ_ACTIVITY: Allow activity on a 20 MHz channel, ++ * even if otherwise set to NO_IR. + */ + enum ieee80211_channel_flags { + IEEE80211_CHAN_DISABLED = BIT(0), +@@ -155,6 +157,7 @@ enum ieee80211_channel_flags { + IEEE80211_CHAN_NO_6GHZ_AFC_CLIENT = BIT(23), + IEEE80211_CHAN_CAN_MONITOR = BIT(24), + IEEE80211_CHAN_ALLOW_6GHZ_VLP_AP = BIT(25), ++ IEEE80211_CHAN_ALLOW_20MHZ_ACTIVITY = BIT(26), + }; + + #define IEEE80211_CHAN_NO_HT40 \ +diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h +index f6c1b181c886d..ea30fa455a098 100644 +--- a/include/uapi/linux/nl80211.h ++++ b/include/uapi/linux/nl80211.h +@@ -4327,6 +4327,8 @@ enum nl80211_wmm_rule { + * otherwise completely disabled. + * @NL80211_FREQUENCY_ATTR_ALLOW_6GHZ_VLP_AP: This channel can be used for a + * very low power (VLP) AP, despite being NO_IR. ++ * @NL80211_FREQUENCY_ATTR_ALLOW_20MHZ_ACTIVITY: This channel can be active in ++ * 20 MHz bandwidth, despite being NO_IR. + * @NL80211_FREQUENCY_ATTR_MAX: highest frequency attribute number + * currently defined + * @__NL80211_FREQUENCY_ATTR_AFTER_LAST: internal use +@@ -4371,6 +4373,7 @@ enum nl80211_frequency_attr { + NL80211_FREQUENCY_ATTR_NO_6GHZ_AFC_CLIENT, + NL80211_FREQUENCY_ATTR_CAN_MONITOR, + NL80211_FREQUENCY_ATTR_ALLOW_6GHZ_VLP_AP, ++ NL80211_FREQUENCY_ATTR_ALLOW_20MHZ_ACTIVITY, + + /* keep last */ + __NL80211_FREQUENCY_ATTR_AFTER_LAST, +@@ -4582,31 +4585,34 @@ enum nl80211_sched_scan_match_attr { + * @NL80211_RRF_NO_6GHZ_AFC_CLIENT: Client connection to AFC AP not allowed + * @NL80211_RRF_ALLOW_6GHZ_VLP_AP: Very low power (VLP) AP can be permitted + * despite NO_IR configuration. ++ * @NL80211_RRF_ALLOW_20MHZ_ACTIVITY: Allow activity in 20 MHz bandwidth, ++ * despite NO_IR configuration. + */ + enum nl80211_reg_rule_flags { +- NL80211_RRF_NO_OFDM = 1<<0, +- NL80211_RRF_NO_CCK = 1<<1, +- NL80211_RRF_NO_INDOOR = 1<<2, +- NL80211_RRF_NO_OUTDOOR = 1<<3, +- NL80211_RRF_DFS = 1<<4, +- NL80211_RRF_PTP_ONLY = 1<<5, +- NL80211_RRF_PTMP_ONLY = 1<<6, +- NL80211_RRF_NO_IR = 1<<7, +- __NL80211_RRF_NO_IBSS = 1<<8, +- NL80211_RRF_AUTO_BW = 1<<11, +- NL80211_RRF_IR_CONCURRENT = 1<<12, +- NL80211_RRF_NO_HT40MINUS = 1<<13, +- NL80211_RRF_NO_HT40PLUS = 1<<14, +- NL80211_RRF_NO_80MHZ = 1<<15, +- NL80211_RRF_NO_160MHZ = 1<<16, +- NL80211_RRF_NO_HE = 1<<17, +- NL80211_RRF_NO_320MHZ = 1<<18, +- NL80211_RRF_NO_EHT = 1<<19, +- NL80211_RRF_PSD = 1<<20, +- NL80211_RRF_DFS_CONCURRENT = 1<<21, +- NL80211_RRF_NO_6GHZ_VLP_CLIENT = 1<<22, +- NL80211_RRF_NO_6GHZ_AFC_CLIENT = 1<<23, +- NL80211_RRF_ALLOW_6GHZ_VLP_AP = 1<<24, ++ NL80211_RRF_NO_OFDM = 1 << 0, ++ NL80211_RRF_NO_CCK = 1 << 1, ++ NL80211_RRF_NO_INDOOR = 1 << 2, ++ NL80211_RRF_NO_OUTDOOR = 1 << 3, ++ NL80211_RRF_DFS = 1 << 4, ++ NL80211_RRF_PTP_ONLY = 1 << 5, ++ NL80211_RRF_PTMP_ONLY = 1 << 6, ++ NL80211_RRF_NO_IR = 1 << 7, ++ __NL80211_RRF_NO_IBSS = 1 << 8, ++ NL80211_RRF_AUTO_BW = 1 << 11, ++ NL80211_RRF_IR_CONCURRENT = 1 << 12, ++ NL80211_RRF_NO_HT40MINUS = 1 << 13, ++ NL80211_RRF_NO_HT40PLUS = 1 << 14, ++ NL80211_RRF_NO_80MHZ = 1 << 15, ++ NL80211_RRF_NO_160MHZ = 1 << 16, ++ NL80211_RRF_NO_HE = 1 << 17, ++ NL80211_RRF_NO_320MHZ = 1 << 18, ++ NL80211_RRF_NO_EHT = 1 << 19, ++ NL80211_RRF_PSD = 1 << 20, ++ NL80211_RRF_DFS_CONCURRENT = 1 << 21, ++ NL80211_RRF_NO_6GHZ_VLP_CLIENT = 1 << 22, ++ NL80211_RRF_NO_6GHZ_AFC_CLIENT = 1 << 23, ++ NL80211_RRF_ALLOW_6GHZ_VLP_AP = 1 << 24, ++ NL80211_RRF_ALLOW_20MHZ_ACTIVITY = 1 << 25, + }; + + #define NL80211_RRF_PASSIVE_SCAN NL80211_RRF_NO_IR +diff --git a/net/wireless/chan.c b/net/wireless/chan.c +index 9f918b77b40e2..4cdb74a3f38c6 100644 +--- a/net/wireless/chan.c ++++ b/net/wireless/chan.c +@@ -6,7 +6,7 @@ + * + * Copyright 2009 Johannes Berg + * Copyright 2013-2014 Intel Mobile Communications GmbH +- * Copyright 2018-2024 Intel Corporation ++ * Copyright 2018-2025 Intel Corporation + */ + + #include +@@ -1497,6 +1497,12 @@ bool cfg80211_reg_check_beaconing(struct wiphy *wiphy, + if (cfg->reg_power == IEEE80211_REG_VLP_AP) + permitting_flags |= IEEE80211_CHAN_ALLOW_6GHZ_VLP_AP; + ++ if ((cfg->iftype == NL80211_IFTYPE_P2P_GO || ++ cfg->iftype == NL80211_IFTYPE_AP) && ++ (chandef->width == NL80211_CHAN_WIDTH_20_NOHT || ++ chandef->width == NL80211_CHAN_WIDTH_20)) ++ permitting_flags |= IEEE80211_CHAN_ALLOW_20MHZ_ACTIVITY; ++ + return _cfg80211_reg_can_beacon(wiphy, chandef, cfg->iftype, + check_no_ir ? IEEE80211_CHAN_NO_IR : 0, + permitting_flags); +diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c +index b457fe78672b7..370b668678da0 100644 +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -1234,6 +1234,10 @@ static int nl80211_msg_put_channel(struct sk_buff *msg, struct wiphy *wiphy, + if ((chan->flags & IEEE80211_CHAN_ALLOW_6GHZ_VLP_AP) && + nla_put_flag(msg, NL80211_FREQUENCY_ATTR_ALLOW_6GHZ_VLP_AP)) + goto nla_put_failure; ++ if ((chan->flags & IEEE80211_CHAN_ALLOW_20MHZ_ACTIVITY) && ++ nla_put_flag(msg, ++ NL80211_FREQUENCY_ATTR_ALLOW_20MHZ_ACTIVITY)) ++ goto nla_put_failure; + } + + if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_MAX_TX_POWER, +diff --git a/net/wireless/reg.c b/net/wireless/reg.c +index 212e9561aae77..c1752b31734fa 100644 +--- a/net/wireless/reg.c ++++ b/net/wireless/reg.c +@@ -5,7 +5,7 @@ + * Copyright 2008-2011 Luis R. Rodriguez + * Copyright 2013-2014 Intel Mobile Communications GmbH + * Copyright 2017 Intel Deutschland GmbH +- * Copyright (C) 2018 - 2024 Intel Corporation ++ * Copyright (C) 2018 - 2025 Intel Corporation + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above +@@ -1603,6 +1603,8 @@ static u32 map_regdom_flags(u32 rd_flags) + channel_flags |= IEEE80211_CHAN_PSD; + if (rd_flags & NL80211_RRF_ALLOW_6GHZ_VLP_AP) + channel_flags |= IEEE80211_CHAN_ALLOW_6GHZ_VLP_AP; ++ if (rd_flags & NL80211_RRF_ALLOW_20MHZ_ACTIVITY) ++ channel_flags |= IEEE80211_CHAN_ALLOW_20MHZ_ACTIVITY; + return channel_flags; + } + +-- +2.39.5 + diff --git a/queue-6.14/wifi-cfg80211-update-the-link-address-when-a-link-is.patch b/queue-6.14/wifi-cfg80211-update-the-link-address-when-a-link-is.patch new file mode 100644 index 0000000000..97fd05d919 --- /dev/null +++ b/queue-6.14/wifi-cfg80211-update-the-link-address-when-a-link-is.patch @@ -0,0 +1,52 @@ +From 2b0883f069eb335a775aa7f4f0763d0c84974aeb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 8 Mar 2025 23:03:37 +0200 +Subject: wifi: cfg80211: Update the link address when a link is added + +From: Ilan Peer + +[ Upstream commit e16caea70610ed4226034dfcdaa5c43b36ff9e0a ] + +When links are added, update the wireless device link addresses based +on the information provided by the driver. + +Signed-off-by: Ilan Peer +Signed-off-by: Miri Korenblit +Link: https://patch.msgid.link/20250308225541.d694a9125aba.I79b010ea9aab47893e4f22c266362fde30b7f9ac@changeid +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + include/net/cfg80211.h | 1 + + net/wireless/mlme.c | 4 ++++ + 2 files changed, 5 insertions(+) + +diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h +index 363d7dd2255aa..c168b0e89b79d 100644 +--- a/include/net/cfg80211.h ++++ b/include/net/cfg80211.h +@@ -9750,6 +9750,7 @@ struct cfg80211_mlo_reconf_done_data { + u16 added_links; + struct { + struct cfg80211_bss *bss; ++ u8 *addr; + } links[IEEE80211_MLD_MAX_NUM_LINKS]; + }; + +diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c +index e10f2b3b4b7f6..c1b71179601db 100644 +--- a/net/wireless/mlme.c ++++ b/net/wireless/mlme.c +@@ -1361,6 +1361,10 @@ void cfg80211_mlo_reconf_add_done(struct net_device *dev, + if (data->added_links & BIT(link_id)) { + wdev->links[link_id].client.current_bss = + bss_from_pub(bss); ++ ++ memcpy(wdev->links[link_id].addr, ++ data->links[link_id].addr, ++ ETH_ALEN); + } else { + cfg80211_unhold_bss(bss_from_pub(bss)); + cfg80211_put_bss(wiphy, bss); +-- +2.39.5 + diff --git a/queue-6.14/wifi-iwlwifi-add-support-for-killer-on-mtl.patch b/queue-6.14/wifi-iwlwifi-add-support-for-killer-on-mtl.patch new file mode 100644 index 0000000000..72109352ed --- /dev/null +++ b/queue-6.14/wifi-iwlwifi-add-support-for-killer-on-mtl.patch @@ -0,0 +1,36 @@ +From 5c6fd9d34ebdf09702b8aa2893e5b90e43a83f13 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 6 May 2025 21:42:59 +0200 +Subject: wifi: iwlwifi: add support for Killer on MTL + +From: Johannes Berg + +[ Upstream commit ebedf8b7f05b9c886d68d63025db8d1b12343157 ] + +For now, we need another entry for these devices, this +will be changed completely for 6.16. + +Closes: https://bugzilla.kernel.org/show_bug.cgi?id=219926 +Link: https://patch.msgid.link/20250506214258.2efbdc9e9a82.I31915ec252bd1c74bd53b89a0e214e42a74b6f2e@changeid +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/intel/iwlwifi/pcie/drv.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c +index d4c1bc20971fb..69cf46c79b4b3 100644 +--- a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c ++++ b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c +@@ -587,6 +587,8 @@ VISIBLE_IF_IWLWIFI_KUNIT const struct iwl_dev_info iwl_dev_info_table[] = { + IWL_DEV_INFO(0x7A70, 0x1692, iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_killer_1690i_name), + IWL_DEV_INFO(0x7AF0, 0x1691, iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_killer_1690s_name), + IWL_DEV_INFO(0x7AF0, 0x1692, iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_killer_1690i_name), ++ IWL_DEV_INFO(0x7F70, 0x1691, iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_killer_1690s_name), ++ IWL_DEV_INFO(0x7F70, 0x1692, iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_killer_1690i_name), + + IWL_DEV_INFO(0x271C, 0x0214, iwl9260_2ac_cfg, iwl9260_1_name), + IWL_DEV_INFO(0x7E40, 0x1691, iwl_cfg_ma, iwl_ax411_killer_1690s_name), +-- +2.39.5 + diff --git a/queue-6.14/wifi-iwlwifi-don-t-warn-during-reprobe.patch b/queue-6.14/wifi-iwlwifi-don-t-warn-during-reprobe.patch new file mode 100644 index 0000000000..31a59d1731 --- /dev/null +++ b/queue-6.14/wifi-iwlwifi-don-t-warn-during-reprobe.patch @@ -0,0 +1,43 @@ +From ae088e428fdeeba11bd7621b6207e8f8eb869dcb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Feb 2025 14:55:35 +0200 +Subject: wifi: iwlwifi: don't warn during reprobe + +From: Miri Korenblit + +[ Upstream commit 696cca64308dc641d0bbe4aa2c09dd9752aa288d ] + +During reprobe, the sw state is being destroyd, and so is the +connection. When the peer STA is being removed, the opmode sends a +command to flush the TXQs of the STA and uses iwl_trans_wait_txq_empty. + +This one warns if the FW is not alive, but it really shouldn't if +there is a FW error - and return silently instead, just like we do when +sending a hcmd. + +Signed-off-by: Miri Korenblit +Reviewed-by: Johannes Berg +Link: https://patch.msgid.link/20250205145347.76425b10e5a0.I3bf0de2eb090a8b94c4e36d93dd91df61fadb808@changeid +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/intel/iwlwifi/iwl-trans.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.c b/drivers/net/wireless/intel/iwlwifi/iwl-trans.c +index eb631080c4563..75571f8693ee3 100644 +--- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.c ++++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.c +@@ -690,6 +690,9 @@ IWL_EXPORT_SYMBOL(iwl_trans_txq_enable_cfg); + + int iwl_trans_wait_txq_empty(struct iwl_trans *trans, int queue) + { ++ if (unlikely(test_bit(STATUS_FW_ERROR, &trans->status))) ++ return -EIO; ++ + if (WARN_ONCE(trans->state != IWL_TRANS_FW_ALIVE, + "bad state = %d\n", trans->state)) + return -EIO; +-- +2.39.5 + diff --git a/queue-6.14/wifi-iwlwifi-don-t-warn-when-if-there-is-a-fw-error.patch b/queue-6.14/wifi-iwlwifi-don-t-warn-when-if-there-is-a-fw-error.patch new file mode 100644 index 0000000000..fd6c06b9c4 --- /dev/null +++ b/queue-6.14/wifi-iwlwifi-don-t-warn-when-if-there-is-a-fw-error.patch @@ -0,0 +1,47 @@ +From afa59c570ed3157a9dc1526d4d2b194db67ea0aa Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 8 Mar 2025 23:19:23 +0200 +Subject: wifi: iwlwifi: don't warn when if there is a FW error + +From: Miri Korenblit + +[ Upstream commit c7f50d0433a016d43681592836a3d484817bfb34 ] + +iwl_trans_reclaim is warning if it is called when the FW is not alive. +But if it is called when there is a pending restart, i.e. after a FW +error, there is no need to warn, instead - return silently. + +Signed-off-by: Miri Korenblit +Link: https://patch.msgid.link/20250308231427.ba3d90b22c25.I9332506af1997faefcf0bdb51d98d5e874051722@changeid +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/intel/iwlwifi/iwl-trans.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.c b/drivers/net/wireless/intel/iwlwifi/iwl-trans.c +index ced8261c725f8..eb631080c4563 100644 +--- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.c ++++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.c +@@ -2,7 +2,7 @@ + /* + * Copyright (C) 2015 Intel Mobile Communications GmbH + * Copyright (C) 2016-2017 Intel Deutschland GmbH +- * Copyright (C) 2019-2021, 2023-2024 Intel Corporation ++ * Copyright (C) 2019-2021, 2023-2025 Intel Corporation + */ + #include + #include +@@ -655,6 +655,9 @@ IWL_EXPORT_SYMBOL(iwl_trans_tx); + void iwl_trans_reclaim(struct iwl_trans *trans, int queue, int ssn, + struct sk_buff_head *skbs, bool is_flush) + { ++ if (unlikely(test_bit(STATUS_FW_ERROR, &trans->status))) ++ return; ++ + if (WARN_ONCE(trans->state != IWL_TRANS_FW_ALIVE, + "bad state = %d\n", trans->state)) + return; +-- +2.39.5 + diff --git a/queue-6.14/wifi-iwlwifi-fix-debug-actions-order.patch b/queue-6.14/wifi-iwlwifi-fix-debug-actions-order.patch new file mode 100644 index 0000000000..4152f4e7d0 --- /dev/null +++ b/queue-6.14/wifi-iwlwifi-fix-debug-actions-order.patch @@ -0,0 +1,74 @@ +From f2c411e63725d361221b876394c1d865768a5a78 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 8 Mar 2025 23:19:18 +0200 +Subject: wifi: iwlwifi: fix debug actions order + +From: Johannes Berg + +[ Upstream commit eb29b4ffafb20281624dcd2cbb768d6f30edf600 ] + +The order of actions taken for debug was implemented incorrectly. +Now we implemented the dump split and do the FW reset only in the +middle of the dump (rather than the FW killing itself on error.) +As a result, some of the actions taken when applying the config +will now crash the device, so we need to fix the order. + +Signed-off-by: Johannes Berg +Signed-off-by: Miri Korenblit +Link: https://patch.msgid.link/20250308231427.6de7fa8e63ed.I40632c48e2a67a8aca05def572a934b88ce7934b@changeid +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c b/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c +index 08d990ba8a794..ce787326aa69d 100644 +--- a/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c ++++ b/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c +@@ -1,6 +1,6 @@ + // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause + /* +- * Copyright (C) 2018-2024 Intel Corporation ++ * Copyright (C) 2018-2025 Intel Corporation + */ + #include + #include "iwl-drv.h" +@@ -1372,15 +1372,15 @@ void _iwl_dbg_tlv_time_point(struct iwl_fw_runtime *fwrt, + switch (tp_id) { + case IWL_FW_INI_TIME_POINT_EARLY: + iwl_dbg_tlv_init_cfg(fwrt); +- iwl_dbg_tlv_apply_config(fwrt, conf_list); + iwl_dbg_tlv_update_drams(fwrt); + iwl_dbg_tlv_tp_trigger(fwrt, sync, trig_list, tp_data, NULL); ++ iwl_dbg_tlv_apply_config(fwrt, conf_list); + break; + case IWL_FW_INI_TIME_POINT_AFTER_ALIVE: + iwl_dbg_tlv_apply_buffers(fwrt); + iwl_dbg_tlv_send_hcmds(fwrt, hcmd_list); +- iwl_dbg_tlv_apply_config(fwrt, conf_list); + iwl_dbg_tlv_tp_trigger(fwrt, sync, trig_list, tp_data, NULL); ++ iwl_dbg_tlv_apply_config(fwrt, conf_list); + break; + case IWL_FW_INI_TIME_POINT_PERIODIC: + iwl_dbg_tlv_set_periodic_trigs(fwrt); +@@ -1390,14 +1390,14 @@ void _iwl_dbg_tlv_time_point(struct iwl_fw_runtime *fwrt, + case IWL_FW_INI_TIME_POINT_MISSED_BEACONS: + case IWL_FW_INI_TIME_POINT_FW_DHC_NOTIFICATION: + iwl_dbg_tlv_send_hcmds(fwrt, hcmd_list); +- iwl_dbg_tlv_apply_config(fwrt, conf_list); + iwl_dbg_tlv_tp_trigger(fwrt, sync, trig_list, tp_data, + iwl_dbg_tlv_check_fw_pkt); ++ iwl_dbg_tlv_apply_config(fwrt, conf_list); + break; + default: + iwl_dbg_tlv_send_hcmds(fwrt, hcmd_list); +- iwl_dbg_tlv_apply_config(fwrt, conf_list); + iwl_dbg_tlv_tp_trigger(fwrt, sync, trig_list, tp_data, NULL); ++ iwl_dbg_tlv_apply_config(fwrt, conf_list); + break; + } + } +-- +2.39.5 + diff --git a/queue-6.14/wifi-iwlwifi-fix-the-eckv-uefi-variable-name.patch b/queue-6.14/wifi-iwlwifi-fix-the-eckv-uefi-variable-name.patch new file mode 100644 index 0000000000..461817cbe2 --- /dev/null +++ b/queue-6.14/wifi-iwlwifi-fix-the-eckv-uefi-variable-name.patch @@ -0,0 +1,71 @@ +From 12a6938497f0e178131889eaba16c7ddf51cc95a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 8 Mar 2025 23:19:13 +0200 +Subject: wifi: iwlwifi: fix the ECKV UEFI variable name + +From: Emmanuel Grumbach + +[ Upstream commit 3ea2970b0578011ab8402ad0cff39712255f63df ] + +This UEFI variable name was badly named. Fix its name and also use the +right GUID to find it: we need to use the BT_WIFI (a.k.a. Common) GUID. + +Signed-off-by: Emmanuel Grumbach +Signed-off-by: Miri Korenblit +Link: https://patch.msgid.link/20250308231426.78c998d0fa71.I2bc9d72c1dc2c4d7028f0265634a940c2fadbbb5@changeid +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/intel/iwlwifi/fw/uefi.c | 8 +++++--- + drivers/net/wireless/intel/iwlwifi/fw/uefi.h | 4 ++-- + 2 files changed, 7 insertions(+), 5 deletions(-) + +diff --git a/drivers/net/wireless/intel/iwlwifi/fw/uefi.c b/drivers/net/wireless/intel/iwlwifi/fw/uefi.c +index 434eed4130b90..91bcff499311d 100644 +--- a/drivers/net/wireless/intel/iwlwifi/fw/uefi.c ++++ b/drivers/net/wireless/intel/iwlwifi/fw/uefi.c +@@ -1,6 +1,6 @@ + // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause + /* +- * Copyright(c) 2021-2024 Intel Corporation ++ * Copyright(c) 2021-2025 Intel Corporation + */ + + #include "iwl-drv.h" +@@ -678,8 +678,10 @@ int iwl_uefi_get_eckv(struct iwl_fw_runtime *fwrt, u32 *extl_clk) + struct uefi_cnv_var_eckv *data; + int ret = 0; + +- data = iwl_uefi_get_verified_variable(fwrt->trans, IWL_UEFI_ECKV_NAME, +- "ECKV", sizeof(*data), NULL); ++ data = iwl_uefi_get_verified_variable_guid(fwrt->trans, ++ &IWL_EFI_WIFI_BT_GUID, ++ IWL_UEFI_ECKV_NAME, ++ "ECKV", sizeof(*data), NULL); + if (IS_ERR(data)) + return -EINVAL; + +diff --git a/drivers/net/wireless/intel/iwlwifi/fw/uefi.h b/drivers/net/wireless/intel/iwlwifi/fw/uefi.h +index 0c8943a8bd011..eb3c05417da37 100644 +--- a/drivers/net/wireless/intel/iwlwifi/fw/uefi.h ++++ b/drivers/net/wireless/intel/iwlwifi/fw/uefi.h +@@ -1,6 +1,6 @@ + /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ + /* +- * Copyright(c) 2021-2024 Intel Corporation ++ * Copyright(c) 2021-2025 Intel Corporation + */ + #ifndef __iwl_fw_uefi__ + #define __iwl_fw_uefi__ +@@ -19,7 +19,7 @@ + #define IWL_UEFI_WTAS_NAME L"UefiCnvWlanWTAS" + #define IWL_UEFI_SPLC_NAME L"UefiCnvWlanSPLC" + #define IWL_UEFI_WRDD_NAME L"UefiCnvWlanWRDD" +-#define IWL_UEFI_ECKV_NAME L"UefiCnvWlanECKV" ++#define IWL_UEFI_ECKV_NAME L"UefiCnvCommonECKV" + #define IWL_UEFI_DSM_NAME L"UefiCnvWlanGeneralCfg" + #define IWL_UEFI_WBEM_NAME L"UefiCnvWlanWBEM" + #define IWL_UEFI_PUNCTURING_NAME L"UefiCnvWlanPuncturing" +-- +2.39.5 + diff --git a/queue-6.14/wifi-iwlwifi-mark-br-device-not-integrated.patch b/queue-6.14/wifi-iwlwifi-mark-br-device-not-integrated.patch new file mode 100644 index 0000000000..1ae65ad6fc --- /dev/null +++ b/queue-6.14/wifi-iwlwifi-mark-br-device-not-integrated.patch @@ -0,0 +1,40 @@ +From f53c569e8446158d54a2a4f68efc4d29e3decb9b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 8 Mar 2025 23:19:17 +0200 +Subject: wifi: iwlwifi: mark Br device not integrated + +From: Johannes Berg + +[ Upstream commit 5f0ab2f35a43773a0dfe1297129a8dbff906b932 ] + +This is a discrete device, don't mark it as integrated. +This also means we cannot set the LTR delay. + +Signed-off-by: Johannes Berg +Signed-off-by: Miri Korenblit +Link: https://patch.msgid.link/20250308231427.9bb69393fcc9.I197129383e5441c8139cbb0e810ae0b71198a37c@changeid +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/intel/iwlwifi/cfg/dr.c | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/dr.c b/drivers/net/wireless/intel/iwlwifi/cfg/dr.c +index ab7c0f8d54f42..d3542af0f625e 100644 +--- a/drivers/net/wireless/intel/iwlwifi/cfg/dr.c ++++ b/drivers/net/wireless/intel/iwlwifi/cfg/dr.c +@@ -148,11 +148,9 @@ const struct iwl_cfg_trans_params iwl_br_trans_cfg = { + .mq_rx_supported = true, + .rf_id = true, + .gen2 = true, +- .integrated = true, + .umac_prph_offset = 0x300000, + .xtal_latency = 12000, + .low_latency_xtal = true, +- .ltr_delay = IWL_CFG_TRANS_LTR_DELAY_2500US, + }; + + const char iwl_br_name[] = "Intel(R) TBD Br device"; +-- +2.39.5 + diff --git a/queue-6.14/wifi-iwlwifi-mvm-fix-setting-the-tk-when-associated.patch b/queue-6.14/wifi-iwlwifi-mvm-fix-setting-the-tk-when-associated.patch new file mode 100644 index 0000000000..e85556b2ee --- /dev/null +++ b/queue-6.14/wifi-iwlwifi-mvm-fix-setting-the-tk-when-associated.patch @@ -0,0 +1,41 @@ +From e5bae2b178c32aac5e48f71994adaa6c5379918e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 8 Mar 2025 23:19:25 +0200 +Subject: wifi: iwlwifi: mvm: fix setting the TK when associated + +From: Avraham Stern + +[ Upstream commit 3ad61970ac9e164be1b09b46c01aa942e8966132 ] + +When running secured ranging and the initiator is associated with +the responder, the TK was not set in the range request command. +Fix it. + +Signed-off-by: Avraham Stern +Signed-off-by: Miri Korenblit +Link: https://patch.msgid.link/20250308231427.603dc31579d9.Icd19d797e56483c08dd22c55b96fee481c4d2f3d@changeid +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c b/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c +index b26141c30c61c..0a96c26e741b8 100644 +--- a/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c ++++ b/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c +@@ -773,7 +773,11 @@ iwl_mvm_ftm_set_secured_ranging(struct iwl_mvm *mvm, struct ieee80211_vif *vif, + + target.bssid = bssid; + target.cipher = cipher; ++ target.tk = NULL; + ieee80211_iter_keys(mvm->hw, vif, iter, &target); ++ ++ if (!WARN_ON(!target.tk)) ++ memcpy(tk, target.tk, TK_11AZ_LEN); + } else { + memcpy(tk, entry->tk, sizeof(entry->tk)); + } +-- +2.39.5 + diff --git a/queue-6.14/wifi-iwlwifi-use-correct-imr-dump-variable.patch b/queue-6.14/wifi-iwlwifi-use-correct-imr-dump-variable.patch new file mode 100644 index 0000000000..00a0e18f81 --- /dev/null +++ b/queue-6.14/wifi-iwlwifi-use-correct-imr-dump-variable.patch @@ -0,0 +1,45 @@ +From 7a2d38a4c76d4c727339d2012b02024adf85515f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Feb 2025 14:55:46 +0200 +Subject: wifi: iwlwifi: use correct IMR dump variable + +From: Johannes Berg + +[ Upstream commit 21e4d29ac0def546d57bacebe4a51cbed1209b03 ] + +We shouldn't dump the reg_data here which dumps the last +entry again, it should use the imr_reg_data. + +Signed-off-by: Johannes Berg +Signed-off-by: Miri Korenblit +Link: https://patch.msgid.link/20250205145347.3313b18667d1.Iaa9ab66b1d397912a573525e060d39ea01b29d19@changeid +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/intel/iwlwifi/fw/dbg.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c +index 6594216f873c4..cd284767ff4ba 100644 +--- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c ++++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c +@@ -1,6 +1,6 @@ + // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause + /* +- * Copyright (C) 2005-2014, 2018-2024 Intel Corporation ++ * Copyright (C) 2005-2014, 2018-2025 Intel Corporation + * Copyright (C) 2013-2015 Intel Mobile Communications GmbH + * Copyright (C) 2015-2017 Intel Deutschland GmbH + */ +@@ -2691,7 +2691,7 @@ static u32 iwl_dump_ini_trigger(struct iwl_fw_runtime *fwrt, + } + /* collect DRAM_IMR region in the last */ + if (imr_reg_data.reg_tlv) +- size += iwl_dump_ini_mem(fwrt, list, ®_data, ++ size += iwl_dump_ini_mem(fwrt, list, &imr_reg_data, + &iwl_dump_ini_region_ops[IWL_FW_INI_REGION_DRAM_IMR]); + + if (size) { +-- +2.39.5 + diff --git a/queue-6.14/wifi-iwlwifi-w-a-fw-smps-mode-selection.patch b/queue-6.14/wifi-iwlwifi-w-a-fw-smps-mode-selection.patch new file mode 100644 index 0000000000..b05068e4b3 --- /dev/null +++ b/queue-6.14/wifi-iwlwifi-w-a-fw-smps-mode-selection.patch @@ -0,0 +1,99 @@ +From 3a276fdab3978a150a29db725d062bfac0b0324d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 8 Mar 2025 23:19:19 +0200 +Subject: wifi: iwlwifi: w/a FW SMPS mode selection + +From: Daniel Gabay + +[ Upstream commit b2e709805ce955f80803b7cab3421813c79e1df4 ] + +The FW is now responsible of determining the SMPS mode. +If the user disabled power save in a certain vif, we send the vif-level +power command to clear out the POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK bit +for that vif. +But erroneously, the FW checks DEVICE_POWER_FLAGS_POWER_SAVE_ENA_MSK in +the device-level command to determine the SMPS mode. + +To W/A this, send also the device-level command when the power save of a +vif changes, and disable power save if there is any vif that has power +save disabled. + +Signed-off-by: Daniel Gabay +Signed-off-by: Miri Korenblit +Link: https://patch.msgid.link/20250308231427.7bf205efa027.I2c793ff1fc2a6779a95faaee1ded348100fd97f1@changeid +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c | 15 +++++++++++++++ + .../net/wireless/intel/iwlwifi/mvm/mld-mac80211.c | 3 ++- + drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 3 +++ + 3 files changed, 20 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +index af6644b7e95fb..e17ad647da48c 100644 +--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c ++++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +@@ -4099,6 +4099,20 @@ iwl_mvm_sta_state_authorized_to_assoc(struct iwl_mvm *mvm, + return 0; + } + ++void iwl_mvm_smps_workaround(struct iwl_mvm *mvm, struct ieee80211_vif *vif, ++ bool update) ++{ ++ struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); ++ ++ if (!iwl_mvm_has_rlc_offload(mvm)) ++ return; ++ ++ mvmvif->ps_disabled = !vif->cfg.ps; ++ ++ if (update) ++ iwl_mvm_power_update_mac(mvm); ++} ++ + /* Common part for MLD and non-MLD modes */ + int iwl_mvm_mac_sta_state_common(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, +@@ -4191,6 +4205,7 @@ int iwl_mvm_mac_sta_state_common(struct ieee80211_hw *hw, + new_state == IEEE80211_STA_AUTHORIZED) { + ret = iwl_mvm_sta_state_assoc_to_authorized(mvm, vif, sta, + callbacks); ++ iwl_mvm_smps_workaround(mvm, vif, true); + } else if (old_state == IEEE80211_STA_AUTHORIZED && + new_state == IEEE80211_STA_ASSOC) { + ret = iwl_mvm_sta_state_authorized_to_assoc(mvm, vif, sta, +diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c +index 341a2a7a49ec9..78d7153a0cfca 100644 +--- a/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c ++++ b/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c +@@ -1,6 +1,6 @@ + // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause + /* +- * Copyright (C) 2022-2024 Intel Corporation ++ * Copyright (C) 2022-2025 Intel Corporation + */ + #include "mvm.h" + +@@ -887,6 +887,7 @@ static void iwl_mvm_mld_vif_cfg_changed_station(struct iwl_mvm *mvm, + } + + if (changes & BSS_CHANGED_PS) { ++ iwl_mvm_smps_workaround(mvm, vif, false); + ret = iwl_mvm_power_update_mac(mvm); + if (ret) + IWL_ERR(mvm, "failed to update power mode\n"); +diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +index ee769da72e68c..211f542ec8557 100644 +--- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h ++++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +@@ -3043,4 +3043,7 @@ iwl_mvm_send_ap_tx_power_constraint_cmd(struct iwl_mvm *mvm, + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *bss_conf, + bool is_ap); ++ ++void iwl_mvm_smps_workaround(struct iwl_mvm *mvm, struct ieee80211_vif *vif, ++ bool update); + #endif /* __IWL_MVM_H__ */ +-- +2.39.5 + diff --git a/queue-6.14/wifi-mac80211-add-counter-for-all-monitor-interfaces.patch b/queue-6.14/wifi-mac80211-add-counter-for-all-monitor-interfaces.patch new file mode 100644 index 0000000000..163a5e4539 --- /dev/null +++ b/queue-6.14/wifi-mac80211-add-counter-for-all-monitor-interfaces.patch @@ -0,0 +1,174 @@ +From 93769ff11c58cbe95a841d753c54c80992ef3803 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 20 Feb 2025 10:41:39 +0100 +Subject: wifi: mac80211: Add counter for all monitor interfaces + +From: Alexander Wetzel + +[ Upstream commit 129860044c611008be37f49d04cf41874e3659e6 ] + +Count open monitor interfaces regardless of the monitor interface type. +The new counter virt_monitors takes over counting interfaces depending +on the virtual monitor interface while monitors is used for all active +monitor interfaces. + +This fixes monitor packet mirroring when using MONITOR_FLAG_ACTIVE or +NO_VIRTUAL_MONITOR interfaces. + +Fixes: 286e69677065 ("wifi: mac80211: Drop cooked monitor support") +Reported-by: Karthikeyan Periyasamy +Closes: https://lore.kernel.org/r/cc715114-4e3b-619a-49dc-a4878075e1dc@quicinc.com +Signed-off-by: Alexander Wetzel +Tested-by: Karthikeyan Periyasamy +Link: https://patch.msgid.link/20250220094139.61459-1-Alexander@wetzel-home.de +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/mac80211/cfg.c | 5 ++--- + net/mac80211/ethtool.c | 2 +- + net/mac80211/ieee80211_i.h | 2 +- + net/mac80211/iface.c | 22 +++++++++++++--------- + net/mac80211/util.c | 3 ++- + 5 files changed, 19 insertions(+), 15 deletions(-) + +diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c +index 1ec246133d244..a7aeb37254bbf 100644 +--- a/net/mac80211/cfg.c ++++ b/net/mac80211/cfg.c +@@ -4370,9 +4370,8 @@ static int ieee80211_cfg_get_channel(struct wiphy *wiphy, + if (chanctx_conf) { + *chandef = link->conf->chanreq.oper; + ret = 0; +- } else if (!ieee80211_hw_check(&local->hw, NO_VIRTUAL_MONITOR) && +- local->open_count > 0 && +- local->open_count == local->monitors && ++ } else if (local->open_count > 0 && ++ local->open_count == local->virt_monitors && + sdata->vif.type == NL80211_IFTYPE_MONITOR) { + *chandef = local->monitor_chanreq.oper; + ret = 0; +diff --git a/net/mac80211/ethtool.c b/net/mac80211/ethtool.c +index 42f7ee142ce3f..0397755a3bd1c 100644 +--- a/net/mac80211/ethtool.c ++++ b/net/mac80211/ethtool.c +@@ -158,7 +158,7 @@ static void ieee80211_get_stats(struct net_device *dev, + if (chanctx_conf) + channel = chanctx_conf->def.chan; + else if (local->open_count > 0 && +- local->open_count == local->monitors && ++ local->open_count == local->virt_monitors && + sdata->vif.type == NL80211_IFTYPE_MONITOR) + channel = local->monitor_chanreq.oper.chan; + else +diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h +index afc6fda6b606b..3d7304ce23e23 100644 +--- a/net/mac80211/ieee80211_i.h ++++ b/net/mac80211/ieee80211_i.h +@@ -1378,7 +1378,7 @@ struct ieee80211_local { + spinlock_t queue_stop_reason_lock; + + int open_count; +- int monitors, tx_mntrs; ++ int monitors, virt_monitors, tx_mntrs; + /* number of interfaces with corresponding FIF_ flags */ + int fif_fcsfail, fif_plcpfail, fif_control, fif_other_bss, fif_pspoll, + fif_probe_req; +diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c +index 5616c0adbe093..768d774d7d1f9 100644 +--- a/net/mac80211/iface.c ++++ b/net/mac80211/iface.c +@@ -582,11 +582,13 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, bool going_do + /* no need to tell driver */ + break; + case NL80211_IFTYPE_MONITOR: ++ local->monitors--; ++ + if (!(sdata->u.mntr.flags & MONITOR_FLAG_ACTIVE) && + !ieee80211_hw_check(&local->hw, NO_VIRTUAL_MONITOR)) { + +- local->monitors--; +- if (local->monitors == 0) { ++ local->virt_monitors--; ++ if (local->virt_monitors == 0) { + local->hw.conf.flags &= ~IEEE80211_CONF_MONITOR; + hw_reconf_flags |= IEEE80211_CONF_CHANGE_MONITOR; + } +@@ -686,7 +688,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, bool going_do + case NL80211_IFTYPE_AP_VLAN: + break; + case NL80211_IFTYPE_MONITOR: +- if (local->monitors == 0) ++ if (local->virt_monitors == 0) + ieee80211_del_virtual_monitor(local); + + ieee80211_recalc_idle(local); +@@ -723,7 +725,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, bool going_do + ieee80211_configure_filter(local); + ieee80211_hw_config(local, hw_reconf_flags); + +- if (local->monitors == local->open_count) ++ if (local->virt_monitors == local->open_count) + ieee80211_add_virtual_monitor(local); + } + +@@ -982,7 +984,7 @@ static bool ieee80211_set_sdata_offload_flags(struct ieee80211_sub_if_data *sdat + local->hw.wiphy->frag_threshold != (u32)-1) + flags &= ~IEEE80211_OFFLOAD_ENCAP_ENABLED; + +- if (local->monitors) ++ if (local->virt_monitors) + flags &= ~IEEE80211_OFFLOAD_ENCAP_ENABLED; + } else { + flags &= ~IEEE80211_OFFLOAD_ENCAP_ENABLED; +@@ -992,7 +994,7 @@ static bool ieee80211_set_sdata_offload_flags(struct ieee80211_sub_if_data *sdat + ieee80211_iftype_supports_hdr_offload(sdata->vif.type)) { + flags |= IEEE80211_OFFLOAD_DECAP_ENABLED; + +- if (local->monitors && ++ if (local->virt_monitors && + !ieee80211_hw_check(&local->hw, SUPPORTS_CONC_MON_RX_DECAP)) + flags &= ~IEEE80211_OFFLOAD_DECAP_ENABLED; + } else { +@@ -1336,20 +1338,22 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up) + if (res) + goto err_stop; + } else { +- if (local->monitors == 0 && local->open_count == 0) { ++ if (local->virt_monitors == 0 && local->open_count == 0) { + res = ieee80211_add_virtual_monitor(local); + if (res) + goto err_stop; + } +- local->monitors++; ++ local->virt_monitors++; + + /* must be before the call to ieee80211_configure_filter */ +- if (local->monitors == 1) { ++ if (local->virt_monitors == 1) { + local->hw.conf.flags |= IEEE80211_CONF_MONITOR; + hw_reconf_flags |= IEEE80211_CONF_CHANGE_MONITOR; + } + } + ++ local->monitors++; ++ + ieee80211_adjust_monitor_flags(sdata, 1); + ieee80211_configure_filter(local); + ieee80211_recalc_offload(local); +diff --git a/net/mac80211/util.c b/net/mac80211/util.c +index fdda14c08e2b1..dec6e16b8c7d2 100644 +--- a/net/mac80211/util.c ++++ b/net/mac80211/util.c +@@ -2156,7 +2156,8 @@ int ieee80211_reconfig(struct ieee80211_local *local) + + wake_up: + +- if (local->monitors == local->open_count && local->monitors > 0) ++ if (local->virt_monitors > 0 && ++ local->virt_monitors == local->open_count) + ieee80211_add_virtual_monitor(local); + + /* +-- +2.39.5 + diff --git a/queue-6.14/wifi-mac80211-add-ht-and-vht-basic-set-verification.patch b/queue-6.14/wifi-mac80211-add-ht-and-vht-basic-set-verification.patch new file mode 100644 index 0000000000..22cb6b8112 --- /dev/null +++ b/queue-6.14/wifi-mac80211-add-ht-and-vht-basic-set-verification.patch @@ -0,0 +1,176 @@ +From 8a4cec99816cdc03febb90e205ffafaf6c2802b5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Feb 2025 11:39:18 +0200 +Subject: wifi: mac80211: add HT and VHT basic set verification + +From: Benjamin Berg + +[ Upstream commit 574faa0e936d12718e2cadad11ce1e184d9e5a32 ] + +So far we did not verify the HT and VHT basic MCS set. However, in +P802.11REVme/D7.0 (6.5.4.2.4) says that the MLME-JOIN.request shall +return an error if the VHT and HT basic set requirements are not met. + +Given broken APs, apply VHT basic MCS/NSS set checks only in +strict mode. + +Signed-off-by: Benjamin Berg +Reviewed-by: Johannes Berg +Signed-off-by: Miri Korenblit +Link: https://patch.msgid.link/20250205110958.e2d8d4095f6b.I66bcf6c2de3b9d3325e4ffd9f573f4cd26ce5685@changeid +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/mac80211/mlme.c | 129 ++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 129 insertions(+) + +diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c +index 8235400b7e5d8..ef65ae5137dcd 100644 +--- a/net/mac80211/mlme.c ++++ b/net/mac80211/mlme.c +@@ -345,6 +345,115 @@ ieee80211_determine_ap_chan(struct ieee80211_sub_if_data *sdata, + return IEEE80211_CONN_MODE_EHT; + } + ++static bool ++ieee80211_verify_sta_ht_mcs_support(struct ieee80211_sub_if_data *sdata, ++ struct ieee80211_supported_band *sband, ++ const struct ieee80211_ht_operation *ht_op) ++{ ++ struct ieee80211_sta_ht_cap sta_ht_cap; ++ int i; ++ ++ if (sband->band == NL80211_BAND_6GHZ) ++ return true; ++ ++ if (!ht_op) ++ return false; ++ ++ memcpy(&sta_ht_cap, &sband->ht_cap, sizeof(sta_ht_cap)); ++ ieee80211_apply_htcap_overrides(sdata, &sta_ht_cap); ++ ++ /* ++ * P802.11REVme/D7.0 - 6.5.4.2.4 ++ * ... ++ * If the MLME of an HT STA receives an MLME-JOIN.request primitive ++ * with the SelectedBSS parameter containing a Basic HT-MCS Set field ++ * in the HT Operation parameter that contains any unsupported MCSs, ++ * the MLME response in the resulting MLME-JOIN.confirm primitive shall ++ * contain a ResultCode parameter that is not set to the value SUCCESS. ++ * ... ++ */ ++ ++ /* Simply check that all basic rates are in the STA RX mask */ ++ for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) { ++ if ((ht_op->basic_set[i] & sta_ht_cap.mcs.rx_mask[i]) != ++ ht_op->basic_set[i]) ++ return false; ++ } ++ ++ return true; ++} ++ ++static bool ++ieee80211_verify_sta_vht_mcs_support(struct ieee80211_sub_if_data *sdata, ++ int link_id, ++ struct ieee80211_supported_band *sband, ++ const struct ieee80211_vht_operation *vht_op) ++{ ++ struct ieee80211_sta_vht_cap sta_vht_cap; ++ u16 ap_min_req_set, sta_rx_mcs_map, sta_tx_mcs_map; ++ int nss; ++ ++ if (sband->band != NL80211_BAND_5GHZ) ++ return true; ++ ++ if (!vht_op) ++ return false; ++ ++ memcpy(&sta_vht_cap, &sband->vht_cap, sizeof(sta_vht_cap)); ++ ieee80211_apply_vhtcap_overrides(sdata, &sta_vht_cap); ++ ++ ap_min_req_set = le16_to_cpu(vht_op->basic_mcs_set); ++ sta_rx_mcs_map = le16_to_cpu(sta_vht_cap.vht_mcs.rx_mcs_map); ++ sta_tx_mcs_map = le16_to_cpu(sta_vht_cap.vht_mcs.tx_mcs_map); ++ ++ /* ++ * Many APs are incorrectly advertising an all-zero value here, ++ * which really means MCS 0-7 are required for 1-8 streams, but ++ * they don't really mean it that way. ++ * Some other APs are incorrectly advertising 3 spatial streams ++ * with MCS 0-7 are required, but don't really mean it that way ++ * and we'll connect only with HT, rather than even HE. ++ * As a result, unfortunately the VHT basic MCS/NSS set cannot ++ * be used at all, so check it only in strict mode. ++ */ ++ if (!ieee80211_hw_check(&sdata->local->hw, STRICT)) ++ return true; ++ ++ /* ++ * P802.11REVme/D7.0 - 6.5.4.2.4 ++ * ... ++ * If the MLME of a VHT STA receives an MLME-JOIN.request primitive ++ * with a SelectedBSS parameter containing a Basic VHT-MCS And NSS Set ++ * field in the VHT Operation parameter that contains any unsupported ++ * tuple, the MLME response in the resulting ++ * MLME-JOIN.confirm primitive shall contain a ResultCode parameter ++ * that is not set to the value SUCCESS. ++ * ... ++ */ ++ for (nss = 8; nss > 0; nss--) { ++ u8 ap_op_val = (ap_min_req_set >> (2 * (nss - 1))) & 3; ++ u8 sta_rx_val; ++ u8 sta_tx_val; ++ ++ if (ap_op_val == IEEE80211_HE_MCS_NOT_SUPPORTED) ++ continue; ++ ++ sta_rx_val = (sta_rx_mcs_map >> (2 * (nss - 1))) & 3; ++ sta_tx_val = (sta_tx_mcs_map >> (2 * (nss - 1))) & 3; ++ ++ if (sta_rx_val == IEEE80211_HE_MCS_NOT_SUPPORTED || ++ sta_tx_val == IEEE80211_HE_MCS_NOT_SUPPORTED || ++ sta_rx_val < ap_op_val || sta_tx_val < ap_op_val) { ++ link_id_info(sdata, link_id, ++ "Missing mandatory rates for %d Nss, rx %d, tx %d oper %d, disable VHT\n", ++ nss, sta_rx_val, sta_tx_val, ap_op_val); ++ return false; ++ } ++ } ++ ++ return true; ++} ++ + static bool + ieee80211_verify_peer_he_mcs_support(struct ieee80211_sub_if_data *sdata, + int link_id, +@@ -1042,6 +1151,26 @@ ieee80211_determine_chan_mode(struct ieee80211_sub_if_data *sdata, + link_id_info(sdata, link_id, + "regulatory prevented using AP config, downgraded\n"); + ++ if (conn->mode >= IEEE80211_CONN_MODE_HT && ++ !ieee80211_verify_sta_ht_mcs_support(sdata, sband, ++ elems->ht_operation)) { ++ conn->mode = IEEE80211_CONN_MODE_LEGACY; ++ conn->bw_limit = IEEE80211_CONN_BW_LIMIT_20; ++ link_id_info(sdata, link_id, ++ "required MCSes not supported, disabling HT\n"); ++ } ++ ++ if (conn->mode >= IEEE80211_CONN_MODE_VHT && ++ !ieee80211_verify_sta_vht_mcs_support(sdata, link_id, sband, ++ elems->vht_operation)) { ++ conn->mode = IEEE80211_CONN_MODE_HT; ++ conn->bw_limit = min_t(enum ieee80211_conn_bw_limit, ++ conn->bw_limit, ++ IEEE80211_CONN_BW_LIMIT_40); ++ link_id_info(sdata, link_id, ++ "required MCSes not supported, disabling VHT\n"); ++ } ++ + if (conn->mode >= IEEE80211_CONN_MODE_HE && + (!ieee80211_verify_peer_he_mcs_support(sdata, link_id, + (void *)elems->he_cap, +-- +2.39.5 + diff --git a/queue-6.14/wifi-mac80211-always-send-max-agg-subframe-num-in-st.patch b/queue-6.14/wifi-mac80211-always-send-max-agg-subframe-num-in-st.patch new file mode 100644 index 0000000000..e5be63ea74 --- /dev/null +++ b/queue-6.14/wifi-mac80211-always-send-max-agg-subframe-num-in-st.patch @@ -0,0 +1,48 @@ +From 4e4c413916479a35a1fb290e2bb772d7ce1a5786 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Feb 2025 11:39:23 +0200 +Subject: wifi: mac80211: always send max agg subframe num in strict mode + +From: Johannes Berg + +[ Upstream commit 3fca951123b68df8d1b47bbf90409f8a3671362b ] + +Instead of only sending the correct number for EHT and up, +always send the correct number as it should be in strict +mode. + +Signed-off-by: Johannes Berg +Signed-off-by: Miri Korenblit +Link: https://patch.msgid.link/20250205110958.5910263db6da.Icd1f93fabc9705e4e760d834095c29b60b934d9e@changeid +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/mac80211/agg-tx.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c +index 61f2cac37728c..92120f9051499 100644 +--- a/net/mac80211/agg-tx.c ++++ b/net/mac80211/agg-tx.c +@@ -9,7 +9,7 @@ + * Copyright 2007, Michael Wu + * Copyright 2007-2010, Intel Corporation + * Copyright(c) 2015-2017 Intel Deutschland GmbH +- * Copyright (C) 2018 - 2023 Intel Corporation ++ * Copyright (C) 2018 - 2024 Intel Corporation + */ + + #include +@@ -464,7 +464,8 @@ static void ieee80211_send_addba_with_timeout(struct sta_info *sta, + sta->ampdu_mlme.addba_req_num[tid]++; + spin_unlock_bh(&sta->lock); + +- if (sta->sta.deflink.eht_cap.has_eht) { ++ if (sta->sta.deflink.eht_cap.has_eht || ++ ieee80211_hw_check(&local->hw, STRICT)) { + buf_size = local->hw.max_tx_aggregation_subframes; + } else if (sta->sta.deflink.he_cap.has_he) { + buf_size = min_t(u16, local->hw.max_tx_aggregation_subframes, +-- +2.39.5 + diff --git a/queue-6.14/wifi-mac80211-don-t-include-mle-in-ml-reconf-per-sta.patch b/queue-6.14/wifi-mac80211-don-t-include-mle-in-ml-reconf-per-sta.patch new file mode 100644 index 0000000000..a6c5af9681 --- /dev/null +++ b/queue-6.14/wifi-mac80211-don-t-include-mle-in-ml-reconf-per-sta.patch @@ -0,0 +1,54 @@ +From 82c431c4e231c2dcc3760184e663561873bcea22 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 8 Mar 2025 23:03:40 +0200 +Subject: wifi: mac80211: don't include MLE in ML reconf per-STA profile + +From: Johannes Berg + +[ Upstream commit c3171bed65ec323803b6b73f74017f7d0fd7aa6c ] + +In the multi-link reconfiguration frame, the per-STA profile for +added links shouldn't include the multi-link element. Set the +association ID to an invalid value, so it doesn't erroneously +match the link ID if that happens to be zero. + +Signed-off-by: Johannes Berg +Reviewed-by: Ilan Peer +Signed-off-by: Miri Korenblit +Link: https://patch.msgid.link/20250308225541.8e5be244c70f.I3472cd5c347814ee3600869a88488997bcd43224@changeid +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/mac80211/ieee80211_i.h | 2 +- + net/mac80211/mlme.c | 2 ++ + 2 files changed, 3 insertions(+), 1 deletion(-) + +diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h +index e7dc3f0cfc9a9..8f5f7797f0b6b 100644 +--- a/net/mac80211/ieee80211_i.h ++++ b/net/mac80211/ieee80211_i.h +@@ -462,7 +462,7 @@ struct ieee80211_mgd_assoc_data { + bool s1g; + bool spp_amsdu; + +- unsigned int assoc_link_id; ++ s8 assoc_link_id; + + u8 fils_nonces[2 * FILS_NONCE_LEN]; + u8 fils_kek[FILS_MAX_KEK_LEN]; +diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c +index e3deb89674b23..676274519cdfb 100644 +--- a/net/mac80211/mlme.c ++++ b/net/mac80211/mlme.c +@@ -10156,6 +10156,8 @@ int ieee80211_mgd_assoc_ml_reconf(struct ieee80211_sub_if_data *sdata, + if (!data) + return -ENOMEM; + ++ data->assoc_link_id = -1; ++ + uapsd_supported = true; + ieee80211_ml_reconf_selectors(userspace_selectors); + for (link_id = 0; link_id < IEEE80211_MLD_MAX_NUM_LINKS; +-- +2.39.5 + diff --git a/queue-6.14/wifi-mac80211-don-t-unconditionally-call-drv_mgd_com.patch b/queue-6.14/wifi-mac80211-don-t-unconditionally-call-drv_mgd_com.patch new file mode 100644 index 0000000000..4523649edf --- /dev/null +++ b/queue-6.14/wifi-mac80211-don-t-unconditionally-call-drv_mgd_com.patch @@ -0,0 +1,39 @@ +From c087d84d0774ec665c223aa3d6b9120a8fea0e87 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Feb 2025 11:39:22 +0200 +Subject: wifi: mac80211: don't unconditionally call drv_mgd_complete_tx() + +From: Johannes Berg + +[ Upstream commit 1798271b3604b902d45033ec569f2bf77e94ecc2 ] + +We might not have called drv_mgd_prepare_tx(), so only call +drv_mgd_complete_tx() under the same conditions. + +Signed-off-by: Johannes Berg +Reviewed-by: Emmanuel Grumbach +Signed-off-by: Miri Korenblit +Link: https://patch.msgid.link/20250205110958.e091fc39a351.Ie6a3cdca070612a0aa4b3c6914ab9ed602d1f456@changeid +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/mac80211/mlme.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c +index f92cbbc32a9e5..3bd1c4eeae52f 100644 +--- a/net/mac80211/mlme.c ++++ b/net/mac80211/mlme.c +@@ -3832,7 +3832,8 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, + if (tx) + ieee80211_flush_queues(local, sdata, false); + +- drv_mgd_complete_tx(sdata->local, sdata, &info); ++ if (tx || frame_buf) ++ drv_mgd_complete_tx(sdata->local, sdata, &info); + + /* clear AP addr only after building the needed mgmt frames */ + eth_zero_addr(sdata->deflink.u.mgd.bssid); +-- +2.39.5 + diff --git a/queue-6.14/wifi-mac80211-drop-cooked-monitor-support.patch b/queue-6.14/wifi-mac80211-drop-cooked-monitor-support.patch new file mode 100644 index 0000000000..6297941f87 --- /dev/null +++ b/queue-6.14/wifi-mac80211-drop-cooked-monitor-support.patch @@ -0,0 +1,876 @@ +From eb337a626244cb506ec2095837f3ebb0803321d2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 4 Feb 2025 12:13:52 +0100 +Subject: wifi: mac80211: Drop cooked monitor support + +From: Alexander Wetzel + +[ Upstream commit 286e696770654d79b34bd15953e7101a1c4784c7 ] + +Hostapd switched from cooked monitor interfaces to nl80211 Dec 2011. +Drop support for the outdated cooked monitor interfaces and fix +creating the virtual monitor interfaces in the following cases: + + 1) We have one non-monitor and one monitor interface with + %MONITOR_FLAG_ACTIVE enabled and then delete the non-monitor + interface. + + 2) We only have monitor interfaces enabled on resume while at least one + has %MONITOR_FLAG_ACTIVE set. + +Signed-off-by: Alexander Wetzel +Link: https://patch.msgid.link/20250204111352.7004-2-Alexander@wetzel-home.de +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + include/net/dropreason.h | 6 -- + net/mac80211/cfg.c | 9 +- + net/mac80211/drop.h | 21 ++-- + net/mac80211/ieee80211_i.h | 11 +-- + net/mac80211/iface.c | 50 ++++------ + net/mac80211/main.c | 16 +-- + net/mac80211/rx.c | 194 ++++++++++--------------------------- + net/mac80211/status.c | 34 +------ + net/mac80211/tx.c | 2 +- + 9 files changed, 94 insertions(+), 249 deletions(-) + +diff --git a/include/net/dropreason.h b/include/net/dropreason.h +index 56cb7be92244c..7d3b1a2a6feca 100644 +--- a/include/net/dropreason.h ++++ b/include/net/dropreason.h +@@ -17,12 +17,6 @@ enum skb_drop_reason_subsys { + */ + SKB_DROP_REASON_SUBSYS_MAC80211_UNUSABLE, + +- /** +- * @SKB_DROP_REASON_SUBSYS_MAC80211_MONITOR: mac80211 drop reasons +- * for frames still going to monitor, see net/mac80211/drop.h +- */ +- SKB_DROP_REASON_SUBSYS_MAC80211_MONITOR, +- + /** + * @SKB_DROP_REASON_SUBSYS_OPENVSWITCH: openvswitch drop reasons, + * see net/openvswitch/drop.h +diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c +index b766472703b12..1ec246133d244 100644 +--- a/net/mac80211/cfg.c ++++ b/net/mac80211/cfg.c +@@ -89,15 +89,14 @@ static int ieee80211_set_mon_options(struct ieee80211_sub_if_data *sdata, + + /* check flags first */ + if (params->flags && ieee80211_sdata_running(sdata)) { +- u32 mask = MONITOR_FLAG_COOK_FRAMES | MONITOR_FLAG_ACTIVE; ++ u32 mask = MONITOR_FLAG_ACTIVE; + + /* +- * Prohibit MONITOR_FLAG_COOK_FRAMES and +- * MONITOR_FLAG_ACTIVE to be changed while the +- * interface is up. ++ * Prohibit MONITOR_FLAG_ACTIVE to be changed ++ * while the interface is up. + * Else we would need to add a lot of cruft + * to update everything: +- * cooked_mntrs, monitor and all fif_* counters ++ * monitor and all fif_* counters + * reconfigure hardware + */ + if ((params->flags & mask) != (sdata->u.mntr.flags & mask)) +diff --git a/net/mac80211/drop.h b/net/mac80211/drop.h +index 59e3ec4dc9607..eb9ab310f91ca 100644 +--- a/net/mac80211/drop.h ++++ b/net/mac80211/drop.h +@@ -11,12 +11,6 @@ + + typedef unsigned int __bitwise ieee80211_rx_result; + +-#define MAC80211_DROP_REASONS_MONITOR(R) \ +- R(RX_DROP_M_UNEXPECTED_4ADDR_FRAME) \ +- R(RX_DROP_M_BAD_BCN_KEYIDX) \ +- R(RX_DROP_M_BAD_MGMT_KEYIDX) \ +-/* this line for the trailing \ - add before this */ +- + #define MAC80211_DROP_REASONS_UNUSABLE(R) \ + /* 0x00 == ___RX_DROP_UNUSABLE */ \ + R(RX_DROP_U_MIC_FAIL) \ +@@ -66,6 +60,10 @@ typedef unsigned int __bitwise ieee80211_rx_result; + R(RX_DROP_U_UNEXPECTED_STA_4ADDR) \ + R(RX_DROP_U_UNEXPECTED_VLAN_MCAST) \ + R(RX_DROP_U_NOT_PORT_CONTROL) \ ++ R(RX_DROP_U_UNEXPECTED_4ADDR_FRAME) \ ++ R(RX_DROP_U_BAD_BCN_KEYIDX) \ ++ /* 0x30 */ \ ++ R(RX_DROP_U_BAD_MGMT_KEYIDX) \ + R(RX_DROP_U_UNKNOWN_ACTION_REJECTED) \ + /* this line for the trailing \ - add before this */ + +@@ -78,10 +76,6 @@ enum ___mac80211_drop_reason { + ___RX_QUEUED = SKB_NOT_DROPPED_YET, + + #define ENUM(x) ___ ## x, +- ___RX_DROP_MONITOR = SKB_DROP_REASON_SUBSYS_MAC80211_MONITOR << +- SKB_DROP_REASON_SUBSYS_SHIFT, +- MAC80211_DROP_REASONS_MONITOR(ENUM) +- + ___RX_DROP_UNUSABLE = SKB_DROP_REASON_SUBSYS_MAC80211_UNUSABLE << + SKB_DROP_REASON_SUBSYS_SHIFT, + MAC80211_DROP_REASONS_UNUSABLE(ENUM) +@@ -89,11 +83,10 @@ enum ___mac80211_drop_reason { + }; + + enum mac80211_drop_reason { +- RX_CONTINUE = (__force ieee80211_rx_result)___RX_CONTINUE, +- RX_QUEUED = (__force ieee80211_rx_result)___RX_QUEUED, +- RX_DROP_MONITOR = (__force ieee80211_rx_result)___RX_DROP_MONITOR, ++ RX_CONTINUE = (__force ieee80211_rx_result)___RX_CONTINUE, ++ RX_QUEUED = (__force ieee80211_rx_result)___RX_QUEUED, ++ RX_DROP = (__force ieee80211_rx_result)___RX_DROP_UNUSABLE, + #define DEF(x) x = (__force ieee80211_rx_result)___ ## x, +- MAC80211_DROP_REASONS_MONITOR(DEF) + MAC80211_DROP_REASONS_UNUSABLE(DEF) + #undef DEF + }; +diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h +index 8f5f7797f0b6b..afc6fda6b606b 100644 +--- a/net/mac80211/ieee80211_i.h ++++ b/net/mac80211/ieee80211_i.h +@@ -200,7 +200,6 @@ enum ieee80211_packet_rx_flags { + /** + * enum ieee80211_rx_flags - RX data flags + * +- * @IEEE80211_RX_CMNTR: received on cooked monitor already + * @IEEE80211_RX_BEACON_REPORTED: This frame was already reported + * to cfg80211_report_obss_beacon(). + * +@@ -208,8 +207,7 @@ enum ieee80211_packet_rx_flags { + * for a single frame. + */ + enum ieee80211_rx_flags { +- IEEE80211_RX_CMNTR = BIT(0), +- IEEE80211_RX_BEACON_REPORTED = BIT(1), ++ IEEE80211_RX_BEACON_REPORTED = BIT(0), + }; + + struct ieee80211_rx_data { +@@ -1380,7 +1378,7 @@ struct ieee80211_local { + spinlock_t queue_stop_reason_lock; + + int open_count; +- int monitors, cooked_mntrs, tx_mntrs; ++ int monitors, tx_mntrs; + /* number of interfaces with corresponding FIF_ flags */ + int fif_fcsfail, fif_plcpfail, fif_control, fif_other_bss, fif_pspoll, + fif_probe_req; +@@ -1492,7 +1490,7 @@ struct ieee80211_local { + + /* see iface.c */ + struct list_head interfaces; +- struct list_head mon_list; /* only that are IFF_UP && !cooked */ ++ struct list_head mon_list; /* only that are IFF_UP */ + struct mutex iflist_mtx; + + /* Scanning and BSS list */ +@@ -2090,8 +2088,7 @@ struct sk_buff * + ieee80211_build_data_template(struct ieee80211_sub_if_data *sdata, + struct sk_buff *skb, u32 info_flags); + void ieee80211_tx_monitor(struct ieee80211_local *local, struct sk_buff *skb, +- int retry_count, bool send_to_cooked, +- struct ieee80211_tx_status *status); ++ int retry_count, struct ieee80211_tx_status *status); + + void ieee80211_check_fast_xmit(struct sta_info *sta); + void ieee80211_check_fast_xmit_all(struct ieee80211_local *local); +diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c +index d299bdbca6b3b..5616c0adbe093 100644 +--- a/net/mac80211/iface.c ++++ b/net/mac80211/iface.c +@@ -483,8 +483,6 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, bool going_do + ieee80211_ibss_stop(sdata); + break; + case NL80211_IFTYPE_MONITOR: +- if (sdata->u.mntr.flags & MONITOR_FLAG_COOK_FRAMES) +- break; + list_del_rcu(&sdata->u.mntr.list); + break; + default: +@@ -584,18 +582,17 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, bool going_do + /* no need to tell driver */ + break; + case NL80211_IFTYPE_MONITOR: +- if (sdata->u.mntr.flags & MONITOR_FLAG_COOK_FRAMES) { +- local->cooked_mntrs--; +- break; +- } ++ if (!(sdata->u.mntr.flags & MONITOR_FLAG_ACTIVE) && ++ !ieee80211_hw_check(&local->hw, NO_VIRTUAL_MONITOR)) { + +- local->monitors--; +- if (local->monitors == 0) { +- local->hw.conf.flags &= ~IEEE80211_CONF_MONITOR; +- hw_reconf_flags |= IEEE80211_CONF_CHANGE_MONITOR; +- } ++ local->monitors--; ++ if (local->monitors == 0) { ++ local->hw.conf.flags &= ~IEEE80211_CONF_MONITOR; ++ hw_reconf_flags |= IEEE80211_CONF_CHANGE_MONITOR; ++ } + +- ieee80211_adjust_monitor_flags(sdata, -1); ++ ieee80211_adjust_monitor_flags(sdata, -1); ++ } + break; + case NL80211_IFTYPE_NAN: + /* clean all the functions */ +@@ -1333,27 +1330,24 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up) + } + break; + case NL80211_IFTYPE_MONITOR: +- if (sdata->u.mntr.flags & MONITOR_FLAG_COOK_FRAMES) { +- local->cooked_mntrs++; +- break; +- } +- + if ((sdata->u.mntr.flags & MONITOR_FLAG_ACTIVE) || + ieee80211_hw_check(&local->hw, NO_VIRTUAL_MONITOR)) { + res = drv_add_interface(local, sdata); + if (res) + goto err_stop; +- } else if (local->monitors == 0 && local->open_count == 0) { +- res = ieee80211_add_virtual_monitor(local); +- if (res) +- goto err_stop; +- } ++ } else { ++ if (local->monitors == 0 && local->open_count == 0) { ++ res = ieee80211_add_virtual_monitor(local); ++ if (res) ++ goto err_stop; ++ } ++ local->monitors++; + +- /* must be before the call to ieee80211_configure_filter */ +- local->monitors++; +- if (local->monitors == 1) { +- local->hw.conf.flags |= IEEE80211_CONF_MONITOR; +- hw_reconf_flags |= IEEE80211_CONF_CHANGE_MONITOR; ++ /* must be before the call to ieee80211_configure_filter */ ++ if (local->monitors == 1) { ++ local->hw.conf.flags |= IEEE80211_CONF_MONITOR; ++ hw_reconf_flags |= IEEE80211_CONF_CHANGE_MONITOR; ++ } + } + + ieee80211_adjust_monitor_flags(sdata, 1); +@@ -1430,8 +1424,6 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up) + rcu_assign_pointer(local->p2p_sdata, sdata); + break; + case NL80211_IFTYPE_MONITOR: +- if (sdata->u.mntr.flags & MONITOR_FLAG_COOK_FRAMES) +- break; + list_add_tail_rcu(&sdata->u.mntr.list, &local->mon_list); + break; + default: +diff --git a/net/mac80211/main.c b/net/mac80211/main.c +index 2b6249d75a5d4..6b6de43d9420a 100644 +--- a/net/mac80211/main.c ++++ b/net/mac80211/main.c +@@ -1746,18 +1746,7 @@ void ieee80211_free_hw(struct ieee80211_hw *hw) + wiphy_free(local->hw.wiphy); + } + EXPORT_SYMBOL(ieee80211_free_hw); +- +-static const char * const drop_reasons_monitor[] = { +-#define V(x) #x, +- [0] = "RX_DROP_MONITOR", +- MAC80211_DROP_REASONS_MONITOR(V) +-}; +- +-static struct drop_reason_list drop_reason_list_monitor = { +- .reasons = drop_reasons_monitor, +- .n_reasons = ARRAY_SIZE(drop_reasons_monitor), +-}; +- ++#define V(x) #x, + static const char * const drop_reasons_unusable[] = { + [0] = "RX_DROP_UNUSABLE", + MAC80211_DROP_REASONS_UNUSABLE(V) +@@ -1786,8 +1775,6 @@ static int __init ieee80211_init(void) + if (ret) + goto err_netdev; + +- drop_reasons_register_subsys(SKB_DROP_REASON_SUBSYS_MAC80211_MONITOR, +- &drop_reason_list_monitor); + drop_reasons_register_subsys(SKB_DROP_REASON_SUBSYS_MAC80211_UNUSABLE, + &drop_reason_list_unusable); + +@@ -1806,7 +1793,6 @@ static void __exit ieee80211_exit(void) + + ieee80211_iface_exit(); + +- drop_reasons_unregister_subsys(SKB_DROP_REASON_SUBSYS_MAC80211_MONITOR); + drop_reasons_unregister_subsys(SKB_DROP_REASON_SUBSYS_MAC80211_UNUSABLE); + + rcu_barrier(); +diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c +index 0659ec892ec6c..ad019a50b6b33 100644 +--- a/net/mac80211/rx.c ++++ b/net/mac80211/rx.c +@@ -1045,14 +1045,14 @@ static ieee80211_rx_result ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx) + if (is_multicast_ether_addr(hdr->addr1)) { + if (ieee80211_has_tods(hdr->frame_control) || + !ieee80211_has_fromds(hdr->frame_control)) +- return RX_DROP_MONITOR; ++ return RX_DROP; + if (ether_addr_equal(hdr->addr3, dev_addr)) +- return RX_DROP_MONITOR; ++ return RX_DROP; + } else { + if (!ieee80211_has_a4(hdr->frame_control)) +- return RX_DROP_MONITOR; ++ return RX_DROP; + if (ether_addr_equal(hdr->addr4, dev_addr)) +- return RX_DROP_MONITOR; ++ return RX_DROP; + } + } + +@@ -1064,20 +1064,20 @@ static ieee80211_rx_result ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx) + struct ieee80211_mgmt *mgmt; + + if (!ieee80211_is_mgmt(hdr->frame_control)) +- return RX_DROP_MONITOR; ++ return RX_DROP; + + if (ieee80211_is_action(hdr->frame_control)) { + u8 category; + + /* make sure category field is present */ + if (rx->skb->len < IEEE80211_MIN_ACTION_SIZE) +- return RX_DROP_MONITOR; ++ return RX_DROP; + + mgmt = (struct ieee80211_mgmt *)hdr; + category = mgmt->u.action.category; + if (category != WLAN_CATEGORY_MESH_ACTION && + category != WLAN_CATEGORY_SELF_PROTECTED) +- return RX_DROP_MONITOR; ++ return RX_DROP; + return RX_CONTINUE; + } + +@@ -1087,7 +1087,7 @@ static ieee80211_rx_result ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx) + ieee80211_is_auth(hdr->frame_control)) + return RX_CONTINUE; + +- return RX_DROP_MONITOR; ++ return RX_DROP; + } + + return RX_CONTINUE; +@@ -1513,7 +1513,7 @@ ieee80211_rx_h_check(struct ieee80211_rx_data *rx) + hdrlen = ieee80211_hdrlen(hdr->frame_control); + + if (rx->skb->len < hdrlen + 8) +- return RX_DROP_MONITOR; ++ return RX_DROP; + + skb_copy_bits(rx->skb, hdrlen + 6, ðertype, 2); + if (ethertype == rx->sdata->control_port_protocol) +@@ -1526,7 +1526,7 @@ ieee80211_rx_h_check(struct ieee80211_rx_data *rx) + GFP_ATOMIC)) + return RX_DROP_U_SPURIOUS; + +- return RX_DROP_MONITOR; ++ return RX_DROP; + } + + return RX_CONTINUE; +@@ -1862,7 +1862,7 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) + cfg80211_rx_unexpected_4addr_frame( + rx->sdata->dev, sta->sta.addr, + GFP_ATOMIC); +- return RX_DROP_M_UNEXPECTED_4ADDR_FRAME; ++ return RX_DROP_U_UNEXPECTED_4ADDR_FRAME; + } + /* + * Update counter and free packet here to avoid +@@ -1997,7 +1997,7 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) + cfg80211_rx_unprot_mlme_mgmt(rx->sdata->dev, + skb->data, + skb->len); +- return RX_DROP_M_BAD_BCN_KEYIDX; ++ return RX_DROP_U_BAD_BCN_KEYIDX; + } + + rx->key = ieee80211_rx_get_bigtk(rx, mmie_keyidx); +@@ -2011,11 +2011,11 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) + + if (mmie_keyidx < NUM_DEFAULT_KEYS || + mmie_keyidx >= NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS) +- return RX_DROP_M_BAD_MGMT_KEYIDX; /* unexpected BIP keyidx */ ++ return RX_DROP_U_BAD_MGMT_KEYIDX; /* unexpected BIP keyidx */ + if (rx->link_sta) { + if (ieee80211_is_group_privacy_action(skb) && + test_sta_flag(rx->sta, WLAN_STA_MFP)) +- return RX_DROP_MONITOR; ++ return RX_DROP; + + rx->key = rcu_dereference(rx->link_sta->gtk[mmie_keyidx]); + } +@@ -2100,11 +2100,11 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) + + if (rx->key) { + if (unlikely(rx->key->flags & KEY_FLAG_TAINTED)) +- return RX_DROP_MONITOR; ++ return RX_DROP; + + /* TODO: add threshold stuff again */ + } else { +- return RX_DROP_MONITOR; ++ return RX_DROP; + } + + switch (rx->key->conf.cipher) { +@@ -2278,7 +2278,7 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx) + goto out; + + if (is_multicast_ether_addr(hdr->addr1)) +- return RX_DROP_MONITOR; ++ return RX_DROP; + + I802_DEBUG_INC(rx->local->rx_handlers_fragments); + +@@ -2333,7 +2333,7 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx) + rx->seqno_idx, hdr); + if (!entry) { + I802_DEBUG_INC(rx->local->rx_handlers_drop_defrag); +- return RX_DROP_MONITOR; ++ return RX_DROP; + } + + /* "The receiver shall discard MSDUs and MMPDUs whose constituent +@@ -2855,25 +2855,25 @@ ieee80211_rx_mesh_data(struct ieee80211_sub_if_data *sdata, struct sta_info *sta + return RX_CONTINUE; + + if (!pskb_may_pull(skb, sizeof(*eth) + 6)) +- return RX_DROP_MONITOR; ++ return RX_DROP; + + mesh_hdr = (struct ieee80211s_hdr *)(skb->data + sizeof(*eth)); + mesh_hdrlen = ieee80211_get_mesh_hdrlen(mesh_hdr); + + if (!pskb_may_pull(skb, sizeof(*eth) + mesh_hdrlen)) +- return RX_DROP_MONITOR; ++ return RX_DROP; + + eth = (struct ethhdr *)skb->data; + multicast = is_multicast_ether_addr(eth->h_dest); + + mesh_hdr = (struct ieee80211s_hdr *)(eth + 1); + if (!mesh_hdr->ttl) +- return RX_DROP_MONITOR; ++ return RX_DROP; + + /* frame is in RMC, don't forward */ + if (is_multicast_ether_addr(eth->h_dest) && + mesh_rmc_check(sdata, eth->h_source, mesh_hdr)) +- return RX_DROP_MONITOR; ++ return RX_DROP; + + /* forward packet */ + if (sdata->crypto_tx_tailroom_needed_cnt) +@@ -2890,7 +2890,7 @@ ieee80211_rx_mesh_data(struct ieee80211_sub_if_data *sdata, struct sta_info *sta + /* has_a4 already checked in ieee80211_rx_mesh_check */ + proxied_addr = mesh_hdr->eaddr2; + else +- return RX_DROP_MONITOR; ++ return RX_DROP; + + rcu_read_lock(); + mppath = mpp_path_lookup(sdata, proxied_addr); +@@ -2922,14 +2922,14 @@ ieee80211_rx_mesh_data(struct ieee80211_sub_if_data *sdata, struct sta_info *sta + goto rx_accept; + + IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, dropped_frames_ttl); +- return RX_DROP_MONITOR; ++ return RX_DROP; + } + + if (!ifmsh->mshcfg.dot11MeshForwarding) { + if (is_multicast_ether_addr(eth->h_dest)) + goto rx_accept; + +- return RX_DROP_MONITOR; ++ return RX_DROP; + } + + skb_set_queue_mapping(skb, ieee802_1d_to_ac[skb->priority]); +@@ -3122,7 +3122,7 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx) + return RX_CONTINUE; + + if (unlikely(!ieee80211_is_data_present(fc))) +- return RX_DROP_MONITOR; ++ return RX_DROP; + + if (unlikely(ieee80211_has_a4(hdr->frame_control))) { + switch (rx->sdata->vif.type) { +@@ -3179,19 +3179,16 @@ ieee80211_rx_h_data(struct ieee80211_rx_data *rx) + return RX_CONTINUE; + + if (unlikely(!ieee80211_is_data_present(hdr->frame_control))) +- return RX_DROP_MONITOR; ++ return RX_DROP; + +- /* +- * Send unexpected-4addr-frame event to hostapd. For older versions, +- * also drop the frame to cooked monitor interfaces. +- */ ++ /* Send unexpected-4addr-frame event to hostapd */ + if (ieee80211_has_a4(hdr->frame_control) && + sdata->vif.type == NL80211_IFTYPE_AP) { + if (rx->sta && + !test_and_set_sta_flag(rx->sta, WLAN_STA_4ADDR_EVENT)) + cfg80211_rx_unexpected_4addr_frame( + rx->sdata->dev, rx->sta->sta.addr, GFP_ATOMIC); +- return RX_DROP_MONITOR; ++ return RX_DROP; + } + + res = __ieee80211_data_to_8023(rx, &port_control); +@@ -3203,7 +3200,7 @@ ieee80211_rx_h_data(struct ieee80211_rx_data *rx) + return res; + + if (!ieee80211_frame_allowed(rx, fc)) +- return RX_DROP_MONITOR; ++ return RX_DROP; + + /* directly handle TDLS channel switch requests/responses */ + if (unlikely(((struct ethhdr *)rx->skb->data)->h_proto == +@@ -3268,11 +3265,11 @@ ieee80211_rx_h_ctrl(struct ieee80211_rx_data *rx, struct sk_buff_head *frames) + }; + + if (!rx->sta) +- return RX_DROP_MONITOR; ++ return RX_DROP; + + if (skb_copy_bits(skb, offsetof(struct ieee80211_bar, control), + &bar_data, sizeof(bar_data))) +- return RX_DROP_MONITOR; ++ return RX_DROP; + + tid = le16_to_cpu(bar_data.control) >> 12; + +@@ -3284,7 +3281,7 @@ ieee80211_rx_h_ctrl(struct ieee80211_rx_data *rx, struct sk_buff_head *frames) + + tid_agg_rx = rcu_dereference(rx->sta->ampdu_mlme.tid_rx[tid]); + if (!tid_agg_rx) +- return RX_DROP_MONITOR; ++ return RX_DROP; + + start_seq_num = le16_to_cpu(bar_data.start_seq_num) >> 4; + event.u.ba.tid = tid; +@@ -3308,12 +3305,7 @@ ieee80211_rx_h_ctrl(struct ieee80211_rx_data *rx, struct sk_buff_head *frames) + return RX_QUEUED; + } + +- /* +- * After this point, we only want management frames, +- * so we can drop all remaining control frames to +- * cooked monitor interfaces. +- */ +- return RX_DROP_MONITOR; ++ return RX_DROP; + } + + static void ieee80211_process_sa_query_req(struct ieee80211_sub_if_data *sdata, +@@ -3422,10 +3414,10 @@ ieee80211_rx_h_mgmt_check(struct ieee80211_rx_data *rx) + * and unknown (reserved) frames are useless. + */ + if (rx->skb->len < 24) +- return RX_DROP_MONITOR; ++ return RX_DROP; + + if (!ieee80211_is_mgmt(mgmt->frame_control)) +- return RX_DROP_MONITOR; ++ return RX_DROP; + + /* drop too small action frames */ + if (ieee80211_is_action(mgmt->frame_control) && +@@ -3951,17 +3943,16 @@ ieee80211_rx_h_action_return(struct ieee80211_rx_data *rx) + * ones. For all other modes we will return them to the sender, + * setting the 0x80 bit in the action category, as required by + * 802.11-2012 9.24.4. +- * Newer versions of hostapd shall also use the management frame +- * registration mechanisms, but older ones still use cooked +- * monitor interfaces so push all frames there. ++ * Newer versions of hostapd use the management frame registration ++ * mechanisms and old cooked monitor interface is no longer supported. + */ + if (!(status->rx_flags & IEEE80211_RX_MALFORMED_ACTION_FRM) && + (sdata->vif.type == NL80211_IFTYPE_AP || + sdata->vif.type == NL80211_IFTYPE_AP_VLAN)) +- return RX_DROP_MONITOR; ++ return RX_DROP; + + if (is_multicast_ether_addr(mgmt->da)) +- return RX_DROP_MONITOR; ++ return RX_DROP; + + /* do not return rejected action frames */ + if (mgmt->u.action.category & 0x80) +@@ -4006,7 +3997,7 @@ ieee80211_rx_h_ext(struct ieee80211_rx_data *rx) + return RX_CONTINUE; + + if (sdata->vif.type != NL80211_IFTYPE_STATION) +- return RX_DROP_MONITOR; ++ return RX_DROP; + + /* for now only beacons are ext, so queue them */ + ieee80211_queue_skb_to_iface(sdata, rx->link_id, rx->sta, rx->skb); +@@ -4027,7 +4018,7 @@ ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx) + sdata->vif.type != NL80211_IFTYPE_ADHOC && + sdata->vif.type != NL80211_IFTYPE_OCB && + sdata->vif.type != NL80211_IFTYPE_STATION) +- return RX_DROP_MONITOR; ++ return RX_DROP; + + switch (stype) { + case cpu_to_le16(IEEE80211_STYPE_AUTH): +@@ -4038,32 +4029,32 @@ ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx) + case cpu_to_le16(IEEE80211_STYPE_DEAUTH): + if (is_multicast_ether_addr(mgmt->da) && + !is_broadcast_ether_addr(mgmt->da)) +- return RX_DROP_MONITOR; ++ return RX_DROP; + + /* process only for station/IBSS */ + if (sdata->vif.type != NL80211_IFTYPE_STATION && + sdata->vif.type != NL80211_IFTYPE_ADHOC) +- return RX_DROP_MONITOR; ++ return RX_DROP; + break; + case cpu_to_le16(IEEE80211_STYPE_ASSOC_RESP): + case cpu_to_le16(IEEE80211_STYPE_REASSOC_RESP): + case cpu_to_le16(IEEE80211_STYPE_DISASSOC): + if (is_multicast_ether_addr(mgmt->da) && + !is_broadcast_ether_addr(mgmt->da)) +- return RX_DROP_MONITOR; ++ return RX_DROP; + + /* process only for station */ + if (sdata->vif.type != NL80211_IFTYPE_STATION) +- return RX_DROP_MONITOR; ++ return RX_DROP; + break; + case cpu_to_le16(IEEE80211_STYPE_PROBE_REQ): + /* process only for ibss and mesh */ + if (sdata->vif.type != NL80211_IFTYPE_ADHOC && + sdata->vif.type != NL80211_IFTYPE_MESH_POINT) +- return RX_DROP_MONITOR; ++ return RX_DROP; + break; + default: +- return RX_DROP_MONITOR; ++ return RX_DROP; + } + + ieee80211_queue_skb_to_iface(sdata, rx->link_id, rx->sta, rx->skb); +@@ -4071,82 +4062,9 @@ ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx) + return RX_QUEUED; + } + +-static void ieee80211_rx_cooked_monitor(struct ieee80211_rx_data *rx, +- struct ieee80211_rate *rate, +- ieee80211_rx_result reason) +-{ +- struct ieee80211_sub_if_data *sdata; +- struct ieee80211_local *local = rx->local; +- struct sk_buff *skb = rx->skb, *skb2; +- struct net_device *prev_dev = NULL; +- struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); +- int needed_headroom; +- +- /* +- * If cooked monitor has been processed already, then +- * don't do it again. If not, set the flag. +- */ +- if (rx->flags & IEEE80211_RX_CMNTR) +- goto out_free_skb; +- rx->flags |= IEEE80211_RX_CMNTR; +- +- /* If there are no cooked monitor interfaces, just free the SKB */ +- if (!local->cooked_mntrs) +- goto out_free_skb; +- +- /* room for the radiotap header based on driver features */ +- needed_headroom = ieee80211_rx_radiotap_hdrlen(local, status, skb); +- +- if (skb_headroom(skb) < needed_headroom && +- pskb_expand_head(skb, needed_headroom, 0, GFP_ATOMIC)) +- goto out_free_skb; +- +- /* prepend radiotap information */ +- ieee80211_add_rx_radiotap_header(local, skb, rate, needed_headroom, +- false); +- +- skb_reset_mac_header(skb); +- skb->ip_summed = CHECKSUM_UNNECESSARY; +- skb->pkt_type = PACKET_OTHERHOST; +- skb->protocol = htons(ETH_P_802_2); +- +- list_for_each_entry_rcu(sdata, &local->interfaces, list) { +- if (!ieee80211_sdata_running(sdata)) +- continue; +- +- if (sdata->vif.type != NL80211_IFTYPE_MONITOR || +- !(sdata->u.mntr.flags & MONITOR_FLAG_COOK_FRAMES)) +- continue; +- +- if (prev_dev) { +- skb2 = skb_clone(skb, GFP_ATOMIC); +- if (skb2) { +- skb2->dev = prev_dev; +- netif_receive_skb(skb2); +- } +- } +- +- prev_dev = sdata->dev; +- dev_sw_netstats_rx_add(sdata->dev, skb->len); +- } +- +- if (prev_dev) { +- skb->dev = prev_dev; +- netif_receive_skb(skb); +- return; +- } +- +- out_free_skb: +- kfree_skb_reason(skb, (__force u32)reason); +-} +- + static void ieee80211_rx_handlers_result(struct ieee80211_rx_data *rx, + ieee80211_rx_result res) + { +- struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb); +- struct ieee80211_supported_band *sband; +- struct ieee80211_rate *rate = NULL; +- + if (res == RX_QUEUED) { + I802_DEBUG_INC(rx->sdata->local->rx_handlers_queued); + return; +@@ -4158,23 +4076,13 @@ static void ieee80211_rx_handlers_result(struct ieee80211_rx_data *rx, + rx->link_sta->rx_stats.dropped++; + } + +- if (u32_get_bits((__force u32)res, SKB_DROP_REASON_SUBSYS_MASK) == +- SKB_DROP_REASON_SUBSYS_MAC80211_UNUSABLE) { +- kfree_skb_reason(rx->skb, (__force u32)res); +- return; +- } +- +- sband = rx->local->hw.wiphy->bands[status->band]; +- if (status->encoding == RX_ENC_LEGACY) +- rate = &sband->bitrates[status->rate_idx]; +- +- ieee80211_rx_cooked_monitor(rx, rate, res); ++ kfree_skb_reason(rx->skb, (__force u32)res); + } + + static void ieee80211_rx_handlers(struct ieee80211_rx_data *rx, + struct sk_buff_head *frames) + { +- ieee80211_rx_result res = RX_DROP_MONITOR; ++ ieee80211_rx_result res = RX_DROP; + struct sk_buff *skb; + + #define CALL_RXH(rxh) \ +@@ -4238,7 +4146,7 @@ static void ieee80211_rx_handlers(struct ieee80211_rx_data *rx, + static void ieee80211_invoke_rx_handlers(struct ieee80211_rx_data *rx) + { + struct sk_buff_head reorder_release; +- ieee80211_rx_result res = RX_DROP_MONITOR; ++ ieee80211_rx_result res = RX_DROP; + + __skb_queue_head_init(&reorder_release); + +diff --git a/net/mac80211/status.c b/net/mac80211/status.c +index 5f28f3633fa0a..b17b3cc7fb903 100644 +--- a/net/mac80211/status.c ++++ b/net/mac80211/status.c +@@ -895,8 +895,7 @@ static int ieee80211_tx_get_rates(struct ieee80211_hw *hw, + } + + void ieee80211_tx_monitor(struct ieee80211_local *local, struct sk_buff *skb, +- int retry_count, bool send_to_cooked, +- struct ieee80211_tx_status *status) ++ int retry_count, struct ieee80211_tx_status *status) + { + struct sk_buff *skb2; + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); +@@ -930,10 +929,6 @@ void ieee80211_tx_monitor(struct ieee80211_local *local, struct sk_buff *skb, + if (sdata->u.mntr.flags & MONITOR_FLAG_SKIP_TX) + continue; + +- if ((sdata->u.mntr.flags & MONITOR_FLAG_COOK_FRAMES) && +- !send_to_cooked) +- continue; +- + if (prev_dev) { + skb2 = skb_clone(skb, GFP_ATOMIC); + if (skb2) { +@@ -964,7 +959,6 @@ static void __ieee80211_tx_status(struct ieee80211_hw *hw, + struct ieee80211_tx_info *info = status->info; + struct sta_info *sta; + __le16 fc; +- bool send_to_cooked; + bool acked; + bool noack_success; + struct ieee80211_bar *bar; +@@ -1091,28 +1085,10 @@ static void __ieee80211_tx_status(struct ieee80211_hw *hw, + + ieee80211_report_used_skb(local, skb, false, status->ack_hwtstamp); + +- /* this was a transmitted frame, but now we want to reuse it */ +- skb_orphan(skb); +- +- /* Need to make a copy before skb->cb gets cleared */ +- send_to_cooked = !!(info->flags & IEEE80211_TX_CTL_INJECTED) || +- !(ieee80211_is_data(fc)); +- +- /* +- * This is a bit racy but we can avoid a lot of work +- * with this test... +- */ +- if (!local->tx_mntrs && (!send_to_cooked || !local->cooked_mntrs)) { +- if (status->free_list) +- list_add_tail(&skb->list, status->free_list); +- else +- dev_kfree_skb(skb); +- return; +- } +- +- /* send to monitor interfaces */ +- ieee80211_tx_monitor(local, skb, retry_count, +- send_to_cooked, status); ++ if (status->free_list) ++ list_add_tail(&skb->list, status->free_list); ++ else ++ dev_kfree_skb(skb); + } + + void ieee80211_tx_status_skb(struct ieee80211_hw *hw, struct sk_buff *skb) +diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c +index a24636bda6793..1289df373795e 100644 +--- a/net/mac80211/tx.c ++++ b/net/mac80211/tx.c +@@ -5617,7 +5617,7 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, + if (!copy) + return bcn; + +- ieee80211_tx_monitor(hw_to_local(hw), copy, 1, false, NULL); ++ ieee80211_tx_monitor(hw_to_local(hw), copy, 1, NULL); + + return bcn; + } +-- +2.39.5 + diff --git a/queue-6.14/wifi-mac80211-fix-u-apsd-check-in-ml-reconfiguration.patch b/queue-6.14/wifi-mac80211-fix-u-apsd-check-in-ml-reconfiguration.patch new file mode 100644 index 0000000000..bbe585db7b --- /dev/null +++ b/queue-6.14/wifi-mac80211-fix-u-apsd-check-in-ml-reconfiguration.patch @@ -0,0 +1,48 @@ +From d1ea5fc22b36ef0fadc474c4f851becb7c20c12d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 8 Mar 2025 23:03:31 +0200 +Subject: wifi: mac80211: fix U-APSD check in ML reconfiguration + +From: Johannes Berg + +[ Upstream commit 7a6a740be17e049a2742c76bb1dadb3d78c930d9 ] + +If U-APSD isn't enabled by us, then IEEE80211_STA_UAPSD_ENABLED +won't be set, but the AP can still support it in that case. Only +require U-APSD from the AP if we enabled it, don't require it to +be disabled on the AP if we didn't. + +Signed-off-by: Johannes Berg +Reviewed-by: Ilan Peer +Signed-off-by: Miri Korenblit +Link: https://patch.msgid.link/20250308225541.b4674be12a38.I01959e448c6a2a3e8bc5d561bbae9e8d2cca616a@changeid +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/mac80211/mlme.c | 9 ++++----- + 1 file changed, 4 insertions(+), 5 deletions(-) + +diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c +index 3f30c4c1f78bb..f92cbbc32a9e5 100644 +--- a/net/mac80211/mlme.c ++++ b/net/mac80211/mlme.c +@@ -10216,12 +10216,11 @@ int ieee80211_mgd_assoc_ml_reconf(struct ieee80211_sub_if_data *sdata, + } + } + +- /* Require U-APSD support to be similar to the current valid +- * links +- */ +- if (uapsd_supported != +- !!(sdata->u.mgd.flags & IEEE80211_STA_UAPSD_ENABLED)) { ++ /* Require U-APSD support if we enabled it */ ++ if (sdata->u.mgd.flags & IEEE80211_STA_UAPSD_ENABLED && ++ !uapsd_supported) { + err = -EINVAL; ++ sdata_info(sdata, "U-APSD on but not available on (all) new links\n"); + goto err_free; + } + +-- +2.39.5 + diff --git a/queue-6.14/wifi-mac80211-fix-warning-on-disconnect-during-faile.patch b/queue-6.14/wifi-mac80211-fix-warning-on-disconnect-during-faile.patch new file mode 100644 index 0000000000..c1388aab65 --- /dev/null +++ b/queue-6.14/wifi-mac80211-fix-warning-on-disconnect-during-faile.patch @@ -0,0 +1,39 @@ +From 306d996b401997c39664c279c1a4eb6ea76ad79f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 8 Mar 2025 23:03:36 +0200 +Subject: wifi: mac80211: fix warning on disconnect during failed ML reconf + +From: Johannes Berg + +[ Upstream commit 0e104aa3676d020f6c442cd7fbaeb72adaaab6fc ] + +If multi-link reconfiguration fails, we can disconnect with a local link +already allocated but the BSS entry not assigned yet, which leads to a +warning in cfg80211. Add a check to avoid the warning. + +Signed-off-by: Johannes Berg +Reviewed-by: Ilan Peer +Signed-off-by: Miri Korenblit +Link: https://patch.msgid.link/20250308225541.699bd9cbabe5.I599d5ff69092a65e916e2acd25137ae9df8debe8@changeid +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/mac80211/mlme.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c +index 676274519cdfb..3f30c4c1f78bb 100644 +--- a/net/mac80211/mlme.c ++++ b/net/mac80211/mlme.c +@@ -4298,7 +4298,7 @@ static void __ieee80211_disconnect(struct ieee80211_sub_if_data *sdata) + struct ieee80211_link_data *link; + + link = sdata_dereference(sdata->link[link_id], sdata); +- if (!link) ++ if (!link || !link->conf->bss) + continue; + cfg80211_unlink_bss(local->hw.wiphy, link->conf->bss); + link->conf->bss = NULL; +-- +2.39.5 + diff --git a/queue-6.14/wifi-mac80211-remove-misplaced-drv_mgd_complete_tx-c.patch b/queue-6.14/wifi-mac80211-remove-misplaced-drv_mgd_complete_tx-c.patch new file mode 100644 index 0000000000..93378ab3d1 --- /dev/null +++ b/queue-6.14/wifi-mac80211-remove-misplaced-drv_mgd_complete_tx-c.patch @@ -0,0 +1,41 @@ +From dea3488aa4b02a45c4a2dd825126ea93bda8e770 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Feb 2025 11:39:21 +0200 +Subject: wifi: mac80211: remove misplaced drv_mgd_complete_tx() call + +From: Johannes Berg + +[ Upstream commit f4995cdc4d02d0abc8e9fcccad5c71ce676c1e3f ] + +In the original commit 15fae3410f1d ("mac80211: notify driver on +mgd TX completion") I evidently made a mistake and placed the +call in the "associated" if, rather than the "assoc_data". Later +I noticed the missing call and placed it in commit c042600c17d8 +("wifi: mac80211: adding missing drv_mgd_complete_tx() call"), +but didn't remove the wrong one. Remove it now. + +Signed-off-by: Johannes Berg +Reviewed-by: Emmanuel Grumbach +Signed-off-by: Miri Korenblit +Link: https://patch.msgid.link/20250205110958.6ed954179bbf.Id8ef8835b7e6da3bf913c76f77d201017dc8a3c9@changeid +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/mac80211/mlme.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c +index 3bd1c4eeae52f..ca247609f11bf 100644 +--- a/net/mac80211/mlme.c ++++ b/net/mac80211/mlme.c +@@ -9508,7 +9508,6 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, + ieee80211_report_disconnect(sdata, frame_buf, + sizeof(frame_buf), true, + req->reason_code, false); +- drv_mgd_complete_tx(sdata->local, sdata, &info); + return 0; + } + +-- +2.39.5 + diff --git a/queue-6.14/wifi-mac80211-set-ieee80211_prep_tx_info-link_id-upo.patch b/queue-6.14/wifi-mac80211-set-ieee80211_prep_tx_info-link_id-upo.patch new file mode 100644 index 0000000000..3023daebf7 --- /dev/null +++ b/queue-6.14/wifi-mac80211-set-ieee80211_prep_tx_info-link_id-upo.patch @@ -0,0 +1,96 @@ +From bda67e991199e80abc8418b3024d7e3a718e759d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Feb 2025 11:39:20 +0200 +Subject: wifi: mac80211: set ieee80211_prep_tx_info::link_id upon Auth Rx + +From: Emmanuel Grumbach + +[ Upstream commit 8c60179b64434894eac1ffab7396bac131bc8b6e ] + +This will be used by the low level driver. +Note that link_id will be 0 in case of a non-MLO authentication. +Also fix a call-site of mgd_prepare_tx() where the link_id was not +populated. + +Update the documentation to reflect the current state +ieee80211_prep_tx_info::link_id is also available in mgd_complete_tx(). + +Signed-off-by: Emmanuel Grumbach +Signed-off-by: Miri Korenblit +Link: https://patch.msgid.link/20250205110958.6a590f189ce5.I1fc5c0da26b143f5b07191eb592f01f7083d55ae@changeid +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + include/net/mac80211.h | 4 ++-- + net/mac80211/driver-ops.h | 3 ++- + net/mac80211/mlme.c | 4 +++- + 3 files changed, 7 insertions(+), 4 deletions(-) + +diff --git a/include/net/mac80211.h b/include/net/mac80211.h +index dcbb2e54746c7..b421526aae851 100644 +--- a/include/net/mac80211.h ++++ b/include/net/mac80211.h +@@ -7,7 +7,7 @@ + * Copyright 2007-2010 Johannes Berg + * Copyright 2013-2014 Intel Mobile Communications GmbH + * Copyright (C) 2015 - 2017 Intel Deutschland GmbH +- * Copyright (C) 2018 - 2024 Intel Corporation ++ * Copyright (C) 2018 - 2025 Intel Corporation + */ + + #ifndef MAC80211_H +@@ -3829,7 +3829,7 @@ enum ieee80211_reconfig_type { + * @was_assoc: set if this call is due to deauth/disassoc + * while just having been associated + * @link_id: the link id on which the frame will be TX'ed. +- * Only used with the mgd_prepare_tx() method. ++ * 0 for a non-MLO connection. + */ + struct ieee80211_prep_tx_info { + u16 duration; +diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h +index 5acecc7bd4a99..307587c8a0037 100644 +--- a/net/mac80211/driver-ops.h ++++ b/net/mac80211/driver-ops.h +@@ -2,7 +2,7 @@ + /* + * Portions of this file + * Copyright(c) 2016 Intel Deutschland GmbH +-* Copyright (C) 2018-2019, 2021-2024 Intel Corporation ++* Copyright (C) 2018-2019, 2021-2025 Intel Corporation + */ + + #ifndef __MAC80211_DRIVER_OPS +@@ -955,6 +955,7 @@ static inline void drv_mgd_complete_tx(struct ieee80211_local *local, + return; + WARN_ON_ONCE(sdata->vif.type != NL80211_IFTYPE_STATION); + ++ info->link_id = info->link_id < 0 ? 0 : info->link_id; + trace_drv_mgd_complete_tx(local, sdata, info->duration, + info->subtype, info->success); + if (local->ops->mgd_complete_tx) +diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c +index ca247609f11bf..8235400b7e5d8 100644 +--- a/net/mac80211/mlme.c ++++ b/net/mac80211/mlme.c +@@ -8,7 +8,7 @@ + * Copyright 2007, Michael Wu + * Copyright 2013-2014 Intel Mobile Communications GmbH + * Copyright (C) 2015 - 2017 Intel Deutschland GmbH +- * Copyright (C) 2018 - 2024 Intel Corporation ++ * Copyright (C) 2018 - 2025 Intel Corporation + */ + + #include +@@ -4579,6 +4579,8 @@ static void ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata, + auth_transaction = le16_to_cpu(mgmt->u.auth.auth_transaction); + status_code = le16_to_cpu(mgmt->u.auth.status_code); + ++ info.link_id = ifmgd->auth_data->link_id; ++ + if (auth_alg != ifmgd->auth_data->algorithm || + (auth_alg != WLAN_AUTH_SAE && + auth_transaction != ifmgd->auth_data->expected_transaction) || +-- +2.39.5 + diff --git a/queue-6.14/wifi-mac80211_hwsim-fix-mld-address-translation.patch b/queue-6.14/wifi-mac80211_hwsim-fix-mld-address-translation.patch new file mode 100644 index 0000000000..bdf7f5c67e --- /dev/null +++ b/queue-6.14/wifi-mac80211_hwsim-fix-mld-address-translation.patch @@ -0,0 +1,59 @@ +From 5b154d22631e8ffa85470a4e12712dc9474f99a8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 8 Mar 2025 23:03:34 +0200 +Subject: wifi: mac80211_hwsim: Fix MLD address translation + +From: Ilan Peer + +[ Upstream commit 65bff0be9b154621b617fc2e4bd89f1e18e97cdb ] + +Do address translations only between shared links. It is +possible that while an non-AP MLD station and an AP MLD +station have shared links, the frame is intended to be sent +on a link which is not shared (for example when sending a +probe response). + +Signed-off-by: Ilan Peer +Signed-off-by: Miri Korenblit +Link: https://patch.msgid.link/20250308225541.1aa461270bb6.Ic21592e1b1634653f02b80628cb2152f6e9de367@changeid +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/virtual/mac80211_hwsim.c | 14 ++++++++------ + 1 file changed, 8 insertions(+), 6 deletions(-) + +diff --git a/drivers/net/wireless/virtual/mac80211_hwsim.c b/drivers/net/wireless/virtual/mac80211_hwsim.c +index cf6a331d40427..a68530344d205 100644 +--- a/drivers/net/wireless/virtual/mac80211_hwsim.c ++++ b/drivers/net/wireless/virtual/mac80211_hwsim.c +@@ -4,7 +4,7 @@ + * Copyright (c) 2008, Jouni Malinen + * Copyright (c) 2011, Javier Lopez + * Copyright (c) 2016 - 2017 Intel Deutschland GmbH +- * Copyright (C) 2018 - 2024 Intel Corporation ++ * Copyright (C) 2018 - 2025 Intel Corporation + */ + + /* +@@ -1983,11 +1983,13 @@ static void mac80211_hwsim_tx(struct ieee80211_hw *hw, + return; + } + +- if (sta && sta->mlo) { +- if (WARN_ON(!link_sta)) { +- ieee80211_free_txskb(hw, skb); +- return; +- } ++ /* Do address translations only between shared links. It is ++ * possible that while an non-AP MLD station and an AP MLD ++ * station have shared links, the frame is intended to be sent ++ * on a link which is not shared (for example when sending a ++ * probe response). ++ */ ++ if (sta && sta->mlo && link_sta) { + /* address translation to link addresses on TX */ + ether_addr_copy(hdr->addr1, link_sta->addr); + ether_addr_copy(hdr->addr2, bss_conf->addr); +-- +2.39.5 + diff --git a/queue-6.14/wifi-mt76-check-link_conf-pointer-in-mt76_connac_mcu.patch b/queue-6.14/wifi-mt76-check-link_conf-pointer-in-mt76_connac_mcu.patch new file mode 100644 index 0000000000..693d43a612 --- /dev/null +++ b/queue-6.14/wifi-mt76-check-link_conf-pointer-in-mt76_connac_mcu.patch @@ -0,0 +1,36 @@ +From 3a754e58dda56cde2d97cecedeb36c91a7fc610e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 11 Mar 2025 18:45:09 +0100 +Subject: wifi: mt76: Check link_conf pointer in + mt76_connac_mcu_sta_basic_tlv() + +From: Shayne Chen + +[ Upstream commit 9890624c1b3948c1c7f1d0e19ef0bb7680b8c80d ] + +This is a preliminary patch to introduce MLO support for MT7996 driver. + +Signed-off-by: Shayne Chen +Link: https://patch.msgid.link/20250311-mt7996-mlo-v2-10-31df6972519b@kernel.org +Signed-off-by: Felix Fietkau +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c +index d0e49d68c5dbf..bafcf5a279e23 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c ++++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c +@@ -391,7 +391,7 @@ void mt76_connac_mcu_sta_basic_tlv(struct mt76_dev *dev, struct sk_buff *skb, + basic->conn_type = cpu_to_le32(CONNECTION_INFRA_BC); + + if (vif->type == NL80211_IFTYPE_STATION && +- !is_zero_ether_addr(link_conf->bssid)) { ++ link_conf && !is_zero_ether_addr(link_conf->bssid)) { + memcpy(basic->peer_addr, link_conf->bssid, ETH_ALEN); + basic->aid = cpu_to_le16(vif->cfg.aid); + } else { +-- +2.39.5 + diff --git a/queue-6.14/wifi-mt76-mt7925-fix-fails-to-enter-low-power-mode-i.patch b/queue-6.14/wifi-mt76-mt7925-fix-fails-to-enter-low-power-mode-i.patch new file mode 100644 index 0000000000..b6c3fbdf57 --- /dev/null +++ b/queue-6.14/wifi-mt76-mt7925-fix-fails-to-enter-low-power-mode-i.patch @@ -0,0 +1,44 @@ +From d22e21bf0540da69c996f1d057c4a4a145083cca Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 14 Jan 2025 13:06:22 +0800 +Subject: wifi: mt76: mt7925: fix fails to enter low power mode in suspend + state + +From: Quan Zhou + +[ Upstream commit 2d5630b0c9466ac6549495828aa7dce7424a272a ] + +The mt7925 sometimes fails to enter low power mode during suspend. +This is caused by the chip firmware sending an additional ACK event +to the host after processing the suspend command. Due to timing issues, +this event may not reach the host, causing the chip to get stuck. +To resolve this, the ACK flag in the suspend command is removed, +as it is not needed in the MT7925 architecture. This prevents the +firmware from sending the additional ACK event, ensuring the device +can reliably enter low power mode during suspend. + +Signed-off-by: Quan Zhou +Link: https://patch.msgid.link/d056938144a3a0336c3a4e3cec6f271899f32bf7.1736775666.git.quan.zhou@mediatek.com +Signed-off-by: Felix Fietkau +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/mediatek/mt76/mt7925/mcu.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c +index 87b3a88038e3c..59fa812b30d35 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c ++++ b/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c +@@ -3294,6 +3294,9 @@ int mt7925_mcu_fill_message(struct mt76_dev *mdev, struct sk_buff *skb, + else + uni_txd->option = MCU_CMD_UNI_EXT_ACK; + ++ if (cmd == MCU_UNI_CMD(HIF_CTRL)) ++ uni_txd->option &= ~MCU_CMD_ACK; ++ + goto exit; + } + +-- +2.39.5 + diff --git a/queue-6.14/wifi-mt76-mt7925-load-the-appropriate-clc-data-based.patch b/queue-6.14/wifi-mt76-mt7925-load-the-appropriate-clc-data-based.patch new file mode 100644 index 0000000000..60dfa66f27 --- /dev/null +++ b/queue-6.14/wifi-mt76-mt7925-load-the-appropriate-clc-data-based.patch @@ -0,0 +1,134 @@ +From 8f86db495561a6dc28a543fec1c0c8e2f6f4fd03 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 4 Mar 2025 19:36:44 +0800 +Subject: wifi: mt76: mt7925: load the appropriate CLC data based on hardware + type + +From: Ming Yen Hsieh + +[ Upstream commit f2027ef3f733d3f0bb7f27fa3343784058f946ab ] + +Read the EEPROM to determine the hardware type and uses this to load the +correct CLC data. + +Signed-off-by: Ming Yen Hsieh +Link: https://patch.msgid.link/20250304113649.867387-1-mingyen.hsieh@mediatek.com +Signed-off-by: Felix Fietkau +Signed-off-by: Sasha Levin +--- + .../net/wireless/mediatek/mt76/mt7925/mcu.c | 61 ++++++++++++++++++- + .../wireless/mediatek/mt76/mt7925/mt7925.h | 3 + + 2 files changed, 63 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c +index f8d45d43f7807..775ccd667dd3f 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c ++++ b/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c +@@ -631,6 +631,54 @@ int mt7925_mcu_uni_rx_ba(struct mt792x_dev *dev, + enable, false); + } + ++static int mt7925_mcu_read_eeprom(struct mt792x_dev *dev, u32 offset, u8 *val) ++{ ++ struct { ++ u8 rsv[4]; ++ ++ __le16 tag; ++ __le16 len; ++ ++ __le32 addr; ++ __le32 valid; ++ u8 data[MT7925_EEPROM_BLOCK_SIZE]; ++ } __packed req = { ++ .tag = cpu_to_le16(1), ++ .len = cpu_to_le16(sizeof(req) - 4), ++ .addr = cpu_to_le32(round_down(offset, ++ MT7925_EEPROM_BLOCK_SIZE)), ++ }; ++ struct evt { ++ u8 rsv[4]; ++ ++ __le16 tag; ++ __le16 len; ++ ++ __le32 ver; ++ __le32 addr; ++ __le32 valid; ++ __le32 size; ++ __le32 magic_num; ++ __le32 type; ++ __le32 rsv1[4]; ++ u8 data[32]; ++ } __packed *res; ++ struct sk_buff *skb; ++ int ret; ++ ++ ret = mt76_mcu_send_and_get_msg(&dev->mt76, MCU_WM_UNI_CMD_QUERY(EFUSE_CTRL), ++ &req, sizeof(req), true, &skb); ++ if (ret) ++ return ret; ++ ++ res = (struct evt *)skb->data; ++ *val = res->data[offset % MT7925_EEPROM_BLOCK_SIZE]; ++ ++ dev_kfree_skb(skb); ++ ++ return 0; ++} ++ + static int mt7925_load_clc(struct mt792x_dev *dev, const char *fw_name) + { + const struct mt76_connac2_fw_trailer *hdr; +@@ -639,13 +687,20 @@ static int mt7925_load_clc(struct mt792x_dev *dev, const char *fw_name) + struct mt76_dev *mdev = &dev->mt76; + struct mt792x_phy *phy = &dev->phy; + const struct firmware *fw; ++ u8 *clc_base = NULL, hw_encap = 0; + int ret, i, len, offset = 0; +- u8 *clc_base = NULL; + + if (mt7925_disable_clc || + mt76_is_usb(&dev->mt76)) + return 0; + ++ if (mt76_is_mmio(&dev->mt76)) { ++ ret = mt7925_mcu_read_eeprom(dev, MT_EE_HW_TYPE, &hw_encap); ++ if (ret) ++ return ret; ++ hw_encap = u8_get_bits(hw_encap, MT_EE_HW_TYPE_ENCAP); ++ } ++ + ret = request_firmware(&fw, fw_name, mdev->dev); + if (ret) + return ret; +@@ -690,6 +745,10 @@ static int mt7925_load_clc(struct mt792x_dev *dev, const char *fw_name) + if (phy->clc[clc->idx]) + continue; + ++ /* header content sanity */ ++ if (u8_get_bits(clc->type, MT_EE_HW_TYPE_ENCAP) != hw_encap) ++ continue; ++ + phy->clc[clc->idx] = devm_kmemdup(mdev->dev, clc, + le32_to_cpu(clc->len), + GFP_KERNEL); +diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/mt7925.h b/drivers/net/wireless/mediatek/mt76/mt7925/mt7925.h +index cb7b1a49fbd14..073e433069e0e 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7925/mt7925.h ++++ b/drivers/net/wireless/mediatek/mt76/mt7925/mt7925.h +@@ -167,9 +167,12 @@ enum mt7925_eeprom_field { + MT_EE_CHIP_ID = 0x000, + MT_EE_VERSION = 0x002, + MT_EE_MAC_ADDR = 0x004, ++ MT_EE_HW_TYPE = 0xa71, + __MT_EE_MAX = 0x9ff + }; + ++#define MT_EE_HW_TYPE_ENCAP GENMASK(1, 0) ++ + enum { + TXPWR_USER, + TXPWR_EEPROM, +-- +2.39.5 + diff --git a/queue-6.14/wifi-mt76-mt7925-simplify-hif-suspend-handling-to-av.patch b/queue-6.14/wifi-mt76-mt7925-simplify-hif-suspend-handling-to-av.patch new file mode 100644 index 0000000000..e8194e66c1 --- /dev/null +++ b/queue-6.14/wifi-mt76-mt7925-simplify-hif-suspend-handling-to-av.patch @@ -0,0 +1,50 @@ +From b1a1156dd8e1e1792df6dbfb9e4e409b4492af12 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 24 Feb 2025 21:05:14 +0800 +Subject: wifi: mt76: mt7925: Simplify HIF suspend handling to avoid suspend + fail + +From: Quan Zhou + +[ Upstream commit bf39813599b0375a3eebbbc6837f728554b3883a ] + +System suspend failures may occur due to inappropriate +handling of traffic not idle event by the WiFi driver. +The WiFi firmware's traffic not idle indication does +not need to be tied to suspend. Fix the flow to ensuring +the system can suspend properly. + +Signed-off-by: Quan Zhou +Link: https://patch.msgid.link/34208c7280325f57a651363d339399eb1744d3b7.1740400998.git.quan.zhou@mediatek.com +Signed-off-by: Felix Fietkau +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/mediatek/mt76/mt7925/mcu.c | 12 ++++-------- + 1 file changed, 4 insertions(+), 8 deletions(-) + +diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c +index 775ccd667dd3f..87b3a88038e3c 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c ++++ b/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c +@@ -348,14 +348,10 @@ mt7925_mcu_handle_hif_ctrl_basic(struct mt792x_dev *dev, struct tlv *tlv) + basic = (struct mt7925_mcu_hif_ctrl_basic_tlv *)tlv; + + if (basic->hifsuspend) { +- if (basic->hif_tx_traffic_status == HIF_TRAFFIC_IDLE && +- basic->hif_rx_traffic_status == HIF_TRAFFIC_IDLE) +- /* success */ +- dev->hif_idle = true; +- else +- /* busy */ +- /* invalid */ +- dev->hif_idle = false; ++ dev->hif_idle = true; ++ if (!(basic->hif_tx_traffic_status == HIF_TRAFFIC_IDLE && ++ basic->hif_rx_traffic_status == HIF_TRAFFIC_IDLE)) ++ dev_info(dev->mt76.dev, "Hif traffic not idle.\n"); + } else { + dev->hif_resumed = true; + } +-- +2.39.5 + diff --git a/queue-6.14/wifi-mt76-mt7996-fix-ser-reset-trigger-on-wed-reset.patch b/queue-6.14/wifi-mt76-mt7996-fix-ser-reset-trigger-on-wed-reset.patch new file mode 100644 index 0000000000..669e7e0624 --- /dev/null +++ b/queue-6.14/wifi-mt76-mt7996-fix-ser-reset-trigger-on-wed-reset.patch @@ -0,0 +1,51 @@ +From 3498bf5cd305661fa36d9f7298bf4dc62af0bf1c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 11 Mar 2025 11:36:39 +0100 +Subject: wifi: mt76: mt7996: fix SER reset trigger on WED reset + +From: Rex Lu + +[ Upstream commit 8d38abdf6c182225c5c0a81451fa51b7b36a635d ] + +The firmware needs a specific trigger when WED is being reset due to an +ethernet reset condition. This helps prevent further L1 SER failure. + +Signed-off-by: Rex Lu +Link: https://patch.msgid.link/20250311103646.43346-2-nbd@nbd.name +Signed-off-by: Felix Fietkau +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/mediatek/mt76/mt7996/mcu.h | 3 ++- + drivers/net/wireless/mediatek/mt76/mt7996/mmio.c | 2 +- + 2 files changed, 3 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.h +index 43468bcaffc6d..a75e1c9435bb0 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.h ++++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.h +@@ -908,7 +908,8 @@ enum { + UNI_CMD_SER_SET_RECOVER_L3_TX_DISABLE, + UNI_CMD_SER_SET_RECOVER_L3_BF, + UNI_CMD_SER_SET_RECOVER_L4_MDP, +- UNI_CMD_SER_SET_RECOVER_FULL, ++ UNI_CMD_SER_SET_RECOVER_FROM_ETH, ++ UNI_CMD_SER_SET_RECOVER_FULL = 8, + UNI_CMD_SER_SET_SYSTEM_ASSERT, + /* action */ + UNI_CMD_SER_ENABLE = 1, +diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mmio.c b/drivers/net/wireless/mediatek/mt76/mt7996/mmio.c +index 7a8ee6c75cf2b..9d37f82387464 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7996/mmio.c ++++ b/drivers/net/wireless/mediatek/mt76/mt7996/mmio.c +@@ -281,7 +281,7 @@ static int mt7996_mmio_wed_reset(struct mtk_wed_device *wed) + if (test_and_set_bit(MT76_STATE_WED_RESET, &mphy->state)) + return -EBUSY; + +- ret = mt7996_mcu_set_ser(dev, UNI_CMD_SER_TRIGGER, UNI_CMD_SER_SET_RECOVER_L1, ++ ret = mt7996_mcu_set_ser(dev, UNI_CMD_SER_TRIGGER, UNI_CMD_SER_SET_RECOVER_FROM_ETH, + mphy->band_idx); + if (ret) + goto out; +-- +2.39.5 + diff --git a/queue-6.14/wifi-mt76-mt7996-implement-driver-specific-get_txpow.patch b/queue-6.14/wifi-mt76-mt7996-implement-driver-specific-get_txpow.patch new file mode 100644 index 0000000000..e5b4a0c5aa --- /dev/null +++ b/queue-6.14/wifi-mt76-mt7996-implement-driver-specific-get_txpow.patch @@ -0,0 +1,70 @@ +From b02016da89ed93c7adcfb2c31c2deb134a872778 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 11 Mar 2025 11:36:44 +0100 +Subject: wifi: mt76: mt7996: implement driver specific get_txpower function + +From: Felix Fietkau + +[ Upstream commit 86db2c5d4ed390b97a5b455a97e2cd9c4f3eff2b ] + +Fixes reporting tx power for vifs that don't have a channel context +assigned. Report the tx power of a phy that is covered by the vif's +radio mask. + +Link: https://patch.msgid.link/20250311103646.43346-7-nbd@nbd.name +Signed-off-by: Felix Fietkau +Signed-off-by: Sasha Levin +--- + .../net/wireless/mediatek/mt76/mt7996/main.c | 29 ++++++++++++++++++- + 1 file changed, 28 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c +index 69dd565d83190..980a059b3b38f 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c ++++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c +@@ -601,6 +601,33 @@ static void mt7996_configure_filter(struct ieee80211_hw *hw, + mutex_unlock(&dev->mt76.mutex); + } + ++static int ++mt7996_get_txpower(struct ieee80211_hw *hw, struct ieee80211_vif *vif, ++ unsigned int link_id, int *dbm) ++{ ++ struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; ++ struct mt7996_phy *phy = mt7996_vif_link_phy(&mvif->deflink); ++ struct mt7996_dev *dev = mt7996_hw_dev(hw); ++ struct wireless_dev *wdev; ++ int n_chains, delta, i; ++ ++ if (!phy) { ++ wdev = ieee80211_vif_to_wdev(vif); ++ for (i = 0; i < hw->wiphy->n_radio; i++) ++ if (wdev->radio_mask & BIT(i)) ++ phy = dev->radio_phy[i]; ++ ++ if (!phy) ++ return -EINVAL; ++ } ++ ++ n_chains = hweight16(phy->mt76->chainmask); ++ delta = mt76_tx_power_nss_delta(n_chains); ++ *dbm = DIV_ROUND_UP(phy->mt76->txpower_cur + delta, 2); ++ ++ return 0; ++} ++ + static u8 + mt7996_get_rates_table(struct mt7996_phy *phy, struct ieee80211_bss_conf *conf, + bool beacon, bool mcast) +@@ -1650,7 +1677,7 @@ const struct ieee80211_ops mt7996_ops = { + .remain_on_channel = mt76_remain_on_channel, + .cancel_remain_on_channel = mt76_cancel_remain_on_channel, + .release_buffered_frames = mt76_release_buffered_frames, +- .get_txpower = mt76_get_txpower, ++ .get_txpower = mt7996_get_txpower, + .channel_switch_beacon = mt7996_channel_switch_beacon, + .get_stats = mt7996_get_stats, + .get_et_sset_count = mt7996_get_et_sset_count, +-- +2.39.5 + diff --git a/queue-6.14/wifi-mt76-mt7996-revise-txs-size.patch b/queue-6.14/wifi-mt76-mt7996-revise-txs-size.patch new file mode 100644 index 0000000000..9d9610c076 --- /dev/null +++ b/queue-6.14/wifi-mt76-mt7996-revise-txs-size.patch @@ -0,0 +1,61 @@ +From 099e34a43c61780a04e81978b1df58db50919a99 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 11 Mar 2025 11:36:38 +0100 +Subject: wifi: mt76: mt7996: revise TXS size + +From: Benjamin Lin + +[ Upstream commit 593c829b4326f7b3b15a69e97c9044ecbad3c319 ] + +Size of MPDU/PPDU TXS is 12 DWs. +In mt7996/mt7992, last 4 DWs are reserved, so TXS size was mistakenly +considered to be 8 DWs. However, in mt7990, 9th DW of TXS starts to be used. + +Signed-off-by: Benjamin Lin +Link: https://patch.msgid.link/20250311103646.43346-1-nbd@nbd.name +Signed-off-by: Felix Fietkau +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.h | 3 +++ + drivers/net/wireless/mediatek/mt76/mt7996/mac.c | 4 ++-- + 2 files changed, 5 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.h b/drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.h +index db0c29e65185c..487ad716f872a 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.h ++++ b/drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.h +@@ -314,6 +314,9 @@ enum tx_frag_idx { + #define MT_TXFREE_INFO_COUNT GENMASK(27, 24) + #define MT_TXFREE_INFO_STAT GENMASK(29, 28) + ++#define MT_TXS_HDR_SIZE 4 /* Unit: DW */ ++#define MT_TXS_SIZE 12 /* Unit: DW */ ++ + #define MT_TXS0_BW GENMASK(31, 29) + #define MT_TXS0_TID GENMASK(28, 26) + #define MT_TXS0_AMPDU BIT(25) +diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c +index 88f9d9059d5f2..c7e8336027334 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c ++++ b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c +@@ -1413,7 +1413,7 @@ bool mt7996_rx_check(struct mt76_dev *mdev, void *data, int len) + mt7996_mac_tx_free(dev, data, len); + return false; + case PKT_TYPE_TXS: +- for (rxd += 4; rxd + 8 <= end; rxd += 8) ++ for (rxd += MT_TXS_HDR_SIZE; rxd + MT_TXS_SIZE <= end; rxd += MT_TXS_SIZE) + mt7996_mac_add_txs(dev, rxd); + return false; + case PKT_TYPE_RX_FW_MONITOR: +@@ -1456,7 +1456,7 @@ void mt7996_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q, + mt7996_mcu_rx_event(dev, skb); + break; + case PKT_TYPE_TXS: +- for (rxd += 4; rxd + 8 <= end; rxd += 8) ++ for (rxd += MT_TXS_HDR_SIZE; rxd + MT_TXS_SIZE <= end; rxd += MT_TXS_SIZE) + mt7996_mac_add_txs(dev, rxd); + dev_kfree_skb(skb); + break; +-- +2.39.5 + diff --git a/queue-6.14/wifi-mt76-mt7996-use-the-correct-vif-link-for-scanni.patch b/queue-6.14/wifi-mt76-mt7996-use-the-correct-vif-link-for-scanni.patch new file mode 100644 index 0000000000..ee78a81160 --- /dev/null +++ b/queue-6.14/wifi-mt76-mt7996-use-the-correct-vif-link-for-scanni.patch @@ -0,0 +1,108 @@ +From c10cbc1ce1d39894ba4a550d8dc441882c2a0ea7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 11 Mar 2025 11:36:42 +0100 +Subject: wifi: mt76: mt7996: use the correct vif link for scanning/roc + +From: Felix Fietkau + +[ Upstream commit 13b4c81083cc4b59fb639a511c0a9a7c38efde7e ] + +Use the newly added offchannel_link pointer in vif data + +Link: https://patch.msgid.link/20250311103646.43346-5-nbd@nbd.name +Signed-off-by: Felix Fietkau +Signed-off-by: Sasha Levin +--- + .../net/wireless/mediatek/mt76/mt7996/mac.c | 40 +++++++++++++------ + .../net/wireless/mediatek/mt76/mt7996/main.c | 1 + + 2 files changed, 28 insertions(+), 13 deletions(-) + +diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c +index 019c925ae600e..88f9d9059d5f2 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c ++++ b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c +@@ -832,7 +832,8 @@ void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi, + u8 band_idx = (info->hw_queue & MT_TX_HW_QUEUE_PHY) >> 2; + u8 p_fmt, q_idx, omac_idx = 0, wmm_idx = 0; + bool is_8023 = info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP; +- struct mt76_vif_link *mvif; ++ struct mt76_vif_link *mlink = NULL; ++ struct mt7996_vif *mvif; + u16 tx_count = 15; + u32 val; + bool inband_disc = !!(changed & (BSS_CHANGED_UNSOL_BCAST_PROBE_RESP | +@@ -840,11 +841,18 @@ void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi, + bool beacon = !!(changed & (BSS_CHANGED_BEACON | + BSS_CHANGED_BEACON_ENABLED)) && (!inband_disc); + +- mvif = vif ? (struct mt76_vif_link *)vif->drv_priv : NULL; +- if (mvif) { +- omac_idx = mvif->omac_idx; +- wmm_idx = mvif->wmm_idx; +- band_idx = mvif->band_idx; ++ if (vif) { ++ mvif = (struct mt7996_vif *)vif->drv_priv; ++ if (wcid->offchannel) ++ mlink = rcu_dereference(mvif->mt76.offchannel_link); ++ if (!mlink) ++ mlink = &mvif->deflink.mt76; ++ } ++ ++ if (mlink) { ++ omac_idx = mlink->omac_idx; ++ wmm_idx = mlink->wmm_idx; ++ band_idx = mlink->band_idx; + } + + if (inband_disc) { +@@ -910,13 +918,13 @@ void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi, + is_multicast_ether_addr(hdr->addr1); + u8 idx = MT7996_BASIC_RATES_TBL; + +- if (mvif) { +- if (mcast && mvif->mcast_rates_idx) +- idx = mvif->mcast_rates_idx; +- else if (beacon && mvif->beacon_rates_idx) +- idx = mvif->beacon_rates_idx; ++ if (mlink) { ++ if (mcast && mlink->mcast_rates_idx) ++ idx = mlink->mcast_rates_idx; ++ else if (beacon && mlink->beacon_rates_idx) ++ idx = mlink->beacon_rates_idx; + else +- idx = mvif->basic_rates_idx; ++ idx = mlink->basic_rates_idx; + } + + val = FIELD_PREP(MT_TXD6_TX_RATE, idx) | MT_TXD6_FIXED_BW; +@@ -984,8 +992,14 @@ int mt7996_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, + + if (vif) { + struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; ++ struct mt76_vif_link *mlink = NULL; ++ ++ if (wcid->offchannel) ++ mlink = rcu_dereference(mvif->mt76.offchannel_link); ++ if (!mlink) ++ mlink = &mvif->deflink.mt76; + +- txp->fw.bss_idx = mvif->deflink.mt76.idx; ++ txp->fw.bss_idx = mlink->idx; + } + + txp->fw.token = cpu_to_le16(id); +diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c +index 980a059b3b38f..b01cc7ef47999 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c ++++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c +@@ -249,6 +249,7 @@ int mt7996_vif_link_add(struct mt76_phy *mphy, struct ieee80211_vif *vif, + mlink->band_idx = band_idx; + mlink->wmm_idx = vif->type == NL80211_IFTYPE_AP ? 0 : 3; + mlink->wcid = &link->sta.wcid; ++ mlink->wcid->offchannel = mlink->offchannel; + + ret = mt7996_mcu_add_dev_info(phy, vif, link_conf, mlink, true); + if (ret) +-- +2.39.5 + diff --git a/queue-6.14/wifi-mt76-only-mark-tx-status-failed-frames-as-acked.patch b/queue-6.14/wifi-mt76-only-mark-tx-status-failed-frames-as-acked.patch new file mode 100644 index 0000000000..f0c6434856 --- /dev/null +++ b/queue-6.14/wifi-mt76-only-mark-tx-status-failed-frames-as-acked.patch @@ -0,0 +1,111 @@ +From 9442374e73b8bf9ee5bb6755ca564fddc5c6d973 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 11 Mar 2025 11:36:43 +0100 +Subject: wifi: mt76: only mark tx-status-failed frames as ACKed on mt76x0/2 + +From: Felix Fietkau + +[ Upstream commit 0c5a89ceddc1728a40cb3313948401dd70e3c649 ] + +The interrupt status polling is unreliable, which can cause status events +to get lost. On all newer chips, txs-timeout is an indication that the +packet was either never sent, or never acked. +Fixes issues with inactivity polling. + +Link: https://patch.msgid.link/20250311103646.43346-6-nbd@nbd.name +Signed-off-by: Felix Fietkau +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/mediatek/mt76/mt76.h | 1 + + drivers/net/wireless/mediatek/mt76/mt76x0/pci.c | 3 ++- + drivers/net/wireless/mediatek/mt76/mt76x0/usb.c | 3 ++- + drivers/net/wireless/mediatek/mt76/mt76x2/pci.c | 3 ++- + drivers/net/wireless/mediatek/mt76/mt76x2/usb.c | 3 ++- + drivers/net/wireless/mediatek/mt76/tx.c | 3 ++- + 6 files changed, 11 insertions(+), 5 deletions(-) + +diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h +index 05651efb549ec..8714418f3906c 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt76.h ++++ b/drivers/net/wireless/mediatek/mt76/mt76.h +@@ -491,6 +491,7 @@ struct mt76_hw_cap { + #define MT_DRV_RX_DMA_HDR BIT(3) + #define MT_DRV_HW_MGMT_TXQ BIT(4) + #define MT_DRV_AMSDU_OFFLOAD BIT(5) ++#define MT_DRV_IGNORE_TXS_FAILED BIT(6) + + struct mt76_driver_ops { + u32 drv_flags; +diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c b/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c +index b456ccd00d581..11c16d1fc70fc 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c ++++ b/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c +@@ -156,7 +156,8 @@ mt76x0e_probe(struct pci_dev *pdev, const struct pci_device_id *id) + static const struct mt76_driver_ops drv_ops = { + .txwi_size = sizeof(struct mt76x02_txwi), + .drv_flags = MT_DRV_TX_ALIGNED4_SKBS | +- MT_DRV_SW_RX_AIRTIME, ++ MT_DRV_SW_RX_AIRTIME | ++ MT_DRV_IGNORE_TXS_FAILED, + .survey_flags = SURVEY_INFO_TIME_TX, + .update_survey = mt76x02_update_channel, + .set_channel = mt76x0_set_channel, +diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c b/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c +index b031c500b7415..90e5666c0857d 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c ++++ b/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c +@@ -214,7 +214,8 @@ static int mt76x0u_probe(struct usb_interface *usb_intf, + const struct usb_device_id *id) + { + static const struct mt76_driver_ops drv_ops = { +- .drv_flags = MT_DRV_SW_RX_AIRTIME, ++ .drv_flags = MT_DRV_SW_RX_AIRTIME | ++ MT_DRV_IGNORE_TXS_FAILED, + .survey_flags = SURVEY_INFO_TIME_TX, + .update_survey = mt76x02_update_channel, + .set_channel = mt76x0_set_channel, +diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/pci.c b/drivers/net/wireless/mediatek/mt76/mt76x2/pci.c +index 727bfdd00b400..2303019670e2c 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt76x2/pci.c ++++ b/drivers/net/wireless/mediatek/mt76/mt76x2/pci.c +@@ -22,7 +22,8 @@ mt76x2e_probe(struct pci_dev *pdev, const struct pci_device_id *id) + static const struct mt76_driver_ops drv_ops = { + .txwi_size = sizeof(struct mt76x02_txwi), + .drv_flags = MT_DRV_TX_ALIGNED4_SKBS | +- MT_DRV_SW_RX_AIRTIME, ++ MT_DRV_SW_RX_AIRTIME | ++ MT_DRV_IGNORE_TXS_FAILED, + .survey_flags = SURVEY_INFO_TIME_TX, + .update_survey = mt76x02_update_channel, + .set_channel = mt76x2e_set_channel, +diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c +index a4f4d12f904e7..84ef80ab4afbf 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c ++++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c +@@ -30,7 +30,8 @@ static int mt76x2u_probe(struct usb_interface *intf, + const struct usb_device_id *id) + { + static const struct mt76_driver_ops drv_ops = { +- .drv_flags = MT_DRV_SW_RX_AIRTIME, ++ .drv_flags = MT_DRV_SW_RX_AIRTIME | ++ MT_DRV_IGNORE_TXS_FAILED, + .survey_flags = SURVEY_INFO_TIME_TX, + .update_survey = mt76x02_update_channel, + .set_channel = mt76x2u_set_channel, +diff --git a/drivers/net/wireless/mediatek/mt76/tx.c b/drivers/net/wireless/mediatek/mt76/tx.c +index af0c50c983ec1..513916469ca2f 100644 +--- a/drivers/net/wireless/mediatek/mt76/tx.c ++++ b/drivers/net/wireless/mediatek/mt76/tx.c +@@ -100,7 +100,8 @@ __mt76_tx_status_skb_done(struct mt76_dev *dev, struct sk_buff *skb, u8 flags, + return; + + /* Tx status can be unreliable. if it fails, mark the frame as ACKed */ +- if (flags & MT_TX_CB_TXS_FAILED) { ++ if (flags & MT_TX_CB_TXS_FAILED && ++ (dev->drv->drv_flags & MT_DRV_IGNORE_TXS_FAILED)) { + info->status.rates[0].count = 0; + info->status.rates[0].idx = -1; + info->flags |= IEEE80211_TX_STAT_ACK; +-- +2.39.5 + diff --git a/queue-6.14/wifi-mt76-scan-fix-setting-tx_info-fields.patch b/queue-6.14/wifi-mt76-scan-fix-setting-tx_info-fields.patch new file mode 100644 index 0000000000..47a80e5fa9 --- /dev/null +++ b/queue-6.14/wifi-mt76-scan-fix-setting-tx_info-fields.patch @@ -0,0 +1,62 @@ +From c90044c4daacf819ca458ecee6795950faf356cb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 11 Mar 2025 11:36:45 +0100 +Subject: wifi: mt76: scan: fix setting tx_info fields + +From: Felix Fietkau + +[ Upstream commit 5b5f1ca9ce73ab6c35e5cd3348f8432ba190d7f4 ] + +ieee80211_tx_prepare_skb initializes the skb cb, so fields need to be set +afterwards. + +Link: https://patch.msgid.link/20250311103646.43346-8-nbd@nbd.name +Signed-off-by: Felix Fietkau +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/mediatek/mt76/scan.c | 21 +++++++++++++-------- + 1 file changed, 13 insertions(+), 8 deletions(-) + +diff --git a/drivers/net/wireless/mediatek/mt76/scan.c b/drivers/net/wireless/mediatek/mt76/scan.c +index 1c4f9deaaada5..9b20ccbeb8cf1 100644 +--- a/drivers/net/wireless/mediatek/mt76/scan.c ++++ b/drivers/net/wireless/mediatek/mt76/scan.c +@@ -52,11 +52,6 @@ mt76_scan_send_probe(struct mt76_dev *dev, struct cfg80211_ssid *ssid) + ether_addr_copy(hdr->addr3, req->bssid); + } + +- info = IEEE80211_SKB_CB(skb); +- if (req->no_cck) +- info->flags |= IEEE80211_TX_CTL_NO_CCK_RATE; +- info->control.flags |= IEEE80211_TX_CTRL_DONT_USE_RATE_MASK; +- + if (req->ie_len) + skb_put_data(skb, req->ie, req->ie_len); + +@@ -64,10 +59,20 @@ mt76_scan_send_probe(struct mt76_dev *dev, struct cfg80211_ssid *ssid) + skb_set_queue_mapping(skb, IEEE80211_AC_VO); + + rcu_read_lock(); +- if (ieee80211_tx_prepare_skb(phy->hw, vif, skb, band, NULL)) +- mt76_tx(phy, NULL, mvif->wcid, skb); +- else ++ ++ if (!ieee80211_tx_prepare_skb(phy->hw, vif, skb, band, NULL)) { + ieee80211_free_txskb(phy->hw, skb); ++ goto out; ++ } ++ ++ info = IEEE80211_SKB_CB(skb); ++ if (req->no_cck) ++ info->flags |= IEEE80211_TX_CTL_NO_CCK_RATE; ++ info->control.flags |= IEEE80211_TX_CTRL_DONT_USE_RATE_MASK; ++ ++ mt76_tx(phy, NULL, mvif->wcid, skb); ++ ++out: + rcu_read_unlock(); + } + +-- +2.39.5 + diff --git a/queue-6.14/wifi-mt76-scan-set-vif-offchannel-link-for-scanning-.patch b/queue-6.14/wifi-mt76-scan-set-vif-offchannel-link-for-scanning-.patch new file mode 100644 index 0000000000..86eb0f8c91 --- /dev/null +++ b/queue-6.14/wifi-mt76-scan-set-vif-offchannel-link-for-scanning-.patch @@ -0,0 +1,67 @@ +From ff7359618d15d367f16391050eace589235a5c08 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 11 Mar 2025 11:36:41 +0100 +Subject: wifi: mt76: scan: set vif offchannel link for scanning/roc + +From: Felix Fietkau + +[ Upstream commit 3ba20af886d1f604dceeb4d4c8ff872e2c4e885e ] + +The driver needs to know what vif link to use + +Link: https://patch.msgid.link/20250311103646.43346-4-nbd@nbd.name +Signed-off-by: Felix Fietkau +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/mediatek/mt76/channel.c | 3 +++ + drivers/net/wireless/mediatek/mt76/mt76.h | 2 ++ + 2 files changed, 5 insertions(+) + +diff --git a/drivers/net/wireless/mediatek/mt76/channel.c b/drivers/net/wireless/mediatek/mt76/channel.c +index 6a35c6ebd823e..e7b839e742903 100644 +--- a/drivers/net/wireless/mediatek/mt76/channel.c ++++ b/drivers/net/wireless/mediatek/mt76/channel.c +@@ -293,6 +293,7 @@ struct mt76_vif_link *mt76_get_vif_phy_link(struct mt76_phy *phy, + kfree(mlink); + return ERR_PTR(ret); + } ++ rcu_assign_pointer(mvif->offchannel_link, mlink); + + return mlink; + } +@@ -301,10 +302,12 @@ void mt76_put_vif_phy_link(struct mt76_phy *phy, struct ieee80211_vif *vif, + struct mt76_vif_link *mlink) + { + struct mt76_dev *dev = phy->dev; ++ struct mt76_vif_data *mvif = mlink->mvif; + + if (IS_ERR_OR_NULL(mlink) || !mlink->offchannel) + return; + ++ rcu_assign_pointer(mvif->offchannel_link, NULL); + dev->drv->vif_link_remove(phy, vif, &vif->bss_conf, mlink); + kfree(mlink); + } +diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h +index 8714418f3906c..e4ecd9cde36dc 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt76.h ++++ b/drivers/net/wireless/mediatek/mt76/mt76.h +@@ -351,6 +351,7 @@ struct mt76_wcid { + u8 hw_key_idx; + u8 hw_key_idx2; + ++ u8 offchannel:1; + u8 sta:1; + u8 sta_disabled:1; + u8 amsdu:1; +@@ -788,6 +789,7 @@ struct mt76_vif_link { + + struct mt76_vif_data { + struct mt76_vif_link __rcu *link[IEEE80211_MLD_MAX_NUM_LINKS]; ++ struct mt76_vif_link __rcu *offchannel_link; + + struct mt76_phy *roc_phy; + u16 valid_links; +-- +2.39.5 + diff --git a/queue-6.14/wifi-mwifiex-fix-ht40-bandwidth-issue.patch b/queue-6.14/wifi-mwifiex-fix-ht40-bandwidth-issue.patch new file mode 100644 index 0000000000..d52363dc84 --- /dev/null +++ b/queue-6.14/wifi-mwifiex-fix-ht40-bandwidth-issue.patch @@ -0,0 +1,47 @@ +From 2f33f5362fcd6504d5520f0df42994255ecab9a0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 14 Mar 2025 17:42:38 +0800 +Subject: wifi: mwifiex: Fix HT40 bandwidth issue. + +From: Jeff Chen + +[ Upstream commit 4fcfcbe457349267fe048524078e8970807c1a5b ] + +This patch addresses an issue where, despite the AP supporting 40MHz +bandwidth, the connection was limited to 20MHz. Without this fix, +even if the access point supports 40MHz, the bandwidth after +connection remains at 20MHz. This issue is not a regression. + +Signed-off-by: Jeff Chen +Reviewed-by: Francesco Dolcini +Link: https://patch.msgid.link/20250314094238.2097341-1-jeff.chen_1@nxp.com +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/marvell/mwifiex/11n.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/wireless/marvell/mwifiex/11n.c b/drivers/net/wireless/marvell/mwifiex/11n.c +index 66f0f5377ac18..738bafc3749b0 100644 +--- a/drivers/net/wireless/marvell/mwifiex/11n.c ++++ b/drivers/net/wireless/marvell/mwifiex/11n.c +@@ -403,12 +403,14 @@ mwifiex_cmd_append_11n_tlv(struct mwifiex_private *priv, + + if (sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40 && + bss_desc->bcn_ht_oper->ht_param & +- IEEE80211_HT_PARAM_CHAN_WIDTH_ANY) ++ IEEE80211_HT_PARAM_CHAN_WIDTH_ANY) { ++ chan_list->chan_scan_param[0].radio_type |= ++ CHAN_BW_40MHZ << 2; + SET_SECONDARYCHAN(chan_list->chan_scan_param[0]. + radio_type, + (bss_desc->bcn_ht_oper->ht_param & + IEEE80211_HT_PARAM_CHA_SEC_OFFSET)); +- ++ } + *buffer += struct_size(chan_list, chan_scan_param, 1); + ret_len += struct_size(chan_list, chan_scan_param, 1); + } +-- +2.39.5 + diff --git a/queue-6.14/wifi-rtl8xxxu-retry-firmware-download-on-error.patch b/queue-6.14/wifi-rtl8xxxu-retry-firmware-download-on-error.patch new file mode 100644 index 0000000000..2be26670b6 --- /dev/null +++ b/queue-6.14/wifi-rtl8xxxu-retry-firmware-download-on-error.patch @@ -0,0 +1,67 @@ +From 716608dbfef5f999bdbcd0d7e0e1df04db17e2ac Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 27 Jan 2025 20:48:28 +0100 +Subject: wifi: rtl8xxxu: retry firmware download on error + +From: Soeren Moch + +[ Upstream commit 3d3e28feca7ac8c6cf2a390dbbe1f97e3feb7f36 ] + +Occasionally there is an EPROTO error during firmware download. +This error is converted to EAGAIN in the download function. +But nobody tries again and so device probe fails. + +Implement download retry to fix this. + +This error was observed (and fix tested) on a tbs2910 board [1] +with an embedded RTL8188EU (0bda:8179) device behind a USB hub. + +[1] arch/arm/boot/dts/nxp/imx/imx6q-tbs2910.dts + +Signed-off-by: Soeren Moch +Acked-by: Ping-Ke Shih +Signed-off-by: Ping-Ke Shih +Link: https://patch.msgid.link/20250127194828.599379-1-smoch@web.de +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/realtek/rtl8xxxu/core.c | 17 ++++++++++++----- + 1 file changed, 12 insertions(+), 5 deletions(-) + +diff --git a/drivers/net/wireless/realtek/rtl8xxxu/core.c b/drivers/net/wireless/realtek/rtl8xxxu/core.c +index 4ce0c05c51291..569856ca677f6 100644 +--- a/drivers/net/wireless/realtek/rtl8xxxu/core.c ++++ b/drivers/net/wireless/realtek/rtl8xxxu/core.c +@@ -860,9 +860,10 @@ rtl8xxxu_writeN(struct rtl8xxxu_priv *priv, u16 addr, u8 *buf, u16 len) + return len; + + write_error: +- dev_info(&udev->dev, +- "%s: Failed to write block at addr: %04x size: %04x\n", +- __func__, addr, blocksize); ++ if (rtl8xxxu_debug & RTL8XXXU_DEBUG_REG_WRITE) ++ dev_info(&udev->dev, ++ "%s: Failed to write block at addr: %04x size: %04x\n", ++ __func__, addr, blocksize); + return -EAGAIN; + } + +@@ -4064,8 +4065,14 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw) + */ + rtl8xxxu_write16(priv, REG_TRXFF_BNDY + 2, fops->trxff_boundary); + +- ret = rtl8xxxu_download_firmware(priv); +- dev_dbg(dev, "%s: download_firmware %i\n", __func__, ret); ++ for (int retry = 5; retry >= 0 ; retry--) { ++ ret = rtl8xxxu_download_firmware(priv); ++ dev_dbg(dev, "%s: download_firmware %i\n", __func__, ret); ++ if (ret != -EAGAIN) ++ break; ++ if (retry) ++ dev_dbg(dev, "%s: retry firmware download\n", __func__); ++ } + if (ret) + goto exit; + ret = rtl8xxxu_start_firmware(priv); +-- +2.39.5 + diff --git a/queue-6.14/wifi-rtw88-don-t-use-static-local-variable-in-rtw882.patch b/queue-6.14/wifi-rtw88-don-t-use-static-local-variable-in-rtw882.patch new file mode 100644 index 0000000000..f850f917e1 --- /dev/null +++ b/queue-6.14/wifi-rtw88-don-t-use-static-local-variable-in-rtw882.patch @@ -0,0 +1,78 @@ +From cc1c37af7f080402b6e737231cdcf94a0b1533f6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 26 Jan 2025 16:03:11 +0200 +Subject: wifi: rtw88: Don't use static local variable in + rtw8822b_set_tx_power_index_by_rate + +From: Bitterblue Smith + +[ Upstream commit 00451eb3bec763f708e7e58326468c1e575e5a66 ] + +Some users want to plug two identical USB devices at the same time. +This static variable could theoretically cause them to use incorrect +TX power values. + +Move the variable to the caller and pass a pointer to it to +rtw8822b_set_tx_power_index_by_rate(). + +Signed-off-by: Bitterblue Smith +Acked-by: Ping-Ke Shih +Signed-off-by: Ping-Ke Shih +Link: https://patch.msgid.link/8a60f581-0ab5-4d98-a97d-dd83b605008f@gmail.com +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/realtek/rtw88/rtw8822b.c | 14 ++++++++------ + 1 file changed, 8 insertions(+), 6 deletions(-) + +diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822b.c b/drivers/net/wireless/realtek/rtw88/rtw8822b.c +index 7f03903ddf4bb..23a29019752da 100644 +--- a/drivers/net/wireless/realtek/rtw88/rtw8822b.c ++++ b/drivers/net/wireless/realtek/rtw88/rtw8822b.c +@@ -935,11 +935,11 @@ static void query_phy_status(struct rtw_dev *rtwdev, u8 *phy_status, + } + + static void +-rtw8822b_set_tx_power_index_by_rate(struct rtw_dev *rtwdev, u8 path, u8 rs) ++rtw8822b_set_tx_power_index_by_rate(struct rtw_dev *rtwdev, u8 path, ++ u8 rs, u32 *phy_pwr_idx) + { + struct rtw_hal *hal = &rtwdev->hal; + static const u32 offset_txagc[2] = {0x1d00, 0x1d80}; +- static u32 phy_pwr_idx; + u8 rate, rate_idx, pwr_index, shift; + int j; + +@@ -947,12 +947,12 @@ rtw8822b_set_tx_power_index_by_rate(struct rtw_dev *rtwdev, u8 path, u8 rs) + rate = rtw_rate_section[rs][j]; + pwr_index = hal->tx_pwr_tbl[path][rate]; + shift = rate & 0x3; +- phy_pwr_idx |= ((u32)pwr_index << (shift * 8)); ++ *phy_pwr_idx |= ((u32)pwr_index << (shift * 8)); + if (shift == 0x3) { + rate_idx = rate & 0xfc; + rtw_write32(rtwdev, offset_txagc[path] + rate_idx, +- phy_pwr_idx); +- phy_pwr_idx = 0; ++ *phy_pwr_idx); ++ *phy_pwr_idx = 0; + } + } + } +@@ -960,11 +960,13 @@ rtw8822b_set_tx_power_index_by_rate(struct rtw_dev *rtwdev, u8 path, u8 rs) + static void rtw8822b_set_tx_power_index(struct rtw_dev *rtwdev) + { + struct rtw_hal *hal = &rtwdev->hal; ++ u32 phy_pwr_idx = 0; + int rs, path; + + for (path = 0; path < hal->rf_path_num; path++) { + for (rs = 0; rs < RTW_RATE_SECTION_MAX; rs++) +- rtw8822b_set_tx_power_index_by_rate(rtwdev, path, rs); ++ rtw8822b_set_tx_power_index_by_rate(rtwdev, path, rs, ++ &phy_pwr_idx); + } + } + +-- +2.39.5 + diff --git a/queue-6.14/wifi-rtw88-extend-rtw_fw_send_ra_info-for-rtl8814au.patch b/queue-6.14/wifi-rtw88-extend-rtw_fw_send_ra_info-for-rtl8814au.patch new file mode 100644 index 0000000000..4fb49d4d3b --- /dev/null +++ b/queue-6.14/wifi-rtw88-extend-rtw_fw_send_ra_info-for-rtl8814au.patch @@ -0,0 +1,84 @@ +From 5ee42fcba174ed54dd27165c2f558beebe3fbd83 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 4 Feb 2025 20:39:29 +0200 +Subject: wifi: rtw88: Extend rtw_fw_send_ra_info() for RTL8814AU + +From: Bitterblue Smith + +[ Upstream commit 8f0076726b66a70727a1bef5c087c60291e90ad8 ] + +The existing code is suitable for chips with up to 2 spatial streams. +Inform the firmware about the rates it's allowed to use when +transmitting 3 spatial streams. + +Signed-off-by: Bitterblue Smith +Acked-by: Ping-Ke Shih +Signed-off-by: Ping-Ke Shih +Link: https://patch.msgid.link/08e2f328-1aab-4e50-93ac-c1e5dd9541ac@gmail.com +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/realtek/rtw88/fw.c | 15 +++++++++++++++ + drivers/net/wireless/realtek/rtw88/fw.h | 1 + + drivers/net/wireless/realtek/rtw88/main.h | 1 + + 3 files changed, 17 insertions(+) + +diff --git a/drivers/net/wireless/realtek/rtw88/fw.c b/drivers/net/wireless/realtek/rtw88/fw.c +index 02389b7c68768..6b563ac489a74 100644 +--- a/drivers/net/wireless/realtek/rtw88/fw.c ++++ b/drivers/net/wireless/realtek/rtw88/fw.c +@@ -735,6 +735,7 @@ void rtw_fw_send_ra_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si, + { + u8 h2c_pkt[H2C_PKT_SIZE] = {0}; + bool disable_pt = true; ++ u32 mask_hi; + + SET_H2C_CMD_ID_CLASS(h2c_pkt, H2C_CMD_RA_INFO); + +@@ -755,6 +756,20 @@ void rtw_fw_send_ra_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si, + si->init_ra_lv = 0; + + rtw_fw_send_h2c_command(rtwdev, h2c_pkt); ++ ++ if (rtwdev->chip->id != RTW_CHIP_TYPE_8814A) ++ return; ++ ++ SET_H2C_CMD_ID_CLASS(h2c_pkt, H2C_CMD_RA_INFO_HI); ++ ++ mask_hi = si->ra_mask >> 32; ++ ++ SET_RA_INFO_RA_MASK0(h2c_pkt, (mask_hi & 0xff)); ++ SET_RA_INFO_RA_MASK1(h2c_pkt, (mask_hi & 0xff00) >> 8); ++ SET_RA_INFO_RA_MASK2(h2c_pkt, (mask_hi & 0xff0000) >> 16); ++ SET_RA_INFO_RA_MASK3(h2c_pkt, (mask_hi & 0xff000000) >> 24); ++ ++ rtw_fw_send_h2c_command(rtwdev, h2c_pkt); + } + + void rtw_fw_media_status_report(struct rtw_dev *rtwdev, u8 mac_id, bool connect) +diff --git a/drivers/net/wireless/realtek/rtw88/fw.h b/drivers/net/wireless/realtek/rtw88/fw.h +index 404de1b0c407b..48ad9ceab6ea1 100644 +--- a/drivers/net/wireless/realtek/rtw88/fw.h ++++ b/drivers/net/wireless/realtek/rtw88/fw.h +@@ -557,6 +557,7 @@ static inline void rtw_h2c_pkt_set_header(u8 *h2c_pkt, u8 sub_id) + #define H2C_CMD_DEFAULT_PORT 0x2c + #define H2C_CMD_RA_INFO 0x40 + #define H2C_CMD_RSSI_MONITOR 0x42 ++#define H2C_CMD_RA_INFO_HI 0x46 + #define H2C_CMD_BCN_FILTER_OFFLOAD_P0 0x56 + #define H2C_CMD_BCN_FILTER_OFFLOAD_P1 0x57 + #define H2C_CMD_WL_PHY_INFO 0x58 +diff --git a/drivers/net/wireless/realtek/rtw88/main.h b/drivers/net/wireless/realtek/rtw88/main.h +index 62cd4c5263019..a61ea853f98d9 100644 +--- a/drivers/net/wireless/realtek/rtw88/main.h ++++ b/drivers/net/wireless/realtek/rtw88/main.h +@@ -191,6 +191,7 @@ enum rtw_chip_type { + RTW_CHIP_TYPE_8703B, + RTW_CHIP_TYPE_8821A, + RTW_CHIP_TYPE_8812A, ++ RTW_CHIP_TYPE_8814A, + }; + + enum rtw_tx_queue_type { +-- +2.39.5 + diff --git a/queue-6.14/wifi-rtw88-fix-__rtw_download_firmware-for-rtl8814au.patch b/queue-6.14/wifi-rtw88-fix-__rtw_download_firmware-for-rtl8814au.patch new file mode 100644 index 0000000000..20f9f72f28 --- /dev/null +++ b/queue-6.14/wifi-rtw88-fix-__rtw_download_firmware-for-rtl8814au.patch @@ -0,0 +1,49 @@ +From 08ac89be7dab29283ba5921415d55955e3582085 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 4 Feb 2025 20:36:56 +0200 +Subject: wifi: rtw88: Fix __rtw_download_firmware() for RTL8814AU + +From: Bitterblue Smith + +[ Upstream commit 8425f5c8f04dbcf11ade78f984a494fc0b90e7a0 ] + +Don't call ltecoex_read_reg() and ltecoex_reg_write() when the +ltecoex_addr member of struct rtw_chip_info is NULL. The RTL8814AU +doesn't have this feature. + +Signed-off-by: Bitterblue Smith +Acked-by: Ping-Ke Shih +Signed-off-by: Ping-Ke Shih +Link: https://patch.msgid.link/55b5641f-094e-4f94-9f79-ac053733f2cf@gmail.com +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/realtek/rtw88/mac.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/wireless/realtek/rtw88/mac.c b/drivers/net/wireless/realtek/rtw88/mac.c +index ea6406df42b3d..0491f501c1383 100644 +--- a/drivers/net/wireless/realtek/rtw88/mac.c ++++ b/drivers/net/wireless/realtek/rtw88/mac.c +@@ -785,7 +785,8 @@ static int __rtw_download_firmware(struct rtw_dev *rtwdev, + if (!check_firmware_size(data, size)) + return -EINVAL; + +- if (!ltecoex_read_reg(rtwdev, 0x38, <ecoex_bckp)) ++ if (rtwdev->chip->ltecoex_addr && ++ !ltecoex_read_reg(rtwdev, 0x38, <ecoex_bckp)) + return -EBUSY; + + wlan_cpu_enable(rtwdev, false); +@@ -803,7 +804,8 @@ static int __rtw_download_firmware(struct rtw_dev *rtwdev, + + wlan_cpu_enable(rtwdev, true); + +- if (!ltecoex_reg_write(rtwdev, 0x38, ltecoex_bckp)) { ++ if (rtwdev->chip->ltecoex_addr && ++ !ltecoex_reg_write(rtwdev, 0x38, ltecoex_bckp)) { + ret = -EBUSY; + goto dlfw_fail; + } +-- +2.39.5 + diff --git a/queue-6.14/wifi-rtw88-fix-download_firmware_validate-for-rtl881.patch b/queue-6.14/wifi-rtw88-fix-download_firmware_validate-for-rtl881.patch new file mode 100644 index 0000000000..68010639dd --- /dev/null +++ b/queue-6.14/wifi-rtw88-fix-download_firmware_validate-for-rtl881.patch @@ -0,0 +1,49 @@ +From 15e97621bb90bc4e5601b10842ba9c8916a67d96 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 4 Feb 2025 20:37:36 +0200 +Subject: wifi: rtw88: Fix download_firmware_validate() for RTL8814AU + +From: Bitterblue Smith + +[ Upstream commit 9e8243025cc06abc975c876dffda052073207ab3 ] + +After the firmware is uploaded, download_firmware_validate() checks some +bits in REG_MCUFW_CTRL to see if everything went okay. The +RTL8814AU power on sequence sets bits 13 and 12 to 2, which this +function does not expect, so it thinks the firmware upload failed. + +Make download_firmware_validate() ignore bits 13 and 12. + +Signed-off-by: Bitterblue Smith +Acked-by: Ping-Ke Shih +Signed-off-by: Ping-Ke Shih +Link: https://patch.msgid.link/049d2887-22fc-47b7-9e59-62627cb525f8@gmail.com +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/realtek/rtw88/reg.h | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/realtek/rtw88/reg.h b/drivers/net/wireless/realtek/rtw88/reg.h +index e438405fba566..209b6fc08a73e 100644 +--- a/drivers/net/wireless/realtek/rtw88/reg.h ++++ b/drivers/net/wireless/realtek/rtw88/reg.h +@@ -130,6 +130,7 @@ + #define BIT_SHIFT_ROM_PGE 16 + #define BIT_FW_INIT_RDY BIT(15) + #define BIT_FW_DW_RDY BIT(14) ++#define BIT_CPU_CLK_SEL (BIT(12) | BIT(13)) + #define BIT_RPWM_TOGGLE BIT(7) + #define BIT_RAM_DL_SEL BIT(7) /* legacy only */ + #define BIT_DMEM_CHKSUM_OK BIT(6) +@@ -147,7 +148,7 @@ + BIT_CHECK_SUM_OK) + #define FW_READY_LEGACY (BIT_MCUFWDL_RDY | BIT_FWDL_CHK_RPT | \ + BIT_WINTINI_RDY | BIT_RAM_DL_SEL) +-#define FW_READY_MASK 0xffff ++#define FW_READY_MASK (0xffff & ~BIT_CPU_CLK_SEL) + + #define REG_MCU_TST_CFG 0x84 + #define VAL_FW_TRIGGER 0x1 +-- +2.39.5 + diff --git a/queue-6.14/wifi-rtw88-fix-rtw_desc_to_mcsrate-to-handle-mcs16-3.patch b/queue-6.14/wifi-rtw88-fix-rtw_desc_to_mcsrate-to-handle-mcs16-3.patch new file mode 100644 index 0000000000..5a82be1372 --- /dev/null +++ b/queue-6.14/wifi-rtw88-fix-rtw_desc_to_mcsrate-to-handle-mcs16-3.patch @@ -0,0 +1,42 @@ +From a1059fa495d749f16ad67e2f755ee66ecd3caf58 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 18 Feb 2025 01:29:52 +0200 +Subject: wifi: rtw88: Fix rtw_desc_to_mcsrate() to handle MCS16-31 + +From: Bitterblue Smith + +[ Upstream commit 86d04f8f991a0509e318fe886d5a1cf795736c7d ] + +This function translates the rate number reported by the hardware into +something mac80211 can understand. It was ignoring the 3SS and 4SS HT +rates. Translate them too. + +Also set *nss to 0 for the HT rates, just to make sure it's +initialised. + +Signed-off-by: Bitterblue Smith +Acked-by: Ping-Ke Shih +Signed-off-by: Ping-Ke Shih +Link: https://patch.msgid.link/d0a5a86b-4869-47f6-a5a7-01c0f987cc7f@gmail.com +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/realtek/rtw88/util.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/realtek/rtw88/util.c b/drivers/net/wireless/realtek/rtw88/util.c +index e222d3c01a77e..66819f6944055 100644 +--- a/drivers/net/wireless/realtek/rtw88/util.c ++++ b/drivers/net/wireless/realtek/rtw88/util.c +@@ -101,7 +101,8 @@ void rtw_desc_to_mcsrate(u16 rate, u8 *mcs, u8 *nss) + *nss = 4; + *mcs = rate - DESC_RATEVHT4SS_MCS0; + } else if (rate >= DESC_RATEMCS0 && +- rate <= DESC_RATEMCS15) { ++ rate <= DESC_RATEMCS31) { ++ *nss = 0; + *mcs = rate - DESC_RATEMCS0; + } + } +-- +2.39.5 + diff --git a/queue-6.14/wifi-rtw88-fix-rtw_init_ht_cap-for-rtl8814au.patch b/queue-6.14/wifi-rtw88-fix-rtw_init_ht_cap-for-rtl8814au.patch new file mode 100644 index 0000000000..12f712515c --- /dev/null +++ b/queue-6.14/wifi-rtw88-fix-rtw_init_ht_cap-for-rtl8814au.patch @@ -0,0 +1,59 @@ +From 6c8e3a86883193e67cf00696dafa04613db635b3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 18 Feb 2025 01:30:22 +0200 +Subject: wifi: rtw88: Fix rtw_init_ht_cap() for RTL8814AU + +From: Bitterblue Smith + +[ Upstream commit c7eea1ba05ca5b0dbf77a27cf2e1e6e2fb3c0043 ] + +Set the RX mask and the highest RX rate according to the number of +spatial streams the chip can receive. For RTL8814AU that is 3. + +Signed-off-by: Bitterblue Smith +Acked-by: Ping-Ke Shih +Signed-off-by: Ping-Ke Shih +Link: https://patch.msgid.link/4e786f50-ed1c-4387-8b28-e6ff00e35e81@gmail.com +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/realtek/rtw88/main.c | 17 ++++++----------- + 1 file changed, 6 insertions(+), 11 deletions(-) + +diff --git a/drivers/net/wireless/realtek/rtw88/main.c b/drivers/net/wireless/realtek/rtw88/main.c +index d66abb31f091b..f4ee4e922afa7 100644 +--- a/drivers/net/wireless/realtek/rtw88/main.c ++++ b/drivers/net/wireless/realtek/rtw88/main.c +@@ -1561,6 +1561,7 @@ static void rtw_init_ht_cap(struct rtw_dev *rtwdev, + { + const struct rtw_chip_info *chip = rtwdev->chip; + struct rtw_efuse *efuse = &rtwdev->efuse; ++ int i; + + ht_cap->ht_supported = true; + ht_cap->cap = 0; +@@ -1580,17 +1581,11 @@ static void rtw_init_ht_cap(struct rtw_dev *rtwdev, + ht_cap->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K; + ht_cap->ampdu_density = chip->ampdu_density; + ht_cap->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; +- if (efuse->hw_cap.nss > 1) { +- ht_cap->mcs.rx_mask[0] = 0xFF; +- ht_cap->mcs.rx_mask[1] = 0xFF; +- ht_cap->mcs.rx_mask[4] = 0x01; +- ht_cap->mcs.rx_highest = cpu_to_le16(300); +- } else { +- ht_cap->mcs.rx_mask[0] = 0xFF; +- ht_cap->mcs.rx_mask[1] = 0x00; +- ht_cap->mcs.rx_mask[4] = 0x01; +- ht_cap->mcs.rx_highest = cpu_to_le16(150); +- } ++ ++ for (i = 0; i < efuse->hw_cap.nss; i++) ++ ht_cap->mcs.rx_mask[i] = 0xFF; ++ ht_cap->mcs.rx_mask[4] = 0x01; ++ ht_cap->mcs.rx_highest = cpu_to_le16(150 * efuse->hw_cap.nss); + } + + static void rtw_init_vht_cap(struct rtw_dev *rtwdev, +-- +2.39.5 + diff --git a/queue-6.14/wifi-rtw88-fix-rtw_init_vht_cap-for-rtl8814au.patch b/queue-6.14/wifi-rtw88-fix-rtw_init_vht_cap-for-rtl8814au.patch new file mode 100644 index 0000000000..39c56a667a --- /dev/null +++ b/queue-6.14/wifi-rtw88-fix-rtw_init_vht_cap-for-rtl8814au.patch @@ -0,0 +1,68 @@ +From 74f3e0dea164fd71dc382e5c7566500b54065377 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 18 Feb 2025 01:30:48 +0200 +Subject: wifi: rtw88: Fix rtw_init_vht_cap() for RTL8814AU + +From: Bitterblue Smith + +[ Upstream commit 6be7544d19fcfcb729495e793bc6181f85bb8949 ] + +Set the MCS maps and the highest rates according to the number of +spatial streams the chip has. For RTL8814AU that is 3. + +Signed-off-by: Bitterblue Smith +Acked-by: Ping-Ke Shih +Signed-off-by: Ping-Ke Shih +Link: https://patch.msgid.link/e86aa009-b5bf-4b3a-8112-ea5e3cd49465@gmail.com +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/realtek/rtw88/main.c | 23 +++++++++-------------- + 1 file changed, 9 insertions(+), 14 deletions(-) + +diff --git a/drivers/net/wireless/realtek/rtw88/main.c b/drivers/net/wireless/realtek/rtw88/main.c +index 0cee0fd8c0ef0..d66abb31f091b 100644 +--- a/drivers/net/wireless/realtek/rtw88/main.c ++++ b/drivers/net/wireless/realtek/rtw88/main.c +@@ -1597,8 +1597,9 @@ static void rtw_init_vht_cap(struct rtw_dev *rtwdev, + struct ieee80211_sta_vht_cap *vht_cap) + { + struct rtw_efuse *efuse = &rtwdev->efuse; +- u16 mcs_map; ++ u16 mcs_map = 0; + __le16 highest; ++ int i; + + if (efuse->hw_cap.ptcl != EFUSE_HW_CAP_IGNORE && + efuse->hw_cap.ptcl != EFUSE_HW_CAP_PTCL_VHT) +@@ -1621,21 +1622,15 @@ static void rtw_init_vht_cap(struct rtw_dev *rtwdev, + if (rtw_chip_has_rx_ldpc(rtwdev)) + vht_cap->cap |= IEEE80211_VHT_CAP_RXLDPC; + +- mcs_map = IEEE80211_VHT_MCS_SUPPORT_0_9 << 0 | +- IEEE80211_VHT_MCS_NOT_SUPPORTED << 4 | +- IEEE80211_VHT_MCS_NOT_SUPPORTED << 6 | +- IEEE80211_VHT_MCS_NOT_SUPPORTED << 8 | +- IEEE80211_VHT_MCS_NOT_SUPPORTED << 10 | +- IEEE80211_VHT_MCS_NOT_SUPPORTED << 12 | +- IEEE80211_VHT_MCS_NOT_SUPPORTED << 14; +- if (efuse->hw_cap.nss > 1) { +- highest = cpu_to_le16(780); +- mcs_map |= IEEE80211_VHT_MCS_SUPPORT_0_9 << 2; +- } else { +- highest = cpu_to_le16(390); +- mcs_map |= IEEE80211_VHT_MCS_NOT_SUPPORTED << 2; ++ for (i = 0; i < 8; i++) { ++ if (i < efuse->hw_cap.nss) ++ mcs_map |= IEEE80211_VHT_MCS_SUPPORT_0_9 << (i * 2); ++ else ++ mcs_map |= IEEE80211_VHT_MCS_NOT_SUPPORTED << (i * 2); + } + ++ highest = cpu_to_le16(390 * efuse->hw_cap.nss); ++ + vht_cap->vht_mcs.rx_mcs_map = cpu_to_le16(mcs_map); + vht_cap->vht_mcs.tx_mcs_map = cpu_to_le16(mcs_map); + vht_cap->vht_mcs.rx_highest = highest; +-- +2.39.5 + diff --git a/queue-6.14/wifi-rtw88-fix-rtw_mac_power_switch-for-rtl8814au.patch b/queue-6.14/wifi-rtw88-fix-rtw_mac_power_switch-for-rtl8814au.patch new file mode 100644 index 0000000000..d8118b45d0 --- /dev/null +++ b/queue-6.14/wifi-rtw88-fix-rtw_mac_power_switch-for-rtl8814au.patch @@ -0,0 +1,37 @@ +From d3b0bba30e3237d759262225e5915aa8b4a60eae Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 18 Feb 2025 01:28:59 +0200 +Subject: wifi: rtw88: Fix rtw_mac_power_switch() for RTL8814AU + +From: Bitterblue Smith + +[ Upstream commit e66bca16638ee59e997f9d9a3711b3ae587d04d9 ] + +rtw_mac_power_switch() checks bit 8 of REG_SYS_STATUS1 to see if the +chip is powered on. This bit appears to be always on in the RTL8814AU, +so ignore it. + +Signed-off-by: Bitterblue Smith +Acked-by: Ping-Ke Shih +Signed-off-by: Ping-Ke Shih +Link: https://patch.msgid.link/2f0fcffb-3067-4d95-a68c-f2f3a5a47921@gmail.com +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/realtek/rtw88/mac.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/net/wireless/realtek/rtw88/mac.c b/drivers/net/wireless/realtek/rtw88/mac.c +index cae9cca6dca3d..ea6406df42b3d 100644 +--- a/drivers/net/wireless/realtek/rtw88/mac.c ++++ b/drivers/net/wireless/realtek/rtw88/mac.c +@@ -291,6 +291,7 @@ static int rtw_mac_power_switch(struct rtw_dev *rtwdev, bool pwr_on) + if (rtw_read8(rtwdev, REG_CR) == 0xea) + cur_pwr = false; + else if (rtw_hci_type(rtwdev) == RTW_HCI_TYPE_USB && ++ chip->id != RTW_CHIP_TYPE_8814A && + (rtw_read8(rtwdev, REG_SYS_STATUS1 + 1) & BIT(0))) + cur_pwr = false; + else +-- +2.39.5 + diff --git a/queue-6.14/wifi-rtw88-fix-rtw_update_sta_info-for-rtl8814au.patch b/queue-6.14/wifi-rtw88-fix-rtw_update_sta_info-for-rtl8814au.patch new file mode 100644 index 0000000000..01e4c0c648 --- /dev/null +++ b/queue-6.14/wifi-rtw88-fix-rtw_update_sta_info-for-rtl8814au.patch @@ -0,0 +1,71 @@ +From 447dc2002ed22c0b02a9d2aefbded524f0b70215 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 4 Feb 2025 20:42:08 +0200 +Subject: wifi: rtw88: Fix rtw_update_sta_info() for RTL8814AU + +From: Bitterblue Smith + +[ Upstream commit 9f00e2218e15a2ea3c284567424a100c10b6fb85 ] + +This function tells the firmware what rates it can use. + +Put the 3SS and 4SS HT rates supported by the other station into the +rate mask. + +Remove the 3SS and 4SS rates from the rate mask if the hardware only has +2 spatial streams. + +And finally, select the right rate ID (a parameter for the firmware) +when the hardware has 3 spatial streams. + +Signed-off-by: Bitterblue Smith +Acked-by: Ping-Ke Shih +Signed-off-by: Ping-Ke Shih +Link: https://patch.msgid.link/48d1d90f-2aeb-4ec5-9a24-0980e10eae1e@gmail.com +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/realtek/rtw88/main.c | 14 +++++++++----- + 1 file changed, 9 insertions(+), 5 deletions(-) + +diff --git a/drivers/net/wireless/realtek/rtw88/main.c b/drivers/net/wireless/realtek/rtw88/main.c +index f4ee4e922afa7..9b9e76eebce95 100644 +--- a/drivers/net/wireless/realtek/rtw88/main.c ++++ b/drivers/net/wireless/realtek/rtw88/main.c +@@ -1234,7 +1234,9 @@ void rtw_update_sta_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si, + if (sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_RXLDPC) + ldpc_en = VHT_LDPC_EN; + } else if (sta->deflink.ht_cap.ht_supported) { +- ra_mask |= (sta->deflink.ht_cap.mcs.rx_mask[1] << 20) | ++ ra_mask |= ((u64)sta->deflink.ht_cap.mcs.rx_mask[3] << 36) | ++ ((u64)sta->deflink.ht_cap.mcs.rx_mask[2] << 28) | ++ (sta->deflink.ht_cap.mcs.rx_mask[1] << 20) | + (sta->deflink.ht_cap.mcs.rx_mask[0] << 12); + if (sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_RX_STBC) + stbc_en = HT_STBC_EN; +@@ -1244,6 +1246,9 @@ void rtw_update_sta_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si, + + if (efuse->hw_cap.nss == 1 || rtwdev->hal.txrx_1ss) + ra_mask &= RA_MASK_VHT_RATES_1SS | RA_MASK_HT_RATES_1SS; ++ else if (efuse->hw_cap.nss == 2) ++ ra_mask &= RA_MASK_VHT_RATES_2SS | RA_MASK_HT_RATES_2SS | ++ RA_MASK_VHT_RATES_1SS | RA_MASK_HT_RATES_1SS; + + if (hal->current_band_type == RTW_BAND_5G) { + ra_mask |= (u64)sta->deflink.supp_rates[NL80211_BAND_5GHZ] << 4; +@@ -1302,10 +1307,9 @@ void rtw_update_sta_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si, + break; + } + +- if (sta->deflink.vht_cap.vht_supported && ra_mask & 0xffc00000) +- tx_num = 2; +- else if (sta->deflink.ht_cap.ht_supported && ra_mask & 0xfff00000) +- tx_num = 2; ++ if (sta->deflink.vht_cap.vht_supported || ++ sta->deflink.ht_cap.ht_supported) ++ tx_num = efuse->hw_cap.nss; + + rate_id = get_rate_id(wireless_set, bw_mode, tx_num); + +-- +2.39.5 + diff --git a/queue-6.14/wifi-rtw89-8922a-fix-incorrect-sta-id-in-eht-mu-ppdu.patch b/queue-6.14/wifi-rtw89-8922a-fix-incorrect-sta-id-in-eht-mu-ppdu.patch new file mode 100644 index 0000000000..84544eae4d --- /dev/null +++ b/queue-6.14/wifi-rtw89-8922a-fix-incorrect-sta-id-in-eht-mu-ppdu.patch @@ -0,0 +1,41 @@ +From eba55d0778884be93adeabbef487a4f530842ae4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Feb 2025 14:12:35 +0800 +Subject: wifi: rtw89: 8922a: fix incorrect STA-ID in EHT MU PPDU + +From: Kuan-Chung Chen + +[ Upstream commit bdce0574243b43b3bb2064f609c0c326df44c4c6 ] + +EHT MU PPDU contains user field of EHT-SIG field with STA-ID that +must match AID subfield in the Associate Response. Add a necessary +setting to prevent these from being inconsistent. + +Signed-off-by: Kuan-Chung Chen +Signed-off-by: Ping-Ke Shih +Link: https://patch.msgid.link/20250217061235.32031-1-pkshih@realtek.com +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/realtek/rtw89/fw.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c +index 92e6bc05cbf66..f4b3438615541 100644 +--- a/drivers/net/wireless/realtek/rtw89/fw.c ++++ b/drivers/net/wireless/realtek/rtw89/fw.c +@@ -3329,9 +3329,10 @@ int rtw89_fw_h2c_assoc_cmac_tbl_g7(struct rtw89_dev *rtwdev, + CCTLINFO_G7_W5_NOMINAL_PKT_PADDING3 | + CCTLINFO_G7_W5_NOMINAL_PKT_PADDING4); + +- h2c->w6 = le32_encode_bits(vif->type == NL80211_IFTYPE_STATION ? 1 : 0, ++ h2c->w6 = le32_encode_bits(vif->cfg.aid, CCTLINFO_G7_W6_AID12_PAID) | ++ le32_encode_bits(vif->type == NL80211_IFTYPE_STATION ? 1 : 0, + CCTLINFO_G7_W6_ULDL); +- h2c->m6 = cpu_to_le32(CCTLINFO_G7_W6_ULDL); ++ h2c->m6 = cpu_to_le32(CCTLINFO_G7_W6_AID12_PAID | CCTLINFO_G7_W6_ULDL); + + if (rtwsta_link) { + h2c->w8 = le32_encode_bits(link_sta->he_cap.has_he, +-- +2.39.5 + diff --git a/queue-6.14/wifi-rtw89-add-wiphy_lock-to-work-that-isn-t-held-wi.patch b/queue-6.14/wifi-rtw89-add-wiphy_lock-to-work-that-isn-t-held-wi.patch new file mode 100644 index 0000000000..f5cfcc2f21 --- /dev/null +++ b/queue-6.14/wifi-rtw89-add-wiphy_lock-to-work-that-isn-t-held-wi.patch @@ -0,0 +1,72 @@ +From 969d27cd411e02f7b2fc63449f4569ab7f9f0a1a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 22 Jan 2025 14:03:01 +0800 +Subject: wifi: rtw89: add wiphy_lock() to work that isn't held wiphy_lock() + yet + +From: Ping-Ke Shih + +[ Upstream commit ebfc9199df05d37b67f4d1b7ee997193f3d2e7c8 ] + +To ensure where are protected by driver mutex can also be protected by +wiphy_lock(), so afterward we can remove driver mutex safely. + +Signed-off-by: Ping-Ke Shih +Link: https://patch.msgid.link/20250122060310.31976-2-pkshih@realtek.com +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/realtek/rtw89/regd.c | 2 ++ + drivers/net/wireless/realtek/rtw89/ser.c | 4 ++++ + 2 files changed, 6 insertions(+) + +diff --git a/drivers/net/wireless/realtek/rtw89/regd.c b/drivers/net/wireless/realtek/rtw89/regd.c +index 80b2f74589eb9..5b8d95c90d739 100644 +--- a/drivers/net/wireless/realtek/rtw89/regd.c ++++ b/drivers/net/wireless/realtek/rtw89/regd.c +@@ -720,6 +720,7 @@ void rtw89_regd_notifier(struct wiphy *wiphy, struct regulatory_request *request + struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); + struct rtw89_dev *rtwdev = hw->priv; + ++ wiphy_lock(wiphy); + mutex_lock(&rtwdev->mutex); + rtw89_leave_ps_mode(rtwdev); + +@@ -737,6 +738,7 @@ void rtw89_regd_notifier(struct wiphy *wiphy, struct regulatory_request *request + + exit: + mutex_unlock(&rtwdev->mutex); ++ wiphy_unlock(wiphy); + } + + /* Maximum Transmit Power field (@raw) can be EIRP or PSD. +diff --git a/drivers/net/wireless/realtek/rtw89/ser.c b/drivers/net/wireless/realtek/rtw89/ser.c +index 26a944d3b6727..d0c8584308c06 100644 +--- a/drivers/net/wireless/realtek/rtw89/ser.c ++++ b/drivers/net/wireless/realtek/rtw89/ser.c +@@ -156,9 +156,11 @@ static void ser_state_run(struct rtw89_ser *ser, u8 evt) + rtw89_debug(rtwdev, RTW89_DBG_SER, "ser: %s receive %s\n", + ser_st_name(ser), ser_ev_name(ser, evt)); + ++ wiphy_lock(rtwdev->hw->wiphy); + mutex_lock(&rtwdev->mutex); + rtw89_leave_lps(rtwdev); + mutex_unlock(&rtwdev->mutex); ++ wiphy_unlock(rtwdev->hw->wiphy); + + ser->st_tbl[ser->state].st_func(ser, evt); + } +@@ -708,9 +710,11 @@ static void ser_l2_reset_st_hdl(struct rtw89_ser *ser, u8 evt) + + switch (evt) { + case SER_EV_STATE_IN: ++ wiphy_lock(rtwdev->hw->wiphy); + mutex_lock(&rtwdev->mutex); + ser_l2_reset_st_pre_hdl(ser); + mutex_unlock(&rtwdev->mutex); ++ wiphy_unlock(rtwdev->hw->wiphy); + + ieee80211_restart_hw(rtwdev->hw); + ser_set_alarm(ser, SER_RECFG_TIMEOUT, SER_EV_L2_RECFG_TIMEOUT); +-- +2.39.5 + diff --git a/queue-6.14/wifi-rtw89-call-power_on-ahead-before-selecting-firm.patch b/queue-6.14/wifi-rtw89-call-power_on-ahead-before-selecting-firm.patch new file mode 100644 index 0000000000..da7d130526 --- /dev/null +++ b/queue-6.14/wifi-rtw89-call-power_on-ahead-before-selecting-firm.patch @@ -0,0 +1,168 @@ +From c7d89529f6baa37fb22f34bbefa1d19bac9372e4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 3 Feb 2025 15:29:08 +0800 +Subject: wifi: rtw89: call power_on ahead before selecting firmware + +From: Ping-Ke Shih + +[ Upstream commit d078f5857a00c06fa0ddee26d3cb722e938e1688 ] + +Driver selects firmware by hardware version, which normally can be read +from registers before selecting firmware. However, certain chips such as +RTL8851B, it needs to read hardware version from efuse while doing +power_on, but do power_on after selecting firmware in current flow. + +To resolve this flow problem, move power_on out from +rtw89_mac_partial_init(), and call rtw89_mac_pwr_on() separately at +proper places to have expected flow. + +Signed-off-by: Ping-Ke Shih +Link: https://patch.msgid.link/20250203072911.47313-2-pkshih@realtek.com +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/realtek/rtw89/core.c | 23 +++++++++++------- + drivers/net/wireless/realtek/rtw89/mac.c | 29 ++++++++++++++++------- + drivers/net/wireless/realtek/rtw89/mac.h | 1 + + 3 files changed, 36 insertions(+), 17 deletions(-) + +diff --git a/drivers/net/wireless/realtek/rtw89/core.c b/drivers/net/wireless/realtek/rtw89/core.c +index c84446ec9e4f4..422cc3867f3bc 100644 +--- a/drivers/net/wireless/realtek/rtw89/core.c ++++ b/drivers/net/wireless/realtek/rtw89/core.c +@@ -5086,8 +5086,6 @@ static int rtw89_chip_efuse_info_setup(struct rtw89_dev *rtwdev) + + rtw89_hci_mac_pre_deinit(rtwdev); + +- rtw89_mac_pwr_off(rtwdev); +- + return 0; + } + +@@ -5168,36 +5166,45 @@ int rtw89_chip_info_setup(struct rtw89_dev *rtwdev) + + rtw89_read_chip_ver(rtwdev); + ++ ret = rtw89_mac_pwr_on(rtwdev); ++ if (ret) { ++ rtw89_err(rtwdev, "failed to power on\n"); ++ return ret; ++ } ++ + ret = rtw89_wait_firmware_completion(rtwdev); + if (ret) { + rtw89_err(rtwdev, "failed to wait firmware completion\n"); +- return ret; ++ goto out; + } + + ret = rtw89_fw_recognize(rtwdev); + if (ret) { + rtw89_err(rtwdev, "failed to recognize firmware\n"); +- return ret; ++ goto out; + } + + ret = rtw89_chip_efuse_info_setup(rtwdev); + if (ret) +- return ret; ++ goto out; + + ret = rtw89_fw_recognize_elements(rtwdev); + if (ret) { + rtw89_err(rtwdev, "failed to recognize firmware elements\n"); +- return ret; ++ goto out; + } + + ret = rtw89_chip_board_info_setup(rtwdev); + if (ret) +- return ret; ++ goto out; + + rtw89_core_setup_rfe_parms(rtwdev); + rtwdev->ps_mode = rtw89_update_ps_mode(rtwdev); + +- return 0; ++out: ++ rtw89_mac_pwr_off(rtwdev); ++ ++ return ret; + } + EXPORT_SYMBOL(rtw89_chip_info_setup); + +diff --git a/drivers/net/wireless/realtek/rtw89/mac.c b/drivers/net/wireless/realtek/rtw89/mac.c +index 2c74d7781bd40..def12dbfe48d3 100644 +--- a/drivers/net/wireless/realtek/rtw89/mac.c ++++ b/drivers/net/wireless/realtek/rtw89/mac.c +@@ -1495,6 +1495,21 @@ static int rtw89_mac_power_switch(struct rtw89_dev *rtwdev, bool on) + #undef PWR_ACT + } + ++int rtw89_mac_pwr_on(struct rtw89_dev *rtwdev) ++{ ++ int ret; ++ ++ ret = rtw89_mac_power_switch(rtwdev, true); ++ if (ret) { ++ rtw89_mac_power_switch(rtwdev, false); ++ ret = rtw89_mac_power_switch(rtwdev, true); ++ if (ret) ++ return ret; ++ } ++ ++ return 0; ++} ++ + void rtw89_mac_pwr_off(struct rtw89_dev *rtwdev) + { + rtw89_mac_power_switch(rtwdev, false); +@@ -3996,14 +4011,6 @@ int rtw89_mac_partial_init(struct rtw89_dev *rtwdev, bool include_bb) + { + int ret; + +- ret = rtw89_mac_power_switch(rtwdev, true); +- if (ret) { +- rtw89_mac_power_switch(rtwdev, false); +- ret = rtw89_mac_power_switch(rtwdev, true); +- if (ret) +- return ret; +- } +- + rtw89_mac_ctrl_hci_dma_trx(rtwdev, true); + + if (include_bb) { +@@ -4036,6 +4043,10 @@ int rtw89_mac_init(struct rtw89_dev *rtwdev) + bool include_bb = !!chip->bbmcu_nr; + int ret; + ++ ret = rtw89_mac_pwr_on(rtwdev); ++ if (ret) ++ return ret; ++ + ret = rtw89_mac_partial_init(rtwdev, include_bb); + if (ret) + goto fail; +@@ -4067,7 +4078,7 @@ int rtw89_mac_init(struct rtw89_dev *rtwdev) + + return ret; + fail: +- rtw89_mac_power_switch(rtwdev, false); ++ rtw89_mac_pwr_off(rtwdev); + + return ret; + } +diff --git a/drivers/net/wireless/realtek/rtw89/mac.h b/drivers/net/wireless/realtek/rtw89/mac.h +index 373366a602e0b..71574dbd8764e 100644 +--- a/drivers/net/wireless/realtek/rtw89/mac.h ++++ b/drivers/net/wireless/realtek/rtw89/mac.h +@@ -1145,6 +1145,7 @@ rtw89_write32_port_set(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_l + rtw89_write32_set(rtwdev, reg, bit); + } + ++int rtw89_mac_pwr_on(struct rtw89_dev *rtwdev); + void rtw89_mac_pwr_off(struct rtw89_dev *rtwdev); + int rtw89_mac_partial_init(struct rtw89_dev *rtwdev, bool include_bb); + int rtw89_mac_init(struct rtw89_dev *rtwdev); +-- +2.39.5 + diff --git a/queue-6.14/wifi-rtw89-coex-add-protect-to-avoid-a2dp-lag-while-.patch b/queue-6.14/wifi-rtw89-coex-add-protect-to-avoid-a2dp-lag-while-.patch new file mode 100644 index 0000000000..98a1bbfd1a --- /dev/null +++ b/queue-6.14/wifi-rtw89-coex-add-protect-to-avoid-a2dp-lag-while-.patch @@ -0,0 +1,315 @@ +From 077b13879e4a2d37ef3548387d77dc5e80b4218b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 10 Jan 2025 09:54:14 +0800 +Subject: wifi: rtw89: coex: Add protect to avoid A2DP lag while Wi-Fi + connecting + +From: Ching-Te Ku + +[ Upstream commit 5251fd321684b591245a072b765d01a6c22a112c ] + +To get a well Wi-Fi RF quality, Wi-Fi need to do RF calibrations. While +Wi-Fi is doing RF calibrations, driver will pause the Bluetooth traffic +to make sure the RF calibration will not be interfered by Bluetooth. +However, if the RF calibrations take too much time, Bluetooth audio +will perform a lag sound. Add a function to make Bluetooth can do +traffic between the individual calibrations to avoid Bluetooth sound +lag. And patch related A2DP coexistence mechanism actions. + +Signed-off-by: Ching-Te Ku +Signed-off-by: Ping-Ke Shih +Link: https://patch.msgid.link/20250110015416.10704-2-pkshih@realtek.com +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/realtek/rtw89/coex.c | 90 +++++++++++-------- + drivers/net/wireless/realtek/rtw89/coex.h | 2 + + drivers/net/wireless/realtek/rtw89/core.h | 3 +- + drivers/net/wireless/realtek/rtw89/rtw8851b.c | 6 ++ + drivers/net/wireless/realtek/rtw89/rtw8852a.c | 6 ++ + drivers/net/wireless/realtek/rtw89/rtw8852b.c | 6 ++ + .../net/wireless/realtek/rtw89/rtw8852bt.c | 6 ++ + drivers/net/wireless/realtek/rtw89/rtw8852c.c | 6 ++ + 8 files changed, 85 insertions(+), 40 deletions(-) + +diff --git a/drivers/net/wireless/realtek/rtw89/coex.c b/drivers/net/wireless/realtek/rtw89/coex.c +index 7b10ee97c6277..86e8f78ec94a4 100644 +--- a/drivers/net/wireless/realtek/rtw89/coex.c ++++ b/drivers/net/wireless/realtek/rtw89/coex.c +@@ -4587,17 +4587,16 @@ static void _action_bt_a2dp(struct rtw89_dev *rtwdev) + + _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); + ++ if (a2dp.vendor_id == 0x4c || dm->leak_ap || bt_linfo->slave_role) ++ dm->slot_dur[CXST_W1] = 20; ++ else ++ dm->slot_dur[CXST_W1] = 40; ++ ++ dm->slot_dur[CXST_B1] = BTC_B1_MAX; ++ + switch (btc->cx.state_map) { + case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-A2DP */ +- if (a2dp.vendor_id == 0x4c || dm->leak_ap) { +- dm->slot_dur[CXST_W1] = 40; +- dm->slot_dur[CXST_B1] = 200; +- _set_policy(rtwdev, +- BTC_CXP_PAUTO_TDW1B1, BTC_ACT_BT_A2DP); +- } else { +- _set_policy(rtwdev, +- BTC_CXP_PAUTO_TD50B1, BTC_ACT_BT_A2DP); +- } ++ _set_policy(rtwdev, BTC_CXP_PAUTO_TDW1B1, BTC_ACT_BT_A2DP); + break; + case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-A2DP */ + _set_policy(rtwdev, BTC_CXP_PAUTO2_TD3050, BTC_ACT_BT_A2DP); +@@ -4607,15 +4606,10 @@ static void _action_bt_a2dp(struct rtw89_dev *rtwdev) + break; + case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-A2DP */ + case BTC_WLINKING: /* wl-connecting + bt-A2DP */ +- if (a2dp.vendor_id == 0x4c || dm->leak_ap) { +- dm->slot_dur[CXST_W1] = 40; +- dm->slot_dur[CXST_B1] = 200; +- _set_policy(rtwdev, BTC_CXP_AUTO_TDW1B1, +- BTC_ACT_BT_A2DP); +- } else { +- _set_policy(rtwdev, BTC_CXP_AUTO_TD50B1, +- BTC_ACT_BT_A2DP); +- } ++ if (btc->cx.wl.rfk_info.con_rfk) ++ _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_BT_A2DP); ++ else ++ _set_policy(rtwdev, BTC_CXP_AUTO_TDW1B1, BTC_ACT_BT_A2DP); + break; + case BTC_WIDLE: /* wl-idle + bt-A2DP */ + _set_policy(rtwdev, BTC_CXP_AUTO_TD20B1, BTC_ACT_BT_A2DP); +@@ -4643,7 +4637,10 @@ static void _action_bt_a2dpsink(struct rtw89_dev *rtwdev) + _set_policy(rtwdev, BTC_CXP_FIX_TD2060, BTC_ACT_BT_A2DPSINK); + break; + case BTC_WLINKING: /* wl-connecting + bt-A2dp_Sink */ +- _set_policy(rtwdev, BTC_CXP_FIX_TD3030, BTC_ACT_BT_A2DPSINK); ++ if (btc->cx.wl.rfk_info.con_rfk) ++ _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_BT_A2DPSINK); ++ else ++ _set_policy(rtwdev, BTC_CXP_FIX_TD3030, BTC_ACT_BT_A2DPSINK); + break; + case BTC_WIDLE: /* wl-idle + bt-A2dp_Sink */ + _set_policy(rtwdev, BTC_CXP_FIX_TD2080, BTC_ACT_BT_A2DPSINK); +@@ -4697,21 +4694,20 @@ static void _action_bt_a2dp_hid(struct rtw89_dev *rtwdev) + + _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); + ++ if (a2dp.vendor_id == 0x4c || dm->leak_ap || bt_linfo->slave_role) ++ dm->slot_dur[CXST_W1] = 20; ++ else ++ dm->slot_dur[CXST_W1] = 40; ++ ++ dm->slot_dur[CXST_B1] = BTC_B1_MAX; ++ + switch (btc->cx.state_map) { + case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-A2DP+HID */ + case BTC_WIDLE: /* wl-idle + bt-A2DP */ +- if (a2dp.vendor_id == 0x4c || dm->leak_ap) { +- dm->slot_dur[CXST_W1] = 40; +- dm->slot_dur[CXST_B1] = 200; +- _set_policy(rtwdev, +- BTC_CXP_PAUTO_TDW1B1, BTC_ACT_BT_A2DP_HID); +- } else { +- _set_policy(rtwdev, +- BTC_CXP_PAUTO_TD50B1, BTC_ACT_BT_A2DP_HID); +- } ++ _set_policy(rtwdev, BTC_CXP_PAUTO_TDW1B1, BTC_ACT_BT_A2DP_HID); + break; + case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-A2DP+HID */ +- _set_policy(rtwdev, BTC_CXP_PAUTO2_TD3050, BTC_ACT_BT_A2DP_HID); ++ _set_policy(rtwdev, BTC_CXP_PAUTO2_TD3070, BTC_ACT_BT_A2DP_HID); + break; + + case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-A2DP+HID */ +@@ -4719,15 +4715,10 @@ static void _action_bt_a2dp_hid(struct rtw89_dev *rtwdev) + break; + case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-A2DP+HID */ + case BTC_WLINKING: /* wl-connecting + bt-A2DP+HID */ +- if (a2dp.vendor_id == 0x4c || dm->leak_ap) { +- dm->slot_dur[CXST_W1] = 40; +- dm->slot_dur[CXST_B1] = 200; +- _set_policy(rtwdev, BTC_CXP_AUTO_TDW1B1, +- BTC_ACT_BT_A2DP_HID); +- } else { +- _set_policy(rtwdev, BTC_CXP_AUTO_TD50B1, +- BTC_ACT_BT_A2DP_HID); +- } ++ if (btc->cx.wl.rfk_info.con_rfk) ++ _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_BT_A2DP_HID); ++ else ++ _set_policy(rtwdev, BTC_CXP_AUTO_TDW1B1, BTC_ACT_BT_A2DP_HID); + break; + } + } +@@ -7001,7 +6992,7 @@ void _run_coex(struct rtw89_dev *rtwdev, enum btc_reason_and_action reason) + goto exit; + } + +- if (wl->status.val & btc_scanning_map.val) { ++ if (wl->status.val & btc_scanning_map.val && !wl->rfk_info.con_rfk) { + _action_wl_scan(rtwdev); + bt->scan_rx_low_pri = true; + goto exit; +@@ -11040,3 +11031,24 @@ void rtw89_coex_recognize_ver(struct rtw89_dev *rtwdev) + rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC] use version def[%d] = 0x%08x\n", + (int)(btc->ver - rtw89_btc_ver_defs), btc->ver->fw_ver_code); + } ++ ++void rtw89_btc_ntfy_preserve_bt_time(struct rtw89_dev *rtwdev, u32 ms) ++{ ++ struct rtw89_btc_bt_link_info *bt_linfo = &rtwdev->btc.cx.bt.link_info; ++ struct rtw89_btc_bt_a2dp_desc a2dp = bt_linfo->a2dp_desc; ++ ++ if (test_bit(RTW89_FLAG_SER_HANDLING, rtwdev->flags)) ++ return; ++ ++ if (!a2dp.exist) ++ return; ++ ++ fsleep(ms * 1000); ++} ++EXPORT_SYMBOL(rtw89_btc_ntfy_preserve_bt_time); ++ ++void rtw89_btc_ntfy_conn_rfk(struct rtw89_dev *rtwdev, bool state) ++{ ++ rtwdev->btc.cx.wl.rfk_info.con_rfk = state; ++} ++EXPORT_SYMBOL(rtw89_btc_ntfy_conn_rfk); +diff --git a/drivers/net/wireless/realtek/rtw89/coex.h b/drivers/net/wireless/realtek/rtw89/coex.h +index dbdb56e063ef0..757d03675cf4e 100644 +--- a/drivers/net/wireless/realtek/rtw89/coex.h ++++ b/drivers/net/wireless/realtek/rtw89/coex.h +@@ -290,6 +290,8 @@ void rtw89_coex_power_on(struct rtw89_dev *rtwdev); + void rtw89_btc_set_policy(struct rtw89_dev *rtwdev, u16 policy_type); + void rtw89_btc_set_policy_v1(struct rtw89_dev *rtwdev, u16 policy_type); + void rtw89_coex_recognize_ver(struct rtw89_dev *rtwdev); ++void rtw89_btc_ntfy_preserve_bt_time(struct rtw89_dev *rtwdev, u32 ms); ++void rtw89_btc_ntfy_conn_rfk(struct rtw89_dev *rtwdev, bool state); + + static inline u8 rtw89_btc_phymap(struct rtw89_dev *rtwdev, + enum rtw89_phy_idx phy_idx, +diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h +index c493153ec77b3..963f0046f0bc3 100644 +--- a/drivers/net/wireless/realtek/rtw89/core.h ++++ b/drivers/net/wireless/realtek/rtw89/core.h +@@ -1762,7 +1762,8 @@ struct rtw89_btc_wl_rfk_info { + u32 phy_map: 2; + u32 band: 2; + u32 type: 8; +- u32 rsvd: 14; ++ u32 con_rfk: 1; ++ u32 rsvd: 13; + + u32 start_time; + u32 proc_time; +diff --git a/drivers/net/wireless/realtek/rtw89/rtw8851b.c b/drivers/net/wireless/realtek/rtw89/rtw8851b.c +index a1df4ba97cd4d..546e88cd46493 100644 +--- a/drivers/net/wireless/realtek/rtw89/rtw8851b.c ++++ b/drivers/net/wireless/realtek/rtw89/rtw8851b.c +@@ -1596,10 +1596,16 @@ static void rtw8851b_rfk_channel(struct rtw89_dev *rtwdev, + enum rtw89_chanctx_idx chanctx_idx = rtwvif_link->chanctx_idx; + enum rtw89_phy_idx phy_idx = rtwvif_link->phy_idx; + ++ rtw89_btc_ntfy_conn_rfk(rtwdev, true); ++ + rtw8851b_rx_dck(rtwdev, phy_idx, chanctx_idx); + rtw8851b_iqk(rtwdev, phy_idx, chanctx_idx); ++ rtw89_btc_ntfy_preserve_bt_time(rtwdev, 30); + rtw8851b_tssi(rtwdev, phy_idx, true, chanctx_idx); ++ rtw89_btc_ntfy_preserve_bt_time(rtwdev, 30); + rtw8851b_dpk(rtwdev, phy_idx, chanctx_idx); ++ ++ rtw89_btc_ntfy_conn_rfk(rtwdev, false); + } + + static void rtw8851b_rfk_band_changed(struct rtw89_dev *rtwdev, +diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852a.c b/drivers/net/wireless/realtek/rtw89/rtw8852a.c +index cd79a997fe022..e12e5bd402e5b 100644 +--- a/drivers/net/wireless/realtek/rtw89/rtw8852a.c ++++ b/drivers/net/wireless/realtek/rtw89/rtw8852a.c +@@ -1356,10 +1356,16 @@ static void rtw8852a_rfk_channel(struct rtw89_dev *rtwdev, + enum rtw89_chanctx_idx chanctx_idx = rtwvif_link->chanctx_idx; + enum rtw89_phy_idx phy_idx = rtwvif_link->phy_idx; + ++ rtw89_btc_ntfy_conn_rfk(rtwdev, true); ++ + rtw8852a_rx_dck(rtwdev, phy_idx, true, chanctx_idx); + rtw8852a_iqk(rtwdev, phy_idx, chanctx_idx); ++ rtw89_btc_ntfy_preserve_bt_time(rtwdev, 30); + rtw8852a_tssi(rtwdev, phy_idx, chanctx_idx); ++ rtw89_btc_ntfy_preserve_bt_time(rtwdev, 30); + rtw8852a_dpk(rtwdev, phy_idx, chanctx_idx); ++ ++ rtw89_btc_ntfy_conn_rfk(rtwdev, false); + } + + static void rtw8852a_rfk_band_changed(struct rtw89_dev *rtwdev, +diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852b.c b/drivers/net/wireless/realtek/rtw89/rtw8852b.c +index fcb69fa6cf86d..ab9365b0ec089 100644 +--- a/drivers/net/wireless/realtek/rtw89/rtw8852b.c ++++ b/drivers/net/wireless/realtek/rtw89/rtw8852b.c +@@ -568,10 +568,16 @@ static void rtw8852b_rfk_channel(struct rtw89_dev *rtwdev, + enum rtw89_chanctx_idx chanctx_idx = rtwvif_link->chanctx_idx; + enum rtw89_phy_idx phy_idx = rtwvif_link->phy_idx; + ++ rtw89_btc_ntfy_conn_rfk(rtwdev, true); ++ + rtw8852b_rx_dck(rtwdev, phy_idx, chanctx_idx); + rtw8852b_iqk(rtwdev, phy_idx, chanctx_idx); ++ rtw89_btc_ntfy_preserve_bt_time(rtwdev, 30); + rtw8852b_tssi(rtwdev, phy_idx, true, chanctx_idx); ++ rtw89_btc_ntfy_preserve_bt_time(rtwdev, 30); + rtw8852b_dpk(rtwdev, phy_idx, chanctx_idx); ++ ++ rtw89_btc_ntfy_conn_rfk(rtwdev, false); + } + + static void rtw8852b_rfk_band_changed(struct rtw89_dev *rtwdev, +diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852bt.c b/drivers/net/wireless/realtek/rtw89/rtw8852bt.c +index bc740e9abf263..412e633944f37 100644 +--- a/drivers/net/wireless/realtek/rtw89/rtw8852bt.c ++++ b/drivers/net/wireless/realtek/rtw89/rtw8852bt.c +@@ -541,10 +541,16 @@ static void rtw8852bt_rfk_channel(struct rtw89_dev *rtwdev, + enum rtw89_chanctx_idx chanctx_idx = rtwvif_link->chanctx_idx; + enum rtw89_phy_idx phy_idx = rtwvif_link->phy_idx; + ++ rtw89_btc_ntfy_conn_rfk(rtwdev, true); ++ + rtw8852bt_rx_dck(rtwdev, phy_idx, chanctx_idx); + rtw8852bt_iqk(rtwdev, phy_idx, chanctx_idx); ++ rtw89_btc_ntfy_preserve_bt_time(rtwdev, 30); + rtw8852bt_tssi(rtwdev, phy_idx, true, chanctx_idx); ++ rtw89_btc_ntfy_preserve_bt_time(rtwdev, 30); + rtw8852bt_dpk(rtwdev, phy_idx, chanctx_idx); ++ ++ rtw89_btc_ntfy_conn_rfk(rtwdev, false); + } + + static void rtw8852bt_rfk_band_changed(struct rtw89_dev *rtwdev, +diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852c.c b/drivers/net/wireless/realtek/rtw89/rtw8852c.c +index 63a2bc88cdbcd..cd68f6cbeecbf 100644 +--- a/drivers/net/wireless/realtek/rtw89/rtw8852c.c ++++ b/drivers/net/wireless/realtek/rtw89/rtw8852c.c +@@ -1853,10 +1853,16 @@ static void rtw8852c_rfk_channel(struct rtw89_dev *rtwdev, + enum rtw89_phy_idx phy_idx = rtwvif_link->phy_idx; + + rtw8852c_mcc_get_ch_info(rtwdev, phy_idx); ++ rtw89_btc_ntfy_conn_rfk(rtwdev, true); ++ + rtw8852c_rx_dck(rtwdev, phy_idx, false); + rtw8852c_iqk(rtwdev, phy_idx, chanctx_idx); ++ rtw89_btc_ntfy_preserve_bt_time(rtwdev, 30); + rtw8852c_tssi(rtwdev, phy_idx, chanctx_idx); ++ rtw89_btc_ntfy_preserve_bt_time(rtwdev, 30); + rtw8852c_dpk(rtwdev, phy_idx, chanctx_idx); ++ ++ rtw89_btc_ntfy_conn_rfk(rtwdev, false); + rtw89_fw_h2c_rf_ntfy_mcc(rtwdev); + } + +-- +2.39.5 + diff --git a/queue-6.14/wifi-rtw89-coex-assign-value-over-than-0-to-avoid-fi.patch b/queue-6.14/wifi-rtw89-coex-assign-value-over-than-0-to-avoid-fi.patch new file mode 100644 index 0000000000..9d04bbb47c --- /dev/null +++ b/queue-6.14/wifi-rtw89-coex-assign-value-over-than-0-to-avoid-fi.patch @@ -0,0 +1,42 @@ +From 08d709fc50675992488589ab835a99b3b4760ba1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Feb 2025 09:32:31 +0800 +Subject: wifi: rtw89: coex: Assign value over than 0 to avoid firmware timer + hang + +From: Ching-Te Ku + +[ Upstream commit 2e4c4717b3f6f019c71af984564b6e4d0ae8d0bd ] + +If the slot duration is 0, the firmware timer will trigger timer hang at +the timer initializing state in a low rate due to hardware algorithm. + +Signed-off-by: Ching-Te Ku +Signed-off-by: Ping-Ke Shih +Link: https://patch.msgid.link/20250205013233.10945-2-pkshih@realtek.com +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/realtek/rtw89/coex.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/wireless/realtek/rtw89/coex.c b/drivers/net/wireless/realtek/rtw89/coex.c +index 9e06cc36a75e2..d94a028555e20 100644 +--- a/drivers/net/wireless/realtek/rtw89/coex.c ++++ b/drivers/net/wireless/realtek/rtw89/coex.c +@@ -89,10 +89,10 @@ static const struct rtw89_btc_fbtc_slot s_def[] = { + [CXST_B4] = __DEF_FBTC_SLOT(50, 0xe5555555, SLOT_MIX), + [CXST_LK] = __DEF_FBTC_SLOT(20, 0xea5a5a5a, SLOT_ISO), + [CXST_BLK] = __DEF_FBTC_SLOT(500, 0x55555555, SLOT_MIX), +- [CXST_E2G] = __DEF_FBTC_SLOT(0, 0xea5a5a5a, SLOT_MIX), +- [CXST_E5G] = __DEF_FBTC_SLOT(0, 0xffffffff, SLOT_ISO), ++ [CXST_E2G] = __DEF_FBTC_SLOT(5, 0xea5a5a5a, SLOT_MIX), ++ [CXST_E5G] = __DEF_FBTC_SLOT(5, 0xffffffff, SLOT_ISO), + [CXST_EBT] = __DEF_FBTC_SLOT(5, 0xe5555555, SLOT_MIX), +- [CXST_ENULL] = __DEF_FBTC_SLOT(0, 0xaaaaaaaa, SLOT_ISO), ++ [CXST_ENULL] = __DEF_FBTC_SLOT(5, 0xaaaaaaaa, SLOT_ISO), + [CXST_WLK] = __DEF_FBTC_SLOT(250, 0xea5a5a5a, SLOT_MIX), + [CXST_W1FDD] = __DEF_FBTC_SLOT(50, 0xffffffff, SLOT_ISO), + [CXST_B1FDD] = __DEF_FBTC_SLOT(50, 0xffffdfff, SLOT_ISO), +-- +2.39.5 + diff --git a/queue-6.14/wifi-rtw89-coex-fix-coexistence-report-not-show-as-e.patch b/queue-6.14/wifi-rtw89-coex-fix-coexistence-report-not-show-as-e.patch new file mode 100644 index 0000000000..1dbf3963a6 --- /dev/null +++ b/queue-6.14/wifi-rtw89-coex-fix-coexistence-report-not-show-as-e.patch @@ -0,0 +1,51 @@ +From 4d139cd5c91c8e377e02d1d3a43a5e97a4c043a9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 8 Mar 2025 10:58:30 +0800 +Subject: wifi: rtw89: coex: Fix coexistence report not show as expected + +From: Ching-Te Ku + +[ Upstream commit a36230aa5f5efceaf5f81682673732a921b91518 ] + +This report will feedback some basic information from firmware(PTA counter, +report counter, mailbox counter etc). And the report version need to match +driver & firmware both side. The original logic break the switch case logic +before driver update the report version. It made the report can not be +parsed correctly. Delete the break at the version 7 and 8. +Add logic to count C2H event report. + +Signed-off-by: Ching-Te Ku +Signed-off-by: Ping-Ke Shih +Link: https://patch.msgid.link/20250308025832.10400-3-pkshih@realtek.com +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/realtek/rtw89/coex.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/drivers/net/wireless/realtek/rtw89/coex.c b/drivers/net/wireless/realtek/rtw89/coex.c +index 68316d44b2043..9e06cc36a75e2 100644 +--- a/drivers/net/wireless/realtek/rtw89/coex.c ++++ b/drivers/net/wireless/realtek/rtw89/coex.c +@@ -1372,11 +1372,9 @@ static u32 _chk_btc_report(struct rtw89_dev *rtwdev, + } else if (ver->fcxbtcrpt == 8) { + pfinfo = &pfwinfo->rpt_ctrl.finfo.v8; + pcinfo->req_len = sizeof(pfwinfo->rpt_ctrl.finfo.v8); +- break; + } else if (ver->fcxbtcrpt == 7) { + pfinfo = &pfwinfo->rpt_ctrl.finfo.v7; + pcinfo->req_len = sizeof(pfwinfo->rpt_ctrl.finfo.v7); +- break; + } else { + goto err; + } +@@ -8115,6 +8113,7 @@ void rtw89_btc_c2h_handle(struct rtw89_dev *rtwdev, struct sk_buff *skb, + return; + + func = rtw89_btc_c2h_get_index_by_ver(rtwdev, func); ++ pfwinfo->cnt_c2h++; + + switch (func) { + case BTF_EVNT_BUF_OVERFLOW: +-- +2.39.5 + diff --git a/queue-6.14/wifi-rtw89-coex-separated-wi-fi-connecting-event-fro.patch b/queue-6.14/wifi-rtw89-coex-separated-wi-fi-connecting-event-fro.patch new file mode 100644 index 0000000000..dfdb9b1f4d --- /dev/null +++ b/queue-6.14/wifi-rtw89-coex-separated-wi-fi-connecting-event-fro.patch @@ -0,0 +1,59 @@ +From 17e516cfa51c9ed2d81caa000123416b6ae0e685 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 10 Jan 2025 09:54:15 +0800 +Subject: wifi: rtw89: coex: Separated Wi-Fi connecting event from Wi-Fi scan + event + +From: Ching-Te Ku + +[ Upstream commit 4a57346652154bb339c48b41166df9154cff33f5 ] + +Wi-Fi connecting process don't need to assign to firmware slot control, +if assign firmware slot control for Wi-Fi connecting event, firmware will +not toggle slots because driver don't tell the slot schedule to firmware. +Wi-Fi connecting event end should also cancel the 4way handshake status. + +Signed-off-by: Ching-Te Ku +Signed-off-by: Ping-Ke Shih +Link: https://patch.msgid.link/20250110015416.10704-3-pkshih@realtek.com +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/realtek/rtw89/coex.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/wireless/realtek/rtw89/coex.c b/drivers/net/wireless/realtek/rtw89/coex.c +index d94a028555e20..7b10ee97c6277 100644 +--- a/drivers/net/wireless/realtek/rtw89/coex.c ++++ b/drivers/net/wireless/realtek/rtw89/coex.c +@@ -5406,7 +5406,8 @@ static void _action_wl_scan(struct rtw89_dev *rtwdev) + struct rtw89_btc_wl_info *wl = &btc->cx.wl; + struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info; + +- if (RTW89_CHK_FW_FEATURE(SCAN_OFFLOAD, &rtwdev->fw)) { ++ if (btc->cx.state_map != BTC_WLINKING && ++ RTW89_CHK_FW_FEATURE(SCAN_OFFLOAD, &rtwdev->fw)) { + _action_wl_25g_mcc(rtwdev); + rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], Scan offload!\n"); + } else if (rtwdev->dbcc_en) { +@@ -7221,6 +7222,8 @@ void rtw89_btc_ntfy_scan_finish(struct rtw89_dev *rtwdev, u8 phy_idx) + _fw_set_drv_info(rtwdev, CXDRVINFO_DBCC); + } + ++ btc->dm.tdma_instant_excute = 1; ++ + _run_coex(rtwdev, BTC_RSN_NTFY_SCAN_FINISH); + } + +@@ -7669,7 +7672,8 @@ void rtw89_btc_ntfy_role_info(struct rtw89_dev *rtwdev, + else + wl->status.map.connecting = 0; + +- if (state == BTC_ROLE_MSTS_STA_DIS_CONN) ++ if (state == BTC_ROLE_MSTS_STA_DIS_CONN || ++ state == BTC_ROLE_MSTS_STA_CONN_END) + wl->status.map._4way = false; + + _run_coex(rtwdev, BTC_RSN_NTFY_ROLE_INFO); +-- +2.39.5 + diff --git a/queue-6.14/wifi-rtw89-fw-add-blacklist-to-avoid-obsolete-secure.patch b/queue-6.14/wifi-rtw89-fw-add-blacklist-to-avoid-obsolete-secure.patch new file mode 100644 index 0000000000..80b4fee860 --- /dev/null +++ b/queue-6.14/wifi-rtw89-fw-add-blacklist-to-avoid-obsolete-secure.patch @@ -0,0 +1,229 @@ +From 7873bb14b5fc355d74255892d090d1d87b87ea34 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Feb 2025 14:43:04 +0800 +Subject: wifi: rtw89: fw: add blacklist to avoid obsolete secure firmware + +From: Ping-Ke Shih + +[ Upstream commit f11d042b3a2e92ab1aa10e0da8e290bcdcf31d39 ] + +To ensure secure chip only runs expected secure firmware, stop using +obsolete firmware in blacklist which weakness or flaw was found. + +Signed-off-by: Ping-Ke Shih +Link: https://patch.msgid.link/20250217064308.43559-2-pkshih@realtek.com +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/realtek/rtw89/core.h | 2 + + drivers/net/wireless/realtek/rtw89/fw.c | 52 ++++++++++++++++++- + drivers/net/wireless/realtek/rtw89/fw.h | 12 +++++ + drivers/net/wireless/realtek/rtw89/rtw8851b.c | 1 + + drivers/net/wireless/realtek/rtw89/rtw8852a.c | 1 + + drivers/net/wireless/realtek/rtw89/rtw8852b.c | 1 + + .../net/wireless/realtek/rtw89/rtw8852bt.c | 1 + + drivers/net/wireless/realtek/rtw89/rtw8852c.c | 1 + + drivers/net/wireless/realtek/rtw89/rtw8922a.c | 1 + + 9 files changed, 71 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h +index 979587e92c849..c493153ec77b3 100644 +--- a/drivers/net/wireless/realtek/rtw89/core.h ++++ b/drivers/net/wireless/realtek/rtw89/core.h +@@ -17,6 +17,7 @@ struct rtw89_dev; + struct rtw89_pci_info; + struct rtw89_mac_gen_def; + struct rtw89_phy_gen_def; ++struct rtw89_fw_blacklist; + struct rtw89_efuse_block_cfg; + struct rtw89_h2c_rf_tssi; + struct rtw89_fw_txpwr_track_cfg; +@@ -4251,6 +4252,7 @@ struct rtw89_chip_info { + bool try_ce_fw; + u8 bbmcu_nr; + u32 needed_fw_elms; ++ const struct rtw89_fw_blacklist *fw_blacklist; + u32 fifo_size; + bool small_fifo_size; + u32 dle_scc_rsvd_size; +diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c +index 3164ff69803a1..92e6bc05cbf66 100644 +--- a/drivers/net/wireless/realtek/rtw89/fw.c ++++ b/drivers/net/wireless/realtek/rtw89/fw.c +@@ -38,6 +38,16 @@ struct rtw89_arp_rsp { + + static const u8 mss_signature[] = {0x4D, 0x53, 0x53, 0x4B, 0x50, 0x4F, 0x4F, 0x4C}; + ++const struct rtw89_fw_blacklist rtw89_fw_blacklist_default = { ++ .ver = 0x00, ++ .list = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, ++ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, ++ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, ++ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, ++ }, ++}; ++EXPORT_SYMBOL(rtw89_fw_blacklist_default); ++ + union rtw89_fw_element_arg { + size_t offset; + enum rtw89_rf_path rf_path; +@@ -344,6 +354,46 @@ static int __parse_formatted_mssc(struct rtw89_dev *rtwdev, + return 0; + } + ++static int __check_secure_blacklist(struct rtw89_dev *rtwdev, ++ struct rtw89_fw_bin_info *info, ++ struct rtw89_fw_hdr_section_info *section_info, ++ const void *content) ++{ ++ const struct rtw89_fw_blacklist *chip_blacklist = rtwdev->chip->fw_blacklist; ++ const union rtw89_fw_section_mssc_content *section_content = content; ++ struct rtw89_fw_secure *sec = &rtwdev->fw.sec; ++ u8 byte_idx; ++ u8 bit_mask; ++ ++ if (!sec->secure_boot) ++ return 0; ++ ++ if (!info->secure_section_exist || section_info->ignore) ++ return 0; ++ ++ if (!chip_blacklist) { ++ rtw89_err(rtwdev, "chip no blacklist for secure firmware\n"); ++ return -ENOENT; ++ } ++ ++ byte_idx = section_content->blacklist.bit_in_chip_list >> 3; ++ bit_mask = BIT(section_content->blacklist.bit_in_chip_list & 0x7); ++ ++ if (section_content->blacklist.ver > chip_blacklist->ver) { ++ rtw89_err(rtwdev, "chip blacklist out of date (%u, %u)\n", ++ section_content->blacklist.ver, chip_blacklist->ver); ++ return -EINVAL; ++ } ++ ++ if (chip_blacklist->list[byte_idx] & bit_mask) { ++ rtw89_err(rtwdev, "firmware %u in chip blacklist\n", ++ section_content->blacklist.ver); ++ return -EPERM; ++ } ++ ++ return 0; ++} ++ + static int __parse_security_section(struct rtw89_dev *rtwdev, + struct rtw89_fw_bin_info *info, + struct rtw89_fw_hdr_section_info *section_info, +@@ -374,7 +424,7 @@ static int __parse_security_section(struct rtw89_dev *rtwdev, + info->secure_section_exist = true; + } + +- return 0; ++ return __check_secure_blacklist(rtwdev, info, section_info, content); + } + + static int rtw89_fw_hdr_parser_v1(struct rtw89_dev *rtwdev, const u8 *fw, u32 len, +diff --git a/drivers/net/wireless/realtek/rtw89/fw.h b/drivers/net/wireless/realtek/rtw89/fw.h +index 2026bc2fd2acd..ee2be09bd3dbd 100644 +--- a/drivers/net/wireless/realtek/rtw89/fw.h ++++ b/drivers/net/wireless/realtek/rtw89/fw.h +@@ -663,6 +663,11 @@ struct rtw89_fw_mss_pool_hdr { + } __packed; + + union rtw89_fw_section_mssc_content { ++ struct { ++ u8 pad[0x20]; ++ u8 bit_in_chip_list; ++ u8 ver; ++ } __packed blacklist; + struct { + u8 pad[58]; + __le32 v; +@@ -673,6 +678,13 @@ union rtw89_fw_section_mssc_content { + } __packed key_sign_len; + } __packed; + ++struct rtw89_fw_blacklist { ++ u8 ver; ++ u8 list[32]; ++}; ++ ++extern const struct rtw89_fw_blacklist rtw89_fw_blacklist_default; ++ + static inline void SET_CTRL_INFO_MACID(void *table, u32 val) + { + le32p_replace_bits((__le32 *)(table) + 0, val, GENMASK(6, 0)); +diff --git a/drivers/net/wireless/realtek/rtw89/rtw8851b.c b/drivers/net/wireless/realtek/rtw89/rtw8851b.c +index 24d48aced57ac..a1df4ba97cd4d 100644 +--- a/drivers/net/wireless/realtek/rtw89/rtw8851b.c ++++ b/drivers/net/wireless/realtek/rtw89/rtw8851b.c +@@ -2445,6 +2445,7 @@ const struct rtw89_chip_info rtw8851b_chip_info = { + .try_ce_fw = true, + .bbmcu_nr = 0, + .needed_fw_elms = 0, ++ .fw_blacklist = NULL, + .fifo_size = 196608, + .small_fifo_size = true, + .dle_scc_rsvd_size = 98304, +diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852a.c b/drivers/net/wireless/realtek/rtw89/rtw8852a.c +index eeb40a60c2b98..cd79a997fe022 100644 +--- a/drivers/net/wireless/realtek/rtw89/rtw8852a.c ++++ b/drivers/net/wireless/realtek/rtw89/rtw8852a.c +@@ -2162,6 +2162,7 @@ const struct rtw89_chip_info rtw8852a_chip_info = { + .try_ce_fw = false, + .bbmcu_nr = 0, + .needed_fw_elms = 0, ++ .fw_blacklist = NULL, + .fifo_size = 458752, + .small_fifo_size = false, + .dle_scc_rsvd_size = 0, +diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852b.c b/drivers/net/wireless/realtek/rtw89/rtw8852b.c +index 4335fa85c334b..fcb69fa6cf86d 100644 +--- a/drivers/net/wireless/realtek/rtw89/rtw8852b.c ++++ b/drivers/net/wireless/realtek/rtw89/rtw8852b.c +@@ -798,6 +798,7 @@ const struct rtw89_chip_info rtw8852b_chip_info = { + .try_ce_fw = true, + .bbmcu_nr = 0, + .needed_fw_elms = 0, ++ .fw_blacklist = &rtw89_fw_blacklist_default, + .fifo_size = 196608, + .small_fifo_size = true, + .dle_scc_rsvd_size = 98304, +diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852bt.c b/drivers/net/wireless/realtek/rtw89/rtw8852bt.c +index 7f64a5695486b..bc740e9abf263 100644 +--- a/drivers/net/wireless/realtek/rtw89/rtw8852bt.c ++++ b/drivers/net/wireless/realtek/rtw89/rtw8852bt.c +@@ -732,6 +732,7 @@ const struct rtw89_chip_info rtw8852bt_chip_info = { + .try_ce_fw = true, + .bbmcu_nr = 0, + .needed_fw_elms = RTW89_AX_GEN_DEF_NEEDED_FW_ELEMENTS_NO_6GHZ, ++ .fw_blacklist = &rtw89_fw_blacklist_default, + .fifo_size = 458752, + .small_fifo_size = true, + .dle_scc_rsvd_size = 98304, +diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852c.c b/drivers/net/wireless/realtek/rtw89/rtw8852c.c +index 9778621d9bc41..63a2bc88cdbcd 100644 +--- a/drivers/net/wireless/realtek/rtw89/rtw8852c.c ++++ b/drivers/net/wireless/realtek/rtw89/rtw8852c.c +@@ -2954,6 +2954,7 @@ const struct rtw89_chip_info rtw8852c_chip_info = { + .try_ce_fw = false, + .bbmcu_nr = 0, + .needed_fw_elms = 0, ++ .fw_blacklist = &rtw89_fw_blacklist_default, + .fifo_size = 458752, + .small_fifo_size = false, + .dle_scc_rsvd_size = 0, +diff --git a/drivers/net/wireless/realtek/rtw89/rtw8922a.c b/drivers/net/wireless/realtek/rtw89/rtw8922a.c +index 731bc6f18d38b..2696fdf350f63 100644 +--- a/drivers/net/wireless/realtek/rtw89/rtw8922a.c ++++ b/drivers/net/wireless/realtek/rtw89/rtw8922a.c +@@ -2721,6 +2721,7 @@ const struct rtw89_chip_info rtw8922a_chip_info = { + .try_ce_fw = false, + .bbmcu_nr = 1, + .needed_fw_elms = RTW89_BE_GEN_DEF_NEEDED_FW_ELEMENTS, ++ .fw_blacklist = &rtw89_fw_blacklist_default, + .fifo_size = 589824, + .small_fifo_size = false, + .dle_scc_rsvd_size = 0, +-- +2.39.5 + diff --git a/queue-6.14/wifi-rtw89-fw-get-sb_sel_ver-via-get_unaligned_le32.patch b/queue-6.14/wifi-rtw89-fw-get-sb_sel_ver-via-get_unaligned_le32.patch new file mode 100644 index 0000000000..63c735986d --- /dev/null +++ b/queue-6.14/wifi-rtw89-fw-get-sb_sel_ver-via-get_unaligned_le32.patch @@ -0,0 +1,36 @@ +From 156150c1a836d95a1a2849a74918ede35d0c9498 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Feb 2025 14:43:05 +0800 +Subject: wifi: rtw89: fw: get sb_sel_ver via get_unaligned_le32() + +From: Ping-Ke Shih + +[ Upstream commit 2f9da853f4d848d23bade4c22931ea0f5a011674 ] + +The sb_sel_ver is selection version for secure boot recorded in firmware +binary data, and its size is 4 and offset is 58 (not natural alignment). +Use get_unaligned_le32() to get this value safely. Find this by reviewing. + +Signed-off-by: Ping-Ke Shih +Link: https://patch.msgid.link/20250217064308.43559-3-pkshih@realtek.com +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/realtek/rtw89/fw.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c +index 4727eeb55b486..3164ff69803a1 100644 +--- a/drivers/net/wireless/realtek/rtw89/fw.c ++++ b/drivers/net/wireless/realtek/rtw89/fw.c +@@ -314,7 +314,7 @@ static int __parse_formatted_mssc(struct rtw89_dev *rtwdev, + if (!sec->secure_boot) + goto out; + +- sb_sel_ver = le32_to_cpu(section_content->sb_sel_ver.v); ++ sb_sel_ver = get_unaligned_le32(§ion_content->sb_sel_ver.v); + if (sb_sel_ver && sb_sel_ver != sec->sb_sel_mgn) + goto ignore; + +-- +2.39.5 + diff --git a/queue-6.14/wifi-rtw89-fw-propagate-error-code-from-rtw89_h2c_tx.patch b/queue-6.14/wifi-rtw89-fw-propagate-error-code-from-rtw89_h2c_tx.patch new file mode 100644 index 0000000000..a5de01416b --- /dev/null +++ b/queue-6.14/wifi-rtw89-fw-propagate-error-code-from-rtw89_h2c_tx.patch @@ -0,0 +1,42 @@ +From 57d3696f52e93d3871f6c4d23c4ea316a5e09c66 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Feb 2025 14:43:06 +0800 +Subject: wifi: rtw89: fw: propagate error code from rtw89_h2c_tx() + +From: Ping-Ke Shih + +[ Upstream commit 56e1acaa0f80620b8e2c3410db35b4b975782b0a ] + +The error code should be propagated to callers during downloading firmware +header and body. Remove unnecessary assignment of -1. + +Signed-off-by: Ping-Ke Shih +Link: https://patch.msgid.link/20250217064308.43559-4-pkshih@realtek.com +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/realtek/rtw89/fw.c | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c +index 2f3869c700696..4727eeb55b486 100644 +--- a/drivers/net/wireless/realtek/rtw89/fw.c ++++ b/drivers/net/wireless/realtek/rtw89/fw.c +@@ -1322,7 +1322,6 @@ static int __rtw89_fw_download_hdr(struct rtw89_dev *rtwdev, + ret = rtw89_h2c_tx(rtwdev, skb, false); + if (ret) { + rtw89_err(rtwdev, "failed to send h2c\n"); +- ret = -1; + goto fail; + } + +@@ -1409,7 +1408,6 @@ static int __rtw89_fw_download_main(struct rtw89_dev *rtwdev, + ret = rtw89_h2c_tx(rtwdev, skb, true); + if (ret) { + rtw89_err(rtwdev, "failed to send h2c\n"); +- ret = -1; + goto fail; + } + +-- +2.39.5 + diff --git a/queue-6.14/wifi-rtw89-fw-validate-multi-firmware-header-before-.patch b/queue-6.14/wifi-rtw89-fw-validate-multi-firmware-header-before-.patch new file mode 100644 index 0000000000..e779847dee --- /dev/null +++ b/queue-6.14/wifi-rtw89-fw-validate-multi-firmware-header-before-.patch @@ -0,0 +1,73 @@ +From 602a36a06df1539b937d49289fe4646ea26f734b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 3 Feb 2025 15:29:11 +0800 +Subject: wifi: rtw89: fw: validate multi-firmware header before getting its + size + +From: Ping-Ke Shih + +[ Upstream commit 2b8bdc5237014cc61784b3676cbaca5325959f3d ] + +To access firmware elements appended after multi-firmware, add its size +as offset to get start address of firmware elements. + + +-----+-------+------+---------+--------------+ -- + | sig | fw_nr | rsvd | version | reserved | \ + +---------------------------------------------+ | + fw 0 | cv | type | mp | rsvd | shift | size | rsvd | | + +---------------------------------------------+ | + fw 1 | cv | type | mp | rsvd | shift | size | rsvd | | + +---------------------------------------------+ | + fw N-1 | ... | | + +=============================================+ | mfw size + | fw 0 content | | + +=============================================+ | + | fw 1 content | | + +=============================================+ | + | ... | | + +=============================================+ | + | fw N -1 content | | + +=============================================+ --/ + | fw element TLV X | + +=============================================+ + | fw element TLV Y | + +=============================================+ + | fw element TLV Z | + +=============================================+ + +To avoid Coverity warning when getting mfw size, validate it header ahead. + +Addresses-Coverity-ID: 1544385 ("Untrusted array index read") + +Signed-off-by: Ping-Ke Shih +Link: https://patch.msgid.link/20250203072911.47313-5-pkshih@realtek.com +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/realtek/rtw89/fw.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c +index f4b3438615541..aed0647955d8e 100644 +--- a/drivers/net/wireless/realtek/rtw89/fw.c ++++ b/drivers/net/wireless/realtek/rtw89/fw.c +@@ -601,12 +601,17 @@ static u32 rtw89_mfw_get_size(struct rtw89_dev *rtwdev) + (const struct rtw89_mfw_hdr *)firmware->data; + const struct rtw89_mfw_info *mfw_info; + u32 size; ++ int ret; + + if (mfw_hdr->sig != RTW89_MFW_SIG) { + rtw89_warn(rtwdev, "not mfw format\n"); + return 0; + } + ++ ret = rtw89_mfw_validate_hdr(rtwdev, firmware, mfw_hdr); ++ if (ret) ++ return ret; ++ + mfw_info = &mfw_hdr->info[mfw_hdr->fw_nr - 1]; + size = le32_to_cpu(mfw_info->shift) + le32_to_cpu(mfw_info->size); + +-- +2.39.5 + diff --git a/queue-6.14/wifi-rtw89-fw-validate-multi-firmware-header-before-.patch-7297 b/queue-6.14/wifi-rtw89-fw-validate-multi-firmware-header-before-.patch-7297 new file mode 100644 index 0000000000..030668cb47 --- /dev/null +++ b/queue-6.14/wifi-rtw89-fw-validate-multi-firmware-header-before-.patch-7297 @@ -0,0 +1,107 @@ +From 279c639077ee54c3542ea9d54a9b4745a20bf41a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 3 Feb 2025 15:29:10 +0800 +Subject: wifi: rtw89: fw: validate multi-firmware header before accessing + +From: Ping-Ke Shih + +[ Upstream commit 1f0efffd597893404aea5c3d4f1bdaa1c61d4434 ] + +A firmeware file contains multi-firmware with a header to represent +contents. The mfw_hdr->fw_nr is to define number of firmware in file. + + +-----+-------+------+---------+--------------+ + | sig | fw_nr | rsvd | version | reserved | + +---------------------------------------------+ -- + fw 0 | cv | type | mp | rsvd | shift | size | rsvd | \ + +---------------------------------------------+ | + fw 1 | cv | type | mp | rsvd | shift | size | rsvd | | mfw_hdr->fw_nr + +---------------------------------------------+ | + fw N-1 | ... | / + +=============================================+ -- + | fw 0 content | + | (pointed by fw0 shift/size) | + +=============================================+ + +To avoid Coverity warning, validate header is in range of firmware size, +and also validate the range of actual firmware content is in range. + +Addresses-Coverity-ID: 1494046 ("Untrusted loop bound") + +Signed-off-by: Ping-Ke Shih +Link: https://patch.msgid.link/20250203072911.47313-4-pkshih@realtek.com +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/realtek/rtw89/fw.c | 35 +++++++++++++++++++++++++ + 1 file changed, 35 insertions(+) + +diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c +index aed0647955d8e..1fbcba718998f 100644 +--- a/drivers/net/wireless/realtek/rtw89/fw.c ++++ b/drivers/net/wireless/realtek/rtw89/fw.c +@@ -539,6 +539,30 @@ static int rtw89_fw_hdr_parser(struct rtw89_dev *rtwdev, + } + } + ++static int rtw89_mfw_validate_hdr(struct rtw89_dev *rtwdev, ++ const struct firmware *firmware, ++ const struct rtw89_mfw_hdr *mfw_hdr) ++{ ++ const void *mfw = firmware->data; ++ u32 mfw_len = firmware->size; ++ u8 fw_nr = mfw_hdr->fw_nr; ++ const void *ptr; ++ ++ if (fw_nr == 0) { ++ rtw89_err(rtwdev, "mfw header has no fw entry\n"); ++ return -ENOENT; ++ } ++ ++ ptr = &mfw_hdr->info[fw_nr]; ++ ++ if (ptr > mfw + mfw_len) { ++ rtw89_err(rtwdev, "mfw header out of address\n"); ++ return -EFAULT; ++ } ++ ++ return 0; ++} ++ + static + int rtw89_mfw_recognize(struct rtw89_dev *rtwdev, enum rtw89_fw_type type, + struct rtw89_fw_suit *fw_suit, bool nowarn) +@@ -549,6 +573,7 @@ int rtw89_mfw_recognize(struct rtw89_dev *rtwdev, enum rtw89_fw_type type, + u32 mfw_len = firmware->size; + const struct rtw89_mfw_hdr *mfw_hdr = (const struct rtw89_mfw_hdr *)mfw; + const struct rtw89_mfw_info *mfw_info = NULL, *tmp; ++ int ret; + int i; + + if (mfw_hdr->sig != RTW89_MFW_SIG) { +@@ -561,6 +586,10 @@ int rtw89_mfw_recognize(struct rtw89_dev *rtwdev, enum rtw89_fw_type type, + return 0; + } + ++ ret = rtw89_mfw_validate_hdr(rtwdev, firmware, mfw_hdr); ++ if (ret) ++ return ret; ++ + for (i = 0; i < mfw_hdr->fw_nr; i++) { + tmp = &mfw_hdr->info[i]; + if (tmp->type != type) +@@ -590,6 +619,12 @@ int rtw89_mfw_recognize(struct rtw89_dev *rtwdev, enum rtw89_fw_type type, + found: + fw_suit->data = mfw + le32_to_cpu(mfw_info->shift); + fw_suit->size = le32_to_cpu(mfw_info->size); ++ ++ if (fw_suit->data + fw_suit->size > mfw + mfw_len) { ++ rtw89_err(rtwdev, "fw_suit %d out of address\n", type); ++ return -EFAULT; ++ } ++ + return 0; + } + +-- +2.39.5 + diff --git a/queue-6.14/wifi-rtw89-parse-channel-from-ie-to-correct-invalid-.patch b/queue-6.14/wifi-rtw89-parse-channel-from-ie-to-correct-invalid-.patch new file mode 100644 index 0000000000..c0cd0779b4 --- /dev/null +++ b/queue-6.14/wifi-rtw89-parse-channel-from-ie-to-correct-invalid-.patch @@ -0,0 +1,178 @@ +From 8fa7acc8503f8b18bc832a80eeea40b29e7b57e6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 20 Feb 2025 14:43:57 +0800 +Subject: wifi: rtw89: Parse channel from IE to correct invalid hardware + reports during scanning + +From: Chih-Kang Chang + +[ Upstream commit e16acf907a3c66b9996a5df43e177a5edec8e0a5 ] + +For some packets, we could not get channel information from PPDU status. +And this causes wrong frequencies being reported. Parse the channel +information from IE if provided by AP to fix this. + +Signed-off-by: Chih-Kang Chang +Signed-off-by: Ping-Ke Shih +Link: https://patch.msgid.link/20250220064357.17962-1-pkshih@realtek.com +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/realtek/rtw89/core.c | 44 +++++++++++++++++++ + drivers/net/wireless/realtek/rtw89/core.h | 1 + + drivers/net/wireless/realtek/rtw89/rtw8851b.c | 1 + + drivers/net/wireless/realtek/rtw89/rtw8852a.c | 1 + + drivers/net/wireless/realtek/rtw89/rtw8852b.c | 1 + + .../net/wireless/realtek/rtw89/rtw8852bt.c | 1 + + drivers/net/wireless/realtek/rtw89/rtw8852c.c | 1 + + drivers/net/wireless/realtek/rtw89/rtw8922a.c | 1 + + 8 files changed, 51 insertions(+) + +diff --git a/drivers/net/wireless/realtek/rtw89/core.c b/drivers/net/wireless/realtek/rtw89/core.c +index 85f739f1173d8..c84446ec9e4f4 100644 +--- a/drivers/net/wireless/realtek/rtw89/core.c ++++ b/drivers/net/wireless/realtek/rtw89/core.c +@@ -2381,6 +2381,49 @@ static void rtw89_core_validate_rx_signal(struct ieee80211_rx_status *rx_status) + rx_status->flag |= RX_FLAG_NO_SIGNAL_VAL; + } + ++static void rtw89_core_update_rx_freq_from_ie(struct rtw89_dev *rtwdev, ++ struct sk_buff *skb, ++ struct ieee80211_rx_status *rx_status) ++{ ++ struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data; ++ size_t hdr_len, ielen; ++ u8 *variable; ++ int chan; ++ ++ if (!rtwdev->chip->rx_freq_frome_ie) ++ return; ++ ++ if (!rtwdev->scanning) ++ return; ++ ++ if (ieee80211_is_beacon(mgmt->frame_control)) { ++ variable = mgmt->u.beacon.variable; ++ hdr_len = offsetof(struct ieee80211_mgmt, ++ u.beacon.variable); ++ } else if (ieee80211_is_probe_resp(mgmt->frame_control)) { ++ variable = mgmt->u.probe_resp.variable; ++ hdr_len = offsetof(struct ieee80211_mgmt, ++ u.probe_resp.variable); ++ } else { ++ return; ++ } ++ ++ if (skb->len > hdr_len) ++ ielen = skb->len - hdr_len; ++ else ++ return; ++ ++ /* The parsing code for both 2GHz and 5GHz bands is the same in this ++ * function. ++ */ ++ chan = cfg80211_get_ies_channel_number(variable, ielen, NL80211_BAND_2GHZ); ++ if (chan == -1) ++ return; ++ ++ rx_status->band = chan > 14 ? RTW89_BAND_5G : RTW89_BAND_2G; ++ rx_status->freq = ieee80211_channel_to_frequency(chan, rx_status->band); ++} ++ + static void rtw89_core_rx_to_mac80211(struct rtw89_dev *rtwdev, + struct rtw89_rx_phy_ppdu *phy_ppdu, + struct rtw89_rx_desc_info *desc_info, +@@ -2398,6 +2441,7 @@ static void rtw89_core_rx_to_mac80211(struct rtw89_dev *rtwdev, + rtw89_core_update_rx_status_by_ppdu(rtwdev, rx_status, phy_ppdu); + rtw89_core_update_radiotap(rtwdev, skb_ppdu, rx_status); + rtw89_core_validate_rx_signal(rx_status); ++ rtw89_core_update_rx_freq_from_ie(rtwdev, skb_ppdu, rx_status); + + /* In low power mode, it does RX in thread context. */ + local_bh_disable(); +diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h +index 93e41def81b40..979587e92c849 100644 +--- a/drivers/net/wireless/realtek/rtw89/core.h ++++ b/drivers/net/wireless/realtek/rtw89/core.h +@@ -4273,6 +4273,7 @@ struct rtw89_chip_info { + bool support_ant_gain; + bool ul_tb_waveform_ctrl; + bool ul_tb_pwr_diff; ++ bool rx_freq_frome_ie; + bool hw_sec_hdr; + bool hw_mgmt_tx_encrypt; + u8 rf_path_num; +diff --git a/drivers/net/wireless/realtek/rtw89/rtw8851b.c b/drivers/net/wireless/realtek/rtw89/rtw8851b.c +index c56f70267882a..24d48aced57ac 100644 +--- a/drivers/net/wireless/realtek/rtw89/rtw8851b.c ++++ b/drivers/net/wireless/realtek/rtw89/rtw8851b.c +@@ -2485,6 +2485,7 @@ const struct rtw89_chip_info rtw8851b_chip_info = { + .support_ant_gain = false, + .ul_tb_waveform_ctrl = true, + .ul_tb_pwr_diff = false, ++ .rx_freq_frome_ie = true, + .hw_sec_hdr = false, + .hw_mgmt_tx_encrypt = false, + .rf_path_num = 1, +diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852a.c b/drivers/net/wireless/realtek/rtw89/rtw8852a.c +index 9bd2842c27d50..eeb40a60c2b98 100644 +--- a/drivers/net/wireless/realtek/rtw89/rtw8852a.c ++++ b/drivers/net/wireless/realtek/rtw89/rtw8852a.c +@@ -2203,6 +2203,7 @@ const struct rtw89_chip_info rtw8852a_chip_info = { + .support_ant_gain = false, + .ul_tb_waveform_ctrl = false, + .ul_tb_pwr_diff = false, ++ .rx_freq_frome_ie = true, + .hw_sec_hdr = false, + .hw_mgmt_tx_encrypt = false, + .rf_path_num = 2, +diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852b.c b/drivers/net/wireless/realtek/rtw89/rtw8852b.c +index dfb2bf61b0b83..4335fa85c334b 100644 +--- a/drivers/net/wireless/realtek/rtw89/rtw8852b.c ++++ b/drivers/net/wireless/realtek/rtw89/rtw8852b.c +@@ -839,6 +839,7 @@ const struct rtw89_chip_info rtw8852b_chip_info = { + .support_ant_gain = true, + .ul_tb_waveform_ctrl = true, + .ul_tb_pwr_diff = false, ++ .rx_freq_frome_ie = true, + .hw_sec_hdr = false, + .hw_mgmt_tx_encrypt = false, + .rf_path_num = 2, +diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852bt.c b/drivers/net/wireless/realtek/rtw89/rtw8852bt.c +index bde3e1fb7ca62..7f64a5695486b 100644 +--- a/drivers/net/wireless/realtek/rtw89/rtw8852bt.c ++++ b/drivers/net/wireless/realtek/rtw89/rtw8852bt.c +@@ -772,6 +772,7 @@ const struct rtw89_chip_info rtw8852bt_chip_info = { + .support_ant_gain = true, + .ul_tb_waveform_ctrl = true, + .ul_tb_pwr_diff = false, ++ .rx_freq_frome_ie = true, + .hw_sec_hdr = false, + .hw_mgmt_tx_encrypt = false, + .rf_path_num = 2, +diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852c.c b/drivers/net/wireless/realtek/rtw89/rtw8852c.c +index bc84b15e7826d..9778621d9bc41 100644 +--- a/drivers/net/wireless/realtek/rtw89/rtw8852c.c ++++ b/drivers/net/wireless/realtek/rtw89/rtw8852c.c +@@ -2998,6 +2998,7 @@ const struct rtw89_chip_info rtw8852c_chip_info = { + .support_ant_gain = true, + .ul_tb_waveform_ctrl = false, + .ul_tb_pwr_diff = true, ++ .rx_freq_frome_ie = false, + .hw_sec_hdr = true, + .hw_mgmt_tx_encrypt = true, + .rf_path_num = 2, +diff --git a/drivers/net/wireless/realtek/rtw89/rtw8922a.c b/drivers/net/wireless/realtek/rtw89/rtw8922a.c +index 11d66bfceb15f..731bc6f18d38b 100644 +--- a/drivers/net/wireless/realtek/rtw89/rtw8922a.c ++++ b/drivers/net/wireless/realtek/rtw89/rtw8922a.c +@@ -2763,6 +2763,7 @@ const struct rtw89_chip_info rtw8922a_chip_info = { + .support_ant_gain = false, + .ul_tb_waveform_ctrl = false, + .ul_tb_pwr_diff = false, ++ .rx_freq_frome_ie = false, + .hw_sec_hdr = true, + .hw_mgmt_tx_encrypt = true, + .rf_path_num = 2, +-- +2.39.5 + diff --git a/queue-6.14/wifi-rtw89-set-force-he-tb-mode-when-connecting-to-1.patch b/queue-6.14/wifi-rtw89-set-force-he-tb-mode-when-connecting-to-1.patch new file mode 100644 index 0000000000..7fbd73ba16 --- /dev/null +++ b/queue-6.14/wifi-rtw89-set-force-he-tb-mode-when-connecting-to-1.patch @@ -0,0 +1,105 @@ +From 694dfc113e44dca46df8a6149f6fc6b0f706f46a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Mar 2025 10:11:44 +0800 +Subject: wifi: rtw89: set force HE TB mode when connecting to 11ax AP + +From: Dian-Syuan Yang + +[ Upstream commit a9b56f219a0fa550f92e65ac58443a7892380e09 ] + +Some of 11ax AP set the UL HE-SIG-A2 reserved subfield to all 0s, which +will cause the 11be chip to recognize trigger frame as EHT. We propose +a method to bypass the "UL HE-SIG-A2 reserved subfield" and always uses +HE TB in response to the AP's trigger frame. + +Signed-off-by: Dian-Syuan Yang +Signed-off-by: Ping-Ke Shih +Link: https://patch.msgid.link/20250306021144.12854-6-pkshih@realtek.com +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/realtek/rtw89/mac.c | 26 +++++++++++++++++++ + drivers/net/wireless/realtek/rtw89/mac.h | 2 ++ + drivers/net/wireless/realtek/rtw89/mac80211.c | 1 + + drivers/net/wireless/realtek/rtw89/reg.h | 4 +++ + 4 files changed, 33 insertions(+) + +diff --git a/drivers/net/wireless/realtek/rtw89/mac.c b/drivers/net/wireless/realtek/rtw89/mac.c +index a37c6d525d6f0..2c74d7781bd40 100644 +--- a/drivers/net/wireless/realtek/rtw89/mac.c ++++ b/drivers/net/wireless/realtek/rtw89/mac.c +@@ -4826,6 +4826,32 @@ void rtw89_mac_set_he_obss_narrow_bw_ru(struct rtw89_dev *rtwdev, + rtw89_write32_set(rtwdev, reg, mac->narrow_bw_ru_dis.mask); + } + ++void rtw89_mac_set_he_tb(struct rtw89_dev *rtwdev, ++ struct rtw89_vif_link *rtwvif_link) ++{ ++ struct ieee80211_bss_conf *bss_conf; ++ bool set; ++ u32 reg; ++ ++ if (rtwdev->chip->chip_gen != RTW89_CHIP_BE) ++ return; ++ ++ rcu_read_lock(); ++ ++ bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true); ++ set = bss_conf->he_support && !bss_conf->eht_support; ++ ++ rcu_read_unlock(); ++ ++ reg = rtw89_mac_reg_by_idx(rtwdev, R_BE_CLIENT_OM_CTRL, ++ rtwvif_link->mac_idx); ++ ++ if (set) ++ rtw89_write32_set(rtwdev, reg, B_BE_TRIG_DIS_EHTTB); ++ else ++ rtw89_write32_clr(rtwdev, reg, B_BE_TRIG_DIS_EHTTB); ++} ++ + void rtw89_mac_stop_ap(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link) + { + rtw89_mac_port_cfg_func_sw(rtwdev, rtwvif_link); +diff --git a/drivers/net/wireless/realtek/rtw89/mac.h b/drivers/net/wireless/realtek/rtw89/mac.h +index 8edea96d037f6..373366a602e0b 100644 +--- a/drivers/net/wireless/realtek/rtw89/mac.h ++++ b/drivers/net/wireless/realtek/rtw89/mac.h +@@ -1185,6 +1185,8 @@ void rtw89_mac_port_cfg_rx_sync(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, bool en); + void rtw89_mac_set_he_obss_narrow_bw_ru(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link); ++void rtw89_mac_set_he_tb(struct rtw89_dev *rtwdev, ++ struct rtw89_vif_link *rtwvif_link); + void rtw89_mac_stop_ap(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link); + void rtw89_mac_enable_beacon_for_ap_vifs(struct rtw89_dev *rtwdev, bool en); + int rtw89_mac_remove_vif(struct rtw89_dev *rtwdev, struct rtw89_vif_link *vif); +diff --git a/drivers/net/wireless/realtek/rtw89/mac80211.c b/drivers/net/wireless/realtek/rtw89/mac80211.c +index b3669e0074df9..7c9b53a9ba3b7 100644 +--- a/drivers/net/wireless/realtek/rtw89/mac80211.c ++++ b/drivers/net/wireless/realtek/rtw89/mac80211.c +@@ -670,6 +670,7 @@ static void __rtw89_ops_bss_link_assoc(struct rtw89_dev *rtwdev, + rtw89_chip_cfg_txpwr_ul_tb_offset(rtwdev, rtwvif_link); + rtw89_mac_port_update(rtwdev, rtwvif_link); + rtw89_mac_set_he_obss_narrow_bw_ru(rtwdev, rtwvif_link); ++ rtw89_mac_set_he_tb(rtwdev, rtwvif_link); + } + + static void __rtw89_ops_bss_assoc(struct rtw89_dev *rtwdev, +diff --git a/drivers/net/wireless/realtek/rtw89/reg.h b/drivers/net/wireless/realtek/rtw89/reg.h +index 10d0efa7a58ef..850ae5bf50ef3 100644 +--- a/drivers/net/wireless/realtek/rtw89/reg.h ++++ b/drivers/net/wireless/realtek/rtw89/reg.h +@@ -7095,6 +7095,10 @@ + #define B_BE_MACLBK_RDY_NUM_MASK GENMASK(7, 3) + #define B_BE_MACLBK_EN BIT(0) + ++#define R_BE_CLIENT_OM_CTRL 0x11040 ++#define R_BE_CLIENT_OM_CTRL_C1 0x15040 ++#define B_BE_TRIG_DIS_EHTTB BIT(24) ++ + #define R_BE_WMAC_NAV_CTL 0x11080 + #define R_BE_WMAC_NAV_CTL_C1 0x15080 + #define B_BE_WMAC_NAV_UPPER_EN BIT(26) +-- +2.39.5 + diff --git a/queue-6.14/x86-amd_node-add-smn-offsets-to-exclusive-region-acc.patch b/queue-6.14/x86-amd_node-add-smn-offsets-to-exclusive-region-acc.patch new file mode 100644 index 0000000000..ae124cdc2b --- /dev/null +++ b/queue-6.14/x86-amd_node-add-smn-offsets-to-exclusive-region-acc.patch @@ -0,0 +1,103 @@ +From 20180ecc6e94dc891504d85cf375881e35d9d205 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 30 Jan 2025 19:48:56 +0000 +Subject: x86/amd_node: Add SMN offsets to exclusive region access + +From: Mario Limonciello + +[ Upstream commit 83518453074d1f3eadbf7e61652b608a60087317 ] + +Offsets 0x60 and 0x64 are used internally by kernel drivers that call +the amd_smn_read() and amd_smn_write() functions. If userspace accesses +the regions at the same time as the kernel it may cause malfunctions in +drivers using the offsets. + +Add these offsets to the exclusions so that the kernel is tainted if a +non locked down userspace tries to access them. + +Signed-off-by: Mario Limonciello +Signed-off-by: Yazen Ghannam +Signed-off-by: Borislav Petkov (AMD) +Signed-off-by: Ingo Molnar +Link: https://lore.kernel.org/r/20250130-wip-x86-amd-nb-cleanup-v4-2-b5cc997e471b@amd.com +Signed-off-by: Sasha Levin +--- + arch/x86/kernel/amd_node.c | 41 ++++++++++++++++++++++++++++++++++++++ + 1 file changed, 41 insertions(+) + +diff --git a/arch/x86/kernel/amd_node.c b/arch/x86/kernel/amd_node.c +index 65045f223c10a..ac571948cb353 100644 +--- a/arch/x86/kernel/amd_node.c ++++ b/arch/x86/kernel/amd_node.c +@@ -93,6 +93,7 @@ static struct pci_dev **amd_roots; + + /* Protect the PCI config register pairs used for SMN. */ + static DEFINE_MUTEX(smn_mutex); ++static bool smn_exclusive; + + #define SMN_INDEX_OFFSET 0x60 + #define SMN_DATA_OFFSET 0x64 +@@ -149,6 +150,9 @@ static int __amd_smn_rw(u8 i_off, u8 d_off, u16 node, u32 address, u32 *value, b + if (!root) + return err; + ++ if (!smn_exclusive) ++ return err; ++ + guard(mutex)(&smn_mutex); + + err = pci_write_config_dword(root, i_off, address); +@@ -202,6 +206,39 @@ static int amd_cache_roots(void) + return 0; + } + ++static int reserve_root_config_spaces(void) ++{ ++ struct pci_dev *root = NULL; ++ struct pci_bus *bus = NULL; ++ ++ while ((bus = pci_find_next_bus(bus))) { ++ /* Root device is Device 0 Function 0 on each Primary Bus. */ ++ root = pci_get_slot(bus, 0); ++ if (!root) ++ continue; ++ ++ if (root->vendor != PCI_VENDOR_ID_AMD && ++ root->vendor != PCI_VENDOR_ID_HYGON) ++ continue; ++ ++ pci_dbg(root, "Reserving PCI config space\n"); ++ ++ /* ++ * There are a few SMN index/data pairs and other registers ++ * that shouldn't be accessed by user space. ++ * So reserve the entire PCI config space for simplicity rather ++ * than covering specific registers piecemeal. ++ */ ++ if (!pci_request_config_region_exclusive(root, 0, PCI_CFG_SPACE_SIZE, NULL)) { ++ pci_err(root, "Failed to reserve config space\n"); ++ return -EEXIST; ++ } ++ } ++ ++ smn_exclusive = true; ++ return 0; ++} ++ + static int __init amd_smn_init(void) + { + int err; +@@ -218,6 +255,10 @@ static int __init amd_smn_init(void) + if (err) + return err; + ++ err = reserve_root_config_spaces(); ++ if (err) ++ return err; ++ + return 0; + } + +-- +2.39.5 + diff --git a/queue-6.14/x86-boot-disable-stack-protector-for-early-boot-code.patch b/queue-6.14/x86-boot-disable-stack-protector-for-early-boot-code.patch new file mode 100644 index 0000000000..c980cdc4a1 --- /dev/null +++ b/queue-6.14/x86-boot-disable-stack-protector-for-early-boot-code.patch @@ -0,0 +1,44 @@ +From 4fef5393716667e290946e84de38b209bda14ad6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 23 Jan 2025 14:07:35 -0500 +Subject: x86/boot: Disable stack protector for early boot code + +From: Brian Gerst + +[ Upstream commit a9a76b38aaf577887103e3ebb41d70e6aa5a4b19 ] + +On 64-bit, this will prevent crashes when the canary access is changed +from %gs:40 to %gs:__stack_chk_guard(%rip). RIP-relative addresses from +the identity-mapped early boot code will target the wrong address with +zero-based percpu. KASLR could then shift that address to an unmapped +page causing a crash on boot. + +This early boot code runs well before user-space is active and does not +need stack protector enabled. + +Signed-off-by: Brian Gerst +Signed-off-by: Ingo Molnar +Reviewed-by: Ard Biesheuvel +Cc: Linus Torvalds +Link: https://lore.kernel.org/r/20250123190747.745588-4-brgerst@gmail.com +Signed-off-by: Sasha Levin +--- + arch/x86/kernel/Makefile | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile +index b43eb7e384eba..84cfa179802c3 100644 +--- a/arch/x86/kernel/Makefile ++++ b/arch/x86/kernel/Makefile +@@ -44,6 +44,8 @@ KCOV_INSTRUMENT_unwind_orc.o := n + KCOV_INSTRUMENT_unwind_frame.o := n + KCOV_INSTRUMENT_unwind_guess.o := n + ++CFLAGS_head32.o := -fno-stack-protector ++CFLAGS_head64.o := -fno-stack-protector + CFLAGS_irq.o := -I $(src)/../include/asm/trace + + obj-y += head_$(BITS).o +-- +2.39.5 + diff --git a/queue-6.14/x86-boot-mark-start_secondary-with-__noendbr.patch b/queue-6.14/x86-boot-mark-start_secondary-with-__noendbr.patch new file mode 100644 index 0000000000..56961e3cdc --- /dev/null +++ b/queue-6.14/x86-boot-mark-start_secondary-with-__noendbr.patch @@ -0,0 +1,71 @@ +From 2b095ffb92dcc2b39a11b125be14f0d58b784c69 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 7 Feb 2025 13:15:34 +0100 +Subject: x86/boot: Mark start_secondary() with __noendbr + +From: Peter Zijlstra + +[ Upstream commit 93f16a1ab78ca56e3cd997d1ea54c214774781ac ] + +The handoff between the boot stubs and start_secondary() are before IBT is +enabled and is definitely not subject to kCFI. As such, suppress all that for +this function. + +Notably when the ENDBR poison would become fatal (ud1 instead of nop) this will +trigger a tripple fault because we haven't set up the IDT to handle #UD yet. + +Signed-off-by: Peter Zijlstra (Intel) +Reviewed-by: Sami Tolvanen +Link: https://lore.kernel.org/r/20250207122546.509520369@infradead.org +Signed-off-by: Sasha Levin +--- + arch/x86/kernel/smpboot.c | 3 ++- + include/linux/objtool.h | 4 +++- + 2 files changed, 5 insertions(+), 2 deletions(-) + +diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c +index 3d5069ee297bf..463634b138bbb 100644 +--- a/arch/x86/kernel/smpboot.c ++++ b/arch/x86/kernel/smpboot.c +@@ -229,7 +229,7 @@ static void ap_calibrate_delay(void) + /* + * Activate a secondary processor. + */ +-static void notrace start_secondary(void *unused) ++static void notrace __noendbr start_secondary(void *unused) + { + /* + * Don't put *anything* except direct CPU state initialization +@@ -314,6 +314,7 @@ static void notrace start_secondary(void *unused) + wmb(); + cpu_startup_entry(CPUHP_AP_ONLINE_IDLE); + } ++ANNOTATE_NOENDBR_SYM(start_secondary); + + /* + * The bootstrap kernel entry code has set these up. Save them for +diff --git a/include/linux/objtool.h b/include/linux/objtool.h +index c722a921165ba..3ca965a2ddc80 100644 +--- a/include/linux/objtool.h ++++ b/include/linux/objtool.h +@@ -128,7 +128,7 @@ + #define UNWIND_HINT(type, sp_reg, sp_offset, signal) "\n\t" + #define STACK_FRAME_NON_STANDARD(func) + #define STACK_FRAME_NON_STANDARD_FP(func) +-#define __ASM_ANNOTATE(label, type) ++#define __ASM_ANNOTATE(label, type) "" + #define ASM_ANNOTATE(type) + #else + .macro UNWIND_HINT type:req sp_reg=0 sp_offset=0 signal=0 +@@ -147,6 +147,8 @@ + * these relocations will never be used for indirect calls. + */ + #define ANNOTATE_NOENDBR ASM_ANNOTATE(ANNOTYPE_NOENDBR) ++#define ANNOTATE_NOENDBR_SYM(sym) asm(__ASM_ANNOTATE(sym, ANNOTYPE_NOENDBR)) ++ + /* + * This should be used immediately before an indirect jump/call. It tells + * objtool the subsequent indirect jump/call is vouched safe for retpoline +-- +2.39.5 + diff --git a/queue-6.14/x86-bugs-kvm-add-support-for-srso_msr_fix.patch b/queue-6.14/x86-bugs-kvm-add-support-for-srso_msr_fix.patch new file mode 100644 index 0000000000..510fac7546 --- /dev/null +++ b/queue-6.14/x86-bugs-kvm-add-support-for-srso_msr_fix.patch @@ -0,0 +1,208 @@ +From 6df764c77bf53fde074bac365d16ca7b0f47a889 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 18 Feb 2025 12:13:33 +0100 +Subject: x86/bugs: KVM: Add support for SRSO_MSR_FIX + +From: Borislav Petkov + +[ Upstream commit 8442df2b49ed9bcd67833ad4f091d15ac91efd00 ] + +Add support for + + CPUID Fn8000_0021_EAX[31] (SRSO_MSR_FIX). If this bit is 1, it + indicates that software may use MSR BP_CFG[BpSpecReduce] to mitigate + SRSO. + +Enable BpSpecReduce to mitigate SRSO across guest/host boundaries. + +Switch back to enabling the bit when virtualization is enabled and to +clear the bit when virtualization is disabled because using a MSR slot +would clear the bit when the guest is exited and any training the guest +has done, would potentially influence the host kernel when execution +enters the kernel and hasn't VMRUN the guest yet. + +More detail on the public thread in Link below. + +Co-developed-by: Sean Christopherson +Signed-off-by: Sean Christopherson +Signed-off-by: Borislav Petkov (AMD) +Link: https://lore.kernel.org/r/20241202120416.6054-1-bp@kernel.org +Signed-off-by: Sasha Levin +--- + Documentation/admin-guide/hw-vuln/srso.rst | 13 ++++++++++++ + arch/x86/include/asm/cpufeatures.h | 4 ++++ + arch/x86/include/asm/msr-index.h | 1 + + arch/x86/kernel/cpu/bugs.c | 24 ++++++++++++++++++---- + arch/x86/kvm/svm/svm.c | 6 ++++++ + arch/x86/lib/msr.c | 2 ++ + 6 files changed, 46 insertions(+), 4 deletions(-) + +diff --git a/Documentation/admin-guide/hw-vuln/srso.rst b/Documentation/admin-guide/hw-vuln/srso.rst +index 2ad1c05b8c883..66af95251a3d1 100644 +--- a/Documentation/admin-guide/hw-vuln/srso.rst ++++ b/Documentation/admin-guide/hw-vuln/srso.rst +@@ -104,7 +104,20 @@ The possible values in this file are: + + (spec_rstack_overflow=ibpb-vmexit) + ++ * 'Mitigation: Reduced Speculation': + ++ This mitigation gets automatically enabled when the above one "IBPB on ++ VMEXIT" has been selected and the CPU supports the BpSpecReduce bit. ++ ++ It gets automatically enabled on machines which have the ++ SRSO_USER_KERNEL_NO=1 CPUID bit. In that case, the code logic is to switch ++ to the above =ibpb-vmexit mitigation because the user/kernel boundary is ++ not affected anymore and thus "safe RET" is not needed. ++ ++ After enabling the IBPB on VMEXIT mitigation option, the BpSpecReduce bit ++ is detected (functionality present on all such machines) and that ++ practically overrides IBPB on VMEXIT as it has a lot less performance ++ impact and takes care of the guest->host attack vector too. + + In order to exploit vulnerability, an attacker needs to: + +diff --git a/arch/x86/include/asm/cpufeatures.h b/arch/x86/include/asm/cpufeatures.h +index b8fbd847c34af..06631474ede29 100644 +--- a/arch/x86/include/asm/cpufeatures.h ++++ b/arch/x86/include/asm/cpufeatures.h +@@ -468,6 +468,10 @@ + #define X86_FEATURE_IBPB_BRTYPE (20*32+28) /* MSR_PRED_CMD[IBPB] flushes all branch type predictions */ + #define X86_FEATURE_SRSO_NO (20*32+29) /* CPU is not affected by SRSO */ + #define X86_FEATURE_SRSO_USER_KERNEL_NO (20*32+30) /* CPU is not affected by SRSO across user/kernel boundaries */ ++#define X86_FEATURE_SRSO_BP_SPEC_REDUCE (20*32+31) /* ++ * BP_CFG[BpSpecReduce] can be used to mitigate SRSO for VMs. ++ * (SRSO_MSR_FIX in the official doc). ++ */ + + /* + * Extended auxiliary flags: Linux defined - for features scattered in various +diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h +index d4308e78a009a..9f402a7b211b9 100644 +--- a/arch/x86/include/asm/msr-index.h ++++ b/arch/x86/include/asm/msr-index.h +@@ -729,6 +729,7 @@ + + /* Zen4 */ + #define MSR_ZEN4_BP_CFG 0xc001102e ++#define MSR_ZEN4_BP_CFG_BP_SPEC_REDUCE_BIT 4 + #define MSR_ZEN4_BP_CFG_SHARED_BTB_FIX_BIT 5 + + /* Fam 19h MSRs */ +diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c +index e0e0ecc401947..f1954147cc5d5 100644 +--- a/arch/x86/kernel/cpu/bugs.c ++++ b/arch/x86/kernel/cpu/bugs.c +@@ -2675,6 +2675,7 @@ enum srso_mitigation { + SRSO_MITIGATION_SAFE_RET, + SRSO_MITIGATION_IBPB, + SRSO_MITIGATION_IBPB_ON_VMEXIT, ++ SRSO_MITIGATION_BP_SPEC_REDUCE, + }; + + enum srso_mitigation_cmd { +@@ -2692,7 +2693,8 @@ static const char * const srso_strings[] = { + [SRSO_MITIGATION_MICROCODE] = "Vulnerable: Microcode, no safe RET", + [SRSO_MITIGATION_SAFE_RET] = "Mitigation: Safe RET", + [SRSO_MITIGATION_IBPB] = "Mitigation: IBPB", +- [SRSO_MITIGATION_IBPB_ON_VMEXIT] = "Mitigation: IBPB on VMEXIT only" ++ [SRSO_MITIGATION_IBPB_ON_VMEXIT] = "Mitigation: IBPB on VMEXIT only", ++ [SRSO_MITIGATION_BP_SPEC_REDUCE] = "Mitigation: Reduced Speculation" + }; + + static enum srso_mitigation srso_mitigation __ro_after_init = SRSO_MITIGATION_NONE; +@@ -2731,7 +2733,7 @@ static void __init srso_select_mitigation(void) + srso_cmd == SRSO_CMD_OFF) { + if (boot_cpu_has(X86_FEATURE_SBPB)) + x86_pred_cmd = PRED_CMD_SBPB; +- return; ++ goto out; + } + + if (has_microcode) { +@@ -2743,7 +2745,7 @@ static void __init srso_select_mitigation(void) + */ + if (boot_cpu_data.x86 < 0x19 && !cpu_smt_possible()) { + setup_force_cpu_cap(X86_FEATURE_SRSO_NO); +- return; ++ goto out; + } + + if (retbleed_mitigation == RETBLEED_MITIGATION_IBPB) { +@@ -2823,6 +2825,12 @@ static void __init srso_select_mitigation(void) + + ibpb_on_vmexit: + case SRSO_CMD_IBPB_ON_VMEXIT: ++ if (boot_cpu_has(X86_FEATURE_SRSO_BP_SPEC_REDUCE)) { ++ pr_notice("Reducing speculation to address VM/HV SRSO attack vector.\n"); ++ srso_mitigation = SRSO_MITIGATION_BP_SPEC_REDUCE; ++ break; ++ } ++ + if (IS_ENABLED(CONFIG_MITIGATION_IBPB_ENTRY)) { + if (has_microcode) { + setup_force_cpu_cap(X86_FEATURE_IBPB_ON_VMEXIT); +@@ -2844,7 +2852,15 @@ static void __init srso_select_mitigation(void) + } + + out: +- pr_info("%s\n", srso_strings[srso_mitigation]); ++ /* ++ * Clear the feature flag if this mitigation is not selected as that ++ * feature flag controls the BpSpecReduce MSR bit toggling in KVM. ++ */ ++ if (srso_mitigation != SRSO_MITIGATION_BP_SPEC_REDUCE) ++ setup_clear_cpu_cap(X86_FEATURE_SRSO_BP_SPEC_REDUCE); ++ ++ if (srso_mitigation != SRSO_MITIGATION_NONE) ++ pr_info("%s\n", srso_strings[srso_mitigation]); + } + + #undef pr_fmt +diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c +index 282c91c6aa338..b8f12b808d83a 100644 +--- a/arch/x86/kvm/svm/svm.c ++++ b/arch/x86/kvm/svm/svm.c +@@ -607,6 +607,9 @@ static void svm_disable_virtualization_cpu(void) + kvm_cpu_svm_disable(); + + amd_pmu_disable_virt(); ++ ++ if (cpu_feature_enabled(X86_FEATURE_SRSO_BP_SPEC_REDUCE)) ++ msr_clear_bit(MSR_ZEN4_BP_CFG, MSR_ZEN4_BP_CFG_BP_SPEC_REDUCE_BIT); + } + + static int svm_enable_virtualization_cpu(void) +@@ -684,6 +687,9 @@ static int svm_enable_virtualization_cpu(void) + rdmsr(MSR_TSC_AUX, sev_es_host_save_area(sd)->tsc_aux, msr_hi); + } + ++ if (cpu_feature_enabled(X86_FEATURE_SRSO_BP_SPEC_REDUCE)) ++ msr_set_bit(MSR_ZEN4_BP_CFG, MSR_ZEN4_BP_CFG_BP_SPEC_REDUCE_BIT); ++ + return 0; + } + +diff --git a/arch/x86/lib/msr.c b/arch/x86/lib/msr.c +index 4bf4fad5b148e..5a18ecc04a6c3 100644 +--- a/arch/x86/lib/msr.c ++++ b/arch/x86/lib/msr.c +@@ -103,6 +103,7 @@ int msr_set_bit(u32 msr, u8 bit) + { + return __flip_bit(msr, bit, true); + } ++EXPORT_SYMBOL_GPL(msr_set_bit); + + /** + * msr_clear_bit - Clear @bit in a MSR @msr. +@@ -118,6 +119,7 @@ int msr_clear_bit(u32 msr, u8 bit) + { + return __flip_bit(msr, bit, false); + } ++EXPORT_SYMBOL_GPL(msr_clear_bit); + + #ifdef CONFIG_TRACEPOINTS + void do_trace_write_msr(unsigned int msr, u64 val, int failed) +-- +2.39.5 + diff --git a/queue-6.14/x86-bugs-make-spectre-user-default-depend-on-mitigat.patch b/queue-6.14/x86-bugs-make-spectre-user-default-depend-on-mitigat.patch new file mode 100644 index 0000000000..96bfa9bda6 --- /dev/null +++ b/queue-6.14/x86-bugs-make-spectre-user-default-depend-on-mitigat.patch @@ -0,0 +1,96 @@ +From 57693499df99672024f45f2ba16ab3f37d5a4a1d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 31 Oct 2024 04:06:17 -0700 +Subject: x86/bugs: Make spectre user default depend on MITIGATION_SPECTRE_V2 + +From: Breno Leitao + +[ Upstream commit 98fdaeb296f51ef08e727a7cc72e5b5c864c4f4d ] + +Change the default value of spectre v2 in user mode to respect the +CONFIG_MITIGATION_SPECTRE_V2 config option. + +Currently, user mode spectre v2 is set to auto +(SPECTRE_V2_USER_CMD_AUTO) by default, even if +CONFIG_MITIGATION_SPECTRE_V2 is disabled. + +Set the spectre_v2 value to auto (SPECTRE_V2_USER_CMD_AUTO) if the +Spectre v2 config (CONFIG_MITIGATION_SPECTRE_V2) is enabled, otherwise +set the value to none (SPECTRE_V2_USER_CMD_NONE). + +Important to say the command line argument "spectre_v2_user" overwrites +the default value in both cases. + +When CONFIG_MITIGATION_SPECTRE_V2 is not set, users have the flexibility +to opt-in for specific mitigations independently. In this scenario, +setting spectre_v2= will not enable spectre_v2_user=, and command line +options spectre_v2_user and spectre_v2 are independent when +CONFIG_MITIGATION_SPECTRE_V2=n. + +Signed-off-by: Breno Leitao +Signed-off-by: Ingo Molnar +Reviewed-by: Pawan Gupta +Acked-by: Josh Poimboeuf +Cc: Peter Zijlstra +Cc: David Kaplan +Link: https://lore.kernel.org/r/20241031-x86_bugs_last_v2-v2-2-b7ff1dab840e@debian.org +Signed-off-by: Sasha Levin +--- + Documentation/admin-guide/kernel-parameters.txt | 2 ++ + arch/x86/kernel/cpu/bugs.c | 10 +++++++--- + 2 files changed, 9 insertions(+), 3 deletions(-) + +diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt +index f9e11cebc598c..a8e98f75b610a 100644 +--- a/Documentation/admin-guide/kernel-parameters.txt ++++ b/Documentation/admin-guide/kernel-parameters.txt +@@ -6602,6 +6602,8 @@ + + Selecting 'on' will also enable the mitigation + against user space to user space task attacks. ++ Selecting specific mitigation does not force enable ++ user mitigations. + + Selecting 'off' will disable both the kernel and + the user space protections. +diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c +index b6994993c39f7..e0e0ecc401947 100644 +--- a/arch/x86/kernel/cpu/bugs.c ++++ b/arch/x86/kernel/cpu/bugs.c +@@ -1442,9 +1442,13 @@ static __ro_after_init enum spectre_v2_mitigation_cmd spectre_v2_cmd; + static enum spectre_v2_user_cmd __init + spectre_v2_parse_user_cmdline(void) + { ++ enum spectre_v2_user_cmd mode; + char arg[20]; + int ret, i; + ++ mode = IS_ENABLED(CONFIG_MITIGATION_SPECTRE_V2) ? ++ SPECTRE_V2_USER_CMD_AUTO : SPECTRE_V2_USER_CMD_NONE; ++ + switch (spectre_v2_cmd) { + case SPECTRE_V2_CMD_NONE: + return SPECTRE_V2_USER_CMD_NONE; +@@ -1457,7 +1461,7 @@ spectre_v2_parse_user_cmdline(void) + ret = cmdline_find_option(boot_command_line, "spectre_v2_user", + arg, sizeof(arg)); + if (ret < 0) +- return SPECTRE_V2_USER_CMD_AUTO; ++ return mode; + + for (i = 0; i < ARRAY_SIZE(v2_user_options); i++) { + if (match_option(arg, ret, v2_user_options[i].option)) { +@@ -1467,8 +1471,8 @@ spectre_v2_parse_user_cmdline(void) + } + } + +- pr_err("Unknown user space protection option (%s). Switching to AUTO select\n", arg); +- return SPECTRE_V2_USER_CMD_AUTO; ++ pr_err("Unknown user space protection option (%s). Switching to default\n", arg); ++ return mode; + } + + static inline bool spectre_v2_in_ibrs_mode(enum spectre_v2_mitigation mode) +-- +2.39.5 + diff --git a/queue-6.14/x86-build-fix-broken-copy-command-in-genimage.sh-whe.patch b/queue-6.14/x86-build-fix-broken-copy-command-in-genimage.sh-whe.patch new file mode 100644 index 0000000000..a3cda7de8c --- /dev/null +++ b/queue-6.14/x86-build-fix-broken-copy-command-in-genimage.sh-whe.patch @@ -0,0 +1,58 @@ +From e885695a8f380dde4e575ef6b6c9ca6fe647667a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 10 Jan 2025 12:05:00 +0000 +Subject: x86/build: Fix broken copy command in genimage.sh when making + isoimage + +From: Nir Lichtman + +[ Upstream commit e451630226bd09dc730eedb4e32cab1cc7155ae8 ] + +Problem: Currently when running the "make isoimage" command there is an +error related to wrong parameters passed to the cp command: + + "cp: missing destination file operand after 'arch/x86/boot/isoimage/'" + +This is caused because FDINITRDS is an empty array. + +Solution: Check if FDINITRDS is empty before executing the "cp" command, +similar to how it is done in the case of hdimage. + +Signed-off-by: Nir Lichtman +Signed-off-by: Ingo Molnar +Cc: "H. Peter Anvin" +Cc: Ard Biesheuvel +Cc: Masahiro Yamada +Cc: Michal Marek +Link: https://lore.kernel.org/r/20250110120500.GA923218@lichtman.org +Signed-off-by: Sasha Levin +--- + arch/x86/boot/genimage.sh | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/arch/x86/boot/genimage.sh b/arch/x86/boot/genimage.sh +index c9299aeb7333e..3882ead513f74 100644 +--- a/arch/x86/boot/genimage.sh ++++ b/arch/x86/boot/genimage.sh +@@ -22,6 +22,7 @@ + # This script requires: + # bash + # syslinux ++# genisoimage + # mtools (for fdimage* and hdimage) + # edk2/OVMF (for hdimage) + # +@@ -251,7 +252,9 @@ geniso() { + cp "$isolinux" "$ldlinux" "$tmp_dir" + cp "$FBZIMAGE" "$tmp_dir"/linux + echo default linux "$KCMDLINE" > "$tmp_dir"/isolinux.cfg +- cp "${FDINITRDS[@]}" "$tmp_dir"/ ++ if [ ${#FDINITRDS[@]} -gt 0 ]; then ++ cp "${FDINITRDS[@]}" "$tmp_dir"/ ++ fi + genisoimage -J -r -appid 'LINUX_BOOT' -input-charset=utf-8 \ + -quiet -o "$FIMAGE" -b isolinux.bin \ + -c boot.cat -no-emul-boot -boot-load-size 4 \ +-- +2.39.5 + diff --git a/queue-6.14/x86-fred-fix-system-hang-during-s4-resume-with-fred-.patch b/queue-6.14/x86-fred-fix-system-hang-during-s4-resume-with-fred-.patch new file mode 100644 index 0000000000..9dc01894ac --- /dev/null +++ b/queue-6.14/x86-fred-fix-system-hang-during-s4-resume-with-fred-.patch @@ -0,0 +1,76 @@ +From 089effee814b14c6cff9e1ace77996688d6a9bf2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 1 Apr 2025 00:57:27 -0700 +Subject: x86/fred: Fix system hang during S4 resume with FRED enabled + +From: Xin Li (Intel) + +[ Upstream commit e5f1e8af9c9e151ecd665f6d2e36fb25fec3b110 ] + +Upon a wakeup from S4, the restore kernel starts and initializes the +FRED MSRs as needed from its perspective. It then loads a hibernation +image, including the image kernel, and attempts to load image pages +directly into their original page frames used before hibernation unless +those frames are currently in use. Once all pages are moved to their +original locations, it jumps to a "trampoline" page in the image kernel. + +At this point, the image kernel takes control, but the FRED MSRs still +contain values set by the restore kernel, which may differ from those +set by the image kernel before hibernation. Therefore, the image kernel +must ensure the FRED MSRs have the same values as before hibernation. +Since these values depend only on the location of the kernel text and +data, they can be recomputed from scratch. + +Reported-by: Xi Pardee +Reported-by: Todd Brandt +Tested-by: Todd Brandt +Suggested-by: H. Peter Anvin (Intel) +Signed-off-by: Xin Li (Intel) +Signed-off-by: Ingo Molnar +Reviewed-by: Rafael J. Wysocki +Reviewed-by: H. Peter Anvin (Intel) +Cc: Andy Lutomirski +Cc: Brian Gerst +Cc: Juergen Gross +Cc: Linus Torvalds +Link: https://lore.kernel.org/r/20250401075728.3626147-1-xin@zytor.com +Signed-off-by: Sasha Levin +--- + arch/x86/power/cpu.c | 14 ++++++++++++++ + 1 file changed, 14 insertions(+) + +diff --git a/arch/x86/power/cpu.c b/arch/x86/power/cpu.c +index 63230ff8cf4f0..08e76a5ca1553 100644 +--- a/arch/x86/power/cpu.c ++++ b/arch/x86/power/cpu.c +@@ -27,6 +27,7 @@ + #include + #include + #include ++#include + + #ifdef CONFIG_X86_32 + __visible unsigned long saved_context_ebx; +@@ -231,6 +232,19 @@ static void notrace __restore_processor_state(struct saved_context *ctxt) + */ + #ifdef CONFIG_X86_64 + wrmsrl(MSR_GS_BASE, ctxt->kernelmode_gs_base); ++ ++ /* ++ * Reinitialize FRED to ensure the FRED MSRs contain the same values ++ * as before hibernation. ++ * ++ * Note, the setup of FRED RSPs requires access to percpu data ++ * structures. Therefore, FRED reinitialization can only occur after ++ * the percpu access pointer (i.e., MSR_GS_BASE) is restored. ++ */ ++ if (ctxt->cr4 & X86_CR4_FRED) { ++ cpu_init_fred_exceptions(); ++ cpu_init_fred_rsps(); ++ } + #else + loadsegment(fs, __KERNEL_PERCPU); + #endif +-- +2.39.5 + diff --git a/queue-6.14/x86-headers-replace-__assembly__-with-__assembler__-.patch b/queue-6.14/x86-headers-replace-__assembly__-with-__assembler__-.patch new file mode 100644 index 0000000000..688491c033 --- /dev/null +++ b/queue-6.14/x86-headers-replace-__assembly__-with-__assembler__-.patch @@ -0,0 +1,2152 @@ +From 33c2fd3e499ad954c10239300b231df207eb7924 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 19 Mar 2025 11:30:57 +0100 +Subject: x86/headers: Replace __ASSEMBLY__ with __ASSEMBLER__ in non-UAPI + headers + +From: Thomas Huth + +[ Upstream commit 24a295e4ef1ca8e97d8b7015e1887b6e83e1c8be ] + +While the GCC and Clang compilers already define __ASSEMBLER__ +automatically when compiling assembly code, __ASSEMBLY__ is a +macro that only gets defined by the Makefiles in the kernel. + +This can be very confusing when switching between userspace +and kernelspace coding, or when dealing with UAPI headers that +rather should use __ASSEMBLER__ instead. So let's standardize on +the __ASSEMBLER__ macro that is provided by the compilers now. + +This is mostly a mechanical patch (done with a simple "sed -i" +statement), with some manual tweaks in , +and that mentioned this macro in comments with some +missing underscores. + +Signed-off-by: Thomas Huth +Signed-off-by: Ingo Molnar +Cc: Brian Gerst +Cc: Juergen Gross +Cc: H. Peter Anvin +Cc: Kees Cook +Cc: Linus Torvalds +Link: https://lore.kernel.org/r/20250314071013.1575167-38-thuth@redhat.com +Signed-off-by: Sasha Levin +--- + arch/x86/boot/boot.h | 4 ++-- + arch/x86/entry/vdso/extable.h | 2 +- + arch/x86/include/asm/alternative.h | 6 +++--- + arch/x86/include/asm/asm.h | 10 +++++----- + arch/x86/include/asm/boot.h | 2 +- + arch/x86/include/asm/cpufeature.h | 4 ++-- + arch/x86/include/asm/cpumask.h | 4 ++-- + arch/x86/include/asm/current.h | 4 ++-- + arch/x86/include/asm/desc_defs.h | 4 ++-- + arch/x86/include/asm/dwarf2.h | 2 +- + arch/x86/include/asm/fixmap.h | 4 ++-- + arch/x86/include/asm/frame.h | 10 +++++----- + arch/x86/include/asm/fred.h | 4 ++-- + arch/x86/include/asm/fsgsbase.h | 4 ++-- + arch/x86/include/asm/ftrace.h | 8 ++++---- + arch/x86/include/asm/hw_irq.h | 4 ++-- + arch/x86/include/asm/ibt.h | 12 ++++++------ + arch/x86/include/asm/idtentry.h | 6 +++--- + arch/x86/include/asm/inst.h | 2 +- + arch/x86/include/asm/irqflags.h | 10 +++++----- + arch/x86/include/asm/jump_label.h | 4 ++-- + arch/x86/include/asm/kasan.h | 2 +- + arch/x86/include/asm/kexec.h | 4 ++-- + arch/x86/include/asm/linkage.h | 6 +++--- + arch/x86/include/asm/mem_encrypt.h | 4 ++-- + arch/x86/include/asm/msr.h | 4 ++-- + arch/x86/include/asm/nops.h | 2 +- + arch/x86/include/asm/nospec-branch.h | 6 +++--- + arch/x86/include/asm/orc_types.h | 4 ++-- + arch/x86/include/asm/page.h | 4 ++-- + arch/x86/include/asm/page_32.h | 4 ++-- + arch/x86/include/asm/page_32_types.h | 4 ++-- + arch/x86/include/asm/page_64.h | 4 ++-- + arch/x86/include/asm/page_64_types.h | 2 +- + arch/x86/include/asm/page_types.h | 4 ++-- + arch/x86/include/asm/paravirt.h | 14 +++++++------- + arch/x86/include/asm/paravirt_types.h | 4 ++-- + arch/x86/include/asm/percpu.h | 4 ++-- + arch/x86/include/asm/pgtable-2level_types.h | 4 ++-- + arch/x86/include/asm/pgtable-3level_types.h | 4 ++-- + arch/x86/include/asm/pgtable-invert.h | 4 ++-- + arch/x86/include/asm/pgtable.h | 12 ++++++------ + arch/x86/include/asm/pgtable_32.h | 4 ++-- + arch/x86/include/asm/pgtable_32_areas.h | 2 +- + arch/x86/include/asm/pgtable_64.h | 6 +++--- + arch/x86/include/asm/pgtable_64_types.h | 4 ++-- + arch/x86/include/asm/pgtable_types.h | 10 +++++----- + arch/x86/include/asm/prom.h | 4 ++-- + arch/x86/include/asm/pti.h | 4 ++-- + arch/x86/include/asm/ptrace.h | 4 ++-- + arch/x86/include/asm/purgatory.h | 4 ++-- + arch/x86/include/asm/pvclock-abi.h | 4 ++-- + arch/x86/include/asm/realmode.h | 4 ++-- + arch/x86/include/asm/segment.h | 8 ++++---- + arch/x86/include/asm/setup.h | 6 +++--- + arch/x86/include/asm/setup_data.h | 4 ++-- + arch/x86/include/asm/shared/tdx.h | 4 ++-- + arch/x86/include/asm/shstk.h | 4 ++-- + arch/x86/include/asm/signal.h | 8 ++++---- + arch/x86/include/asm/smap.h | 6 +++--- + arch/x86/include/asm/smp.h | 4 ++-- + arch/x86/include/asm/tdx.h | 4 ++-- + arch/x86/include/asm/thread_info.h | 12 ++++++------ + arch/x86/include/asm/unwind_hints.h | 4 ++-- + arch/x86/include/asm/vdso/getrandom.h | 4 ++-- + arch/x86/include/asm/vdso/gettimeofday.h | 4 ++-- + arch/x86/include/asm/vdso/processor.h | 4 ++-- + arch/x86/include/asm/vdso/vsyscall.h | 4 ++-- + arch/x86/include/asm/xen/interface.h | 10 +++++----- + arch/x86/include/asm/xen/interface_32.h | 4 ++-- + arch/x86/include/asm/xen/interface_64.h | 4 ++-- + arch/x86/math-emu/control_w.h | 2 +- + arch/x86/math-emu/exception.h | 6 +++--- + arch/x86/math-emu/fpu_emu.h | 6 +++--- + arch/x86/math-emu/status_w.h | 6 +++--- + arch/x86/realmode/rm/realmode.h | 4 ++-- + arch/x86/realmode/rm/wakeup.h | 2 +- + tools/arch/x86/include/asm/asm.h | 8 ++++---- + tools/arch/x86/include/asm/nops.h | 2 +- + tools/arch/x86/include/asm/orc_types.h | 4 ++-- + tools/arch/x86/include/asm/pvclock-abi.h | 4 ++-- + 81 files changed, 201 insertions(+), 201 deletions(-) + +diff --git a/arch/x86/boot/boot.h b/arch/x86/boot/boot.h +index 0f24f7ebec9ba..38f17a1e1e367 100644 +--- a/arch/x86/boot/boot.h ++++ b/arch/x86/boot/boot.h +@@ -16,7 +16,7 @@ + + #define STACK_SIZE 1024 /* Minimum number of bytes for stack */ + +-#ifndef __ASSEMBLY__ ++#ifndef __ASSEMBLER__ + + #include + #include +@@ -327,6 +327,6 @@ void probe_cards(int unsafe); + /* video-vesa.c */ + void vesa_store_edid(void); + +-#endif /* __ASSEMBLY__ */ ++#endif /* __ASSEMBLER__ */ + + #endif /* BOOT_BOOT_H */ +diff --git a/arch/x86/entry/vdso/extable.h b/arch/x86/entry/vdso/extable.h +index b56f6b0129416..baba612b832c3 100644 +--- a/arch/x86/entry/vdso/extable.h ++++ b/arch/x86/entry/vdso/extable.h +@@ -7,7 +7,7 @@ + * vDSO uses a dedicated handler the addresses are relative to the overall + * exception table, not each individual entry. + */ +-#ifdef __ASSEMBLY__ ++#ifdef __ASSEMBLER__ + #define _ASM_VDSO_EXTABLE_HANDLE(from, to) \ + ASM_VDSO_EXTABLE_HANDLE from to + +diff --git a/arch/x86/include/asm/alternative.h b/arch/x86/include/asm/alternative.h +index 9e01490220ece..abfca03f47a79 100644 +--- a/arch/x86/include/asm/alternative.h ++++ b/arch/x86/include/asm/alternative.h +@@ -16,7 +16,7 @@ + #define ALT_DIRECT_CALL(feature) ((ALT_FLAG_DIRECT_CALL << ALT_FLAGS_SHIFT) | (feature)) + #define ALT_CALL_ALWAYS ALT_DIRECT_CALL(X86_FEATURE_ALWAYS) + +-#ifndef __ASSEMBLY__ ++#ifndef __ASSEMBLER__ + + #include + +@@ -318,7 +318,7 @@ static inline int alternatives_text_reserved(void *start, void *end) + void BUG_func(void); + void nop_func(void); + +-#else /* __ASSEMBLY__ */ ++#else /* __ASSEMBLER__ */ + + #ifdef CONFIG_SMP + .macro LOCK_PREFIX +@@ -401,6 +401,6 @@ void nop_func(void); + ALTERNATIVE_2 oldinstr, newinstr_no, X86_FEATURE_ALWAYS, \ + newinstr_yes, ft_flags + +-#endif /* __ASSEMBLY__ */ ++#endif /* __ASSEMBLER__ */ + + #endif /* _ASM_X86_ALTERNATIVE_H */ +diff --git a/arch/x86/include/asm/asm.h b/arch/x86/include/asm/asm.h +index 2bec0c89a95c2..e9653ee72813c 100644 +--- a/arch/x86/include/asm/asm.h ++++ b/arch/x86/include/asm/asm.h +@@ -2,7 +2,7 @@ + #ifndef _ASM_X86_ASM_H + #define _ASM_X86_ASM_H + +-#ifdef __ASSEMBLY__ ++#ifdef __ASSEMBLER__ + # define __ASM_FORM(x, ...) x,## __VA_ARGS__ + # define __ASM_FORM_RAW(x, ...) x,## __VA_ARGS__ + # define __ASM_FORM_COMMA(x, ...) x,## __VA_ARGS__, +@@ -113,7 +113,7 @@ + + #endif + +-#ifndef __ASSEMBLY__ ++#ifndef __ASSEMBLER__ + #ifndef __pic__ + static __always_inline __pure void *rip_rel_ptr(void *p) + { +@@ -144,7 +144,7 @@ static __always_inline __pure void *rip_rel_ptr(void *p) + # include + + /* Exception table entry */ +-#ifdef __ASSEMBLY__ ++#ifdef __ASSEMBLER__ + + # define _ASM_EXTABLE_TYPE(from, to, type) \ + .pushsection "__ex_table","a" ; \ +@@ -164,7 +164,7 @@ static __always_inline __pure void *rip_rel_ptr(void *p) + # define _ASM_NOKPROBE(entry) + # endif + +-#else /* ! __ASSEMBLY__ */ ++#else /* ! __ASSEMBLER__ */ + + # define DEFINE_EXTABLE_TYPE_REG \ + ".macro extable_type_reg type:req reg:req\n" \ +@@ -221,7 +221,7 @@ static __always_inline __pure void *rip_rel_ptr(void *p) + */ + register unsigned long current_stack_pointer asm(_ASM_SP); + #define ASM_CALL_CONSTRAINT "+r" (current_stack_pointer) +-#endif /* __ASSEMBLY__ */ ++#endif /* __ASSEMBLER__ */ + + #define _ASM_EXTABLE(from, to) \ + _ASM_EXTABLE_TYPE(from, to, EX_TYPE_DEFAULT) +diff --git a/arch/x86/include/asm/boot.h b/arch/x86/include/asm/boot.h +index 3e5b111e619d4..3f02ff6d333d3 100644 +--- a/arch/x86/include/asm/boot.h ++++ b/arch/x86/include/asm/boot.h +@@ -74,7 +74,7 @@ + # define BOOT_STACK_SIZE 0x1000 + #endif + +-#ifndef __ASSEMBLY__ ++#ifndef __ASSEMBLER__ + extern unsigned int output_len; + extern const unsigned long kernel_text_size; + extern const unsigned long kernel_total_size; +diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h +index de1ad09fe8d72..7e67bacf02f37 100644 +--- a/arch/x86/include/asm/cpufeature.h ++++ b/arch/x86/include/asm/cpufeature.h +@@ -4,7 +4,7 @@ + + #include + +-#if defined(__KERNEL__) && !defined(__ASSEMBLY__) ++#if defined(__KERNEL__) && !defined(__ASSEMBLER__) + + #include + #include +@@ -208,5 +208,5 @@ static __always_inline bool _static_cpu_has(u16 bit) + #define CPU_FEATURE_TYPEVAL boot_cpu_data.x86_vendor, boot_cpu_data.x86, \ + boot_cpu_data.x86_model + +-#endif /* defined(__KERNEL__) && !defined(__ASSEMBLY__) */ ++#endif /* defined(__KERNEL__) && !defined(__ASSEMBLER__) */ + #endif /* _ASM_X86_CPUFEATURE_H */ +diff --git a/arch/x86/include/asm/cpumask.h b/arch/x86/include/asm/cpumask.h +index 4acfd57de8f1c..70f6b60ad67b9 100644 +--- a/arch/x86/include/asm/cpumask.h ++++ b/arch/x86/include/asm/cpumask.h +@@ -1,7 +1,7 @@ + /* SPDX-License-Identifier: GPL-2.0 */ + #ifndef _ASM_X86_CPUMASK_H + #define _ASM_X86_CPUMASK_H +-#ifndef __ASSEMBLY__ ++#ifndef __ASSEMBLER__ + #include + + extern void setup_cpu_local_masks(void); +@@ -34,5 +34,5 @@ static __always_inline void arch_cpumask_clear_cpu(int cpu, struct cpumask *dstp + + #define arch_cpu_is_offline(cpu) unlikely(!arch_cpu_online(cpu)) + +-#endif /* __ASSEMBLY__ */ ++#endif /* __ASSEMBLER__ */ + #endif /* _ASM_X86_CPUMASK_H */ +diff --git a/arch/x86/include/asm/current.h b/arch/x86/include/asm/current.h +index bf5953883ec36..f2d0b38879808 100644 +--- a/arch/x86/include/asm/current.h ++++ b/arch/x86/include/asm/current.h +@@ -5,7 +5,7 @@ + #include + #include + +-#ifndef __ASSEMBLY__ ++#ifndef __ASSEMBLER__ + + #include + #include +@@ -51,6 +51,6 @@ static __always_inline struct task_struct *get_current(void) + + #define current get_current() + +-#endif /* __ASSEMBLY__ */ ++#endif /* __ASSEMBLER__ */ + + #endif /* _ASM_X86_CURRENT_H */ +diff --git a/arch/x86/include/asm/desc_defs.h b/arch/x86/include/asm/desc_defs.h +index d440a65af8f39..7e6b9314758a1 100644 +--- a/arch/x86/include/asm/desc_defs.h ++++ b/arch/x86/include/asm/desc_defs.h +@@ -58,7 +58,7 @@ + + #define DESC_USER (_DESC_DPL(3)) + +-#ifndef __ASSEMBLY__ ++#ifndef __ASSEMBLER__ + + #include + +@@ -166,7 +166,7 @@ struct desc_ptr { + unsigned long address; + } __attribute__((packed)) ; + +-#endif /* !__ASSEMBLY__ */ ++#endif /* !__ASSEMBLER__ */ + + /* Boot IDT definitions */ + #define BOOT_IDT_ENTRIES 32 +diff --git a/arch/x86/include/asm/dwarf2.h b/arch/x86/include/asm/dwarf2.h +index 430fca13bb568..302e11b15da86 100644 +--- a/arch/x86/include/asm/dwarf2.h ++++ b/arch/x86/include/asm/dwarf2.h +@@ -2,7 +2,7 @@ + #ifndef _ASM_X86_DWARF2_H + #define _ASM_X86_DWARF2_H + +-#ifndef __ASSEMBLY__ ++#ifndef __ASSEMBLER__ + #warning "asm/dwarf2.h should be only included in pure assembly files" + #endif + +diff --git a/arch/x86/include/asm/fixmap.h b/arch/x86/include/asm/fixmap.h +index d0dcefb5cc59d..4519c9f35ba04 100644 +--- a/arch/x86/include/asm/fixmap.h ++++ b/arch/x86/include/asm/fixmap.h +@@ -31,7 +31,7 @@ + /* fixmap starts downwards from the 507th entry in level2_fixmap_pgt */ + #define FIXMAP_PMD_TOP 507 + +-#ifndef __ASSEMBLY__ ++#ifndef __ASSEMBLER__ + #include + #include + #include +@@ -196,5 +196,5 @@ void __init *early_memremap_decrypted_wp(resource_size_t phys_addr, + void __early_set_fixmap(enum fixed_addresses idx, + phys_addr_t phys, pgprot_t flags); + +-#endif /* !__ASSEMBLY__ */ ++#endif /* !__ASSEMBLER__ */ + #endif /* _ASM_X86_FIXMAP_H */ +diff --git a/arch/x86/include/asm/frame.h b/arch/x86/include/asm/frame.h +index fb42659f6e988..0ab65073c1cc0 100644 +--- a/arch/x86/include/asm/frame.h ++++ b/arch/x86/include/asm/frame.h +@@ -11,7 +11,7 @@ + + #ifdef CONFIG_FRAME_POINTER + +-#ifdef __ASSEMBLY__ ++#ifdef __ASSEMBLER__ + + .macro FRAME_BEGIN + push %_ASM_BP +@@ -51,7 +51,7 @@ + .endm + #endif /* CONFIG_X86_64 */ + +-#else /* !__ASSEMBLY__ */ ++#else /* !__ASSEMBLER__ */ + + #define FRAME_BEGIN \ + "push %" _ASM_BP "\n" \ +@@ -82,18 +82,18 @@ static inline unsigned long encode_frame_pointer(struct pt_regs *regs) + + #endif /* CONFIG_X86_64 */ + +-#endif /* __ASSEMBLY__ */ ++#endif /* __ASSEMBLER__ */ + + #define FRAME_OFFSET __ASM_SEL(4, 8) + + #else /* !CONFIG_FRAME_POINTER */ + +-#ifdef __ASSEMBLY__ ++#ifdef __ASSEMBLER__ + + .macro ENCODE_FRAME_POINTER ptregs_offset=0 + .endm + +-#else /* !__ASSEMBLY */ ++#else /* !__ASSEMBLER__ */ + + #define ENCODE_FRAME_POINTER + +diff --git a/arch/x86/include/asm/fred.h b/arch/x86/include/asm/fred.h +index 25ca00bd70e83..2a29e52168815 100644 +--- a/arch/x86/include/asm/fred.h ++++ b/arch/x86/include/asm/fred.h +@@ -32,7 +32,7 @@ + #define FRED_CONFIG_INT_STKLVL(l) (_AT(unsigned long, l) << 9) + #define FRED_CONFIG_ENTRYPOINT(p) _AT(unsigned long, (p)) + +-#ifndef __ASSEMBLY__ ++#ifndef __ASSEMBLER__ + + #ifdef CONFIG_X86_FRED + #include +@@ -113,6 +113,6 @@ static inline void fred_entry_from_kvm(unsigned int type, unsigned int vector) { + static inline void fred_sync_rsp0(unsigned long rsp0) { } + static inline void fred_update_rsp0(void) { } + #endif /* CONFIG_X86_FRED */ +-#endif /* !__ASSEMBLY__ */ ++#endif /* !__ASSEMBLER__ */ + + #endif /* ASM_X86_FRED_H */ +diff --git a/arch/x86/include/asm/fsgsbase.h b/arch/x86/include/asm/fsgsbase.h +index 9e7e8ca8e2997..02f239569b93d 100644 +--- a/arch/x86/include/asm/fsgsbase.h ++++ b/arch/x86/include/asm/fsgsbase.h +@@ -2,7 +2,7 @@ + #ifndef _ASM_FSGSBASE_H + #define _ASM_FSGSBASE_H + +-#ifndef __ASSEMBLY__ ++#ifndef __ASSEMBLER__ + + #ifdef CONFIG_X86_64 + +@@ -80,6 +80,6 @@ extern unsigned long x86_fsgsbase_read_task(struct task_struct *task, + + #endif /* CONFIG_X86_64 */ + +-#endif /* __ASSEMBLY__ */ ++#endif /* __ASSEMBLER__ */ + + #endif /* _ASM_FSGSBASE_H */ +diff --git a/arch/x86/include/asm/ftrace.h b/arch/x86/include/asm/ftrace.h +index f9cb4d07df58f..2d02d5b0517c1 100644 +--- a/arch/x86/include/asm/ftrace.h ++++ b/arch/x86/include/asm/ftrace.h +@@ -22,7 +22,7 @@ + #define ARCH_SUPPORTS_FTRACE_OPS 1 + #endif + +-#ifndef __ASSEMBLY__ ++#ifndef __ASSEMBLER__ + extern void __fentry__(void); + + static inline unsigned long ftrace_call_adjust(unsigned long addr) +@@ -118,11 +118,11 @@ struct dyn_arch_ftrace { + }; + + #endif /* CONFIG_DYNAMIC_FTRACE */ +-#endif /* __ASSEMBLY__ */ ++#endif /* __ASSEMBLER__ */ + #endif /* CONFIG_FUNCTION_TRACER */ + + +-#ifndef __ASSEMBLY__ ++#ifndef __ASSEMBLER__ + + void prepare_ftrace_return(unsigned long ip, unsigned long *parent, + unsigned long frame_pointer); +@@ -166,6 +166,6 @@ static inline bool arch_trace_is_compat_syscall(struct pt_regs *regs) + } + #endif /* CONFIG_FTRACE_SYSCALLS && CONFIG_IA32_EMULATION */ + #endif /* !COMPILE_OFFSETS */ +-#endif /* !__ASSEMBLY__ */ ++#endif /* !__ASSEMBLER__ */ + + #endif /* _ASM_X86_FTRACE_H */ +diff --git a/arch/x86/include/asm/hw_irq.h b/arch/x86/include/asm/hw_irq.h +index edebf1020e049..162ebd73a6981 100644 +--- a/arch/x86/include/asm/hw_irq.h ++++ b/arch/x86/include/asm/hw_irq.h +@@ -16,7 +16,7 @@ + + #include + +-#ifndef __ASSEMBLY__ ++#ifndef __ASSEMBLER__ + + #include + #include +@@ -128,6 +128,6 @@ extern char spurious_entries_start[]; + typedef struct irq_desc* vector_irq_t[NR_VECTORS]; + DECLARE_PER_CPU(vector_irq_t, vector_irq); + +-#endif /* !ASSEMBLY_ */ ++#endif /* !__ASSEMBLER__ */ + + #endif /* _ASM_X86_HW_IRQ_H */ +diff --git a/arch/x86/include/asm/ibt.h b/arch/x86/include/asm/ibt.h +index 1e59581d500ca..e7f4caa42839a 100644 +--- a/arch/x86/include/asm/ibt.h ++++ b/arch/x86/include/asm/ibt.h +@@ -21,7 +21,7 @@ + + #define HAS_KERNEL_IBT 1 + +-#ifndef __ASSEMBLY__ ++#ifndef __ASSEMBLER__ + + #ifdef CONFIG_X86_64 + #define ASM_ENDBR "endbr64\n\t" +@@ -77,7 +77,7 @@ static inline bool is_endbr(u32 val) + extern __noendbr u64 ibt_save(bool disable); + extern __noendbr void ibt_restore(u64 save); + +-#else /* __ASSEMBLY__ */ ++#else /* __ASSEMBLER__ */ + + #ifdef CONFIG_X86_64 + #define ENDBR endbr64 +@@ -85,13 +85,13 @@ extern __noendbr void ibt_restore(u64 save); + #define ENDBR endbr32 + #endif + +-#endif /* __ASSEMBLY__ */ ++#endif /* __ASSEMBLER__ */ + + #else /* !IBT */ + + #define HAS_KERNEL_IBT 0 + +-#ifndef __ASSEMBLY__ ++#ifndef __ASSEMBLER__ + + #define ASM_ENDBR + #define IBT_NOSEAL(name) +@@ -103,11 +103,11 @@ static inline bool is_endbr(u32 val) { return false; } + static inline u64 ibt_save(bool disable) { return 0; } + static inline void ibt_restore(u64 save) { } + +-#else /* __ASSEMBLY__ */ ++#else /* __ASSEMBLER__ */ + + #define ENDBR + +-#endif /* __ASSEMBLY__ */ ++#endif /* __ASSEMBLER__ */ + + #endif /* CONFIG_X86_KERNEL_IBT */ + +diff --git a/arch/x86/include/asm/idtentry.h b/arch/x86/include/asm/idtentry.h +index ad5c68f0509d4..a4ec27c679887 100644 +--- a/arch/x86/include/asm/idtentry.h ++++ b/arch/x86/include/asm/idtentry.h +@@ -7,7 +7,7 @@ + + #define IDT_ALIGN (8 * (1 + HAS_KERNEL_IBT)) + +-#ifndef __ASSEMBLY__ ++#ifndef __ASSEMBLER__ + #include + #include + +@@ -474,7 +474,7 @@ static inline void fred_install_sysvec(unsigned int vector, const idtentry_t fun + idt_install_sysvec(vector, asm_##function); \ + } + +-#else /* !__ASSEMBLY__ */ ++#else /* !__ASSEMBLER__ */ + + /* + * The ASM variants for DECLARE_IDTENTRY*() which emit the ASM entry stubs. +@@ -579,7 +579,7 @@ SYM_CODE_START(spurious_entries_start) + SYM_CODE_END(spurious_entries_start) + #endif + +-#endif /* __ASSEMBLY__ */ ++#endif /* __ASSEMBLER__ */ + + /* + * The actual entry points. Note that DECLARE_IDTENTRY*() serves two +diff --git a/arch/x86/include/asm/inst.h b/arch/x86/include/asm/inst.h +index 438ccd4f3cc45..e48a00b3311d5 100644 +--- a/arch/x86/include/asm/inst.h ++++ b/arch/x86/include/asm/inst.h +@@ -6,7 +6,7 @@ + #ifndef X86_ASM_INST_H + #define X86_ASM_INST_H + +-#ifdef __ASSEMBLY__ ++#ifdef __ASSEMBLER__ + + #define REG_NUM_INVALID 100 + +diff --git a/arch/x86/include/asm/irqflags.h b/arch/x86/include/asm/irqflags.h +index 1c2db11a2c3cb..9a9b21b78905a 100644 +--- a/arch/x86/include/asm/irqflags.h ++++ b/arch/x86/include/asm/irqflags.h +@@ -4,7 +4,7 @@ + + #include + +-#ifndef __ASSEMBLY__ ++#ifndef __ASSEMBLER__ + + #include + +@@ -101,7 +101,7 @@ static __always_inline void halt(void) + #ifdef CONFIG_PARAVIRT_XXL + #include + #else +-#ifndef __ASSEMBLY__ ++#ifndef __ASSEMBLER__ + #include + + static __always_inline unsigned long arch_local_save_flags(void) +@@ -137,10 +137,10 @@ static __always_inline unsigned long arch_local_irq_save(void) + + #endif + +-#endif /* __ASSEMBLY__ */ ++#endif /* __ASSEMBLER__ */ + #endif /* CONFIG_PARAVIRT_XXL */ + +-#ifndef __ASSEMBLY__ ++#ifndef __ASSEMBLER__ + static __always_inline int arch_irqs_disabled_flags(unsigned long flags) + { + return !(flags & X86_EFLAGS_IF); +@@ -158,6 +158,6 @@ static __always_inline void arch_local_irq_restore(unsigned long flags) + if (!arch_irqs_disabled_flags(flags)) + arch_local_irq_enable(); + } +-#endif /* !__ASSEMBLY__ */ ++#endif /* !__ASSEMBLER__ */ + + #endif +diff --git a/arch/x86/include/asm/jump_label.h b/arch/x86/include/asm/jump_label.h +index 3f1c1d6c0da12..61dd1dee7812e 100644 +--- a/arch/x86/include/asm/jump_label.h ++++ b/arch/x86/include/asm/jump_label.h +@@ -7,7 +7,7 @@ + #include + #include + +-#ifndef __ASSEMBLY__ ++#ifndef __ASSEMBLER__ + + #include + #include +@@ -55,6 +55,6 @@ static __always_inline bool arch_static_branch_jump(struct static_key * const ke + + extern int arch_jump_entry_size(struct jump_entry *entry); + +-#endif /* __ASSEMBLY__ */ ++#endif /* __ASSEMBLER__ */ + + #endif +diff --git a/arch/x86/include/asm/kasan.h b/arch/x86/include/asm/kasan.h +index de75306b932ef..d7e33c7f096b0 100644 +--- a/arch/x86/include/asm/kasan.h ++++ b/arch/x86/include/asm/kasan.h +@@ -23,7 +23,7 @@ + (1ULL << (__VIRTUAL_MASK_SHIFT - \ + KASAN_SHADOW_SCALE_SHIFT))) + +-#ifndef __ASSEMBLY__ ++#ifndef __ASSEMBLER__ + + #ifdef CONFIG_KASAN + void __init kasan_early_init(void); +diff --git a/arch/x86/include/asm/kexec.h b/arch/x86/include/asm/kexec.h +index 8ad187462b68e..c75509241ff28 100644 +--- a/arch/x86/include/asm/kexec.h ++++ b/arch/x86/include/asm/kexec.h +@@ -13,7 +13,7 @@ + # define KEXEC_CONTROL_PAGE_SIZE 4096 + # define KEXEC_CONTROL_CODE_MAX_SIZE 2048 + +-#ifndef __ASSEMBLY__ ++#ifndef __ASSEMBLER__ + + #include + #include +@@ -225,6 +225,6 @@ unsigned int arch_crash_get_elfcorehdr_size(void); + #define crash_get_elfcorehdr_size arch_crash_get_elfcorehdr_size + #endif + +-#endif /* __ASSEMBLY__ */ ++#endif /* __ASSEMBLER__ */ + + #endif /* _ASM_X86_KEXEC_H */ +diff --git a/arch/x86/include/asm/linkage.h b/arch/x86/include/asm/linkage.h +index dc31b13b87a0d..c95dad65801d5 100644 +--- a/arch/x86/include/asm/linkage.h ++++ b/arch/x86/include/asm/linkage.h +@@ -38,7 +38,7 @@ + #define ASM_FUNC_ALIGN __stringify(__FUNC_ALIGN) + #define SYM_F_ALIGN __FUNC_ALIGN + +-#ifdef __ASSEMBLY__ ++#ifdef __ASSEMBLER__ + + #if defined(CONFIG_MITIGATION_RETHUNK) && !defined(__DISABLE_EXPORTS) && !defined(BUILD_VDSO) + #define RET jmp __x86_return_thunk +@@ -50,7 +50,7 @@ + #endif + #endif /* CONFIG_MITIGATION_RETPOLINE */ + +-#else /* __ASSEMBLY__ */ ++#else /* __ASSEMBLER__ */ + + #if defined(CONFIG_MITIGATION_RETHUNK) && !defined(__DISABLE_EXPORTS) && !defined(BUILD_VDSO) + #define ASM_RET "jmp __x86_return_thunk\n\t" +@@ -62,7 +62,7 @@ + #endif + #endif /* CONFIG_MITIGATION_RETPOLINE */ + +-#endif /* __ASSEMBLY__ */ ++#endif /* __ASSEMBLER__ */ + + /* + * Depending on -fpatchable-function-entry=N,N usage (CONFIG_CALL_PADDING) the +diff --git a/arch/x86/include/asm/mem_encrypt.h b/arch/x86/include/asm/mem_encrypt.h +index f922b682b9b4c..1530ee301dfea 100644 +--- a/arch/x86/include/asm/mem_encrypt.h ++++ b/arch/x86/include/asm/mem_encrypt.h +@@ -10,7 +10,7 @@ + #ifndef __X86_MEM_ENCRYPT_H__ + #define __X86_MEM_ENCRYPT_H__ + +-#ifndef __ASSEMBLY__ ++#ifndef __ASSEMBLER__ + + #include + #include +@@ -114,6 +114,6 @@ void add_encrypt_protection_map(void); + + extern char __start_bss_decrypted[], __end_bss_decrypted[], __start_bss_decrypted_unused[]; + +-#endif /* __ASSEMBLY__ */ ++#endif /* __ASSEMBLER__ */ + + #endif /* __X86_MEM_ENCRYPT_H__ */ +diff --git a/arch/x86/include/asm/msr.h b/arch/x86/include/asm/msr.h +index 001853541f1e8..9397a319d165d 100644 +--- a/arch/x86/include/asm/msr.h ++++ b/arch/x86/include/asm/msr.h +@@ -4,7 +4,7 @@ + + #include "msr-index.h" + +-#ifndef __ASSEMBLY__ ++#ifndef __ASSEMBLER__ + + #include + #include +@@ -397,5 +397,5 @@ static inline int wrmsr_safe_regs_on_cpu(unsigned int cpu, u32 regs[8]) + return wrmsr_safe_regs(regs); + } + #endif /* CONFIG_SMP */ +-#endif /* __ASSEMBLY__ */ ++#endif /* __ASSEMBLER__ */ + #endif /* _ASM_X86_MSR_H */ +diff --git a/arch/x86/include/asm/nops.h b/arch/x86/include/asm/nops.h +index 1c1b7550fa550..cd94221d83358 100644 +--- a/arch/x86/include/asm/nops.h ++++ b/arch/x86/include/asm/nops.h +@@ -82,7 +82,7 @@ + #define ASM_NOP7 _ASM_BYTES(BYTES_NOP7) + #define ASM_NOP8 _ASM_BYTES(BYTES_NOP8) + +-#ifndef __ASSEMBLY__ ++#ifndef __ASSEMBLER__ + extern const unsigned char * const x86_nops[]; + #endif + +diff --git a/arch/x86/include/asm/nospec-branch.h b/arch/x86/include/asm/nospec-branch.h +index b1ac1d0d29ca8..0cc2d535e5c5f 100644 +--- a/arch/x86/include/asm/nospec-branch.h ++++ b/arch/x86/include/asm/nospec-branch.h +@@ -177,7 +177,7 @@ + add $(BITS_PER_LONG/8), %_ASM_SP; \ + lfence; + +-#ifdef __ASSEMBLY__ ++#ifdef __ASSEMBLER__ + + /* + * (ab)use RETPOLINE_SAFE on RET to annotate away 'bare' RET instructions +@@ -335,7 +335,7 @@ + #define CLEAR_BRANCH_HISTORY_VMEXIT + #endif + +-#else /* __ASSEMBLY__ */ ++#else /* __ASSEMBLER__ */ + + #define ITS_THUNK_SIZE 64 + +@@ -612,6 +612,6 @@ static __always_inline void mds_idle_clear_cpu_buffers(void) + mds_clear_cpu_buffers(); + } + +-#endif /* __ASSEMBLY__ */ ++#endif /* __ASSEMBLER__ */ + + #endif /* _ASM_X86_NOSPEC_BRANCH_H_ */ +diff --git a/arch/x86/include/asm/orc_types.h b/arch/x86/include/asm/orc_types.h +index 46d7e06763c9f..e0125afa53fb9 100644 +--- a/arch/x86/include/asm/orc_types.h ++++ b/arch/x86/include/asm/orc_types.h +@@ -45,7 +45,7 @@ + #define ORC_TYPE_REGS 3 + #define ORC_TYPE_REGS_PARTIAL 4 + +-#ifndef __ASSEMBLY__ ++#ifndef __ASSEMBLER__ + #include + + /* +@@ -73,6 +73,6 @@ struct orc_entry { + #endif + } __packed; + +-#endif /* __ASSEMBLY__ */ ++#endif /* __ASSEMBLER__ */ + + #endif /* _ORC_TYPES_H */ +diff --git a/arch/x86/include/asm/page.h b/arch/x86/include/asm/page.h +index c9fe207916f48..9265f2fca99ae 100644 +--- a/arch/x86/include/asm/page.h ++++ b/arch/x86/include/asm/page.h +@@ -14,7 +14,7 @@ + #include + #endif /* CONFIG_X86_64 */ + +-#ifndef __ASSEMBLY__ ++#ifndef __ASSEMBLER__ + + struct page; + +@@ -84,7 +84,7 @@ static __always_inline u64 __is_canonical_address(u64 vaddr, u8 vaddr_bits) + return __canonical_address(vaddr, vaddr_bits) == vaddr; + } + +-#endif /* __ASSEMBLY__ */ ++#endif /* __ASSEMBLER__ */ + + #include + #include +diff --git a/arch/x86/include/asm/page_32.h b/arch/x86/include/asm/page_32.h +index 580d71aca65a4..0c623706cb7ef 100644 +--- a/arch/x86/include/asm/page_32.h ++++ b/arch/x86/include/asm/page_32.h +@@ -4,7 +4,7 @@ + + #include + +-#ifndef __ASSEMBLY__ ++#ifndef __ASSEMBLER__ + + #define __phys_addr_nodebug(x) ((x) - PAGE_OFFSET) + #ifdef CONFIG_DEBUG_VIRTUAL +@@ -26,6 +26,6 @@ static inline void copy_page(void *to, void *from) + { + memcpy(to, from, PAGE_SIZE); + } +-#endif /* !__ASSEMBLY__ */ ++#endif /* !__ASSEMBLER__ */ + + #endif /* _ASM_X86_PAGE_32_H */ +diff --git a/arch/x86/include/asm/page_32_types.h b/arch/x86/include/asm/page_32_types.h +index faf9cc1c14bb6..88e3c8d582986 100644 +--- a/arch/x86/include/asm/page_32_types.h ++++ b/arch/x86/include/asm/page_32_types.h +@@ -63,7 +63,7 @@ + */ + #define KERNEL_IMAGE_SIZE (512 * 1024 * 1024) + +-#ifndef __ASSEMBLY__ ++#ifndef __ASSEMBLER__ + + /* + * This much address space is reserved for vmalloc() and iomap() +@@ -75,6 +75,6 @@ extern int sysctl_legacy_va_layout; + extern void find_low_pfn_range(void); + extern void setup_bootmem_allocator(void); + +-#endif /* !__ASSEMBLY__ */ ++#endif /* !__ASSEMBLER__ */ + + #endif /* _ASM_X86_PAGE_32_DEFS_H */ +diff --git a/arch/x86/include/asm/page_64.h b/arch/x86/include/asm/page_64.h +index d63576608ce76..442357defa117 100644 +--- a/arch/x86/include/asm/page_64.h ++++ b/arch/x86/include/asm/page_64.h +@@ -4,7 +4,7 @@ + + #include + +-#ifndef __ASSEMBLY__ ++#ifndef __ASSEMBLER__ + #include + #include + +@@ -94,7 +94,7 @@ static __always_inline unsigned long task_size_max(void) + } + #endif /* CONFIG_X86_5LEVEL */ + +-#endif /* !__ASSEMBLY__ */ ++#endif /* !__ASSEMBLER__ */ + + #ifdef CONFIG_X86_VSYSCALL_EMULATION + # define __HAVE_ARCH_GATE_AREA 1 +diff --git a/arch/x86/include/asm/page_64_types.h b/arch/x86/include/asm/page_64_types.h +index 06ef25411d622..1faa8f88850ab 100644 +--- a/arch/x86/include/asm/page_64_types.h ++++ b/arch/x86/include/asm/page_64_types.h +@@ -2,7 +2,7 @@ + #ifndef _ASM_X86_PAGE_64_DEFS_H + #define _ASM_X86_PAGE_64_DEFS_H + +-#ifndef __ASSEMBLY__ ++#ifndef __ASSEMBLER__ + #include + #endif + +diff --git a/arch/x86/include/asm/page_types.h b/arch/x86/include/asm/page_types.h +index 974688973cf6e..9f77bf03d7472 100644 +--- a/arch/x86/include/asm/page_types.h ++++ b/arch/x86/include/asm/page_types.h +@@ -43,7 +43,7 @@ + #define IOREMAP_MAX_ORDER (PMD_SHIFT) + #endif /* CONFIG_X86_64 */ + +-#ifndef __ASSEMBLY__ ++#ifndef __ASSEMBLER__ + + #ifdef CONFIG_DYNAMIC_PHYSICAL_MASK + extern phys_addr_t physical_mask; +@@ -66,6 +66,6 @@ bool pfn_range_is_mapped(unsigned long start_pfn, unsigned long end_pfn); + + extern void initmem_init(void); + +-#endif /* !__ASSEMBLY__ */ ++#endif /* !__ASSEMBLER__ */ + + #endif /* _ASM_X86_PAGE_DEFS_H */ +diff --git a/arch/x86/include/asm/paravirt.h b/arch/x86/include/asm/paravirt.h +index 29e7331a0c98d..0ace044d6f2cd 100644 +--- a/arch/x86/include/asm/paravirt.h ++++ b/arch/x86/include/asm/paravirt.h +@@ -6,7 +6,7 @@ + + #include + +-#ifndef __ASSEMBLY__ ++#ifndef __ASSEMBLER__ + struct mm_struct; + #endif + +@@ -15,7 +15,7 @@ struct mm_struct; + #include + #include + +-#ifndef __ASSEMBLY__ ++#ifndef __ASSEMBLER__ + #include + #include + #include +@@ -720,7 +720,7 @@ static __always_inline unsigned long arch_local_irq_save(void) + extern void default_banner(void); + void native_pv_lock_init(void) __init; + +-#else /* __ASSEMBLY__ */ ++#else /* __ASSEMBLER__ */ + + #ifdef CONFIG_X86_64 + #ifdef CONFIG_PARAVIRT_XXL +@@ -740,18 +740,18 @@ void native_pv_lock_init(void) __init; + #endif /* CONFIG_PARAVIRT_XXL */ + #endif /* CONFIG_X86_64 */ + +-#endif /* __ASSEMBLY__ */ ++#endif /* __ASSEMBLER__ */ + #else /* CONFIG_PARAVIRT */ + # define default_banner x86_init_noop + +-#ifndef __ASSEMBLY__ ++#ifndef __ASSEMBLER__ + static inline void native_pv_lock_init(void) + { + } + #endif + #endif /* !CONFIG_PARAVIRT */ + +-#ifndef __ASSEMBLY__ ++#ifndef __ASSEMBLER__ + #ifndef CONFIG_PARAVIRT_XXL + static inline void paravirt_enter_mmap(struct mm_struct *mm) + { +@@ -769,5 +769,5 @@ static inline void paravirt_set_cap(void) + { + } + #endif +-#endif /* __ASSEMBLY__ */ ++#endif /* __ASSEMBLER__ */ + #endif /* _ASM_X86_PARAVIRT_H */ +diff --git a/arch/x86/include/asm/paravirt_types.h b/arch/x86/include/asm/paravirt_types.h +index abccfccc2e3fa..1fca6281988a9 100644 +--- a/arch/x86/include/asm/paravirt_types.h ++++ b/arch/x86/include/asm/paravirt_types.h +@@ -4,7 +4,7 @@ + + #ifdef CONFIG_PARAVIRT + +-#ifndef __ASSEMBLY__ ++#ifndef __ASSEMBLER__ + #include + + #include +@@ -518,7 +518,7 @@ unsigned long pv_native_read_cr2(void); + + #define paravirt_nop ((void *)nop_func) + +-#endif /* __ASSEMBLY__ */ ++#endif /* __ASSEMBLER__ */ + + #define ALT_NOT_XEN ALT_NOT(X86_FEATURE_XENPV) + +diff --git a/arch/x86/include/asm/percpu.h b/arch/x86/include/asm/percpu.h +index e525cd85f999f..afb9099fba9fc 100644 +--- a/arch/x86/include/asm/percpu.h ++++ b/arch/x86/include/asm/percpu.h +@@ -10,7 +10,7 @@ + # define __percpu_rel + #endif + +-#ifdef __ASSEMBLY__ ++#ifdef __ASSEMBLER__ + + #ifdef CONFIG_SMP + # define __percpu %__percpu_seg: +@@ -619,7 +619,7 @@ do { \ + /* We can use this directly for local CPU (faster). */ + DECLARE_PER_CPU_READ_MOSTLY(unsigned long, this_cpu_off); + +-#endif /* !__ASSEMBLY__ */ ++#endif /* !__ASSEMBLER__ */ + + #ifdef CONFIG_SMP + +diff --git a/arch/x86/include/asm/pgtable-2level_types.h b/arch/x86/include/asm/pgtable-2level_types.h +index 4a12c276b1812..66425424ce91a 100644 +--- a/arch/x86/include/asm/pgtable-2level_types.h ++++ b/arch/x86/include/asm/pgtable-2level_types.h +@@ -2,7 +2,7 @@ + #ifndef _ASM_X86_PGTABLE_2LEVEL_DEFS_H + #define _ASM_X86_PGTABLE_2LEVEL_DEFS_H + +-#ifndef __ASSEMBLY__ ++#ifndef __ASSEMBLER__ + #include + + typedef unsigned long pteval_t; +@@ -16,7 +16,7 @@ typedef union { + pteval_t pte; + pteval_t pte_low; + } pte_t; +-#endif /* !__ASSEMBLY__ */ ++#endif /* !__ASSEMBLER__ */ + + #define SHARED_KERNEL_PMD 0 + +diff --git a/arch/x86/include/asm/pgtable-3level_types.h b/arch/x86/include/asm/pgtable-3level_types.h +index 80911349519e8..9d5b257d44e3c 100644 +--- a/arch/x86/include/asm/pgtable-3level_types.h ++++ b/arch/x86/include/asm/pgtable-3level_types.h +@@ -2,7 +2,7 @@ + #ifndef _ASM_X86_PGTABLE_3LEVEL_DEFS_H + #define _ASM_X86_PGTABLE_3LEVEL_DEFS_H + +-#ifndef __ASSEMBLY__ ++#ifndef __ASSEMBLER__ + #include + + typedef u64 pteval_t; +@@ -25,7 +25,7 @@ typedef union { + }; + pmdval_t pmd; + } pmd_t; +-#endif /* !__ASSEMBLY__ */ ++#endif /* !__ASSEMBLER__ */ + + #define SHARED_KERNEL_PMD (!static_cpu_has(X86_FEATURE_PTI)) + +diff --git a/arch/x86/include/asm/pgtable-invert.h b/arch/x86/include/asm/pgtable-invert.h +index a0c1525f1b6f4..e12e52ae8083d 100644 +--- a/arch/x86/include/asm/pgtable-invert.h ++++ b/arch/x86/include/asm/pgtable-invert.h +@@ -2,7 +2,7 @@ + #ifndef _ASM_PGTABLE_INVERT_H + #define _ASM_PGTABLE_INVERT_H 1 + +-#ifndef __ASSEMBLY__ ++#ifndef __ASSEMBLER__ + + /* + * A clear pte value is special, and doesn't get inverted. +@@ -36,6 +36,6 @@ static inline u64 flip_protnone_guard(u64 oldval, u64 val, u64 mask) + return val; + } + +-#endif /* __ASSEMBLY__ */ ++#endif /* __ASSEMBLER__ */ + + #endif +diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h +index 593f10aabd45a..7bd6bd6df4a11 100644 +--- a/arch/x86/include/asm/pgtable.h ++++ b/arch/x86/include/asm/pgtable.h +@@ -15,7 +15,7 @@ + cachemode2protval(_PAGE_CACHE_MODE_UC_MINUS))) \ + : (prot)) + +-#ifndef __ASSEMBLY__ ++#ifndef __ASSEMBLER__ + #include + #include + #include +@@ -973,7 +973,7 @@ static inline pgd_t pti_set_user_pgtbl(pgd_t *pgdp, pgd_t pgd) + } + #endif /* CONFIG_MITIGATION_PAGE_TABLE_ISOLATION */ + +-#endif /* __ASSEMBLY__ */ ++#endif /* __ASSEMBLER__ */ + + + #ifdef CONFIG_X86_32 +@@ -982,7 +982,7 @@ static inline pgd_t pti_set_user_pgtbl(pgd_t *pgdp, pgd_t pgd) + # include + #endif + +-#ifndef __ASSEMBLY__ ++#ifndef __ASSEMBLER__ + #include + #include + #include +@@ -1233,12 +1233,12 @@ static inline int pgd_none(pgd_t pgd) + } + #endif /* CONFIG_PGTABLE_LEVELS > 4 */ + +-#endif /* __ASSEMBLY__ */ ++#endif /* __ASSEMBLER__ */ + + #define KERNEL_PGD_BOUNDARY pgd_index(PAGE_OFFSET) + #define KERNEL_PGD_PTRS (PTRS_PER_PGD - KERNEL_PGD_BOUNDARY) + +-#ifndef __ASSEMBLY__ ++#ifndef __ASSEMBLER__ + + extern int direct_gbpages; + void init_mem_mapping(void); +@@ -1812,6 +1812,6 @@ bool arch_is_platform_page(u64 paddr); + WARN_ON_ONCE(pgd_present(*pgdp) && !pgd_same(*pgdp, pgd)); \ + set_pgd(pgdp, pgd); \ + }) +-#endif /* __ASSEMBLY__ */ ++#endif /* __ASSEMBLER__ */ + + #endif /* _ASM_X86_PGTABLE_H */ +diff --git a/arch/x86/include/asm/pgtable_32.h b/arch/x86/include/asm/pgtable_32.h +index 7d4ad8907297c..b612cc57a4d34 100644 +--- a/arch/x86/include/asm/pgtable_32.h ++++ b/arch/x86/include/asm/pgtable_32.h +@@ -13,7 +13,7 @@ + * This file contains the functions and defines necessary to modify and use + * the i386 page table tree. + */ +-#ifndef __ASSEMBLY__ ++#ifndef __ASSEMBLER__ + #include + #include + #include +@@ -45,7 +45,7 @@ do { \ + flush_tlb_one_kernel((vaddr)); \ + } while (0) + +-#endif /* !__ASSEMBLY__ */ ++#endif /* !__ASSEMBLER__ */ + + /* + * This is used to calculate the .brk reservation for initial pagetables. +diff --git a/arch/x86/include/asm/pgtable_32_areas.h b/arch/x86/include/asm/pgtable_32_areas.h +index b6355416a15a8..921148b429676 100644 +--- a/arch/x86/include/asm/pgtable_32_areas.h ++++ b/arch/x86/include/asm/pgtable_32_areas.h +@@ -13,7 +13,7 @@ + */ + #define VMALLOC_OFFSET (8 * 1024 * 1024) + +-#ifndef __ASSEMBLY__ ++#ifndef __ASSEMBLER__ + extern bool __vmalloc_start_set; /* set once high_memory is set */ + #endif + +diff --git a/arch/x86/include/asm/pgtable_64.h b/arch/x86/include/asm/pgtable_64.h +index d1426b64c1b97..b89f8f1194a9f 100644 +--- a/arch/x86/include/asm/pgtable_64.h ++++ b/arch/x86/include/asm/pgtable_64.h +@@ -5,7 +5,7 @@ + #include + #include + +-#ifndef __ASSEMBLY__ ++#ifndef __ASSEMBLER__ + + /* + * This file contains the functions and defines necessary to modify and use +@@ -270,7 +270,7 @@ static inline bool gup_fast_permitted(unsigned long start, unsigned long end) + + #include + +-#else /* __ASSEMBLY__ */ ++#else /* __ASSEMBLER__ */ + + #define l4_index(x) (((x) >> 39) & 511) + #define pud_index(x) (((x) >> PUD_SHIFT) & (PTRS_PER_PUD - 1)) +@@ -291,5 +291,5 @@ L3_START_KERNEL = pud_index(__START_KERNEL_map) + i = i + 1 ; \ + .endr + +-#endif /* __ASSEMBLY__ */ ++#endif /* __ASSEMBLER__ */ + #endif /* _ASM_X86_PGTABLE_64_H */ +diff --git a/arch/x86/include/asm/pgtable_64_types.h b/arch/x86/include/asm/pgtable_64_types.h +index ec68f8369bdca..5bb782d856f2c 100644 +--- a/arch/x86/include/asm/pgtable_64_types.h ++++ b/arch/x86/include/asm/pgtable_64_types.h +@@ -4,7 +4,7 @@ + + #include + +-#ifndef __ASSEMBLY__ ++#ifndef __ASSEMBLER__ + #include + #include + +@@ -44,7 +44,7 @@ static inline bool pgtable_l5_enabled(void) + extern unsigned int pgdir_shift; + extern unsigned int ptrs_per_p4d; + +-#endif /* !__ASSEMBLY__ */ ++#endif /* !__ASSEMBLER__ */ + + #define SHARED_KERNEL_PMD 0 + +diff --git a/arch/x86/include/asm/pgtable_types.h b/arch/x86/include/asm/pgtable_types.h +index 4b804531b03c3..ded7075c60634 100644 +--- a/arch/x86/include/asm/pgtable_types.h ++++ b/arch/x86/include/asm/pgtable_types.h +@@ -164,7 +164,7 @@ + * to have the WB mode at index 0 (all bits clear). This is the default + * right now and likely would break too much if changed. + */ +-#ifndef __ASSEMBLY__ ++#ifndef __ASSEMBLER__ + enum page_cache_mode { + _PAGE_CACHE_MODE_WB = 0, + _PAGE_CACHE_MODE_WC = 1, +@@ -239,7 +239,7 @@ enum page_cache_mode { + #define __PAGE_KERNEL_IO_NOCACHE __PAGE_KERNEL_NOCACHE + + +-#ifndef __ASSEMBLY__ ++#ifndef __ASSEMBLER__ + + #define __PAGE_KERNEL_ENC (__PAGE_KERNEL | _ENC) + #define __PAGE_KERNEL_ENC_WP (__PAGE_KERNEL_WP | _ENC) +@@ -262,7 +262,7 @@ enum page_cache_mode { + #define PAGE_KERNEL_IO __pgprot_mask(__PAGE_KERNEL_IO) + #define PAGE_KERNEL_IO_NOCACHE __pgprot_mask(__PAGE_KERNEL_IO_NOCACHE) + +-#endif /* __ASSEMBLY__ */ ++#endif /* __ASSEMBLER__ */ + + /* + * early identity mapping pte attrib macros. +@@ -281,7 +281,7 @@ enum page_cache_mode { + # include + #endif + +-#ifndef __ASSEMBLY__ ++#ifndef __ASSEMBLER__ + + #include + +@@ -580,6 +580,6 @@ extern int __init kernel_map_pages_in_pgd(pgd_t *pgd, u64 pfn, + unsigned long page_flags); + extern int __init kernel_unmap_pages_in_pgd(pgd_t *pgd, unsigned long address, + unsigned long numpages); +-#endif /* !__ASSEMBLY__ */ ++#endif /* !__ASSEMBLER__ */ + + #endif /* _ASM_X86_PGTABLE_DEFS_H */ +diff --git a/arch/x86/include/asm/prom.h b/arch/x86/include/asm/prom.h +index 365798cb4408d..5d0dbab852640 100644 +--- a/arch/x86/include/asm/prom.h ++++ b/arch/x86/include/asm/prom.h +@@ -8,7 +8,7 @@ + + #ifndef _ASM_X86_PROM_H + #define _ASM_X86_PROM_H +-#ifndef __ASSEMBLY__ ++#ifndef __ASSEMBLER__ + + #include + #include +@@ -33,5 +33,5 @@ static inline void x86_flattree_get_config(void) { } + + extern char cmd_line[COMMAND_LINE_SIZE]; + +-#endif /* __ASSEMBLY__ */ ++#endif /* __ASSEMBLER__ */ + #endif +diff --git a/arch/x86/include/asm/pti.h b/arch/x86/include/asm/pti.h +index ab167c96b9ab4..88d0a1ab1f77e 100644 +--- a/arch/x86/include/asm/pti.h ++++ b/arch/x86/include/asm/pti.h +@@ -1,7 +1,7 @@ + /* SPDX-License-Identifier: GPL-2.0 */ + #ifndef _ASM_X86_PTI_H + #define _ASM_X86_PTI_H +-#ifndef __ASSEMBLY__ ++#ifndef __ASSEMBLER__ + + #ifdef CONFIG_MITIGATION_PAGE_TABLE_ISOLATION + extern void pti_init(void); +@@ -11,5 +11,5 @@ extern void pti_finalize(void); + static inline void pti_check_boottime_disable(void) { } + #endif + +-#endif /* __ASSEMBLY__ */ ++#endif /* __ASSEMBLER__ */ + #endif /* _ASM_X86_PTI_H */ +diff --git a/arch/x86/include/asm/ptrace.h b/arch/x86/include/asm/ptrace.h +index 5a83fbd9bc0b4..50f75467f73d0 100644 +--- a/arch/x86/include/asm/ptrace.h ++++ b/arch/x86/include/asm/ptrace.h +@@ -6,7 +6,7 @@ + #include + #include + +-#ifndef __ASSEMBLY__ ++#ifndef __ASSEMBLER__ + #ifdef __i386__ + + struct pt_regs { +@@ -469,5 +469,5 @@ extern int do_set_thread_area(struct task_struct *p, int idx, + # define do_set_thread_area_64(p, s, t) (0) + #endif + +-#endif /* !__ASSEMBLY__ */ ++#endif /* !__ASSEMBLER__ */ + #endif /* _ASM_X86_PTRACE_H */ +diff --git a/arch/x86/include/asm/purgatory.h b/arch/x86/include/asm/purgatory.h +index 5528e93250494..2fee5e9f1ccc3 100644 +--- a/arch/x86/include/asm/purgatory.h ++++ b/arch/x86/include/asm/purgatory.h +@@ -2,10 +2,10 @@ + #ifndef _ASM_X86_PURGATORY_H + #define _ASM_X86_PURGATORY_H + +-#ifndef __ASSEMBLY__ ++#ifndef __ASSEMBLER__ + #include + + extern void purgatory(void); +-#endif /* __ASSEMBLY__ */ ++#endif /* __ASSEMBLER__ */ + + #endif /* _ASM_PURGATORY_H */ +diff --git a/arch/x86/include/asm/pvclock-abi.h b/arch/x86/include/asm/pvclock-abi.h +index 1436226efe3ef..b9fece5fc96d6 100644 +--- a/arch/x86/include/asm/pvclock-abi.h ++++ b/arch/x86/include/asm/pvclock-abi.h +@@ -1,7 +1,7 @@ + /* SPDX-License-Identifier: GPL-2.0 */ + #ifndef _ASM_X86_PVCLOCK_ABI_H + #define _ASM_X86_PVCLOCK_ABI_H +-#ifndef __ASSEMBLY__ ++#ifndef __ASSEMBLER__ + + /* + * These structs MUST NOT be changed. +@@ -44,5 +44,5 @@ struct pvclock_wall_clock { + #define PVCLOCK_GUEST_STOPPED (1 << 1) + /* PVCLOCK_COUNTS_FROM_ZERO broke ABI and can't be used anymore. */ + #define PVCLOCK_COUNTS_FROM_ZERO (1 << 2) +-#endif /* __ASSEMBLY__ */ ++#endif /* __ASSEMBLER__ */ + #endif /* _ASM_X86_PVCLOCK_ABI_H */ +diff --git a/arch/x86/include/asm/realmode.h b/arch/x86/include/asm/realmode.h +index 87e5482acd0dc..f607081a022ab 100644 +--- a/arch/x86/include/asm/realmode.h ++++ b/arch/x86/include/asm/realmode.h +@@ -9,7 +9,7 @@ + #define TH_FLAGS_SME_ACTIVE_BIT 0 + #define TH_FLAGS_SME_ACTIVE BIT(TH_FLAGS_SME_ACTIVE_BIT) + +-#ifndef __ASSEMBLY__ ++#ifndef __ASSEMBLER__ + + #include + #include +@@ -95,6 +95,6 @@ void reserve_real_mode(void); + void load_trampoline_pgtable(void); + void init_real_mode(void); + +-#endif /* __ASSEMBLY__ */ ++#endif /* __ASSEMBLER__ */ + + #endif /* _ARCH_X86_REALMODE_H */ +diff --git a/arch/x86/include/asm/segment.h b/arch/x86/include/asm/segment.h +index 9d6411c659205..77d8f49b92bdd 100644 +--- a/arch/x86/include/asm/segment.h ++++ b/arch/x86/include/asm/segment.h +@@ -233,7 +233,7 @@ + #define VDSO_CPUNODE_BITS 12 + #define VDSO_CPUNODE_MASK 0xfff + +-#ifndef __ASSEMBLY__ ++#ifndef __ASSEMBLER__ + + /* Helper functions to store/load CPU and node numbers */ + +@@ -265,7 +265,7 @@ static inline void vdso_read_cpunode(unsigned *cpu, unsigned *node) + *node = (p >> VDSO_CPUNODE_BITS); + } + +-#endif /* !__ASSEMBLY__ */ ++#endif /* !__ASSEMBLER__ */ + + #ifdef __KERNEL__ + +@@ -286,7 +286,7 @@ static inline void vdso_read_cpunode(unsigned *cpu, unsigned *node) + */ + #define XEN_EARLY_IDT_HANDLER_SIZE (8 + ENDBR_INSN_SIZE) + +-#ifndef __ASSEMBLY__ ++#ifndef __ASSEMBLER__ + + extern const char early_idt_handler_array[NUM_EXCEPTION_VECTORS][EARLY_IDT_HANDLER_SIZE]; + extern void early_ignore_irq(void); +@@ -350,7 +350,7 @@ static inline void __loadsegment_fs(unsigned short value) + #define savesegment(seg, value) \ + asm("mov %%" #seg ",%0":"=r" (value) : : "memory") + +-#endif /* !__ASSEMBLY__ */ ++#endif /* !__ASSEMBLER__ */ + #endif /* __KERNEL__ */ + + #endif /* _ASM_X86_SEGMENT_H */ +diff --git a/arch/x86/include/asm/setup.h b/arch/x86/include/asm/setup.h +index 85f4fde3515c4..09201d47c967b 100644 +--- a/arch/x86/include/asm/setup.h ++++ b/arch/x86/include/asm/setup.h +@@ -27,7 +27,7 @@ + #define OLD_CL_ADDRESS 0x020 /* Relative to real mode data */ + #define NEW_CL_POINTER 0x228 /* Relative to real mode data */ + +-#ifndef __ASSEMBLY__ ++#ifndef __ASSEMBLER__ + #include + + #include +@@ -141,7 +141,7 @@ extern bool builtin_cmdline_added __ro_after_init; + #define builtin_cmdline_added 0 + #endif + +-#else /* __ASSEMBLY */ ++#else /* __ASSEMBLER__ */ + + .macro __RESERVE_BRK name, size + .pushsection .bss..brk, "aw" +@@ -153,6 +153,6 @@ SYM_DATA_END(__brk_\name) + + #define RESERVE_BRK(name, size) __RESERVE_BRK name, size + +-#endif /* __ASSEMBLY__ */ ++#endif /* __ASSEMBLER__ */ + + #endif /* _ASM_X86_SETUP_H */ +diff --git a/arch/x86/include/asm/setup_data.h b/arch/x86/include/asm/setup_data.h +index 77c51111a8939..7bb16f843c93d 100644 +--- a/arch/x86/include/asm/setup_data.h ++++ b/arch/x86/include/asm/setup_data.h +@@ -4,7 +4,7 @@ + + #include + +-#ifndef __ASSEMBLY__ ++#ifndef __ASSEMBLER__ + + struct pci_setup_rom { + struct setup_data data; +@@ -27,6 +27,6 @@ struct efi_setup_data { + u64 reserved[8]; + }; + +-#endif /* __ASSEMBLY__ */ ++#endif /* __ASSEMBLER__ */ + + #endif /* _ASM_X86_SETUP_DATA_H */ +diff --git a/arch/x86/include/asm/shared/tdx.h b/arch/x86/include/asm/shared/tdx.h +index fcbbef484a78e..a28ff6b141458 100644 +--- a/arch/x86/include/asm/shared/tdx.h ++++ b/arch/x86/include/asm/shared/tdx.h +@@ -106,7 +106,7 @@ + #define TDX_PS_1G 2 + #define TDX_PS_NR (TDX_PS_1G + 1) + +-#ifndef __ASSEMBLY__ ++#ifndef __ASSEMBLER__ + + #include + +@@ -177,5 +177,5 @@ static __always_inline u64 hcall_func(u64 exit_reason) + return exit_reason; + } + +-#endif /* !__ASSEMBLY__ */ ++#endif /* !__ASSEMBLER__ */ + #endif /* _ASM_X86_SHARED_TDX_H */ +diff --git a/arch/x86/include/asm/shstk.h b/arch/x86/include/asm/shstk.h +index 4cb77e004615d..ba6f2fe438488 100644 +--- a/arch/x86/include/asm/shstk.h ++++ b/arch/x86/include/asm/shstk.h +@@ -2,7 +2,7 @@ + #ifndef _ASM_X86_SHSTK_H + #define _ASM_X86_SHSTK_H + +-#ifndef __ASSEMBLY__ ++#ifndef __ASSEMBLER__ + #include + + struct task_struct; +@@ -37,6 +37,6 @@ static inline int shstk_update_last_frame(unsigned long val) { return 0; } + static inline bool shstk_is_enabled(void) { return false; } + #endif /* CONFIG_X86_USER_SHADOW_STACK */ + +-#endif /* __ASSEMBLY__ */ ++#endif /* __ASSEMBLER__ */ + + #endif /* _ASM_X86_SHSTK_H */ +diff --git a/arch/x86/include/asm/signal.h b/arch/x86/include/asm/signal.h +index 4a4043ca64934..c72d461753742 100644 +--- a/arch/x86/include/asm/signal.h ++++ b/arch/x86/include/asm/signal.h +@@ -2,7 +2,7 @@ + #ifndef _ASM_X86_SIGNAL_H + #define _ASM_X86_SIGNAL_H + +-#ifndef __ASSEMBLY__ ++#ifndef __ASSEMBLER__ + #include + + /* Most things should be clean enough to redefine this at will, if care +@@ -28,9 +28,9 @@ typedef struct { + #define SA_IA32_ABI 0x02000000u + #define SA_X32_ABI 0x01000000u + +-#endif /* __ASSEMBLY__ */ ++#endif /* __ASSEMBLER__ */ + #include +-#ifndef __ASSEMBLY__ ++#ifndef __ASSEMBLER__ + + #define __ARCH_HAS_SA_RESTORER + +@@ -101,5 +101,5 @@ struct pt_regs; + + #endif /* !__i386__ */ + +-#endif /* __ASSEMBLY__ */ ++#endif /* __ASSEMBLER__ */ + #endif /* _ASM_X86_SIGNAL_H */ +diff --git a/arch/x86/include/asm/smap.h b/arch/x86/include/asm/smap.h +index 2de1e5a75c573..daea94c2993c5 100644 +--- a/arch/x86/include/asm/smap.h ++++ b/arch/x86/include/asm/smap.h +@@ -13,7 +13,7 @@ + #include + #include + +-#ifdef __ASSEMBLY__ ++#ifdef __ASSEMBLER__ + + #define ASM_CLAC \ + ALTERNATIVE "", "clac", X86_FEATURE_SMAP +@@ -21,7 +21,7 @@ + #define ASM_STAC \ + ALTERNATIVE "", "stac", X86_FEATURE_SMAP + +-#else /* __ASSEMBLY__ */ ++#else /* __ASSEMBLER__ */ + + static __always_inline void clac(void) + { +@@ -61,6 +61,6 @@ static __always_inline void smap_restore(unsigned long flags) + #define ASM_STAC \ + ALTERNATIVE("", "stac", X86_FEATURE_SMAP) + +-#endif /* __ASSEMBLY__ */ ++#endif /* __ASSEMBLER__ */ + + #endif /* _ASM_X86_SMAP_H */ +diff --git a/arch/x86/include/asm/smp.h b/arch/x86/include/asm/smp.h +index ca073f40698fa..d234a6321c189 100644 +--- a/arch/x86/include/asm/smp.h ++++ b/arch/x86/include/asm/smp.h +@@ -1,7 +1,7 @@ + /* SPDX-License-Identifier: GPL-2.0 */ + #ifndef _ASM_X86_SMP_H + #define _ASM_X86_SMP_H +-#ifndef __ASSEMBLY__ ++#ifndef __ASSEMBLER__ + #include + + #include +@@ -175,7 +175,7 @@ extern void nmi_selftest(void); + extern unsigned int smpboot_control; + extern unsigned long apic_mmio_base; + +-#endif /* !__ASSEMBLY__ */ ++#endif /* !__ASSEMBLER__ */ + + /* Control bits for startup_64 */ + #define STARTUP_READ_APICID 0x80000000 +diff --git a/arch/x86/include/asm/tdx.h b/arch/x86/include/asm/tdx.h +index 40f9a97371a90..4a1922ec80cf7 100644 +--- a/arch/x86/include/asm/tdx.h ++++ b/arch/x86/include/asm/tdx.h +@@ -30,7 +30,7 @@ + #define TDX_SUCCESS 0ULL + #define TDX_RND_NO_ENTROPY 0x8000020300000000ULL + +-#ifndef __ASSEMBLY__ ++#ifndef __ASSEMBLER__ + + #include + +@@ -126,5 +126,5 @@ static inline int tdx_enable(void) { return -ENODEV; } + static inline const char *tdx_dump_mce_info(struct mce *m) { return NULL; } + #endif /* CONFIG_INTEL_TDX_HOST */ + +-#endif /* !__ASSEMBLY__ */ ++#endif /* !__ASSEMBLER__ */ + #endif /* _ASM_X86_TDX_H */ +diff --git a/arch/x86/include/asm/thread_info.h b/arch/x86/include/asm/thread_info.h +index a55c214f3ba64..9282465eea21d 100644 +--- a/arch/x86/include/asm/thread_info.h ++++ b/arch/x86/include/asm/thread_info.h +@@ -54,7 +54,7 @@ + * - this struct should fit entirely inside of one cache line + * - this struct shares the supervisor stack pages + */ +-#ifndef __ASSEMBLY__ ++#ifndef __ASSEMBLER__ + struct task_struct; + #include + #include +@@ -73,7 +73,7 @@ struct thread_info { + .flags = 0, \ + } + +-#else /* !__ASSEMBLY__ */ ++#else /* !__ASSEMBLER__ */ + + #include + +@@ -161,7 +161,7 @@ struct thread_info { + * + * preempt_count needs to be 1 initially, until the scheduler is functional. + */ +-#ifndef __ASSEMBLY__ ++#ifndef __ASSEMBLER__ + + /* + * Walks up the stack frames to make sure that the specified object is +@@ -213,7 +213,7 @@ static inline int arch_within_stack_frames(const void * const stack, + #endif + } + +-#endif /* !__ASSEMBLY__ */ ++#endif /* !__ASSEMBLER__ */ + + /* + * Thread-synchronous status. +@@ -224,7 +224,7 @@ static inline int arch_within_stack_frames(const void * const stack, + */ + #define TS_COMPAT 0x0002 /* 32bit syscall active (64BIT)*/ + +-#ifndef __ASSEMBLY__ ++#ifndef __ASSEMBLER__ + #ifdef CONFIG_COMPAT + #define TS_I386_REGS_POKED 0x0004 /* regs poked by 32-bit ptracer */ + +@@ -242,6 +242,6 @@ static inline int arch_within_stack_frames(const void * const stack, + + extern void arch_setup_new_exec(void); + #define arch_setup_new_exec arch_setup_new_exec +-#endif /* !__ASSEMBLY__ */ ++#endif /* !__ASSEMBLER__ */ + + #endif /* _ASM_X86_THREAD_INFO_H */ +diff --git a/arch/x86/include/asm/unwind_hints.h b/arch/x86/include/asm/unwind_hints.h +index 85cc57cb65392..8f4579c5a6f8b 100644 +--- a/arch/x86/include/asm/unwind_hints.h ++++ b/arch/x86/include/asm/unwind_hints.h +@@ -5,7 +5,7 @@ + + #include "orc_types.h" + +-#ifdef __ASSEMBLY__ ++#ifdef __ASSEMBLER__ + + .macro UNWIND_HINT_END_OF_STACK + UNWIND_HINT type=UNWIND_HINT_TYPE_END_OF_STACK +@@ -88,6 +88,6 @@ + #define UNWIND_HINT_RESTORE \ + UNWIND_HINT(UNWIND_HINT_TYPE_RESTORE, 0, 0, 0) + +-#endif /* __ASSEMBLY__ */ ++#endif /* __ASSEMBLER__ */ + + #endif /* _ASM_X86_UNWIND_HINTS_H */ +diff --git a/arch/x86/include/asm/vdso/getrandom.h b/arch/x86/include/asm/vdso/getrandom.h +index 2bf9c0e970c3e..785f8edcb9c99 100644 +--- a/arch/x86/include/asm/vdso/getrandom.h ++++ b/arch/x86/include/asm/vdso/getrandom.h +@@ -5,7 +5,7 @@ + #ifndef __ASM_VDSO_GETRANDOM_H + #define __ASM_VDSO_GETRANDOM_H + +-#ifndef __ASSEMBLY__ ++#ifndef __ASSEMBLER__ + + #include + +@@ -37,6 +37,6 @@ static __always_inline const struct vdso_rng_data *__arch_get_vdso_rng_data(void + return &vdso_rng_data; + } + +-#endif /* !__ASSEMBLY__ */ ++#endif /* !__ASSEMBLER__ */ + + #endif /* __ASM_VDSO_GETRANDOM_H */ +diff --git a/arch/x86/include/asm/vdso/gettimeofday.h b/arch/x86/include/asm/vdso/gettimeofday.h +index 375a34b0f3657..428f3f4c2235f 100644 +--- a/arch/x86/include/asm/vdso/gettimeofday.h ++++ b/arch/x86/include/asm/vdso/gettimeofday.h +@@ -10,7 +10,7 @@ + #ifndef __ASM_VDSO_GETTIMEOFDAY_H + #define __ASM_VDSO_GETTIMEOFDAY_H + +-#ifndef __ASSEMBLY__ ++#ifndef __ASSEMBLER__ + + #include + #include +@@ -350,6 +350,6 @@ static __always_inline u64 vdso_calc_ns(const struct vdso_data *vd, u64 cycles, + } + #define vdso_calc_ns vdso_calc_ns + +-#endif /* !__ASSEMBLY__ */ ++#endif /* !__ASSEMBLER__ */ + + #endif /* __ASM_VDSO_GETTIMEOFDAY_H */ +diff --git a/arch/x86/include/asm/vdso/processor.h b/arch/x86/include/asm/vdso/processor.h +index 2cbce97d29eaf..c9b2ba7a9ec4c 100644 +--- a/arch/x86/include/asm/vdso/processor.h ++++ b/arch/x86/include/asm/vdso/processor.h +@@ -5,7 +5,7 @@ + #ifndef __ASM_VDSO_PROCESSOR_H + #define __ASM_VDSO_PROCESSOR_H + +-#ifndef __ASSEMBLY__ ++#ifndef __ASSEMBLER__ + + /* REP NOP (PAUSE) is a good thing to insert into busy-wait loops. */ + static __always_inline void rep_nop(void) +@@ -22,6 +22,6 @@ struct getcpu_cache; + + notrace long __vdso_getcpu(unsigned *cpu, unsigned *node, struct getcpu_cache *unused); + +-#endif /* __ASSEMBLY__ */ ++#endif /* __ASSEMBLER__ */ + + #endif /* __ASM_VDSO_PROCESSOR_H */ +diff --git a/arch/x86/include/asm/vdso/vsyscall.h b/arch/x86/include/asm/vdso/vsyscall.h +index 88b31d4cdfaf3..6622e0103444e 100644 +--- a/arch/x86/include/asm/vdso/vsyscall.h ++++ b/arch/x86/include/asm/vdso/vsyscall.h +@@ -10,7 +10,7 @@ + #define VDSO_PAGE_PVCLOCK_OFFSET 0 + #define VDSO_PAGE_HVCLOCK_OFFSET 1 + +-#ifndef __ASSEMBLY__ ++#ifndef __ASSEMBLER__ + + #include + #include +@@ -37,6 +37,6 @@ struct vdso_rng_data *__x86_get_k_vdso_rng_data(void) + /* The asm-generic header needs to be included after the definitions above */ + #include + +-#endif /* !__ASSEMBLY__ */ ++#endif /* !__ASSEMBLER__ */ + + #endif /* __ASM_VDSO_VSYSCALL_H */ +diff --git a/arch/x86/include/asm/xen/interface.h b/arch/x86/include/asm/xen/interface.h +index baca0b00ef768..a078a2b0f032b 100644 +--- a/arch/x86/include/asm/xen/interface.h ++++ b/arch/x86/include/asm/xen/interface.h +@@ -72,7 +72,7 @@ + #endif + #endif + +-#ifndef __ASSEMBLY__ ++#ifndef __ASSEMBLER__ + /* Explicitly size integers that represent pfns in the public interface + * with Xen so that on ARM we can have one ABI that works for 32 and 64 + * bit guests. */ +@@ -137,7 +137,7 @@ DEFINE_GUEST_HANDLE(xen_ulong_t); + #define TI_SET_DPL(_ti, _dpl) ((_ti)->flags |= (_dpl)) + #define TI_SET_IF(_ti, _if) ((_ti)->flags |= ((!!(_if))<<2)) + +-#ifndef __ASSEMBLY__ ++#ifndef __ASSEMBLER__ + struct trap_info { + uint8_t vector; /* exception vector */ + uint8_t flags; /* 0-3: privilege level; 4: clear event enable? */ +@@ -186,7 +186,7 @@ struct arch_shared_info { + uint32_t wc_sec_hi; + #endif + }; +-#endif /* !__ASSEMBLY__ */ ++#endif /* !__ASSEMBLER__ */ + + #ifdef CONFIG_X86_32 + #include +@@ -196,7 +196,7 @@ struct arch_shared_info { + + #include + +-#ifndef __ASSEMBLY__ ++#ifndef __ASSEMBLER__ + /* + * The following is all CPU context. Note that the fpu_ctxt block is filled + * in by FXSAVE if the CPU has feature FXSR; otherwise FSAVE is used. +@@ -376,7 +376,7 @@ struct xen_pmu_arch { + } c; + }; + +-#endif /* !__ASSEMBLY__ */ ++#endif /* !__ASSEMBLER__ */ + + /* + * Prefix forces emulation of some non-trapping instructions. +diff --git a/arch/x86/include/asm/xen/interface_32.h b/arch/x86/include/asm/xen/interface_32.h +index dc40578abded7..74d9768a9cf77 100644 +--- a/arch/x86/include/asm/xen/interface_32.h ++++ b/arch/x86/include/asm/xen/interface_32.h +@@ -44,7 +44,7 @@ + */ + #define __HYPERVISOR_VIRT_START 0xF5800000 + +-#ifndef __ASSEMBLY__ ++#ifndef __ASSEMBLER__ + + struct cpu_user_regs { + uint32_t ebx; +@@ -85,7 +85,7 @@ typedef struct xen_callback xen_callback_t; + + #define XEN_CALLBACK(__cs, __eip) \ + ((struct xen_callback){ .cs = (__cs), .eip = (unsigned long)(__eip) }) +-#endif /* !__ASSEMBLY__ */ ++#endif /* !__ASSEMBLER__ */ + + + /* +diff --git a/arch/x86/include/asm/xen/interface_64.h b/arch/x86/include/asm/xen/interface_64.h +index c10f279aae936..38a19edb81a31 100644 +--- a/arch/x86/include/asm/xen/interface_64.h ++++ b/arch/x86/include/asm/xen/interface_64.h +@@ -77,7 +77,7 @@ + #define VGCF_in_syscall (1<<_VGCF_in_syscall) + #define VGCF_IN_SYSCALL VGCF_in_syscall + +-#ifndef __ASSEMBLY__ ++#ifndef __ASSEMBLER__ + + struct iret_context { + /* Top of stack (%rsp at point of hypercall). */ +@@ -143,7 +143,7 @@ typedef unsigned long xen_callback_t; + #define XEN_CALLBACK(__cs, __rip) \ + ((unsigned long)(__rip)) + +-#endif /* !__ASSEMBLY__ */ ++#endif /* !__ASSEMBLER__ */ + + + #endif /* _ASM_X86_XEN_INTERFACE_64_H */ +diff --git a/arch/x86/math-emu/control_w.h b/arch/x86/math-emu/control_w.h +index 60f4dcc5edc3c..93cbc89b34e25 100644 +--- a/arch/x86/math-emu/control_w.h ++++ b/arch/x86/math-emu/control_w.h +@@ -11,7 +11,7 @@ + #ifndef _CONTROLW_H_ + #define _CONTROLW_H_ + +-#ifdef __ASSEMBLY__ ++#ifdef __ASSEMBLER__ + #define _Const_(x) $##x + #else + #define _Const_(x) x +diff --git a/arch/x86/math-emu/exception.h b/arch/x86/math-emu/exception.h +index 75230b9775777..59961d350bc4d 100644 +--- a/arch/x86/math-emu/exception.h ++++ b/arch/x86/math-emu/exception.h +@@ -10,7 +10,7 @@ + #ifndef _EXCEPTION_H_ + #define _EXCEPTION_H_ + +-#ifdef __ASSEMBLY__ ++#ifdef __ASSEMBLER__ + #define Const_(x) $##x + #else + #define Const_(x) x +@@ -37,7 +37,7 @@ + #define PRECISION_LOST_UP Const_((EX_Precision | SW_C1)) + #define PRECISION_LOST_DOWN Const_(EX_Precision) + +-#ifndef __ASSEMBLY__ ++#ifndef __ASSEMBLER__ + + #ifdef DEBUG + #define EXCEPTION(x) { printk("exception in %s at line %d\n", \ +@@ -46,6 +46,6 @@ + #define EXCEPTION(x) FPU_exception(x) + #endif + +-#endif /* __ASSEMBLY__ */ ++#endif /* __ASSEMBLER__ */ + + #endif /* _EXCEPTION_H_ */ +diff --git a/arch/x86/math-emu/fpu_emu.h b/arch/x86/math-emu/fpu_emu.h +index 0c122226ca56f..def569c50b760 100644 +--- a/arch/x86/math-emu/fpu_emu.h ++++ b/arch/x86/math-emu/fpu_emu.h +@@ -20,7 +20,7 @@ + */ + #define PECULIAR_486 + +-#ifdef __ASSEMBLY__ ++#ifdef __ASSEMBLER__ + #include "fpu_asm.h" + #define Const(x) $##x + #else +@@ -68,7 +68,7 @@ + + #define FPU_Exception Const(0x80000000) /* Added to tag returns. */ + +-#ifndef __ASSEMBLY__ ++#ifndef __ASSEMBLER__ + + #include "fpu_system.h" + +@@ -213,6 +213,6 @@ asmlinkage int FPU_round(FPU_REG *arg, unsigned int extent, int dummy, + #include "fpu_proto.h" + #endif + +-#endif /* __ASSEMBLY__ */ ++#endif /* __ASSEMBLER__ */ + + #endif /* _FPU_EMU_H_ */ +diff --git a/arch/x86/math-emu/status_w.h b/arch/x86/math-emu/status_w.h +index b77bafec95260..f642957330efc 100644 +--- a/arch/x86/math-emu/status_w.h ++++ b/arch/x86/math-emu/status_w.h +@@ -13,7 +13,7 @@ + + #include "fpu_emu.h" /* for definition of PECULIAR_486 */ + +-#ifdef __ASSEMBLY__ ++#ifdef __ASSEMBLER__ + #define Const__(x) $##x + #else + #define Const__(x) x +@@ -37,7 +37,7 @@ + + #define SW_Exc_Mask Const__(0x27f) /* Status word exception bit mask */ + +-#ifndef __ASSEMBLY__ ++#ifndef __ASSEMBLER__ + + #define COMP_A_gt_B 1 + #define COMP_A_eq_B 2 +@@ -63,6 +63,6 @@ static inline void setcc(int cc) + # define clear_C1() + #endif /* PECULIAR_486 */ + +-#endif /* __ASSEMBLY__ */ ++#endif /* __ASSEMBLER__ */ + + #endif /* _STATUS_H_ */ +diff --git a/arch/x86/realmode/rm/realmode.h b/arch/x86/realmode/rm/realmode.h +index c76041a353970..867e55f1d6af4 100644 +--- a/arch/x86/realmode/rm/realmode.h ++++ b/arch/x86/realmode/rm/realmode.h +@@ -2,7 +2,7 @@ + #ifndef ARCH_X86_REALMODE_RM_REALMODE_H + #define ARCH_X86_REALMODE_RM_REALMODE_H + +-#ifdef __ASSEMBLY__ ++#ifdef __ASSEMBLER__ + + /* + * 16-bit ljmpw to the real_mode_seg +@@ -12,7 +12,7 @@ + */ + #define LJMPW_RM(to) .byte 0xea ; .word (to), real_mode_seg + +-#endif /* __ASSEMBLY__ */ ++#endif /* __ASSEMBLER__ */ + + /* + * Signature at the end of the realmode region +diff --git a/arch/x86/realmode/rm/wakeup.h b/arch/x86/realmode/rm/wakeup.h +index 0e4fd08ae4471..3b6d8fa82d3e1 100644 +--- a/arch/x86/realmode/rm/wakeup.h ++++ b/arch/x86/realmode/rm/wakeup.h +@@ -7,7 +7,7 @@ + #ifndef ARCH_X86_KERNEL_ACPI_RM_WAKEUP_H + #define ARCH_X86_KERNEL_ACPI_RM_WAKEUP_H + +-#ifndef __ASSEMBLY__ ++#ifndef __ASSEMBLER__ + #include + + /* This must match data at wakeup.S */ +diff --git a/tools/arch/x86/include/asm/asm.h b/tools/arch/x86/include/asm/asm.h +index 3ad3da9a7d974..dbe39b44256ba 100644 +--- a/tools/arch/x86/include/asm/asm.h ++++ b/tools/arch/x86/include/asm/asm.h +@@ -2,7 +2,7 @@ + #ifndef _ASM_X86_ASM_H + #define _ASM_X86_ASM_H + +-#ifdef __ASSEMBLY__ ++#ifdef __ASSEMBLER__ + # define __ASM_FORM(x, ...) x,## __VA_ARGS__ + # define __ASM_FORM_RAW(x, ...) x,## __VA_ARGS__ + # define __ASM_FORM_COMMA(x, ...) x,## __VA_ARGS__, +@@ -123,7 +123,7 @@ + #ifdef __KERNEL__ + + /* Exception table entry */ +-#ifdef __ASSEMBLY__ ++#ifdef __ASSEMBLER__ + # define _ASM_EXTABLE_HANDLE(from, to, handler) \ + .pushsection "__ex_table","a" ; \ + .balign 4 ; \ +@@ -154,7 +154,7 @@ + # define _ASM_NOKPROBE(entry) + # endif + +-#else /* ! __ASSEMBLY__ */ ++#else /* ! __ASSEMBLER__ */ + # define _EXPAND_EXTABLE_HANDLE(x) #x + # define _ASM_EXTABLE_HANDLE(from, to, handler) \ + " .pushsection \"__ex_table\",\"a\"\n" \ +@@ -186,7 +186,7 @@ + */ + register unsigned long current_stack_pointer asm(_ASM_SP); + #define ASM_CALL_CONSTRAINT "+r" (current_stack_pointer) +-#endif /* __ASSEMBLY__ */ ++#endif /* __ASSEMBLER__ */ + + #endif /* __KERNEL__ */ + +diff --git a/tools/arch/x86/include/asm/nops.h b/tools/arch/x86/include/asm/nops.h +index 1c1b7550fa550..cd94221d83358 100644 +--- a/tools/arch/x86/include/asm/nops.h ++++ b/tools/arch/x86/include/asm/nops.h +@@ -82,7 +82,7 @@ + #define ASM_NOP7 _ASM_BYTES(BYTES_NOP7) + #define ASM_NOP8 _ASM_BYTES(BYTES_NOP8) + +-#ifndef __ASSEMBLY__ ++#ifndef __ASSEMBLER__ + extern const unsigned char * const x86_nops[]; + #endif + +diff --git a/tools/arch/x86/include/asm/orc_types.h b/tools/arch/x86/include/asm/orc_types.h +index 46d7e06763c9f..e0125afa53fb9 100644 +--- a/tools/arch/x86/include/asm/orc_types.h ++++ b/tools/arch/x86/include/asm/orc_types.h +@@ -45,7 +45,7 @@ + #define ORC_TYPE_REGS 3 + #define ORC_TYPE_REGS_PARTIAL 4 + +-#ifndef __ASSEMBLY__ ++#ifndef __ASSEMBLER__ + #include + + /* +@@ -73,6 +73,6 @@ struct orc_entry { + #endif + } __packed; + +-#endif /* __ASSEMBLY__ */ ++#endif /* __ASSEMBLER__ */ + + #endif /* _ORC_TYPES_H */ +diff --git a/tools/arch/x86/include/asm/pvclock-abi.h b/tools/arch/x86/include/asm/pvclock-abi.h +index 1436226efe3ef..b9fece5fc96d6 100644 +--- a/tools/arch/x86/include/asm/pvclock-abi.h ++++ b/tools/arch/x86/include/asm/pvclock-abi.h +@@ -1,7 +1,7 @@ + /* SPDX-License-Identifier: GPL-2.0 */ + #ifndef _ASM_X86_PVCLOCK_ABI_H + #define _ASM_X86_PVCLOCK_ABI_H +-#ifndef __ASSEMBLY__ ++#ifndef __ASSEMBLER__ + + /* + * These structs MUST NOT be changed. +@@ -44,5 +44,5 @@ struct pvclock_wall_clock { + #define PVCLOCK_GUEST_STOPPED (1 << 1) + /* PVCLOCK_COUNTS_FROM_ZERO broke ABI and can't be used anymore. */ + #define PVCLOCK_COUNTS_FROM_ZERO (1 << 2) +-#endif /* __ASSEMBLY__ */ ++#endif /* __ASSEMBLER__ */ + #endif /* _ASM_X86_PVCLOCK_ABI_H */ +-- +2.39.5 + diff --git a/queue-6.14/x86-headers-replace-__assembly__-with-__assembler__-.patch-7903 b/queue-6.14/x86-headers-replace-__assembly__-with-__assembler__-.patch-7903 new file mode 100644 index 0000000000..7d3ec68a54 --- /dev/null +++ b/queue-6.14/x86-headers-replace-__assembly__-with-__assembler__-.patch-7903 @@ -0,0 +1,232 @@ +From 7e4799f00592455780de17b2e53c082ff8bb40ac Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 10 Mar 2025 11:42:56 +0100 +Subject: x86/headers: Replace __ASSEMBLY__ with __ASSEMBLER__ in UAPI headers + +From: Thomas Huth + +[ Upstream commit 8a141be3233af7d4f7014ebc44d5452d46b2b1be ] + +__ASSEMBLY__ is only defined by the Makefile of the kernel, so +this is not really useful for UAPI headers (unless the userspace +Makefile defines it, too). Let's switch to __ASSEMBLER__ which +gets set automatically by the compiler when compiling assembly +code. + +Signed-off-by: Thomas Huth +Signed-off-by: Ingo Molnar +Cc: "H. Peter Anvin" +Cc: Linus Torvalds +Cc: Kees Cook +Cc: Brian Gerst +Link: https://lore.kernel.org/r/20250310104256.123527-1-thuth@redhat.com +Signed-off-by: Sasha Levin +--- + arch/x86/include/uapi/asm/bootparam.h | 4 ++-- + arch/x86/include/uapi/asm/e820.h | 4 ++-- + arch/x86/include/uapi/asm/ldt.h | 4 ++-- + arch/x86/include/uapi/asm/msr.h | 4 ++-- + arch/x86/include/uapi/asm/ptrace-abi.h | 6 +++--- + arch/x86/include/uapi/asm/ptrace.h | 4 ++-- + arch/x86/include/uapi/asm/setup_data.h | 4 ++-- + arch/x86/include/uapi/asm/signal.h | 8 ++++---- + 8 files changed, 19 insertions(+), 19 deletions(-) + +diff --git a/arch/x86/include/uapi/asm/bootparam.h b/arch/x86/include/uapi/asm/bootparam.h +index 9b82eebd7add5..dafbf581c515d 100644 +--- a/arch/x86/include/uapi/asm/bootparam.h ++++ b/arch/x86/include/uapi/asm/bootparam.h +@@ -26,7 +26,7 @@ + #define XLF_5LEVEL_ENABLED (1<<6) + #define XLF_MEM_ENCRYPTION (1<<7) + +-#ifndef __ASSEMBLY__ ++#ifndef __ASSEMBLER__ + + #include + #include +@@ -210,6 +210,6 @@ enum x86_hardware_subarch { + X86_NR_SUBARCHS, + }; + +-#endif /* __ASSEMBLY__ */ ++#endif /* __ASSEMBLER__ */ + + #endif /* _ASM_X86_BOOTPARAM_H */ +diff --git a/arch/x86/include/uapi/asm/e820.h b/arch/x86/include/uapi/asm/e820.h +index 2f491efe3a126..55bc668671560 100644 +--- a/arch/x86/include/uapi/asm/e820.h ++++ b/arch/x86/include/uapi/asm/e820.h +@@ -54,7 +54,7 @@ + */ + #define E820_RESERVED_KERN 128 + +-#ifndef __ASSEMBLY__ ++#ifndef __ASSEMBLER__ + #include + struct e820entry { + __u64 addr; /* start of memory segment */ +@@ -76,7 +76,7 @@ struct e820map { + #define BIOS_ROM_BASE 0xffe00000 + #define BIOS_ROM_END 0xffffffff + +-#endif /* __ASSEMBLY__ */ ++#endif /* __ASSEMBLER__ */ + + + #endif /* _UAPI_ASM_X86_E820_H */ +diff --git a/arch/x86/include/uapi/asm/ldt.h b/arch/x86/include/uapi/asm/ldt.h +index d62ac5db093b4..a82c039d8e6a7 100644 +--- a/arch/x86/include/uapi/asm/ldt.h ++++ b/arch/x86/include/uapi/asm/ldt.h +@@ -12,7 +12,7 @@ + /* The size of each LDT entry. */ + #define LDT_ENTRY_SIZE 8 + +-#ifndef __ASSEMBLY__ ++#ifndef __ASSEMBLER__ + /* + * Note on 64bit base and limit is ignored and you cannot set DS/ES/CS + * not to the default values if you still want to do syscalls. This +@@ -44,5 +44,5 @@ struct user_desc { + #define MODIFY_LDT_CONTENTS_STACK 1 + #define MODIFY_LDT_CONTENTS_CODE 2 + +-#endif /* !__ASSEMBLY__ */ ++#endif /* !__ASSEMBLER__ */ + #endif /* _ASM_X86_LDT_H */ +diff --git a/arch/x86/include/uapi/asm/msr.h b/arch/x86/include/uapi/asm/msr.h +index e7516b402a00f..4b8917ca28fe7 100644 +--- a/arch/x86/include/uapi/asm/msr.h ++++ b/arch/x86/include/uapi/asm/msr.h +@@ -2,7 +2,7 @@ + #ifndef _UAPI_ASM_X86_MSR_H + #define _UAPI_ASM_X86_MSR_H + +-#ifndef __ASSEMBLY__ ++#ifndef __ASSEMBLER__ + + #include + #include +@@ -10,5 +10,5 @@ + #define X86_IOC_RDMSR_REGS _IOWR('c', 0xA0, __u32[8]) + #define X86_IOC_WRMSR_REGS _IOWR('c', 0xA1, __u32[8]) + +-#endif /* __ASSEMBLY__ */ ++#endif /* __ASSEMBLER__ */ + #endif /* _UAPI_ASM_X86_MSR_H */ +diff --git a/arch/x86/include/uapi/asm/ptrace-abi.h b/arch/x86/include/uapi/asm/ptrace-abi.h +index 16074b9c93bb5..5823584dea132 100644 +--- a/arch/x86/include/uapi/asm/ptrace-abi.h ++++ b/arch/x86/include/uapi/asm/ptrace-abi.h +@@ -25,7 +25,7 @@ + + #else /* __i386__ */ + +-#if defined(__ASSEMBLY__) || defined(__FRAME_OFFSETS) ++#if defined(__ASSEMBLER__) || defined(__FRAME_OFFSETS) + /* + * C ABI says these regs are callee-preserved. They aren't saved on kernel entry + * unless syscall needs a complete, fully filled "struct pt_regs". +@@ -57,7 +57,7 @@ + #define EFLAGS 144 + #define RSP 152 + #define SS 160 +-#endif /* __ASSEMBLY__ */ ++#endif /* __ASSEMBLER__ */ + + /* top of stack page */ + #define FRAME_SIZE 168 +@@ -87,7 +87,7 @@ + + #define PTRACE_SINGLEBLOCK 33 /* resume execution until next branch */ + +-#ifndef __ASSEMBLY__ ++#ifndef __ASSEMBLER__ + #include + #endif + +diff --git a/arch/x86/include/uapi/asm/ptrace.h b/arch/x86/include/uapi/asm/ptrace.h +index 85165c0edafc8..e0b5b4f6226b1 100644 +--- a/arch/x86/include/uapi/asm/ptrace.h ++++ b/arch/x86/include/uapi/asm/ptrace.h +@@ -7,7 +7,7 @@ + #include + + +-#ifndef __ASSEMBLY__ ++#ifndef __ASSEMBLER__ + + #ifdef __i386__ + /* this struct defines the way the registers are stored on the +@@ -81,6 +81,6 @@ struct pt_regs { + + + +-#endif /* !__ASSEMBLY__ */ ++#endif /* !__ASSEMBLER__ */ + + #endif /* _UAPI_ASM_X86_PTRACE_H */ +diff --git a/arch/x86/include/uapi/asm/setup_data.h b/arch/x86/include/uapi/asm/setup_data.h +index b111b0c185449..50c45ead4e7c9 100644 +--- a/arch/x86/include/uapi/asm/setup_data.h ++++ b/arch/x86/include/uapi/asm/setup_data.h +@@ -18,7 +18,7 @@ + #define SETUP_INDIRECT (1<<31) + #define SETUP_TYPE_MAX (SETUP_ENUM_MAX | SETUP_INDIRECT) + +-#ifndef __ASSEMBLY__ ++#ifndef __ASSEMBLER__ + + #include + +@@ -78,6 +78,6 @@ struct ima_setup_data { + __u64 size; + } __attribute__((packed)); + +-#endif /* __ASSEMBLY__ */ ++#endif /* __ASSEMBLER__ */ + + #endif /* _UAPI_ASM_X86_SETUP_DATA_H */ +diff --git a/arch/x86/include/uapi/asm/signal.h b/arch/x86/include/uapi/asm/signal.h +index f777346450ec3..1067efabf18b5 100644 +--- a/arch/x86/include/uapi/asm/signal.h ++++ b/arch/x86/include/uapi/asm/signal.h +@@ -2,7 +2,7 @@ + #ifndef _UAPI_ASM_X86_SIGNAL_H + #define _UAPI_ASM_X86_SIGNAL_H + +-#ifndef __ASSEMBLY__ ++#ifndef __ASSEMBLER__ + #include + #include + +@@ -16,7 +16,7 @@ struct siginfo; + typedef unsigned long sigset_t; + + #endif /* __KERNEL__ */ +-#endif /* __ASSEMBLY__ */ ++#endif /* __ASSEMBLER__ */ + + + #define SIGHUP 1 +@@ -68,7 +68,7 @@ typedef unsigned long sigset_t; + + #include + +-#ifndef __ASSEMBLY__ ++#ifndef __ASSEMBLER__ + + + # ifndef __KERNEL__ +@@ -106,6 +106,6 @@ typedef struct sigaltstack { + __kernel_size_t ss_size; + } stack_t; + +-#endif /* __ASSEMBLY__ */ ++#endif /* __ASSEMBLER__ */ + + #endif /* _UAPI_ASM_X86_SIGNAL_H */ +-- +2.39.5 + diff --git a/queue-6.14/x86-ibt-handle-fineibt-in-handle_cfi_failure.patch b/queue-6.14/x86-ibt-handle-fineibt-in-handle_cfi_failure.patch new file mode 100644 index 0000000000..bd66b72a04 --- /dev/null +++ b/queue-6.14/x86-ibt-handle-fineibt-in-handle_cfi_failure.patch @@ -0,0 +1,140 @@ +From 63388f7dbfa5dc2ae6ba7312d68eb0b58e020e9e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 13 Feb 2025 12:45:47 +0100 +Subject: x86/ibt: Handle FineIBT in handle_cfi_failure() + +From: Peter Zijlstra + +[ Upstream commit 882b86fd4e0d49bf91148dbadcdbece19ded40e6 ] + +Sami reminded me that FineIBT failure does not hook into the regular +CFI failure case, and as such CFI_PERMISSIVE does not work. + +Reported-by: Sami Tolvanen +Signed-off-by: Peter Zijlstra (Intel) +Reviewed-by: Sami Tolvanen +Link: https://lkml.kernel.org/r/20250214092619.GB21726@noisy.programming.kicks-ass.net +Signed-off-by: Sasha Levin +--- + arch/x86/include/asm/cfi.h | 11 +++++++++++ + arch/x86/kernel/alternative.c | 30 ++++++++++++++++++++++++++++++ + arch/x86/kernel/cfi.c | 22 ++++++++++++++++++---- + 3 files changed, 59 insertions(+), 4 deletions(-) + +diff --git a/arch/x86/include/asm/cfi.h b/arch/x86/include/asm/cfi.h +index 31d19c815f992..7dd5ab239c87b 100644 +--- a/arch/x86/include/asm/cfi.h ++++ b/arch/x86/include/asm/cfi.h +@@ -126,6 +126,17 @@ static inline int cfi_get_offset(void) + + extern u32 cfi_get_func_hash(void *func); + ++#ifdef CONFIG_FINEIBT ++extern bool decode_fineibt_insn(struct pt_regs *regs, unsigned long *target, u32 *type); ++#else ++static inline bool ++decode_fineibt_insn(struct pt_regs *regs, unsigned long *target, u32 *type) ++{ ++ return false; ++} ++ ++#endif ++ + #else + static inline enum bug_trap_type handle_cfi_failure(struct pt_regs *regs) + { +diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c +index f843fd37cf987..e1913bcb806e2 100644 +--- a/arch/x86/kernel/alternative.c ++++ b/arch/x86/kernel/alternative.c +@@ -1271,6 +1271,7 @@ asm( ".pushsection .rodata \n" + " endbr64 \n" + " subl $0x12345678, %r10d \n" + " je fineibt_preamble_end \n" ++ "fineibt_preamble_ud2: \n" + " ud2 \n" + " nop \n" + "fineibt_preamble_end: \n" +@@ -1278,9 +1279,11 @@ asm( ".pushsection .rodata \n" + ); + + extern u8 fineibt_preamble_start[]; ++extern u8 fineibt_preamble_ud2[]; + extern u8 fineibt_preamble_end[]; + + #define fineibt_preamble_size (fineibt_preamble_end - fineibt_preamble_start) ++#define fineibt_preamble_ud2 (fineibt_preamble_ud2 - fineibt_preamble_start) + #define fineibt_preamble_hash 7 + + asm( ".pushsection .rodata \n" +@@ -1598,6 +1601,33 @@ static void poison_cfi(void *addr, void *wr_addr) + } + } + ++/* ++ * regs->ip points to a UD2 instruction, return true and fill out target and ++ * type when this UD2 is from a FineIBT preamble. ++ * ++ * We check the preamble by checking for the ENDBR instruction relative to the ++ * UD2 instruction. ++ */ ++bool decode_fineibt_insn(struct pt_regs *regs, unsigned long *target, u32 *type) ++{ ++ unsigned long addr = regs->ip - fineibt_preamble_ud2; ++ u32 endbr, hash; ++ ++ __get_kernel_nofault(&endbr, addr, u32, Efault); ++ if (endbr != gen_endbr()) ++ return false; ++ ++ *target = addr + fineibt_preamble_size; ++ ++ __get_kernel_nofault(&hash, addr + fineibt_preamble_hash, u32, Efault); ++ *type = (u32)regs->r10 + hash; ++ ++ return true; ++ ++Efault: ++ return false; ++} ++ + #else + + static void __apply_fineibt(s32 *start_retpoline, s32 *end_retpoline, +diff --git a/arch/x86/kernel/cfi.c b/arch/x86/kernel/cfi.c +index e6bf78fac1462..f6905bef0af84 100644 +--- a/arch/x86/kernel/cfi.c ++++ b/arch/x86/kernel/cfi.c +@@ -70,11 +70,25 @@ enum bug_trap_type handle_cfi_failure(struct pt_regs *regs) + unsigned long target; + u32 type; + +- if (!is_cfi_trap(regs->ip)) +- return BUG_TRAP_TYPE_NONE; ++ switch (cfi_mode) { ++ case CFI_KCFI: ++ if (!is_cfi_trap(regs->ip)) ++ return BUG_TRAP_TYPE_NONE; ++ ++ if (!decode_cfi_insn(regs, &target, &type)) ++ return report_cfi_failure_noaddr(regs, regs->ip); ++ ++ break; + +- if (!decode_cfi_insn(regs, &target, &type)) +- return report_cfi_failure_noaddr(regs, regs->ip); ++ case CFI_FINEIBT: ++ if (!decode_fineibt_insn(regs, &target, &type)) ++ return BUG_TRAP_TYPE_NONE; ++ ++ break; ++ ++ default: ++ return BUG_TRAP_TYPE_NONE; ++ } + + return report_cfi_failure(regs, regs->ip, &target, type); + } +-- +2.39.5 + diff --git a/queue-6.14/x86-kaslr-reduce-kaslr-entropy-on-most-x86-systems.patch b/queue-6.14/x86-kaslr-reduce-kaslr-entropy-on-most-x86-systems.patch new file mode 100644 index 0000000000..171b9cd512 --- /dev/null +++ b/queue-6.14/x86-kaslr-reduce-kaslr-entropy-on-most-x86-systems.patch @@ -0,0 +1,88 @@ +From ace30a5c8ff752b9ebe8c9066207c638f7a14f0f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 7 Feb 2025 10:42:34 +1100 +Subject: x86/kaslr: Reduce KASLR entropy on most x86 systems + +From: Balbir Singh + +[ Upstream commit 7ffb791423c7c518269a9aad35039ef824a40adb ] + +When CONFIG_PCI_P2PDMA=y (which is basically enabled on all +large x86 distros), it maps the PFN's via a ZONE_DEVICE +mapping using devm_memremap_pages(). The mapped virtual +address range corresponds to the pci_resource_start() +of the BAR address and size corresponding to the BAR length. + +When KASLR is enabled, the direct map range of the kernel is +reduced to the size of physical memory plus additional padding. +If the BAR address is beyond this limit, PCI peer to peer DMA +mappings fail. + +Fix this by not shrinking the size of the direct map when +CONFIG_PCI_P2PDMA=y. + +This reduces the total available entropy, but it's better than +the current work around of having to disable KASLR completely. + +[ mingo: Clarified the changelog to point out the broad impact ... ] + +Signed-off-by: Balbir Singh +Signed-off-by: Ingo Molnar +Reviewed-by: Kees Cook +Acked-by: Bjorn Helgaas # drivers/pci/Kconfig +Cc: Linus Torvalds +Cc: Peter Zijlstra +Cc: Andy Lutomirski +Link: https://lore.kernel.org/lkml/20250206023201.1481957-1-balbirs@nvidia.com/ +Link: https://lore.kernel.org/r/20250206234234.1912585-1-balbirs@nvidia.com +-- + arch/x86/mm/kaslr.c | 10 ++++++++-- + drivers/pci/Kconfig | 6 ++++++ + 2 files changed, 14 insertions(+), 2 deletions(-) +Signed-off-by: Sasha Levin +--- + arch/x86/mm/kaslr.c | 10 ++++++++-- + drivers/pci/Kconfig | 6 ++++++ + 2 files changed, 14 insertions(+), 2 deletions(-) + +diff --git a/arch/x86/mm/kaslr.c b/arch/x86/mm/kaslr.c +index 11a93542d1983..3c306de52fd4d 100644 +--- a/arch/x86/mm/kaslr.c ++++ b/arch/x86/mm/kaslr.c +@@ -113,8 +113,14 @@ void __init kernel_randomize_memory(void) + memory_tb = DIV_ROUND_UP(max_pfn << PAGE_SHIFT, 1UL << TB_SHIFT) + + CONFIG_RANDOMIZE_MEMORY_PHYSICAL_PADDING; + +- /* Adapt physical memory region size based on available memory */ +- if (memory_tb < kaslr_regions[0].size_tb) ++ /* ++ * Adapt physical memory region size based on available memory, ++ * except when CONFIG_PCI_P2PDMA is enabled. P2PDMA exposes the ++ * device BAR space assuming the direct map space is large enough ++ * for creating a ZONE_DEVICE mapping in the direct map corresponding ++ * to the physical BAR address. ++ */ ++ if (!IS_ENABLED(CONFIG_PCI_P2PDMA) && (memory_tb < kaslr_regions[0].size_tb)) + kaslr_regions[0].size_tb = memory_tb; + + /* +diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig +index 2fbd379923fd1..5c3054aaec8c1 100644 +--- a/drivers/pci/Kconfig ++++ b/drivers/pci/Kconfig +@@ -203,6 +203,12 @@ config PCI_P2PDMA + P2P DMA transactions must be between devices behind the same root + port. + ++ Enabling this option will reduce the entropy of x86 KASLR memory ++ regions. For example - on a 46 bit system, the entropy goes down ++ from 16 bits to 15 bits. The actual reduction in entropy depends ++ on the physical address bits, on processor features, kernel config ++ (5 level page table) and physical memory present on the system. ++ + If unsure, say N. + + config PCI_LABEL +-- +2.39.5 + diff --git a/queue-6.14/x86-kconfig-make-cfi_auto_default-depend-on-rust-or-.patch b/queue-6.14/x86-kconfig-make-cfi_auto_default-depend-on-rust-or-.patch new file mode 100644 index 0000000000..b191e973db --- /dev/null +++ b/queue-6.14/x86-kconfig-make-cfi_auto_default-depend-on-rust-or-.patch @@ -0,0 +1,95 @@ +From 7a8614dc5f7fb0795b75ae9d77c870d28dc6c506 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 10 Apr 2025 11:54:20 +0000 +Subject: x86/Kconfig: make CFI_AUTO_DEFAULT depend on !RUST or Rust >= 1.88 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Paweł Anikiel + +[ Upstream commit 5595c31c370957aabe739ac3996aedba8267603f ] + +Calling core::fmt::write() from rust code while FineIBT is enabled +results in a kernel panic: + +[ 4614.199779] kernel BUG at arch/x86/kernel/cet.c:132! +[ 4614.205343] Oops: invalid opcode: 0000 [#1] PREEMPT SMP NOPTI +[ 4614.211781] CPU: 2 UID: 0 PID: 6057 Comm: dmabuf_dump Tainted: G U O 6.12.17-android16-0-g6ab38c534a43 #1 9da040f27673ec3945e23b998a0f8bd64c846599 +[ 4614.227832] Tainted: [U]=USER, [O]=OOT_MODULE +[ 4614.241247] RIP: 0010:do_kernel_cp_fault+0xea/0xf0 +... +[ 4614.398144] RIP: 0010:_RNvXs5_NtNtNtCs3o2tGsuHyou_4core3fmt3num3impyNtB9_7Display3fmt+0x0/0x20 +[ 4614.407792] Code: 48 f7 df 48 0f 48 f9 48 89 f2 89 c6 5d e9 18 fd ff ff 0f 1f 84 00 00 00 00 00 f3 0f 1e fa 41 81 ea 14 61 af 2c 74 03 0f 0b 90 <66> 0f 1f 00 55 48 89 e5 48 89 f2 48 8b 3f be 01 00 00 00 5d e9 e7 +[ 4614.428775] RSP: 0018:ffffb95acfa4ba68 EFLAGS: 00010246 +[ 4614.434609] RAX: 0000000000000000 RBX: 0000000000000010 RCX: 0000000000000000 +[ 4614.442587] RDX: 0000000000000007 RSI: ffffb95acfa4ba70 RDI: ffffb95acfa4bc88 +[ 4614.450557] RBP: ffffb95acfa4bae0 R08: ffff0a00ffffff05 R09: 0000000000000070 +[ 4614.458527] R10: 0000000000000000 R11: ffffffffab67eaf0 R12: ffffb95acfa4bcc8 +[ 4614.466493] R13: ffffffffac5d50f0 R14: 0000000000000000 R15: 0000000000000000 +[ 4614.474473] ? __cfi__RNvXs5_NtNtNtCs3o2tGsuHyou_4core3fmt3num3impyNtB9_7Display3fmt+0x10/0x10 +[ 4614.484118] ? _RNvNtCs3o2tGsuHyou_4core3fmt5write+0x1d2/0x250 + +This happens because core::fmt::write() calls +core::fmt::rt::Argument::fmt(), which currently has CFI disabled: + +library/core/src/fmt/rt.rs: +171 // FIXME: Transmuting formatter in new and indirectly branching to/calling +172 // it here is an explicit CFI violation. +173 #[allow(inline_no_sanitize)] +174 #[no_sanitize(cfi, kcfi)] +175 #[inline] +176 pub(super) unsafe fn fmt(&self, f: &mut Formatter<'_>) -> Result { + +This causes a Control Protection exception, because FineIBT has sealed +off the original function's endbr64. + +This makes rust currently incompatible with FineIBT. Add a Kconfig +dependency that prevents FineIBT from getting turned on by default +if rust is enabled. + +[ Rust 1.88.0 (scheduled for 2025-06-26) should have this fixed [1], + and thus we relaxed the condition with Rust >= 1.88. + + When `objtool` lands checking for this with e.g. [2], the plan is + to ideally run that in upstream Rust's CI to prevent regressions + early [3], since we do not control `core`'s source code. + + Alice tested the Rust PR backported to an older compiler. + + Peter would like that Rust provides a stable `core` which can be + pulled into the kernel: "Relying on that much out of tree code is + 'unfortunate'". + + - Miguel ] + +Signed-off-by: Paweł Anikiel +Reviewed-by: Alice Ryhl +Acked-by: Peter Zijlstra +Link: https://github.com/rust-lang/rust/pull/139632 [1] +Link: https://lore.kernel.org/rust-for-linux/20250410154556.GB9003@noisy.programming.kicks-ass.net/ [2] +Link: https://github.com/rust-lang/rust/pull/139632#issuecomment-2801950873 [3] +Link: https://lore.kernel.org/r/20250410115420.366349-1-panikiel@google.com +Link: https://lore.kernel.org/r/att0-CANiq72kjDM0cKALVy4POEzhfdT4nO7tqz0Pm7xM+3=_0+L1t=A@mail.gmail.com +[ Reduced splat. - Miguel ] +Signed-off-by: Miguel Ojeda +Signed-off-by: Sasha Levin +--- + arch/x86/Kconfig | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig +index 473364353bd96..5439bff8850a9 100644 +--- a/arch/x86/Kconfig ++++ b/arch/x86/Kconfig +@@ -2430,6 +2430,7 @@ config STRICT_SIGALTSTACK_SIZE + config CFI_AUTO_DEFAULT + bool "Attempt to use FineIBT by default at boot time" + depends on FINEIBT ++ depends on !RUST || RUSTC_VERSION >= 108800 + default y + help + Attempt to use FineIBT by default at boot time. If enabled, +-- +2.39.5 + diff --git a/queue-6.14/x86-locking-use-alt_output_sp-for-percpu_-try_-cmpxc.patch b/queue-6.14/x86-locking-use-alt_output_sp-for-percpu_-try_-cmpxc.patch new file mode 100644 index 0000000000..ddd73f02b4 --- /dev/null +++ b/queue-6.14/x86-locking-use-alt_output_sp-for-percpu_-try_-cmpxc.patch @@ -0,0 +1,93 @@ +From 1d6c55ace126ffc44b8aeae8297837b61b0f0f98 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 14 Feb 2025 16:07:46 +0100 +Subject: x86/locking: Use ALT_OUTPUT_SP() for + percpu_{,try_}cmpxchg{64,128}_op() + +From: Uros Bizjak + +[ Upstream commit 4087e16b033140cf2ce509ec23503bddec818a16 ] + +percpu_{,try_}cmpxchg{64,128}() macros use CALL instruction inside +asm statement in one of their alternatives. Use ALT_OUTPUT_SP() +macro to add required dependence on %esp register. + +ALT_OUTPUT_SP() implements the above dependence by adding +ASM_CALL_CONSTRAINT to its arguments. This constraint should be used +for any inline asm which has a CALL instruction, otherwise the +compiler may schedule the asm before the frame pointer gets set up +by the containing function, causing objtool to print a "call without +frame pointer save/setup" warning. + +Signed-off-by: Uros Bizjak +Signed-off-by: Ingo Molnar +Cc: Linus Torvalds +Link: https://lore.kernel.org/r/20250214150929.5780-1-ubizjak@gmail.com +Signed-off-by: Sasha Levin +--- + arch/x86/include/asm/percpu.h | 28 ++++++++++++++-------------- + 1 file changed, 14 insertions(+), 14 deletions(-) + +diff --git a/arch/x86/include/asm/percpu.h b/arch/x86/include/asm/percpu.h +index afb9099fba9fc..9c47da5b0a2a2 100644 +--- a/arch/x86/include/asm/percpu.h ++++ b/arch/x86/include/asm/percpu.h +@@ -350,9 +350,9 @@ do { \ + \ + asm qual (ALTERNATIVE("call this_cpu_cmpxchg8b_emu", \ + "cmpxchg8b " __percpu_arg([var]), X86_FEATURE_CX8) \ +- : [var] "+m" (__my_cpu_var(_var)), \ +- "+a" (old__.low), \ +- "+d" (old__.high) \ ++ : ALT_OUTPUT_SP([var] "+m" (__my_cpu_var(_var)), \ ++ "+a" (old__.low), \ ++ "+d" (old__.high)) \ + : "b" (new__.low), \ + "c" (new__.high), \ + "S" (&(_var)) \ +@@ -381,10 +381,10 @@ do { \ + asm qual (ALTERNATIVE("call this_cpu_cmpxchg8b_emu", \ + "cmpxchg8b " __percpu_arg([var]), X86_FEATURE_CX8) \ + CC_SET(z) \ +- : CC_OUT(z) (success), \ +- [var] "+m" (__my_cpu_var(_var)), \ +- "+a" (old__.low), \ +- "+d" (old__.high) \ ++ : ALT_OUTPUT_SP(CC_OUT(z) (success), \ ++ [var] "+m" (__my_cpu_var(_var)), \ ++ "+a" (old__.low), \ ++ "+d" (old__.high)) \ + : "b" (new__.low), \ + "c" (new__.high), \ + "S" (&(_var)) \ +@@ -421,9 +421,9 @@ do { \ + \ + asm qual (ALTERNATIVE("call this_cpu_cmpxchg16b_emu", \ + "cmpxchg16b " __percpu_arg([var]), X86_FEATURE_CX16) \ +- : [var] "+m" (__my_cpu_var(_var)), \ +- "+a" (old__.low), \ +- "+d" (old__.high) \ ++ : ALT_OUTPUT_SP([var] "+m" (__my_cpu_var(_var)), \ ++ "+a" (old__.low), \ ++ "+d" (old__.high)) \ + : "b" (new__.low), \ + "c" (new__.high), \ + "S" (&(_var)) \ +@@ -452,10 +452,10 @@ do { \ + asm qual (ALTERNATIVE("call this_cpu_cmpxchg16b_emu", \ + "cmpxchg16b " __percpu_arg([var]), X86_FEATURE_CX16) \ + CC_SET(z) \ +- : CC_OUT(z) (success), \ +- [var] "+m" (__my_cpu_var(_var)), \ +- "+a" (old__.low), \ +- "+d" (old__.high) \ ++ : ALT_OUTPUT_SP(CC_OUT(z) (success), \ ++ [var] "+m" (__my_cpu_var(_var)), \ ++ "+a" (old__.low), \ ++ "+d" (old__.high)) \ + : "b" (new__.low), \ + "c" (new__.high), \ + "S" (&(_var)) \ +-- +2.39.5 + diff --git a/queue-6.14/x86-microcode-update-the-intel-processor-flag-scan-c.patch b/queue-6.14/x86-microcode-update-the-intel-processor-flag-scan-c.patch new file mode 100644 index 0000000000..4435ecc04c --- /dev/null +++ b/queue-6.14/x86-microcode-update-the-intel-processor-flag-scan-c.patch @@ -0,0 +1,59 @@ +From 2488d3a1c852dab405e0aaab2372b99ccf634d21 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 19 Feb 2025 18:41:21 +0000 +Subject: x86/microcode: Update the Intel processor flag scan check + +From: Sohil Mehta + +[ Upstream commit 7e6b0a2e4152f4046af95eeb46f8b4f9b2a7398d ] + +The Family model check to read the processor flag MSR is misleading and +potentially incorrect. It doesn't consider Family while comparing the +model number. The original check did have a Family number but it got +lost/moved during refactoring. + +intel_collect_cpu_info() is called through multiple paths such as early +initialization, CPU hotplug as well as IFS image load. Some of these +flows would be error prone due to the ambiguous check. + +Correct the processor flag scan check to use a Family number and update +it to a VFM based one to make it more readable. + +Signed-off-by: Sohil Mehta +Signed-off-by: Ingo Molnar +Acked-by: Dave Hansen +Link: https://lore.kernel.org/r/20250219184133.816753-4-sohil.mehta@intel.com +Signed-off-by: Sasha Levin +--- + arch/x86/include/asm/intel-family.h | 1 + + arch/x86/kernel/cpu/microcode/intel.c | 2 +- + 2 files changed, 2 insertions(+), 1 deletion(-) + +diff --git a/arch/x86/include/asm/intel-family.h b/arch/x86/include/asm/intel-family.h +index ef5a06ddf0287..44fe88d6cf5c0 100644 +--- a/arch/x86/include/asm/intel-family.h ++++ b/arch/x86/include/asm/intel-family.h +@@ -46,6 +46,7 @@ + #define INTEL_ANY IFM(X86_FAMILY_ANY, X86_MODEL_ANY) + + #define INTEL_PENTIUM_PRO IFM(6, 0x01) ++#define INTEL_PENTIUM_III_DESCHUTES IFM(6, 0x05) + + #define INTEL_CORE_YONAH IFM(6, 0x0E) + +diff --git a/arch/x86/kernel/cpu/microcode/intel.c b/arch/x86/kernel/cpu/microcode/intel.c +index 9309468c8d2c1..2a397da43923b 100644 +--- a/arch/x86/kernel/cpu/microcode/intel.c ++++ b/arch/x86/kernel/cpu/microcode/intel.c +@@ -74,7 +74,7 @@ void intel_collect_cpu_info(struct cpu_signature *sig) + sig->pf = 0; + sig->rev = intel_get_microcode_revision(); + +- if (x86_model(sig->sig) >= 5 || x86_family(sig->sig) > 6) { ++ if (IFM(x86_family(sig->sig), x86_model(sig->sig)) >= INTEL_PENTIUM_III_DESCHUTES) { + unsigned int val[2]; + + /* get processor flags from MSR 0x17 */ +-- +2.39.5 + diff --git a/queue-6.14/x86-mm-check-return-value-from-memblock_phys_alloc_r.patch b/queue-6.14/x86-mm-check-return-value-from-memblock_phys_alloc_r.patch new file mode 100644 index 0000000000..5f4b11be0b --- /dev/null +++ b/queue-6.14/x86-mm-check-return-value-from-memblock_phys_alloc_r.patch @@ -0,0 +1,53 @@ +From d6bbb9e87c67c4c3ad1a10c95fdc38eeb79b770b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 15 Nov 2024 20:36:59 +0300 +Subject: x86/mm: Check return value from memblock_phys_alloc_range() + +From: Philip Redkin + +[ Upstream commit 631ca8909fd5c62b9fda9edda93924311a78a9c4 ] + +At least with CONFIG_PHYSICAL_START=0x100000, if there is < 4 MiB of +contiguous free memory available at this point, the kernel will crash +and burn because memblock_phys_alloc_range() returns 0 on failure, +which leads memblock_phys_free() to throw the first 4 MiB of physical +memory to the wolves. + +At a minimum it should fail gracefully with a meaningful diagnostic, +but in fact everything seems to work fine without the weird reserve +allocation. + +Signed-off-by: Philip Redkin +Signed-off-by: Ingo Molnar +Cc: Dave Hansen +Cc: Rik van Riel +Cc: "H. Peter Anvin" +Link: https://lore.kernel.org/r/94b3e98f-96a7-3560-1f76-349eb95ccf7f@rarity.fan +Signed-off-by: Sasha Levin +--- + arch/x86/mm/init.c | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c +index 62aa4d66a032d..bfa444a7dbb04 100644 +--- a/arch/x86/mm/init.c ++++ b/arch/x86/mm/init.c +@@ -645,8 +645,13 @@ static void __init memory_map_top_down(unsigned long map_start, + */ + addr = memblock_phys_alloc_range(PMD_SIZE, PMD_SIZE, map_start, + map_end); +- memblock_phys_free(addr, PMD_SIZE); +- real_end = addr + PMD_SIZE; ++ if (!addr) { ++ pr_warn("Failed to release memory for alloc_low_pages()"); ++ real_end = max(map_start, ALIGN_DOWN(map_end, PMD_SIZE)); ++ } else { ++ memblock_phys_free(addr, PMD_SIZE); ++ real_end = addr + PMD_SIZE; ++ } + + /* step_size need to be small so pgt_buf from BRK could cover it */ + step_size = PMD_SIZE; +-- +2.39.5 + diff --git a/queue-6.14/x86-mm-init-handle-the-special-case-of-device-privat.patch b/queue-6.14/x86-mm-init-handle-the-special-case-of-device-privat.patch new file mode 100644 index 0000000000..9689937646 --- /dev/null +++ b/queue-6.14/x86-mm-init-handle-the-special-case-of-device-privat.patch @@ -0,0 +1,112 @@ +From d47c6fdcfa4fe3b4b55c9eb6a938bda8be128ff1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 1 Apr 2025 11:07:52 +1100 +Subject: x86/mm/init: Handle the special case of device private pages in + add_pages(), to not increase max_pfn and trigger dma_addressing_limited() + bounce buffers +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Balbir Singh + +[ Upstream commit 7170130e4c72ce0caa0cb42a1627c635cc262821 ] + +As Bert Karwatzki reported, the following recent commit causes a +performance regression on AMD iGPU and dGPU systems: + + 7ffb791423c7 ("x86/kaslr: Reduce KASLR entropy on most x86 systems") + +It exposed a bug with nokaslr and zone device interaction. + +The root cause of the bug is that, the GPU driver registers a zone +device private memory region. When KASLR is disabled or the above commit +is applied, the direct_map_physmem_end is set to much higher than 10 TiB +typically to the 64TiB address. When zone device private memory is added +to the system via add_pages(), it bumps up the max_pfn to the same +value. This causes dma_addressing_limited() to return true, since the +device cannot address memory all the way up to max_pfn. + +This caused a regression for games played on the iGPU, as it resulted in +the DMA32 zone being used for GPU allocations. + +Fix this by not bumping up max_pfn on x86 systems, when pgmap is passed +into add_pages(). The presence of pgmap is used to determine if device +private memory is being added via add_pages(). + +More details: + +devm_request_mem_region() and request_free_mem_region() request for +device private memory. iomem_resource is passed as the base resource +with start and end parameters. iomem_resource's end depends on several +factors, including the platform and virtualization. On x86 for example +on bare metal, this value is set to boot_cpu_data.x86_phys_bits. +boot_cpu_data.x86_phys_bits can change depending on support for MKTME. +By default it is set to the same as log2(direct_map_physmem_end) which +is 46 to 52 bits depending on the number of levels in the page table. +The allocation routines used iomem_resource's end and +direct_map_physmem_end to figure out where to allocate the region. + +[ arch/powerpc is also impacted by this problem, but this patch does not fix + the issue for PowerPC. ] + +Testing: + + 1. Tested on a virtual machine with test_hmm for zone device inseration + + 2. A previous version of this patch was tested by Bert, please see: + https://lore.kernel.org/lkml/d87680bab997fdc9fb4e638983132af235d9a03a.camel@web.de/ + +[ mingo: Clarified the comments and the changelog. ] + +Reported-by: Bert Karwatzki +Tested-by: Bert Karwatzki +Fixes: 7ffb791423c7 ("x86/kaslr: Reduce KASLR entropy on most x86 systems") +Signed-off-by: Balbir Singh +Signed-off-by: Ingo Molnar +Cc: Brian Gerst +Cc: Juergen Gross +Cc: H. Peter Anvin +Cc: Linus Torvalds +Cc: Andrew Morton +Cc: Christoph Hellwig +Cc: Pierre-Eric Pelloux-Prayer +Cc: Alex Deucher +Cc: Christian König +Cc: David Airlie +Cc: Simona Vetter +Link: https://lore.kernel.org/r/20250401000752.249348-1-balbirs@nvidia.com +Signed-off-by: Sasha Levin +--- + arch/x86/mm/init_64.c | 15 ++++++++++++--- + 1 file changed, 12 insertions(+), 3 deletions(-) + +diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c +index 01ea7c6df3036..17c89dad4f7ff 100644 +--- a/arch/x86/mm/init_64.c ++++ b/arch/x86/mm/init_64.c +@@ -967,9 +967,18 @@ int add_pages(int nid, unsigned long start_pfn, unsigned long nr_pages, + ret = __add_pages(nid, start_pfn, nr_pages, params); + WARN_ON_ONCE(ret); + +- /* update max_pfn, max_low_pfn and high_memory */ +- update_end_of_memory_vars(start_pfn << PAGE_SHIFT, +- nr_pages << PAGE_SHIFT); ++ /* ++ * Special case: add_pages() is called by memremap_pages() for adding device ++ * private pages. Do not bump up max_pfn in the device private path, ++ * because max_pfn changes affect dma_addressing_limited(). ++ * ++ * dma_addressing_limited() returning true when max_pfn is the device's ++ * addressable memory can force device drivers to use bounce buffers ++ * and impact their performance negatively: ++ */ ++ if (!params->pgmap) ++ /* update max_pfn, max_low_pfn and high_memory */ ++ update_end_of_memory_vars(start_pfn << PAGE_SHIFT, nr_pages << PAGE_SHIFT); + + return ret; + } +-- +2.39.5 + diff --git a/queue-6.14/x86-mm-make-mmu_gather_rcu_table_free-unconditional.patch b/queue-6.14/x86-mm-make-mmu_gather_rcu_table_free-unconditional.patch new file mode 100644 index 0000000000..6e51fecedb --- /dev/null +++ b/queue-6.14/x86-mm-make-mmu_gather_rcu_table_free-unconditional.patch @@ -0,0 +1,163 @@ +From 8461e188cca93e70eb8f4eb1930ad736ada1461a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 13 Feb 2025 11:13:52 -0500 +Subject: x86/mm: Make MMU_GATHER_RCU_TABLE_FREE unconditional + +From: Rik van Riel + +[ Upstream commit a37259732a7dc33047fa1e4f9a338088f452e017 ] + +Currently x86 uses CONFIG_MMU_GATHER_TABLE_FREE when using +paravirt, and not when running on bare metal. + +There is no real good reason to do things differently for +each setup. Make them all the same. + +Currently get_user_pages_fast synchronizes against page table +freeing in two different ways: + + - on bare metal, by blocking IRQs, which block TLB flush IPIs + - on paravirt, with MMU_GATHER_RCU_TABLE_FREE + +This is done because some paravirt TLB flush implementations +handle the TLB flush in the hypervisor, and will do the flush +even when the target CPU has interrupts disabled. + +Always handle page table freeing with MMU_GATHER_RCU_TABLE_FREE. +Using RCU synchronization between page table freeing and get_user_pages_fast() +allows bare metal to also do TLB flushing while interrupts are disabled. + +Various places in the mm do still block IRQs or disable preemption +as an implicit way to block RCU frees. + +That makes it safe to use INVLPGB on AMD CPUs. + +Suggested-by: Peter Zijlstra +Signed-off-by: Rik van Riel +Signed-off-by: Ingo Molnar +Tested-by: Manali Shukla +Tested-by: Brendan Jackman +Tested-by: Michael Kelley +Link: https://lore.kernel.org/r/20250213161423.449435-2-riel@surriel.com +Signed-off-by: Sasha Levin +--- + arch/x86/Kconfig | 2 +- + arch/x86/kernel/paravirt.c | 17 +---------------- + arch/x86/mm/pgtable.c | 27 ++++----------------------- + 3 files changed, 6 insertions(+), 40 deletions(-) + +diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig +index f86e7072a5ba3..473364353bd96 100644 +--- a/arch/x86/Kconfig ++++ b/arch/x86/Kconfig +@@ -277,7 +277,7 @@ config X86 + select HAVE_PCI + select HAVE_PERF_REGS + select HAVE_PERF_USER_STACK_DUMP +- select MMU_GATHER_RCU_TABLE_FREE if PARAVIRT ++ select MMU_GATHER_RCU_TABLE_FREE + select MMU_GATHER_MERGE_VMAS + select HAVE_POSIX_CPU_TIMERS_TASK_WORK + select HAVE_REGS_AND_STACK_ACCESS_API +diff --git a/arch/x86/kernel/paravirt.c b/arch/x86/kernel/paravirt.c +index c5bb980b8a673..6669d251c4f75 100644 +--- a/arch/x86/kernel/paravirt.c ++++ b/arch/x86/kernel/paravirt.c +@@ -59,21 +59,6 @@ void __init native_pv_lock_init(void) + static_branch_enable(&virt_spin_lock_key); + } + +-#ifndef CONFIG_PT_RECLAIM +-static void native_tlb_remove_table(struct mmu_gather *tlb, void *table) +-{ +- struct ptdesc *ptdesc = (struct ptdesc *)table; +- +- pagetable_dtor(ptdesc); +- tlb_remove_page(tlb, ptdesc_page(ptdesc)); +-} +-#else +-static void native_tlb_remove_table(struct mmu_gather *tlb, void *table) +-{ +- tlb_remove_table(tlb, table); +-} +-#endif +- + struct static_key paravirt_steal_enabled; + struct static_key paravirt_steal_rq_enabled; + +@@ -197,7 +182,7 @@ struct paravirt_patch_template pv_ops = { + .mmu.flush_tlb_kernel = native_flush_tlb_global, + .mmu.flush_tlb_one_user = native_flush_tlb_one_user, + .mmu.flush_tlb_multi = native_flush_tlb_multi, +- .mmu.tlb_remove_table = native_tlb_remove_table, ++ .mmu.tlb_remove_table = tlb_remove_table, + + .mmu.exit_mmap = paravirt_nop, + .mmu.notify_page_enc_status_changed = paravirt_nop, +diff --git a/arch/x86/mm/pgtable.c b/arch/x86/mm/pgtable.c +index 9b0ee41b545c7..1ddbd799acdf5 100644 +--- a/arch/x86/mm/pgtable.c ++++ b/arch/x86/mm/pgtable.c +@@ -18,25 +18,6 @@ EXPORT_SYMBOL(physical_mask); + #define PGTABLE_HIGHMEM 0 + #endif + +-#ifndef CONFIG_PARAVIRT +-#ifndef CONFIG_PT_RECLAIM +-static inline +-void paravirt_tlb_remove_table(struct mmu_gather *tlb, void *table) +-{ +- struct ptdesc *ptdesc = (struct ptdesc *)table; +- +- pagetable_dtor(ptdesc); +- tlb_remove_page(tlb, ptdesc_page(ptdesc)); +-} +-#else +-static inline +-void paravirt_tlb_remove_table(struct mmu_gather *tlb, void *table) +-{ +- tlb_remove_table(tlb, table); +-} +-#endif /* !CONFIG_PT_RECLAIM */ +-#endif /* !CONFIG_PARAVIRT */ +- + gfp_t __userpte_alloc_gfp = GFP_PGTABLE_USER | PGTABLE_HIGHMEM; + + pgtable_t pte_alloc_one(struct mm_struct *mm) +@@ -64,7 +45,7 @@ early_param("userpte", setup_userpte); + void ___pte_free_tlb(struct mmu_gather *tlb, struct page *pte) + { + paravirt_release_pte(page_to_pfn(pte)); +- paravirt_tlb_remove_table(tlb, page_ptdesc(pte)); ++ tlb_remove_table(tlb, page_ptdesc(pte)); + } + + #if CONFIG_PGTABLE_LEVELS > 2 +@@ -78,21 +59,21 @@ void ___pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd) + #ifdef CONFIG_X86_PAE + tlb->need_flush_all = 1; + #endif +- paravirt_tlb_remove_table(tlb, virt_to_ptdesc(pmd)); ++ tlb_remove_table(tlb, virt_to_ptdesc(pmd)); + } + + #if CONFIG_PGTABLE_LEVELS > 3 + void ___pud_free_tlb(struct mmu_gather *tlb, pud_t *pud) + { + paravirt_release_pud(__pa(pud) >> PAGE_SHIFT); +- paravirt_tlb_remove_table(tlb, virt_to_ptdesc(pud)); ++ tlb_remove_table(tlb, virt_to_ptdesc(pud)); + } + + #if CONFIG_PGTABLE_LEVELS > 4 + void ___p4d_free_tlb(struct mmu_gather *tlb, p4d_t *p4d) + { + paravirt_release_p4d(__pa(p4d) >> PAGE_SHIFT); +- paravirt_tlb_remove_table(tlb, virt_to_ptdesc(p4d)); ++ tlb_remove_table(tlb, virt_to_ptdesc(p4d)); + } + #endif /* CONFIG_PGTABLE_LEVELS > 4 */ + #endif /* CONFIG_PGTABLE_LEVELS > 3 */ +-- +2.39.5 + diff --git a/queue-6.14/x86-nmi-add-an-emergency-handler-in-nmi_desc-use-it-.patch b/queue-6.14/x86-nmi-add-an-emergency-handler-in-nmi_desc-use-it-.patch new file mode 100644 index 0000000000..d3df8e1da4 --- /dev/null +++ b/queue-6.14/x86-nmi-add-an-emergency-handler-in-nmi_desc-use-it-.patch @@ -0,0 +1,173 @@ +From dc16939bcbe3e8d9eb7ff803d48390e3aee56af0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Feb 2025 14:18:44 -0500 +Subject: x86/nmi: Add an emergency handler in nmi_desc & use it in + nmi_shootdown_cpus() + +From: Waiman Long + +[ Upstream commit fe37c699ae3eed6e02ee55fbf5cb9ceb7fcfd76c ] + +Depending on the type of panics, it was found that the +__register_nmi_handler() function can be called in NMI context from +nmi_shootdown_cpus() leading to a lockdep splat: + + WARNING: inconsistent lock state + inconsistent {INITIAL USE} -> {IN-NMI} usage. + + lock(&nmi_desc[0].lock); + + lock(&nmi_desc[0].lock); + + Call Trace: + _raw_spin_lock_irqsave + __register_nmi_handler + nmi_shootdown_cpus + kdump_nmi_shootdown_cpus + native_machine_crash_shutdown + __crash_kexec + +In this particular case, the following panic message was printed before: + + Kernel panic - not syncing: Fatal hardware error! + +This message seemed to be given out from __ghes_panic() running in +NMI context. + +The __register_nmi_handler() function which takes the nmi_desc lock +with irq disabled shouldn't be called from NMI context as this can +lead to deadlock. + +The nmi_shootdown_cpus() function can only be invoked once. After the +first invocation, all other CPUs should be stuck in the newly added +crash_nmi_callback() and cannot respond to a second NMI. + +Fix it by adding a new emergency NMI handler to the nmi_desc +structure and provide a new set_emergency_nmi_handler() helper to set +crash_nmi_callback() in any context. The new emergency handler will +preempt other handlers in the linked list. That will eliminate the need +to take any lock and serve the panic in NMI use case. + +Signed-off-by: Waiman Long +Signed-off-by: Ingo Molnar +Acked-by: Rik van Riel +Cc: Thomas Gleixner +Link: https://lore.kernel.org/r/20250206191844.131700-1-longman@redhat.com +Signed-off-by: Sasha Levin +--- + arch/x86/include/asm/nmi.h | 2 ++ + arch/x86/kernel/nmi.c | 42 ++++++++++++++++++++++++++++++++++++++ + arch/x86/kernel/reboot.c | 10 +++------ + 3 files changed, 47 insertions(+), 7 deletions(-) + +diff --git a/arch/x86/include/asm/nmi.h b/arch/x86/include/asm/nmi.h +index 41a0ebb699ec6..f677382093f36 100644 +--- a/arch/x86/include/asm/nmi.h ++++ b/arch/x86/include/asm/nmi.h +@@ -56,6 +56,8 @@ int __register_nmi_handler(unsigned int, struct nmiaction *); + + void unregister_nmi_handler(unsigned int, const char *); + ++void set_emergency_nmi_handler(unsigned int type, nmi_handler_t handler); ++ + void stop_nmi(void); + void restart_nmi(void); + void local_touch_nmi(void); +diff --git a/arch/x86/kernel/nmi.c b/arch/x86/kernel/nmi.c +index ed163c8c8604e..9a95d00f14233 100644 +--- a/arch/x86/kernel/nmi.c ++++ b/arch/x86/kernel/nmi.c +@@ -40,8 +40,12 @@ + #define CREATE_TRACE_POINTS + #include + ++/* ++ * An emergency handler can be set in any context including NMI ++ */ + struct nmi_desc { + raw_spinlock_t lock; ++ nmi_handler_t emerg_handler; + struct list_head head; + }; + +@@ -132,9 +136,22 @@ static void nmi_check_duration(struct nmiaction *action, u64 duration) + static int nmi_handle(unsigned int type, struct pt_regs *regs) + { + struct nmi_desc *desc = nmi_to_desc(type); ++ nmi_handler_t ehandler; + struct nmiaction *a; + int handled=0; + ++ /* ++ * Call the emergency handler, if set ++ * ++ * In the case of crash_nmi_callback() emergency handler, it will ++ * return in the case of the crashing CPU to enable it to complete ++ * other necessary crashing actions ASAP. Other handlers in the ++ * linked list won't need to be run. ++ */ ++ ehandler = desc->emerg_handler; ++ if (ehandler) ++ return ehandler(type, regs); ++ + rcu_read_lock(); + + /* +@@ -224,6 +241,31 @@ void unregister_nmi_handler(unsigned int type, const char *name) + } + EXPORT_SYMBOL_GPL(unregister_nmi_handler); + ++/** ++ * set_emergency_nmi_handler - Set emergency handler ++ * @type: NMI type ++ * @handler: the emergency handler to be stored ++ * ++ * Set an emergency NMI handler which, if set, will preempt all the other ++ * handlers in the linked list. If a NULL handler is passed in, it will clear ++ * it. It is expected that concurrent calls to this function will not happen ++ * or the system is screwed beyond repair. ++ */ ++void set_emergency_nmi_handler(unsigned int type, nmi_handler_t handler) ++{ ++ struct nmi_desc *desc = nmi_to_desc(type); ++ ++ if (WARN_ON_ONCE(desc->emerg_handler == handler)) ++ return; ++ desc->emerg_handler = handler; ++ ++ /* ++ * Ensure the emergency handler is visible to other CPUs before ++ * function return ++ */ ++ smp_wmb(); ++} ++ + static void + pci_serr_error(unsigned char reason, struct pt_regs *regs) + { +diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c +index dc1dd3f3e67fc..9aaac1f9f45b5 100644 +--- a/arch/x86/kernel/reboot.c ++++ b/arch/x86/kernel/reboot.c +@@ -926,15 +926,11 @@ void nmi_shootdown_cpus(nmi_shootdown_cb callback) + shootdown_callback = callback; + + atomic_set(&waiting_for_crash_ipi, num_online_cpus() - 1); +- /* Would it be better to replace the trap vector here? */ +- if (register_nmi_handler(NMI_LOCAL, crash_nmi_callback, +- NMI_FLAG_FIRST, "crash")) +- return; /* Return what? */ ++ + /* +- * Ensure the new callback function is set before sending +- * out the NMI ++ * Set emergency handler to preempt other handlers. + */ +- wmb(); ++ set_emergency_nmi_handler(NMI_LOCAL, crash_nmi_callback); + + apic_send_IPI_allbutself(NMI_VECTOR); + +-- +2.39.5 + diff --git a/queue-6.14/x86-relocs-handle-r_x86_64_rex_gotpcrelx-relocations.patch b/queue-6.14/x86-relocs-handle-r_x86_64_rex_gotpcrelx-relocations.patch new file mode 100644 index 0000000000..6c95c5445a --- /dev/null +++ b/queue-6.14/x86-relocs-handle-r_x86_64_rex_gotpcrelx-relocations.patch @@ -0,0 +1,58 @@ +From d8e603969259e50aa632d1a3fde8883f41e26150 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 23 Jan 2025 14:07:37 -0500 +Subject: x86/relocs: Handle R_X86_64_REX_GOTPCRELX relocations + +From: Brian Gerst + +[ Upstream commit cb7927fda002ca49ae62e2782c1692acc7b80c67 ] + +Clang may produce R_X86_64_REX_GOTPCRELX relocations when redefining the +stack protector location. Treat them as another type of PC-relative +relocation. + +Signed-off-by: Brian Gerst +Signed-off-by: Ingo Molnar +Reviewed-by: Ard Biesheuvel +Cc: Linus Torvalds +Link: https://lore.kernel.org/r/20250123190747.745588-6-brgerst@gmail.com +Signed-off-by: Sasha Levin +--- + arch/x86/tools/relocs.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/arch/x86/tools/relocs.c b/arch/x86/tools/relocs.c +index e937be979ec86..92a1e503305ef 100644 +--- a/arch/x86/tools/relocs.c ++++ b/arch/x86/tools/relocs.c +@@ -32,6 +32,11 @@ static struct relocs relocs32; + static struct relocs relocs32neg; + static struct relocs relocs64; + # define FMT PRIu64 ++ ++#ifndef R_X86_64_REX_GOTPCRELX ++# define R_X86_64_REX_GOTPCRELX 42 ++#endif ++ + #else + # define FMT PRIu32 + #endif +@@ -227,6 +232,7 @@ static const char *rel_type(unsigned type) + REL_TYPE(R_X86_64_PC16), + REL_TYPE(R_X86_64_8), + REL_TYPE(R_X86_64_PC8), ++ REL_TYPE(R_X86_64_REX_GOTPCRELX), + #else + REL_TYPE(R_386_NONE), + REL_TYPE(R_386_32), +@@ -861,6 +867,7 @@ static int do_reloc64(struct section *sec, Elf_Rel *rel, ElfW(Sym) *sym, + + case R_X86_64_PC32: + case R_X86_64_PLT32: ++ case R_X86_64_REX_GOTPCRELX: + /* + * PC relative relocations don't need to be adjusted unless + * referencing a percpu symbol. +-- +2.39.5 + diff --git a/queue-6.14/x86-smpboot-fix-init-delay-assignment-for-extended-i.patch b/queue-6.14/x86-smpboot-fix-init-delay-assignment-for-extended-i.patch new file mode 100644 index 0000000000..7abbd0cfb0 --- /dev/null +++ b/queue-6.14/x86-smpboot-fix-init-delay-assignment-for-extended-i.patch @@ -0,0 +1,50 @@ +From c41a8b2954d722d3f52e36d9930f5ebbe99ceaa1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 19 Feb 2025 18:41:28 +0000 +Subject: x86/smpboot: Fix INIT delay assignment for extended Intel Families + +From: Sohil Mehta + +[ Upstream commit 7a2ad752746bfb13e89a83984ecc52a48bae4969 ] + +Some old crusty CPUs need an extra delay that slows down booting. See +the comment above 'init_udelay' for details. Newer CPUs don't need the +delay. + +Right now, for Intel, Family 6 and only Family 6 skips the delay. That +leaves out both the Family 15 (Pentium 4s) and brand new Family 18/19 +models. + +The omission of Family 15 (Pentium 4s) seems like an oversight and 18/19 +do not need the delay. + +Skip the delay on all Intel processors Family 6 and beyond. + +Signed-off-by: Sohil Mehta +Signed-off-by: Ingo Molnar +Link: https://lore.kernel.org/r/20250219184133.816753-11-sohil.mehta@intel.com +Signed-off-by: Sasha Levin +--- + arch/x86/kernel/smpboot.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c +index c10850ae6f094..3d5069ee297bf 100644 +--- a/arch/x86/kernel/smpboot.c ++++ b/arch/x86/kernel/smpboot.c +@@ -676,9 +676,9 @@ static void __init smp_quirk_init_udelay(void) + return; + + /* if modern processor, use no delay */ +- if (((boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) && (boot_cpu_data.x86 == 6)) || +- ((boot_cpu_data.x86_vendor == X86_VENDOR_HYGON) && (boot_cpu_data.x86 >= 0x18)) || +- ((boot_cpu_data.x86_vendor == X86_VENDOR_AMD) && (boot_cpu_data.x86 >= 0xF))) { ++ if ((boot_cpu_data.x86_vendor == X86_VENDOR_INTEL && boot_cpu_data.x86_vfm >= INTEL_PENTIUM_PRO) || ++ (boot_cpu_data.x86_vendor == X86_VENDOR_HYGON && boot_cpu_data.x86 >= 0x18) || ++ (boot_cpu_data.x86_vendor == X86_VENDOR_AMD && boot_cpu_data.x86 >= 0xF)) { + init_udelay = 0; + return; + } +-- +2.39.5 + diff --git a/queue-6.14/x86-stackprotector-64-only-export-__ref_stack_chk_gu.patch b/queue-6.14/x86-stackprotector-64-only-export-__ref_stack_chk_gu.patch new file mode 100644 index 0000000000..820565945f --- /dev/null +++ b/queue-6.14/x86-stackprotector-64-only-export-__ref_stack_chk_gu.patch @@ -0,0 +1,45 @@ +From fb5cdc710092ea8865c74899e5cc017068a9e39e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 12 Mar 2025 12:48:49 +0100 +Subject: x86/stackprotector/64: Only export __ref_stack_chk_guard on + CONFIG_SMP +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Ingo Molnar + +[ Upstream commit 91d5451d97ce35cbd510277fa3b7abf9caa4e34d ] + +The __ref_stack_chk_guard symbol doesn't exist on UP: + + :4:15: error: ‘__ref_stack_chk_guard’ undeclared here (not in a function) + +Fix the #ifdef around the entry.S export. + +Signed-off-by: Ingo Molnar +Cc: Brian Gerst +Cc: Ard Biesheuvel +Cc: Uros Bizjak +Link: https://lore.kernel.org/r/20250123190747.745588-8-brgerst@gmail.com +Signed-off-by: Sasha Levin +--- + arch/x86/entry/entry.S | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/x86/entry/entry.S b/arch/x86/entry/entry.S +index 58e3124ee2b42..5b96249734ada 100644 +--- a/arch/x86/entry/entry.S ++++ b/arch/x86/entry/entry.S +@@ -63,7 +63,7 @@ THUNK warn_thunk_thunk, __warn_thunk + * entirely in the C code, and use an alias emitted by the linker script + * instead. + */ +-#ifdef CONFIG_STACKPROTECTOR ++#if defined(CONFIG_STACKPROTECTOR) && defined(CONFIG_SMP) + EXPORT_SYMBOL(__ref_stack_chk_guard); + #endif + #endif +-- +2.39.5 + diff --git a/queue-6.14/x86-traps-cleanup-and-robustify-decode_bug.patch b/queue-6.14/x86-traps-cleanup-and-robustify-decode_bug.patch new file mode 100644 index 0000000000..e9fe481d63 --- /dev/null +++ b/queue-6.14/x86-traps-cleanup-and-robustify-decode_bug.patch @@ -0,0 +1,192 @@ +From b141cfe5571a915d4a27ac40e2687a7a2c5e93fb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 7 Feb 2025 13:15:36 +0100 +Subject: x86/traps: Cleanup and robustify decode_bug() + +From: Peter Zijlstra + +[ Upstream commit c20ad96c9a8f0aeaf4e4057730a22de2657ad0c2 ] + +Notably, don't attempt to decode an immediate when MOD == 3. + +Additionally have it return the instruction length, such that WARN +like bugs can more reliably skip to the correct instruction. + +Signed-off-by: Peter Zijlstra (Intel) +Reviewed-by: Sami Tolvanen +Link: https://lore.kernel.org/r/20250207122546.721120726@infradead.org +Signed-off-by: Sasha Levin +--- + arch/x86/include/asm/bug.h | 5 ++- + arch/x86/include/asm/ibt.h | 4 +- + arch/x86/kernel/traps.c | 82 ++++++++++++++++++++++++++++---------- + 3 files changed, 65 insertions(+), 26 deletions(-) + +diff --git a/arch/x86/include/asm/bug.h b/arch/x86/include/asm/bug.h +index e85ac0c7c039e..1a5e4b3726940 100644 +--- a/arch/x86/include/asm/bug.h ++++ b/arch/x86/include/asm/bug.h +@@ -22,8 +22,9 @@ + #define SECOND_BYTE_OPCODE_UD2 0x0b + + #define BUG_NONE 0xffff +-#define BUG_UD1 0xfffe +-#define BUG_UD2 0xfffd ++#define BUG_UD2 0xfffe ++#define BUG_UD1 0xfffd ++#define BUG_UD1_UBSAN 0xfffc + + #ifdef CONFIG_GENERIC_BUG + +diff --git a/arch/x86/include/asm/ibt.h b/arch/x86/include/asm/ibt.h +index e7f4caa42839a..b04bcbb1a14ef 100644 +--- a/arch/x86/include/asm/ibt.h ++++ b/arch/x86/include/asm/ibt.h +@@ -41,7 +41,7 @@ + _ASM_PTR fname "\n\t" \ + ".popsection\n\t" + +-static inline __attribute_const__ u32 gen_endbr(void) ++static __always_inline __attribute_const__ u32 gen_endbr(void) + { + u32 endbr; + +@@ -56,7 +56,7 @@ static inline __attribute_const__ u32 gen_endbr(void) + return endbr; + } + +-static inline __attribute_const__ u32 gen_endbr_poison(void) ++static __always_inline __attribute_const__ u32 gen_endbr_poison(void) + { + /* + * 4 byte NOP that isn't NOP4 (in fact it is OSP NOP3), such that it +diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c +index 5e3e036e6e537..b18fc7539b8d7 100644 +--- a/arch/x86/kernel/traps.c ++++ b/arch/x86/kernel/traps.c +@@ -94,10 +94,17 @@ __always_inline int is_valid_bugaddr(unsigned long addr) + + /* + * Check for UD1 or UD2, accounting for Address Size Override Prefixes. +- * If it's a UD1, get the ModRM byte to pass along to UBSan. ++ * If it's a UD1, further decode to determine its use: ++ * ++ * UBSan{0}: 67 0f b9 00 ud1 (%eax),%eax ++ * UBSan{10}: 67 0f b9 40 10 ud1 0x10(%eax),%eax ++ * static_call: 0f b9 cc ud1 %esp,%ecx ++ * ++ * Notably UBSAN uses EAX, static_call uses ECX. + */ +-__always_inline int decode_bug(unsigned long addr, u32 *imm) ++__always_inline int decode_bug(unsigned long addr, s32 *imm, int *len) + { ++ unsigned long start = addr; + u8 v; + + if (addr < TASK_SIZE_MAX) +@@ -110,24 +117,42 @@ __always_inline int decode_bug(unsigned long addr, u32 *imm) + return BUG_NONE; + + v = *(u8 *)(addr++); +- if (v == SECOND_BYTE_OPCODE_UD2) ++ if (v == SECOND_BYTE_OPCODE_UD2) { ++ *len = addr - start; + return BUG_UD2; ++ } + +- if (!IS_ENABLED(CONFIG_UBSAN_TRAP) || v != SECOND_BYTE_OPCODE_UD1) ++ if (v != SECOND_BYTE_OPCODE_UD1) + return BUG_NONE; + +- /* Retrieve the immediate (type value) for the UBSAN UD1 */ +- v = *(u8 *)(addr++); +- if (X86_MODRM_RM(v) == 4) +- addr++; +- + *imm = 0; +- if (X86_MODRM_MOD(v) == 1) +- *imm = *(u8 *)addr; +- else if (X86_MODRM_MOD(v) == 2) +- *imm = *(u32 *)addr; +- else +- WARN_ONCE(1, "Unexpected MODRM_MOD: %u\n", X86_MODRM_MOD(v)); ++ v = *(u8 *)(addr++); /* ModRM */ ++ ++ if (X86_MODRM_MOD(v) != 3 && X86_MODRM_RM(v) == 4) ++ addr++; /* SIB */ ++ ++ /* Decode immediate, if present */ ++ switch (X86_MODRM_MOD(v)) { ++ case 0: if (X86_MODRM_RM(v) == 5) ++ addr += 4; /* RIP + disp32 */ ++ break; ++ ++ case 1: *imm = *(s8 *)addr; ++ addr += 1; ++ break; ++ ++ case 2: *imm = *(s32 *)addr; ++ addr += 4; ++ break; ++ ++ case 3: break; ++ } ++ ++ /* record instruction length */ ++ *len = addr - start; ++ ++ if (X86_MODRM_REG(v) == 0) /* EAX */ ++ return BUG_UD1_UBSAN; + + return BUG_UD1; + } +@@ -258,10 +283,10 @@ static inline void handle_invalid_op(struct pt_regs *regs) + static noinstr bool handle_bug(struct pt_regs *regs) + { + bool handled = false; +- int ud_type; +- u32 imm; ++ int ud_type, ud_len; ++ s32 ud_imm; + +- ud_type = decode_bug(regs->ip, &imm); ++ ud_type = decode_bug(regs->ip, &ud_imm, &ud_len); + if (ud_type == BUG_NONE) + return handled; + +@@ -281,15 +306,28 @@ static noinstr bool handle_bug(struct pt_regs *regs) + */ + if (regs->flags & X86_EFLAGS_IF) + raw_local_irq_enable(); +- if (ud_type == BUG_UD2) { ++ ++ switch (ud_type) { ++ case BUG_UD2: + if (report_bug(regs->ip, regs) == BUG_TRAP_TYPE_WARN || + handle_cfi_failure(regs) == BUG_TRAP_TYPE_WARN) { +- regs->ip += LEN_UD2; ++ regs->ip += ud_len; + handled = true; + } +- } else if (IS_ENABLED(CONFIG_UBSAN_TRAP)) { +- pr_crit("%s at %pS\n", report_ubsan_failure(regs, imm), (void *)regs->ip); ++ break; ++ ++ case BUG_UD1_UBSAN: ++ if (IS_ENABLED(CONFIG_UBSAN_TRAP)) { ++ pr_crit("%s at %pS\n", ++ report_ubsan_failure(regs, ud_imm), ++ (void *)regs->ip); ++ } ++ break; ++ ++ default: ++ break; + } ++ + if (regs->flags & X86_EFLAGS_IF) + raw_local_irq_disable(); + instrumentation_end(); +-- +2.39.5 + diff --git a/queue-6.14/xen-add-support-for-xenserver-6.1-platform-device.patch b/queue-6.14/xen-add-support-for-xenserver-6.1-platform-device.patch new file mode 100644 index 0000000000..beefe9d675 --- /dev/null +++ b/queue-6.14/xen-add-support-for-xenserver-6.1-platform-device.patch @@ -0,0 +1,65 @@ +From 86e188ad56b9086716c7119310c7c5bcdafe468e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 27 Feb 2025 14:50:15 +0000 +Subject: xen: Add support for XenServer 6.1 platform device + +From: Frediano Ziglio + +[ Upstream commit 2356f15caefc0cc63d9cc5122641754f76ef9b25 ] + +On XenServer on Windows machine a platform device with ID 2 instead of +1 is used. + +This device is mainly identical to device 1 but due to some Windows +update behaviour it was decided to use a device with a different ID. + +This causes compatibility issues with Linux which expects, if Xen +is detected, to find a Xen platform device (5853:0001) otherwise code +will crash due to some missing initialization (specifically grant +tables). Specifically from dmesg + + RIP: 0010:gnttab_expand+0x29/0x210 + Code: 90 0f 1f 44 00 00 55 31 d2 48 89 e5 41 57 41 56 41 55 41 89 fd + 41 54 53 48 83 ec 10 48 8b 05 7e 9a 49 02 44 8b 35 a7 9a 49 02 + <8b> 48 04 8d 44 39 ff f7 f1 45 8d 24 06 89 c3 e8 43 fe ff ff + 44 39 + RSP: 0000:ffffba34c01fbc88 EFLAGS: 00010086 + ... + +The device 2 is presented by Xapi adding device specification to +Qemu command line. + +Signed-off-by: Frediano Ziglio +Acked-by: Juergen Gross +Message-ID: <20250227145016.25350-1-frediano.ziglio@cloud.com> +Signed-off-by: Juergen Gross +Signed-off-by: Sasha Levin +--- + drivers/xen/platform-pci.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/drivers/xen/platform-pci.c b/drivers/xen/platform-pci.c +index 544d3f9010b92..1db82da56db62 100644 +--- a/drivers/xen/platform-pci.c ++++ b/drivers/xen/platform-pci.c +@@ -26,6 +26,8 @@ + + #define DRV_NAME "xen-platform-pci" + ++#define PCI_DEVICE_ID_XEN_PLATFORM_XS61 0x0002 ++ + static unsigned long platform_mmio; + static unsigned long platform_mmio_alloc; + static unsigned long platform_mmiolen; +@@ -174,6 +176,8 @@ static int platform_pci_probe(struct pci_dev *pdev, + static const struct pci_device_id platform_pci_tbl[] = { + {PCI_VENDOR_ID_XEN, PCI_DEVICE_ID_XEN_PLATFORM, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, ++ {PCI_VENDOR_ID_XEN, PCI_DEVICE_ID_XEN_PLATFORM_XS61, ++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0,} + }; + +-- +2.39.5 + diff --git a/queue-6.14/xen-pci-do-not-register-devices-with-segments-0x1000.patch b/queue-6.14/xen-pci-do-not-register-devices-with-segments-0x1000.patch new file mode 100644 index 0000000000..a9f2c85194 --- /dev/null +++ b/queue-6.14/xen-pci-do-not-register-devices-with-segments-0x1000.patch @@ -0,0 +1,97 @@ +From abcb17d547cb47a00cbb94366e77746e0fd0f0cd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 19 Feb 2025 10:20:55 +0100 +Subject: xen/pci: Do not register devices with segments >= 0x10000 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Roger Pau Monne + +[ Upstream commit 5ccf1b8ae76ddf348e02a0d1564ff9baf8b6c415 ] + +The current hypercall interface for doing PCI device operations always uses +a segment field that has a 16 bit width. However on Linux there are buses +like VMD that hook up devices into the PCI hierarchy at segment >= 0x10000, +after the maximum possible segment enumerated in ACPI. + +Attempting to register or manage those devices with Xen would result in +errors at best, or overlaps with existing devices living on the truncated +equivalent segment values. Note also that the VMD segment numbers are +arbitrarily assigned by the OS, and hence there would need to be some +negotiation between Xen and the OS to agree on how to enumerate VMD +segments and devices behind them. + +Skip notifying Xen about those devices. Given how VMD bridges can +multiplex interrupts on behalf of devices behind them there's no need for +Xen to be aware of such devices for them to be usable by Linux. + +Signed-off-by: Roger Pau Monné +Acked-by: Juergen Gross +Message-ID: <20250219092059.90850-2-roger.pau@citrix.com> +Signed-off-by: Juergen Gross +Signed-off-by: Sasha Levin +--- + drivers/xen/pci.c | 32 ++++++++++++++++++++++++++++++++ + 1 file changed, 32 insertions(+) + +diff --git a/drivers/xen/pci.c b/drivers/xen/pci.c +index 416f231809cb6..bfe07adb3e3a6 100644 +--- a/drivers/xen/pci.c ++++ b/drivers/xen/pci.c +@@ -43,6 +43,18 @@ static int xen_add_device(struct device *dev) + pci_mcfg_reserved = true; + } + #endif ++ ++ if (pci_domain_nr(pci_dev->bus) >> 16) { ++ /* ++ * The hypercall interface is limited to 16bit PCI segment ++ * values, do not attempt to register devices with Xen in ++ * segments greater or equal than 0x10000. ++ */ ++ dev_info(dev, ++ "not registering with Xen: invalid PCI segment\n"); ++ return 0; ++ } ++ + if (pci_seg_supported) { + DEFINE_RAW_FLEX(struct physdev_pci_device_add, add, optarr, 1); + +@@ -149,6 +161,16 @@ static int xen_remove_device(struct device *dev) + int r; + struct pci_dev *pci_dev = to_pci_dev(dev); + ++ if (pci_domain_nr(pci_dev->bus) >> 16) { ++ /* ++ * The hypercall interface is limited to 16bit PCI segment ++ * values. ++ */ ++ dev_info(dev, ++ "not unregistering with Xen: invalid PCI segment\n"); ++ return 0; ++ } ++ + if (pci_seg_supported) { + struct physdev_pci_device device = { + .seg = pci_domain_nr(pci_dev->bus), +@@ -182,6 +204,16 @@ int xen_reset_device(const struct pci_dev *dev) + .flags = PCI_DEVICE_RESET_FLR, + }; + ++ if (pci_domain_nr(dev->bus) >> 16) { ++ /* ++ * The hypercall interface is limited to 16bit PCI segment ++ * values. ++ */ ++ dev_info(&dev->dev, ++ "unable to notify Xen of device reset: invalid PCI segment\n"); ++ return 0; ++ } ++ + return HYPERVISOR_physdev_op(PHYSDEVOP_pci_device_reset, &device); + } + EXPORT_SYMBOL_GPL(xen_reset_device); +-- +2.39.5 + diff --git a/queue-6.14/xenbus-allow-pvh-dom0-a-non-local-xenstore.patch b/queue-6.14/xenbus-allow-pvh-dom0-a-non-local-xenstore.patch new file mode 100644 index 0000000000..f4c9933aee --- /dev/null +++ b/queue-6.14/xenbus-allow-pvh-dom0-a-non-local-xenstore.patch @@ -0,0 +1,69 @@ +From 9c6d54ccd05c0b1a7509a95d412e75a13ae90e20 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 6 May 2025 16:44:56 -0400 +Subject: xenbus: Allow PVH dom0 a non-local xenstore + +From: Jason Andryuk + +[ Upstream commit 90989869baae47ee2aa3bcb6f6eb9fbbe4287958 ] + +Make xenbus_init() allow a non-local xenstore for a PVH dom0 - it is +currently forced to XS_LOCAL. With Hyperlaunch booting dom0 and a +xenstore stubdom, dom0 can be handled as a regular XS_HVM following the +late init path. + +Ideally we'd drop the use of xen_initial_domain() and just check for the +event channel instead. However, ARM has a xen,enhanced no-xenstore +mode, where the event channel and PFN would both be 0. Retain the +xen_initial_domain() check, and use that for an additional check when +the event channel is 0. + +Check the full 64bit HVM_PARAM_STORE_EVTCHN value to catch the off +chance that high bits are set for the 32bit event channel. + +Signed-off-by: Jason Andryuk +Change-Id: I5506da42e4c6b8e85079fefb2f193c8de17c7437 +Reviewed-by: Stefano Stabellini +Signed-off-by: Juergen Gross +Message-ID: <20250506204456.5220-1-jason.andryuk@amd.com> +Signed-off-by: Sasha Levin +--- + drivers/xen/xenbus/xenbus_probe.c | 14 ++++++++------ + 1 file changed, 8 insertions(+), 6 deletions(-) + +diff --git a/drivers/xen/xenbus/xenbus_probe.c b/drivers/xen/xenbus/xenbus_probe.c +index 6d32ffb011365..86fe6e7790566 100644 +--- a/drivers/xen/xenbus/xenbus_probe.c ++++ b/drivers/xen/xenbus/xenbus_probe.c +@@ -966,9 +966,15 @@ static int __init xenbus_init(void) + if (xen_pv_domain()) + xen_store_domain_type = XS_PV; + if (xen_hvm_domain()) ++ { + xen_store_domain_type = XS_HVM; +- if (xen_hvm_domain() && xen_initial_domain()) +- xen_store_domain_type = XS_LOCAL; ++ err = hvm_get_parameter(HVM_PARAM_STORE_EVTCHN, &v); ++ if (err) ++ goto out_error; ++ xen_store_evtchn = (int)v; ++ if (!v && xen_initial_domain()) ++ xen_store_domain_type = XS_LOCAL; ++ } + if (xen_pv_domain() && !xen_start_info->store_evtchn) + xen_store_domain_type = XS_LOCAL; + if (xen_pv_domain() && xen_start_info->store_evtchn) +@@ -987,10 +993,6 @@ static int __init xenbus_init(void) + xen_store_interface = gfn_to_virt(xen_store_gfn); + break; + case XS_HVM: +- err = hvm_get_parameter(HVM_PARAM_STORE_EVTCHN, &v); +- if (err) +- goto out_error; +- xen_store_evtchn = (int)v; + err = hvm_get_parameter(HVM_PARAM_STORE_PFN, &v); + if (err) + goto out_error; +-- +2.39.5 + diff --git a/queue-6.14/xfrm-prevent-high-seq-input-in-non-esn-mode.patch b/queue-6.14/xfrm-prevent-high-seq-input-in-non-esn-mode.patch new file mode 100644 index 0000000000..54f6e97dad --- /dev/null +++ b/queue-6.14/xfrm-prevent-high-seq-input-in-non-esn-mode.patch @@ -0,0 +1,53 @@ +From 413c86f30f373395052d2694e75386c20444b087 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Feb 2025 20:27:49 +0200 +Subject: xfrm: prevent high SEQ input in non-ESN mode + +From: Leon Romanovsky + +[ Upstream commit e3aa43a50a6455831e3c32dabc7ece38d9cd9d05 ] + +In non-ESN mode, the SEQ numbers are limited to 32 bits and seq_hi/oseq_hi +are not used. So make sure that user gets proper error message, in case +such assignment occurred. + +Signed-off-by: Leon Romanovsky +Signed-off-by: Steffen Klassert +Signed-off-by: Sasha Levin +--- + net/xfrm/xfrm_user.c | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c +index 82a768500999b..b5266e0848e82 100644 +--- a/net/xfrm/xfrm_user.c ++++ b/net/xfrm/xfrm_user.c +@@ -178,6 +178,12 @@ static inline int verify_replay(struct xfrm_usersa_info *p, + "Replay seq and seq_hi should be 0 for output SA"); + return -EINVAL; + } ++ if (rs->oseq_hi && !(p->flags & XFRM_STATE_ESN)) { ++ NL_SET_ERR_MSG( ++ extack, ++ "Replay oseq_hi should be 0 in non-ESN mode for output SA"); ++ return -EINVAL; ++ } + if (rs->bmp_len) { + NL_SET_ERR_MSG(extack, "Replay bmp_len should 0 for output SA"); + return -EINVAL; +@@ -190,6 +196,12 @@ static inline int verify_replay(struct xfrm_usersa_info *p, + "Replay oseq and oseq_hi should be 0 for input SA"); + return -EINVAL; + } ++ if (rs->seq_hi && !(p->flags & XFRM_STATE_ESN)) { ++ NL_SET_ERR_MSG( ++ extack, ++ "Replay seq_hi should be 0 in non-ESN mode for input SA"); ++ return -EINVAL; ++ } + } + + return 0; +-- +2.39.5 +