mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Lorenzo Pieralisi <lpieralisi@kernel.org>
To: "Rafael J. Wysocki" <rafael@kernel.org>,
	 Mark Rutland <mark.rutland@arm.com>,
	Marc Zyngier <maz@kernel.org>,
	 Daniel Lezcano <daniel.lezcano@kernel.org>,
	 Thomas Gleixner <tglx@kernel.org>,
	 Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	 Danilo Krummrich <dakr@kernel.org>,
	Hanjun Guo <guohanjun@huawei.com>,
	 Sudeep Holla <sudeep.holla@kernel.org>,
	 Wim Van Sebroeck <wim@linux-watchdog.org>,
	 Guenter Roeck <linux@roeck-us.net>,
	Robin Murphy <robin.murphy@arm.com>,
	 Catalin Marinas <catalin.marinas@arm.com>,
	Will Deacon <will@kernel.org>,
	 Bartosz Golaszewski <brgl@kernel.org>,
	 Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Cc: linux-acpi@vger.kernel.org, linux-kernel@vger.kernel.org,
	 linux-arm-kernel@lists.infradead.org,
	driver-core@lists.linux.dev,  linux-watchdog@vger.kernel.org,
	Lorenzo Pieralisi <lpieralisi@kernel.org>
Subject: [PATCH RFC 07/11] ACPI/IORT: Convert IORT devices to IRQs software-node properties
Date: Fri, 25 Sep 2026 09:48:06 +0200	[thread overview]
Message-ID: <20260925-acpi-static-table-irq-probe-defer-v1-7-2c62125d0085@kernel.org> (raw)
In-Reply-To: <20260925-acpi-static-table-irq-probe-defer-v1-0-2c62125d0085@kernel.org>

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


  parent reply	other threads:[~2026-09-25  7:48 UTC|newest]

Thread overview: 31+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
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  9:45   ` Andy Shevchenko
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
2026-09-25 10:54       ` Andy Shevchenko
2026-09-25 11:32         ` Lorenzo Pieralisi
2026-09-28 16:15         ` Lorenzo Pieralisi
2026-09-30 17:13           ` Jonathan Cameron
2026-10-06 16:19           ` Robin Murphy
2026-09-28 23:24   ` Ashok Raj
2026-09-29  8:40     ` Lorenzo Pieralisi
2026-09-30  0:38       ` Ashok Raj
2026-09-30  7:40         ` Andy Shevchenko
2026-09-30  7:56           ` Lorenzo Pieralisi
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
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
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 ` [PATCH RFC 06/11] ACPI: GTDT: Convert SBSA watchdog to IRQ properties Lorenzo Pieralisi
2026-09-25  9:56   ` Andy Shevchenko
2026-09-25  7:48 ` Lorenzo Pieralisi [this message]
2026-09-25  7:48 ` [PATCH RFC 08/11] watchdog: sbsa: Handle IRQ probe deferral Lorenzo Pieralisi
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 ` [PATCH RFC 10/11] iommu/arm-smmu-v3: Add " Lorenzo Pieralisi
2026-09-28 22:41   ` Ashok Raj
2026-09-29  8:43     ` Lorenzo Pieralisi
2026-09-25  7:48 ` [PATCH RFC 11/11] perf/arm-smmu-v3-pmu: " Lorenzo Pieralisi

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260925-acpi-static-table-irq-probe-defer-v1-7-2c62125d0085@kernel.org \
    --to=lpieralisi@kernel.org \
    --cc=andriy.shevchenko@linux.intel.com \
    --cc=brgl@kernel.org \
    --cc=catalin.marinas@arm.com \
    --cc=dakr@kernel.org \
    --cc=daniel.lezcano@kernel.org \
    --cc=driver-core@lists.linux.dev \
    --cc=gregkh@linuxfoundation.org \
    --cc=guohanjun@huawei.com \
    --cc=linux-acpi@vger.kernel.org \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-watchdog@vger.kernel.org \
    --cc=linux@roeck-us.net \
    --cc=mark.rutland@arm.com \
    --cc=maz@kernel.org \
    --cc=rafael@kernel.org \
    --cc=robin.murphy@arm.com \
    --cc=sudeep.holla@kernel.org \
    --cc=tglx@kernel.org \
    --cc=will@kernel.org \
    --cc=wim@linux-watchdog.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®