/* * Enumerate the possible CPU set from the device tree. */ void __init smp_init_cpus(void) { const char *enable_method; struct device_node *dn = NULL; int cpu = 0; while ((dn = of_find_node_by_type(dn, "cpu"))) { if (cpu >= NR_CPUS) goto next; /* * We currently support only the "spin-table" enable-method. */ enable_method = of_get_property(dn, "enable-method", NULL); if (!enable_method) { pr_err("CPU %d: missing enable-method property\n", cpu); goto next; } smp_enable_ops[cpu] = smp_get_enable_ops(enable_method); if (!smp_enable_ops[cpu]) { pr_err("CPU %d: invalid enable-method property: %s\n", cpu, enable_method); goto next; } if (smp_enable_ops[cpu]->init_cpu(dn, cpu)) goto next; set_cpu_possible(cpu, true); next: cpu++; } /* sanity check */ if (cpu > NR_CPUS) pr_warning("no. of cores (%d) greater than configured maximum of %d - clipping\n", cpu, NR_CPUS); }
/* * Enumerate the possible CPU set from the device tree and build the * cpu logical map array containing MPIDR values related to logical * cpus. Assumes that cpu_logical_map(0) has already been initialized. */ void __init smp_init_cpus(void) { const char *enable_method; struct device_node *dn = NULL; int i, cpu = 1; bool bootcpu_valid = false; while ((dn = of_find_node_by_type(dn, "cpu"))) { const u32 *cell; u64 hwid; /* * A cpu node with missing "reg" property is * considered invalid to build a cpu_logical_map * entry. */ cell = of_get_property(dn, "reg", NULL); if (!cell) { pr_err("%s: missing reg property\n", dn->full_name); goto next; } hwid = of_read_number(cell, of_n_addr_cells(dn)); /* * Non affinity bits must be set to 0 in the DT */ if (hwid & ~MPIDR_HWID_BITMASK) { pr_err("%s: invalid reg property\n", dn->full_name); goto next; } /* * Duplicate MPIDRs are a recipe for disaster. Scan * all initialized entries and check for * duplicates. If any is found just ignore the cpu. * cpu_logical_map was initialized to INVALID_HWID to * avoid matching valid MPIDR values. */ for (i = 1; (i < cpu) && (i < NR_CPUS); i++) { if (cpu_logical_map(i) == hwid) { pr_err("%s: duplicate cpu reg properties in the DT\n", dn->full_name); goto next; } } /* * The numbering scheme requires that the boot CPU * must be assigned logical id 0. Record it so that * the logical map built from DT is validated and can * be used. */ if (hwid == cpu_logical_map(0)) { if (bootcpu_valid) { pr_err("%s: duplicate boot cpu reg property in DT\n", dn->full_name); goto next; } bootcpu_valid = true; /* * cpu_logical_map has already been * initialized and the boot cpu doesn't need * the enable-method so continue without * incrementing cpu. */ continue; } if (cpu >= NR_CPUS) goto next; /* * We currently support only the "spin-table" enable-method. */ enable_method = of_get_property(dn, "enable-method", NULL); if (!enable_method) { pr_err("%s: missing enable-method property\n", dn->full_name); goto next; } smp_enable_ops[cpu] = smp_get_enable_ops(enable_method); if (!smp_enable_ops[cpu]) { pr_err("%s: invalid enable-method property: %s\n", dn->full_name, enable_method); goto next; } if (smp_enable_ops[cpu]->init_cpu(dn, cpu)) goto next; pr_debug("cpu logical map 0x%llx\n", hwid); cpu_logical_map(cpu) = hwid; next: cpu++; } /* sanity check */ if (cpu > NR_CPUS) pr_warning("no. of cores (%d) greater than configured maximum of %d - clipping\n", cpu, NR_CPUS); if (!bootcpu_valid) { pr_err("DT missing boot CPU MPIDR, not enabling secondaries\n"); return; } /* * All the cpus that made it to the cpu_logical_map have been * validated so set them as possible cpus. */ for (i = 0; i < NR_CPUS; i++) if (cpu_logical_map(i) != INVALID_HWID) set_cpu_possible(i, true); }