|
@@ -8,6 +8,7 @@
|
|
|
#include <linux/export.h>
|
|
|
#include <linux/init.h>
|
|
|
#include <linux/jump_label.h>
|
|
|
+#include <linux/libfdt.h>
|
|
|
#include <linux/memblock.h>
|
|
|
#include <linux/printk.h>
|
|
|
#include <linux/sched.h>
|
|
@@ -671,12 +672,24 @@ static struct dt_cpu_feature_match __initdata
|
|
|
{"wait-v3", feat_enable, 0},
|
|
|
};
|
|
|
|
|
|
-/* XXX: how to configure this? Default + boot time? */
|
|
|
-#ifdef CONFIG_PPC_CPUFEATURES_ENABLE_UNKNOWN
|
|
|
-#define CPU_FEATURE_ENABLE_UNKNOWN 1
|
|
|
-#else
|
|
|
-#define CPU_FEATURE_ENABLE_UNKNOWN 0
|
|
|
-#endif
|
|
|
+static bool __initdata using_dt_cpu_ftrs;
|
|
|
+static bool __initdata enable_unknown = true;
|
|
|
+
|
|
|
+static int __init dt_cpu_ftrs_parse(char *str)
|
|
|
+{
|
|
|
+ if (!str)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ if (!strcmp(str, "off"))
|
|
|
+ using_dt_cpu_ftrs = false;
|
|
|
+ else if (!strcmp(str, "known"))
|
|
|
+ enable_unknown = false;
|
|
|
+ else
|
|
|
+ return 1;
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+early_param("dt_cpu_ftrs", dt_cpu_ftrs_parse);
|
|
|
|
|
|
static void __init cpufeatures_setup_start(u32 isa)
|
|
|
{
|
|
@@ -707,7 +720,7 @@ static bool __init cpufeatures_process_feature(struct dt_cpu_feature *f)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- if (!known && CPU_FEATURE_ENABLE_UNKNOWN) {
|
|
|
+ if (!known && enable_unknown) {
|
|
|
if (!feat_try_enable_unknown(f)) {
|
|
|
pr_info("not enabling: %s (unknown and unsupported by kernel)\n",
|
|
|
f->name);
|
|
@@ -756,6 +769,26 @@ static void __init cpufeatures_setup_finished(void)
|
|
|
cur_cpu_spec->cpu_features, cur_cpu_spec->mmu_features);
|
|
|
}
|
|
|
|
|
|
+static int __init disabled_on_cmdline(void)
|
|
|
+{
|
|
|
+ unsigned long root, chosen;
|
|
|
+ const char *p;
|
|
|
+
|
|
|
+ root = of_get_flat_dt_root();
|
|
|
+ chosen = of_get_flat_dt_subnode_by_name(root, "chosen");
|
|
|
+ if (chosen == -FDT_ERR_NOTFOUND)
|
|
|
+ return false;
|
|
|
+
|
|
|
+ p = of_get_flat_dt_prop(chosen, "bootargs", NULL);
|
|
|
+ if (!p)
|
|
|
+ return false;
|
|
|
+
|
|
|
+ if (strstr(p, "dt_cpu_ftrs=off"))
|
|
|
+ return true;
|
|
|
+
|
|
|
+ return false;
|
|
|
+}
|
|
|
+
|
|
|
static int __init fdt_find_cpu_features(unsigned long node, const char *uname,
|
|
|
int depth, void *data)
|
|
|
{
|
|
@@ -766,8 +799,6 @@ static int __init fdt_find_cpu_features(unsigned long node, const char *uname,
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-static bool __initdata using_dt_cpu_ftrs = false;
|
|
|
-
|
|
|
bool __init dt_cpu_ftrs_in_use(void)
|
|
|
{
|
|
|
return using_dt_cpu_ftrs;
|
|
@@ -775,6 +806,8 @@ bool __init dt_cpu_ftrs_in_use(void)
|
|
|
|
|
|
bool __init dt_cpu_ftrs_init(void *fdt)
|
|
|
{
|
|
|
+ using_dt_cpu_ftrs = false;
|
|
|
+
|
|
|
/* Setup and verify the FDT, if it fails we just bail */
|
|
|
if (!early_init_dt_verify(fdt))
|
|
|
return false;
|
|
@@ -782,6 +815,9 @@ bool __init dt_cpu_ftrs_init(void *fdt)
|
|
|
if (!of_scan_flat_dt(fdt_find_cpu_features, NULL))
|
|
|
return false;
|
|
|
|
|
|
+ if (disabled_on_cmdline())
|
|
|
+ return false;
|
|
|
+
|
|
|
cpufeatures_setup_cpu();
|
|
|
|
|
|
using_dt_cpu_ftrs = true;
|
|
@@ -1027,5 +1063,8 @@ static int __init dt_cpu_ftrs_scan_callback(unsigned long node, const char
|
|
|
|
|
|
void __init dt_cpu_ftrs_scan(void)
|
|
|
{
|
|
|
+ if (!using_dt_cpu_ftrs)
|
|
|
+ return;
|
|
|
+
|
|
|
of_scan_flat_dt(dt_cpu_ftrs_scan_callback, NULL);
|
|
|
}
|