drivers/base/arch_topology.c

Source file repositories/reference/linux-study-clean/drivers/base/arch_topology.c

File Facts

System
Linux kernel
Corpus path
drivers/base/arch_topology.c
Extension
.c
Size
24830 bytes
Lines
980
Domain
Driver Families
Bucket
drivers/base
Inferred role
Driver Families: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

core_initcall(register_cpufreq_notifier);

static void parsing_done_workfn(struct work_struct *work)
{
	cpufreq_unregister_notifier(&init_cpu_capacity_notifier,
					 CPUFREQ_POLICY_NOTIFIER);
	free_cpumask_var(cpus_to_visit);
}

#else
core_initcall(free_raw_capacity);
#endif

#if defined(CONFIG_ARM64) || defined(CONFIG_RISCV)

/* Used to enable the SMT control */
static unsigned int max_smt_thread_num = 1;

/*
 * This function returns the logic cpu number of the node.
 * There are basically three kinds of return values:
 * (1) logic cpu number which is > 0.
 * (2) -ENODEV when the device tree(DT) node is valid and found in the DT but
 * there is no possible logical CPU in the kernel to match. This happens
 * when CONFIG_NR_CPUS is configure to be smaller than the number of
 * CPU nodes in DT. We need to just ignore this case.
 * (3) -1 if the node does not exist in the device tree
 */
static int __init get_cpu_for_node(struct device_node *node)
{
	int cpu;
	struct device_node *cpu_node __free(device_node) =
		of_parse_phandle(node, "cpu", 0);

	if (!cpu_node)
		return -1;

	cpu = of_cpu_node_to_id(cpu_node);
	if (cpu >= 0)
		topology_parse_cpu_capacity(cpu_node, cpu);
	else
		pr_info("CPU node for %pOF exist but the possible cpu range is :%*pbl\n",
			cpu_node, cpumask_pr_args(cpu_possible_mask));

	return cpu;
}

static int __init parse_core(struct device_node *core, int package_id,
			     int cluster_id, int core_id)
{
	char name[20];
	bool leaf = true;
	int i = 0;
	int cpu;

	do {
		snprintf(name, sizeof(name), "thread%d", i);
		struct device_node *t __free(device_node) =
			of_get_child_by_name(core, name);

		if (!t)
			break;

		leaf = false;
		cpu = get_cpu_for_node(t);
		if (cpu >= 0) {
			cpu_topology[cpu].package_id = package_id;
			cpu_topology[cpu].cluster_id = cluster_id;
			cpu_topology[cpu].core_id = core_id;
			cpu_topology[cpu].thread_id = i;
		} else if (cpu != -ENODEV) {
			pr_err("%pOF: Can't get CPU for thread\n", t);
			return -EINVAL;
		}
		i++;
	} while (1);

	max_smt_thread_num = max_t(unsigned int, max_smt_thread_num, i);

	cpu = get_cpu_for_node(core);
	if (cpu >= 0) {
		if (!leaf) {
			pr_err("%pOF: Core has both threads and CPU\n",
			       core);
			return -EINVAL;
		}

		cpu_topology[cpu].package_id = package_id;
		cpu_topology[cpu].cluster_id = cluster_id;
		cpu_topology[cpu].core_id = core_id;

Annotation

Implementation Notes