static int __init dt_cpu_ftrs_scan_callback(unsigned long node, const char *uname, int depth, void *data) { const __be32 *prop; int count, i; u32 isa; /* We are scanning "ibm,powerpc-cpu-features" nodes only */ if (!of_flat_dt_is_compatible(node, "ibm,powerpc-cpu-features")) return 0; prop = of_get_flat_dt_prop(node, "isa", NULL); if (!prop) /* We checked before, "can't happen" */ return 0; isa = be32_to_cpup(prop); /* Count and allocate space for cpu features */ of_scan_flat_dt_subnodes(node, count_cpufeatures_subnodes, &nr_dt_cpu_features); dt_cpu_features = __va( memblock_alloc(sizeof(struct dt_cpu_feature)* nr_dt_cpu_features, PAGE_SIZE)); cpufeatures_setup_start(isa); /* Scan nodes into dt_cpu_features and enable those without deps */ count = 0; of_scan_flat_dt_subnodes(node, scan_cpufeatures_subnodes, &count); /* Recursive enable remaining features with dependencies */ for (i = 0; i < nr_dt_cpu_features; i++) { struct dt_cpu_feature *f = &dt_cpu_features[i]; cpufeatures_deps_enable(f); } prop = of_get_flat_dt_prop(node, "display-name", NULL); if (prop && strlen((char *)prop) != 0) { strlcpy(dt_cpu_name, (char *)prop, sizeof(dt_cpu_name)); cur_cpu_spec->cpu_name = dt_cpu_name; } cpufeatures_setup_finished(); memblock_free(__pa(dt_cpu_features), sizeof(struct dt_cpu_feature)*nr_dt_cpu_features); return 0; }
static void __init cpufeatures_deps_enable(struct dt_cpu_feature *f) { const __be32 *prop; int len; int nr_deps; int i; if (f->enabled || f->disabled) return; prop = of_get_flat_dt_prop(f->node, "dependencies", &len); if (!prop) { pr_warn("%s: missing dependencies property", f->name); return; } nr_deps = len / sizeof(int); for (i = 0; i < nr_deps; i++) { unsigned long phandle = be32_to_cpu(prop[i]); int j; for (j = 0; j < nr_dt_cpu_features; j++) { struct dt_cpu_feature *d = &dt_cpu_features[j]; if (of_get_flat_dt_phandle(d->node) == phandle) { cpufeatures_deps_enable(d); if (d->disabled) { f->disabled = 1; return; } } } } if (cpufeatures_process_feature(f)) f->enabled = 1; else f->disabled = 1; }