From 28f060c4b0667a7fbed9818ef19b6974d53ad708 Mon Sep 17 00:00:00 2001 From: Kenny Cheng Date: Mon, 23 Feb 2026 07:47:15 +0800 Subject: of: fix incorrect device creation for reserved memory nodes The current global search for nodes in reserved_mem_matches can find nodes outside "/reserved-memory". These nodes might not have actual memory reserved (via memblock), leading to drivers (e.g., ramoops) accessing unreserved memory and causing memory corruption. Restrict the scan to the "/reserved-memory" node to ensure created devices are correctly backed by reserved memory. This enforces specification compliance and avoids dangerous probing. Signed-off-by: Kenny Cheng Link: https://patch.msgid.link/20260222234715.1748302-1-chao.shun.cheng.tw@gmail.com Signed-off-by: Rob Herring (Arm) --- drivers/of/platform.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/of/platform.c b/drivers/of/platform.c index ba591fbceb56..2a7111e8354d 100644 --- a/drivers/of/platform.c +++ b/drivers/of/platform.c @@ -500,7 +500,7 @@ static const struct of_device_id reserved_mem_matches[] = { static int __init of_platform_default_populate_init(void) { - struct device_node *node; + struct device_node *node, *reserved; device_links_supplier_sync_state_pause(); @@ -563,8 +563,14 @@ static int __init of_platform_default_populate_init(void) * platform_devices for every node in /reserved-memory with a * "compatible", */ - for_each_matching_node(node, reserved_mem_matches) - of_platform_device_create(node, NULL, NULL); + reserved = of_find_node_by_path("/reserved-memory"); + if (reserved) { + for_each_child_of_node(reserved, node) { + if (of_match_node(reserved_mem_matches, node)) + of_platform_device_create(node, NULL, NULL); + } + of_node_put(reserved); + } node = of_find_node_by_path("/firmware"); if (node) { -- cgit v1.2.3 From 60477d78971342c476e221b643e56ed0dce8e888 Mon Sep 17 00:00:00 2001 From: Song Hongyi Date: Wed, 25 Feb 2026 17:38:14 +0800 Subject: of: property: fix typo in kernel-doc return description Fix the spelling of "success" in the return value description of the kernel-doc comment to improve documentation quality. Signed-off-by: Song Hongyi Link: https://patch.msgid.link/20260225093814.124735-1-szpcq123@gmail.com Signed-off-by: Rob Herring (Arm) --- drivers/of/property.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/of/property.c b/drivers/of/property.c index 50d95d512bf5..457e628ff9db 100644 --- a/drivers/of/property.c +++ b/drivers/of/property.c @@ -88,7 +88,7 @@ EXPORT_SYMBOL(of_graph_is_present); * Search for a property in a device node and count the number of elements of * size elem_size in it. * - * Return: The number of elements on sucess, -EINVAL if the property does not + * Return: The number of elements on success, -EINVAL if the property does not * exist or its length does not match a multiple of elem_size and -ENODATA if * the property does not have a value. */ -- cgit v1.2.3 From eda024766c84d08833d18a3903537161e744e2b3 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 27 Feb 2026 08:26:25 +0100 Subject: bus: Remove not-going-to-be-supported code for Baikal SoC As noticed in the discussion [1] the Baikal SoC and platforms are not going to be finalized, hence remove stale code. Link: https://lore.kernel.org/lkml/22b92ddf-6321-41b5-8073-f9c7064d3432@infradead.org/ [1] Signed-off-by: Andy Shevchenko Reviewed-by: Randy Dunlap Link: https://patch.msgid.link/20260227072726.1142944-2-andriy.shevchenko@linux.intel.com Signed-off-by: Rob Herring (Arm) --- drivers/bus/Kconfig | 30 ---- drivers/bus/Makefile | 2 - drivers/bus/bt1-apb.c | 396 -------------------------------------------------- drivers/bus/bt1-axi.c | 292 ------------------------------------- 4 files changed, 720 deletions(-) delete mode 100644 drivers/bus/bt1-apb.c delete mode 100644 drivers/bus/bt1-axi.c (limited to 'drivers') diff --git a/drivers/bus/Kconfig b/drivers/bus/Kconfig index 2a1b46f07080..5a7361c81be5 100644 --- a/drivers/bus/Kconfig +++ b/drivers/bus/Kconfig @@ -38,36 +38,6 @@ config BRCMSTB_GISB_ARB arbiter. This driver provides timeout and target abort error handling and internal bus master decoding. -config BT1_APB - bool "Baikal-T1 APB-bus driver" - depends on MIPS_BAIKAL_T1 || COMPILE_TEST - select REGMAP_MMIO - help - Baikal-T1 AXI-APB bridge is used to access the SoC subsystem CSRs. - IO requests are routed to this bus by means of the DW AMBA 3 AXI - Interconnect. In case of any APB protocol collisions, slave device - not responding on timeout an IRQ is raised with an erroneous address - reported to the APB terminator (APB Errors Handler Block). This - driver provides the interrupt handler to detect the erroneous - address, prints an error message about the address fault, updates an - errors counter. The counter and the APB-bus operations timeout can be - accessed via corresponding sysfs nodes. - -config BT1_AXI - bool "Baikal-T1 AXI-bus driver" - depends on MIPS_BAIKAL_T1 || COMPILE_TEST - select MFD_SYSCON - help - AXI3-bus is the main communication bus connecting all high-speed - peripheral IP-cores with RAM controller and with MIPS P5600 cores on - Baikal-T1 SoC. Traffic arbitration is done by means of DW AMBA 3 AXI - Interconnect (so called AXI Main Interconnect) routing IO requests - from one SoC block to another. This driver provides a way to detect - any bus protocol errors and device not responding situations by - means of an embedded on top of the interconnect errors handler - block (EHB). AXI Interconnect QoS arbitration tuning is currently - unsupported. - config MOXTET tristate "CZ.NIC Turris Mox module configuration bus" depends on SPI_MASTER && OF diff --git a/drivers/bus/Makefile b/drivers/bus/Makefile index 8e693fe8a03a..768a27e96276 100644 --- a/drivers/bus/Makefile +++ b/drivers/bus/Makefile @@ -13,8 +13,6 @@ obj-$(CONFIG_MOXTET) += moxtet.o # DPAA2 fsl-mc bus obj-$(CONFIG_FSL_MC_BUS) += fsl-mc/ -obj-$(CONFIG_BT1_APB) += bt1-apb.o -obj-$(CONFIG_BT1_AXI) += bt1-axi.o obj-$(CONFIG_IMX_AIPSTZ) += imx-aipstz.o obj-$(CONFIG_IMX_WEIM) += imx-weim.o obj-$(CONFIG_INTEL_IXP4XX_EB) += intel-ixp4xx-eb.o diff --git a/drivers/bus/bt1-apb.c b/drivers/bus/bt1-apb.c deleted file mode 100644 index 7463124b6dd9..000000000000 --- a/drivers/bus/bt1-apb.c +++ /dev/null @@ -1,396 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (C) 2020 BAIKAL ELECTRONICS, JSC - * - * Authors: - * Serge Semin - * - * Baikal-T1 APB-bus driver - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define APB_EHB_ISR 0x00 -#define APB_EHB_ISR_PENDING BIT(0) -#define APB_EHB_ISR_MASK BIT(1) -#define APB_EHB_ADDR 0x04 -#define APB_EHB_TIMEOUT 0x08 - -#define APB_EHB_TIMEOUT_MIN 0x000003FFU -#define APB_EHB_TIMEOUT_MAX 0xFFFFFFFFU - -/* - * struct bt1_apb - Baikal-T1 APB EHB private data - * @dev: Pointer to the device structure. - * @regs: APB EHB registers map. - * @res: No-device error injection memory region. - * @irq: Errors IRQ number. - * @rate: APB-bus reference clock rate. - * @pclk: APB-reference clock. - * @prst: APB domain reset line. - * @count: Number of errors detected. - */ -struct bt1_apb { - struct device *dev; - - struct regmap *regs; - void __iomem *res; - int irq; - - unsigned long rate; - struct clk *pclk; - - struct reset_control *prst; - - atomic_t count; -}; - -static const struct regmap_config bt1_apb_regmap_cfg = { - .reg_bits = 32, - .val_bits = 32, - .reg_stride = 4, - .max_register = APB_EHB_TIMEOUT, - .fast_io = true -}; - -static inline unsigned long bt1_apb_n_to_timeout_us(struct bt1_apb *apb, u32 n) -{ - u64 timeout = (u64)n * USEC_PER_SEC; - - do_div(timeout, apb->rate); - - return timeout; - -} - -static inline unsigned long bt1_apb_timeout_to_n_us(struct bt1_apb *apb, - unsigned long timeout) -{ - u64 n = (u64)timeout * apb->rate; - - do_div(n, USEC_PER_SEC); - - return n; - -} - -static irqreturn_t bt1_apb_isr(int irq, void *data) -{ - struct bt1_apb *apb = data; - u32 addr = 0; - - regmap_read(apb->regs, APB_EHB_ADDR, &addr); - - dev_crit_ratelimited(apb->dev, - "APB-bus fault %d: Slave access timeout at 0x%08x\n", - atomic_inc_return(&apb->count), - addr); - - /* - * Print backtrace on each CPU. This might be pointless if the fault - * has happened on the same CPU as the IRQ handler is executed or - * the other core proceeded further execution despite the error. - * But if it's not, by looking at the trace we would get straight to - * the cause of the problem. - */ - trigger_all_cpu_backtrace(); - - regmap_update_bits(apb->regs, APB_EHB_ISR, APB_EHB_ISR_PENDING, 0); - - return IRQ_HANDLED; -} - -static void bt1_apb_clear_data(void *data) -{ - struct bt1_apb *apb = data; - struct platform_device *pdev = to_platform_device(apb->dev); - - platform_set_drvdata(pdev, NULL); -} - -static struct bt1_apb *bt1_apb_create_data(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct bt1_apb *apb; - int ret; - - apb = devm_kzalloc(dev, sizeof(*apb), GFP_KERNEL); - if (!apb) - return ERR_PTR(-ENOMEM); - - ret = devm_add_action(dev, bt1_apb_clear_data, apb); - if (ret) { - dev_err(dev, "Can't add APB EHB data clear action\n"); - return ERR_PTR(ret); - } - - apb->dev = dev; - atomic_set(&apb->count, 0); - platform_set_drvdata(pdev, apb); - - return apb; -} - -static int bt1_apb_request_regs(struct bt1_apb *apb) -{ - struct platform_device *pdev = to_platform_device(apb->dev); - void __iomem *regs; - - regs = devm_platform_ioremap_resource_byname(pdev, "ehb"); - if (IS_ERR(regs)) { - dev_err(apb->dev, "Couldn't map APB EHB registers\n"); - return PTR_ERR(regs); - } - - apb->regs = devm_regmap_init_mmio(apb->dev, regs, &bt1_apb_regmap_cfg); - if (IS_ERR(apb->regs)) { - dev_err(apb->dev, "Couldn't create APB EHB regmap\n"); - return PTR_ERR(apb->regs); - } - - apb->res = devm_platform_ioremap_resource_byname(pdev, "nodev"); - if (IS_ERR(apb->res)) - dev_err(apb->dev, "Couldn't map reserved region\n"); - - return PTR_ERR_OR_ZERO(apb->res); -} - -static int bt1_apb_request_rst(struct bt1_apb *apb) -{ - int ret; - - apb->prst = devm_reset_control_get_optional_exclusive(apb->dev, "prst"); - if (IS_ERR(apb->prst)) - return dev_err_probe(apb->dev, PTR_ERR(apb->prst), - "Couldn't get reset control line\n"); - - ret = reset_control_deassert(apb->prst); - if (ret) - dev_err(apb->dev, "Failed to deassert the reset line\n"); - - return ret; -} - -static int bt1_apb_request_clk(struct bt1_apb *apb) -{ - apb->pclk = devm_clk_get_enabled(apb->dev, "pclk"); - if (IS_ERR(apb->pclk)) - return dev_err_probe(apb->dev, PTR_ERR(apb->pclk), - "Couldn't get APB clock descriptor\n"); - - apb->rate = clk_get_rate(apb->pclk); - if (!apb->rate) { - dev_err(apb->dev, "Invalid clock rate\n"); - return -EINVAL; - } - - return 0; -} - -static void bt1_apb_clear_irq(void *data) -{ - struct bt1_apb *apb = data; - - regmap_update_bits(apb->regs, APB_EHB_ISR, APB_EHB_ISR_MASK, 0); -} - -static int bt1_apb_request_irq(struct bt1_apb *apb) -{ - struct platform_device *pdev = to_platform_device(apb->dev); - int ret; - - apb->irq = platform_get_irq(pdev, 0); - if (apb->irq < 0) - return apb->irq; - - ret = devm_request_irq(apb->dev, apb->irq, bt1_apb_isr, IRQF_SHARED, - "bt1-apb", apb); - if (ret) { - dev_err(apb->dev, "Couldn't request APB EHB IRQ\n"); - return ret; - } - - ret = devm_add_action(apb->dev, bt1_apb_clear_irq, apb); - if (ret) { - dev_err(apb->dev, "Can't add APB EHB IRQs clear action\n"); - return ret; - } - - /* Unmask IRQ and clear it' pending flag. */ - regmap_update_bits(apb->regs, APB_EHB_ISR, - APB_EHB_ISR_PENDING | APB_EHB_ISR_MASK, - APB_EHB_ISR_MASK); - - return 0; -} - -static ssize_t count_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct bt1_apb *apb = dev_get_drvdata(dev); - - return scnprintf(buf, PAGE_SIZE, "%d\n", atomic_read(&apb->count)); -} -static DEVICE_ATTR_RO(count); - -static ssize_t timeout_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct bt1_apb *apb = dev_get_drvdata(dev); - unsigned long timeout; - int ret; - u32 n; - - ret = regmap_read(apb->regs, APB_EHB_TIMEOUT, &n); - if (ret) - return ret; - - timeout = bt1_apb_n_to_timeout_us(apb, n); - - return scnprintf(buf, PAGE_SIZE, "%lu\n", timeout); -} - -static ssize_t timeout_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct bt1_apb *apb = dev_get_drvdata(dev); - unsigned long timeout; - int ret; - u32 n; - - if (kstrtoul(buf, 0, &timeout) < 0) - return -EINVAL; - - n = bt1_apb_timeout_to_n_us(apb, timeout); - n = clamp(n, APB_EHB_TIMEOUT_MIN, APB_EHB_TIMEOUT_MAX); - - ret = regmap_write(apb->regs, APB_EHB_TIMEOUT, n); - - return ret ?: count; -} -static DEVICE_ATTR_RW(timeout); - -static ssize_t inject_error_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - return scnprintf(buf, PAGE_SIZE, "Error injection: nodev irq\n"); -} - -static ssize_t inject_error_store(struct device *dev, - struct device_attribute *attr, - const char *data, size_t count) -{ - struct bt1_apb *apb = dev_get_drvdata(dev); - - /* - * Either dummy read from the unmapped address in the APB IO area - * or manually set the IRQ status. - */ - if (sysfs_streq(data, "nodev")) - readl(apb->res); - else if (sysfs_streq(data, "irq")) - regmap_update_bits(apb->regs, APB_EHB_ISR, APB_EHB_ISR_PENDING, - APB_EHB_ISR_PENDING); - else - return -EINVAL; - - return count; -} -static DEVICE_ATTR_RW(inject_error); - -static struct attribute *bt1_apb_sysfs_attrs[] = { - &dev_attr_count.attr, - &dev_attr_timeout.attr, - &dev_attr_inject_error.attr, - NULL -}; -ATTRIBUTE_GROUPS(bt1_apb_sysfs); - -static void bt1_apb_remove_sysfs(void *data) -{ - struct bt1_apb *apb = data; - - device_remove_groups(apb->dev, bt1_apb_sysfs_groups); -} - -static int bt1_apb_init_sysfs(struct bt1_apb *apb) -{ - int ret; - - ret = device_add_groups(apb->dev, bt1_apb_sysfs_groups); - if (ret) { - dev_err(apb->dev, "Failed to create EHB APB sysfs nodes\n"); - return ret; - } - - ret = devm_add_action_or_reset(apb->dev, bt1_apb_remove_sysfs, apb); - if (ret) - dev_err(apb->dev, "Can't add APB EHB sysfs remove action\n"); - - return ret; -} - -static int bt1_apb_probe(struct platform_device *pdev) -{ - struct bt1_apb *apb; - int ret; - - apb = bt1_apb_create_data(pdev); - if (IS_ERR(apb)) - return PTR_ERR(apb); - - ret = bt1_apb_request_regs(apb); - if (ret) - return ret; - - ret = bt1_apb_request_rst(apb); - if (ret) - return ret; - - ret = bt1_apb_request_clk(apb); - if (ret) - return ret; - - ret = bt1_apb_request_irq(apb); - if (ret) - return ret; - - ret = bt1_apb_init_sysfs(apb); - if (ret) - return ret; - - return 0; -} - -static const struct of_device_id bt1_apb_of_match[] = { - { .compatible = "baikal,bt1-apb" }, - { } -}; -MODULE_DEVICE_TABLE(of, bt1_apb_of_match); - -static struct platform_driver bt1_apb_driver = { - .probe = bt1_apb_probe, - .driver = { - .name = "bt1-apb", - .of_match_table = bt1_apb_of_match - } -}; -module_platform_driver(bt1_apb_driver); - -MODULE_AUTHOR("Serge Semin "); -MODULE_DESCRIPTION("Baikal-T1 APB-bus driver"); diff --git a/drivers/bus/bt1-axi.c b/drivers/bus/bt1-axi.c deleted file mode 100644 index a5254c73bf43..000000000000 --- a/drivers/bus/bt1-axi.c +++ /dev/null @@ -1,292 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (C) 2020 BAIKAL ELECTRONICS, JSC - * - * Authors: - * Serge Semin - * - * Baikal-T1 AXI-bus driver - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define BT1_AXI_WERRL 0x110 -#define BT1_AXI_WERRH 0x114 -#define BT1_AXI_WERRH_TYPE BIT(23) -#define BT1_AXI_WERRH_ADDR_FLD 24 -#define BT1_AXI_WERRH_ADDR_MASK GENMASK(31, BT1_AXI_WERRH_ADDR_FLD) - -/* - * struct bt1_axi - Baikal-T1 AXI-bus private data - * @dev: Pointer to the device structure. - * @qos_regs: AXI Interconnect QoS tuning registers. - * @sys_regs: Baikal-T1 System Controller registers map. - * @irq: Errors IRQ number. - * @aclk: AXI reference clock. - * @arst: AXI Interconnect reset line. - * @count: Number of errors detected. - */ -struct bt1_axi { - struct device *dev; - - void __iomem *qos_regs; - struct regmap *sys_regs; - int irq; - - struct clk *aclk; - - struct reset_control *arst; - - atomic_t count; -}; - -static irqreturn_t bt1_axi_isr(int irq, void *data) -{ - struct bt1_axi *axi = data; - u32 low = 0, high = 0; - - regmap_read(axi->sys_regs, BT1_AXI_WERRL, &low); - regmap_read(axi->sys_regs, BT1_AXI_WERRH, &high); - - dev_crit_ratelimited(axi->dev, - "AXI-bus fault %d: %s at 0x%x%08x\n", - atomic_inc_return(&axi->count), - high & BT1_AXI_WERRH_TYPE ? "no slave" : "slave protocol error", - high, low); - - /* - * Print backtrace on each CPU. This might be pointless if the fault - * has happened on the same CPU as the IRQ handler is executed or - * the other core proceeded further execution despite the error. - * But if it's not, by looking at the trace we would get straight to - * the cause of the problem. - */ - trigger_all_cpu_backtrace(); - - return IRQ_HANDLED; -} - -static void bt1_axi_clear_data(void *data) -{ - struct bt1_axi *axi = data; - struct platform_device *pdev = to_platform_device(axi->dev); - - platform_set_drvdata(pdev, NULL); -} - -static struct bt1_axi *bt1_axi_create_data(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct bt1_axi *axi; - int ret; - - axi = devm_kzalloc(dev, sizeof(*axi), GFP_KERNEL); - if (!axi) - return ERR_PTR(-ENOMEM); - - ret = devm_add_action(dev, bt1_axi_clear_data, axi); - if (ret) { - dev_err(dev, "Can't add AXI EHB data clear action\n"); - return ERR_PTR(ret); - } - - axi->dev = dev; - atomic_set(&axi->count, 0); - platform_set_drvdata(pdev, axi); - - return axi; -} - -static int bt1_axi_request_regs(struct bt1_axi *axi) -{ - struct platform_device *pdev = to_platform_device(axi->dev); - struct device *dev = axi->dev; - - axi->sys_regs = syscon_regmap_lookup_by_phandle(dev->of_node, "syscon"); - if (IS_ERR(axi->sys_regs)) { - dev_err(dev, "Couldn't find syscon registers\n"); - return PTR_ERR(axi->sys_regs); - } - - axi->qos_regs = devm_platform_ioremap_resource_byname(pdev, "qos"); - if (IS_ERR(axi->qos_regs)) - dev_err(dev, "Couldn't map AXI-bus QoS registers\n"); - - return PTR_ERR_OR_ZERO(axi->qos_regs); -} - -static int bt1_axi_request_rst(struct bt1_axi *axi) -{ - int ret; - - axi->arst = devm_reset_control_get_optional_exclusive(axi->dev, "arst"); - if (IS_ERR(axi->arst)) - return dev_err_probe(axi->dev, PTR_ERR(axi->arst), - "Couldn't get reset control line\n"); - - ret = reset_control_deassert(axi->arst); - if (ret) - dev_err(axi->dev, "Failed to deassert the reset line\n"); - - return ret; -} - -static int bt1_axi_request_clk(struct bt1_axi *axi) -{ - axi->aclk = devm_clk_get_enabled(axi->dev, "aclk"); - if (IS_ERR(axi->aclk)) - return dev_err_probe(axi->dev, PTR_ERR(axi->aclk), - "Couldn't get AXI Interconnect clock\n"); - - return 0; -} - -static int bt1_axi_request_irq(struct bt1_axi *axi) -{ - struct platform_device *pdev = to_platform_device(axi->dev); - int ret; - - axi->irq = platform_get_irq(pdev, 0); - if (axi->irq < 0) - return axi->irq; - - ret = devm_request_irq(axi->dev, axi->irq, bt1_axi_isr, IRQF_SHARED, - "bt1-axi", axi); - if (ret) - dev_err(axi->dev, "Couldn't request AXI EHB IRQ\n"); - - return ret; -} - -static ssize_t count_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct bt1_axi *axi = dev_get_drvdata(dev); - - return scnprintf(buf, PAGE_SIZE, "%d\n", atomic_read(&axi->count)); -} -static DEVICE_ATTR_RO(count); - -static ssize_t inject_error_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - return scnprintf(buf, PAGE_SIZE, "Error injection: bus unaligned\n"); -} - -static ssize_t inject_error_store(struct device *dev, - struct device_attribute *attr, - const char *data, size_t count) -{ - struct bt1_axi *axi = dev_get_drvdata(dev); - - /* - * Performing unaligned read from the memory will cause the CM2 bus - * error while unaligned writing - the AXI bus write error handled - * by this driver. - */ - if (sysfs_streq(data, "bus")) - readb(axi->qos_regs); - else if (sysfs_streq(data, "unaligned")) - writeb(0, axi->qos_regs); - else - return -EINVAL; - - return count; -} -static DEVICE_ATTR_RW(inject_error); - -static struct attribute *bt1_axi_sysfs_attrs[] = { - &dev_attr_count.attr, - &dev_attr_inject_error.attr, - NULL -}; -ATTRIBUTE_GROUPS(bt1_axi_sysfs); - -static void bt1_axi_remove_sysfs(void *data) -{ - struct bt1_axi *axi = data; - - device_remove_groups(axi->dev, bt1_axi_sysfs_groups); -} - -static int bt1_axi_init_sysfs(struct bt1_axi *axi) -{ - int ret; - - ret = device_add_groups(axi->dev, bt1_axi_sysfs_groups); - if (ret) { - dev_err(axi->dev, "Failed to add sysfs files group\n"); - return ret; - } - - ret = devm_add_action_or_reset(axi->dev, bt1_axi_remove_sysfs, axi); - if (ret) - dev_err(axi->dev, "Can't add AXI EHB sysfs remove action\n"); - - return ret; -} - -static int bt1_axi_probe(struct platform_device *pdev) -{ - struct bt1_axi *axi; - int ret; - - axi = bt1_axi_create_data(pdev); - if (IS_ERR(axi)) - return PTR_ERR(axi); - - ret = bt1_axi_request_regs(axi); - if (ret) - return ret; - - ret = bt1_axi_request_rst(axi); - if (ret) - return ret; - - ret = bt1_axi_request_clk(axi); - if (ret) - return ret; - - ret = bt1_axi_request_irq(axi); - if (ret) - return ret; - - ret = bt1_axi_init_sysfs(axi); - if (ret) - return ret; - - return 0; -} - -static const struct of_device_id bt1_axi_of_match[] = { - { .compatible = "baikal,bt1-axi" }, - { } -}; -MODULE_DEVICE_TABLE(of, bt1_axi_of_match); - -static struct platform_driver bt1_axi_driver = { - .probe = bt1_axi_probe, - .driver = { - .name = "bt1-axi", - .of_match_table = bt1_axi_of_match - } -}; -module_platform_driver(bt1_axi_driver); - -MODULE_AUTHOR("Serge Semin "); -MODULE_DESCRIPTION("Baikal-T1 AXI-bus driver"); -- cgit v1.2.3 From 82b6c1b542ea0530318c6f2a880d884eb4dce49f Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 2 Mar 2026 17:29:05 +0100 Subject: of: Add of_machine_get_match() helper Currently, there are two helpers to match the root compatible value against an of_device_id array: - of_machine_device_match() returns true if a match is found, - of_machine_get_match_data() returns the match data if a match is found. However, there is no helper that returns the actual of_device_id structure corresponding to the match, leading to code duplication in various drivers. Fix this by reworking of_machine_device_match() to return the actual match structure, and renaming it to of_machine_get_match(). Retain the old of_machine_device_match() functionality using a cheap static inline wrapper around the new of_machine_get_match() helper. Signed-off-by: Geert Uytterhoeven Acked-by: Viresh Kumar Link: https://patch.msgid.link/14e1c03d443b1a5f210609ec3a1ebbaeab8fb3d9.1772468323.git.geert+renesas@glider.be Signed-off-by: Rob Herring (Arm) --- drivers/of/base.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/of/base.c b/drivers/of/base.c index 57420806c1a2..2a01d2a66eed 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -435,13 +435,12 @@ bool of_machine_compatible_match(const char *const *compats) EXPORT_SYMBOL(of_machine_compatible_match); /** - * of_machine_device_match - Test root of device tree against a of_device_id array + * of_machine_get_match - Test root of device tree against an of_device_id array * @matches: NULL terminated array of of_device_id match structures to search in * - * Returns true if the root node has any of the given compatible values in its - * compatible property. + * Returns matched entry or NULL */ -bool of_machine_device_match(const struct of_device_id *matches) +const struct of_device_id *of_machine_get_match(const struct of_device_id *matches) { struct device_node *root; const struct of_device_id *match = NULL; @@ -452,9 +451,9 @@ bool of_machine_device_match(const struct of_device_id *matches) of_node_put(root); } - return match != NULL; + return match; } -EXPORT_SYMBOL(of_machine_device_match); +EXPORT_SYMBOL(of_machine_get_match); /** * of_machine_get_match_data - Tell if root of device tree has a matching of_match structure -- cgit v1.2.3 From 57814f2e0cd7960fc8bbe097c05fdf2c3f8c67e4 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 2 Mar 2026 17:29:06 +0100 Subject: of: Convert to of_machine_get_match() Use the of_machine_get_match() helper instead of open-coding the same operation. Signed-off-by: Geert Uytterhoeven Acked-by: Viresh Kumar Link: https://patch.msgid.link/83ed49314b94dab7781e1d74236af72dd5c349c6.1772468323.git.geert+renesas@glider.be Signed-off-by: Rob Herring (Arm) --- drivers/of/base.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/of/base.c b/drivers/of/base.c index 2a01d2a66eed..af048ab88e69 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -464,15 +464,8 @@ EXPORT_SYMBOL(of_machine_get_match); const void *of_machine_get_match_data(const struct of_device_id *matches) { const struct of_device_id *match; - struct device_node *root; - - root = of_find_node_by_path("/"); - if (!root) - return NULL; - - match = of_match_node(matches, root); - of_node_put(root); + match = of_machine_get_match(matches); if (!match) return NULL; -- cgit v1.2.3 From 1838e0924e508eb30e140ad8f037863ee53be3c6 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 2 Mar 2026 17:29:07 +0100 Subject: cpufreq: airoha: Convert to of_machine_get_match() Use the of_machine_get_match() helper instead of open-coding the same operation. Signed-off-by: Geert Uytterhoeven Acked-by: Viresh Kumar Link: https://patch.msgid.link/cc76137755d93af982bf255095adafc7d523692c.1772468323.git.geert+renesas@glider.be Signed-off-by: Rob Herring (Arm) --- drivers/cpufreq/airoha-cpufreq.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/cpufreq/airoha-cpufreq.c b/drivers/cpufreq/airoha-cpufreq.c index b6b1cdc4d11d..3e7770860d13 100644 --- a/drivers/cpufreq/airoha-cpufreq.c +++ b/drivers/cpufreq/airoha-cpufreq.c @@ -115,15 +115,10 @@ MODULE_DEVICE_TABLE(of, airoha_cpufreq_match_list); static int __init airoha_cpufreq_init(void) { - struct device_node *np = of_find_node_by_path("/"); const struct of_device_id *match; int ret; - if (!np) - return -ENODEV; - - match = of_match_node(airoha_cpufreq_match_list, np); - of_node_put(np); + match = of_machine_get_match(airoha_cpufreq_match_list); if (!match) return -ENODEV; -- cgit v1.2.3 From 8cd94ead5184c5bdde74dc0afc316c6f3c41fdd7 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 2 Mar 2026 17:29:08 +0100 Subject: cpufreq: qcom-nvmem: Convert to of_machine_get_match() Use the of_machine_get_match() helper instead of open-coding the same operation. Signed-off-by: Geert Uytterhoeven Acked-by: Viresh Kumar Link: https://patch.msgid.link/886a603a7a1de6c8cb14ee0783ee0bceea4d914a.1772468323.git.geert+renesas@glider.be Signed-off-by: Rob Herring (Arm) --- drivers/cpufreq/qcom-cpufreq-nvmem.c | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/cpufreq/qcom-cpufreq-nvmem.c b/drivers/cpufreq/qcom-cpufreq-nvmem.c index b8081acba928..e6d28d162442 100644 --- a/drivers/cpufreq/qcom-cpufreq-nvmem.c +++ b/drivers/cpufreq/qcom-cpufreq-nvmem.c @@ -291,17 +291,9 @@ static int qcom_cpufreq_ipq8064_name_version(struct device *cpu_dev, ret = qcom_smem_get_soc_id(&msm_id); if (ret == -ENODEV) { const struct of_device_id *match; - struct device_node *root; - - root = of_find_node_by_path("/"); - if (!root) { - ret = -ENODEV; - goto exit; - } /* Fallback to compatible match with no SMEM initialized */ - match = of_match_node(qcom_cpufreq_ipq806x_match_list, root); - of_node_put(root); + match = of_machine_get_match(qcom_cpufreq_ipq806x_match_list); if (!match) { ret = -ENODEV; goto exit; @@ -647,14 +639,10 @@ MODULE_DEVICE_TABLE(of, qcom_cpufreq_match_list); */ static int __init qcom_cpufreq_init(void) { - struct device_node *np __free(device_node) = of_find_node_by_path("/"); const struct of_device_id *match; int ret; - if (!np) - return -ENODEV; - - match = of_match_node(qcom_cpufreq_match_list, np); + match = of_machine_get_match(qcom_cpufreq_match_list); if (!match) return -ENODEV; -- cgit v1.2.3 From 951318c4651a646f4835ae33abe7c4cb232e7c6e Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 2 Mar 2026 17:29:09 +0100 Subject: cpufreq: ti-cpufreq: Convert to of_machine_get_match() Use the of_machine_get_match() helper instead of open-coding the same operation. Signed-off-by: Geert Uytterhoeven Acked-by: Viresh Kumar Link: https://patch.msgid.link/bba0631aea78b6db7d453a9f9e98ea16b7e2c269.1772468323.git.geert+renesas@glider.be Signed-off-by: Rob Herring (Arm) --- drivers/cpufreq/ti-cpufreq.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/cpufreq/ti-cpufreq.c b/drivers/cpufreq/ti-cpufreq.c index 3d1129aeed02..a01abc1622eb 100644 --- a/drivers/cpufreq/ti-cpufreq.c +++ b/drivers/cpufreq/ti-cpufreq.c @@ -502,16 +502,6 @@ static const struct of_device_id ti_cpufreq_of_match[] __maybe_unused = { {}, }; -static const struct of_device_id *ti_cpufreq_match_node(void) -{ - struct device_node *np __free(device_node) = of_find_node_by_path("/"); - const struct of_device_id *match; - - match = of_match_node(ti_cpufreq_of_match, np); - - return match; -} - static int ti_cpufreq_probe(struct platform_device *pdev) { u32 version[VERSION_COUNT]; @@ -596,7 +586,7 @@ static int __init ti_cpufreq_init(void) const struct of_device_id *match; /* Check to ensure we are on a compatible platform */ - match = ti_cpufreq_match_node(); + match = of_machine_get_match(ti_cpufreq_of_match); if (match) platform_device_register_data(NULL, "ti-cpufreq", -1, match, sizeof(*match)); -- cgit v1.2.3 From 3ee3d8a44976ac7e39584637ee4c840d70ab2ad1 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 2 Mar 2026 17:29:10 +0100 Subject: soc: qcom: pd-mapper: Convert to of_machine_get_match() Use the of_machine_get_match() helper instead of open-coding the same operation. Signed-off-by: Geert Uytterhoeven Reviewed-by: Konrad Dybcio Acked-by: Viresh Kumar Link: https://patch.msgid.link/0d23a449e62ac85f04ff07bc2758efbaa709c9d1.1772468323.git.geert+renesas@glider.be Signed-off-by: Rob Herring (Arm) --- drivers/soc/qcom/qcom_pd_mapper.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/soc/qcom/qcom_pd_mapper.c b/drivers/soc/qcom/qcom_pd_mapper.c index dc10bc859ff4..8a1a18f8c859 100644 --- a/drivers/soc/qcom/qcom_pd_mapper.c +++ b/drivers/soc/qcom/qcom_pd_mapper.c @@ -615,15 +615,9 @@ static struct qcom_pdm_data *qcom_pdm_start(void) const struct qcom_pdm_domain_data * const *domains; const struct of_device_id *match; struct qcom_pdm_data *data; - struct device_node *root; int ret, i; - root = of_find_node_by_path("/"); - if (!root) - return ERR_PTR(-ENODEV); - - match = of_match_node(qcom_pdm_domains, root); - of_node_put(root); + match = of_machine_get_match(qcom_pdm_domains); if (!match) { pr_notice("PDM: no support for the platform, userspace daemon might be required.\n"); return ERR_PTR(-ENODEV); -- cgit v1.2.3 From c349e45fbe1f752432f291d24f43d67ab9007758 Mon Sep 17 00:00:00 2001 From: Herve Codina Date: Wed, 25 Mar 2026 15:35:44 +0100 Subject: of: property: Allow fw_devlink device-tree on x86 PCI drivers can use a device-tree overlay to describe the hardware available on the PCI board. This is the case, for instance, of the LAN966x PCI device driver. Adding some more nodes in the device-tree overlay adds some more consumer/supplier relationship between devices instantiated from this overlay. Those fw_node consumer/supplier relationships are handled by fw_devlink and are created based on the device-tree parsing done by the of_fwnode_add_links() function. Those consumer/supplier links are needed in order to ensure a correct PM runtime management and a correct removal order between devices. For instance, without those links a supplier can be removed before its consumers is removed leading to all kind of issue if this consumer still want the use the already removed supplier. The support for the usage of an overlay from a PCI driver has been added on x86 systems in commit 1f340724419ed ("PCI: of: Create device tree PCI host bridge node"). In the past, support for fw_devlink on x86 had been tried but this support has been removed in commit 4a48b66b3f52 ("of: property: Disable fw_devlink DT support for X86"). Indeed, this support was breaking some x86 systems such as OLPC system and the regression was reported in [0]. Instead of disabling this support for all x86 system, use a finer grain and disable this support only for the possible problematic subset of x86 systems (at least OLPC and CE4100). Those systems use a device-tree to describe their hardware. Identify those systems using key properties in the device-tree. Signed-off-by: Herve Codina Link: https://lore.kernel.org/lkml/3c1f2473-92ad-bfc4-258e-a5a08ad73dd0@web.de/ [0] Link: https://patch.msgid.link/20260325143555.451852-18-herve.codina@bootlin.com Signed-off-by: Rob Herring (Arm) --- drivers/of/property.c | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/of/property.c b/drivers/of/property.c index 457e628ff9db..136946f8b746 100644 --- a/drivers/of/property.c +++ b/drivers/of/property.c @@ -1620,12 +1620,36 @@ static int of_fwnode_irq_get(const struct fwnode_handle *fwnode, return of_irq_get(to_of_node(fwnode), index); } +static int match_property_by_path(const char *node_path, const char *prop_name, + const char *value) +{ + struct device_node *np __free(device_node) = of_find_node_by_path(node_path); + + return of_property_match_string(np, prop_name, value); +} + +static bool of_is_fwnode_add_links_supported(void) +{ + static int is_supported = -1; + + if (!IS_ENABLED(CONFIG_X86)) + return true; + + if (is_supported != -1) + return !!is_supported; + + is_supported = !((match_property_by_path("/soc", "compatible", "intel,ce4100-cp") >= 0) || + (match_property_by_path("/", "architecture", "OLPC") >= 0)); + + return !!is_supported; +} + static int of_fwnode_add_links(struct fwnode_handle *fwnode) { const struct property *p; struct device_node *con_np = to_of_node(fwnode); - if (IS_ENABLED(CONFIG_X86)) + if (!of_is_fwnode_add_links_supported()) return 0; if (!con_np) -- cgit v1.2.3 From bb04fcc89a889ad7d5e3427cd1afddd924ef691c Mon Sep 17 00:00:00 2001 From: Pengpeng Hou Date: Fri, 3 Apr 2026 11:55:29 +0800 Subject: drivers/of: fdt: validate stdout-path properties before parsing them early_init_dt_scan_chosen_stdout() fetches stdout-path and linux,stdout-path directly from the flat DT and immediately passes the result to strchrnul(). Flat DT properties are raw firmware-supplied byte sequences, and this path does not prove that either property is NUL-terminated within its declared bounds. Use fdt_stringlist_get() so malformed unterminated stdout-path properties are rejected before the local parser walks them as C strings. Signed-off-by: Pengpeng Hou Link: https://patch.msgid.link/20260403143001.1-dt-fdt-stdout-pengpeng@iscas.ac.cn Signed-off-by: Rob Herring (Arm) --- drivers/of/fdt.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index 43a0944ca462..9e4131f0e9b2 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c @@ -954,9 +954,9 @@ int __init early_init_dt_scan_chosen_stdout(void) if (offset < 0) return -ENOENT; - p = fdt_getprop(fdt, offset, "stdout-path", &l); + p = fdt_stringlist_get(fdt, offset, "stdout-path", 0, &l); if (!p) - p = fdt_getprop(fdt, offset, "linux,stdout-path", &l); + p = fdt_stringlist_get(fdt, offset, "linux,stdout-path", 0, &l); if (!p || !l) return -ENOENT; -- cgit v1.2.3 From b74f2f7fb2bb8c651e322919342aeddf747d69f7 Mon Sep 17 00:00:00 2001 From: Pengpeng Hou Date: Fri, 3 Apr 2026 13:59:47 +0800 Subject: drivers/of: fdt: validate flat DT string properties before string use Firmware-supplied flat DT properties are raw byte sequences. Several early FDT helpers fetch properties such as status, model, compatible, and device_type and then use them as C strings with strcmp(), strlen(), or pr_info() without first proving that the property is NUL-terminated within its declared length. Use fdt_stringlist_get() for these string properties instead. That preserves the existing behavior for valid DTBs while rejecting malformed unterminated properties before they are passed to C string helpers. Signed-off-by: Pengpeng Hou Link: https://patch.msgid.link/20260403164501.1-drivers-of-fdt-v2-pengpeng@iscas.ac.cn Signed-off-by: Rob Herring (Arm) --- drivers/of/fdt.c | 38 ++++++++++++++------------------------ 1 file changed, 14 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index 9e4131f0e9b2..becc855ff8b5 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c @@ -68,7 +68,7 @@ void __init of_fdt_limit_memory(int limit) bool of_fdt_device_is_available(const void *blob, unsigned long node) { - const char *status = fdt_getprop(blob, node, "status", NULL); + const char *status = fdt_stringlist_get(blob, node, "status", 0, NULL); if (!status) return true; @@ -677,22 +677,15 @@ void __init of_flat_dt_read_addr_size(const __be32 *prop, int entry_index, * specific compatible values. */ static int of_fdt_is_compatible(const void *blob, - unsigned long node, const char *compat) + unsigned long node, const char *compat) { const char *cp; - int cplen; - unsigned long l, score = 0; + int idx = 0, score = 0; - cp = fdt_getprop(blob, node, "compatible", &cplen); - if (cp == NULL) - return 0; - while (cplen > 0) { + while ((cp = fdt_stringlist_get(blob, node, "compatible", idx++, NULL))) { score++; if (of_compat_cmp(cp, compat, strlen(compat)) == 0) return score; - l = strlen(cp) + 1; - cp += l; - cplen -= l; } return 0; @@ -741,9 +734,10 @@ const char * __init of_flat_dt_get_machine_name(void) const char *name; unsigned long dt_root = of_get_flat_dt_root(); - name = of_get_flat_dt_prop(dt_root, "model", NULL); + name = fdt_stringlist_get(initial_boot_params, dt_root, "model", 0, NULL); if (!name) - name = of_get_flat_dt_prop(dt_root, "compatible", NULL); + name = fdt_stringlist_get(initial_boot_params, dt_root, + "compatible", 0, NULL); return name; } @@ -775,19 +769,14 @@ const void * __init of_flat_dt_match_machine(const void *default_match, } if (!best_data) { const char *prop; - int size; + int idx = 0, size; pr_err("\n unrecognized device tree list:\n[ "); - prop = of_get_flat_dt_prop(dt_root, "compatible", &size); - if (prop) { - while (size > 0) { - printk("'%s' ", prop); - size -= strlen(prop) + 1; - prop += strlen(prop) + 1; - } - } - printk("]\n\n"); + while ((prop = fdt_stringlist_get(initial_boot_params, dt_root, + "compatible", idx++, &size))) + pr_err("'%s' ", prop); + pr_err("]\n\n"); return NULL; } @@ -1032,7 +1021,8 @@ int __init early_init_dt_scan_memory(void) const void *fdt = initial_boot_params; fdt_for_each_subnode(node, fdt, 0) { - const char *type = of_get_flat_dt_prop(node, "device_type", NULL); + const char *type = fdt_stringlist_get(fdt, node, + "device_type", 0, NULL); const __be32 *reg; int i, l; bool hotpluggable; -- cgit v1.2.3 From faecdd423c27f0d6090156a435ba9dbbac0eaddb Mon Sep 17 00:00:00 2001 From: Wentao Liang Date: Thu, 9 Apr 2026 02:22:33 +0000 Subject: of: unittest: fix use-after-free in of_unittest_changeset() The variable 'parent' is assigned the value of 'nchangeset' earlier in the function, meaning both point to the same struct device_node. The call to of_node_put(nchangeset) can decrement the reference count to zero and free the node if there are no other holders. After that, the code still uses 'parent' to check for the presence of a property and to read a string property, leading to a use-after-free. Fix this by moving the of_node_put() call after the last access to 'parent', avoiding the UAF. Fixes: 1c668ea65506 ("of: unittest: Use of_property_present()") Cc: stable@vger.kernel.org Signed-off-by: Wentao Liang Link: https://patch.msgid.link/20260409022233.418103-1-vulab@iscas.ac.cn Signed-off-by: Rob Herring (Arm) --- drivers/of/unittest.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/of/unittest.c b/drivers/of/unittest.c index 2940295843e6..eae7ebdf5130 100644 --- a/drivers/of/unittest.c +++ b/drivers/of/unittest.c @@ -896,8 +896,6 @@ static void __init of_unittest_changeset(void) unittest(!of_changeset_apply(&chgset), "apply failed\n"); - of_node_put(nchangeset); - /* Make sure node names are constructed correctly */ unittest((np = of_find_node_by_path("/testcase-data/changeset/n2/n21")), "'%pOF' not added\n", n21); @@ -919,6 +917,7 @@ static void __init of_unittest_changeset(void) if (!ret) unittest(strcmp(propstr, "hello") == 0, "original value not in updated property after revert"); + of_node_put(nchangeset); of_changeset_destroy(&chgset); of_node_put(n1); -- cgit v1.2.3 From 07fd339b2c253205794bea5d9b4b7548a4546c56 Mon Sep 17 00:00:00 2001 From: Wentao Liang Date: Thu, 9 Apr 2026 03:48:59 +0000 Subject: of: unittest: fix use-after-free in testdrv_probe() The function testdrv_probe() retrieves the device_node from the PCI device, applies an overlay, and then immediately calls of_node_put(dn). This releases the reference held by the PCI core, potentially freeing the node if the reference count drops to zero. Later, the same freed pointer 'dn' is passed to of_platform_default_populate(), leading to a use-after-free. The reference to pdev->dev.of_node is owned by the device model and should not be released by the driver. Remove the erroneous of_node_put() to prevent premature freeing. Fixes: 26409dd04589 ("of: unittest: Add pci_dt_testdrv pci driver") Cc: stable@vger.kernel.org Signed-off-by: Wentao Liang Link: https://patch.msgid.link/20260409034859.429071-1-vulab@iscas.ac.cn Signed-off-by: Rob Herring (Arm) --- drivers/of/unittest.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/of/unittest.c b/drivers/of/unittest.c index eae7ebdf5130..4078569a0f96 100644 --- a/drivers/of/unittest.c +++ b/drivers/of/unittest.c @@ -4317,7 +4317,6 @@ static int testdrv_probe(struct pci_dev *pdev, const struct pci_device_id *id) size = info->dtbo_end - info->dtbo_begin; ret = of_overlay_fdt_apply(info->dtbo_begin, size, &ovcs_id, dn); - of_node_put(dn); if (ret) return ret; -- cgit v1.2.3