diff --git a/kestrel/src/kestrel.c b/kestrel/src/kestrel.c index a59a537045d436f9c37430b3b1dfe5884f7f60e5..76eb362d750f6f9b70567c6981b9a66e2727d0f0 100644 --- a/kestrel/src/kestrel.c +++ b/kestrel/src/kestrel.c @@ -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; } diff --git a/kestrel/src/kestrel.h b/kestrel/src/kestrel.h index 78d4f00cb7e8a3330bcf9f19ee6e0a1e0a03b5d6..bbc051793711ba5be8ca641b2ef80354885fe612 100644 --- a/kestrel/src/kestrel.h +++ b/kestrel/src/kestrel.h @@ -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); diff --git a/kestrel/src/redfish.c b/kestrel/src/redfish.c index 21e119c1882d530366a80f213a01eab591e56519..0f762f74b733c2af93f6bcbadb4ad0f82d5f72e8 100644 --- a/kestrel/src/redfish.c +++ b/kestrel/src/redfish.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) { 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); diff --git a/kestrel/src/shell.c b/kestrel/src/shell.c index 3c76dc0aea97e28928be2d4e237398388ed35d2e..4be71af284c6afe034f8f6c966cacce412e7b2e1 100644 --- a/kestrel/src/shell.c +++ b/kestrel/src/shell.c @@ -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 { diff --git a/kestrel/src/webportal.c b/kestrel/src/webportal.c index 315ac30401d3d35391a6a39854ad8b67d6708d81..274db4286c9852351e850e6c43f3aeaf73677c27 100644 --- a/kestrel/src/webportal.c +++ b/kestrel/src/webportal.c @@ -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 { diff --git a/kestrel/src/zephyr.c b/kestrel/src/zephyr.c index b8bdb9467a5330385b03e90a7396985b4ae9f538..4b6c70ade4b3d12b5be548f16265cb5c273d4d66 100644 --- a/kestrel/src/zephyr.c +++ b/kestrel/src/zephyr.c @@ -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); } } @@ -245,4 +245,4 @@ void main(void) configure_gpios(); LOG_INF("Kestrel system initialization complete\n"); -} \ No newline at end of file +}