* [PATCH v2 0/2] Add Altera timeout bridge driver
@ 2026-10-21 19:56 Vyacheslav Yurkov via B4 Relay
2026-10-21 19:56 ` [PATCH v2 1/2] dt-bindings: bus: Add Altera AXI Timeout Bridge Vyacheslav Yurkov via B4 Relay
2026-10-21 19:56 ` [PATCH v2 2/2] bus: Add Altera AXI Timeout Bridge driver Vyacheslav Yurkov via B4 Relay
0 siblings, 2 replies; 6+ messages in thread
From: Vyacheslav Yurkov via B4 Relay @ 2026-10-21 19:56 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: devicetree, linux-kernel, Vyacheslav Yurkov
This series adds support for the Altera's AXI Timeout Bridge IP.
The timeout bridge connects an Axi bus to the HPS and provides a
downstream address space for devices implemented in the FPGA. The
bridge also exposes status information and generates an interrupt when
a timeout occurs.
The driver registers the timeout bridge as a bus and allows child
devices behind the bridge to be described as the child nodes in the
device tree.
The latest bridge documentation (as of October 2026):
https://docs.altera.com/r/docs/683609/26.1/quartus-prime-pro-edition-user-guide/axi-timeout-bridge-ip
Signed-off-by: Vyacheslav Yurkov <V.Yurkov.EXT@bruker.com>
---
Changes in v2:
- Address review notes
- Simplify error handling
- Provide better description for DT Schema
- Link to v1: https://lore.kernel.org/r/20261003-feature-timeout-ip-v1-0-8837c311d571@bruker.com
---
Vyacheslav Yurkov (2):
dt-bindings: bus: Add Altera AXI Timeout Bridge
bus: Add Altera AXI Timeout Bridge driver
.../ABI/testing/sysfs-driver-altera-timeout-bridge | 21 +++
.../bindings/bus/altr,axi-timeout-bridge-1.0.yaml | 80 ++++++++++
MAINTAINERS | 7 +
drivers/bus/Kconfig | 9 ++
drivers/bus/Makefile | 1 +
drivers/bus/altera-timeout-bridge.c | 173 +++++++++++++++++++++
6 files changed, 291 insertions(+)
---
base-commit: a804c5742bff224d4cb4d25dd383554d598be32b
change-id: 20261003-feature-timeout-ip-7a93630de299
Best regards,
--
Vyacheslav Yurkov <V.Yurkov.EXT@bruker.com>
^ permalink raw reply [flat|nested] 6+ messages in thread* [PATCH v2 1/2] dt-bindings: bus: Add Altera AXI Timeout Bridge 2026-10-21 19:56 [PATCH v2 0/2] Add Altera timeout bridge driver Vyacheslav Yurkov via B4 Relay @ 2026-10-21 19:56 ` Vyacheslav Yurkov via B4 Relay 2026-10-21 20:05 ` sashiko-bot 2026-10-22 2:29 ` Rob Herring (Arm) 2026-10-21 19:56 ` [PATCH v2 2/2] bus: Add Altera AXI Timeout Bridge driver Vyacheslav Yurkov via B4 Relay 1 sibling, 2 replies; 6+ messages in thread From: Vyacheslav Yurkov via B4 Relay @ 2026-10-21 19:56 UTC (permalink / raw) To: Rob Herring, Krzysztof Kozlowski, Conor Dooley Cc: devicetree, linux-kernel, Vyacheslav Yurkov From: Vyacheslav Yurkov <V.Yurkov.EXT@bruker.com> The Altera AXI Timeout Bridge is an FPGA IP core placed between an AXI host, such as the HPS-to-FPGA bridge, and peripherals implemented in the FPGA fabric. It forwards transactions unchanged and monitors each one for completion. If a peripheral does not respond in time, the bridge terminates the transaction with an error response so that the host does not hang, raises an interrupt, and reports the address of the timed-out transaction in its control and status registers. Signed-off-by: Vyacheslav Yurkov <V.Yurkov.EXT@bruker.com> --- .../bindings/bus/altr,axi-timeout-bridge-1.0.yaml | 80 ++++++++++++++++++++++ 1 file changed, 80 insertions(+) diff --git a/Documentation/devicetree/bindings/bus/altr,axi-timeout-bridge-1.0.yaml b/Documentation/devicetree/bindings/bus/altr,axi-timeout-bridge-1.0.yaml new file mode 100644 index 000000000000..3512494442d4 --- /dev/null +++ b/Documentation/devicetree/bindings/bus/altr,axi-timeout-bridge-1.0.yaml @@ -0,0 +1,80 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/bus/altr,axi-timeout-bridge-1.0.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Altera AXI Timeout Bridge + +maintainers: + - Vyacheslav Yurkov <V.Yurkov.EXT@bruker.com> + +description: | + The Altera AXI Timeout Bridge is an FPGA soft IP placed between an AXI + host, such as the HPS-to-FPGA bridge, and the downstream peripherals + implemented in the FPGA fabric. It forwards transactions unchanged and + monitors each one for completion. + + If a downstream peripheral does not respond within a configured number + of clock cycles, the bridge terminates the outstanding transaction with + an error response so that the host does not hang, + and raises an interrupt. + +properties: + compatible: + const: altr,axi-timeout-bridge-1.0 + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + ranges: true + + "#address-cells": + const: 1 + + "#size-cells": + const: 1 + +patternProperties: + "^[a-zA-Z][a-zA-Z0-9,+._-]*@[0-9a-f]+$": + type: object + description: | + Device connected to the timeout bridge. + + required: + - compatible + - reg + + additionalProperties: true + +required: + - compatible + - reg + - interrupts + - ranges + - "#address-cells" + - "#size-cells" + +additionalProperties: false + +examples: + - | + #include <dt-bindings/interrupt-controller/irq.h> + + timeout-bridge@10000 { + compatible = "altr,axi-timeout-bridge-1.0"; + #address-cells = <1>; + #size-cells = <1>; + + reg = <0x10000 0x10>; + interrupts = <0 12 IRQ_TYPE_LEVEL_HIGH>; + ranges = <0x0 0x10010 0x1000>; + + timeout-device@100 { + compatible = "timeout-device"; + reg = <0x100 0x10>; + }; + }; -- 2.34.1 ^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH v2 1/2] dt-bindings: bus: Add Altera AXI Timeout Bridge 2026-10-21 19:56 ` [PATCH v2 1/2] dt-bindings: bus: Add Altera AXI Timeout Bridge Vyacheslav Yurkov via B4 Relay @ 2026-10-21 20:05 ` sashiko-bot 2026-10-22 2:29 ` Rob Herring (Arm) 1 sibling, 0 replies; 6+ messages in thread From: sashiko-bot @ 2026-10-21 20:05 UTC (permalink / raw) To: Vyacheslav Yurkov; +Cc: devicetree, robh, conor+dt Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider: - [Low] dt-bindings: bus: undocumented compatible in axi-timeout-bridge example - [Low] dt-bindings: bus: non-canonical property order in axi-timeout-bridge example -- commit b1b42eb61f1fec5cade8d2ad793870c54e4f6574 Author: Vyacheslav Yurkov <V.Yurkov.EXT@bruker.com> dt-bindings: bus: Add Altera AXI Timeout Bridge This commit adds the devicetree binding schema for the Altera AXI Timeout Bridge FPGA IP core, which monitors AXI transactions to downstream fabric peripherals and terminates timed-out accesses with an error response and interrupt. > diff --git a/Documentation/devicetree/bindings/bus/altr,axi-timeout-bridge-1.0.yaml b/Documentation/devicetree/bindings/bus/altr,axi-timeout-bridge-1.0.yaml > new file mode 100644 > index 0000000000000..3512494442d46 > --- /dev/null > +++ b/Documentation/devicetree/bindings/bus/altr,axi-timeout-bridge-1.0.yaml > @@ -0,0 +1,80 @@ [ ... ] > +examples: > + - | > + #include <dt-bindings/interrupt-controller/irq.h> > + > + timeout-bridge@10000 { > + compatible = "altr,axi-timeout-bridge-1.0"; > + #address-cells = <1>; > + #size-cells = <1>; > + > + reg = <0x10000 0x10>; > + interrupts = <0 12 IRQ_TYPE_LEVEL_HIGH>; > + ranges = <0x0 0x10010 0x1000>; [Severity: Low] In Documentation/devicetree/bindings/bus/altr,axi-timeout-bridge-1.0.yaml under the examples section, the timeout-bridge@10000 node places #address-cells and #size-cells before reg, and interrupts before ranges. Per Documentation/devicetree/bindings/dts-coding-style.rst and check_property_order() in scripts/dtc/dt-check-style, properties in a node are expected to begin with compatible, reg, and ranges, followed by common properties sorted by their #-stripped names (#address-cells, interrupts, #size-cells). Running scripts/dtc/dt-check-style --mode=strict on this binding reports property-order warnings for reg and ranges. Should the properties in timeout-bridge@10000 be reordered so that compatible, reg, and ranges come first? > + > + timeout-device@100 { > + compatible = "timeout-device"; > + reg = <0x100 0x10>; > + }; > + }; [Severity: Low] In Documentation/devicetree/bindings/bus/altr,axi-timeout-bridge-1.0.yaml under the examples section, the child node timeout-device@100 uses compatible = "timeout-device", which has no vendor prefix and is not documented by any binding schema under Documentation/devicetree/bindings/. When make dt_binding_check runs without DT_SCHEMA_FILES set, scripts/Makefile.dtbs invokes dt-validate with -m: DT_CHECKER ?= dt-validate DT_CHECKER_FLAGS ?= $(if $(DT_SCHEMA_FILES),-l $(DT_SCHEMA_FILES),-m) This checks that every node with a compatible string in the compiled example matches a known schema, causing validation of /example-0/timeout-bridge@10000/timeout-device@100 to fail with: failed to match any schema with compatible: ['timeout-device'] Could timeout-device@100 in the example use an existing documented compatible string so that make dt_binding_check passes when dt-validate runs with -m? -- Sashiko AI review · https://sashiko.dev/#/patchset/20261021-feature-timeout-ip-v2-0-a037be089518@bruker.com?part=1 ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH v2 1/2] dt-bindings: bus: Add Altera AXI Timeout Bridge 2026-10-21 19:56 ` [PATCH v2 1/2] dt-bindings: bus: Add Altera AXI Timeout Bridge Vyacheslav Yurkov via B4 Relay 2026-10-21 20:05 ` sashiko-bot @ 2026-10-22 2:29 ` Rob Herring (Arm) 1 sibling, 0 replies; 6+ messages in thread From: Rob Herring (Arm) @ 2026-10-22 2:29 UTC (permalink / raw) To: Vyacheslav Yurkov Cc: Conor Dooley, Krzysztof Kozlowski, devicetree, linux-kernel On Wed, 21 Oct 2026 19:56:23 +0000, Vyacheslav Yurkov wrote: > The Altera AXI Timeout Bridge is an FPGA IP core placed between an AXI > host, such as the HPS-to-FPGA bridge, and peripherals implemented in > the FPGA fabric. It forwards transactions unchanged and monitors each > one for completion. If a peripheral does not respond in time, the > bridge terminates the transaction with an error response so that the > host does not hang, raises an interrupt, and reports the address of > the timed-out transaction in its control and status registers. > > Signed-off-by: Vyacheslav Yurkov <V.Yurkov.EXT@bruker.com> > --- > .../bindings/bus/altr,axi-timeout-bridge-1.0.yaml | 80 ++++++++++++++++++++++ > 1 file changed, 80 insertions(+) > My bot found errors running 'make dt_binding_check' on your patch: yamllint warnings/errors: dtschema/dtc warnings/errors: Documentation/devicetree/bindings/bus/altr,axi-timeout-bridge-1.0.example.dtb: /example-0/timeout-bridge@10000/timeout-device@100: failed to match any schema with compatible: ['timeout-device'] doc reference errors (make refcheckdocs): See https://patchwork.kernel.org/project/devicetree/patch/20261021-feature-timeout-ip-v2-1-a037be089518@bruker.com The base for the series is generally the latest rc1. A different dependency should be noted in *this* patch. If you already ran 'make dt_binding_check' and didn't see the above error(s), then make sure 'yamllint' is installed and dt-schema is up to date: pip3 install dtschema --upgrade Please check and re-submit after running the above command yourself. Note that DT_SCHEMA_FILES can be set to your schema file to speed up checking your schema. However, it must be unset to test all examples with your schema. ^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH v2 2/2] bus: Add Altera AXI Timeout Bridge driver 2026-10-21 19:56 [PATCH v2 0/2] Add Altera timeout bridge driver Vyacheslav Yurkov via B4 Relay 2026-10-21 19:56 ` [PATCH v2 1/2] dt-bindings: bus: Add Altera AXI Timeout Bridge Vyacheslav Yurkov via B4 Relay @ 2026-10-21 19:56 ` Vyacheslav Yurkov via B4 Relay 2026-10-21 20:11 ` sashiko-bot 1 sibling, 1 reply; 6+ messages in thread From: Vyacheslav Yurkov via B4 Relay @ 2026-10-21 19:56 UTC (permalink / raw) To: Rob Herring, Krzysztof Kozlowski, Conor Dooley Cc: devicetree, linux-kernel, Vyacheslav Yurkov From: Vyacheslav Yurkov <V.Yurkov.EXT@bruker.com> The Altera AXI Timeout Bridge sits between an AXI host and peripherals in the FPGA fabric. When a peripheral fails to respond, the bridge completes the transaction with an error response instead of letting the host hang, raises an interrupt, and latches the address of the timed-out transaction. Add a driver that populates the peripherals behind the bridge as child devices and handles the timeout interrupt. On each timeout, the driver logs the address, clears the interrupt, and notifies user space through sysfs: irq_count number of timeouts since the driver was bound last_timeout_address address of the most recent timed-out transaction last_timeout_address supports poll(), so a monitoring application can wait for timeouts without busy-polling. The timed out process would get SIGBUS fault on arm32. Signed-off-by: Vyacheslav Yurkov <V.Yurkov.EXT@bruker.com> --- .../ABI/testing/sysfs-driver-altera-timeout-bridge | 21 +++ MAINTAINERS | 7 + drivers/bus/Kconfig | 9 ++ drivers/bus/Makefile | 1 + drivers/bus/altera-timeout-bridge.c | 173 +++++++++++++++++++++ 5 files changed, 211 insertions(+) diff --git a/Documentation/ABI/testing/sysfs-driver-altera-timeout-bridge b/Documentation/ABI/testing/sysfs-driver-altera-timeout-bridge new file mode 100644 index 000000000000..cb03177bd55d --- /dev/null +++ b/Documentation/ABI/testing/sysfs-driver-altera-timeout-bridge @@ -0,0 +1,21 @@ +What: /sys/bus/platform/devices/<dev>/irq_count +Date: October 2026 +KernelVersion: 7.5 +Contact: Vyacheslav Yurkov <V.Yurkov.EXT@bruker.com> +Description: + (RO) Number of transaction timeouts reported by the + Altera AXI Timeout Bridge since the driver was bound. + +What: /sys/bus/platform/devices/<dev>/last_timeout_address +Date: October 2026 +KernelVersion: 7.5 +Contact: Vyacheslav Yurkov <V.Yurkov.EXT@bruker.com> +Description: + (RO) Address of the most recent transaction that timed + out, as reported by the bridge, formatted as a + hexadecimal number with a 0x prefix. Reads 0x0 until + the first timeout occurs. + + The attribute supports poll(): user space can wait for + POLLPRI | POLLERR to be notified of each new timeout, + re-reading the attribute from offset 0 afterwards. diff --git a/MAINTAINERS b/MAINTAINERS index 7b5cab72d851..27f7ffd6f0cb 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -945,6 +945,13 @@ ALPS PS/2 TOUCHPAD DRIVER R: Pali Rohár <pali@kernel.org> F: drivers/input/mouse/alps.* +ALTERA AXI TIMEOUT BRIDGE DRIVER +M Vyacheslav Yurkov <V.Yurkov.EXT@bruker.com> +S: Maintained +F: Documentation/ABI/testing/sysfs-driver-altera-timeout-bridge +F: Documentation/devicetree/bindings/bus/altr,axi-timeout-bridge-1.0.yaml +F: drivers/bus/altera-timeout-bridge.c + ALTERA MAILBOX DRIVER M: Tien Sung Ang <tiensung.ang@altera.com> S: Maintained diff --git a/drivers/bus/Kconfig b/drivers/bus/Kconfig index e4b1db809187..c27b6d903713 100644 --- a/drivers/bus/Kconfig +++ b/drivers/bus/Kconfig @@ -247,6 +247,15 @@ config DA8XX_MSTPRI configuration. Allows to adjust the priorities of all master peripherals. +config ALTERA_TIMEOUT_BRIDGE + tristate "Altera AXI Timeout Bridge bus" + depends on OF && HAS_IOMEM + help + Driver for Altera AXI Timeout Bridge, which can be used as bus. + The subordinate devices can be connected to the bridge, which + detects frozen read/write requests and notifies user space by + means of a sysfs interrupt flag. + source "drivers/bus/fsl-mc/Kconfig" source "drivers/bus/mhi/Kconfig" diff --git a/drivers/bus/Makefile b/drivers/bus/Makefile index a01f97fef3e8..ad4e6d7b1e49 100644 --- a/drivers/bus/Makefile +++ b/drivers/bus/Makefile @@ -39,6 +39,7 @@ obj-$(CONFIG_UNIPHIER_SYSTEM_BUS) += uniphier-system-bus.o obj-$(CONFIG_VEXPRESS_CONFIG) += vexpress-config.o obj-$(CONFIG_DA8XX_MSTPRI) += da8xx-mstpri.o +obj-$(CONFIG_ALTERA_TIMEOUT_BRIDGE) += altera-timeout-bridge.o # MHI obj-y += mhi/ diff --git a/drivers/bus/altera-timeout-bridge.c b/drivers/bus/altera-timeout-bridge.c new file mode 100644 index 000000000000..87886c3ad794 --- /dev/null +++ b/drivers/bus/altera-timeout-bridge.c @@ -0,0 +1,173 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Altera AXI Timeout Bridge Bus Driver + * + * Copyright (C) 2026 Bruker Corporation + */ + +#include <linux/interrupt.h> +#include <linux/io-64-nonatomic-lo-hi.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/of_platform.h> +#include <linux/platform_device.h> +#include <linux/spinlock.h> + +#define ALTERA_TIMEOUT_BRIDGE_REG_IRQ_STATUS_RESET 0x00 +#define ALTERA_TIMEOUT_BRIDGE_REG_TIMED_OUT_ADDRESS_LO 0x08 +#define ALTERA_TIMEOUT_BRIDGE_REG_TIMED_OUT_ADDRESS_HI 0x0C + +struct altera_timeout_bridge_data { + struct device *dev; + struct resource *bridge_register_resource; + void __iomem *bridge_registers; + atomic_t irq_count; + u64 last_timeout_address; + spinlock_t lock; + struct kernfs_node *irq_node; +}; + +static ssize_t last_timeout_address_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct altera_timeout_bridge_data *driver_data = dev_get_drvdata(dev); + unsigned long flags; + u64 addr; + + spin_lock_irqsave(&driver_data->lock, flags); + addr = driver_data->last_timeout_address; + spin_unlock_irqrestore(&driver_data->lock, flags); + + return sysfs_emit(buf, "0x%016llx\n", addr); +} + +static ssize_t irq_count_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct altera_timeout_bridge_data *driver_data = dev_get_drvdata(dev); + + return sysfs_emit(buf, "%u\n", atomic_read(&driver_data->irq_count)); +} + +static DEVICE_ATTR_RO(last_timeout_address); +static DEVICE_ATTR_RO(irq_count); + +static struct attribute *altera_timeout_bridge_sysfs_attrs[] = { + &dev_attr_last_timeout_address.attr, + &dev_attr_irq_count.attr, + NULL /* sentinel */ +}; + +static const struct attribute_group altera_timeout_bridge_sysfs_group = { + .attrs = altera_timeout_bridge_sysfs_attrs, +}; + +static irqreturn_t altera_timeout_bridge_isr(int irq, void *data) +{ + struct altera_timeout_bridge_data *driver_data = data; + u64 timed_out_address; + resource_size_t effective_base_address; + resource_size_t effective_address; + + atomic_inc(&driver_data->irq_count); + + // Read and print the timed-out address (encoded in the lower nibble + // 0x8..0xF according to AXI Timeout Bridge IP (CSR Interrupt Status Information) + timed_out_address = lo_hi_readq(driver_data->bridge_registers + + ALTERA_TIMEOUT_BRIDGE_REG_TIMED_OUT_ADDRESS_LO); + effective_base_address = driver_data->bridge_register_resource->start; + effective_address = effective_base_address + timed_out_address; + + spin_lock(&driver_data->lock); + driver_data->last_timeout_address = effective_address; + spin_unlock(&driver_data->lock); + + dev_err_ratelimited(driver_data->dev, "timeout at address 0x%llx\n", + (unsigned long long)effective_address); + + // Reset IRQ status in the bridge + writel(0x1, + driver_data->bridge_registers + + ALTERA_TIMEOUT_BRIDGE_REG_IRQ_STATUS_RESET); + // notify the user space + sysfs_notify_dirent(driver_data->irq_node); + + return IRQ_HANDLED; +} + +static void altera_timeout_bridge_put_dirent(void *data) +{ + sysfs_put(data); +} + +static int altera_timeout_bridge_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct altera_timeout_bridge_data *driver_data; + int ret; + int irq; + + driver_data = + devm_kzalloc(&pdev->dev, sizeof(*driver_data), GFP_KERNEL); + if (!driver_data) + return -ENOMEM; + + driver_data->dev = dev; + platform_set_drvdata(pdev, driver_data); + + driver_data->bridge_registers = + devm_platform_get_and_ioremap_resource(pdev, 0, + &driver_data->bridge_register_resource); + if (IS_ERR(driver_data->bridge_registers)) + return PTR_ERR(driver_data->bridge_registers); + + ret = devm_device_add_group(dev, &altera_timeout_bridge_sysfs_group); + if (ret) + return ret; + + driver_data->irq_node = sysfs_get_dirent(dev->kobj.sd, "last_timeout_address"); + if (!driver_data->irq_node) + return -ENOENT; + + ret = devm_add_action_or_reset(dev, altera_timeout_bridge_put_dirent, + driver_data->irq_node); + if (ret) + return ret; + + spin_lock_init(&driver_data->lock); + irq = platform_get_irq(pdev, 0); + if (irq < 0) + return irq; + + ret = devm_request_irq(dev, irq, + altera_timeout_bridge_isr, + 0, + dev_name(dev), + driver_data); + if (ret) + return dev_err_probe(dev, ret, "Failed to request IRQ\n"); + + return devm_of_platform_populate(dev); +} + +static const struct of_device_id altera_timeout_bridge_of_match[] = { + { .compatible = "altr,axi-timeout-bridge-1.0", }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, altera_timeout_bridge_of_match); + +static struct platform_driver altera_timeout_bridge_driver = { + .probe = altera_timeout_bridge_probe, + .driver = { + .name = "axi-timeout-bridge", + .of_match_table = altera_timeout_bridge_of_match, + }, +}; + +module_platform_driver(altera_timeout_bridge_driver); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("AXI Timeout Bridge Bus"); +MODULE_AUTHOR("Vyacheslav Yurkov <V.Yurkov.EXT@bruker.com>"); + -- 2.34.1 ^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH v2 2/2] bus: Add Altera AXI Timeout Bridge driver 2026-10-21 19:56 ` [PATCH v2 2/2] bus: Add Altera AXI Timeout Bridge driver Vyacheslav Yurkov via B4 Relay @ 2026-10-21 20:11 ` sashiko-bot 0 siblings, 0 replies; 6+ messages in thread From: sashiko-bot @ 2026-10-21 20:11 UTC (permalink / raw) To: Vyacheslav Yurkov; +Cc: devicetree, robh, conor+dt Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider: - [High] bus: wrong base and 32-bit truncation in altera_timeout_bridge_isr() - [High] bus: uninitialized spinlock exposed via sysfs in altera_timeout_bridge_probe() - [Medium] bus: altera-timeout-bridge: NULL deref or probe failure when CONFIG_SYSFS=n - [Low] MAINTAINERS: missing colon on M tag for Altera AXI Timeout Bridge driver -- commit 2fab3abca0c9e4fa16264b963ed344d58e87a918 Author: Vyacheslav Yurkov <V.Yurkov.EXT@bruker.com> bus: Add Altera AXI Timeout Bridge driver This commit adds a bus driver for the Altera AXI Timeout Bridge that populates child devices behind the bridge and handles timeout interrupts by logging the timed-out address and exposing irq_count and last_timeout_address via sysfs. > diff --git a/MAINTAINERS b/MAINTAINERS > index 7b5cab72d851b..27f7ffd6f0cb2 100644 > --- a/MAINTAINERS > +++ b/MAINTAINERS > @@ -945,6 +945,13 @@ ALPS PS/2 TOUCHPAD DRIVER > R: Pali Rohár <pali@kernel.org> > F: drivers/input/mouse/alps.* > > +ALTERA AXI TIMEOUT BRIDGE DRIVER > +M Vyacheslav Yurkov <V.Yurkov.EXT@bruker.com> [Severity: Low] Should the M tag in MAINTAINERS under ALTERA AXI TIMEOUT BRIDGE DRIVER have a colon after M ("M:") so scripts/parse-maintainers.pl and scripts/get_maintainer.pl can parse the entry without failing? > +S: Maintained > +F: Documentation/ABI/testing/sysfs-driver-altera-timeout-bridge > +F: Documentation/devicetree/bindings/bus/altr,axi-timeout-bridge-1.0.yaml > +F: drivers/bus/altera-timeout-bridge.c > + > ALTERA MAILBOX DRIVER > M: Tien Sung Ang <tiensung.ang@altera.com> > S: Maintained [ ... ] > diff --git a/drivers/bus/altera-timeout-bridge.c b/drivers/bus/altera-timeout-bridge.c > new file mode 100644 > index 0000000000000..87886c3ad7941 > --- /dev/null > +++ b/drivers/bus/altera-timeout-bridge.c > @@ -0,0 +1,173 @@ [ ... ] > +static ssize_t last_timeout_address_show(struct device *dev, struct device_attribute *attr, > + char *buf) > +{ > + struct altera_timeout_bridge_data *driver_data = dev_get_drvdata(dev); > + unsigned long flags; > + u64 addr; > + > + spin_lock_irqsave(&driver_data->lock, flags); > + addr = driver_data->last_timeout_address; > + spin_unlock_irqrestore(&driver_data->lock, flags); > + > + return sysfs_emit(buf, "0x%016llx\n", addr); > +} [ ... ] > +static irqreturn_t altera_timeout_bridge_isr(int irq, void *data) > +{ > + struct altera_timeout_bridge_data *driver_data = data; > + u64 timed_out_address; > + resource_size_t effective_base_address; > + resource_size_t effective_address; > + > + atomic_inc(&driver_data->irq_count); > + > + // Read and print the timed-out address (encoded in the lower nibble > + // 0x8..0xF according to AXI Timeout Bridge IP (CSR Interrupt Status Information) > + timed_out_address = lo_hi_readq(driver_data->bridge_registers + > + ALTERA_TIMEOUT_BRIDGE_REG_TIMED_OUT_ADDRESS_LO); > + effective_base_address = driver_data->bridge_register_resource->start; > + effective_address = effective_base_address + timed_out_address; > + > + spin_lock(&driver_data->lock); > + driver_data->last_timeout_address = effective_address; > + spin_unlock(&driver_data->lock); [Severity: High] Does altera_timeout_bridge_isr() in drivers/bus/altera-timeout-bridge.c compute the wrong physical address and truncate 64-bit addresses on 32-bit platforms? In altera_timeout_bridge_probe(), devm_platform_get_and_ioremap_resource() populates driver_data->bridge_register_resource from reg index 0, which is the bridge's own 16-byte CSR register block rather than the subordinate bus address window described by ranges: Documentation/devicetree/bindings/bus/altr,axi-timeout-bridge-1.0.yaml: reg = <0x10000 0x10>; interrupts = <0 12 IRQ_TYPE_LEVEL_HIGH>; ranges = <0x0 0x10010 0x1000>; timeout-device@100 { compatible = "timeout-device"; reg = <0x100 0x10>; }; Adding driver_data->bridge_register_resource->start to timed_out_address adds the CSR base address (0x10000 in the binding example, yielding 0x10100 instead of 0x10110) rather than translating the subordinate bus address through ranges. In addition, timed_out_address and driver_data->last_timeout_address are u64, whereas effective_base_address and effective_address are resource_size_t. On 32-bit platforms without CONFIG_PHYS_ADDR_T_64BIT (such as arm32 without LPAE), resource_size_t is 32 bits wide, so assigning the sum to effective_address truncates the upper 32 bits before storing into driver_data->last_timeout_address. > + > + dev_err_ratelimited(driver_data->dev, "timeout at address 0x%llx\n", > + (unsigned long long)effective_address); [ ... ] > +static int altera_timeout_bridge_probe(struct platform_device *pdev) > +{ > + struct device *dev = &pdev->dev; > + struct altera_timeout_bridge_data *driver_data; > + int ret; > + int irq; > + > + driver_data = > + devm_kzalloc(&pdev->dev, sizeof(*driver_data), GFP_KERNEL); > + if (!driver_data) > + return -ENOMEM; > + > + driver_data->dev = dev; > + platform_set_drvdata(pdev, driver_data); > + > + driver_data->bridge_registers = > + devm_platform_get_and_ioremap_resource(pdev, 0, > + &driver_data->bridge_register_resource); > + if (IS_ERR(driver_data->bridge_registers)) > + return PTR_ERR(driver_data->bridge_registers); > + > + ret = devm_device_add_group(dev, &altera_timeout_bridge_sysfs_group); > + if (ret) > + return ret; > + > + driver_data->irq_node = sysfs_get_dirent(dev->kobj.sd, "last_timeout_address"); > + if (!driver_data->irq_node) > + return -ENOENT; [Severity: Medium] What happens in altera_timeout_bridge_probe() when CONFIG_SYSFS=n? In drivers/bus/Kconfig, config ALTERA_TIMEOUT_BRIDGE depends only on OF && HAS_IOMEM. When CONFIG_SYSFS=n, devm_device_add_group() succeeds as a stub while dev->kobj.sd remains NULL. Calling sysfs_get_dirent(dev->kobj.sd, "last_timeout_address") then passes a NULL parent into kernfs_find_and_get_ns(): altera_timeout_bridge_probe() sysfs_get_dirent(dev->kobj.sd, "last_timeout_address") kernfs_find_and_get(NULL, "last_timeout_address") kernfs_find_and_get_ns(NULL, "last_timeout_address", NULL) kernfs_root(parent) If CONFIG_KERNFS=y (for instance with CONFIG_CGROUPS=y), kernfs_root(parent) dereferences parent->__parent on a NULL pointer. If CONFIG_KERNFS=n, sysfs_get_dirent() returns NULL and altera_timeout_bridge_probe() fails with -ENOENT before devm_of_platform_populate() can populate the child devices on the bus. > + > + ret = devm_add_action_or_reset(dev, altera_timeout_bridge_put_dirent, > + driver_data->irq_node); > + if (ret) > + return ret; > + > + spin_lock_init(&driver_data->lock); [Severity: High] Can last_timeout_address_show() in drivers/bus/altera-timeout-bridge.c acquire driver_data->lock before spin_lock_init() initializes it? In altera_timeout_bridge_probe(), devm_device_add_group() creates the last_timeout_address sysfs attribute before spin_lock_init(&driver_data->lock) is called. Once the sysfs group is registered, a userspace reader (such as udev) opening and reading last_timeout_address invokes last_timeout_address_show(), which calls spin_lock_irqsave(&driver_data->lock, flags) on an uninitialized spinlock_t (or during error unwind if sysfs_get_dirent() or devm_add_action_or_reset() returns an error). Should spin_lock_init(&driver_data->lock) be called before devm_device_add_group()? [ ... ] > +} > + > +static const struct of_device_id altera_timeout_bridge_of_match[] = { [ ... ] Let's double check everything in the response: all rules followed, plain text, wrapped at 78 characters, ends with a blank line. We are done!commit 2fab3abca0c9e4fa16264b963ed344d58e87a918 Author: Vyacheslav Yurkov <V.Yurkov.EXT@bruker.com> bus: Add Altera AXI Timeout Bridge driver This commit adds a bus driver for the Altera AXI Timeout Bridge that populates child devices behind the bridge and handles timeout interrupts by logging the timed-out address and exposing irq_count and last_timeout_address via sysfs. > diff --git a/MAINTAINERS b/MAINTAINERS > index 7b5cab72d851b..27f7ffd6f0cb2 100644 > --- a/MAINTAINERS > +++ b/MAINTAINERS > @@ -945,6 +945,13 @@ ALPS PS/2 TOUCHPAD DRIVER > R: Pali Rohár <pali@kernel.org> > F: drivers/input/mouse/alps.* > > +ALTERA AXI TIMEOUT BRIDGE DRIVER > +M Vyacheslav Yurkov <V.Yurkov.EXT@bruker.com> [Severity: Low] Should the M tag in MAINTAINERS under ALTERA AXI TIMEOUT BRIDGE DRIVER have a colon after M ("M:") so scripts/parse-maintainers.pl and scripts/get_maintainer.pl can parse the entry without failing? > +S: Maintained > +F: Documentation/ABI/testing/sysfs-driver-altera-timeout-bridge > +F: Documentation/devicetree/bindings/bus/altr,axi-timeout-bridge-1.0.yaml > +F: drivers/bus/altera-timeout-bridge.c > + > ALTERA MAILBOX DRIVER > M: Tien Sung Ang <tiensung.ang@altera.com> > S: Maintained [ ... ] > diff --git a/drivers/bus/altera-timeout-bridge.c b/drivers/bus/altera-timeout-bridge.c > new file mode 100644 > index 0000000000000..87886c3ad7941 > --- /dev/null > +++ b/drivers/bus/altera-timeout-bridge.c > @@ -0,0 +1,173 @@ [ ... ] > +static ssize_t last_timeout_address_show(struct device *dev, struct device_attribute *attr, > + char *buf) > +{ > + struct altera_timeout_bridge_data *driver_data = dev_get_drvdata(dev); > + unsigned long flags; > + u64 addr; > + > + spin_lock_irqsave(&driver_data->lock, flags); > + addr = driver_data->last_timeout_address; > + spin_unlock_irqrestore(&driver_data->lock, flags); > + > + return sysfs_emit(buf, "0x%016llx\n", addr); > +} [ ... ] > +static irqreturn_t altera_timeout_bridge_isr(int irq, void *data) > +{ > + struct altera_timeout_bridge_data *driver_data = data; > + u64 timed_out_address; > + resource_size_t effective_base_address; > + resource_size_t effective_address; > + > + atomic_inc(&driver_data->irq_count); > + > + // Read and print the timed-out address (encoded in the lower nibble > + // 0x8..0xF according to AXI Timeout Bridge IP (CSR Interrupt Status Information) > + timed_out_address = lo_hi_readq(driver_data->bridge_registers + > + ALTERA_TIMEOUT_BRIDGE_REG_TIMED_OUT_ADDRESS_LO); > + effective_base_address = driver_data->bridge_register_resource->start; > + effective_address = effective_base_address + timed_out_address; > + > + spin_lock(&driver_data->lock); > + driver_data->last_timeout_address = effective_address; > + spin_unlock(&driver_data->lock); [Severity: High] Does altera_timeout_bridge_isr() in drivers/bus/altera-timeout-bridge.c compute the wrong physical address and truncate 64-bit addresses on 32-bit platforms? In altera_timeout_bridge_probe(), devm_platform_get_and_ioremap_resource() populates driver_data->bridge_register_resource from reg index 0, which is the bridge's own 16-byte CSR register block rather than the subordinate bus address window described by ranges: Documentation/devicetree/bindings/bus/altr,axi-timeout-bridge-1.0.yaml: reg = <0x10000 0x10>; interrupts = <0 12 IRQ_TYPE_LEVEL_HIGH>; ranges = <0x0 0x10010 0x1000>; timeout-device@100 { compatible = "timeout-device"; reg = <0x100 0x10>; }; Adding driver_data->bridge_register_resource->start to timed_out_address adds the CSR base address (0x10000 in the binding example, yielding 0x10100 instead of 0x10110) rather than translating the subordinate bus address through ranges. In addition, timed_out_address and driver_data->last_timeout_address are u64, whereas effective_base_address and effective_address are resource_size_t. On 32-bit platforms without CONFIG_PHYS_ADDR_T_64BIT (such as arm32 without LPAE), resource_size_t is 32 bits wide, so assigning the sum to effective_address truncates the upper 32 bits before storing into driver_data->last_timeout_address. > + > + dev_err_ratelimited(driver_data->dev, "timeout at address 0x%llx\n", > + (unsigned long long)effective_address); [ ... ] > +static int altera_timeout_bridge_probe(struct platform_device *pdev) > +{ > + struct device *dev = &pdev->dev; > + struct altera_timeout_bridge_data *driver_data; > + int ret; > + int irq; > + > + driver_data = > + devm_kzalloc(&pdev->dev, sizeof(*driver_data), GFP_KERNEL); > + if (!driver_data) > + return -ENOMEM; > + > + driver_data->dev = dev; > + platform_set_drvdata(pdev, driver_data); > + > + driver_data->bridge_registers = > + devm_platform_get_and_ioremap_resource(pdev, 0, > + &driver_data->bridge_register_resource); > + if (IS_ERR(driver_data->bridge_registers)) > + return PTR_ERR(driver_data->bridge_registers); > + > + ret = devm_device_add_group(dev, &altera_timeout_bridge_sysfs_group); > + if (ret) > + return ret; > + > + driver_data->irq_node = sysfs_get_dirent(dev->kobj.sd, "last_timeout_address"); > + if (!driver_data->irq_node) > + return -ENOENT; [Severity: Medium] What happens in altera_timeout_bridge_probe() when CONFIG_SYSFS=n? In drivers/bus/Kconfig, config ALTERA_TIMEOUT_BRIDGE depends only on OF && HAS_IOMEM. When CONFIG_SYSFS=n, devm_device_add_group() succeeds as a stub while dev->kobj.sd remains NULL. Calling sysfs_get_dirent(dev->kobj.sd, "last_timeout_address") then passes a NULL parent into kernfs_find_and_get_ns(): altera_timeout_bridge_probe() sysfs_get_dirent(dev->kobj.sd, "last_timeout_address") kernfs_find_and_get(NULL, "last_timeout_address") kernfs_find_and_get_ns(NULL, "last_timeout_address", NULL) kernfs_root(parent) If CONFIG_KERNFS=y (for instance with CONFIG_CGROUPS=y), kernfs_root(parent) dereferences parent->__parent on a NULL pointer. If CONFIG_KERNFS=n, sysfs_get_dirent() returns NULL and altera_timeout_bridge_probe() fails with -ENOENT before devm_of_platform_populate() can populate the child devices on the bus. > + > + ret = devm_add_action_or_reset(dev, altera_timeout_bridge_put_dirent, > + driver_data->irq_node); > + if (ret) > + return ret; > + > + spin_lock_init(&driver_data->lock); [Severity: High] Can last_timeout_address_show() in drivers/bus/altera-timeout-bridge.c acquire driver_data->lock before spin_lock_init() initializes it? In altera_timeout_bridge_probe(), devm_device_add_group() creates the last_timeout_address sysfs attribute before spin_lock_init(&driver_data->lock) is called. Once the sysfs group is registered, a userspace reader (such as udev) opening and reading last_timeout_address invokes last_timeout_address_show(), which calls spin_lock_irqsave(&driver_data->lock, flags) on an uninitialized spinlock_t (or during error unwind if sysfs_get_dirent() or devm_add_action_or_reset() returns an error). Should spin_lock_init(&driver_data->lock) be called before devm_device_add_group()? [ ... ] > +} > + > +static const struct of_device_id altera_timeout_bridge_of_match[] = { [ ... ] -- Sashiko AI review · https://sashiko.dev/#/patchset/20261021-feature-timeout-ip-v2-0-a037be089518@bruker.com?part=2 ^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2026-10-22 2:29 UTC | newest] Thread overview: 6+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-10-21 19:56 [PATCH v2 0/2] Add Altera timeout bridge driver Vyacheslav Yurkov via B4 Relay 2026-10-21 19:56 ` [PATCH v2 1/2] dt-bindings: bus: Add Altera AXI Timeout Bridge Vyacheslav Yurkov via B4 Relay 2026-10-21 20:05 ` sashiko-bot 2026-10-22 2:29 ` Rob Herring (Arm) 2026-10-21 19:56 ` [PATCH v2 2/2] bus: Add Altera AXI Timeout Bridge driver Vyacheslav Yurkov via B4 Relay 2026-10-21 20:11 ` sashiko-bot
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox