diff options
author | Mathieu Briand <mathieu.briand@linaro.org> | 2012-05-11 11:29:18 +0200 |
---|---|---|
committer | Andrey Konovalov <andrey.konovalov@linaro.org> | 2013-05-25 13:04:35 +0400 |
commit | 0a6da5300c989d978190637506a3a064d3a52492 (patch) | |
tree | ac60c00fc5a80cce9ae8579d73714d1478de5fac /drivers | |
parent | fd54d96fcaed9c77f1d4fe7d3ba14f8ac4dcee3f (diff) |
cpufreq/arm-bl-cpufreq: unit tests
Add in-modules tests on arm-bl-cpufreq cpufreq driver.
To build the tests, add the following config option:
ARM_BL_CPUFREQ_TEST=y
The tests will run when the driver is loaded, but they are not run
by default. To run the tests, you need to pass the option
test_config=1 to the arm-bl-cpufreq driver when loading it.
Signed-off-by: Mathieu Briand <mathieu.briand@linaro.org>
Signed-off-by: Dave Martin <dave.martin@linaro.org>
Signed-off-by: Nicolas Pitre <nicolas.pitre@linaro.org>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/cpufreq/Kconfig.arm | 9 | ||||
-rw-r--r-- | drivers/cpufreq/arm-bl-cpufreq.c | 45 | ||||
-rw-r--r-- | drivers/cpufreq/arm-bl-cpufreq.h | 37 | ||||
-rw-r--r-- | drivers/cpufreq/arm-bl-cpufreq_tests.c | 652 |
4 files changed, 725 insertions, 18 deletions
diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm index 97dd3fc49a3..204812a5b92 100644 --- a/drivers/cpufreq/Kconfig.arm +++ b/drivers/cpufreq/Kconfig.arm @@ -14,6 +14,15 @@ config ARM_BL_CPUFREQ If unsure, say N. +config ARM_BL_CPUFREQ_TEST + depends on ARM_BL_CPUFREQ + bool "Unit testing on cpufreq interface for the ARM big.LITTLE switcher" + help + Make tests on the cpufreq interface for the ARM big.LITTLE + switcher before loading it. + + If unsure, say N. + config ARM_OMAP2PLUS_CPUFREQ bool "TI OMAP2+" depends on ARCH_OMAP2PLUS diff --git a/drivers/cpufreq/arm-bl-cpufreq.c b/drivers/cpufreq/arm-bl-cpufreq.c index 0d7d0fcd4e3..bc633f2d7b0 100644 --- a/drivers/cpufreq/arm-bl-cpufreq.c +++ b/drivers/cpufreq/arm-bl-cpufreq.c @@ -18,7 +18,8 @@ */ #define MODULE_NAME "arm-bl-cpufreq" -#define pr_fmt(fmt) MODULE_NAME ": " fmt +#define __module_pr_fmt(prefix, fmt) MODULE_NAME ": " prefix fmt +#define pr_fmt(fmt) __module_pr_fmt("", fmt) #include <linux/bug.h> #include <linux/cache.h> @@ -32,6 +33,17 @@ #include <asm/bL_switcher.h> +#include "arm-bl-cpufreq.h" + +/* + * Include tests prototypes and includes + * We need to include this file a second time with ARM_BL_CPUFREQ_DEFINE_TESTS + * defined to include functions body. + */ +#include "arm-bl-cpufreq_tests.c" + +#define ARM_BL_CPUFREQ_DEFINE_TESTS +#include "arm-bl-cpufreq_tests.c" /* Dummy frequencies representing the big and little clusters: */ #define FREQ_BIG 1000000 @@ -41,22 +53,6 @@ #define CLUSTER_BIG 0 #define CLUSTER_LITTLE 1 -/* - * Switch latency advertised to cpufreq. This value is bogus and will - * need to be properly calibrated when running on real hardware. - */ -#define BL_CPUFREQ_FAKE_LATENCY 1 - -static struct cpufreq_frequency_table __read_mostly bl_freqs[] = { - { CLUSTER_BIG, FREQ_BIG }, - { CLUSTER_LITTLE, FREQ_LITTLE }, - { 0, CPUFREQ_TABLE_END }, -}; - -/* Cached current cluster for each CPU to save on IPIs */ -static DEFINE_PER_CPU(unsigned int, cpu_cur_cluster); - - /* Miscellaneous helpers */ static unsigned int entry_to_freq( @@ -237,13 +233,26 @@ static int __init bl_cpufreq_module_init(void) { int err; + /* test_config : + * - 0: Do not run tests + * - 1: Run tests and then register cpufreq driver if tests passed + */ + if ((test_config > 0) && (pre_init_tests() != 0)) + return -EINVAL; + err = cpufreq_register_driver(&bl_cpufreq_driver); if(err) pr_info("cpufreq backend driver registration failed (%d)\n", err); - else + else { pr_info("cpufreq backend driver registered.\n"); + if ((test_config > 0) && (post_init_tests() != 0)) { + cpufreq_unregister_driver(&bl_cpufreq_driver); + return -EINVAL; + } + } + return err; } module_init(bl_cpufreq_module_init); diff --git a/drivers/cpufreq/arm-bl-cpufreq.h b/drivers/cpufreq/arm-bl-cpufreq.h new file mode 100644 index 00000000000..b13bb8c543d --- /dev/null +++ b/drivers/cpufreq/arm-bl-cpufreq.h @@ -0,0 +1,37 @@ +#ifndef ARM_BL_CPUFREQ_H +#define ARM_BL_CPUFREQ_H + +/* Dummy frequencies representing the big and little clusters: */ +#define FREQ_BIG 1000000 +#define FREQ_LITTLE 100000 + +/* Cluster numbers */ +#define CLUSTER_BIG 0 +#define CLUSTER_LITTLE 1 + +/* + * Switch latency advertised to cpufreq. This value is bogus and will + * need to be properly calibrated when running on real hardware. + */ +#define BL_CPUFREQ_FAKE_LATENCY 1 + +static struct cpufreq_frequency_table __read_mostly bl_freqs[] = { + { CLUSTER_BIG, FREQ_BIG }, + { CLUSTER_LITTLE, FREQ_LITTLE }, + { 0, CPUFREQ_TABLE_END }, +}; + +/* Cached current cluster for each CPU to save on IPIs */ +static DEFINE_PER_CPU(unsigned int, cpu_cur_cluster); + +static unsigned int entry_to_freq(struct cpufreq_frequency_table const *entry); +static unsigned int entry_to_cluster( + struct cpufreq_frequency_table const *entry); +static struct cpufreq_frequency_table const *find_entry_by_cluster(int cluster); +static unsigned int cluster_to_freq(int cluster); +static int get_current_cluster(unsigned int cpu); +static int get_current_cached_cluster(unsigned int cpu); +static unsigned int get_current_freq(unsigned int cpu); +static unsigned int bl_cpufreq_get(unsigned int cpu); + +#endif /* ! ARM_BL_CPUFREQ_H */ diff --git a/drivers/cpufreq/arm-bl-cpufreq_tests.c b/drivers/cpufreq/arm-bl-cpufreq_tests.c new file mode 100644 index 00000000000..da349e165f4 --- /dev/null +++ b/drivers/cpufreq/arm-bl-cpufreq_tests.c @@ -0,0 +1,652 @@ +/* + * arm-bl-cpufreqtests.c: Unit tests on the simple cpufreq backend for the + * ARM big.LITTLE switcher + * Copyright (C) 2012 Linaro Limited + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef ARM_BL_CPUFREQ_DEFINE_TESTS +#include <linux/cpufreq.h> +#include <linux/module.h> +#include <linux/printk.h> +#include <linux/delay.h> +#include <linux/sched.h> + +#include "arm-bl-cpufreq.h" + +static short int test_config; + +static int pre_init_tests(void); +static int post_init_tests(void); + +#else /* ! ARM_BL_CPUFREQ_DEFINE_TESTS */ + +#ifdef CONFIG_ARM_BL_CPUFREQ_TEST + +#ifdef pr_fmt +#undef pr_fmt +#endif +#define pr_fmt(fmt) __module_pr_fmt("[test] ", fmt) + +#define SWITCH_DELAY 10 +#define SWITCH_TRANSITION_DELAY 200 +#define POST_INIT_TESTS_DELAY 100 + +static DECLARE_WAIT_QUEUE_HEAD(test_wq); +static int test_transition_count; +unsigned int test_transition_freq; + +module_param(test_config, short, 1); +MODULE_PARM_DESC(test_config, "Make tests before registering cpufreq driver. (0 : no tests, 1 : tests and registering driver (default))"); + +static struct cpufreq_frequency_table const *get_other_entry( + struct cpufreq_frequency_table const *entry) +{ + if (entry_to_cluster(entry) == CLUSTER_BIG) + return find_entry_by_cluster(CLUSTER_LITTLE); + else + return find_entry_by_cluster(CLUSTER_BIG); +} + +static int test_cpufreq_frequency_table(void) +{ + int nTest = 0, failCount = 0, testResult = 0; + struct cpufreq_frequency_table const *entry; + + /* Get big and little cpufreq_frequency_table entries and check + * entry_to_freq() and entry_to_cluster() return corresponding + * frequencies and cluster id. + */ + entry = find_entry_by_cluster(CLUSTER_BIG); + + ++nTest; + if (entry_to_freq(entry) != FREQ_BIG) { + testResult = 0; + ++failCount; + } else + testResult = 1; + pr_info("name=pre-init/frequency_table/%d:entry_to_freq(big) result=%s\n", + nTest, (testResult ? "PASS" : "FAIL")); + + ++nTest; + if (entry_to_cluster(entry) != CLUSTER_BIG) { + testResult = 0; + ++failCount; + } else + testResult = 1; + pr_info("name=pre-init/frequency_table/%d:entry_to_cluster(big) result=%s\n", + nTest, (testResult ? "PASS" : "FAIL")); + + entry = find_entry_by_cluster(CLUSTER_LITTLE); + + ++nTest; + if (entry_to_freq(entry) != FREQ_LITTLE) { + testResult = 0; + ++failCount; + } else + testResult = 1; + pr_info("name=pre-init/frequency_table/%d:entry_to_freq(little) result=%s\n", + nTest, (testResult ? "PASS" : "FAIL")); + + ++nTest; + if (entry_to_cluster(entry) != CLUSTER_LITTLE) { + testResult = 0; + ++failCount; + } else + testResult = 1; + pr_info("name=pre-init/frequency_table/%d:entry_to_cluster(little) result=%s\n", + nTest, (testResult ? "PASS" : "FAIL")); + + pr_info("name=pre-init/frequency_table run=%d result=%s pass=%d fail=%d\n", + nTest, (failCount == 0 ? "PASS" : "FAIL"), + (nTest - failCount), failCount); + if (failCount != 0) + return -1; + + return 0; +} + +static int test_cluster_to_freq(void) +{ + int nTest = 0, failCount = 0, testResult = 0; + + /* Check if test_cluster_to_freq() result is consistent, ie : + * - CLUSTER_BIG => FREQ_BIG + * - CLUSTER_LITTLE => FREQ_LITTLE + */ + ++nTest; + if (cluster_to_freq(CLUSTER_BIG) != FREQ_BIG) { + testResult = 0; + ++failCount; + } else + testResult = 1; + pr_info("name=pre-init/cluster_to_freq/%d:cluster_to_freq(big) result=%s\n", + nTest, (testResult ? "PASS" : "FAIL")); + + ++nTest; + if (cluster_to_freq(CLUSTER_LITTLE) != FREQ_LITTLE) { + testResult = 0; + ++failCount; + } else + testResult = 1; + pr_info("name=pre-init/cluster_to_freq/%d:cluster_to_freq(little) result=%s\n", + nTest, (testResult ? "PASS" : "FAIL")); + + pr_info("name=pre-init/cluster_to_freq run=%d result=%s pass=%d fail=%d\n", + nTest, (failCount == 0 ? "PASS" : "FAIL"), + (nTest - failCount), failCount); + if (failCount != 0) + return -1; + + return 0; +} + +static int test_get_current_cluster(void) +{ + int nTest = 0, failCount = 0, testResult = 0; + unsigned int cluster, cpu; + + /* Check if get_current_cluster() return a consistent value, ie + * CLUSTER_BIG or CLUSTER_LITTLE + */ + for_each_cpu(cpu, cpu_present_mask) { + cluster = get_current_cluster(cpu); + ++nTest; + if ((cluster != CLUSTER_BIG) && (cluster != CLUSTER_LITTLE)) { + testResult = 0; + ++failCount; + } else + testResult = 1; + pr_info("name=pre-init/get_current_cluster/%d:get_current_cluster(%u) result=%s\n", + nTest, cpu, (testResult ? "PASS" : "FAIL")); + } + + pr_info("name=pre-init/get_current_cluster run=%d result=%s pass=%d fail=%d\n", + nTest, (failCount == 0 ? "PASS" : "FAIL"), + (nTest - failCount), failCount); + if (failCount != 0) + return -1; + + return 0; +} + +static int test_bl_cpufreq_get(void) +{ + int nTest = 0, failCount = 0, testResult = 0; + unsigned int cpu; + struct cpufreq_frequency_table const *other_entry = NULL; + struct cpufreq_frequency_table const *origin_entry = NULL; + struct cpufreq_policy *policy = NULL; + + /* + * Check bl_cpufreq_get() return value : for all cores value has to be + * the frequency of origin_entry + */ + for_each_cpu(cpu, cpu_present_mask) { + policy = cpufreq_cpu_get(cpu); + origin_entry = find_entry_by_cluster(get_current_cluster(cpu)); + other_entry = get_other_entry(origin_entry); + + ++nTest; + if (bl_cpufreq_get(cpu) != entry_to_freq(origin_entry)) { + testResult = 0; + ++failCount; + } else + testResult = 1; + pr_info("name=post-init/bl_cpufreq_get/%d:origin(%u) result=%s\n", + nTest, cpu, (testResult ? "PASS" : "FAIL")); + + /* + * Switch to "other" cluster, ie cluster not used at module + * loading time + */ + cpufreq_driver_target(policy, entry_to_freq(other_entry), + CPUFREQ_RELATION_H); + + ++nTest; + if (bl_cpufreq_get(cpu) != entry_to_freq(other_entry)) { + testResult = 0; + ++failCount; + } else + testResult = 1; + pr_info("name=post-init/bl_cpufreq_get/%d:other(%u) result=%s\n", + nTest, cpu, (testResult ? "PASS" : "FAIL")); + + /* + * Switch back to "origin" cluster, ie cluster used at module + * loading time + */ + cpufreq_driver_target(policy, entry_to_freq(origin_entry), + CPUFREQ_RELATION_H); + cpufreq_cpu_put(policy); + } + + pr_info("name=post-init/bl_cpufreq_get run=%d result=%s pass=%d fail=%d\n", + nTest, (failCount == 0 ? "PASS" : "FAIL"), + (nTest - failCount), failCount); + if (failCount != 0) + return -1; + + return 0; +} + +static int test_get_current_freq(void) +{ + int nTest = 0, failCount = 0, testResult = 0; + unsigned int cpu; + struct cpufreq_frequency_table const *other_entry = NULL; + struct cpufreq_frequency_table const *origin_entry = NULL; + struct cpufreq_policy *policy = NULL; + + /* + * Check if get_current_freq() return a consistent value, ie + * FREQ_BIG while on big cluster and FREQ_LITTLE on little cluster + */ + for_each_cpu(cpu, cpu_present_mask) { + policy = cpufreq_cpu_get(cpu); + origin_entry = find_entry_by_cluster(get_current_cluster(cpu)); + other_entry = get_other_entry(origin_entry); + + ++nTest; + if (get_current_freq(cpu) != entry_to_freq(origin_entry)) { + testResult = 0; + ++failCount; + } else + testResult = 1; + pr_info("name=post-init/get_current_freq/%d:origin(%u) result=%s\n", + nTest, cpu, (testResult ? "PASS" : "FAIL")); + + /* + * Switch to "other" cluster, ie cluster not used at module + * loading time + */ + cpufreq_driver_target(policy, entry_to_freq(other_entry), + CPUFREQ_RELATION_H); + + ++nTest; + if (get_current_freq(cpu) != entry_to_freq(other_entry)) { + testResult = 0; + ++failCount; + } else + testResult = 1; + pr_info("name=post-init/get_current_freq/%d:other(%u) result=%s\n", + nTest, cpu, (testResult ? "PASS" : "FAIL")); + + /* + * Switch back to "origin" cluster, ie cluster used at module + * loading time + */ + cpufreq_driver_target(policy, entry_to_freq(origin_entry), + CPUFREQ_RELATION_H); + cpufreq_cpu_put(policy); + } + + pr_info("name=post-init/get_current_freq run=%d result=%s pass=%d fail=%d\n", + nTest, (failCount == 0 ? "PASS" : "FAIL"), + (nTest - failCount), failCount); + if (failCount != 0) + return -1; + + return 0; +} + +static int test_get_current_cached_cluster(void) +{ + int nTest = 0, failCount = 0, testResult = 0; + unsigned int cpu, cluster; + struct cpufreq_frequency_table const *other_entry = NULL; + struct cpufreq_frequency_table const *origin_entry = NULL; + struct cpufreq_policy *policy = NULL; + + /* + * Check if get_current_cached_cluster() return a consistent value, ie + * CLUSTER_BIG while on big cluster and CLUSTER_LITTLE on little cluster + */ + for_each_cpu(cpu, cpu_present_mask) { + policy = cpufreq_cpu_get(cpu); + origin_entry = find_entry_by_cluster(get_current_cluster(cpu)); + other_entry = get_other_entry(origin_entry); + + ++nTest; + cluster = get_current_cached_cluster(cpu); + if (cluster != entry_to_cluster(origin_entry)) { + testResult = 0; + ++failCount; + } else + testResult = 1; + pr_info("name=post-init/get_current_cached_cluster/%d:origin(%u) result=%s\n", + nTest, cpu, (testResult ? "PASS" : "FAIL")); + + /* + * Switch to "other" cluster, ie cluster not used at module + * loading time + */ + cpufreq_driver_target(policy, entry_to_freq(other_entry), + CPUFREQ_RELATION_H); + + ++nTest; + cluster = get_current_cached_cluster(cpu); + if (cluster != entry_to_cluster(other_entry)) { + testResult = 0; + ++failCount; + } else + testResult = 1; + pr_info("name=post-init/get_current_cached_cluster/%d:other(%u) result=%s\n", + nTest, cpu, (testResult ? "PASS" : "FAIL")); + + /* + * Switch back to "origin" cluster, ie cluster used at module + * loading time + */ + cpufreq_driver_target(policy, entry_to_freq(origin_entry), + CPUFREQ_RELATION_H); + cpufreq_cpu_put(policy); + } + + pr_info("name=post-init/get_current_cached_cluster run=%d result=%s pass=%d fail=%d\n", + nTest, (failCount == 0 ? "PASS" : "FAIL"), + (nTest - failCount), failCount); + if (failCount != 0) + return -1; + + return 0; +} + +static int test_cpufreq_driver_target(void) +{ + int nTest = 0, failCount = 0, testResult = 0; + unsigned int cpu; + struct cpufreq_frequency_table const *other_entry = NULL; + struct cpufreq_frequency_table const *origin_entry = NULL; + struct cpufreq_policy *policy = NULL; + + /* + * Try to switch between cluster and check if switch was performed with + * success + */ + for_each_cpu(cpu, cpu_present_mask) { + policy = cpufreq_cpu_get(cpu); + origin_entry = find_entry_by_cluster(get_current_cluster(cpu)); + other_entry = get_other_entry(origin_entry); + + /* Switch to "other" cluster, ie cluster not used at module + * loading time + */ + cpufreq_driver_target(policy, entry_to_freq(other_entry), + CPUFREQ_RELATION_H); + + /* + * Give the hardware some time to switch between clusters + */ + mdelay(SWITCH_DELAY); + + ++nTest; + if (get_current_cluster(cpu) != entry_to_cluster(other_entry)) { + testResult = 0; + ++failCount; + } else + testResult = 1; + pr_info("name=post-init/cpufreq_driver_target/%d:other(%u) result=%s\n", + nTest, cpu, (testResult ? "PASS" : "FAIL")); + + /* Switch again to "other" cluster + */ + cpufreq_driver_target(policy, entry_to_freq(other_entry), + CPUFREQ_RELATION_H); + /* + * Give the hardware some time to switch between clusters + */ + mdelay(SWITCH_DELAY); + + ++nTest; + if (get_current_cluster(cpu) != entry_to_cluster(other_entry)) { + testResult = 0; + ++failCount; + } else + testResult = 1; + pr_info("name=post-init/cpufreq_driver_target/%d:otherAgain(%u) result=%s\n", + nTest, cpu, (testResult ? "PASS" : "FAIL")); + + /* Switch back to "origin" cluster, ie cluster used at module loading + * time + */ + cpufreq_driver_target(policy, entry_to_freq(origin_entry), + CPUFREQ_RELATION_H); + /* + * Give the hardware some time to switch between clusters + */ + mdelay(SWITCH_DELAY); + + ++nTest; + if (get_current_cluster(cpu) != entry_to_cluster(origin_entry)) + { + testResult = 0; + ++failCount; + } else + testResult = 1; + pr_info("name=post-init/cpufreq_driver_target/%d:origin(%u) result=%s\n", + nTest, cpu, (testResult ? "PASS" : "FAIL")); + + /* Switch again to "origin" cluster + */ + cpufreq_driver_target(policy, entry_to_freq(origin_entry), + CPUFREQ_RELATION_H); + /* + * Give the hardware some time to switch between clusters + */ + mdelay(SWITCH_DELAY); + + ++nTest; + if (get_current_cluster(cpu) != entry_to_cluster(origin_entry)) + { + testResult = 0; + ++failCount; + } else + testResult = 1; + pr_info("name=post-init/cpufreq_driver_target/%d:originAgain(%u) result=%s\n", + nTest, cpu, (testResult ? "PASS" : "FAIL")); + + cpufreq_cpu_put(policy); + } + + pr_info("name=post-init/cpufreq_driver_target run=%d result=%s pass=%d fail=%d\n", + nTest, (failCount == 0 ? "PASS" : "FAIL"), + (nTest - failCount), failCount); + if (failCount != 0) + return -1; + + return 0; +} + +/* Check that new frequency is expected frequency, increment count and wake up + * test function. + */ +static int test_arm_bl_cpufreq_notifier(struct notifier_block *nb, + unsigned long val, void *data) +{ + struct cpufreq_freqs *freq = data; + + if (freq->new != test_transition_freq) + test_transition_freq = -1; + + ++test_transition_count; + + wake_up(&test_wq); + + return 0; +} +static struct notifier_block test_arm_bl_cpufreq_notifier_block = { + .notifier_call = test_arm_bl_cpufreq_notifier +}; + +static int test_transitions(void) +{ + int nTest = 0, failCount = 0, testResult = 0; + unsigned int cpu, origin_freq, other_freq; + struct cpufreq_frequency_table const *other_entry = NULL; + struct cpufreq_frequency_table const *origin_entry = NULL; + struct cpufreq_policy *policy = NULL; + + /* + * register test_arm_bl_cpufreq_notifier_block as notifier : + * test_arm_bl_cpufreq_notifier_block will be called on cluster + * change and increment transition_count + */ + cpufreq_register_notifier(&test_arm_bl_cpufreq_notifier_block, + CPUFREQ_TRANSITION_NOTIFIER); + + /* + * Switch between cluster and check if notifications are received + */ + for_each_cpu(cpu, cpu_present_mask) { + policy = cpufreq_cpu_get(cpu); + origin_entry = find_entry_by_cluster(get_current_cluster(cpu)); + other_entry = get_other_entry(origin_entry); + origin_freq = entry_to_freq(origin_entry); + other_freq = entry_to_freq(other_entry); + + /* Switch on little cluster and check notification + */ + ++nTest; + test_transition_count = 0; + test_transition_freq = other_freq; + cpufreq_driver_target(policy, other_freq, CPUFREQ_RELATION_H); + wait_event_timeout(test_wq, (test_transition_count == 2), + msecs_to_jiffies(SWITCH_TRANSITION_DELAY)); + + if ((test_transition_count != 2) + || (test_transition_freq != other_freq)) { + testResult = 0; + ++failCount; + } else + testResult = 1; + pr_info("name=post-init/transitions/%d:other(%u) result=%s\n", + nTest, cpu, (testResult ? "PASS" : "FAIL")); + + /* Switch on big cluster and check notification + */ + ++nTest; + test_transition_count = 0; + test_transition_freq = origin_freq; + cpufreq_driver_target(policy, origin_freq, CPUFREQ_RELATION_H); + wait_event_timeout(test_wq, (test_transition_count == 2), + msecs_to_jiffies(SWITCH_TRANSITION_DELAY)); + + if ((test_transition_count != 2) + || (test_transition_freq != origin_freq)) { + testResult = 0; + ++failCount; + } else + testResult = 1; + pr_info("name=post-init/transitions/%d:origin(%u) result=%s\n", + nTest, cpu, (testResult ? "PASS" : "FAIL")); + + cpufreq_cpu_put(policy); + } + + cpufreq_unregister_notifier(&test_arm_bl_cpufreq_notifier_block, + CPUFREQ_TRANSITION_NOTIFIER); + + pr_info("name=post-init/transitions run=%d result=%s pass=%d fail=%d\n", + nTest, (failCount == 0 ? "PASS" : "FAIL"), + (nTest - failCount), failCount); + if (failCount != 0) + return -1; + + return 0; +} + +static int pre_init_tests(void) +{ + int nTest = 0, failCount = 0; + + pr_info("Begin pre-init tests"); + + ++nTest; + if (test_cpufreq_frequency_table() < 0) + ++failCount; + + ++nTest; + if (test_cluster_to_freq() < 0) + ++failCount; + + ++nTest; + if (test_get_current_cluster() < 0) + ++failCount; + + pr_info("name=pre-init run=%d result=%s pass=%d fail=%d\n", + nTest, (failCount == 0 ? "PASS" : "FAIL"), + (nTest - failCount), failCount); + if (failCount != 0) + return -1; + + return 0; +} + +static int post_init_tests(void) +{ + /* + * Run all post-init tests + * + * We wait POST_INIT_TESTS_DELAY ms between tests to be sure system is + * in a stable state before running a new test. + */ + int nTest = 0, failCount = 0; + + + mdelay(POST_INIT_TESTS_DELAY); + ++nTest; + if (test_cpufreq_driver_target() < 0) + ++failCount; + + mdelay(POST_INIT_TESTS_DELAY); + ++nTest; + if (test_transitions() < 0) + ++failCount; + + mdelay(POST_INIT_TESTS_DELAY); + ++nTest; + if (test_get_current_freq() < 0) + ++failCount; + + mdelay(POST_INIT_TESTS_DELAY); + ++nTest; + if (test_bl_cpufreq_get() < 0) + ++failCount; + + mdelay(POST_INIT_TESTS_DELAY); + ++nTest; + if (test_get_current_cached_cluster() < 0) + ++failCount; + + pr_info("name=post-init run=%d result=%s pass=%d fail=%d\n", + nTest, (failCount == 0 ? "PASS" : "FAIL"), + (nTest - failCount), failCount); + if (failCount != 0) + return -1; + + return 0; +} + +#undef pr_fmt +#define pr_fmt(fmt) __module_pr_fmt("", fmt) +#else /* ! CONFIG_ARM_BL_CPUFREQ_TEST */ + +static int pre_init_tests(void) { return 0; } +static int post_init_tests(void) { return 0; } + +#endif /* CONFIG_ARM_BL_CPUFREQ_TEST */ +#endif /* ARM_BL_CPUFREQ_DEFINE_TESTS */ |