From e81c07686cb8d6b8cade7cccdbb0740bd01c49ce Mon Sep 17 00:00:00 2001 From: mohmah01 Date: Fri, 30 Aug 2024 17:07:56 +0100 Subject: [PATCH 1/3] module/scmi : Add scmi notification handler API to requester. Add bind to notification handler API in the requester modules. Signed-off-by: mohmah01 --- module/scmi/src/mod_scmi.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/module/scmi/src/mod_scmi.c b/module/scmi/src/mod_scmi.c index 05aec0ee1..3aa5d0fe8 100644 --- a/module/scmi/src/mod_scmi.c +++ b/module/scmi/src/mod_scmi.c @@ -983,6 +983,9 @@ static int scmi_bind(fwk_id_t id, unsigned int round) scmi_ctx.scmi_protocol_requester_id_to_idx[scmi_protocol_id] = (uint8_t)(protocol_idx); protocol_req->message_handler = protocol_api->message_handler; +#ifdef BUILD_HAS_SCMI_NOTIFICATIONS + protocol_req->notification_handler = protocol_api->notification_handler; +#endif } #ifdef BUILD_HAS_MOD_RESOURCE_PERMS -- GitLab From 2adeb9ad38f7eff8bf06f82f6b7034566be01394 Mon Sep 17 00:00:00 2001 From: mohmah01 Date: Fri, 30 Aug 2024 17:09:28 +0100 Subject: [PATCH 2/3] module/scmi_system_power_req: Add Notification handling to system power requester Add notification subscriber function to requester module to allow agents subscribe to notifications Add notification handler function to handle the notification of system power change in agent: the function will send a framework notification which can be used by platform system module. --- .../include/internal/scmi_system_power_req.h | 49 +++++++ .../include/mod_scmi_system_power_req.h | 32 ++++- .../src/mod_scmi_system_power_req.c | 135 ++++++++++++++++-- 3 files changed, 204 insertions(+), 12 deletions(-) create mode 100644 module/scmi_system_power_req/include/internal/scmi_system_power_req.h diff --git a/module/scmi_system_power_req/include/internal/scmi_system_power_req.h b/module/scmi_system_power_req/include/internal/scmi_system_power_req.h new file mode 100644 index 000000000..60f3e5996 --- /dev/null +++ b/module/scmi_system_power_req/include/internal/scmi_system_power_req.h @@ -0,0 +1,49 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef INTERNAL_SCMI_SYS_POWER_REQ_H +#define INTERNAL_SCMI_SYS_POWER_REQ_H + +#include + +/*! + * \brief Flag mask for set state notification + */ +#define STATE_NOTIFY_FLAGS_MASK 0x1U + +/*! + * \brief Notification Payload + */ +struct scmi_sys_power_notification_payload { + /*! Agent ID receiving notification */ + uint32_t agent_id; + + /*! System Power command flags*/ + uint32_t flags; + + /*! System Power state being transitioned to */ + uint32_t system_state; +}; + +/*! + * \brief Notification Subscription Payload + */ +struct scmi_sys_power_req_state_notify_a2p { + /*! Notifications flags*/ + uint32_t flags; +}; + +/* + * Assert that the notification parameters size is more than the + * size of the state and flags + */ +static_assert( + (sizeof(((struct scmi_sys_power_notification_payload *)0)->flags) + + sizeof(((struct scmi_sys_power_notification_payload *)0)->system_state)) < + FWK_EVENT_PARAMETERS_SIZE); + +#endif /* INTERNAL_SCMI_SYS_POWER_REQ_H */ diff --git a/module/scmi_system_power_req/include/mod_scmi_system_power_req.h b/module/scmi_system_power_req/include/mod_scmi_system_power_req.h index 2122f711e..0007eb22e 100644 --- a/module/scmi_system_power_req/include/mod_scmi_system_power_req.h +++ b/module/scmi_system_power_req/include/mod_scmi_system_power_req.h @@ -1,6 +1,6 @@ /* * Arm SCP/MCP Software - * Copyright (c) 2022-2023, Arm Limited and Contributors. All rights reserved. + * Copyright (c) 2022-2024, Arm Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -8,10 +8,12 @@ #ifndef MOD_SCMI_SYSTEM_POWER_REQ_H #define MOD_SCMI_SYSTEM_POWER_REQ_H +#include #include #include #include +#include #include #include @@ -36,6 +38,18 @@ struct scmi_sys_power_req_state_set_a2p { uint32_t system_state; }; +/* Supported notifications */ +enum mod_system_power_req_notifications { + MOD_SYS_POWER_REQ_STATE_CHANGE_NOTIFICATION, + MOD_SYS_POWER_REQ_NOTIFICATION_COUNT, +}; + +/* System change notification */ +static const fwk_id_t mod_scmi_system_power_notification_system_power_change = + FWK_ID_NOTIFICATION_INIT( + FWK_MODULE_IDX_SCMI_SYSTEM_POWER_REQ, + MOD_SYS_POWER_REQ_STATE_CHANGE_NOTIFICATION); + /*! * \brief System Power Requester module restricted interface. * @@ -90,6 +104,22 @@ struct mod_system_power_requester_api { * */ int (*get_req_state)(fwk_id_t id, uint32_t *state); + +#ifdef BUILD_HAS_SCMI_NOTIFICATIONS + /*! + * \brief Subscribe to scmi notifications of system power state change + * Used for agents. + * \param id ID to determine which element to subscribe + * + * \retval ::FWK_SUCCESS The subscription message is sent successfully. + * + * \retval ::FWK_PENDING The power state transition request was submitted. + * + * \retval ::FWK_E_ACCESS Invalid access, the framework has rejected the + * call to the API. + */ + int (*notification_subscribe)(fwk_id_t id); +#endif }; /*! diff --git a/module/scmi_system_power_req/src/mod_scmi_system_power_req.c b/module/scmi_system_power_req/src/mod_scmi_system_power_req.c index d9870946f..94e38a435 100644 --- a/module/scmi_system_power_req/src/mod_scmi_system_power_req.c +++ b/module/scmi_system_power_req/src/mod_scmi_system_power_req.c @@ -1,9 +1,10 @@ /* * Arm SCP/MCP Software - * Copyright (c) 2022-2023, Arm Limited and Contributors. All rights reserved. + * Copyright (c) 2022-2024, Arm Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ +#include #include #include @@ -19,6 +20,7 @@ #include #include #include +#include #include #include @@ -70,6 +72,15 @@ static int scmi_system_power_req_message_handler( size_t payload_size, unsigned int message_id); +#ifdef BUILD_HAS_SCMI_NOTIFICATIONS +static int scmi_system_power_req_notification_handler( + fwk_id_t protocol_id, + fwk_id_t service_id, + const uint32_t *payload, + size_t payload_size, + unsigned int message_id); +#endif + /* * Internal variables. */ @@ -178,6 +189,9 @@ static struct mod_scmi_to_protocol_api scmi_system_power_req_scmi_to_protocol_api = { .get_scmi_protocol_id = scmi_system_power_req_get_scmi_protocol_id, .message_handler = scmi_system_power_req_message_handler, +#ifdef BUILD_HAS_SCMI_NOTIFICATIONS + .notification_handler = scmi_system_power_req_notification_handler, +#endif }; static bool try_get_element_idx_from_service( @@ -339,12 +353,115 @@ static int scmi_system_power_req_get_state(fwk_id_t id, uint32_t *state) return FWK_E_PARAM; } +#ifdef BUILD_HAS_SCMI_NOTIFICATIONS +/* Agent subscribe to SCMI system power notifications */ +static int scmi_system_power_req_notification_subscribe(fwk_id_t id) +{ + int status; + struct scmi_sys_power_req_state_notify_a2p payload; + uint8_t token; + bool request_ack_by_interrupt; + uint32_t element_id; + + if (!try_get_element_idx(id, &element_id)) { + return FWK_E_RANGE; + } + + struct scmi_system_power_req_dev_ctx *dev_ctx = + &(mod_ctx.dev_ctx_table[element_id]); + + /* No ack needed */ + request_ack_by_interrupt = false; + token = (uint8_t)0; + + payload.flags = STATE_NOTIFY_FLAGS_MASK; + + /* Send to platform to subscribe to system power change notification */ + status = mod_ctx.scmi_api->scmi_send_message( + MOD_SCMI_SYS_POWER_STATE_NOTIFY, + MOD_SCMI_PROTOCOL_ID_SYS_POWER, + token, + dev_ctx->config->service_id, + (const void *)&payload, + sizeof(payload), + request_ack_by_interrupt); + + return status; +} +#endif + static const struct mod_system_power_requester_api scmi_system_power_req_driver_api = { .set_req_state = scmi_system_power_req_set_state, .get_req_state = scmi_system_power_req_get_state, +#ifdef BUILD_HAS_SCMI_NOTIFICATIONS + .notification_subscribe = scmi_system_power_req_notification_subscribe, +#endif }; +/* + * SCMI notifications APIs + */ +#ifdef BUILD_HAS_SCMI_NOTIFICATIONS + +/* System power SCMI notification handler */ +static int scmi_system_power_req_notification_handler( + fwk_id_t protocol_id, + fwk_id_t service_id, + const uint32_t *payload, + size_t payload_size, + unsigned int message_id) +{ +# ifdef BUILD_HAS_NOTIFICATION + struct scmi_sys_power_notification_payload *parameters; + int status = FWK_SUCCESS; + + if (payload_size != sizeof(struct scmi_sys_power_notification_payload)) { + return FWK_E_PARAM; + } + + unsigned int count = 0; + + /* + * Framework notification is propagated when SCMI system power + * notification is received + */ + struct fwk_event notification_event = { + .id = mod_scmi_system_power_notification_system_power_change, + .response_requested = false, + .source_id = FWK_ID_MODULE_INIT(FWK_MODULE_IDX_SCMI_SYSTEM_POWER_REQ), + }; + + parameters = (struct scmi_sys_power_notification_payload *)payload; + + /* Add the system state to the notification parameter */ + fwk_str_memcpy( + notification_event.params, + ¶meters->system_state, + sizeof(parameters->system_state)); + + /* + * Send forceful or graceful to the notification params + */ + fwk_str_memcpy( + ¬ification_event.params[sizeof(parameters->system_state)], + ¶meters->flags, + sizeof(parameters->flags)); + + status = fwk_notification_notify(¬ification_event, &count); + + return status; + +# else + /* + * Framework notification is not supported + */ + return FWK_E_SUPPORT; + +# endif +} + +#endif /* * Framework handlers */ @@ -353,7 +470,6 @@ static int scmi_system_power_req_init( unsigned int element_count, const void *data) { - unsigned int i; /* We definitely need elements in this module. */ if (element_count == 0) { return FWK_E_SUPPORT; @@ -363,15 +479,6 @@ static int scmi_system_power_req_init( mod_ctx.dev_ctx_table = fwk_mm_calloc(element_count, sizeof(mod_ctx.dev_ctx_table[0])); - /* - * Configure each element's state at the startup with that set in the - * config file. - */ - for (i = 0; i < element_count; i++) { - mod_ctx.dev_ctx_table[i].state = - mod_ctx.dev_ctx_table[i].config->start_state; - } - return FWK_SUCCESS; } @@ -397,6 +504,12 @@ static int scmi_system_power_req_elem_init( dev_ctx->config = mod_sys_pow_req_config; + /* + * Configure each element's state at the startup with that set in the + * config file. + */ + dev_ctx->state = dev_ctx->config->start_state; + return FWK_SUCCESS; } -- GitLab From a6975472d080b574bfa7e03a3850874c11a6ae94 Mon Sep 17 00:00:00 2001 From: mohmah01 Date: Fri, 30 Aug 2024 17:10:00 +0100 Subject: [PATCH 3/3] module/scmi_system_power_req: SCMI Notification Unit test Add test cases for SCMI notification handler and notification subscribe APIs. Signed-off-by: mohmah01 --- .../scmi_system_power_req/test/CMakeLists.txt | 10 +- .../mod_scmi_system_power_req_unit_test.c | 135 +++++++++++++++++- 2 files changed, 142 insertions(+), 3 deletions(-) diff --git a/module/scmi_system_power_req/test/CMakeLists.txt b/module/scmi_system_power_req/test/CMakeLists.txt index 739ed7b5d..dc7d2b310 100644 --- a/module/scmi_system_power_req/test/CMakeLists.txt +++ b/module/scmi_system_power_req/test/CMakeLists.txt @@ -1,6 +1,6 @@ # # Arm SCP/MCP Software -# Copyright (c) 2022, Arm Limited and Contributors. All rights reserved. +# Copyright (c) 2024, Arm Limited and Contributors. All rights reserved. # # SPDX-License-Identifier: BSD-3-Clause # @@ -22,5 +22,13 @@ list(APPEND MOCK_REPLACEMENTS fwk_module) list(APPEND MOCK_REPLACEMENTS fwk_mm) list(APPEND MOCK_REPLACEMENTS fwk_id) list(APPEND MOCK_REPLACEMENTS fwk_core) +list(APPEND MOCK_REPLACEMENTS fwk_notification) +list(APPEND MOCK_REPLACEMENTS fwk_string) include(${SCP_ROOT}/unit_test/module_common.cmake) + +target_compile_definitions(${UNIT_TEST_TARGET} PUBLIC + "BUILD_HAS_SCMI_NOTIFICATIONS") + +target_compile_definitions(${UNIT_TEST_TARGET} PUBLIC + "BUILD_HAS_NOTIFICATION") diff --git a/module/scmi_system_power_req/test/mod_scmi_system_power_req_unit_test.c b/module/scmi_system_power_req/test/mod_scmi_system_power_req_unit_test.c index a9c252c72..aebcfa680 100644 --- a/module/scmi_system_power_req/test/mod_scmi_system_power_req_unit_test.c +++ b/module/scmi_system_power_req/test/mod_scmi_system_power_req_unit_test.c @@ -1,6 +1,6 @@ /* * Arm SCP/MCP Software - * Copyright (c) 2022-2023, Arm Limited and Contributors. All rights reserved. + * Copyright (c) 2022-2024, Arm Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -11,8 +11,9 @@ #include #include #include +#include +#include #include - #include #include @@ -22,6 +23,8 @@ #include UNIT_TEST_SRC +#define SCMI_SYS_POWER_STATE_SET_NOTIFY 0x000 + enum scp_sys_pow_nums { MOD_SCMI_SYS_POWER_REQ_IDX_0, MOD_SCMI_SYS_POWER_REQ_IDX_1, @@ -374,6 +377,54 @@ void test_function_scmi_system_power_req_set_state_no_response(void) TEST_ASSERT_EQUAL(status, FWK_SUCCESS); } +void test_function_scmi_system_power_req_notification_subscribe(void) +{ + int status; + fwk_id_t id; + uint8_t scmi_protocol_id = (uint8_t)MOD_SCMI_PROTOCOL_ID_SYS_POWER; + uint8_t scmi_message_id = (uint8_t)MOD_SCMI_SYS_POWER_STATE_NOTIFY; + + const struct scmi_sys_power_req_state_notify_a2p payload = { + .flags = STATE_NOTIFY_FLAGS_MASK, + }; + + fwk_id_get_element_idx_ExpectAnyArgsAndReturn(1); + fwk_id_is_type_ExpectAnyArgsAndReturn(true); + + scmi_send_message_ExpectWithArrayAndReturn( + scmi_message_id, + scmi_protocol_id, + 0, + dev_ctx[MOD_SCMI_SYS_POWER_REQ_IDX_1].config->service_id, + (const void *)&payload, + sizeof(payload), + sizeof(payload), + false, + FWK_SUCCESS); + + status = scmi_system_power_req_notification_subscribe(id); + TEST_ASSERT_EQUAL(status, FWK_SUCCESS); +} + +void test_function_scmi_system_power_req_notification_subscribe_err(void) +{ + int status; + fwk_id_t id; + + /* Element number >= element count */ + fwk_id_get_element_idx_ExpectAnyArgsAndReturn(2); + fwk_id_is_type_ExpectAnyArgsAndReturn(true); + + status = scmi_system_power_req_notification_subscribe(id); + TEST_ASSERT_EQUAL(status, FWK_E_RANGE); + + /* id is not element */ + fwk_id_is_type_ExpectAnyArgsAndReturn(false); + + status = scmi_system_power_req_notification_subscribe(id); + TEST_ASSERT_EQUAL(status, FWK_E_RANGE); +} + void test_scmi_system_power_req_state_set_handler(void) { int status; @@ -459,6 +510,82 @@ void test_scmi_system_power_req_message_handler(void) TEST_ASSERT_EQUAL(status, FWK_SUCCESS); } +void test_scmi_scmi_system_power_req_notification_handler(void) +{ + int status; + fwk_id_t service_id; + fwk_id_t protocol_id; + unsigned int message_id = SCMI_SYS_POWER_STATE_SET_NOTIFY; + unsigned int count = 0; + + const struct scmi_sys_power_notification_payload payload = { + .system_state = MOD_PD_STATE_OFF, + .flags = 1, + }; + + size_t payload_size = sizeof(payload); + + struct fwk_event notification_event = { + .id = mod_scmi_system_power_notification_system_power_change, + .response_requested = false, + .source_id = FWK_ID_MODULE_INIT(FWK_MODULE_IDX_SCMI_SYSTEM_POWER_REQ), + }; + + TEST_ASSERT_TRUE( + sizeof(notification_event.params) > + (sizeof(payload.system_state) + sizeof(payload.flags))); + + fwk_str_memcpy_ExpectWithArray( + notification_event.params, + sizeof(notification_event.params), + &payload.system_state, + sizeof(payload.system_state), + sizeof(payload.system_state)); + + fwk_str_memcpy_ExpectWithArray( + ¬ification_event.params[sizeof(payload.system_state)], + sizeof(notification_event.params[sizeof(payload.system_state)]), + &payload.flags, + sizeof(payload.flags), + sizeof(payload.flags)); + + fwk_notification_notify_ExpectWithArrayAndReturn( + ¬ification_event, 1, &count, 1, FWK_SUCCESS); + + status = scmi_system_power_req_notification_handler( + protocol_id, + service_id, + (const uint32_t *)&payload, + payload_size, + message_id); + + TEST_ASSERT_EQUAL(status, FWK_SUCCESS); +} + +void test_scmi_scmi_system_power_req_notification_handler_wrong_size(void) +{ + int status; + fwk_id_t service_id; + fwk_id_t protocol_id; + unsigned int message_id = SCMI_SYS_POWER_STATE_SET_NOTIFY; + + const struct scmi_sys_power_notification_payload payload = { + .system_state = MOD_PD_STATE_OFF, + .flags = 0, + }; + + size_t payload_size = sizeof(payload) + 1; + + status = scmi_system_power_req_notification_handler( + protocol_id, + service_id, + (const uint32_t *)&payload, + payload_size, + message_id); + + TEST_ASSERT_EQUAL(status, FWK_E_PARAM); +} + int scmi_test_main(void) { UNITY_BEGIN(); @@ -470,9 +597,13 @@ int scmi_test_main(void) RUN_TEST(test_function_scmi_system_power_req_get_state); RUN_TEST(test_function_scmi_system_power_req_set_state); RUN_TEST(test_function_scmi_system_power_req_set_state_no_response); + RUN_TEST(test_function_scmi_system_power_req_notification_subscribe); + RUN_TEST(test_function_scmi_system_power_req_notification_subscribe_err); RUN_TEST(test_scmi_system_power_req_state_set_handler); RUN_TEST(test_scmi_system_power_req_get_scmi_protocol_id); RUN_TEST(test_scmi_system_power_req_message_handler); + RUN_TEST(test_scmi_scmi_system_power_req_notification_handler); + RUN_TEST(test_scmi_scmi_system_power_req_notification_handler_wrong_size); return UNITY_END(); } -- GitLab