* [PATCH RFC 01/11] ACPI: irq: Return -EPROBE_DEFER on missing IRQ domain
2026-09-25 7:47 [PATCH RFC 00/11] ACPI: ARM64: Implement IRQ mapping probe deferral for static table devices Lorenzo Pieralisi
@ 2026-09-25 7:48 ` Lorenzo Pieralisi
2026-09-25 9:45 ` Andy Shevchenko
2026-09-25 7:48 ` [PATCH RFC 02/11] ACPI: Introduce irq_get() for static fwnodes Lorenzo Pieralisi
` (9 subsequent siblings)
10 siblings, 1 reply; 21+ messages in thread
From: Lorenzo Pieralisi @ 2026-09-25 7:48 UTC (permalink / raw)
To: Rafael J. Wysocki, Mark Rutland, Marc Zyngier, Daniel Lezcano,
Thomas Gleixner, Greg Kroah-Hartman, Danilo Krummrich,
Hanjun Guo, Sudeep Holla, Wim Van Sebroeck, Guenter Roeck,
Robin Murphy, Catalin Marinas, Will Deacon, Bartosz Golaszewski,
Andy Shevchenko
Cc: linux-acpi, linux-kernel, linux-arm-kernel, driver-core,
linux-watchdog, Lorenzo Pieralisi
acpi_register_gsi() might fail if the IRQ domain a GSI belongs to has
not been registered yet by the respective interrupt controller driver.
Return -EPROBE_DEFER in this case so that the mapping can be retried
later by deferring the probe for the driver that requested the IRQ
mapping.
Signed-off-by: Lorenzo Pieralisi <lpieralisi@kernel.org>
Cc: "Rafael J. Wysocki" <rafael@kernel.org>
Cc: Marc Zyngier <maz@kernel.org>
---
drivers/acpi/irq.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/drivers/acpi/irq.c b/drivers/acpi/irq.c
index e4293458bf61..d1f1938c83bf 100644
--- a/drivers/acpi/irq.c
+++ b/drivers/acpi/irq.c
@@ -52,11 +52,13 @@ EXPORT_SYMBOL_GPL(acpi_gsi_to_irq);
* @polarity: polarity of the GSI to be mapped
*
* Returns: a valid linux IRQ number on success
+ * -EPROBE_DEFER when the domain was not yet registered
* -EINVAL on failure
*/
int acpi_register_gsi(struct device *dev, u32 gsi, int trigger,
int polarity)
{
+ struct irq_domain *domain;
struct irq_fwspec fwspec;
unsigned int irq;
@@ -66,6 +68,10 @@ int acpi_register_gsi(struct device *dev, u32 gsi, int trigger,
return -EINVAL;
}
+ domain = irq_find_matching_fwnode(fwspec.fwnode, DOMAIN_BUS_ANY);
+ if (!domain)
+ return -EPROBE_DEFER;
+
fwspec.param[0] = gsi;
fwspec.param[1] = acpi_dev_get_irq_type(trigger, polarity);
fwspec.param_count = 2;
--
2.54.0
^ permalink raw reply [flat|nested] 21+ messages in thread* Re: [PATCH RFC 01/11] ACPI: irq: Return -EPROBE_DEFER on missing IRQ domain
2026-09-25 7:48 ` [PATCH RFC 01/11] ACPI: irq: Return -EPROBE_DEFER on missing IRQ domain Lorenzo Pieralisi
@ 2026-09-25 9:45 ` Andy Shevchenko
0 siblings, 0 replies; 21+ messages in thread
From: Andy Shevchenko @ 2026-09-25 9:45 UTC (permalink / raw)
To: Lorenzo Pieralisi
Cc: Rafael J. Wysocki, Mark Rutland, Marc Zyngier, Daniel Lezcano,
Thomas Gleixner, Greg Kroah-Hartman, Danilo Krummrich,
Hanjun Guo, Sudeep Holla, Wim Van Sebroeck, Guenter Roeck,
Robin Murphy, Catalin Marinas, Will Deacon, Bartosz Golaszewski,
linux-acpi, linux-kernel, linux-arm-kernel, driver-core,
linux-watchdog
On Fri, Sep 25, 2026 at 09:48:00AM +0200, Lorenzo Pieralisi wrote:
> acpi_register_gsi() might fail if the IRQ domain a GSI belongs to has
> not been registered yet by the respective interrupt controller driver.
>
> Return -EPROBE_DEFER in this case so that the mapping can be retried
> later by deferring the probe for the driver that requested the IRQ
> mapping.
>
> Signed-off-by: Lorenzo Pieralisi <lpieralisi@kernel.org>
> Cc: "Rafael J. Wysocki" <rafael@kernel.org>
> Cc: Marc Zyngier <maz@kernel.org>
You may keep the Cc list under the '---' cutter, so this noise won't make
the commit message. The email will be still send to the respective people
and someone can harvest it in the lore archive if needed in the future
(when commit gets accepted).
Note, you may keep that part in your local Git tree (in the commit message)
and handle with `b4 trailers`.
> ---
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH RFC 02/11] ACPI: Introduce irq_get() for static fwnodes
2026-09-25 7:47 [PATCH RFC 00/11] ACPI: ARM64: Implement IRQ mapping probe deferral for static table devices Lorenzo Pieralisi
2026-09-25 7:48 ` [PATCH RFC 01/11] ACPI: irq: Return -EPROBE_DEFER on missing IRQ domain Lorenzo Pieralisi
@ 2026-09-25 7:48 ` Lorenzo Pieralisi
2026-09-25 9:49 ` Andy Shevchenko
2026-09-25 7:48 ` [PATCH RFC 03/11] driver core: platform: Add static ACPI nodes IRQ retrieval/mapping code Lorenzo Pieralisi
` (8 subsequent siblings)
10 siblings, 1 reply; 21+ messages in thread
From: Lorenzo Pieralisi @ 2026-09-25 7:48 UTC (permalink / raw)
To: Rafael J. Wysocki, Mark Rutland, Marc Zyngier, Daniel Lezcano,
Thomas Gleixner, Greg Kroah-Hartman, Danilo Krummrich,
Hanjun Guo, Sudeep Holla, Wim Van Sebroeck, Guenter Roeck,
Robin Murphy, Catalin Marinas, Will Deacon, Bartosz Golaszewski,
Andy Shevchenko
Cc: linux-acpi, linux-kernel, linux-arm-kernel, driver-core,
linux-watchdog, Lorenzo Pieralisi
To describe and map GSIs for firmware nodes created out of ACPI static
table entries in a uniform way it is required to define some standard
properties and attach them to ACPI static fwnode as secondary nodes.
Define properties names to describe GSIs and their trigger-mode/polarity,
and implement an irq_get() callback for static fwnodes so that core code
can retrieve and map IRQs for ACPI static fwnodes in standard manner.
An empty stub for property_read_string_array() is also added, so that
the fwnode_irq_get_byname() interface falls back (through
fwnode_property_read_string_array()) to the secondary
fwnode to grab the "interrupt-names" property.
Signed-off-by: Lorenzo Pieralisi <lpieralisi@kernel.org>
Cc: Bartosz Golaszewski <brgl@kernel.org>
Cc: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Cc: "Rafael J. Wysocki" <rafael@kernel.org>
---
drivers/acpi/property.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++++-
include/linux/acpi.h | 4 +++
2 files changed, 72 insertions(+), 1 deletion(-)
diff --git a/drivers/acpi/property.c b/drivers/acpi/property.c
index 8ee5a1f0eb48..c609100c08db 100644
--- a/drivers/acpi/property.c
+++ b/drivers/acpi/property.c
@@ -1766,7 +1766,74 @@ static int acpi_fwnode_irq_get(const struct fwnode_handle *fwnode,
DECLARE_ACPI_FWNODE_OPS(acpi_device_fwnode_ops);
DECLARE_ACPI_FWNODE_OPS(acpi_data_fwnode_ops);
-const struct fwnode_operations acpi_static_fwnode_ops;
+
+static int acpi_static_fwnode_read_u32_prop_index(const struct fwnode_handle *fwnode,
+ const char *propname,
+ unsigned int index, u32 *value)
+{
+ u32 *values;
+ int ret, count;
+
+ count = fwnode_property_count_u32(fwnode, propname);
+ if (count < 0)
+ return count;
+
+ if (index >= count)
+ return -ENOENT;
+
+ values = kcalloc(count, sizeof(*values), GFP_KERNEL);
+ if (!values)
+ return -ENOMEM;
+
+ ret = fwnode_property_read_u32_array(fwnode, propname, values, count);
+ if (!ret)
+ *value = values[index];
+
+ kfree(values);
+ return ret;
+}
+
+static int acpi_static_fwnode_read_string_array(const struct fwnode_handle *fwnode,
+ const char *propname,
+ const char **val, size_t nval)
+{
+ /* Route string handling to secondary software nodes */
+ return -EINVAL;
+}
+
+static int acpi_static_fwnode_irq_get(const struct fwnode_handle *fwnode,
+ unsigned int index)
+{
+ u32 gsi, trigger, polarity;
+ int ret;
+
+ if (!fwnode->secondary)
+ return -ENODEV;
+
+ fwnode = fwnode->secondary;
+
+ ret = acpi_static_fwnode_read_u32_prop_index(fwnode, ACPI_IRQ_PROP_GSI,
+ index, &gsi);
+ if (ret)
+ return ret == -ENOENT ? -ENXIO : ret;
+
+ ret = acpi_static_fwnode_read_u32_prop_index(fwnode, ACPI_IRQ_PROP_GSI_TRIGGER,
+ index, &trigger);
+ if (ret)
+ return ret == -ENOENT ? -ENXIO : ret;
+
+ ret = acpi_static_fwnode_read_u32_prop_index(fwnode, ACPI_IRQ_PROP_GSI_POLARITY,
+ index, &polarity);
+ if (ret)
+ return ret == -ENOENT ? -ENXIO : ret;
+
+ return acpi_register_gsi(NULL, gsi, trigger, polarity);
+}
+
+const struct fwnode_operations acpi_static_fwnode_ops = {
+ .property_read_string_array = acpi_static_fwnode_read_string_array,
+ .irq_get = acpi_static_fwnode_irq_get,
+};
bool is_acpi_device_node(const struct fwnode_handle *fwnode)
{
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index ddacac812094..749cbbdcad08 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -378,6 +378,10 @@ int acpi_register_gsi (struct device *dev, u32 gsi, int triggering, int polarity
int acpi_gsi_to_irq (u32 gsi, unsigned int *irq);
int acpi_isa_irq_to_gsi (unsigned isa_irq, u32 *gsi);
+#define ACPI_IRQ_PROP_GSI "linux,acpi-gsi"
+#define ACPI_IRQ_PROP_GSI_TRIGGER "linux,acpi-gsi-trigger"
+#define ACPI_IRQ_PROP_GSI_POLARITY "linux,acpi-gsi-polarity"
+
typedef struct fwnode_handle *(*acpi_gsi_domain_disp_fn)(u32);
typedef acpi_handle (*acpi_gsi_handle_disp_fn)(u32);
--
2.54.0
^ permalink raw reply [flat|nested] 21+ messages in thread* Re: [PATCH RFC 02/11] ACPI: Introduce irq_get() for static fwnodes
2026-09-25 7:48 ` [PATCH RFC 02/11] ACPI: Introduce irq_get() for static fwnodes Lorenzo Pieralisi
@ 2026-09-25 9:49 ` Andy Shevchenko
2026-09-25 10:30 ` Lorenzo Pieralisi
0 siblings, 1 reply; 21+ messages in thread
From: Andy Shevchenko @ 2026-09-25 9:49 UTC (permalink / raw)
To: Lorenzo Pieralisi
Cc: Rafael J. Wysocki, Mark Rutland, Marc Zyngier, Daniel Lezcano,
Thomas Gleixner, Greg Kroah-Hartman, Danilo Krummrich,
Hanjun Guo, Sudeep Holla, Wim Van Sebroeck, Guenter Roeck,
Robin Murphy, Catalin Marinas, Will Deacon, Bartosz Golaszewski,
linux-acpi, linux-kernel, linux-arm-kernel, driver-core,
linux-watchdog
On Fri, Sep 25, 2026 at 09:48:01AM +0200, Lorenzo Pieralisi wrote:
> To describe and map GSIs for firmware nodes created out of ACPI static
> table entries in a uniform way it is required to define some standard
> properties and attach them to ACPI static fwnode as secondary nodes.
>
> Define properties names to describe GSIs and their trigger-mode/polarity,
> and implement an irq_get() callback for static fwnodes so that core code
> can retrieve and map IRQs for ACPI static fwnodes in standard manner.
>
> An empty stub for property_read_string_array() is also added, so that
> the fwnode_irq_get_byname() interface falls back (through
> fwnode_property_read_string_array()) to the secondary
> fwnode to grab the "interrupt-names" property.
> Signed-off-by: Lorenzo Pieralisi <lpieralisi@kernel.org>
> Cc: Bartosz Golaszewski <brgl@kernel.org>
> Cc: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
> Cc: "Rafael J. Wysocki" <rafael@kernel.org>
> ---
Same here, please avoid polluting commit message with the Cc list.
...
> +static int acpi_static_fwnode_read_u32_prop_index(const struct fwnode_handle *fwnode,
> + const char *propname,
> + unsigned int index, u32 *value)
> +{
> + u32 *values;
> + int ret, count;
> +
> + count = fwnode_property_count_u32(fwnode, propname);
> + if (count < 0)
> + return count;
> +
> + if (index >= count)
> + return -ENOENT;
> +
> + values = kcalloc(count, sizeof(*values), GFP_KERNEL);
> + if (!values)
> + return -ENOMEM;
> +
> + ret = fwnode_property_read_u32_array(fwnode, propname, values, count);
> + if (!ret)
> + *value = values[index];
Use standard pattern, id est
if (ret)
...
> + kfree(values);
You want to use __free()
> + return ret;
> +}
I believe the whole approach is suboptimal, if you wish get indexed value (but why?)
it needs to be retrieved as that in the guts of ACPI. Allocating memory for the whole
array to retrieve a single element is simply wrong.
...
> +#define ACPI_IRQ_PROP_GSI "linux,acpi-gsi"
> +#define ACPI_IRQ_PROP_GSI_TRIGGER "linux,acpi-gsi-trigger"
> +#define ACPI_IRQ_PROP_GSI_POLARITY "linux,acpi-gsi-polarity"
Oh... This sounds like a big ugly hack.
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply [flat|nested] 21+ messages in thread* Re: [PATCH RFC 02/11] ACPI: Introduce irq_get() for static fwnodes
2026-09-25 9:49 ` Andy Shevchenko
@ 2026-09-25 10:30 ` Lorenzo Pieralisi
2026-09-25 10:54 ` Andy Shevchenko
0 siblings, 1 reply; 21+ messages in thread
From: Lorenzo Pieralisi @ 2026-09-25 10:30 UTC (permalink / raw)
To: Andy Shevchenko
Cc: Rafael J. Wysocki, Mark Rutland, Marc Zyngier, Daniel Lezcano,
Thomas Gleixner, Greg Kroah-Hartman, Danilo Krummrich,
Hanjun Guo, Sudeep Holla, Wim Van Sebroeck, Guenter Roeck,
Robin Murphy, Catalin Marinas, Will Deacon, Bartosz Golaszewski,
linux-acpi, linux-kernel, linux-arm-kernel, driver-core,
linux-watchdog
On Fri, Sep 25, 2026 at 12:49:54PM +0300, Andy Shevchenko wrote:
> On Fri, Sep 25, 2026 at 09:48:01AM +0200, Lorenzo Pieralisi wrote:
> > To describe and map GSIs for firmware nodes created out of ACPI static
> > table entries in a uniform way it is required to define some standard
> > properties and attach them to ACPI static fwnode as secondary nodes.
> >
> > Define properties names to describe GSIs and their trigger-mode/polarity,
> > and implement an irq_get() callback for static fwnodes so that core code
> > can retrieve and map IRQs for ACPI static fwnodes in standard manner.
> >
> > An empty stub for property_read_string_array() is also added, so that
> > the fwnode_irq_get_byname() interface falls back (through
> > fwnode_property_read_string_array()) to the secondary
> > fwnode to grab the "interrupt-names" property.
>
> > Signed-off-by: Lorenzo Pieralisi <lpieralisi@kernel.org>
> > Cc: Bartosz Golaszewski <brgl@kernel.org>
> > Cc: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
> > Cc: "Rafael J. Wysocki" <rafael@kernel.org>
> > ---
>
> Same here, please avoid polluting commit message with the Cc list.
>
> ...
>
> > +static int acpi_static_fwnode_read_u32_prop_index(const struct fwnode_handle *fwnode,
> > + const char *propname,
> > + unsigned int index, u32 *value)
> > +{
> > + u32 *values;
> > + int ret, count;
> > +
> > + count = fwnode_property_count_u32(fwnode, propname);
> > + if (count < 0)
> > + return count;
> > +
> > + if (index >= count)
> > + return -ENOENT;
> > +
> > + values = kcalloc(count, sizeof(*values), GFP_KERNEL);
> > + if (!values)
> > + return -ENOMEM;
> > +
> > + ret = fwnode_property_read_u32_array(fwnode, propname, values, count);
> > + if (!ret)
> > + *value = values[index];
>
> Use standard pattern, id est
>
> if (ret)
> ...
>
> > + kfree(values);
>
> You want to use __free()
>
> > + return ret;
> > +}
>
> I believe the whole approach is suboptimal, if you wish get indexed value (but why?)
Why what (that's what the irq_get() interface requires ?) I agree it is
suboptimal - the whole point of the series is an RFC on using properties
to store GSI number/flags, then how to read them we will optimize it
when/if we agree that's the approach to be taken.
> it needs to be retrieved as that in the guts of ACPI. Allocating memory for the whole
> array to retrieve a single element is simply wrong.
>
> ...
>
> > +#define ACPI_IRQ_PROP_GSI "linux,acpi-gsi"
> > +#define ACPI_IRQ_PROP_GSI_TRIGGER "linux,acpi-gsi-trigger"
> > +#define ACPI_IRQ_PROP_GSI_POLARITY "linux,acpi-gsi-polarity"
>
> Oh... This sounds like a big ugly hack.
That does not help much I am afraid.
What's a ugly hack ? Property names ? Using properties for this purpose ?
Again, it is an RFC for this specific reason and I mentioned that in the
cover letter, thank you for your inputs.
Lorenzo
^ permalink raw reply [flat|nested] 21+ messages in thread* Re: [PATCH RFC 02/11] ACPI: Introduce irq_get() for static fwnodes
2026-09-25 10:30 ` Lorenzo Pieralisi
@ 2026-09-25 10:54 ` Andy Shevchenko
2026-09-25 11:32 ` Lorenzo Pieralisi
0 siblings, 1 reply; 21+ messages in thread
From: Andy Shevchenko @ 2026-09-25 10:54 UTC (permalink / raw)
To: Lorenzo Pieralisi
Cc: Rafael J. Wysocki, Mark Rutland, Marc Zyngier, Daniel Lezcano,
Thomas Gleixner, Greg Kroah-Hartman, Danilo Krummrich,
Hanjun Guo, Sudeep Holla, Wim Van Sebroeck, Guenter Roeck,
Robin Murphy, Catalin Marinas, Will Deacon, Bartosz Golaszewski,
linux-acpi, linux-kernel, linux-arm-kernel, driver-core,
linux-watchdog
On Fri, Sep 25, 2026 at 12:30:07PM +0200, Lorenzo Pieralisi wrote:
> On Fri, Sep 25, 2026 at 12:49:54PM +0300, Andy Shevchenko wrote:
> > On Fri, Sep 25, 2026 at 09:48:01AM +0200, Lorenzo Pieralisi wrote:
...
> > > +static int acpi_static_fwnode_read_u32_prop_index(const struct fwnode_handle *fwnode,
> > > + const char *propname,
> > > + unsigned int index, u32 *value)
> > > +{
> > > + u32 *values;
> > > + int ret, count;
> > > +
> > > + count = fwnode_property_count_u32(fwnode, propname);
> > > + if (count < 0)
> > > + return count;
> > > +
> > > + if (index >= count)
> > > + return -ENOENT;
> > > +
> > > + values = kcalloc(count, sizeof(*values), GFP_KERNEL);
> > > + if (!values)
> > > + return -ENOMEM;
> > > +
> > > + ret = fwnode_property_read_u32_array(fwnode, propname, values, count);
> > > + if (!ret)
> > > + *value = values[index];
> >
> > Use standard pattern, id est
> >
> > if (ret)
> > ...
> >
> > > + kfree(values);
> >
> > You want to use __free()
> >
> > > + return ret;
> > > +}
> >
> > I believe the whole approach is suboptimal, if you wish get indexed value (but why?)
>
> Why what (that's what the irq_get() interface requires ?) I agree it is
> suboptimal - the whole point of the series is an RFC on using properties
> to store GSI number/flags, then how to read them we will optimize it
> when/if we agree that's the approach to be taken.
Why to have indexed APIs. The callers usually do not want a single item from an
array, they want all of them or a big pile (exception is the array of strings,
but we have matching functions for that).
As per approach, this patch is against device property and I don't think we are
going to agree on the approach taken in *this* patch.
> > it needs to be retrieved as that in the guts of ACPI. Allocating memory for the whole
> > array to retrieve a single element is simply wrong.
...
> > > +#define ACPI_IRQ_PROP_GSI "linux,acpi-gsi"
> > > +#define ACPI_IRQ_PROP_GSI_TRIGGER "linux,acpi-gsi-trigger"
> > > +#define ACPI_IRQ_PROP_GSI_POLARITY "linux,acpi-gsi-polarity"
> >
> > Oh... This sounds like a big ugly hack.
>
> That does not help much I am afraid.
>
> What's a ugly hack ? Property names ? Using properties for this purpose ?
Yes, properties started with "linux," for some core functionality.
Yes, using properties for this also doesn't sound right. I think the problem
here is in the table specifications or somewhere that deep. That's why we
ended up in this series.
> Again, it is an RFC for this specific reason and I mentioned that in the
> cover letter, thank you for your inputs.
And here we have a discussion started :-)
P.S. Looks like I was too quick to jump into this thread. I will wait for
others to share their view on all this.
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply [flat|nested] 21+ messages in thread* Re: [PATCH RFC 02/11] ACPI: Introduce irq_get() for static fwnodes
2026-09-25 10:54 ` Andy Shevchenko
@ 2026-09-25 11:32 ` Lorenzo Pieralisi
0 siblings, 0 replies; 21+ messages in thread
From: Lorenzo Pieralisi @ 2026-09-25 11:32 UTC (permalink / raw)
To: Andy Shevchenko
Cc: Rafael J. Wysocki, Mark Rutland, Marc Zyngier, Daniel Lezcano,
Thomas Gleixner, Greg Kroah-Hartman, Danilo Krummrich,
Hanjun Guo, Sudeep Holla, Wim Van Sebroeck, Guenter Roeck,
Robin Murphy, Catalin Marinas, Will Deacon, Bartosz Golaszewski,
linux-acpi, linux-kernel, linux-arm-kernel, driver-core,
linux-watchdog
On Fri, Sep 25, 2026 at 01:54:26PM +0300, Andy Shevchenko wrote:
> On Fri, Sep 25, 2026 at 12:30:07PM +0200, Lorenzo Pieralisi wrote:
> > On Fri, Sep 25, 2026 at 12:49:54PM +0300, Andy Shevchenko wrote:
> > > On Fri, Sep 25, 2026 at 09:48:01AM +0200, Lorenzo Pieralisi wrote:
>
> ...
>
> > > > +static int acpi_static_fwnode_read_u32_prop_index(const struct fwnode_handle *fwnode,
> > > > + const char *propname,
> > > > + unsigned int index, u32 *value)
> > > > +{
> > > > + u32 *values;
> > > > + int ret, count;
> > > > +
> > > > + count = fwnode_property_count_u32(fwnode, propname);
> > > > + if (count < 0)
> > > > + return count;
> > > > +
> > > > + if (index >= count)
> > > > + return -ENOENT;
> > > > +
> > > > + values = kcalloc(count, sizeof(*values), GFP_KERNEL);
> > > > + if (!values)
> > > > + return -ENOMEM;
> > > > +
> > > > + ret = fwnode_property_read_u32_array(fwnode, propname, values, count);
> > > > + if (!ret)
> > > > + *value = values[index];
> > >
> > > Use standard pattern, id est
> > >
> > > if (ret)
> > > ...
> > >
> > > > + kfree(values);
> > >
> > > You want to use __free()
> > >
> > > > + return ret;
> > > > +}
> > >
> > > I believe the whole approach is suboptimal, if you wish get indexed value (but why?)
> >
> > Why what (that's what the irq_get() interface requires ?) I agree it is
> > suboptimal - the whole point of the series is an RFC on using properties
> > to store GSI number/flags, then how to read them we will optimize it
> > when/if we agree that's the approach to be taken.
>
> Why to have indexed APIs. The callers usually do not want a single item from an
> array, they want all of them or a big pile (exception is the array of strings,
> but we have matching functions for that).
>
> As per approach, this patch is against device property and I don't think we are
> going to agree on the approach taken in *this* patch.
>
> > > it needs to be retrieved as that in the guts of ACPI. Allocating memory for the whole
> > > array to retrieve a single element is simply wrong.
>
> ...
>
> > > > +#define ACPI_IRQ_PROP_GSI "linux,acpi-gsi"
> > > > +#define ACPI_IRQ_PROP_GSI_TRIGGER "linux,acpi-gsi-trigger"
> > > > +#define ACPI_IRQ_PROP_GSI_POLARITY "linux,acpi-gsi-polarity"
> > >
> > > Oh... This sounds like a big ugly hack.
> >
> > That does not help much I am afraid.
> >
> > What's a ugly hack ? Property names ? Using properties for this purpose ?
>
> Yes, properties started with "linux," for some core functionality.
I added a name for those out of thin air, again - the question is on
the approch, properties I can call them whatever we like.
I am not a fan of those myself, as mentioned in the cover letter.
> Yes, using properties for this also doesn't sound right. I think the problem
> here is in the table specifications or somewhere that deep. That's why we
> ended up in this series.
>
> > Again, it is an RFC for this specific reason and I mentioned that in the
> > cover letter, thank you for your inputs.
>
> And here we have a discussion started :-)
Thanks !
> P.S. Looks like I was too quick to jump into this thread. I will wait for
> others to share their view on all this.
No, thank you for chiming in so promptly. The main aim is to keep most
of the drivers and API unchanged for a bunch of devices created out of
static tables - ie minimize changes as much as possible, that's the
purpose.
Thanks,
Lorenzo
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH RFC 03/11] driver core: platform: Add static ACPI nodes IRQ retrieval/mapping code
2026-09-25 7:47 [PATCH RFC 00/11] ACPI: ARM64: Implement IRQ mapping probe deferral for static table devices Lorenzo Pieralisi
2026-09-25 7:48 ` [PATCH RFC 01/11] ACPI: irq: Return -EPROBE_DEFER on missing IRQ domain Lorenzo Pieralisi
2026-09-25 7:48 ` [PATCH RFC 02/11] ACPI: Introduce irq_get() for static fwnodes Lorenzo Pieralisi
@ 2026-09-25 7:48 ` Lorenzo Pieralisi
2026-09-25 9:54 ` Andy Shevchenko
2026-09-25 7:48 ` [PATCH RFC 04/11] clocksource/drivers/arm_arch_timer_mmio: Dispose IRQ mappings on probe failure Lorenzo Pieralisi
` (7 subsequent siblings)
10 siblings, 1 reply; 21+ messages in thread
From: Lorenzo Pieralisi @ 2026-09-25 7:48 UTC (permalink / raw)
To: Rafael J. Wysocki, Mark Rutland, Marc Zyngier, Daniel Lezcano,
Thomas Gleixner, Greg Kroah-Hartman, Danilo Krummrich,
Hanjun Guo, Sudeep Holla, Wim Van Sebroeck, Guenter Roeck,
Robin Murphy, Catalin Marinas, Will Deacon, Bartosz Golaszewski,
Andy Shevchenko
Cc: linux-acpi, linux-kernel, linux-arm-kernel, driver-core,
linux-watchdog, Lorenzo Pieralisi
ACPI static fwnodes types are not contemplated in the current
platform_get_irq_affinity()
implementation that is there to retrieve and map IRQs for a device.
Add fwnode_irq_get() to platform_get_irq_affinity() for static ACPI fwnodes
to overcome this shortcoming, enabling IRQ retrieval and mapping for the
ACPI static fwnode type.
Signed-off-by: Lorenzo Pieralisi <lpieralisi@kernel.org>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: "Rafael J. Wysocki" <rafael@kernel.org>
Cc: Danilo Krummrich <dakr@kernel.org>
---
drivers/base/platform.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/drivers/base/platform.c b/drivers/base/platform.c
index 66f9ec73d47e..413c73332308 100644
--- a/drivers/base/platform.c
+++ b/drivers/base/platform.c
@@ -228,6 +228,12 @@ int platform_get_irq_affinity(struct platform_device *dev, unsigned int num,
goto out;
}
+ if (is_acpi_static_node(fwnode)) {
+ ret = fwnode_irq_get(fwnode, num);
+ if (ret > 0 || ret == -EPROBE_DEFER)
+ goto out;
+ }
+
/*
* For the index 0 interrupt, allow falling back to GpioInt
* resources. While a device could have both Interrupt and GpioInt
--
2.54.0
^ permalink raw reply [flat|nested] 21+ messages in thread* Re: [PATCH RFC 03/11] driver core: platform: Add static ACPI nodes IRQ retrieval/mapping code
2026-09-25 7:48 ` [PATCH RFC 03/11] driver core: platform: Add static ACPI nodes IRQ retrieval/mapping code Lorenzo Pieralisi
@ 2026-09-25 9:54 ` Andy Shevchenko
2026-09-25 10:16 ` Lorenzo Pieralisi
0 siblings, 1 reply; 21+ messages in thread
From: Andy Shevchenko @ 2026-09-25 9:54 UTC (permalink / raw)
To: Lorenzo Pieralisi
Cc: Rafael J. Wysocki, Mark Rutland, Marc Zyngier, Daniel Lezcano,
Thomas Gleixner, Greg Kroah-Hartman, Danilo Krummrich,
Hanjun Guo, Sudeep Holla, Wim Van Sebroeck, Guenter Roeck,
Robin Murphy, Catalin Marinas, Will Deacon, Bartosz Golaszewski,
linux-acpi, linux-kernel, linux-arm-kernel, driver-core,
linux-watchdog
On Fri, Sep 25, 2026 at 09:48:02AM +0200, Lorenzo Pieralisi wrote:
> ACPI static fwnodes types are not contemplated in the current
>
> platform_get_irq_affinity()
>
> implementation that is there to retrieve and map IRQs for a device.
>
> Add fwnode_irq_get() to platform_get_irq_affinity() for static ACPI fwnodes
> to overcome this shortcoming, enabling IRQ retrieval and mapping for the
> ACPI static fwnode type.
>
> Signed-off-by: Lorenzo Pieralisi <lpieralisi@kernel.org>
> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> Cc: "Rafael J. Wysocki" <rafael@kernel.org>
> Cc: Danilo Krummrich <dakr@kernel.org>
> ---
Same about the Cc list...
...
> + if (is_acpi_static_node(fwnode)) {
> + ret = fwnode_irq_get(fwnode, num);
> + if (ret > 0 || ret == -EPROBE_DEFER)
> + goto out;
> + }
This even doesn't sound right. If you know this is an ACPI-only feature what
the fwnode has all to do with it? Call the respective ACPI-oriented function.
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply [flat|nested] 21+ messages in thread* Re: [PATCH RFC 03/11] driver core: platform: Add static ACPI nodes IRQ retrieval/mapping code
2026-09-25 9:54 ` Andy Shevchenko
@ 2026-09-25 10:16 ` Lorenzo Pieralisi
0 siblings, 0 replies; 21+ messages in thread
From: Lorenzo Pieralisi @ 2026-09-25 10:16 UTC (permalink / raw)
To: Andy Shevchenko
Cc: Rafael J. Wysocki, Mark Rutland, Marc Zyngier, Daniel Lezcano,
Thomas Gleixner, Greg Kroah-Hartman, Danilo Krummrich,
Hanjun Guo, Sudeep Holla, Wim Van Sebroeck, Guenter Roeck,
Robin Murphy, Catalin Marinas, Will Deacon, Bartosz Golaszewski,
linux-acpi, linux-kernel, linux-arm-kernel, driver-core,
linux-watchdog
On Fri, Sep 25, 2026 at 12:54:15PM +0300, Andy Shevchenko wrote:
> On Fri, Sep 25, 2026 at 09:48:02AM +0200, Lorenzo Pieralisi wrote:
> > ACPI static fwnodes types are not contemplated in the current
> >
> > platform_get_irq_affinity()
> >
> > implementation that is there to retrieve and map IRQs for a device.
> >
> > Add fwnode_irq_get() to platform_get_irq_affinity() for static ACPI fwnodes
> > to overcome this shortcoming, enabling IRQ retrieval and mapping for the
> > ACPI static fwnode type.
> >
> > Signed-off-by: Lorenzo Pieralisi <lpieralisi@kernel.org>
> > Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> > Cc: "Rafael J. Wysocki" <rafael@kernel.org>
> > Cc: Danilo Krummrich <dakr@kernel.org>
> > ---
>
> Same about the Cc list...
>
> ...
>
> > + if (is_acpi_static_node(fwnode)) {
> > + ret = fwnode_irq_get(fwnode, num);
> > + if (ret > 0 || ret == -EPROBE_DEFER)
> > + goto out;
> > + }
>
> This even doesn't sound right. If you know this is an ACPI-only feature what
> the fwnode has all to do with it? Call the respective ACPI-oriented function.
Yes, you are right, it is a last minute change since I noticed that just
calling fwnode_irq_get() without guards would catch previous failures so
it makes sense to do it on specific fwnode type (with is_acpi_static_node()
exported also for !CONFIG_ACPI).
Thanks,
Lorenzo
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH RFC 04/11] clocksource/drivers/arm_arch_timer_mmio: Dispose IRQ mappings on probe failure
2026-09-25 7:47 [PATCH RFC 00/11] ACPI: ARM64: Implement IRQ mapping probe deferral for static table devices Lorenzo Pieralisi
` (2 preceding siblings ...)
2026-09-25 7:48 ` [PATCH RFC 03/11] driver core: platform: Add static ACPI nodes IRQ retrieval/mapping code Lorenzo Pieralisi
@ 2026-09-25 7:48 ` Lorenzo Pieralisi
2026-09-25 9:52 ` Andy Shevchenko
2026-09-25 7:48 ` [PATCH RFC 05/11] clocksource/drivers/arm_arch_timer_mmio: Implement arch mem timer deferred probe Lorenzo Pieralisi
` (6 subsequent siblings)
10 siblings, 1 reply; 21+ messages in thread
From: Lorenzo Pieralisi @ 2026-09-25 7:48 UTC (permalink / raw)
To: Rafael J. Wysocki, Mark Rutland, Marc Zyngier, Daniel Lezcano,
Thomas Gleixner, Greg Kroah-Hartman, Danilo Krummrich,
Hanjun Guo, Sudeep Holla, Wim Van Sebroeck, Guenter Roeck,
Robin Murphy, Catalin Marinas, Will Deacon, Bartosz Golaszewski,
Andy Shevchenko
Cc: linux-acpi, linux-kernel, linux-arm-kernel, driver-core,
linux-watchdog, Lorenzo Pieralisi
On probe failure the driver does not dispose the IRQ mappings that
were carried out before the probe function hit an error condition.
Add code to dispose the IRQ mappings on driver probe failure.
Signed-off-by: Lorenzo Pieralisi <lpieralisi@kernel.org>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Marc Zyngier <maz@kernel.org>
---
drivers/clocksource/arm_arch_timer_mmio.c | 29 +++++++++++++++++++++++++++++
1 file changed, 29 insertions(+)
diff --git a/drivers/clocksource/arm_arch_timer_mmio.c b/drivers/clocksource/arm_arch_timer_mmio.c
index d678f764d3bb..c3f2fe39bdd2 100644
--- a/drivers/clocksource/arm_arch_timer_mmio.c
+++ b/drivers/clocksource/arm_arch_timer_mmio.c
@@ -191,6 +191,34 @@ static irqreturn_t arch_timer_mmio_handler(int irq, void *dev_id)
return IRQ_NONE;
}
+static void arch_timer_mmio_unmap_irq(int *irq)
+{
+ if (irq && *irq) {
+ irq_dispose_mapping(*irq);
+ *irq = 0;
+ }
+}
+
+static void arch_timer_mmio_unmap_frame_irqs(struct arch_timer_mem_frame *frame)
+{
+ arch_timer_mmio_unmap_irq(&frame->phys_irq);
+ arch_timer_mmio_unmap_irq(&frame->virt_irq);
+}
+
+static void arch_timer_mmio_unmap_irqs(struct arch_timer_mem *gt_block)
+{
+ int i;
+
+ for (i = 0; i < ARCH_TIMER_MEM_MAX_FRAMES; i++) {
+ struct arch_timer_mem_frame *frame = >_block->frame[i];
+
+ if (!frame->valid)
+ continue;
+
+ arch_timer_mmio_unmap_frame_irqs(frame);
+ }
+}
+
static struct arch_timer_mem_frame *find_best_frame(struct platform_device *pdev)
{
struct arch_timer_mem_frame *frame, *best_frame = NULL;
@@ -398,6 +426,7 @@ static int arch_timer_mmio_probe(struct platform_device *pdev)
frame = find_best_frame(pdev);
if (!frame) {
+ arch_timer_mmio_unmap_irqs(at->gt_block);
dev_err(&pdev->dev,
"Unable to find a suitable frame in timer @ %pa\n",
&at->gt_block->cntctlbase);
--
2.54.0
^ permalink raw reply [flat|nested] 21+ messages in thread* Re: [PATCH RFC 04/11] clocksource/drivers/arm_arch_timer_mmio: Dispose IRQ mappings on probe failure
2026-09-25 7:48 ` [PATCH RFC 04/11] clocksource/drivers/arm_arch_timer_mmio: Dispose IRQ mappings on probe failure Lorenzo Pieralisi
@ 2026-09-25 9:52 ` Andy Shevchenko
0 siblings, 0 replies; 21+ messages in thread
From: Andy Shevchenko @ 2026-09-25 9:52 UTC (permalink / raw)
To: Lorenzo Pieralisi
Cc: Rafael J. Wysocki, Mark Rutland, Marc Zyngier, Daniel Lezcano,
Thomas Gleixner, Greg Kroah-Hartman, Danilo Krummrich,
Hanjun Guo, Sudeep Holla, Wim Van Sebroeck, Guenter Roeck,
Robin Murphy, Catalin Marinas, Will Deacon, Bartosz Golaszewski,
linux-acpi, linux-kernel, linux-arm-kernel, driver-core,
linux-watchdog
On Fri, Sep 25, 2026 at 09:48:03AM +0200, Lorenzo Pieralisi wrote:
> On probe failure the driver does not dispose the IRQ mappings that
> were carried out before the probe function hit an error condition.
>
> Add code to dispose the IRQ mappings on driver probe failure.
> Signed-off-by: Lorenzo Pieralisi <lpieralisi@kernel.org>
> Cc: Mark Rutland <mark.rutland@arm.com>
> Cc: Marc Zyngier <maz@kernel.org>
> ---
Same here about Cc list...
...
> +static void arch_timer_mmio_unmap_irq(int *irq)
> +{
> + if (irq && *irq) {
Would be better to read and maintain with the negative check.
> + irq_dispose_mapping(*irq);
> + *irq = 0;
> + }
> +}
...
> +static void arch_timer_mmio_unmap_irqs(struct arch_timer_mem *gt_block)
> +{
> + int i;
Why signed?
> + for (i = 0; i < ARCH_TIMER_MEM_MAX_FRAMES; i++) {
for (unsigned int i = 0; i < ARCH_TIMER_MEM_MAX_FRAMES; i++) {
> + struct arch_timer_mem_frame *frame = >_block->frame[i];
> +
> + if (!frame->valid)
> + continue;
> +
> + arch_timer_mmio_unmap_frame_irqs(frame);
> + }
> +}
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH RFC 05/11] clocksource/drivers/arm_arch_timer_mmio: Implement arch mem timer deferred probe
2026-09-25 7:47 [PATCH RFC 00/11] ACPI: ARM64: Implement IRQ mapping probe deferral for static table devices Lorenzo Pieralisi
` (3 preceding siblings ...)
2026-09-25 7:48 ` [PATCH RFC 04/11] clocksource/drivers/arm_arch_timer_mmio: Dispose IRQ mappings on probe failure Lorenzo Pieralisi
@ 2026-09-25 7:48 ` Lorenzo Pieralisi
2026-09-25 7:48 ` [PATCH RFC 06/11] ACPI: GTDT: Convert SBSA watchdog to IRQ properties Lorenzo Pieralisi
` (5 subsequent siblings)
10 siblings, 0 replies; 21+ messages in thread
From: Lorenzo Pieralisi @ 2026-09-25 7:48 UTC (permalink / raw)
To: Rafael J. Wysocki, Mark Rutland, Marc Zyngier, Daniel Lezcano,
Thomas Gleixner, Greg Kroah-Hartman, Danilo Krummrich,
Hanjun Guo, Sudeep Holla, Wim Van Sebroeck, Guenter Roeck,
Robin Murphy, Catalin Marinas, Will Deacon, Bartosz Golaszewski,
Andy Shevchenko
Cc: linux-acpi, linux-kernel, linux-arm-kernel, driver-core,
linux-watchdog, Lorenzo Pieralisi
Resolving the arch mem timer IRQ on ACPI systems might require
two-steps if the IRQ is wired to an interrupt controller whose
driver has not probed yet at the time the IRQ mapping is carried
out through acpi_register_gsi(), which would result in an
-EPROBE_DEFER return value that in turn should trigger a
driver probe deferral.
Instead of trying to map an IRQ when the arch mem timer device is
created, stash the GSIs number and flag values in the arch_timer_mem_frame
data structure and use it at driver probe time to map the GSIs.
Add -EPROBE_DEFER handling to the arch mem timer driver so
that it can cope with GSIs that are routed to interrupt controllers
whose driver has not yet probed at the time acpi_register_gsi() is
invoked.
Signed-off-by: Lorenzo Pieralisi <lpieralisi@kernel.org>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Marc Zyngier <maz@kernel.org>
---
drivers/acpi/arm64/gtdt.c | 27 +++------
drivers/clocksource/arm_arch_timer_mmio.c | 94 +++++++++++++++++++++++++++++++
include/clocksource/arm_arch_timer.h | 4 ++
3 files changed, 106 insertions(+), 19 deletions(-)
diff --git a/drivers/acpi/arm64/gtdt.c b/drivers/acpi/arm64/gtdt.c
index 00158c8aa6d9..d7248684b2c5 100644
--- a/drivers/acpi/arm64/gtdt.c
+++ b/drivers/acpi/arm64/gtdt.c
@@ -287,23 +287,12 @@ static int __init gtdt_parse_timer_block(struct acpi_gtdt_timer_block *block,
if (frame->valid)
goto error;
- frame->phys_irq = map_gt_gsi(gtdt_frame->timer_interrupt,
- gtdt_frame->timer_flags);
- if (frame->phys_irq <= 0) {
- pr_warn("failed to map physical timer irq in frame %d.\n",
- gtdt_frame->frame_number);
- goto error;
- }
+ frame->phys_gsi = gtdt_frame->timer_interrupt;
+ frame->phys_flags = gtdt_frame->timer_flags;
if (gtdt_frame->virtual_timer_interrupt) {
- frame->virt_irq =
- map_gt_gsi(gtdt_frame->virtual_timer_interrupt,
- gtdt_frame->virtual_timer_flags);
- if (frame->virt_irq <= 0) {
- pr_warn("failed to map virtual timer irq in frame %d.\n",
- gtdt_frame->frame_number);
- goto error;
- }
+ frame->virt_gsi = gtdt_frame->virtual_timer_interrupt;
+ frame->virt_flags = gtdt_frame->virtual_timer_flags;
} else {
pr_debug("virtual timer in frame %d not implemented.\n",
gtdt_frame->frame_number);
@@ -329,12 +318,12 @@ static int __init gtdt_parse_timer_block(struct acpi_gtdt_timer_block *block,
frame = &timer_mem->frame[gtdt_frame->frame_number];
- if (frame->phys_irq > 0)
- acpi_unregister_gsi(gtdt_frame->timer_interrupt);
+ frame->phys_gsi = 0;
+ frame->phys_flags = 0;
frame->phys_irq = 0;
- if (frame->virt_irq > 0)
- acpi_unregister_gsi(gtdt_frame->virtual_timer_interrupt);
+ frame->virt_gsi = 0;
+ frame->virt_flags = 0;
frame->virt_irq = 0;
} while (i-- > 0 && gtdt_frame--);
diff --git a/drivers/clocksource/arm_arch_timer_mmio.c b/drivers/clocksource/arm_arch_timer_mmio.c
index c3f2fe39bdd2..cfa819687e68 100644
--- a/drivers/clocksource/arm_arch_timer_mmio.c
+++ b/drivers/clocksource/arm_arch_timer_mmio.c
@@ -10,6 +10,7 @@
#define pr_fmt(fmt) "arch_timer_mmio: " fmt
+#include <linux/acpi.h>
#include <linux/clockchips.h>
#include <linux/interrupt.h>
#include <linux/io-64-nonatomic-lo-hi.h>
@@ -205,6 +206,96 @@ static void arch_timer_mmio_unmap_frame_irqs(struct arch_timer_mem_frame *frame)
arch_timer_mmio_unmap_irq(&frame->virt_irq);
}
+#ifdef CONFIG_ACPI
+static int arch_timer_mmio_map_gsi(struct platform_device *pdev, u32 gsi,
+ u32 flags, int *irq)
+{
+ int trigger, polarity, ret;
+
+ if (!gsi || *irq)
+ return 0;
+
+ trigger = (flags & ACPI_GTDT_INTERRUPT_MODE) ? ACPI_EDGE_SENSITIVE
+ : ACPI_LEVEL_SENSITIVE;
+ polarity = (flags & ACPI_GTDT_INTERRUPT_POLARITY) ? ACPI_ACTIVE_LOW
+ : ACPI_ACTIVE_HIGH;
+
+ ret = acpi_register_gsi(&pdev->dev, gsi, trigger, polarity);
+ if (ret < 0)
+ return ret;
+
+ *irq = ret;
+
+ return 0;
+}
+
+static int arch_timer_mmio_map_frame_gsis(struct platform_device *pdev,
+ struct arch_timer_mem_frame *frame)
+{
+ int ret;
+
+ ret = arch_timer_mmio_map_gsi(pdev, frame->phys_gsi, frame->phys_flags, &frame->phys_irq);
+ if (ret < 0) {
+ if (ret == -EPROBE_DEFER)
+ return ret;
+
+ dev_err(&pdev->dev,
+ "Failed to map physical timer GSI %u for frame @ %pa: %d\n",
+ frame->phys_gsi, &frame->cntbase, ret);
+ return ret;
+ }
+
+ ret = arch_timer_mmio_map_gsi(pdev, frame->virt_gsi, frame->virt_flags, &frame->virt_irq);
+ if (ret < 0) {
+ if (ret != -EPROBE_DEFER)
+ dev_err(&pdev->dev,
+ "Failed to map virtual timer GSI %u for frame @ %pa: %d\n",
+ frame->virt_gsi, &frame->cntbase, ret);
+ arch_timer_mmio_unmap_irq(&frame->phys_irq);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int arch_timer_mmio_map_gsis(struct platform_device *pdev,
+ struct arch_timer_mem *gt_block)
+{
+ int i, ret;
+
+ for (i = 0; i < ARCH_TIMER_MEM_MAX_FRAMES; i++) {
+ struct arch_timer_mem_frame *frame = >_block->frame[i];
+
+ if (!frame->valid)
+ continue;
+
+ ret = arch_timer_mmio_map_frame_gsis(pdev, frame);
+ if (ret < 0)
+ goto unmap_err;
+ }
+
+ return 0;
+
+unmap_err:
+ for (i--; i >= 0; i--) {
+ struct arch_timer_mem_frame *frame = >_block->frame[i];
+
+ if (!frame->valid)
+ continue;
+
+ arch_timer_mmio_unmap_frame_irqs(frame);
+ }
+
+ return ret;
+}
+#else
+static inline int arch_timer_mmio_map_gsis(struct platform_device *pdev,
+ struct arch_timer_mem *gt_block)
+{
+ return -ENODEV;
+}
+#endif
+
static void arch_timer_mmio_unmap_irqs(struct arch_timer_mem *gt_block)
{
int i;
@@ -420,6 +511,9 @@ static int arch_timer_mmio_probe(struct platform_device *pdev)
return ret;
} else {
at->gt_block = dev_get_platdata(&pdev->dev);
+ ret = arch_timer_mmio_map_gsis(pdev, at->gt_block);
+ if (ret)
+ return ret;
}
platform_set_drvdata(pdev, at);
diff --git a/include/clocksource/arm_arch_timer.h b/include/clocksource/arm_arch_timer.h
index 2eda895f19f5..c14741519899 100644
--- a/include/clocksource/arm_arch_timer.h
+++ b/include/clocksource/arm_arch_timer.h
@@ -76,6 +76,10 @@ struct arch_timer_mem_frame {
size_t size;
int phys_irq;
int virt_irq;
+ u32 phys_gsi;
+ u32 phys_flags;
+ u32 virt_gsi;
+ u32 virt_flags;
};
struct arch_timer_mem {
--
2.54.0
^ permalink raw reply [flat|nested] 21+ messages in thread* [PATCH RFC 06/11] ACPI: GTDT: Convert SBSA watchdog to IRQ properties
2026-09-25 7:47 [PATCH RFC 00/11] ACPI: ARM64: Implement IRQ mapping probe deferral for static table devices Lorenzo Pieralisi
` (4 preceding siblings ...)
2026-09-25 7:48 ` [PATCH RFC 05/11] clocksource/drivers/arm_arch_timer_mmio: Implement arch mem timer deferred probe Lorenzo Pieralisi
@ 2026-09-25 7:48 ` Lorenzo Pieralisi
2026-09-25 9:56 ` Andy Shevchenko
2026-09-25 7:48 ` [PATCH RFC 07/11] ACPI/IORT: Convert IORT devices to IRQs software-node properties Lorenzo Pieralisi
` (4 subsequent siblings)
10 siblings, 1 reply; 21+ messages in thread
From: Lorenzo Pieralisi @ 2026-09-25 7:48 UTC (permalink / raw)
To: Rafael J. Wysocki, Mark Rutland, Marc Zyngier, Daniel Lezcano,
Thomas Gleixner, Greg Kroah-Hartman, Danilo Krummrich,
Hanjun Guo, Sudeep Holla, Wim Van Sebroeck, Guenter Roeck,
Robin Murphy, Catalin Marinas, Will Deacon, Bartosz Golaszewski,
Andy Shevchenko
Cc: linux-acpi, linux-kernel, linux-arm-kernel, driver-core,
linux-watchdog, Lorenzo Pieralisi
SBSA watchdog IRQs might be wired to interrupt controllers that are
probed after the SBSA watchdog is probed and therefore the IRQ mappings
cannot be carried out at platform device creation but deferred to
SBSA watchdog probing through the platform_get_irq*() set of APIs.
To do that, stash the GSI number, trigger, polarity into standard
properties attached to a software node that is attached to the
platform device ACPI static fwnode, allowing the SBSA driver to
retrieve those properties and map the IRQ when the SBSA driver
is probed.
Signed-off-by: Lorenzo Pieralisi <lpieralisi@kernel.org>
Cc: Hanjun Guo <guohanjun@huawei.com>
Cc: Sudeep Holla <sudeep.holla@kernel.org>
Cc: "Rafael J. Wysocki" <rafael@kernel.org>
---
drivers/acpi/arm64/gtdt.c | 63 ++++++++++++++++++++++++++++++++++++-----------
1 file changed, 48 insertions(+), 15 deletions(-)
diff --git a/drivers/acpi/arm64/gtdt.c b/drivers/acpi/arm64/gtdt.c
index d7248684b2c5..8629895d18c2 100644
--- a/drivers/acpi/arm64/gtdt.c
+++ b/drivers/acpi/arm64/gtdt.c
@@ -336,8 +336,11 @@ static int __init gtdt_parse_timer_block(struct acpi_gtdt_timer_block *block,
static int __init gtdt_import_sbsa_gwdt(struct acpi_gtdt_watchdog *wd,
int index)
{
+ struct property_entry props[4] = {};
struct platform_device *pdev;
- int irq;
+ u32 gsi[1], triggering[1], polarity[1];
+ struct fwnode_handle *fwnode;
+ int ret, nr_res = 2;
/*
* According to SBSA specification the size of refresh and control
@@ -346,9 +349,7 @@ static int __init gtdt_import_sbsa_gwdt(struct acpi_gtdt_watchdog *wd,
struct resource res[] = {
DEFINE_RES_MEM(wd->control_frame_address, SZ_4K),
DEFINE_RES_MEM(wd->refresh_frame_address, SZ_4K),
- {},
};
- int nr_res = ARRAY_SIZE(res);
pr_debug("found a Watchdog (0x%llx/0x%llx gsi:%u flags:0x%x).\n",
wd->refresh_frame_address, wd->control_frame_address,
@@ -359,26 +360,58 @@ static int __init gtdt_import_sbsa_gwdt(struct acpi_gtdt_watchdog *wd,
return -EINVAL;
}
- irq = map_gt_gsi(wd->timer_interrupt, wd->timer_flags);
- res[2] = DEFINE_RES_IRQ(irq);
- if (irq <= 0) {
- pr_warn("failed to map the Watchdog interrupt.\n");
- nr_res--;
- }
-
/*
* Add a platform device named "sbsa-gwdt" to match the platform driver.
* "sbsa-gwdt": SBSA(Server Base System Architecture) Generic Watchdog
* The platform driver can get device info below by matching this name.
*/
- pdev = platform_device_register_simple("sbsa-gwdt", index, res, nr_res);
- if (IS_ERR(pdev)) {
- if (irq > 0)
- acpi_unregister_gsi(wd->timer_interrupt);
- return PTR_ERR(pdev);
+ pdev = platform_device_alloc("sbsa-gwdt", index);
+ if (!pdev)
+ return -ENOMEM;
+
+ ret = platform_device_add_resources(pdev, res, nr_res);
+ if (ret)
+ goto dev_put;
+
+ fwnode = acpi_alloc_fwnode_static();
+ if (!fwnode) {
+ ret = -ENOMEM;
+ goto dev_put;
}
+ platform_device_set_fwnode(pdev, fwnode);
+
+ if (wd->timer_interrupt) {
+ gsi[0] = wd->timer_interrupt;
+ triggering[0] = (wd->timer_flags & ACPI_GTDT_INTERRUPT_MODE) ?
+ ACPI_EDGE_SENSITIVE : ACPI_LEVEL_SENSITIVE;
+ polarity[0] = (wd->timer_flags & ACPI_GTDT_INTERRUPT_POLARITY) ?
+ ACPI_ACTIVE_LOW : ACPI_ACTIVE_HIGH;
+
+ props[0] = PROPERTY_ENTRY_U32_ARRAY(ACPI_IRQ_PROP_GSI, gsi);
+ props[1] = PROPERTY_ENTRY_U32_ARRAY(ACPI_IRQ_PROP_GSI_TRIGGER,
+ triggering);
+ props[2] = PROPERTY_ENTRY_U32_ARRAY(ACPI_IRQ_PROP_GSI_POLARITY,
+ polarity);
+
+ ret = device_create_managed_software_node(&pdev->dev, props, NULL);
+ if (ret)
+ goto fwnode_free;
+ }
+
+ ret = platform_device_add(pdev);
+ if (ret)
+ goto fwnode_free;
+
return 0;
+
+fwnode_free:
+ device_remove_software_node(&pdev->dev);
+ platform_device_set_fwnode(pdev, NULL);
+ acpi_free_fwnode_static(fwnode);
+dev_put:
+ platform_device_put(pdev);
+ return ret;
}
static int __init gtdt_platform_timer_init(void)
--
2.54.0
^ permalink raw reply [flat|nested] 21+ messages in thread* Re: [PATCH RFC 06/11] ACPI: GTDT: Convert SBSA watchdog to IRQ properties
2026-09-25 7:48 ` [PATCH RFC 06/11] ACPI: GTDT: Convert SBSA watchdog to IRQ properties Lorenzo Pieralisi
@ 2026-09-25 9:56 ` Andy Shevchenko
0 siblings, 0 replies; 21+ messages in thread
From: Andy Shevchenko @ 2026-09-25 9:56 UTC (permalink / raw)
To: Lorenzo Pieralisi
Cc: Rafael J. Wysocki, Mark Rutland, Marc Zyngier, Daniel Lezcano,
Thomas Gleixner, Greg Kroah-Hartman, Danilo Krummrich,
Hanjun Guo, Sudeep Holla, Wim Van Sebroeck, Guenter Roeck,
Robin Murphy, Catalin Marinas, Will Deacon, Bartosz Golaszewski,
linux-acpi, linux-kernel, linux-arm-kernel, driver-core,
linux-watchdog
On Fri, Sep 25, 2026 at 09:48:05AM +0200, Lorenzo Pieralisi wrote:
> SBSA watchdog IRQs might be wired to interrupt controllers that are
> probed after the SBSA watchdog is probed and therefore the IRQ mappings
> cannot be carried out at platform device creation but deferred to
> SBSA watchdog probing through the platform_get_irq*() set of APIs.
>
> To do that, stash the GSI number, trigger, polarity into standard
> properties attached to a software node that is attached to the
> platform device ACPI static fwnode, allowing the SBSA driver to
> retrieve those properties and map the IRQ when the SBSA driver
> is probed.
>
> Signed-off-by: Lorenzo Pieralisi <lpieralisi@kernel.org>
> Cc: Hanjun Guo <guohanjun@huawei.com>
> Cc: Sudeep Holla <sudeep.holla@kernel.org>
> Cc: "Rafael J. Wysocki" <rafael@kernel.org>
> ---
Same about the Cc list...
...
> struct resource res[] = {
> DEFINE_RES_MEM(wd->control_frame_address, SZ_4K),
> DEFINE_RES_MEM(wd->refresh_frame_address, SZ_4K),
> - {},
Side note, even in the old code the last entry should be rather DEFINE_RES().
Because some APIs, such as resource_size() will not work on an 'empty'
resource.
> };
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH RFC 07/11] ACPI/IORT: Convert IORT devices to IRQs software-node properties
2026-09-25 7:47 [PATCH RFC 00/11] ACPI: ARM64: Implement IRQ mapping probe deferral for static table devices Lorenzo Pieralisi
` (5 preceding siblings ...)
2026-09-25 7:48 ` [PATCH RFC 06/11] ACPI: GTDT: Convert SBSA watchdog to IRQ properties Lorenzo Pieralisi
@ 2026-09-25 7:48 ` Lorenzo Pieralisi
2026-09-25 7:48 ` [PATCH RFC 08/11] watchdog: sbsa: Handle IRQ probe deferral Lorenzo Pieralisi
` (3 subsequent siblings)
10 siblings, 0 replies; 21+ messages in thread
From: Lorenzo Pieralisi @ 2026-09-25 7:48 UTC (permalink / raw)
To: Rafael J. Wysocki, Mark Rutland, Marc Zyngier, Daniel Lezcano,
Thomas Gleixner, Greg Kroah-Hartman, Danilo Krummrich,
Hanjun Guo, Sudeep Holla, Wim Van Sebroeck, Guenter Roeck,
Robin Murphy, Catalin Marinas, Will Deacon, Bartosz Golaszewski,
Andy Shevchenko
Cc: linux-acpi, linux-kernel, linux-arm-kernel, driver-core,
linux-watchdog, Lorenzo Pieralisi
Static devices created out of IORT nodes might require GSI interrupts that
are routed to interrupt controllers that have not yet probed (so their
respective IRQ domain is not registered yet and therefore the GSI
mapping would fail if tried) to be mapped in current IORT code.
Instead of trying to map the GSIs at platform device creation time,
stash standard GSIs numbers, trigger/polarity and names properties into
the IORT static fwnode secondary swnodes so that they can be later
retrieved, in a uniform fashion, by the device drivers claiming them.
Signed-off-by: Lorenzo Pieralisi <lpieralisi@kernel.org>
Cc: Hanjun Guo <guohanjun@huawei.com>
Cc: Sudeep Holla <sudeep.holla@kernel.org>
Cc: "Rafael J. Wysocki" <rafael@kernel.org>
---
drivers/acpi/arm64/iort.c | 250 ++++++++++++++++++++++++++--------------------
1 file changed, 142 insertions(+), 108 deletions(-)
diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
index 1020ac953e42..9b7aa51aedc3 100644
--- a/drivers/acpi/arm64/iort.c
+++ b/drivers/acpi/arm64/iort.c
@@ -1567,47 +1567,52 @@ int iort_dma_get_ranges(struct device *dev, u64 *limit)
return nc_dma_get_range(dev, limit);
}
-static void __init acpi_iort_register_irq(int hwirq, const char *name,
- int trigger,
- struct resource *res)
+static void __init acpi_iort_add_irq(u32 hwirq, const char *name, unsigned int trigger_val,
+ u32 *gsi, u32 *trigger,
+ u32 *polarity, const char **names,
+ unsigned int *index)
{
- int irq = acpi_register_gsi(NULL, hwirq, trigger,
- ACPI_ACTIVE_HIGH);
-
- if (irq <= 0) {
- pr_err("could not register gsi hwirq %d name [%s]\n", hwirq,
- name);
+ if (!hwirq)
return;
- }
- res->start = irq;
- res->end = irq;
- res->flags = IORESOURCE_IRQ;
- res->name = name;
+ gsi[*index] = hwirq;
+ trigger[*index] = trigger_val;
+ polarity[*index] = ACPI_ACTIVE_HIGH;
+ if (names)
+ names[*index] = name;
+ (*index)++;
+}
+
+static int __init acpi_iort_get_irq_props(const u32 *gsi,
+ const u32 *trigger,
+ const u32 *polarity,
+ const char * const *names,
+ unsigned int irq_count,
+ const struct property_entry **props)
+{
+ struct property_entry entries[5] = {};
+ int next_prop = 0;
+
+ if (!irq_count)
+ return 0;
+
+ entries[next_prop++] = PROPERTY_ENTRY_U32_ARRAY_LEN(ACPI_IRQ_PROP_GSI,
+ gsi, irq_count);
+ entries[next_prop++] = PROPERTY_ENTRY_U32_ARRAY_LEN(ACPI_IRQ_PROP_GSI_TRIGGER,
+ trigger, irq_count);
+ entries[next_prop++] = PROPERTY_ENTRY_U32_ARRAY_LEN(ACPI_IRQ_PROP_GSI_POLARITY,
+ polarity, irq_count);
+ if (names)
+ entries[next_prop++] = PROPERTY_ENTRY_STRING_ARRAY_LEN("interrupt-names",
+ names, irq_count);
+
+ *props = property_entries_dup(entries);
+ return PTR_ERR_OR_ZERO(*props);
}
static int __init arm_smmu_v3_count_resources(struct acpi_iort_node *node)
{
- struct acpi_iort_smmu_v3 *smmu;
- /* Always present mem resource */
- int num_res = 1;
-
- /* Retrieve SMMUv3 specific data */
- smmu = (struct acpi_iort_smmu_v3 *)node->node_data;
-
- if (smmu->event_gsiv)
- num_res++;
-
- if (smmu->pri_gsiv)
- num_res++;
-
- if (smmu->gerr_gsiv)
- num_res++;
-
- if (smmu->sync_gsiv)
- num_res++;
-
- return num_res;
+ return 1;
}
static bool arm_smmu_v3_is_combined_irq(struct acpi_iort_smmu_v3 *smmu)
@@ -1644,44 +1649,47 @@ static void __init arm_smmu_v3_init_resources(struct resource *res,
struct acpi_iort_node *node)
{
struct acpi_iort_smmu_v3 *smmu;
- int num_res = 0;
/* Retrieve SMMUv3 specific data */
smmu = (struct acpi_iort_smmu_v3 *)node->node_data;
- res[num_res].start = smmu->base_address;
- res[num_res].end = smmu->base_address +
- arm_smmu_v3_resource_size(smmu) - 1;
- res[num_res].flags = IORESOURCE_MEM;
+ res[0].start = smmu->base_address;
+ res[0].end = smmu->base_address + arm_smmu_v3_resource_size(smmu) - 1;
+ res[0].flags = IORESOURCE_MEM;
+}
+
+static int __init arm_smmu_v3_init_irq_props(const struct property_entry **props,
+ struct acpi_iort_node *node)
+{
+ u32 gsi[4], trigger[4], polarity[4];
+ struct acpi_iort_smmu_v3 *smmu;
+ unsigned int irq_count = 0;
+ const char *names[4];
+
+ smmu = (struct acpi_iort_smmu_v3 *)node->node_data;
- num_res++;
if (arm_smmu_v3_is_combined_irq(smmu)) {
- if (smmu->event_gsiv)
- acpi_iort_register_irq(smmu->event_gsiv, "combined",
- ACPI_EDGE_SENSITIVE,
- &res[num_res++]);
+ acpi_iort_add_irq(smmu->event_gsiv, "combined",
+ ACPI_EDGE_SENSITIVE, gsi, trigger,
+ polarity, names, &irq_count);
} else {
+ acpi_iort_add_irq(smmu->event_gsiv, "eventq",
+ ACPI_EDGE_SENSITIVE, gsi, trigger,
+ polarity, names, &irq_count);
- if (smmu->event_gsiv)
- acpi_iort_register_irq(smmu->event_gsiv, "eventq",
- ACPI_EDGE_SENSITIVE,
- &res[num_res++]);
-
- if (smmu->pri_gsiv)
- acpi_iort_register_irq(smmu->pri_gsiv, "priq",
- ACPI_EDGE_SENSITIVE,
- &res[num_res++]);
-
- if (smmu->gerr_gsiv)
- acpi_iort_register_irq(smmu->gerr_gsiv, "gerror",
- ACPI_EDGE_SENSITIVE,
- &res[num_res++]);
-
- if (smmu->sync_gsiv)
- acpi_iort_register_irq(smmu->sync_gsiv, "cmdq-sync",
- ACPI_EDGE_SENSITIVE,
- &res[num_res++]);
+ acpi_iort_add_irq(smmu->pri_gsiv, "priq",
+ ACPI_EDGE_SENSITIVE, gsi, trigger,
+ polarity, names, &irq_count);
+ acpi_iort_add_irq(smmu->gerr_gsiv, "gerror",
+ ACPI_EDGE_SENSITIVE, gsi, trigger,
+ polarity, names, &irq_count);
+ acpi_iort_add_irq(smmu->sync_gsiv, "cmdq-sync",
+ ACPI_EDGE_SENSITIVE, gsi, trigger,
+ polarity, names, &irq_count);
}
+
+ return acpi_iort_get_irq_props(gsi, trigger, polarity, names,
+ irq_count, props);
}
static void __init arm_smmu_v3_dma_configure(struct device *dev,
@@ -1732,54 +1740,55 @@ static int __init arm_smmu_v3_set_proximity(struct device *dev,
static int __init arm_smmu_count_resources(struct acpi_iort_node *node)
{
- struct acpi_iort_smmu *smmu;
-
- /* Retrieve SMMU specific data */
- smmu = (struct acpi_iort_smmu *)node->node_data;
-
- /*
- * Only consider the global fault interrupt and ignore the
- * configuration access interrupt.
- *
- * MMIO address and global fault interrupt resources are always
- * present so add them to the context interrupt count as a static
- * value.
- */
- return smmu->context_interrupt_count + 2;
+ return 1;
}
static void __init arm_smmu_init_resources(struct resource *res,
struct acpi_iort_node *node)
{
struct acpi_iort_smmu *smmu;
- int i, hw_irq, trigger, num_res = 0;
- u64 *ctx_irq, *glb_irq;
/* Retrieve SMMU specific data */
smmu = (struct acpi_iort_smmu *)node->node_data;
- res[num_res].start = smmu->base_address;
- res[num_res].end = smmu->base_address + smmu->span - 1;
- res[num_res].flags = IORESOURCE_MEM;
- num_res++;
+ res[0].start = smmu->base_address;
+ res[0].end = smmu->base_address + smmu->span - 1;
+ res[0].flags = IORESOURCE_MEM;
+}
+
+static int __init arm_smmu_init_irq_props(const struct property_entry **props,
+ struct acpi_iort_node *node)
+{
+ struct acpi_iort_smmu *smmu;
+ unsigned int irq_count = 0;
+ u64 *ctx_irq, *glb_irq;
+ int i;
+
+ smmu = (struct acpi_iort_smmu *)node->node_data;
+
+ u32 *gsi __free(kfree) = kcalloc(smmu->context_interrupt_count + 1,
+ sizeof(*gsi), GFP_KERNEL);
+ u32 *trigger __free(kfree) = kcalloc(smmu->context_interrupt_count + 1,
+ sizeof(*trigger), GFP_KERNEL);
+ u32 *polarity __free(kfree) = kcalloc(smmu->context_interrupt_count + 1,
+ sizeof(*polarity), GFP_KERNEL);
+ if (!gsi || !trigger || !polarity)
+ return -ENOMEM;
glb_irq = ACPI_ADD_PTR(u64, node, smmu->global_interrupt_offset);
- /* Global IRQs */
- hw_irq = IORT_IRQ_MASK(glb_irq[0]);
- trigger = IORT_IRQ_TRIGGER_MASK(glb_irq[0]);
+ acpi_iort_add_irq(IORT_IRQ_MASK(glb_irq[0]), NULL,
+ IORT_IRQ_TRIGGER_MASK(glb_irq[0]), gsi,
+ trigger, polarity, NULL, &irq_count);
- acpi_iort_register_irq(hw_irq, "arm-smmu-global", trigger,
- &res[num_res++]);
-
- /* Context IRQs */
ctx_irq = ACPI_ADD_PTR(u64, node, smmu->context_interrupt_offset);
for (i = 0; i < smmu->context_interrupt_count; i++) {
- hw_irq = IORT_IRQ_MASK(ctx_irq[i]);
- trigger = IORT_IRQ_TRIGGER_MASK(ctx_irq[i]);
-
- acpi_iort_register_irq(hw_irq, "arm-smmu-context", trigger,
- &res[num_res++]);
+ acpi_iort_add_irq(IORT_IRQ_MASK(ctx_irq[i]), NULL,
+ IORT_IRQ_TRIGGER_MASK(ctx_irq[i]), gsi,
+ trigger, polarity, NULL, &irq_count);
}
+
+ return acpi_iort_get_irq_props(gsi, trigger, polarity, NULL,
+ irq_count, props);
}
static void __init arm_smmu_dma_configure(struct device *dev,
@@ -1803,16 +1812,7 @@ static void __init arm_smmu_dma_configure(struct device *dev,
static int __init arm_smmu_v3_pmcg_count_resources(struct acpi_iort_node *node)
{
- struct acpi_iort_pmcg *pmcg;
-
- /* Retrieve PMCG specific data */
- pmcg = (struct acpi_iort_pmcg *)node->node_data;
-
- /*
- * There are always 2 memory resources.
- * If the overflow_gsiv is present then add that for a total of 3.
- */
- return pmcg->overflow_gsiv ? 3 : 2;
+ return 2;
}
static void __init arm_smmu_v3_pmcg_init_resources(struct resource *res,
@@ -1837,10 +1837,22 @@ static void __init arm_smmu_v3_pmcg_init_resources(struct resource *res,
res[1].end = pmcg->page1_base_address + SZ_4K - 1;
res[1].flags = IORESOURCE_MEM;
}
+}
- if (pmcg->overflow_gsiv)
- acpi_iort_register_irq(pmcg->overflow_gsiv, "overflow",
- ACPI_EDGE_SENSITIVE, &res[2]);
+static int __init arm_smmu_v3_pmcg_init_irq_props(const struct property_entry **props,
+ struct acpi_iort_node *node)
+{
+ u32 gsi[1], trigger[1], polarity[1];
+ struct acpi_iort_pmcg *pmcg;
+ unsigned int irq_count = 0;
+ const char *names[1];
+
+ pmcg = (struct acpi_iort_pmcg *)node->node_data;
+
+ acpi_iort_add_irq(pmcg->overflow_gsiv, "overflow", ACPI_EDGE_SENSITIVE,
+ gsi, trigger, polarity, names, &irq_count);
+ return acpi_iort_get_irq_props(gsi, trigger, polarity, names,
+ irq_count, props);
}
static struct acpi_platform_list pmcg_plat_info[] __initdata = {
@@ -1884,6 +1896,8 @@ struct iort_dev_config {
int (*dev_count_resources)(struct acpi_iort_node *node);
void (*dev_init_resources)(struct resource *res,
struct acpi_iort_node *node);
+ int (*dev_init_irq_props)(const struct property_entry **props,
+ struct acpi_iort_node *node);
int (*dev_set_proximity)(struct device *dev,
struct acpi_iort_node *node);
int (*dev_add_platdata)(struct platform_device *pdev);
@@ -1894,6 +1908,7 @@ static const struct iort_dev_config iort_arm_smmu_v3_cfg __initconst = {
.dev_dma_configure = arm_smmu_v3_dma_configure,
.dev_count_resources = arm_smmu_v3_count_resources,
.dev_init_resources = arm_smmu_v3_init_resources,
+ .dev_init_irq_props = arm_smmu_v3_init_irq_props,
.dev_set_proximity = arm_smmu_v3_set_proximity,
};
@@ -1902,12 +1917,14 @@ static const struct iort_dev_config iort_arm_smmu_cfg __initconst = {
.dev_dma_configure = arm_smmu_dma_configure,
.dev_count_resources = arm_smmu_count_resources,
.dev_init_resources = arm_smmu_init_resources,
+ .dev_init_irq_props = arm_smmu_init_irq_props,
};
static const struct iort_dev_config iort_arm_smmu_v3_pmcg_cfg __initconst = {
.name = "arm-smmu-v3-pmcg",
.dev_count_resources = arm_smmu_v3_pmcg_count_resources,
.dev_init_resources = arm_smmu_v3_pmcg_init_resources,
+ .dev_init_irq_props = arm_smmu_v3_pmcg_init_irq_props,
.dev_add_platdata = arm_smmu_v3_pmcg_add_platdata,
};
@@ -1937,6 +1954,7 @@ static int __init iort_add_platform_device(struct acpi_iort_node *node,
const struct iort_dev_config *ops)
{
struct fwnode_handle *fwnode;
+ const struct property_entry *props = NULL;
struct platform_device *pdev;
struct resource *r;
int ret, count;
@@ -1994,6 +2012,20 @@ static int __init iort_add_platform_device(struct acpi_iort_node *node,
platform_device_set_fwnode(pdev, fwnode);
+ if (ops->dev_init_irq_props) {
+ ret = ops->dev_init_irq_props(&props, node);
+ if (ret)
+ goto dev_put;
+
+ if (props) {
+ ret = device_create_managed_software_node(&pdev->dev,
+ props, NULL);
+ property_entries_free(props);
+ if (ret)
+ goto dev_put;
+ }
+ }
+
if (ops->dev_dma_configure)
ops->dev_dma_configure(&pdev->dev, node);
@@ -2007,6 +2039,8 @@ static int __init iort_add_platform_device(struct acpi_iort_node *node,
dma_deconfigure:
arch_teardown_dma_ops(&pdev->dev);
+ device_remove_software_node(&pdev->dev);
+ platform_device_set_fwnode(pdev, NULL);
dev_put:
platform_device_put(pdev);
--
2.54.0
^ permalink raw reply [flat|nested] 21+ messages in thread* [PATCH RFC 08/11] watchdog: sbsa: Handle IRQ probe deferral
2026-09-25 7:47 [PATCH RFC 00/11] ACPI: ARM64: Implement IRQ mapping probe deferral for static table devices Lorenzo Pieralisi
` (6 preceding siblings ...)
2026-09-25 7:48 ` [PATCH RFC 07/11] ACPI/IORT: Convert IORT devices to IRQs software-node properties Lorenzo Pieralisi
@ 2026-09-25 7:48 ` Lorenzo Pieralisi
2026-09-25 7:48 ` [PATCH RFC 09/11] iommu/arm-smmu: Add arm-smmu IRQ mapping -EPROBE_DEFER handling Lorenzo Pieralisi
` (2 subsequent siblings)
10 siblings, 0 replies; 21+ messages in thread
From: Lorenzo Pieralisi @ 2026-09-25 7:48 UTC (permalink / raw)
To: Rafael J. Wysocki, Mark Rutland, Marc Zyngier, Daniel Lezcano,
Thomas Gleixner, Greg Kroah-Hartman, Danilo Krummrich,
Hanjun Guo, Sudeep Holla, Wim Van Sebroeck, Guenter Roeck,
Robin Murphy, Catalin Marinas, Will Deacon, Bartosz Golaszewski,
Andy Shevchenko
Cc: linux-acpi, linux-kernel, linux-arm-kernel, driver-core,
linux-watchdog, Lorenzo Pieralisi
The SBSA watchdog might be wired up to an interrupt controller whose
device driver has not probed yet at SBSA watchdog driver probe time.
Handle probe deferral in the IRQ mapping code path.
Signed-off-by: Lorenzo Pieralisi <lpieralisi@kernel.org>
Cc: Guenter Roeck <linux@roeck-us.net>
Cc: Wim Van Sebroeck <wim@linux-watchdog.org>
---
drivers/watchdog/sbsa_gwdt.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/watchdog/sbsa_gwdt.c b/drivers/watchdog/sbsa_gwdt.c
index e04d42cc7774..f4491409caf5 100644
--- a/drivers/watchdog/sbsa_gwdt.c
+++ b/drivers/watchdog/sbsa_gwdt.c
@@ -352,6 +352,8 @@ static int sbsa_gwdt_probe(struct platform_device *pdev)
if (action) {
irq = platform_get_irq(pdev, 0);
+ if (irq == -EPROBE_DEFER)
+ return dev_err_probe(dev, irq, "failed to get ws0 interrupt\n");
if (irq < 0) {
action = 0;
dev_warn(dev, "unable to get ws0 interrupt.\n");
--
2.54.0
^ permalink raw reply [flat|nested] 21+ messages in thread* [PATCH RFC 09/11] iommu/arm-smmu: Add arm-smmu IRQ mapping -EPROBE_DEFER handling
2026-09-25 7:47 [PATCH RFC 00/11] ACPI: ARM64: Implement IRQ mapping probe deferral for static table devices Lorenzo Pieralisi
` (7 preceding siblings ...)
2026-09-25 7:48 ` [PATCH RFC 08/11] watchdog: sbsa: Handle IRQ probe deferral Lorenzo Pieralisi
@ 2026-09-25 7:48 ` Lorenzo Pieralisi
2026-09-25 7:48 ` [PATCH RFC 10/11] iommu/arm-smmu-v3: Add " Lorenzo Pieralisi
2026-09-25 7:48 ` [PATCH RFC 11/11] perf/arm-smmu-v3-pmu: " Lorenzo Pieralisi
10 siblings, 0 replies; 21+ messages in thread
From: Lorenzo Pieralisi @ 2026-09-25 7:48 UTC (permalink / raw)
To: Rafael J. Wysocki, Mark Rutland, Marc Zyngier, Daniel Lezcano,
Thomas Gleixner, Greg Kroah-Hartman, Danilo Krummrich,
Hanjun Guo, Sudeep Holla, Wim Van Sebroeck, Guenter Roeck,
Robin Murphy, Catalin Marinas, Will Deacon, Bartosz Golaszewski,
Andy Shevchenko
Cc: linux-acpi, linux-kernel, linux-arm-kernel, driver-core,
linux-watchdog, Lorenzo Pieralisi
With the advent of GICv5, IRQs mapping can fail if the interrupt
controller the wired SMMU interrupts are routed to has not probed
yet when the SMMU driver probes.
Handle -EPROBE_DEFER gracefully for IRQ mappings failures.
Signed-off-by: Lorenzo Pieralisi <lpieralisi@kernel.org>
Cc: Will Deacon <will@kernel.org>
Cc: Robin Murphy <robin.murphy@arm.com>
---
drivers/iommu/arm/arm-smmu/arm-smmu.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.c b/drivers/iommu/arm/arm-smmu/arm-smmu.c
index 889a0966d36c..a111b80553da 100644
--- a/drivers/iommu/arm/arm-smmu/arm-smmu.c
+++ b/drivers/iommu/arm/arm-smmu/arm-smmu.c
@@ -2154,6 +2154,8 @@ static int arm_smmu_device_probe(struct platform_device *pdev)
return PTR_ERR(smmu);
num_irqs = platform_irq_count(pdev);
+ if (num_irqs < 0)
+ return dev_err_probe(dev, num_irqs, "IRQ count failed\n");
smmu->num_context_irqs = num_irqs - global_irqs - pmu_irqs;
if (smmu->num_context_irqs <= 0)
@@ -2171,7 +2173,7 @@ static int arm_smmu_device_probe(struct platform_device *pdev)
int irq = platform_get_irq(pdev, global_irqs + pmu_irqs + i);
if (irq < 0)
- return irq;
+ return dev_err_probe(dev, irq, "failed to get context IRQ\n");
smmu->irqs[i] = irq;
}
@@ -2211,7 +2213,7 @@ static int arm_smmu_device_probe(struct platform_device *pdev)
int irq = platform_get_irq(pdev, i);
if (irq < 0)
- return irq;
+ return dev_err_probe(dev, irq, "failed to get global IRQ\n");
err = devm_request_irq(dev, irq, global_fault, IRQF_SHARED,
"arm-smmu global fault", smmu);
--
2.54.0
^ permalink raw reply [flat|nested] 21+ messages in thread* [PATCH RFC 10/11] iommu/arm-smmu-v3: Add IRQ mapping -EPROBE_DEFER handling
2026-09-25 7:47 [PATCH RFC 00/11] ACPI: ARM64: Implement IRQ mapping probe deferral for static table devices Lorenzo Pieralisi
` (8 preceding siblings ...)
2026-09-25 7:48 ` [PATCH RFC 09/11] iommu/arm-smmu: Add arm-smmu IRQ mapping -EPROBE_DEFER handling Lorenzo Pieralisi
@ 2026-09-25 7:48 ` Lorenzo Pieralisi
2026-09-25 7:48 ` [PATCH RFC 11/11] perf/arm-smmu-v3-pmu: " Lorenzo Pieralisi
10 siblings, 0 replies; 21+ messages in thread
From: Lorenzo Pieralisi @ 2026-09-25 7:48 UTC (permalink / raw)
To: Rafael J. Wysocki, Mark Rutland, Marc Zyngier, Daniel Lezcano,
Thomas Gleixner, Greg Kroah-Hartman, Danilo Krummrich,
Hanjun Guo, Sudeep Holla, Wim Van Sebroeck, Guenter Roeck,
Robin Murphy, Catalin Marinas, Will Deacon, Bartosz Golaszewski,
Andy Shevchenko
Cc: linux-acpi, linux-kernel, linux-arm-kernel, driver-core,
linux-watchdog, Lorenzo Pieralisi
With the advent of GICv5, IRQs mapping can fail if the interrupt
controller the wired SMMU interrupts are routed to has not probed
yet when the SMMU driver probes.
Handle -EPROBE_DEFER gracefully for IRQ mappings failures.
Signed-off-by: Lorenzo Pieralisi <lpieralisi@kernel.org>
Cc: Will Deacon <will@kernel.org>
Cc: Robin Murphy <robin.murphy@arm.com>
---
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
index 5732f3ba0122..1832389916a4 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -5562,18 +5562,26 @@ static int arm_smmu_device_probe(struct platform_device *pdev)
/* Interrupt lines */
irq = platform_get_irq_byname_optional(pdev, "combined");
+ if (irq == -EPROBE_DEFER)
+ return dev_err_probe(dev, irq, "failed to get combined IRQ\n");
if (irq > 0)
smmu->combined_irq = irq;
else {
irq = platform_get_irq_byname_optional(pdev, "eventq");
+ if (irq == -EPROBE_DEFER)
+ return dev_err_probe(dev, irq, "failed to get eventq IRQ\n");
if (irq > 0)
smmu->evtq.q.irq = irq;
irq = platform_get_irq_byname_optional(pdev, "priq");
+ if (irq == -EPROBE_DEFER)
+ return dev_err_probe(dev, irq, "failed to get priq IRQ\n");
if (irq > 0)
smmu->priq.q.irq = irq;
irq = platform_get_irq_byname_optional(pdev, "gerror");
+ if (irq == -EPROBE_DEFER)
+ return dev_err_probe(dev, irq, "failed to get gerror IRQ\n");
if (irq > 0)
smmu->gerr_irq = irq;
}
--
2.54.0
^ permalink raw reply [flat|nested] 21+ messages in thread* [PATCH RFC 11/11] perf/arm-smmu-v3-pmu: Add IRQ mapping -EPROBE_DEFER handling
2026-09-25 7:47 [PATCH RFC 00/11] ACPI: ARM64: Implement IRQ mapping probe deferral for static table devices Lorenzo Pieralisi
` (9 preceding siblings ...)
2026-09-25 7:48 ` [PATCH RFC 10/11] iommu/arm-smmu-v3: Add " Lorenzo Pieralisi
@ 2026-09-25 7:48 ` Lorenzo Pieralisi
10 siblings, 0 replies; 21+ messages in thread
From: Lorenzo Pieralisi @ 2026-09-25 7:48 UTC (permalink / raw)
To: Rafael J. Wysocki, Mark Rutland, Marc Zyngier, Daniel Lezcano,
Thomas Gleixner, Greg Kroah-Hartman, Danilo Krummrich,
Hanjun Guo, Sudeep Holla, Wim Van Sebroeck, Guenter Roeck,
Robin Murphy, Catalin Marinas, Will Deacon, Bartosz Golaszewski,
Andy Shevchenko
Cc: linux-acpi, linux-kernel, linux-arm-kernel, driver-core,
linux-watchdog, Lorenzo Pieralisi
With the advent of GICv5, IRQs mapping can fail if the interrupt
controller the wired SMMU PMCG interrupts are routed to has not probed
yet when the SMMU PMCG driver probes.
Handle -EPROBE_DEFER gracefully for IRQ mappings failures.
Signed-off-by: Lorenzo Pieralisi <lpieralisi@kernel.org>
Cc: Will Deacon <will@kernel.org>
Cc: Robin Murphy <robin.murphy@arm.com>
---
drivers/perf/arm_smmuv3_pmu.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/drivers/perf/arm_smmuv3_pmu.c b/drivers/perf/arm_smmuv3_pmu.c
index 8ce34e6bb82b..d8d977c13ab9 100644
--- a/drivers/perf/arm_smmuv3_pmu.c
+++ b/drivers/perf/arm_smmuv3_pmu.c
@@ -893,6 +893,9 @@ static int smmu_pmu_probe(struct platform_device *pdev)
}
irq = platform_get_irq_optional(pdev, 0);
+ if (irq == -EPROBE_DEFER)
+ return dev_err_probe(dev, irq, "failed to get PMCG IRQ\n");
+
if (irq > 0)
smmu_pmu->irq = irq;
--
2.54.0
^ permalink raw reply [flat|nested] 21+ messages in thread