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