[PATCH 07/10] lib: utils: irqchip: derive APLIC targets from sysirq nodes

Raymond Mao <[email protected]>
Newsgroups org.infradead.lists.opensbi
Message-ID <[email protected]>
From: Raymond Mao <[email protected]>

Derive a per-HWIRQ target hartindex map from each sysirq node's
target domain boot-hart, and store the result in aplic_data.
This is used for setting IDC target per HWIRQ under irqchip driver
instead of hardcoding to a specific target.

Signed-off-by: Raymond Mao <[email protected]>
---
 include/sbi_utils/irqchip/aplic.h     |   1 +
 lib/utils/irqchip/fdt_irqchip_aplic.c | 103 ++++++++++++++++++++++++++
 2 files changed, 104 insertions(+)

diff --git a/include/sbi_utils/irqchip/aplic.h b/include/sbi_utils/irqchip/aplic.h
index 3461d1c7..d6e088f8 100644
--- a/include/sbi_utils/irqchip/aplic.h
+++ b/include/sbi_utils/irqchip/aplic.h
@@ -47,6 +47,7 @@ struct aplic_data {
 	struct aplic_msicfg_data msicfg_smode;
 	struct aplic_delegate_data delegate[APLIC_MAX_DELEGATE];
 	u32 *idc_map;
+	u32 *hwirq_target_hartindex;
 };
 
 int aplic_cold_irqchip_init(struct aplic_data *aplic);
diff --git a/lib/utils/irqchip/fdt_irqchip_aplic.c b/lib/utils/irqchip/fdt_irqchip_aplic.c
index f9b567f5..cbbdf8d8 100644
--- a/lib/utils/irqchip/fdt_irqchip_aplic.c
+++ b/lib/utils/irqchip/fdt_irqchip_aplic.c
@@ -13,6 +13,7 @@
 #include <sbi/sbi_console.h>
 #include <sbi/sbi_error.h>
 #include <sbi/sbi_heap.h>
+#include <sbi/sbi_scratch.h>
 #include <sbi_utils/fdt/fdt_helper.h>
 #include <sbi_utils/irqchip/fdt_irqchip.h>
 #include <sbi_utils/irqchip/aplic.h>
@@ -54,6 +55,88 @@ static int irqchip_aplic_update_idc_map(const void *fdt, int nodeoff,
 	return 0;
 }
 
+static u32 irqchip_aplic_domain_boot_hartindex(void *fdt, int domain_offset)
+{
+	int len, cpu_offset;
+	const fdt32_t *val;
+
+	val = fdt_getprop(fdt, domain_offset, "boot-hart", &len);
+	if (val && len >= 4) {
+		cpu_offset = fdt_node_offset_by_phandle(fdt,
+							fdt32_to_cpu(*val));
+		if (cpu_offset >= 0) {
+			u32 hartid;
+
+			if (!fdt_parse_hart_id(fdt, cpu_offset, &hartid)) {
+				u32 hidx = sbi_hartid_to_hartindex(hartid);
+
+				if (sbi_hartindex_valid(hidx))
+					return hidx;
+			}
+		}
+	}
+
+	return current_hartindex();
+}
+
+static void irqchip_aplic_fill_hwirq_targets_from_sysirq(const void *fdt,
+							 int aplic_nodeoff,
+							 struct aplic_data *pd)
+{
+	int chosen_off, nodeoff;
+	int len, rc, index;
+	const fdt32_t *val;
+	u32 boot_hartindex;
+
+	if (!fdt || aplic_nodeoff < 0 || !pd || !pd->hwirq_target_hartindex)
+		return;
+
+	chosen_off = fdt_path_offset(fdt, "/chosen/opensbi-domains");
+	if (chosen_off < 0)
+		return;
+
+	fdt_for_each_subnode(nodeoff, fdt, chosen_off) {
+		if (fdt_node_check_compatible(fdt, nodeoff,
+					      "opensbi,mpxy-sysirq"))
+			continue;
+
+		val = fdt_getprop(fdt, nodeoff, "opensbi,domain", &len);
+		if (!val || len < 4)
+			continue;
+
+		rc = fdt_node_offset_by_phandle(fdt, fdt32_to_cpu(*val));
+		if (rc < 0)
+			continue;
+
+		boot_hartindex = irqchip_aplic_domain_boot_hartindex((void *)fdt,
+								     rc);
+
+		for (index = 0; ; index++) {
+			struct fdt_phandle_args args;
+
+			rc = fdt_parse_phandle_with_args(fdt, nodeoff,
+							 "interrupts-extended",
+							 "#interrupt-cells",
+							 index, &args);
+			if (rc)
+				break;
+			if (args.args_count < 1)
+				continue;
+			if (args.node_offset != aplic_nodeoff)
+				continue;
+
+			u32 hwirq = args.args[0];
+
+			if (!hwirq || hwirq > pd->num_source)
+				continue;
+
+			if (pd->hwirq_target_hartindex[hwirq] == -1U)
+				pd->hwirq_target_hartindex[hwirq] =
+					boot_hartindex;
+		}
+	}
+}
+
 static int irqchip_aplic_cold_init(const void *fdt, int nodeoff,
 				   const struct fdt_match *match)
 {
@@ -85,6 +168,24 @@ static int irqchip_aplic_cold_init(const void *fdt, int nodeoff,
 			goto fail_free_idc_map;
 	}
 
+	/* Precompute target hartindex per HWIRQ from DT. */
+	if (pd->targets_mmode) {
+		u32 i;
+
+		pd->hwirq_target_hartindex =
+			sbi_zalloc(sizeof(*pd->hwirq_target_hartindex) *
+				   (pd->num_source + 1));
+		if (!pd->hwirq_target_hartindex) {
+			rc = SBI_ENOMEM;
+			goto fail_free_idc_map;
+		}
+
+		for (i = 0; i <= pd->num_source; i++)
+			pd->hwirq_target_hartindex[i] = -1U;
+
+		irqchip_aplic_fill_hwirq_targets_from_sysirq(fdt, nodeoff, pd);
+	}
+
 	rc = aplic_cold_irqchip_init(pd);
 	if (rc)
 		goto fail_free_idc_map;
@@ -93,6 +194,8 @@ static int irqchip_aplic_cold_init(const void *fdt, int nodeoff,
 	return 0;
 
 fail_free_idc_map:
+	if (pd->hwirq_target_hartindex)
+		sbi_free(pd->hwirq_target_hartindex);
 	if (pd->num_idc)
 		sbi_free(pd->idc_map);
 fail_free_data:
-- 
2.25.1


-- 
opensbi mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/opensbi
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.