Add chassis power control locks

This avoids multiple threads interfering with
each other during chassis power operations.
parent 75bbadf4
......@@ -146,6 +146,9 @@ k_tid_t thermal_service_thread_id = NULL;
struct k_mutex vuart1_access_mutex;
struct k_mutex occ_access_mutex;
// Semaphores
struct k_sem chassis_control_semaphore;
// Console structures
const struct shell *host_console_service_task_shell = NULL;
#endif
......@@ -2254,8 +2257,15 @@ static int disable_avsbus_pmbus(const cpu_info_t *cpu_info, int cpu_count)
return status;
}
void power_off_chassis(void)
void power_off_chassis(int has_lock)
{
if (!has_lock) {
if (k_sem_take(&chassis_control_semaphore, K_MSEC(10)) != 0) {
// Unable to obtain chassis exclusive lock
return;
}
}
host_power_status = HOST_POWER_STATUS_POWERING_OFF;
display_character('0' + 2 + host_power_status, 0); // STATUS CODE
......@@ -2272,9 +2282,13 @@ void power_off_chassis(void)
host_power_status = HOST_POWER_STATUS_OFFLINE;
display_character('0' + 2 + host_power_status, 0); // STATUS CODE
if (!has_lock) {
k_sem_give(&chassis_control_semaphore);
}
}
static int power_on_chassis(void)
int power_on_chassis(int has_lock)
{
uint8_t platform_fpga_identifier[4];
int platform_power_on_timeout_counter;
......@@ -2282,6 +2296,13 @@ static int power_on_chassis(void)
int i2c_read_retcode;
uint8_t byte;
if (!has_lock) {
if (k_sem_take(&chassis_control_semaphore, K_MSEC(10)) != 0) {
// Unable to obtain chassis exclusive lock
return -EAGAIN;
}
}
host_power_status = HOST_POWER_STATUS_POWERING_ON;
display_character('0' + 2 + host_power_status, 0); // STATUS CODE
......@@ -2291,6 +2312,9 @@ static int power_on_chassis(void)
{
host_power_status = HOST_POWER_STATUS_OFFLINE;
display_character('0' + 2 + host_power_status, 0); // STATUS CODE
if (!has_lock) {
k_sem_give(&chassis_control_semaphore);
}
return -1;
}
platform_fpga_identifier[1] = i2c_read_register_byte((uint8_t *)I2CMASTER4_BASE, HOST_PLATFORM_FPGA_I2C_ADDRESS, 0x0d, NULL);
......@@ -2301,6 +2325,9 @@ static int power_on_chassis(void)
{
host_power_status = HOST_POWER_STATUS_OFFLINE;
display_character('0' + 2 + host_power_status, 0); // STATUS CODE
if (!has_lock) {
k_sem_give(&chassis_control_semaphore);
}
return -1;
}
KESTREL_LOG("Platform FPGA communication verified");
......@@ -2318,7 +2345,10 @@ static int power_on_chassis(void)
if (platform_power_on_timeout_counter > 20000)
{
KESTREL_LOG("Chassis poweron timeout!");
power_off_chassis();
power_off_chassis(1);
if (!has_lock) {
k_sem_give(&chassis_control_semaphore);
}
return -2;
}
usleep(100);
......@@ -2328,6 +2358,10 @@ static int power_on_chassis(void)
if (i2c_read_retcode)
{
KESTREL_LOG("FPGA communication failure during poweron!");
power_off_chassis(1);
if (!has_lock) {
k_sem_give(&chassis_control_semaphore);
}
return -3;
}
if (byte & 0x20)
......@@ -2347,7 +2381,10 @@ static int power_on_chassis(void)
if (apply_avsbus_workarounds(g_cpu_info, cpu_count))
{
KESTREL_LOG("AVSBus setup failed!");
power_off_chassis();
power_off_chassis(1);
if (!has_lock) {
k_sem_give(&chassis_control_semaphore);
}
return -4;
}
......@@ -2355,28 +2392,43 @@ static int power_on_chassis(void)
if (enable_avsbus_pmbus(g_cpu_info, cpu_count))
{
KESTREL_LOG("PMBUS enable failed!");
power_off_chassis();
power_off_chassis(1);
if (!has_lock) {
k_sem_give(&chassis_control_semaphore);
}
return -5;
}
host_power_status = HOST_POWER_STATUS_IPLING;
display_character('0' + 2 + host_power_status, 0); // STATUS CODE
if (!has_lock) {
k_sem_give(&chassis_control_semaphore);
}
return 0;
}
int power_on_host(void)
{
if (power_on_chassis())
if (k_sem_take(&chassis_control_semaphore, K_MSEC(10)) != 0) {
// Unable to obtain chassis exclusive lock
return -EAGAIN;
}
if (power_on_chassis(1))
{
k_sem_give(&chassis_control_semaphore);
return -1;
}
if (start_ipl(0))
{
k_sem_give(&chassis_control_semaphore);
return -1;
}
k_sem_give(&chassis_control_semaphore);
return 0;
}
......@@ -3173,11 +3225,11 @@ static void console_service(void)
}
else if (strcmp(token, "chassison") == 0)
{
power_on_chassis();
power_on_chassis(0);
}
else if (strcmp(token, "chassisoff") == 0)
{
power_off_chassis();
power_off_chassis(0);
KESTREL_LOG("Chassis power commanded OFF");
}
else if (strcmp(token, "status") == 0)
......@@ -3528,6 +3580,9 @@ int kestrel_init(void)
// Initialize mutexes
k_mutex_init(&vuart1_access_mutex);
k_mutex_init(&occ_access_mutex);
// Initialize semaphores
k_sem_init(&chassis_control_semaphore, 0, K_SEM_MAX_LIMIT);
#endif
for (int i = 0; i < MAX_CPUS_SUPPORTED; i++)
......@@ -3677,6 +3732,7 @@ int kestrel_init(void)
display_character('2', 0); // STATUS CODE: 2
kestrel_basic_init_complete = 1;
k_sem_give(&chassis_control_semaphore);
return 0;
}
......@@ -60,12 +60,14 @@ extern k_tid_t kestrel_service_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 struct k_sem chassis_control_semaphore;
extern const struct shell *host_console_service_task_shell;
#endif
int kestrel_init(void);
int power_on_host(void);
void power_off_chassis(void);
int power_on_chassis(int has_lock);
void power_off_chassis(int has_lock);
void print_chassis_status(void);
int write_flash_buffer_to_flash(void);
......
......@@ -435,7 +435,7 @@ int redfish_v1_system_reset_endpoint_handler(struct mg_connection *conn, void *c
else if (strcmp(cmd_params.reset_type, "ForceOff") == 0) {
if (host_power_status != HOST_POWER_STATUS_OFFLINE) {
load_stock_redfish_success_message(&redfish_message_response);
power_off_chassis();
power_off_chassis(0);
}
else {
load_stock_redfish_nooperation_message(&redfish_message_response);
......
......@@ -113,10 +113,15 @@ static int kestrel_shell_cmd_utility(const struct shell *shell, size_t argc, cha
return power_on_host();
}
else if (strcmp(argv[1], "chassison") == 0) {
VERIFY_KESTREL_START_COMPLETE(shell)
return power_on_chassis(0);
}
else if (strcmp(argv[1], "chassisoff") == 0) {
VERIFY_KESTREL_START_COMPLETE(shell)
power_off_chassis();
power_off_chassis(0);
return 0;
}
else {
......
......@@ -259,7 +259,7 @@ int power_control_handler(struct mg_connection *conn, void *cbdata)
}
else {
mg_printf(conn, "Powering off host");
power_off_chassis();
power_off_chassis(0);
}
}
else {
......
......@@ -126,7 +126,7 @@ void host_power_button_pressed(const struct device *dev, struct gpio_callback *c
power_on_host();
}
else if (want_power_off) {
power_off_chassis();
power_off_chassis(0);
}
}
......
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