diff options
23 files changed, 697 insertions, 28 deletions
diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index 9c5e1d944d1c..7560c9166fa7 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -962,6 +962,9 @@ dtb-$(CONFIG_ARCH_VERSATILE) += \ versatile-ab.dtb \ versatile-pb.dtb dtb-$(CONFIG_ARCH_VEXPRESS) += \ + juno.dtb \ + juno-r1.dtb \ + juno-r2.dtb \ vexpress-v2p-ca5s.dtb \ vexpress-v2p-ca9.dtb \ vexpress-v2p-ca15-tc1.dtb \ diff --git a/arch/arm/boot/dts/juno-base.dtsi b/arch/arm/boot/dts/juno-base.dtsi new file mode 120000 index 000000000000..5bf5772d7718 --- /dev/null +++ b/arch/arm/boot/dts/juno-base.dtsi @@ -0,0 +1 @@ +../../../arm64/boot/dts/arm/juno-base.dtsi
\ No newline at end of file diff --git a/arch/arm/boot/dts/juno-clocks.dtsi b/arch/arm/boot/dts/juno-clocks.dtsi new file mode 120000 index 000000000000..d26c206771d4 --- /dev/null +++ b/arch/arm/boot/dts/juno-clocks.dtsi @@ -0,0 +1 @@ +../../../arm64/boot/dts/arm/juno-clocks.dtsi
\ No newline at end of file diff --git a/arch/arm/boot/dts/juno-cs-r1r2.dtsi b/arch/arm/boot/dts/juno-cs-r1r2.dtsi new file mode 120000 index 000000000000..08c059e69464 --- /dev/null +++ b/arch/arm/boot/dts/juno-cs-r1r2.dtsi @@ -0,0 +1 @@ +../../../arm64/boot/dts/arm/juno-cs-r1r2.dtsi
\ No newline at end of file diff --git a/arch/arm/boot/dts/juno-motherboard.dtsi b/arch/arm/boot/dts/juno-motherboard.dtsi new file mode 120000 index 000000000000..a4e1f71b8533 --- /dev/null +++ b/arch/arm/boot/dts/juno-motherboard.dtsi @@ -0,0 +1 @@ +../../../arm64/boot/dts/arm/juno-motherboard.dtsi
\ No newline at end of file diff --git a/arch/arm/boot/dts/juno-r1.dts b/arch/arm/boot/dts/juno-r1.dts new file mode 120000 index 000000000000..f0bf74937285 --- /dev/null +++ b/arch/arm/boot/dts/juno-r1.dts @@ -0,0 +1 @@ +../../../arm64/boot/dts/arm/juno-r1.dts
\ No newline at end of file diff --git a/arch/arm/boot/dts/juno-r2.dts b/arch/arm/boot/dts/juno-r2.dts new file mode 120000 index 000000000000..aba7e1fac440 --- /dev/null +++ b/arch/arm/boot/dts/juno-r2.dts @@ -0,0 +1 @@ +../../../arm64/boot/dts/arm/juno-r2.dts
\ No newline at end of file diff --git a/arch/arm/boot/dts/juno-sched-energy.dtsi b/arch/arm/boot/dts/juno-sched-energy.dtsi new file mode 120000 index 000000000000..3508c8b8438f --- /dev/null +++ b/arch/arm/boot/dts/juno-sched-energy.dtsi @@ -0,0 +1 @@ +../../../arm64/boot/dts/arm/juno-sched-energy.dtsi
\ No newline at end of file diff --git a/arch/arm/boot/dts/juno.dts b/arch/arm/boot/dts/juno.dts new file mode 120000 index 000000000000..186e53545ef2 --- /dev/null +++ b/arch/arm/boot/dts/juno.dts @@ -0,0 +1 @@ +../../../arm64/boot/dts/arm/juno.dts
\ No newline at end of file diff --git a/arch/arm/boot/dts/juno_r2-sched-energy.dtsi b/arch/arm/boot/dts/juno_r2-sched-energy.dtsi new file mode 120000 index 000000000000..0d000be54a83 --- /dev/null +++ b/arch/arm/boot/dts/juno_r2-sched-energy.dtsi @@ -0,0 +1 @@ +../../../arm64/boot/dts/arm/juno_r2-sched-energy.dtsi
\ No newline at end of file diff --git a/arch/arm64/boot/dts/arm/juno-base.dtsi b/arch/arm64/boot/dts/arm/juno-base.dtsi index 1e44b67459d3..eea734b96de1 100644 --- a/arch/arm64/boot/dts/arm/juno-base.dtsi +++ b/arch/arm64/boot/dts/arm/juno-base.dtsi @@ -465,7 +465,7 @@ compatible = "arm,scpi-dvfs-clocks"; #clock-cells = <1>; clock-indices = <0>, <1>, <2>; - clock-output-names = "atlclk", "aplclk","gpuclk"; + clock-output-names = "atlclk", "aplclk","clk_mali"; }; scpi_clk: scpi-clk { compatible = "arm,scpi-variable-clocks"; diff --git a/arch/arm64/boot/dts/arm/juno-r1.dts b/arch/arm64/boot/dts/arm/juno-r1.dts index 0e8943ab94d7..88c83d1d7076 100644 --- a/arch/arm64/boot/dts/arm/juno-r1.dts +++ b/arch/arm64/boot/dts/arm/juno-r1.dts @@ -14,7 +14,7 @@ / { model = "ARM Juno development board (r1)"; - compatible = "arm,juno-r1", "arm,juno", "arm,vexpress"; + compatible = "arm,juno-r1", "arm,juno"; interrupt-parent = <&gic>; #address-cells = <2>; #size-cells = <2>; diff --git a/arch/arm64/boot/dts/arm/juno-r2.dts b/arch/arm64/boot/dts/arm/juno-r2.dts index 405e2fba025b..5c194b4c830a 100644 --- a/arch/arm64/boot/dts/arm/juno-r2.dts +++ b/arch/arm64/boot/dts/arm/juno-r2.dts @@ -14,7 +14,7 @@ / { model = "ARM Juno development board (r2)"; - compatible = "arm,juno-r2", "arm,juno", "arm,vexpress"; + compatible = "arm,juno-r2", "arm,juno"; interrupt-parent = <&gic>; #address-cells = <2>; #size-cells = <2>; diff --git a/arch/arm64/boot/dts/arm/juno.dts b/arch/arm64/boot/dts/arm/juno.dts index 0220494c9b80..69aa396a8aad 100644 --- a/arch/arm64/boot/dts/arm/juno.dts +++ b/arch/arm64/boot/dts/arm/juno.dts @@ -13,7 +13,7 @@ / { model = "ARM Juno development board (r0)"; - compatible = "arm,juno", "arm,vexpress"; + compatible = "arm,juno"; interrupt-parent = <&gic>; #address-cells = <2>; #size-cells = <2>; diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig index 6e4ed5a9c6fd..33e72ac4fa3b 100644 --- a/drivers/firmware/Kconfig +++ b/drivers/firmware/Kconfig @@ -48,6 +48,10 @@ config ARM_SCPI_POWER_DOMAIN This enables support for the SCPI power domains which can be enabled or disabled via the SCP firmware +config ARM_SCPI_PROTOCOL_TEST + tristate "Test code for SCPI Message Protocol" + default ARM_SCPI_PROTOCOL + config EDD tristate "BIOS Enhanced Disk Drive calls determine boot disk" depends on X86 diff --git a/drivers/firmware/Makefile b/drivers/firmware/Makefile index a37f12e8d137..f06daf68e68a 100644 --- a/drivers/firmware/Makefile +++ b/drivers/firmware/Makefile @@ -5,6 +5,7 @@ obj-$(CONFIG_ARM_PSCI_FW) += psci.o obj-$(CONFIG_ARM_PSCI_CHECKER) += psci_checker.o obj-$(CONFIG_ARM_SCPI_PROTOCOL) += arm_scpi.o obj-$(CONFIG_ARM_SCPI_POWER_DOMAIN) += scpi_pm_domain.o +obj-$(CONFIG_ARM_SCPI_PROTOCOL_TEST) += arm_scpi_test.o obj-$(CONFIG_DMI) += dmi_scan.o obj-$(CONFIG_DMI_SYSFS) += dmi-sysfs.o obj-$(CONFIG_EDD) += edd.o diff --git a/drivers/firmware/arm_scpi.c b/drivers/firmware/arm_scpi.c index f6cfc31d34c7..8d39da71d6b9 100644 --- a/drivers/firmware/arm_scpi.c +++ b/drivers/firmware/arm_scpi.c @@ -87,8 +87,6 @@ #define FW_REV_MINOR(x) (((x) & FW_REV_MINOR_MASK) >> FW_REV_MINOR_BITS) #define FW_REV_PATCH(x) ((x) & FW_REV_PATCH_MASK) -#define MAX_RX_TIMEOUT (msecs_to_jiffies(30)) - enum scpi_error_codes { SCPI_SUCCESS = 0, /* Success */ SCPI_ERR_PARAM = 1, /* Invalid parameter(s) */ @@ -480,6 +478,18 @@ static void scpi_tx_prepare(struct mbox_client *c, void *msg) mem->command = cpu_to_le32(t->cmd); } +static void scpi_tx_done(struct mbox_client *c, void *msg, int result) +{ + struct scpi_xfer *t = msg; + + if (!t->rx_buf) + complete(&t->done); + /* + * Messages with rx_buf are expecting a reply and will be on the + * rx_pending list, so leave them alone. + */ +} + static struct scpi_xfer *get_scpi_xfer(struct scpi_chan *ch) { struct scpi_xfer *t; @@ -541,17 +551,24 @@ static int scpi_send_message(u8 idx, void *tx_buf, unsigned int tx_len, reinit_completion(&msg->done); ret = mbox_send_message(scpi_chan->chan, msg); - if (ret < 0 || !rx_buf) - goto out; + if (ret >= 0) { + /* + * Wait for message to be processed. If we end up having to wait + * for a very long time then there is a serious bug, probably in + * the firmware. + * + * IMPORTANT: We must not try and continue after the timeout + * because this driver and the mailbox framework still has data + * structures referring to the failed request and further + * serious bugs will result. + */ + if (!wait_for_completion_timeout(&msg->done, msecs_to_jiffies(10000))) + BUG(); - if (!wait_for_completion_timeout(&msg->done, MAX_RX_TIMEOUT)) - ret = -ETIMEDOUT; - else /* first status word */ - ret = msg->status; -out: - if (ret < 0 && rx_buf) /* remove entry from the list if timed-out */ - scpi_process_cmd(scpi_chan, msg->cmd); + if (rx_buf) + ret = le32_to_cpu(msg->status); + } put_scpi_xfer(msg, scpi_chan); /* SCPI error codes > 0, translate them to Linux scale*/ @@ -642,6 +659,8 @@ static int opp_cmp_func(const void *opp1, const void *opp2) return t1->freq - t2->freq; } +static bool juno_cpufreq_limit_hack = 0; + static struct scpi_dvfs_info *scpi_dvfs_get_info(u8 domain) { struct scpi_dvfs_info *info; @@ -680,6 +699,14 @@ static struct scpi_dvfs_info *scpi_dvfs_get_info(u8 domain) sort(info->opps, info->count, sizeof(*opp), opp_cmp_func, NULL); + /* + * Juno silicon doesn't seem to be able to run the big cluster + * (domain == 0) at max frequency in AArch32 mode (it produces + * random and weird crashes) so drop the highest OPP in that case... + */ + if (juno_cpufreq_limit_hack && domain == 0) + --info->count; + scpi_info->dvfs[domain] = info; return info; } @@ -893,6 +920,10 @@ static int scpi_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct device_node *np = dev->of_node; + if (IS_ENABLED(CONFIG_ARM) && of_find_compatible_node(NULL,NULL,"arm,juno")) { + juno_cpufreq_limit_hack = true; + } + scpi_info = devm_kzalloc(dev, sizeof(*scpi_info), GFP_KERNEL); if (!scpi_info) return -ENOMEM; @@ -935,8 +966,7 @@ static int scpi_probe(struct platform_device *pdev) cl->dev = dev; cl->rx_callback = scpi_handle_remote_msg; cl->tx_prepare = scpi_tx_prepare; - cl->tx_block = true; - cl->tx_tout = 20; + cl->tx_done = scpi_tx_done; cl->knows_txdone = false; /* controller can't ack */ INIT_LIST_HEAD(&pchan->rx_pending); diff --git a/drivers/firmware/arm_scpi_test.c b/drivers/firmware/arm_scpi_test.c new file mode 100644 index 000000000000..c21b35e6f4b8 --- /dev/null +++ b/drivers/firmware/arm_scpi_test.c @@ -0,0 +1,568 @@ +/* + * Test code for System Control and Power Interface (SCPI) + * + * Copyright (C) 2015 Linaro Ltd. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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, see <http://www.gnu.org/licenses/>. + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include <linux/ctype.h> +#include <linux/delay.h> +#include <linux/kthread.h> +#include <linux/module.h> +#include <linux/scpi_protocol.h> + + +static int stress_time; +module_param(stress_time, int, 0644); +MODULE_PARM_DESC(stress_time, "Number of seconds to run each stress test for, overides each test's default."); + +static int run; +static struct kernel_param_ops run_ops; +module_param_cb(run, &run_ops, &run, 0644); +MODULE_PARM_DESC(run, "The number of the test case to run, or -1 for all, 0 to stop tests."); + + +static struct scpi_ops *scpi; + +static struct task_struct *main_thread; + +static DEFINE_MUTEX(main_thread_lock); + + +#define MAX_TEST_THREADS 4 + +static struct test_thread { + struct task_struct *task; + int thread_num; +} test_threads[MAX_TEST_THREADS]; + +static DEFINE_MUTEX(thread_lock); + + +#define MAX_POWER_DOMAINS 8 + +static u16 num_sensors; +static u8 num_pd; +static u8 num_opps[MAX_POWER_DOMAINS]; +static struct mutex pd_lock[MAX_POWER_DOMAINS]; +static u8 num_devices_with_power_states; + + +#define FLAG_SERIAL_DVFS (1<<0) +#define FLAG_SERIAL_PD (1<<1) + +static int test_flags; + + +static int sensor_pmic = -1; + + +static u32 random_seed; + +static u32 random(u32 range) +{ + random_seed = random_seed*69069+1; + + return ((u64)random_seed * (u64)range) >> 32; +} + + +static atomic_t passes; +static atomic_t failures; + +static bool fail_on(bool fail) +{ + if (fail) + atomic_inc(&failures); + else + atomic_inc(&passes); + return fail; +} + +static void show_results(const char *title) +{ + int fail = atomic_xchg(&failures, 0); + int pass = atomic_xchg(&passes, 0); + + if (fail) + pr_err("Results for '%s' is %d/%d (pass/fail)\n", title, pass, fail); + else + pr_info("Results for '%s' is %d/%d (pass/fail)\n", title, pass, fail); +} + + +static bool check_name(const char *name) +{ + char c; + + if (!isalpha(*name++)) + return false; + + while ((c = *name++)) + if (!isalnum(c) && c != '_') + return false; + + return true; +} + +static u64 get_sensor(u16 id) +{ + u64 val; + int ret; + + ret = scpi->sensor_get_value(id, &val); + if (fail_on(ret < 0)) + pr_err("FAILED sensor_get_value %d (%d)\n", id, ret); + + return val; +} + +static void init_sensors(void) +{ + u16 id; + int ret; + + ret = scpi->sensor_get_capability(&num_sensors); + if (fail_on(ret)) + pr_err("FAILED sensor_get_capability (%d)\n", ret); + + pr_info("num_sensors: %d\n", num_sensors); + + for (id = 0; id < num_sensors; id++) { + + struct scpi_sensor_info info; + char name[sizeof(info.name) + 1]; + + ret = scpi->sensor_get_info(id, &info); + if (fail_on(ret)) { + pr_err("FAILED sensor_get_info (%d)\n", ret); + continue; + } + + /* Get sensor name, guarding against missing NUL terminator */ + memcpy(name, info.name, sizeof(info.name)); + name[sizeof(info.name)] = 0; + + pr_info("sensor[%d] id=%d class=%d trigger=%d name=%s\n", id, + info.sensor_id, info.class, info.trigger_type, name); + + if (fail_on(id != info.sensor_id)) + pr_err("FAILED bad sensor id\n"); + if (fail_on(info.class > 4)) + pr_err("FAILED bad sensor class\n"); + if (fail_on(info.trigger_type > 3)) + pr_err("FAILED bad sensor trigger type\n"); + if (fail_on(strlen(name) >= sizeof(info.name) || !check_name(name))) + pr_err("FAILED bad name\n"); + + pr_info("sensor[%d] value is %llu\n", id, get_sensor(id)); + if (strstr(name, "PMIC")) + sensor_pmic = id; + } +} + +static int get_dvfs(u8 pd) +{ + int ret = scpi->dvfs_get_idx(pd); + + if (fail_on(ret < 0)) + pr_err("FAILED get_dvfs %d (%d)\n", pd, ret); + else if (fail_on(ret >= num_opps[pd])) + pr_err("FAILED get_dvfs %d returned out of range index (%d)\n", pd, ret); + + return ret; +} + +static int set_dvfs(u8 pd, u8 opp) +{ + int ret; + + if (test_flags & FLAG_SERIAL_DVFS) + mutex_lock(&pd_lock[0]); + else if (test_flags & FLAG_SERIAL_PD) + mutex_lock(&pd_lock[pd]); + + ret = scpi->dvfs_set_idx(pd, opp); + + if (test_flags & FLAG_SERIAL_DVFS) + mutex_unlock(&pd_lock[0]); + else if (test_flags & FLAG_SERIAL_PD) + mutex_unlock(&pd_lock[pd]); + + if (fail_on(ret < 0)) + pr_err("FAILED set_dvfs %d %d (%d)\n", pd, opp, ret); + + return ret; +} + +static void init_dvfs(void) +{ + u8 pd; + + for (pd = 0; pd < MAX_POWER_DOMAINS; ++pd) { + struct scpi_dvfs_info *info; + int opp; + + info = scpi->dvfs_get_info(pd); + if (IS_ERR(info)) { + pr_info("dvfs_get_info %d failed with %d assume because no more power domains\n", + pd, (int)PTR_ERR(info)); + break; + } + + num_opps[pd] = info->count; + mutex_init(&pd_lock[pd]); + pr_info("pd[%d] count=%u latency=%u\n", + pd, info->count, info->latency); + + opp = get_dvfs(pd); + pr_info("pd[%d] current opp=%d\n", pd, opp); + + for (opp = 0; opp < info->count; ++opp) { + pr_info("pd[%d].opp[%d] freq=%u m_volt=%u\n", pd, opp, + info->opps[opp].freq, info->opps[opp].m_volt); + /* + * Try setting each opp. Note, failure is not necessarily + * an error because cpufreq may be setting values too. + */ + set_dvfs(pd, opp); + if (get_dvfs(pd) == opp) + pr_info("pd[%d] set to opp %d OK\n", pd, opp); + else + pr_warn("pd[%d] failed to set opp to %d\n", pd, opp); + } + } + + if (!pd) { + /* Assume device should have at least one DVFS power domain */ + pr_err("FAILED no power domains\n"); + fail_on(true); + } + num_pd = pd; +} + +static int device_get_power_state(u16 dev_id) +{ + int ret; + + ret = scpi->device_get_power_state(dev_id); + if (fail_on(ret < 0)) + pr_err("FAILED device_get_power_state %d (%d)\n", dev_id, ret); + + return ret; +} + +static int device_set_power_state(u16 dev_id, u8 pstate) +{ + int ret; + + ret = scpi->device_set_power_state(dev_id, pstate); + if (fail_on(ret < 0)) + pr_err("FAILED device_get_power_state %d (%d)\n", dev_id, ret); + + return ret; +} + +static void init_device_power_states(void) +{ + u16 dev_id; + + for (dev_id = 0; dev_id < 0xffff; ++dev_id) { + int state = scpi->device_get_power_state(dev_id); + + if (state < 0) { + pr_info("device_get_power_state %d failed with %d assume because no more devices\n", + dev_id, state); + break; + } + + pr_info("device[%d] current state=%d\n", dev_id, state); + + device_set_power_state(dev_id, state); + if (device_get_power_state(dev_id) == state) + pr_info("device[%d] set state to %d OK\n", dev_id, state); + else + pr_warn("device[%d] failed set state to %d\n", dev_id, state); + } + + if (!dev_id) { + /* Assume device should have at least one device power state */ + pr_err("FAILED no devices with power states\n"); + fail_on(true); + } + num_devices_with_power_states = dev_id; +} + +static int stress_pmic(void *data) +{ + int sensor, pd, opp; + + while (!kthread_should_stop()) { + sensor = sensor_pmic; + pd = random(num_pd); + opp = random(num_opps[pd]); + + switch (random(3)) { + case 0: + if (sensor >= 0) { + get_sensor(sensor); + break; + } + /* If no sensor, do DFVS... */ + case 1: + set_dvfs(pd, opp); + break; + default: + msleep(random(20)); + break; + } + } + + return 0; +} + +static int stress_all(void *data) +{ + int sensor, pd, opp; + + while (!kthread_should_stop()) { + sensor = random(num_sensors); + pd = random(num_pd); + opp = random(num_opps[pd]); + + switch (random(4)) { + case 0: + set_dvfs(pd, opp); + break; + case 1: + opp = get_dvfs(pd); + break; + case 2: + get_sensor(sensor); + break; + default: + msleep(random(20)); + break; + } + } + + return 0; +} + +struct test { + const char *title; + int (*thread_fn)(void *); + int flags; + int num_threads; + int duration; +}; + +static void stop_test_threads(void) +{ + int t, ret; + + for (t = 0; t < MAX_TEST_THREADS; ++t) { + struct test_thread *thread = &test_threads[t]; + + mutex_lock(&thread_lock); + if (thread->task) { + ret = kthread_stop(thread->task); + thread->task = NULL; + if (ret) + pr_warn("Test thread %d exited with status %d\n", t, ret); + } + mutex_unlock(&thread_lock); + } +} + +static void run_test(struct test *test) +{ + int num_threads = min(test->num_threads, MAX_TEST_THREADS); + int duration = stress_time; + int t; + + if (test->duration <= 0) + duration = 0; + else if (duration <= 0) + duration = test->duration; + + pr_info("Running test '%s' for %d seconds\n", test->title, duration); + + test_flags = test->flags; + + for (t = 0; t < num_threads; ++t) { + struct test_thread *thread = &test_threads[t]; + struct task_struct *task; + + mutex_lock(&thread_lock); + thread->thread_num = t; + task = kthread_run(test->thread_fn, thread, "scpi-test-%d", t); + if (IS_ERR(task)) + pr_warn("Failed to create test thread %d\n", t); + else + thread->task = task; + mutex_unlock(&thread_lock); + } + + schedule_timeout_interruptible(msecs_to_jiffies(duration * 1000)); + + stop_test_threads(); + + show_results(test->title); +} + +static struct test tests[] = { + {"Stress All, concurrent DVFS", + stress_all, 0, MAX_TEST_THREADS, 60}, + {"Stress All, concurrent DVFS on different PDs", + stress_all, FLAG_SERIAL_PD, MAX_TEST_THREADS, 60}, + {"Stress All, no concurrent DVFS", + stress_all, FLAG_SERIAL_DVFS, MAX_TEST_THREADS, 60}, + {"Stress PMIC, concurrent DVFS", + stress_pmic, 0, MAX_TEST_THREADS, 60}, + {"Stress PMIC, concurrent DVFS on different PDs", + stress_pmic, FLAG_SERIAL_PD, MAX_TEST_THREADS, 60}, + {"Stress PMIC, no concurrent DVFS", + stress_pmic, FLAG_SERIAL_DVFS, MAX_TEST_THREADS, 60}, + {} +}; + +static int main_thread_fn(void *data) +{ + struct test *test = tests; + int i = 1; + + for (; test->title && !kthread_should_stop(); ++test, ++i) + if (run < 0 || run == i) + run_test(test); + + run = 0; + return 0; +} + +static DEFINE_MUTEX(setup_lock); + +static int setup(void) +{ + int ret = 0; + + mutex_lock(&setup_lock); + + if (!scpi) { + int tries = 12; + + pr_info("Initial setup\n"); + while ((scpi = get_scpi_ops()) == 0 && --tries) { + pr_info("Waiting for get_scpi_ops\n"); + msleep(5000); + } + + if (scpi) { + init_sensors(); + init_dvfs(); + init_device_power_states(); + show_results("Initial setup"); + } else { + pr_err("Given up on get_scpi_ops\n"); + ret = -ENODEV; + } + } + + mutex_unlock(&setup_lock); + + return ret; +} + +static int start_tests(void) +{ + struct task_struct *task; + int ret; + + ret = setup(); + if (ret) { + run = 0; + return ret; + } + + pr_info("Creating main thread\n"); + mutex_lock(&main_thread_lock); + if (main_thread) { + ret = -EBUSY; + } else { + task = kthread_run(main_thread_fn, 0, "scpi-test-main"); + if (IS_ERR(task)) + ret = PTR_ERR(task); + else + main_thread = task; + } + mutex_unlock(&main_thread_lock); + + if (ret) { + pr_err("Failed to create main thread (%d)\n", ret); + run = 0; + } + + return ret; +} + +static void stop_tests(void) +{ + pr_info("Stopping tests\n"); + mutex_lock(&main_thread_lock); + if (main_thread) + kthread_stop(main_thread); + main_thread = NULL; + mutex_unlock(&main_thread_lock); +} + +static int param_set_running(const char *val, const struct kernel_param *kp) +{ + int ret; + + ret = param_set_int(val, kp); + if (!ret) { + if (run) + ret = start_tests(); + else + stop_tests(); + } + + return ret; +} + +static struct kernel_param_ops run_ops = { + .set = param_set_running, + .get = param_get_int, +}; + + +static int scpi_test_init(void) +{ + return 0; +} + +static void scpi_test_exit(void) +{ + stop_tests(); +} + +module_init(scpi_test_init); +module_exit(scpi_test_exit); + + +MODULE_AUTHOR("Jon Medhurst (Tixy) <tixy@linaro.org>"); +MODULE_DESCRIPTION("ARM SCPI driver tests"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/net/ethernet/marvell/sky2.c b/drivers/net/ethernet/marvell/sky2.c index 1145cde2274a..bf397e3c5195 100644 --- a/drivers/net/ethernet/marvell/sky2.c +++ b/drivers/net/ethernet/marvell/sky2.c @@ -101,6 +101,10 @@ static int legacy_pme = 0; module_param(legacy_pme, int, 0); MODULE_PARM_DESC(legacy_pme, "Legacy power management"); +/* Ugh! Let the firmware tell us the hardware address */ +static int mac_address[ETH_ALEN] = { 0, }; +module_param_array(mac_address, int, NULL, 0); + static const struct pci_device_id sky2_id_table[] = { { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9000) }, /* SK-9Sxx */ { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9E00) }, /* SK-9Exx */ @@ -3909,6 +3913,18 @@ static void sky2_get_stats(struct net_device *dev, unsigned int start; u64 _bytes, _packets; + /* Try and check if device if off. If it is, abort gathering stats as + * any attempt to read hardware registers will generate a bus fault. + * This test is hacky and racy as there's nothing stopping the device + * being powered off immediately after the test. + */ + if (hw->pdev->pm_cap) { + u16 pmcsr; + int ret = pci_read_config_word(hw->pdev, hw->pdev->pm_cap + PCI_PM_CTRL, &pmcsr); + if (ret || (pmcsr & PCI_PM_CTRL_STATE_MASK) > PCI_D2) + return; /* Can't read power state or it's state D3 (off) */ + } + do { start = u64_stats_fetch_begin_irq(&sky2->rx_stats.syncp); _bytes = sky2->rx_stats.bytes; @@ -4819,13 +4835,21 @@ static struct net_device *sky2_init_netdev(struct sky2_hw *hw, unsigned port, /* try to get mac address in the following order: * 1) from device tree data * 2) from internal registers set by bootloader + * 3) from the command line parameter */ iap = of_get_mac_address(hw->pdev->dev.of_node); if (iap) memcpy(dev->dev_addr, iap, ETH_ALEN); - else + else { memcpy_fromio(dev->dev_addr, hw->regs + B2_MAC_1 + port * 8, ETH_ALEN); + if (!is_valid_ether_addr(&dev->dev_addr[0])) { + int i; + + for (i = 0; i < ETH_ALEN; i++) + dev->dev_addr[i] = mac_address[i]; + } + } /* if the address is invalid, use a random value */ if (!is_valid_ether_addr(dev->dev_addr)) { diff --git a/linaro/configs/android.conf b/linaro/configs/android.conf index 637c36580a45..c9309874c1de 100644 --- a/linaro/configs/android.conf +++ b/linaro/configs/android.conf @@ -3,6 +3,7 @@ # CONFIG_INET_LRO is not set # CONFIG_MODULES is not set # CONFIG_OABI_COMPAT is not set +# CONFIG_SYSVIPC is not set CONFIG_ANDROID=y CONFIG_ANDROID_BINDER_IPC=y CONFIG_ANDROID_LOW_MEMORY_KILLER=y @@ -19,13 +20,16 @@ CONFIG_CGROUP_SCHED=y CONFIG_CP15_BARRIER_EMULATION=y CONFIG_DM_CRYPT=y CONFIG_DM_VERITY=y +CONFIG_DM_VERITY_FEC=y CONFIG_EMBEDDED=y CONFIG_FB=y +CONFIG_HARDENED_USERCOPY=y CONFIG_HIGH_RES_TIMERS=y CONFIG_INET6_AH=y CONFIG_INET6_ESP=y CONFIG_INET6_IPCOMP=y CONFIG_INET=y +CONFIG_INET_DIAG_DESTROY=y CONFIG_INET_ESP=y CONFIG_INET_XFRM_MODE_TUNNEL=y CONFIG_IP6_NF_FILTER=y @@ -33,7 +37,6 @@ CONFIG_IP6_NF_IPTABLES=y CONFIG_IP6_NF_MANGLE=y CONFIG_IP6_NF_RAW=y CONFIG_IP6_NF_TARGET_REJECT=y -CONFIG_IP6_NF_TARGET_REJECT_SKERR=y CONFIG_IPV6=y CONFIG_IPV6_MIP6=y CONFIG_IPV6_MULTIPLE_TABLES=y @@ -42,6 +45,7 @@ CONFIG_IPV6_PRIVACY=y CONFIG_IPV6_ROUTER_PREF=y CONFIG_IPV6_ROUTE_INFO=y CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_IP_MULTICAST=y CONFIG_IP_MULTIPLE_TABLES=y CONFIG_IP_NF_ARPFILTER=y CONFIG_IP_NF_ARPTABLES=y @@ -52,13 +56,13 @@ CONFIG_IP_NF_MANGLE=y CONFIG_IP_NF_MATCH_AH=y CONFIG_IP_NF_MATCH_ECN=y CONFIG_IP_NF_MATCH_TTL=y +CONFIG_IP_NF_NAT=y CONFIG_IP_NF_RAW=y CONFIG_IP_NF_SECURITY=y CONFIG_IP_NF_TARGET_MASQUERADE=y CONFIG_IP_NF_TARGET_NETMAP=y CONFIG_IP_NF_TARGET_REDIRECT=y CONFIG_IP_NF_TARGET_REJECT=y -CONFIG_IP_NF_TARGET_REJECT_SKERR=y CONFIG_NET=y CONFIG_NETDEVICES=y CONFIG_NETFILTER=y @@ -133,19 +137,26 @@ CONFIG_PPP_BSDCOMP=y CONFIG_PPP_DEFLATE=y CONFIG_PPP_MPPE=y CONFIG_PREEMPT=y -CONFIG_RESOURCE_COUNTERS=y +CONFIG_PROFILING=y +CONFIG_QFMT_V2=y +CONFIG_QUOTA=y +CONFIG_QUOTA_NETLINK_INTERFACE=y +CONFIG_QUOTA_TREE=y +CONFIG_QUOTACTL=y +CONFIG_RANDOMIZE_BASE=y CONFIG_RTC_CLASS=y CONFIG_RT_GROUP_SCHED=y +CONFIG_SECCOMP=y CONFIG_SECURITY=y CONFIG_SECURITY_NETWORK=y +CONFIG_SECURITY_PERF_EVENTS_RESTRICT=y CONFIG_SECURITY_SELINUX=y CONFIG_SETEND_EMULATION=y CONFIG_STAGING=y -CONFIG_SWITCH=y CONFIG_SWP_EMULATION=y CONFIG_SYNC=y -CONFIG_SYSVIPC=y CONFIG_TUN=y +CONFIG_UID_CPUTIME=y CONFIG_UNIX=y CONFIG_USB_GADGET=y CONFIG_USB_CONFIGFS=y @@ -155,8 +166,10 @@ CONFIG_USB_CONFIGFS_F_PTP=y CONFIG_USB_CONFIGFS_F_ACC=y CONFIG_USB_CONFIGFS_F_AUDIO_SRC=y CONFIG_USB_CONFIGFS_UEVENT=y +CONFIG_USB_CONFIGFS_F_MIDI=y CONFIG_USB_OTG_WAKELOCK=y CONFIG_XFRM_USER=y +# CONFIG_AIO is not set # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set # CONFIG_INPUT_MOUSE is not set # CONFIG_LEGACY_PTYS is not set @@ -164,11 +177,14 @@ CONFIG_XFRM_USER=y # CONFIG_PM_WAKELOCKS_GC is not set # CONFIG_VT is not set CONFIG_ANDROID_TIMED_GPIO=y +CONFIG_ARM_KERNMEM_PERMS=y CONFIG_BACKLIGHT_LCD_SUPPORT=y CONFIG_BLK_DEV_LOOP=y CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_SIZE=8192 +CONFIG_CC_STACKPROTECTOR_STRONG=y CONFIG_COMPACTION=y +CONFIG_DEBUG_RODATA=y CONFIG_DM_UEVENT=y CONFIG_DRAGONRISE_FF=y CONFIG_ENABLE_DEFAULT_TRACERS=y @@ -266,14 +282,19 @@ CONFIG_TABLET_USB_AIPTEK=y CONFIG_TABLET_USB_GTCO=y CONFIG_TABLET_USB_HANWANG=y CONFIG_TABLET_USB_KBTAB=y -CONFIG_TABLET_USB_WACOM=y +CONFIG_TASKSTATS=y +CONFIG_TASK_DELAY_ACCT=y +CONFIG_TASK_IO_ACCOUNTING=y +CONFIG_TASK_XACCT=y CONFIG_TIMER_STATS=y CONFIG_TMPFS=y CONFIG_TMPFS_POSIX_ACL=y CONFIG_UHID=y -CONFIG_UID_STAT=y +CONFIG_MEMORY_STATE_TIME=y CONFIG_USB_ANNOUNCE_NEW_DEVICES=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_HIDDEV=y CONFIG_USB_USBNET=y CONFIG_VFAT_FS=y +CONFIG_CPUSETS=y +CONFIG_PROC_PID_CPUSET=y diff --git a/linaro/configs/big-LITTLE-MP.conf b/linaro/configs/big-LITTLE-MP.conf new file mode 100644 index 000000000000..e69de29bb2d1 --- /dev/null +++ b/linaro/configs/big-LITTLE-MP.conf diff --git a/linaro/configs/vexpress.conf b/linaro/configs/vexpress.conf index c4c96f46817d..71677e86b564 100644 --- a/linaro/configs/vexpress.conf +++ b/linaro/configs/vexpress.conf @@ -13,10 +13,13 @@ CONFIG_ARM_BIG_LITTLE_CPUFREQ=y CONFIG_ARM_VEXPRESS_SPC_CPUFREQ=y CONFIG_PM_OPP=y CONFIG_CPU_FREQ=y -CONFIG_CPU_FREQ_GOV_ONDEMAND=y CONFIG_CPU_FREQ_GOV_PERFORMANCE=y -CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_ONDEMAND=y +CONFIG_CPU_FREQ_GOV_INTERACTIVE=y +CONFIG_CPU_FREQ_DEFAULT_GOV_INTERACTIVE=y CONFIG_CMDLINE="console=ttyAMA0,38400n8 root=/dev/mmcblk0p2 rootwait mmci.fmax=4000000" +CONFIG_SECURITY_SELINUX_BOOTPARAM=y CONFIG_VFP=y CONFIG_NEON=y CONFIG_SCSI=y @@ -24,6 +27,8 @@ CONFIG_BLK_DEV_SD=y CONFIG_SMSC911X=y CONFIG_SMC91X=y CONFIG_INPUT_EVDEV=y +CONFIG_INPUT_MOUSE=y +CONFIG_MOUSE_PS2=y CONFIG_SERIO_AMBAKMI=y CONFIG_SERIAL_AMBA_PL011=y CONFIG_SERIAL_AMBA_PL011_CONSOLE=y diff --git a/linaro/configs/vexpress64.conf b/linaro/configs/vexpress64.conf index 2ed7f1c31e7c..d5ae380d9b6f 100644 --- a/linaro/configs/vexpress64.conf +++ b/linaro/configs/vexpress64.conf @@ -1,12 +1,14 @@ CONFIG_ARCH_VEXPRESS=y CONFIG_SMP=y -CONFIG_NR_CPUS=8 CONFIG_HOTPLUG_CPU=y CONFIG_PREEMPT=y CONFIG_CMDLINE="console=ttyAMA0" +CONFIG_SECURITY_SELINUX_BOOTPARAM=y CONFIG_COMPAT=y CONFIG_SMC91X=y CONFIG_INPUT_EVDEV=y +CONFIG_INPUT_MOUSE=y +CONFIG_MOUSE_PS2=y CONFIG_SERIO_AMBAKMI=y CONFIG_SERIAL_AMBA_PL011=y CONFIG_SERIAL_AMBA_PL011_CONSOLE=y @@ -74,6 +76,8 @@ CONFIG_CONNECTOR=y CONFIG_ATA=y CONFIG_SATA_SIL24=y CONFIG_SKY2=y +CONFIG_ARM_TIMER_SP804=y +CONFIG_ARM_CPUIDLE=y CONFIG_DRM=y CONFIG_DRM_ARM=y CONFIG_DRM_HDLCD=y |