Add background temperature monitoring daemon

This enables temperature display in the Web portal,
and lays the groundwork for a future fan control
service.
parent 4458da8d
...@@ -139,9 +139,11 @@ uint8_t kestrel_basic_init_complete = 0; ...@@ -139,9 +139,11 @@ uint8_t kestrel_basic_init_complete = 0;
// Thread identifiers // Thread identifiers
k_tid_t kestrel_service_thread_id = NULL; k_tid_t kestrel_service_thread_id = NULL;
k_tid_t kestrel_console_thread_id = NULL; k_tid_t kestrel_console_thread_id = NULL;
k_tid_t thermal_service_thread_id = NULL;
// Mutexes // Mutexes
struct k_mutex vuart1_access_mutex; struct k_mutex vuart1_access_mutex;
struct k_mutex occ_access_mutex;
// Console structures // Console structures
const struct shell *host_console_service_task_shell = NULL; const struct shell *host_console_service_task_shell = NULL;
...@@ -1737,6 +1739,13 @@ static int process_interrupts_stage2(void) ...@@ -1737,6 +1739,13 @@ static int process_interrupts_stage2(void)
uint8_t led_post_code = (((post_code >> 8) & 0xf) << 4) | (post_code & 0xf); uint8_t led_post_code = (((post_code >> 8) & 0xf) << 4) | (post_code & 0xf);
set_led_bank_display(led_post_code); set_led_bank_display(led_post_code);
if (post_code == 0xfefe)
{
host_power_status = HOST_POWER_STATUS_RUNNING;
set_led_bank_display(0);
display_character('0' + 2 + host_power_status, 0); // STATUS CODE
}
if (enable_post_code_console_output) if (enable_post_code_console_output)
{ {
KESTREL_LOG("[POST CODE] %d.%d", (post_code >> 8) & 0xff, post_code & 0xff); KESTREL_LOG("[POST CODE] %d.%d", (post_code >> 8) & 0xff, post_code & 0xff);
...@@ -2183,6 +2192,7 @@ static int disable_avsbus_pmbus(const cpu_info_t *cpu_info, int cpu_count) ...@@ -2183,6 +2192,7 @@ static int disable_avsbus_pmbus(const cpu_info_t *cpu_info, int cpu_count)
void power_off_chassis(void) void power_off_chassis(void)
{ {
host_power_status = HOST_POWER_STATUS_POWERING_OFF; host_power_status = HOST_POWER_STATUS_POWERING_OFF;
display_character('0' + 2 + host_power_status, 0); // STATUS CODE
// Disable PMBUS // Disable PMBUS
if (disable_avsbus_pmbus(g_cpu_info, configured_cpu_count)) if (disable_avsbus_pmbus(g_cpu_info, configured_cpu_count))
...@@ -2196,6 +2206,7 @@ void power_off_chassis(void) ...@@ -2196,6 +2206,7 @@ void power_off_chassis(void)
run_post_shutdown_bmc_peripheral_teardown(); run_post_shutdown_bmc_peripheral_teardown();
host_power_status = HOST_POWER_STATUS_OFFLINE; host_power_status = HOST_POWER_STATUS_OFFLINE;
display_character('0' + 2 + host_power_status, 0); // STATUS CODE
} }
static int power_on_chassis(void) static int power_on_chassis(void)
...@@ -2207,12 +2218,14 @@ static int power_on_chassis(void) ...@@ -2207,12 +2218,14 @@ static int power_on_chassis(void)
uint8_t byte; uint8_t byte;
host_power_status = HOST_POWER_STATUS_POWERING_ON; host_power_status = HOST_POWER_STATUS_POWERING_ON;
display_character('0' + 2 + host_power_status, 0); // STATUS CODE
// Verify communication with platform control FPGA // Verify communication with platform control FPGA
platform_fpga_identifier[0] = i2c_read_register_byte((uint8_t *)I2CMASTER4_BASE, HOST_PLATFORM_FPGA_I2C_ADDRESS, 0x0c, NULL); platform_fpga_identifier[0] = i2c_read_register_byte((uint8_t *)I2CMASTER4_BASE, HOST_PLATFORM_FPGA_I2C_ADDRESS, 0x0c, NULL);
if (platform_fpga_identifier[0] == 0xff) if (platform_fpga_identifier[0] == 0xff)
{ {
host_power_status = HOST_POWER_STATUS_OFFLINE; host_power_status = HOST_POWER_STATUS_OFFLINE;
display_character('0' + 2 + host_power_status, 0); // STATUS CODE
return -1; return -1;
} }
platform_fpga_identifier[1] = i2c_read_register_byte((uint8_t *)I2CMASTER4_BASE, HOST_PLATFORM_FPGA_I2C_ADDRESS, 0x0d, NULL); platform_fpga_identifier[1] = i2c_read_register_byte((uint8_t *)I2CMASTER4_BASE, HOST_PLATFORM_FPGA_I2C_ADDRESS, 0x0d, NULL);
...@@ -2222,6 +2235,7 @@ static int power_on_chassis(void) ...@@ -2222,6 +2235,7 @@ static int power_on_chassis(void)
(platform_fpga_identifier[3] != 0x20)) (platform_fpga_identifier[3] != 0x20))
{ {
host_power_status = HOST_POWER_STATUS_OFFLINE; host_power_status = HOST_POWER_STATUS_OFFLINE;
display_character('0' + 2 + host_power_status, 0); // STATUS CODE
return -1; return -1;
} }
KESTREL_LOG("Platform FPGA communication verified"); KESTREL_LOG("Platform FPGA communication verified");
...@@ -2280,7 +2294,8 @@ static int power_on_chassis(void) ...@@ -2280,7 +2294,8 @@ static int power_on_chassis(void)
return -5; return -5;
} }
host_power_status = HOST_POWER_STATUS_RUNNING; host_power_status = HOST_POWER_STATUS_IPLING;
display_character('0' + 2 + host_power_status, 0); // STATUS CODE
return 0; return 0;
} }
...@@ -3447,6 +3462,7 @@ int kestrel_init(void) ...@@ -3447,6 +3462,7 @@ int kestrel_init(void)
#if (WITH_ZEPHYR) #if (WITH_ZEPHYR)
// Initialize mutexes // Initialize mutexes
k_mutex_init(&vuart1_access_mutex); k_mutex_init(&vuart1_access_mutex);
k_mutex_init(&occ_access_mutex);
#endif #endif
for (int i = 0; i < MAX_CPUS_SUPPORTED; i++) for (int i = 0; i < MAX_CPUS_SUPPORTED; i++)
......
...@@ -30,8 +30,9 @@ ...@@ -30,8 +30,9 @@
#define HOST_POWER_STATUS_OFFLINE 0 #define HOST_POWER_STATUS_OFFLINE 0
#define HOST_POWER_STATUS_POWERING_ON 1 #define HOST_POWER_STATUS_POWERING_ON 1
#define HOST_POWER_STATUS_RUNNING 2 #define HOST_POWER_STATUS_IPLING 2
#define HOST_POWER_STATUS_POWERING_OFF 3 #define HOST_POWER_STATUS_RUNNING 3
#define HOST_POWER_STATUS_POWERING_OFF 4
#define KESTREL_VERSION_MAJOR 0 #define KESTREL_VERSION_MAJOR 0
#define KESTREL_VERSION_MINOR 1 #define KESTREL_VERSION_MINOR 1
...@@ -56,6 +57,8 @@ extern uint8_t host_power_status; ...@@ -56,6 +57,8 @@ extern uint8_t host_power_status;
#if (WITH_ZEPHYR) #if (WITH_ZEPHYR)
extern k_tid_t kestrel_service_thread_id; extern k_tid_t kestrel_service_thread_id;
extern k_tid_t kestrel_console_thread_id; extern k_tid_t kestrel_console_thread_id;
extern k_tid_t thermal_service_thread_id;
extern struct k_mutex occ_access_mutex;
extern const struct shell *host_console_service_task_shell; extern const struct shell *host_console_service_task_shell;
#endif #endif
......
...@@ -233,6 +233,11 @@ static int kestrel_shell_cmd_occcontrol(const struct shell *shell, size_t argc, ...@@ -233,6 +233,11 @@ static int kestrel_shell_cmd_occcontrol(const struct shell *shell, size_t argc,
} }
if (strcmp(argv[1], "poll") == 0) { if (strcmp(argv[1], "poll") == 0) {
if (k_mutex_lock(&occ_access_mutex, K_MSEC(1000)) != 0) {
printk("Unable to acquire OCC mutex in a timely manner! %s:%d\n", __FILE__, __LINE__);
return -EAGAIN;
}
if (occ_poll(0, 0x2400, IBM_POWER9_SBE_OCC_RESPONSE_SIZE, response_data, &response_length)) if (occ_poll(0, 0x2400, IBM_POWER9_SBE_OCC_RESPONSE_SIZE, response_data, &response_length))
{ {
shell_print(shell, "OCC not responding!"); shell_print(shell, "OCC not responding!");
...@@ -249,6 +254,13 @@ static int kestrel_shell_cmd_occcontrol(const struct shell *shell, size_t argc, ...@@ -249,6 +254,13 @@ static int kestrel_shell_cmd_occcontrol(const struct shell *shell, size_t argc,
shell_print(shell, "Temperature sensor 0x%08x: %d° C", host_cpu_temperature_sensor_data[sensor_number].sensor_id, host_cpu_temperature_sensor_data[sensor_number].temperature_c); shell_print(shell, "Temperature sensor 0x%08x: %d° C", host_cpu_temperature_sensor_data[sensor_number].sensor_id, host_cpu_temperature_sensor_data[sensor_number].temperature_c);
} }
} }
k_mutex_unlock(&occ_access_mutex);
}
else {
shell_print(shell, "%s: Invalid parameter", argv[0]);
print_kestrel_occcontrol_command_usage(shell, argv[0]);
return -1;
} }
return 0; return 0;
......
...@@ -12,6 +12,7 @@ LOG_MODULE_REGISTER(webportal, LOG_LEVEL_DBG); ...@@ -12,6 +12,7 @@ LOG_MODULE_REGISTER(webportal, LOG_LEVEL_DBG);
#include <data/json.h> #include <data/json.h>
#include "simple_pwm.h" #include "simple_pwm.h"
#include "sbe_fsi.h"
#include "webportal.h" #include "webportal.h"
#include "redfish.h" #include "redfish.h"
...@@ -160,6 +161,9 @@ const char* host_power_status_to_string(int power_status) ...@@ -160,6 +161,9 @@ const char* host_power_status_to_string(int power_status)
else if (power_status == HOST_POWER_STATUS_POWERING_ON) { else if (power_status == HOST_POWER_STATUS_POWERING_ON) {
return "Powering On"; return "Powering On";
} }
else if (power_status == HOST_POWER_STATUS_IPLING) {
return "Initial Program Load";
}
else if (power_status == HOST_POWER_STATUS_RUNNING) { else if (power_status == HOST_POWER_STATUS_RUNNING) {
return "Online"; return "Online";
} }
...@@ -201,6 +205,17 @@ int host_status_handler(struct mg_connection *conn, void *cbdata) ...@@ -201,6 +205,17 @@ int host_status_handler(struct mg_connection *conn, void *cbdata)
mg_printf(conn, "PWM channel %d - %d%% (%d RPM)<br>\n", i, (pwm_values[i] * 100) / 256, tach_values[i]); mg_printf(conn, "PWM channel %d - %d%% (%d RPM)<br>\n", i, (pwm_values[i] * 100) / 256, tach_values[i]);
} }
mg_printf(conn, "</div>"); mg_printf(conn, "</div>");
if (host_cpu_temperature_sensor_count != 0)
{
mg_printf(conn, "<p>");
mg_printf(conn, "<b>Thermal</b><br>");
mg_printf(conn, "<div style=\"margin-left: 20px\">");
for (i = 0; i < host_cpu_temperature_sensor_count; i++)
{
mg_printf(conn, "Sensor 0x%08x: %d° C<br>\n", host_cpu_temperature_sensor_data[i].sensor_id, host_cpu_temperature_sensor_data[i].temperature_c);
}
mg_printf(conn, "</div>");
}
mg_printf(conn, "<p>"); mg_printf(conn, "<p>");
mg_printf(conn, "<b>Control</b><br>"); mg_printf(conn, "<b>Control</b><br>");
mg_printf(conn, "<div style=\"margin-left: 20px\">"); mg_printf(conn, "<div style=\"margin-left: 20px\">");
......
...@@ -17,6 +17,7 @@ LOG_MODULE_REGISTER(kestrel_init, LOG_LEVEL_DBG); ...@@ -17,6 +17,7 @@ LOG_MODULE_REGISTER(kestrel_init, LOG_LEVEL_DBG);
#include "webservice.h" #include "webservice.h"
#include "flash_filesystem.h" #include "flash_filesystem.h"
#include "sbe_fsi.h"
#include "kestrel.h" #include "kestrel.h"
static struct gpio_callback host_power_button_callback_data; static struct gpio_callback host_power_button_callback_data;
...@@ -30,6 +31,9 @@ static struct k_sem kestrel_init_thread_lock; ...@@ -30,6 +31,9 @@ static struct k_sem kestrel_init_thread_lock;
static K_THREAD_STACK_DEFINE(kestrel_service_thread_stack, 16384); static K_THREAD_STACK_DEFINE(kestrel_service_thread_stack, 16384);
static struct k_thread kestrel_service_thread_data; static struct k_thread kestrel_service_thread_data;
static K_THREAD_STACK_DEFINE(thermal_service_thread_stack, 16384);
static struct k_thread thermal_service_thread_data;
#define KESTREL_IDLE_THREAD_PRIORITY K_PRIO_PREEMPT(CONFIG_NUM_PREEMPT_PRIORITIES - 1) #define KESTREL_IDLE_THREAD_PRIORITY K_PRIO_PREEMPT(CONFIG_NUM_PREEMPT_PRIORITIES - 1)
#define BUTTON_PRESS_DEBOUNCE_DELAY_MS 200 #define BUTTON_PRESS_DEBOUNCE_DELAY_MS 200
...@@ -60,6 +64,37 @@ static void kestrel_service_thread(void) ...@@ -60,6 +64,37 @@ static void kestrel_service_thread(void)
} }
} }
static void thermal_service_thread(void)
{
uint8_t response_data[IBM_POWER9_SBE_OCC_RESPONSE_SIZE];
size_t response_length = 0;
while (1) {
if (host_power_status == HOST_POWER_STATUS_RUNNING)
{
if (k_mutex_lock(&occ_access_mutex, K_MSEC(1000)) != 0) {
printk("Unable to acquire OCC mutex in a timely manner! %s:%d\n", __FILE__, __LINE__);
continue;
}
if (occ_poll(0, 0x2400, IBM_POWER9_SBE_OCC_RESPONSE_SIZE, response_data, &response_length))
{
// Unable to read sensors
host_cpu_temperature_sensor_count = 0;
}
k_mutex_unlock(&occ_access_mutex);
k_usleep(100000);
}
else
{
host_cpu_temperature_sensor_count = 0;
k_usleep(100000);
}
}
}
void host_power_button_pressed(const struct device *dev, struct gpio_callback *cb, uint32_t pins) void host_power_button_pressed(const struct device *dev, struct gpio_callback *cb, uint32_t pins)
{ {
static uint64_t last_press = 0; static uint64_t last_press = 0;
...@@ -197,6 +232,12 @@ void main(void) ...@@ -197,6 +232,12 @@ void main(void)
NULL, NULL, NULL, KESTREL_SERVICE_THREAD_PRIORITY, 0, K_NO_WAIT); NULL, NULL, NULL, KESTREL_SERVICE_THREAD_PRIORITY, 0, K_NO_WAIT);
k_thread_name_set(kestrel_service_thread_id, "kestrel_service"); k_thread_name_set(kestrel_service_thread_id, "kestrel_service");
thermal_service_thread_id = k_thread_create(&thermal_service_thread_data, thermal_service_thread_stack,
K_THREAD_STACK_SIZEOF(thermal_service_thread_stack),
(k_thread_entry_t)thermal_service_thread,
NULL, NULL, NULL, KESTREL_SERVICE_THREAD_PRIORITY, 0, K_NO_WAIT);
k_thread_name_set(thermal_service_thread_id, "thermal_service");
// Run late setup // Run late setup
configure_gpios(); configure_gpios();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment