mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2026-01-09 17:11:42 +00:00
This adds explicit "int fan" args to the exported functions from common/fan.c: fan_set_percent_needed() and fan_percent_to_rpm(). Within that file, multiple fans are handled independently. This is not complete, though. Host commands and sysjump support still only handle a single fan, so at the moment multiple fans are treated identically in those cases. BUG=chrome-os-partner:23530 BRANCH=none TEST=manual All boards build, "make runtests" passes. On a multi-fan system, the EC command "faninfo" displays multiple results: > faninfo Fan 0 Actual: 0 rpm Fan 0 Target: 0 rpm Fan 0 Duty: 0% Fan 0 Status: 0 (not spinning) Fan 0 Mode: rpm Fan 0 Auto: yes Fan 0 Enable: yes Fan 1 Actual: 0 rpm Fan 1 Target: 0 rpm Fan 1 Duty: 0% Fan 1 Status: 0 (not spinning) Fan 1 Mode: rpm Fan 1 Auto: no Fan 1 Enable: no > and the "fanduty", "fanset", and "fanauto" all require the fan number as the first arg: > fanduty 0 30 Setting fan 0 duty cycle to 30% > fanset 1 2000 Setting fan 1 rpm target to 2000 > fanauto 0 > fanauto 1 On single-fan systems, there is no visible change. Change-Id: Idb8b818122e157960d56779b2a86e5ba433bee1b Signed-off-by: Bill Richardson <wfrichar@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/175368 Reviewed-by: Randall Spangler <rspangler@chromium.org>
875 lines
20 KiB
C
875 lines
20 KiB
C
/* Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
|
|
* Use of this source code is governed by a BSD-style license that can be
|
|
* found in the LICENSE file.
|
|
*
|
|
* Test thermal engine.
|
|
*/
|
|
|
|
#include "battery.h"
|
|
#include "battery_smart.h"
|
|
#include "chipset.h"
|
|
#include "common.h"
|
|
#include "console.h"
|
|
#include "extpower.h"
|
|
#include "extpower_falco.h"
|
|
#include "fan.h"
|
|
#include "hooks.h"
|
|
#include "host_command.h"
|
|
#include "printf.h"
|
|
#include "temp_sensor.h"
|
|
#include "test_util.h"
|
|
#include "thermal.h"
|
|
#include "throttle_ap.h"
|
|
#include "timer.h"
|
|
#include "util.h"
|
|
|
|
/* Normally private stuff from the modules we're going to test */
|
|
#include "thermal_falco_externs.h"
|
|
|
|
|
|
/*****************************************************************************/
|
|
/* Exported data */
|
|
|
|
struct ec_thermal_config thermal_params[TEMP_SENSOR_COUNT];
|
|
|
|
/* The tests below make some assumptions. */
|
|
BUILD_ASSERT(TEMP_SENSOR_COUNT == 4);
|
|
BUILD_ASSERT(EC_TEMP_THRESH_COUNT == 3);
|
|
|
|
/*****************************************************************************/
|
|
/* Mock functions */
|
|
|
|
static int mock_temp[TEMP_SENSOR_COUNT];
|
|
static int host_throttled;
|
|
static int cpu_throttled;
|
|
static int cpu_shutdown;
|
|
static int fan_pct;
|
|
static int no_temps_read;
|
|
static int mock_id;
|
|
static int mock_ac;
|
|
static int mock_charger_current;
|
|
static int mock_battery_discharge_current;
|
|
|
|
/* constants to match against throttling sources */
|
|
static const int t_s_therm = (1 << THROTTLE_SRC_THERMAL);
|
|
static const int t_s_power = (1 << THROTTLE_SRC_POWER);
|
|
static const int t_s_both = ((1 << THROTTLE_SRC_THERMAL) |
|
|
(1 << THROTTLE_SRC_POWER));
|
|
|
|
int dummy_temp_get_val(int idx, int *temp_ptr)
|
|
{
|
|
if (mock_temp[idx] >= 0) {
|
|
*temp_ptr = mock_temp[idx];
|
|
return EC_SUCCESS;
|
|
}
|
|
|
|
return EC_ERROR_NOT_POWERED;
|
|
}
|
|
|
|
void chipset_force_shutdown(void)
|
|
{
|
|
cpu_shutdown = 1;
|
|
}
|
|
|
|
void chipset_throttle_cpu(int throttled)
|
|
{
|
|
cpu_throttled = throttled;
|
|
}
|
|
|
|
void host_throttle_cpu(int throttled)
|
|
{
|
|
host_throttled = throttled;
|
|
}
|
|
|
|
void fan_set_percent_needed(int fan, int pct)
|
|
{
|
|
fan_pct = pct;
|
|
}
|
|
|
|
void smi_sensor_failure_warning(void)
|
|
{
|
|
no_temps_read = 1;
|
|
}
|
|
|
|
static void change_ac(int val)
|
|
{
|
|
mock_ac = val;
|
|
extpower_interrupt(GPIO_AC_PRESENT);
|
|
sleep(1);
|
|
}
|
|
|
|
int gpio_get_level(enum gpio_signal signal)
|
|
{
|
|
if (signal == GPIO_AC_PRESENT)
|
|
return mock_ac;
|
|
return 0;
|
|
}
|
|
|
|
int adc_read_channel(enum adc_channel ch)
|
|
{
|
|
switch (ch) {
|
|
case ADC_AC_ADAPTER_ID_VOLTAGE:
|
|
return mock_id;
|
|
case ADC_CH_CHARGER_CURRENT:
|
|
return mock_charger_current;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/* Test utilities */
|
|
|
|
static void set_temps(int t0, int t1, int t2, int t3)
|
|
{
|
|
mock_temp[0] = t0;
|
|
mock_temp[1] = t1;
|
|
mock_temp[2] = t2;
|
|
mock_temp[3] = t3;
|
|
}
|
|
|
|
static void all_temps(int t)
|
|
{
|
|
set_temps(t, t, t, t);
|
|
}
|
|
|
|
static void reset_mock_battery(void)
|
|
{
|
|
const struct battery_info *bat_info = battery_get_info();
|
|
|
|
/* 50% of charge */
|
|
sb_write(SB_RELATIVE_STATE_OF_CHARGE, 50);
|
|
sb_write(SB_ABSOLUTE_STATE_OF_CHARGE, 50);
|
|
/* 25 degree Celsius */
|
|
sb_write(SB_TEMPERATURE, 250 + 2731);
|
|
/* Normal voltage */
|
|
sb_write(SB_VOLTAGE, bat_info->voltage_normal);
|
|
sb_write(SB_CHARGING_VOLTAGE, bat_info->voltage_max);
|
|
sb_write(SB_CHARGING_CURRENT, 4000);
|
|
/* Discharging at 100mAh */
|
|
sb_write(SB_CURRENT, -100);
|
|
}
|
|
DECLARE_HOOK(HOOK_INIT, reset_mock_battery, HOOK_PRIO_DEFAULT);
|
|
|
|
static void mock_batt(int cur)
|
|
{
|
|
sb_write(SB_CURRENT, -cur); /* discharge current is neg here */
|
|
}
|
|
|
|
static void reset_mocks(void)
|
|
{
|
|
/* Ignore all sensors */
|
|
memset(thermal_params, 0, sizeof(thermal_params));
|
|
|
|
/* All sensors report error anyway */
|
|
set_temps(-1, -1 , -1, -1);
|
|
|
|
/* Reset expectations */
|
|
host_throttled = 0;
|
|
cpu_throttled = 0;
|
|
cpu_shutdown = 0;
|
|
fan_pct = 0;
|
|
no_temps_read = 0;
|
|
|
|
/* other mocked inputs */
|
|
mock_id = 0;
|
|
mock_ac = 0;
|
|
mock_charger_current = 0;
|
|
mock_battery_discharge_current = 0;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/* Tests */
|
|
|
|
static int test_init_val(void)
|
|
{
|
|
reset_mocks();
|
|
sleep(2);
|
|
|
|
TEST_ASSERT(host_throttled == 0);
|
|
TEST_ASSERT(cpu_throttled == 0);
|
|
TEST_ASSERT(cpu_shutdown == 0);
|
|
TEST_ASSERT(fan_pct == 0);
|
|
TEST_ASSERT(no_temps_read);
|
|
|
|
sleep(2);
|
|
|
|
TEST_ASSERT(host_throttled == 0);
|
|
TEST_ASSERT(cpu_throttled == 0);
|
|
TEST_ASSERT(cpu_shutdown == 0);
|
|
TEST_ASSERT(fan_pct == 0);
|
|
TEST_ASSERT(no_temps_read);
|
|
|
|
return EC_SUCCESS;
|
|
}
|
|
|
|
static int test_sensors_can_be_read(void)
|
|
{
|
|
reset_mocks();
|
|
mock_temp[2] = 100;
|
|
|
|
sleep(2);
|
|
|
|
TEST_ASSERT(host_throttled == 0);
|
|
TEST_ASSERT(cpu_throttled == 0);
|
|
TEST_ASSERT(cpu_shutdown == 0);
|
|
TEST_ASSERT(fan_pct == 0);
|
|
TEST_ASSERT(no_temps_read == 0);
|
|
|
|
return EC_SUCCESS;
|
|
}
|
|
|
|
|
|
static int test_one_fan(void)
|
|
{
|
|
reset_mocks();
|
|
thermal_params[2].temp_fan_off = 100;
|
|
thermal_params[2].temp_fan_max = 200;
|
|
|
|
all_temps(50);
|
|
sleep(2);
|
|
TEST_ASSERT(fan_pct == 0);
|
|
|
|
all_temps(100);
|
|
sleep(2);
|
|
TEST_ASSERT(fan_pct == 0);
|
|
|
|
all_temps(101);
|
|
sleep(2);
|
|
TEST_ASSERT(fan_pct == 1);
|
|
|
|
all_temps(130);
|
|
sleep(2);
|
|
TEST_ASSERT(fan_pct == 30);
|
|
|
|
all_temps(150);
|
|
sleep(2);
|
|
TEST_ASSERT(fan_pct == 50);
|
|
|
|
all_temps(170);
|
|
sleep(2);
|
|
TEST_ASSERT(fan_pct == 70);
|
|
|
|
all_temps(200);
|
|
sleep(2);
|
|
TEST_ASSERT(fan_pct == 100);
|
|
|
|
all_temps(300);
|
|
sleep(2);
|
|
TEST_ASSERT(fan_pct == 100);
|
|
|
|
return EC_SUCCESS;
|
|
}
|
|
|
|
static int test_two_fans(void)
|
|
{
|
|
reset_mocks();
|
|
|
|
thermal_params[1].temp_fan_off = 120;
|
|
thermal_params[1].temp_fan_max = 160;
|
|
thermal_params[2].temp_fan_off = 100;
|
|
thermal_params[2].temp_fan_max = 200;
|
|
|
|
all_temps(50);
|
|
sleep(2);
|
|
TEST_ASSERT(fan_pct == 0);
|
|
|
|
all_temps(100);
|
|
sleep(2);
|
|
TEST_ASSERT(fan_pct == 0);
|
|
|
|
all_temps(101);
|
|
sleep(2);
|
|
TEST_ASSERT(fan_pct == 1);
|
|
|
|
all_temps(130);
|
|
sleep(2);
|
|
/* fan 2 is still higher */
|
|
TEST_ASSERT(fan_pct == 30);
|
|
|
|
all_temps(150);
|
|
sleep(2);
|
|
/* now fan 1 is higher: 150 = 75% of [120-160] */
|
|
TEST_ASSERT(fan_pct == 75);
|
|
|
|
all_temps(170);
|
|
sleep(2);
|
|
/* fan 1 is maxed now */
|
|
TEST_ASSERT(fan_pct == 100);
|
|
|
|
all_temps(200);
|
|
sleep(2);
|
|
TEST_ASSERT(fan_pct == 100);
|
|
|
|
all_temps(300);
|
|
sleep(2);
|
|
TEST_ASSERT(fan_pct == 100);
|
|
|
|
return EC_SUCCESS;
|
|
}
|
|
|
|
static int test_all_fans(void)
|
|
{
|
|
reset_mocks();
|
|
|
|
thermal_params[0].temp_fan_off = 20;
|
|
thermal_params[0].temp_fan_max = 60;
|
|
thermal_params[1].temp_fan_off = 120;
|
|
thermal_params[1].temp_fan_max = 160;
|
|
thermal_params[2].temp_fan_off = 100;
|
|
thermal_params[2].temp_fan_max = 200;
|
|
thermal_params[3].temp_fan_off = 300;
|
|
thermal_params[3].temp_fan_max = 500;
|
|
|
|
set_temps(1, 1, 1, 1);
|
|
sleep(2);
|
|
TEST_ASSERT(fan_pct == 0);
|
|
|
|
/* Each sensor has its own range */
|
|
set_temps(40, 0, 0, 0);
|
|
sleep(2);
|
|
TEST_ASSERT(fan_pct == 50);
|
|
|
|
set_temps(0, 140, 0, 0);
|
|
sleep(2);
|
|
TEST_ASSERT(fan_pct == 50);
|
|
|
|
set_temps(0, 0, 150, 0);
|
|
sleep(2);
|
|
TEST_ASSERT(fan_pct == 50);
|
|
|
|
set_temps(0, 0, 0, 400);
|
|
sleep(2);
|
|
TEST_ASSERT(fan_pct == 50);
|
|
|
|
set_temps(60, 0, 0, 0);
|
|
sleep(2);
|
|
TEST_ASSERT(fan_pct == 100);
|
|
|
|
set_temps(0, 160, 0, 0);
|
|
sleep(2);
|
|
TEST_ASSERT(fan_pct == 100);
|
|
|
|
set_temps(0, 0, 200, 0);
|
|
sleep(2);
|
|
TEST_ASSERT(fan_pct == 100);
|
|
|
|
set_temps(0, 0, 0, 500);
|
|
sleep(2);
|
|
TEST_ASSERT(fan_pct == 100);
|
|
|
|
/* But sensor 0 needs the most cooling */
|
|
all_temps(20);
|
|
sleep(2);
|
|
TEST_ASSERT(fan_pct == 0);
|
|
|
|
all_temps(21);
|
|
sleep(2);
|
|
TEST_ASSERT(fan_pct == 2);
|
|
|
|
all_temps(30);
|
|
sleep(2);
|
|
TEST_ASSERT(fan_pct == 25);
|
|
|
|
all_temps(40);
|
|
sleep(2);
|
|
TEST_ASSERT(fan_pct == 50);
|
|
|
|
all_temps(50);
|
|
sleep(2);
|
|
TEST_ASSERT(fan_pct == 75);
|
|
|
|
all_temps(60);
|
|
sleep(2);
|
|
TEST_ASSERT(fan_pct == 100);
|
|
|
|
all_temps(65);
|
|
sleep(2);
|
|
TEST_ASSERT(fan_pct == 100);
|
|
|
|
return EC_SUCCESS;
|
|
}
|
|
|
|
static int test_one_limit(void)
|
|
{
|
|
reset_mocks();
|
|
thermal_params[2].temp_host[EC_TEMP_THRESH_WARN] = 100;
|
|
thermal_params[2].temp_host[EC_TEMP_THRESH_HIGH] = 200;
|
|
thermal_params[2].temp_host[EC_TEMP_THRESH_HALT] = 300;
|
|
|
|
all_temps(50);
|
|
sleep(2);
|
|
TEST_ASSERT(host_throttled == 0);
|
|
TEST_ASSERT(cpu_throttled == 0);
|
|
TEST_ASSERT(cpu_shutdown == 0);
|
|
|
|
all_temps(100);
|
|
sleep(2);
|
|
TEST_ASSERT(host_throttled == 0);
|
|
TEST_ASSERT(cpu_throttled == 0);
|
|
TEST_ASSERT(cpu_shutdown == 0);
|
|
|
|
all_temps(101);
|
|
sleep(2);
|
|
TEST_ASSERT(host_throttled == t_s_therm);
|
|
TEST_ASSERT(cpu_throttled == 0);
|
|
TEST_ASSERT(cpu_shutdown == 0);
|
|
|
|
all_temps(100);
|
|
sleep(2);
|
|
TEST_ASSERT(host_throttled == t_s_therm);
|
|
TEST_ASSERT(cpu_throttled == 0);
|
|
TEST_ASSERT(cpu_shutdown == 0);
|
|
|
|
all_temps(99);
|
|
sleep(2);
|
|
TEST_ASSERT(host_throttled == 0);
|
|
TEST_ASSERT(cpu_throttled == 0);
|
|
TEST_ASSERT(cpu_shutdown == 0);
|
|
|
|
all_temps(199);
|
|
sleep(2);
|
|
TEST_ASSERT(host_throttled == t_s_therm);
|
|
TEST_ASSERT(cpu_throttled == 0);
|
|
TEST_ASSERT(cpu_shutdown == 0);
|
|
|
|
all_temps(200);
|
|
sleep(2);
|
|
TEST_ASSERT(host_throttled == t_s_therm);
|
|
TEST_ASSERT(cpu_throttled == 0);
|
|
TEST_ASSERT(cpu_shutdown == 0);
|
|
|
|
all_temps(201);
|
|
sleep(2);
|
|
TEST_ASSERT(host_throttled == t_s_therm);
|
|
TEST_ASSERT(cpu_throttled == t_s_therm);
|
|
TEST_ASSERT(cpu_shutdown == 0);
|
|
|
|
all_temps(200);
|
|
sleep(2);
|
|
TEST_ASSERT(host_throttled == t_s_therm);
|
|
TEST_ASSERT(cpu_throttled == t_s_therm);
|
|
TEST_ASSERT(cpu_shutdown == 0);
|
|
|
|
all_temps(199);
|
|
sleep(2);
|
|
TEST_ASSERT(host_throttled == t_s_therm);
|
|
TEST_ASSERT(cpu_throttled == 0);
|
|
TEST_ASSERT(cpu_shutdown == 0);
|
|
|
|
all_temps(99);
|
|
sleep(2);
|
|
TEST_ASSERT(host_throttled == 0);
|
|
TEST_ASSERT(cpu_throttled == 0);
|
|
TEST_ASSERT(cpu_shutdown == 0);
|
|
|
|
all_temps(201);
|
|
sleep(2);
|
|
TEST_ASSERT(host_throttled == t_s_therm);
|
|
TEST_ASSERT(cpu_throttled == t_s_therm);
|
|
TEST_ASSERT(cpu_shutdown == 0);
|
|
|
|
all_temps(99);
|
|
sleep(2);
|
|
TEST_ASSERT(host_throttled == 0);
|
|
TEST_ASSERT(cpu_throttled == 0);
|
|
TEST_ASSERT(cpu_shutdown == 0);
|
|
|
|
all_temps(301);
|
|
sleep(2);
|
|
TEST_ASSERT(host_throttled == t_s_therm);
|
|
TEST_ASSERT(cpu_throttled == t_s_therm);
|
|
TEST_ASSERT(cpu_shutdown == 1);
|
|
|
|
/* We probably won't be able to read the CPU temp while shutdown,
|
|
* so nothing will change. */
|
|
all_temps(-1);
|
|
sleep(2);
|
|
TEST_ASSERT(host_throttled == t_s_therm);
|
|
TEST_ASSERT(cpu_throttled == t_s_therm);
|
|
/* cpu_shutdown is only set for testing purposes. The thermal task
|
|
* doesn't do anything that could clear it. */
|
|
|
|
all_temps(50);
|
|
sleep(2);
|
|
TEST_ASSERT(host_throttled == 0);
|
|
TEST_ASSERT(cpu_throttled == 0);
|
|
|
|
return EC_SUCCESS;
|
|
}
|
|
|
|
static int test_several_limits(void)
|
|
{
|
|
reset_mocks();
|
|
|
|
thermal_params[1].temp_host[EC_TEMP_THRESH_WARN] = 150;
|
|
thermal_params[1].temp_host[EC_TEMP_THRESH_HIGH] = 200;
|
|
thermal_params[1].temp_host[EC_TEMP_THRESH_HALT] = 250;
|
|
|
|
thermal_params[2].temp_host[EC_TEMP_THRESH_WARN] = 100;
|
|
thermal_params[2].temp_host[EC_TEMP_THRESH_HIGH] = 200;
|
|
thermal_params[2].temp_host[EC_TEMP_THRESH_HALT] = 300;
|
|
|
|
thermal_params[3].temp_host[EC_TEMP_THRESH_WARN] = 20;
|
|
thermal_params[3].temp_host[EC_TEMP_THRESH_HIGH] = 30;
|
|
thermal_params[3].temp_host[EC_TEMP_THRESH_HALT] = 40;
|
|
|
|
set_temps(500, 100, 150, 10);
|
|
sleep(2);
|
|
TEST_ASSERT(host_throttled == t_s_therm); /* 1=low, 2=warn, 3=low */
|
|
TEST_ASSERT(cpu_throttled == 0);
|
|
TEST_ASSERT(cpu_shutdown == 0);
|
|
|
|
set_temps(500, 50, -1, 10); /* 1=low, 2=X, 3=low */
|
|
sleep(2);
|
|
TEST_ASSERT(host_throttled == 0);
|
|
TEST_ASSERT(cpu_throttled == 0);
|
|
TEST_ASSERT(cpu_shutdown == 0);
|
|
|
|
set_temps(500, 170, 210, 10); /* 1=warn, 2=high, 3=low */
|
|
sleep(2);
|
|
TEST_ASSERT(host_throttled == t_s_therm);
|
|
TEST_ASSERT(cpu_throttled == t_s_therm);
|
|
TEST_ASSERT(cpu_shutdown == 0);
|
|
|
|
set_temps(500, 100, 50, 40); /* 1=low, 2=low, 3=high */
|
|
sleep(2);
|
|
TEST_ASSERT(host_throttled == t_s_therm);
|
|
TEST_ASSERT(cpu_throttled == t_s_therm);
|
|
TEST_ASSERT(cpu_shutdown == 0);
|
|
|
|
set_temps(500, 100, 50, 41); /* 1=low, 2=low, 3=shutdown */
|
|
sleep(2);
|
|
TEST_ASSERT(host_throttled == t_s_therm);
|
|
TEST_ASSERT(cpu_throttled == t_s_therm);
|
|
TEST_ASSERT(cpu_shutdown == 1);
|
|
|
|
all_temps(0); /* reset from shutdown */
|
|
sleep(2);
|
|
TEST_ASSERT(host_throttled == 0);
|
|
TEST_ASSERT(cpu_throttled == 0);
|
|
|
|
|
|
return EC_SUCCESS;
|
|
}
|
|
|
|
static int test_batt(void)
|
|
{
|
|
struct adapter_limits *l;
|
|
int longtime;
|
|
int i;
|
|
|
|
reset_mocks();
|
|
/* We're assuming two limits, mild and urgent. */
|
|
TEST_ASSERT(NUM_BATT_THRESHOLDS == 2);
|
|
/* Find out which is which, only use the lower one */
|
|
if (batt_limits[0].hi_val > batt_limits[1].hi_val)
|
|
l = &batt_limits[1];
|
|
else
|
|
l = &batt_limits[0];
|
|
|
|
/* Find a time longer than all sample count limits */
|
|
for (i = longtime = 0; i < NUM_BATT_THRESHOLDS; i++)
|
|
longtime = MAX(longtime,
|
|
MAX(batt_limits[i].lo_cnt,
|
|
batt_limits[i].hi_cnt));
|
|
longtime += 2;
|
|
|
|
/* On AC, but this doesn't actually matter for this test */
|
|
mock_batt(0);
|
|
change_ac(1);
|
|
|
|
TEST_ASSERT(ap_is_throttled == 0);
|
|
change_ac(0);
|
|
TEST_ASSERT(ap_is_throttled == 0);
|
|
|
|
/* reset, by staying low for a long time */
|
|
usleep(EXTPOWER_FALCO_POLL_PERIOD * longtime);
|
|
TEST_ASSERT(l->triggered == 0);
|
|
TEST_ASSERT(ap_is_throttled == 0);
|
|
|
|
/* mock_batt() specifies the DISCHARGE current. Charging
|
|
* should do nothing, no matter how high. */
|
|
mock_batt(-1);
|
|
usleep(EXTPOWER_FALCO_POLL_PERIOD * longtime);
|
|
TEST_ASSERT(l->triggered == 0);
|
|
TEST_ASSERT(ap_is_throttled == 0);
|
|
|
|
/* midrange for a long time shouldn't do anything */
|
|
mock_batt((l->lo_val + l->hi_val) / 2);
|
|
usleep(EXTPOWER_FALCO_POLL_PERIOD * longtime);
|
|
TEST_ASSERT(l->triggered == 0);
|
|
TEST_ASSERT(ap_is_throttled == 0);
|
|
|
|
/* above high limit for not quite long enough */
|
|
mock_batt(l->hi_val + 1);
|
|
usleep(EXTPOWER_FALCO_POLL_PERIOD * (l->hi_cnt - 1));
|
|
TEST_ASSERT(l->count != 0);
|
|
TEST_ASSERT(l->triggered == 0);
|
|
TEST_ASSERT(ap_is_throttled == 0);
|
|
|
|
/* drop below the high limit once */
|
|
mock_batt(l->hi_val - 1);
|
|
usleep(EXTPOWER_FALCO_POLL_PERIOD * 1);
|
|
TEST_ASSERT(l->count == 0);
|
|
TEST_ASSERT(l->triggered == 0);
|
|
TEST_ASSERT(ap_is_throttled == 0);
|
|
|
|
/* now back up */
|
|
mock_batt(l->hi_val + 1);
|
|
usleep(EXTPOWER_FALCO_POLL_PERIOD * (l->hi_cnt - 1));
|
|
TEST_ASSERT(l->count != 0);
|
|
TEST_ASSERT(l->triggered == 0);
|
|
TEST_ASSERT(ap_is_throttled == 0);
|
|
|
|
/* one more ought to do it */
|
|
usleep(EXTPOWER_FALCO_POLL_PERIOD * 1);
|
|
TEST_ASSERT(l->triggered == 1);
|
|
TEST_ASSERT(ap_is_throttled);
|
|
|
|
/* going midrange for a long time shouldn't change anything */
|
|
mock_batt((l->lo_val + l->hi_val) / 2);
|
|
usleep(EXTPOWER_FALCO_POLL_PERIOD * longtime);
|
|
TEST_ASSERT(l->triggered == 1);
|
|
TEST_ASSERT(ap_is_throttled);
|
|
|
|
/* charge for not quite long enough */
|
|
mock_batt(-1);
|
|
usleep(EXTPOWER_FALCO_POLL_PERIOD * (l->lo_cnt - 1));
|
|
TEST_ASSERT(l->triggered == 1);
|
|
TEST_ASSERT(ap_is_throttled);
|
|
|
|
/* back above the low limit once */
|
|
mock_batt(l->lo_val + 1);
|
|
usleep(EXTPOWER_FALCO_POLL_PERIOD * 1);
|
|
TEST_ASSERT(l->triggered == 1);
|
|
TEST_ASSERT(ap_is_throttled);
|
|
|
|
/* now charge again - that should have reset the count */
|
|
mock_batt(-1);
|
|
usleep(EXTPOWER_FALCO_POLL_PERIOD * (l->lo_cnt - 1));
|
|
TEST_ASSERT(l->triggered == 1);
|
|
TEST_ASSERT(ap_is_throttled);
|
|
|
|
/* One more ought to do it */
|
|
usleep(EXTPOWER_FALCO_POLL_PERIOD * 1);
|
|
TEST_ASSERT(l->triggered == 0);
|
|
TEST_ASSERT(ap_is_throttled == 0);
|
|
|
|
return EC_SUCCESS;
|
|
}
|
|
|
|
static int test_several_limits_with_batt(void)
|
|
{
|
|
struct adapter_limits *l;
|
|
int longtime;
|
|
int i;
|
|
|
|
/* We're assuming two limits, mild and urgent. */
|
|
TEST_ASSERT(NUM_BATT_THRESHOLDS == 2);
|
|
/* Find out which is which, only use the lower one */
|
|
if (batt_limits[0].hi_val > batt_limits[1].hi_val)
|
|
l = &batt_limits[1];
|
|
else
|
|
l = &batt_limits[0];
|
|
|
|
/* Find a time longer than all sample count limits */
|
|
for (i = longtime = 0; i < NUM_BATT_THRESHOLDS; i++)
|
|
longtime = MAX(longtime,
|
|
MAX(batt_limits[i].lo_cnt,
|
|
batt_limits[i].hi_cnt));
|
|
longtime += 2;
|
|
longtime *= EXTPOWER_FALCO_POLL_PERIOD;
|
|
|
|
reset_mocks();
|
|
|
|
/* Set some thermal limits */
|
|
thermal_params[1].temp_host[EC_TEMP_THRESH_WARN] = 150;
|
|
thermal_params[1].temp_host[EC_TEMP_THRESH_HIGH] = 200;
|
|
thermal_params[1].temp_host[EC_TEMP_THRESH_HALT] = 250;
|
|
|
|
thermal_params[2].temp_host[EC_TEMP_THRESH_WARN] = 100;
|
|
thermal_params[2].temp_host[EC_TEMP_THRESH_HIGH] = 200;
|
|
thermal_params[2].temp_host[EC_TEMP_THRESH_HALT] = 300;
|
|
|
|
thermal_params[3].temp_host[EC_TEMP_THRESH_WARN] = 20;
|
|
thermal_params[3].temp_host[EC_TEMP_THRESH_HIGH] = 30;
|
|
thermal_params[3].temp_host[EC_TEMP_THRESH_HALT] = 40;
|
|
|
|
|
|
/* On AC, charging */
|
|
mock_batt(-1);
|
|
all_temps(0);
|
|
change_ac(1);
|
|
usleep(longtime);
|
|
/* Everything is ready */
|
|
TEST_ASSERT(l->triggered == 0);
|
|
TEST_ASSERT(ap_is_throttled == 0);
|
|
TEST_ASSERT(host_throttled == 0);
|
|
TEST_ASSERT(cpu_throttled == 0);
|
|
TEST_ASSERT(cpu_shutdown == 0);
|
|
|
|
|
|
set_temps(500, 100, 150, 10);
|
|
usleep(longtime);
|
|
TEST_ASSERT(host_throttled == t_s_therm); /* 1=low, 2=warn, 3=low */
|
|
TEST_ASSERT(cpu_throttled == 0);
|
|
TEST_ASSERT(cpu_shutdown == 0);
|
|
|
|
/* battery up and down */
|
|
mock_batt(l->hi_val + 1);
|
|
usleep(longtime);
|
|
TEST_ASSERT(l->triggered == 1);
|
|
TEST_ASSERT(ap_is_throttled);
|
|
TEST_ASSERT(cpu_throttled == 0);
|
|
TEST_ASSERT(host_throttled == t_s_both); /* 1=low, 2=warn, 3=low */
|
|
TEST_ASSERT(cpu_shutdown == 0);
|
|
mock_batt(-1);
|
|
usleep(longtime);
|
|
TEST_ASSERT(l->triggered == 0);
|
|
TEST_ASSERT(ap_is_throttled == 0);
|
|
TEST_ASSERT(host_throttled == t_s_therm); /* 1=low, 2=warn, 3=low */
|
|
TEST_ASSERT(cpu_throttled == 0);
|
|
TEST_ASSERT(cpu_shutdown == 0);
|
|
|
|
|
|
set_temps(500, 50, -1, 10); /* 1=low, 2=X, 3=low */
|
|
usleep(longtime);
|
|
TEST_ASSERT(host_throttled == 0);
|
|
TEST_ASSERT(cpu_throttled == 0);
|
|
TEST_ASSERT(cpu_shutdown == 0);
|
|
TEST_ASSERT(l->triggered == 0);
|
|
TEST_ASSERT(ap_is_throttled == 0);
|
|
|
|
/* battery up and down */
|
|
mock_batt(l->hi_val + 1);
|
|
usleep(longtime);
|
|
TEST_ASSERT(l->triggered == 1);
|
|
TEST_ASSERT(ap_is_throttled);
|
|
TEST_ASSERT(cpu_throttled == 0);
|
|
TEST_ASSERT(host_throttled == t_s_power);
|
|
TEST_ASSERT(cpu_shutdown == 0);
|
|
mock_batt(-1);
|
|
usleep(longtime);
|
|
TEST_ASSERT(l->triggered == 0);
|
|
TEST_ASSERT(ap_is_throttled == 0);
|
|
TEST_ASSERT(host_throttled == 0);
|
|
TEST_ASSERT(cpu_throttled == 0);
|
|
TEST_ASSERT(cpu_shutdown == 0);
|
|
|
|
|
|
set_temps(500, 170, 210, 10); /* 1=warn, 2=high, 3=low */
|
|
sleep(2);
|
|
TEST_ASSERT(host_throttled == t_s_therm);
|
|
TEST_ASSERT(cpu_throttled == t_s_therm);
|
|
TEST_ASSERT(cpu_shutdown == 0);
|
|
|
|
/* battery up and down */
|
|
mock_batt(l->hi_val + 1);
|
|
usleep(longtime);
|
|
TEST_ASSERT(l->triggered == 1);
|
|
TEST_ASSERT(ap_is_throttled);
|
|
TEST_ASSERT(cpu_throttled == t_s_therm);
|
|
TEST_ASSERT(host_throttled == t_s_both);
|
|
TEST_ASSERT(cpu_shutdown == 0);
|
|
mock_batt(-1);
|
|
usleep(longtime);
|
|
TEST_ASSERT(l->triggered == 0);
|
|
TEST_ASSERT(ap_is_throttled == 0);
|
|
TEST_ASSERT(host_throttled == t_s_therm);
|
|
TEST_ASSERT(cpu_throttled == t_s_therm);
|
|
TEST_ASSERT(cpu_shutdown == 0);
|
|
|
|
|
|
set_temps(500, 100, 50, 40); /* 1=low, 2=low, 3=high */
|
|
usleep(longtime);
|
|
TEST_ASSERT(host_throttled == t_s_therm);
|
|
TEST_ASSERT(cpu_throttled == t_s_therm);
|
|
TEST_ASSERT(cpu_shutdown == 0);
|
|
|
|
/* battery up and down */
|
|
mock_batt(l->hi_val + 1);
|
|
usleep(longtime);
|
|
TEST_ASSERT(l->triggered == 1);
|
|
TEST_ASSERT(ap_is_throttled);
|
|
TEST_ASSERT(cpu_throttled == t_s_therm);
|
|
TEST_ASSERT(host_throttled == t_s_both);
|
|
TEST_ASSERT(cpu_shutdown == 0);
|
|
mock_batt(-1);
|
|
usleep(longtime);
|
|
TEST_ASSERT(l->triggered == 0);
|
|
TEST_ASSERT(ap_is_throttled == 0);
|
|
TEST_ASSERT(host_throttled == t_s_therm);
|
|
TEST_ASSERT(cpu_throttled == t_s_therm);
|
|
TEST_ASSERT(cpu_shutdown == 0);
|
|
|
|
|
|
set_temps(500, 100, 50, 41); /* 1=low, 2=low, 3=shutdown */
|
|
usleep(longtime);
|
|
TEST_ASSERT(host_throttled == t_s_therm);
|
|
TEST_ASSERT(cpu_throttled == t_s_therm);
|
|
TEST_ASSERT(cpu_shutdown == 1);
|
|
|
|
/* battery up and down */
|
|
mock_batt(l->hi_val + 1);
|
|
usleep(longtime);
|
|
TEST_ASSERT(l->triggered == 1);
|
|
TEST_ASSERT(ap_is_throttled);
|
|
TEST_ASSERT(cpu_throttled == t_s_therm);
|
|
TEST_ASSERT(host_throttled == t_s_both);
|
|
TEST_ASSERT(cpu_shutdown == 1);
|
|
mock_batt(-1);
|
|
usleep(longtime);
|
|
TEST_ASSERT(l->triggered == 0);
|
|
TEST_ASSERT(ap_is_throttled == 0);
|
|
TEST_ASSERT(host_throttled == t_s_therm);
|
|
TEST_ASSERT(cpu_throttled == t_s_therm);
|
|
TEST_ASSERT(cpu_shutdown == 1);
|
|
|
|
|
|
all_temps(0);
|
|
usleep(longtime);
|
|
TEST_ASSERT(host_throttled == 0);
|
|
TEST_ASSERT(cpu_throttled == 0);
|
|
TEST_ASSERT(l->triggered == 0);
|
|
TEST_ASSERT(ap_is_throttled == 0);
|
|
|
|
/* battery up and down */
|
|
mock_batt(l->hi_val + 1);
|
|
usleep(longtime);
|
|
TEST_ASSERT(l->triggered == 1);
|
|
TEST_ASSERT(ap_is_throttled);
|
|
TEST_ASSERT(cpu_throttled == 0);
|
|
TEST_ASSERT(host_throttled == t_s_power);
|
|
mock_batt(-1);
|
|
usleep(longtime);
|
|
TEST_ASSERT(l->triggered == 0);
|
|
TEST_ASSERT(ap_is_throttled == 0);
|
|
TEST_ASSERT(host_throttled == 0);
|
|
TEST_ASSERT(cpu_throttled == 0);
|
|
|
|
return EC_SUCCESS;
|
|
}
|
|
|
|
|
|
void run_test(void)
|
|
{
|
|
test_chipset_on();
|
|
|
|
RUN_TEST(test_init_val);
|
|
RUN_TEST(test_sensors_can_be_read);
|
|
RUN_TEST(test_one_fan);
|
|
RUN_TEST(test_two_fans);
|
|
RUN_TEST(test_all_fans);
|
|
|
|
RUN_TEST(test_one_limit);
|
|
RUN_TEST(test_several_limits);
|
|
|
|
RUN_TEST(test_batt);
|
|
RUN_TEST(test_several_limits_with_batt);
|
|
|
|
test_print_result();
|
|
}
|