Commit 1ab6383e authored by James Morse's avatar James Morse Committed by Zeng Heng
Browse files

ACPI / PPTT: Provide a helper to walk processor containers

maillist inclusion
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/I8T2RT

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/morse/linux.git/log/?h=mpam/snapshot/v6.7-rc2



---------------------------

The PPTT describes CPUs and caches, as well as processor containers.

To enable PPI partitions, the irqchip driver needs to know how many
partitions the platform has, and which CPUs belong to which partition.
When a percpu interrupt is registered, the partition is provided to allow
a different driver to request the same percpu interrupt intid, one per
partition.

The acpi_id of the Processor Container is the natural way to do this
with ACPI, but the DSDT AML interpreter is not available early enough
for the irqchipi driver. Fortunately, the same information can be
described in the PPTT.

Add a helper to count the number or Processor Containers in the PPTT.
This is structured as a walker/callback as the irqchip driver will
also use this to configure each partition.

Only Processor entries in the PPTT that have a valid acpi id are considered
as containers. To identify a particular Processor Container, it must have
an id.

Signed-off-by: default avatarJames Morse <james.morse@arm.com>
Signed-off-by: default avatarZeng Heng <zengheng4@huawei.com>
parent 689cbe75
Loading
Loading
Loading
Loading
+58 −0
Original line number Diff line number Diff line
@@ -21,6 +21,8 @@
#include <linux/cacheinfo.h>
#include <acpi/processor.h>

typedef int (*acpi_pptt_cpu_callback_t)(struct acpi_pptt_processor *, void *);

static struct acpi_subtable_header *fetch_pptt_subtable(struct acpi_table_header *table_hdr,
							u32 pptt_ref)
{
@@ -293,6 +295,62 @@ static struct acpi_pptt_processor *acpi_find_processor_node(struct acpi_table_he
	return NULL;
}

/**
 * acpi_pptt_for_each_container() - Iterate over all processor containers
 *
 * Not all 'Processor' entries in the PPTT are either a CPU or a Processor
 * Container, they may exist purely to describe a Private resource. CPUs
 * have to be leaves, so a Processor Container is a non-leaf that has the
 * 'ACPI Processor ID valid' flag set.
 *
 * Return: 0 for a complete walk, or the first non-zero value from the callback
 *         that stopped the walk.
 */
int acpi_pptt_for_each_container(acpi_pptt_cpu_callback_t callback, void *arg)
{
	struct acpi_pptt_processor *cpu_node;
	struct acpi_table_header *table_hdr;
	struct acpi_subtable_header *entry;
	bool leaf_flag, has_leaf_flag = false;
	unsigned long table_end;
	acpi_status status;
	u32 proc_sz;
	int ret = 0;

	status = acpi_get_table(ACPI_SIG_PPTT, 0, &table_hdr);
	if (ACPI_FAILURE(status))
		return 0;

	if (table_hdr->revision > 1)
		has_leaf_flag = true;

	table_end = (unsigned long)table_hdr + table_hdr->length;
	entry = ACPI_ADD_PTR(struct acpi_subtable_header, table_hdr,
			     sizeof(struct acpi_table_pptt));
	proc_sz = sizeof(struct acpi_pptt_processor);
	while ((unsigned long)entry + proc_sz < table_end) {
		cpu_node = (struct acpi_pptt_processor *)entry;
		if (entry->type == ACPI_PPTT_TYPE_PROCESSOR &&
		    cpu_node->flags & ACPI_PPTT_ACPI_PROCESSOR_ID_VALID)
		{
			leaf_flag = cpu_node->flags & ACPI_PPTT_ACPI_LEAF_NODE;
			if ((has_leaf_flag && !leaf_flag) ||
			    (!has_leaf_flag && !acpi_pptt_leaf_node(table_hdr, cpu_node)))
			{
				ret = callback(cpu_node, arg);
				if (ret)
					break;
			}
		}
		entry = ACPI_ADD_PTR(struct acpi_subtable_header, entry,
				     entry->length);
	}

	acpi_put_table(table_hdr);

	return ret;
}

static u8 acpi_cache_type(enum cache_type type)
{
	switch (type) {