Commit 68905ea6 authored by Marc Zyngier's avatar Marc Zyngier Committed by Thomas Gleixner
Browse files

irqchip/gic-v3: Add FW info retrieval support



Plug the new .get_fwspec_info() callback into the GICv3 core driver, using
some of the existing PPI affinity handling infrastructure.

Signed-off-by: default avatarMarc Zyngier <maz@kernel.org>
Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
Tested-by: default avatarWill Deacon <will@kernel.org>
Link: https://patch.msgid.link/20251020122944.3074811-6-maz@kernel.org
parent 0d5daa93
Loading
Loading
Loading
Loading
+53 −0
Original line number Diff line number Diff line
@@ -69,6 +69,8 @@ struct gic_chip_data {
	bool			has_rss;
	unsigned int		ppi_nr;
	struct partition_desc	**ppi_descs;
	struct partition_affinity *parts;
	unsigned int		nr_parts;
};

#define T241_CHIPS_MAX		4
@@ -1797,11 +1799,58 @@ static int gic_irq_domain_select(struct irq_domain *d,
	return d == partition_get_domain(gic_data.ppi_descs[ppi_idx]);
}

static int gic_irq_get_fwspec_info(struct irq_fwspec *fwspec, struct irq_fwspec_info *info)
{
	const struct cpumask *mask = NULL;

	info->flags = 0;
	info->affinity = NULL;

	/* ACPI is not capable of describing PPI affinity -- yet */
	if (!is_of_node(fwspec->fwnode))
		return 0;

	/* If the specifier provides an affinity, use it */
	if (fwspec->param_count == 4 && fwspec->param[3]) {
		struct fwnode_handle *fw;

		switch (fwspec->param[0]) {
		case 1:			/* PPI */
		case 3:			/* EPPI */
			break;
		default:
			return 0;
		}

		fw = of_fwnode_handle(of_find_node_by_phandle(fwspec->param[3]));
		if (!fw)
			return -ENOENT;

		for (int i = 0; i < gic_data.nr_parts; i++) {
			if (gic_data.parts[i].partition_id == fw) {
				mask = &gic_data.parts[i].mask;
				break;
			}
		}

		if (!mask)
			return -ENOENT;
	} else {
		mask = cpu_possible_mask;
	}

	info->affinity = mask;
	info->flags = IRQ_FWSPEC_INFO_AFFINITY_VALID;

	return 0;
}

static const struct irq_domain_ops gic_irq_domain_ops = {
	.translate = gic_irq_domain_translate,
	.alloc = gic_irq_domain_alloc,
	.free = gic_irq_domain_free,
	.select = gic_irq_domain_select,
	.get_fwspec_info = gic_irq_get_fwspec_info,
};

static int partition_domain_translate(struct irq_domain *d,
@@ -1840,6 +1889,7 @@ static int partition_domain_translate(struct irq_domain *d,
static const struct irq_domain_ops partition_domain_ops = {
	.translate = partition_domain_translate,
	.select = gic_irq_domain_select,
	.get_fwspec_info = gic_irq_get_fwspec_info,
};

static bool gic_enable_quirk_msm8996(void *data)
@@ -2232,6 +2282,9 @@ static void __init gic_populate_ppi_partitions(struct device_node *gic_node)
		part_idx++;
	}

	gic_data.parts = parts;
	gic_data.nr_parts = nr_parts;

	for (i = 0; i < gic_data.ppi_nr; i++) {
		unsigned int irq;
		struct partition_desc *desc;