diff --git a/Makefile.cmake b/Makefile.cmake index c9ab92967a435d905c7a1c775f1de85dad899b49..21a9d599e86b344a1169c608f7efe5fa789d9908 100644 --- a/Makefile.cmake +++ b/Makefile.cmake @@ -311,6 +311,6 @@ mod_test: $(CMAKE) -B $(MOD_TEST_BUILD_DIR) $(MOD_TEST_DIR) -G Ninja $(CMAKE) --build $(MOD_TEST_BUILD_DIR) ${CD} $(MOD_TEST_BUILD_DIR) && $(CTEST) -V --output-junit Testing/TestResults.xml - ${CD} $(MOD_TEST_BUILD_DIR) && $(LCOV) --capture --directory $(MOD_TEST_BUILD_DIR) --output-file scp_v2_unit_test_coverage.info - ${CD} $(MOD_TEST_BUILD_DIR) && $(PYTHON) ../../unit_test/utils/generate_coverage_report.py - ${CD} $(MOD_TEST_BUILD_DIR) && $(GENHTML) scp_v2_unit_test_coverage_filtered.info --prefix "$(TOP_DIR)" --output-directory $(BUILD_DIR)/coverage_report + #${CD} $(MOD_TEST_BUILD_DIR) && $(LCOV) --capture --directory $(MOD_TEST_BUILD_DIR) --output-file scp_v2_unit_test_coverage.info + #${CD} $(MOD_TEST_BUILD_DIR) && $(PYTHON) ../../unit_test/utils/generate_coverage_report.py + #${CD} $(MOD_TEST_BUILD_DIR) && $(GENHTML) scp_v2_unit_test_coverage_filtered.info --prefix "$(TOP_DIR)" --output-directory $(BUILD_DIR)/coverage_report diff --git a/framework/CMakeLists.txt b/framework/CMakeLists.txt index ad676e0cafb088c650e8169bc9d87233d803758d..77066c2a406715dfae8e4b8e58c612505095872f 100644 --- a/framework/CMakeLists.txt +++ b/framework/CMakeLists.txt @@ -99,6 +99,10 @@ if(SCP_ENABLE_SENSOR_SIGNED_VALUE) target_compile_definitions(framework PUBLIC "BUILD_HAS_SENSOR_SIGNED_VALUE") endif() +if(SCP_ENABLE_INBAND_MSG_SUPPORT) + target_compile_definitions(framework PUBLIC "BUILD_HAS_INBAND_MSG_SUPPORT") +endif() + # # Handle the framework logging filter level. # diff --git a/module/mhu2/CMakeLists.txt b/module/mhu2/CMakeLists.txt index fa13c96a777dcabc04a1b3a5195adc8dff8173e5..7d00933f361a47a544c8b78303126cc68334ca65 100644 --- a/module/mhu2/CMakeLists.txt +++ b/module/mhu2/CMakeLists.txt @@ -1,6 +1,6 @@ # # Arm SCP/MCP Software -# Copyright (c) 2021, Arm Limited and Contributors. All rights reserved. +# Copyright (c) 2021-2022, Arm Limited and Contributors. All rights reserved. # # SPDX-License-Identifier: BSD-3-Clause # @@ -16,3 +16,9 @@ target_sources(${SCP_MODULE_TARGET} PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/src/mod_mhu2.c") target_link_libraries(${SCP_MODULE_TARGET} PRIVATE module-smt) + +if("transport" IN_LIST SCP_MODULES) + target_link_libraries(${SCP_MODULE_TARGET} PRIVATE module-transport) +else() + target_link_libraries(${SCP_MODULE_TARGET} PRIVATE module-smt) +endif() diff --git a/module/mhu2/include/mod_mhu2.h b/module/mhu2/include/mod_mhu2.h index faf07736a60ef6191e2d16dfacb05dd03a3281aa..f1e0375afd943a8c968111797593fb78d7d82005 100644 --- a/module/mhu2/include/mod_mhu2.h +++ b/module/mhu2/include/mod_mhu2.h @@ -1,6 +1,6 @@ /* * Arm SCP/MCP Software - * Copyright (c) 2017-2021, Arm Limited and Contributors. All rights reserved. + * Copyright (c) 2017-2022, Arm Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause * @@ -29,8 +29,13 @@ * \brief MHU v2 api indicies */ enum mod_mhu2_api_idx { +#ifdef BUILD_HAS_MOD_TRANSPORT + /*! TRANSPORT driver API */ + MOD_MHU2_API_IDX_TRANSPORT_DRIVER, +#else /*! SMT driver API */ MOD_MHU2_API_IDX_SMT_DRIVER, +#endif /*! Number of APIs */ MOD_MHU2_API_IDX_COUNT, }; @@ -52,7 +57,7 @@ struct mod_mhu2_channel_config { /*! Base address of the registers of the outgoing MHU */ uintptr_t send; - /*! Channel number */ + /*! Channel number for the channel to be used as doorbell */ unsigned int channel; }; diff --git a/module/mhu2/src/mod_mhu2.c b/module/mhu2/src/mod_mhu2.c index 0090cc1e5de18155e64c1b56a8acbad3bf9a39fa..9d6da1856a1f3f0ef707738793c73e56cd4a7638 100644 --- a/module/mhu2/src/mod_mhu2.c +++ b/module/mhu2/src/mod_mhu2.c @@ -1,6 +1,6 @@ /* * Arm SCP/MCP Software - * Copyright (c) 2017-2021, Arm Limited and Contributors. All rights reserved. + * Copyright (c) 2017-2022, Arm Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause * @@ -11,11 +11,16 @@ #include #include -#include +#ifdef BUILD_HAS_MOD_TRANSPORT +# include +#else +# include +#endif #include #include #include +#include #include #include #include @@ -27,9 +32,31 @@ #define MHU_SLOT_COUNT_MAX 32 -struct mhu2_smt_channel { +#if defined(BUILD_HAS_MOD_TRANSPORT) && defined(BUILD_HAS_INBAND_MSG_SUPPORT) +/* MHUv2 channel status register size in bytes */ +# define MHU_CHANNEL_STATUS_REGISTER_WIDTH 4 + +/* + * For, transferring in-band messages, we require at least 9 MHUv2 channels + * excluding the payload. Out of 9 channels, one is used for doorbell and 8 + * channels are used for transferring the in-band message in the same layout + * as a shared memory which includes implementation defined reserved field, + * channel status, channel flags, length, etc. + * + */ +const uint8_t min_channels_required = 9; +#endif + +struct mhu2_bound_channel { fwk_id_t id; - const struct mod_smt_driver_input_api *api; + bool bound_to_smt_channel; + union api { +#ifdef BUILD_HAS_MOD_TRANSPORT + const struct mod_transport_driver_input_api *transport_api; +#else + const struct mod_smt_driver_input_api *smt_api; +#endif + } driver_input_api; }; /* MHU channel context */ @@ -50,8 +77,8 @@ struct mhu2_channel_ctx { /* Mask of slots that are bound to an SMT channel */ uint32_t bound_slots; - /* Table of SMT channels bound to the channel */ - struct mhu2_smt_channel *smt_channel_table; + /* Table of channels bound to the channel */ + struct mhu2_bound_channel *bound_channels_table; }; /* MHU v2 context */ @@ -66,23 +93,32 @@ static struct mhu2_ctx { static void mhu2_isr(uintptr_t ctx_param) { struct mhu2_channel_ctx *channel_ctx = (struct mhu2_channel_ctx *)ctx_param; + struct mhu2_bound_channel *bound_channel; unsigned int slot; - struct mhu2_smt_channel *smt_channel; fwk_assert(channel_ctx != NULL); while (channel_ctx->recv_channel->STAT != 0) { slot = __builtin_ctz(channel_ctx->recv_channel->STAT); - /* - * If the slot is bound to an SMT channel, signal the message to the - * SMT channel. + * If the slot is bound to an SMT or transport channel, + * signal the message to the corresponding module */ if (channel_ctx->bound_slots & (1 << slot)) { - smt_channel = &channel_ctx->smt_channel_table[slot]; - smt_channel->api->signal_message(smt_channel->id); + bound_channel = &channel_ctx->bound_channels_table[slot]; + + if (bound_channel->bound_to_smt_channel) { +#if !defined(BUILD_HAS_MOD_TRANSPORT) + bound_channel->driver_input_api.smt_api->signal_message( + bound_channel->id); +#endif + } else { +#ifdef BUILD_HAS_MOD_TRANSPORT + bound_channel->driver_input_api.transport_api->signal_message( + bound_channel->id); +#endif + } } - /* Acknowledge the interrupt */ channel_ctx->recv_channel->STAT_CLEAR = 1 << slot; } @@ -115,9 +151,163 @@ static int raise_interrupt(fwk_id_t slot_id) return FWK_SUCCESS; } +#if !defined(BUILD_HAS_MOD_TRANSPORT) static const struct mod_smt_driver_api mhu2_mod_smt_driver_api = { .raise_interrupt = raise_interrupt, }; +#endif + +#ifdef BUILD_HAS_MOD_TRANSPORT +# ifdef BUILD_HAS_INBAND_MSG_SUPPORT +/* + * transport module driver API + */ +static int mhu2_send_message( + struct mod_transport_buffer *message, + fwk_id_t slot_id) +{ + struct mhu2_channel_ctx *channel_ctx; + struct mhu2_send_reg *send; + uint8_t channel_count; + size_t payload_size; + uint8_t db_ch = 0, ch = 0; + uint8_t channels_used_for_payload = 0; + uint32_t *msg_ptr; + + channel_ctx = &ctx.channel_ctx_table[fwk_id_get_element_idx(slot_id)]; + + /* Get pointer to the MHUv2 send register */ + send = channel_ctx->send; + + /* Get pointer to the message to be sent */ + msg_ptr = (uint32_t *)message; + + /* Calculate the size of the payload */ + payload_size = message->length - sizeof(message->message_header); + + /* Calculate the number of channels required for payload */ + if (payload_size) { + channels_used_for_payload = + payload_size / MHU_CHANNEL_STATUS_REGISTER_WIDTH; + } + + /* Read the number of channels implemented */ + channel_count = send->MSG_NO_CAP; + + /* Check if minimum number of MHUv2 channels are available */ + if (channel_count < (min_channels_required + channels_used_for_payload)) { + FWK_LOG_INFO( + "[MHUv2] ERROR! Message length exceeds the number of MHUv2" + "channels available\n"); + return FWK_E_SUPPORT; + } + + /* Turn on receiver */ + send->ACCESS_REQUEST = 1; + while (send->ACCESS_READY != 1) + continue; + + /* Get the channel used for doorbell */ + db_ch = channel_ctx->config->channel; + + /* Copy the in-band message to the message status registers */ + for (uint8_t idx = 0; ch < (min_channels_required - 1); ch++) { + /* Skip the doorbell channel */ + if (ch == db_ch) + continue; + + send->channel[ch].STAT_SET = msg_ptr[idx]; + idx++; + } + + /* + * If we have payload to be sent, copy the payload to message status + * registers. + */ + if (payload_size != 0) { + for (uint8_t payload_idx = 0; + payload_idx < (payload_size / MHU_CHANNEL_STATUS_REGISTER_WIDTH); + payload_idx++) { + /* Skip the doorbell channel */ + if ((ch + payload_idx) == db_ch) + continue; + + send->channel[payload_idx + ch].STAT_SET = + message->payload[payload_idx]; + } + } + + /* Receiver no longer required */ + send->ACCESS_REQUEST = 0; + + return FWK_SUCCESS; +} + +static int mhu2_get_message( + struct mod_transport_buffer *message, + fwk_id_t slot_id) +{ + struct mhu2_channel_ctx *channel_ctx; + struct mhu2_recv_reg *recv; + size_t payload_size; + uint8_t db_ch = 0, ch = 0; + uint32_t *msg_ptr; + + channel_ctx = &ctx.channel_ctx_table[fwk_id_get_element_idx(slot_id)]; + + /* Get the channel used for doorbell */ + db_ch = channel_ctx->config->channel; + + /* Get a pointer to buffer */ + msg_ptr = (uint32_t *)message; + + /* Get a pointer to MHUv2 receive register */ + recv = (struct mhu2_recv_reg *)channel_ctx->config->recv; + + /* Copy the in-band message from message status registers */ + for (uint8_t idx = 0; ch < (min_channels_required - 1); ch++) { + /* Skip doorbell channel */ + if (ch == db_ch) + continue; + + msg_ptr[idx++] = recv->channel[ch].STAT; + + /* Clear the message status register */ + recv->channel[ch].STAT_CLEAR = 0xffffffff; + } + + /* Calculate size of the received payload */ + payload_size = message->length - sizeof(message->message_header); + + /* If payload is present, copy it from the message status registers */ + if (payload_size != 0) { + for (uint8_t payload_idx = 0; + payload_idx < (payload_size / MHU_CHANNEL_STATUS_REGISTER_WIDTH); + payload_idx++) { + /* Skip doorbell channel */ + if ((ch + payload_idx) == db_ch) + continue; + + message->payload[payload_idx] = + recv->channel[payload_idx + ch].STAT; + + /* Clear the message status register */ + recv->channel[payload_idx + ch].STAT_CLEAR = 0xffffffff; + } + } + + return FWK_SUCCESS; +} +# endif + +struct mod_transport_driver_api mhu2_mod_transport_driver_api = { +# ifdef BUILD_HAS_INBAND_MSG_SUPPORT + .send_message = mhu2_send_message, + .get_message = mhu2_get_message, +# endif + .trigger_event = raise_interrupt, +}; +#endif /* * Framework handlers @@ -166,10 +356,30 @@ static int mhu2_channel_init(fwk_id_t channel_id, channel_ctx->slot_count = slot_count; channel_ctx->send_channel = &channel_ctx->send->channel[config->channel]; recv_reg = (struct mhu2_recv_reg *)config->recv; + +#if defined(BUILD_HAS_MOD_TRANSPORT) && defined(BUILD_HAS_INBAND_MSG_SUPPORT) + /* + * Mask the channels used for transferring in-band messages. + * Only the doorbell channel should be used to raise interrupt. + */ + for (uint8_t ch = 0; ch < recv_reg->MSG_NO_CAP; ch++) { + /* Skip the channel used for doorbell */ + if (ch == config->channel) + continue; + + /* + * Set channel mask. + * + * Masked channels don't generate interrupt when data is written + * to them. + */ + recv_reg->channel[ch].MASK_SET = 0xffffffff; + } +#endif channel_ctx->recv_channel = &recv_reg->channel[config->channel]; - channel_ctx->smt_channel_table = - fwk_mm_calloc(slot_count, sizeof(channel_ctx->smt_channel_table[0])); + channel_ctx->bound_channels_table = + fwk_mm_calloc(slot_count, sizeof(channel_ctx->bound_channels_table[0])); return FWK_SUCCESS; } @@ -179,25 +389,46 @@ static int mhu2_bind(fwk_id_t id, unsigned int round) int status; struct mhu2_channel_ctx *channel_ctx; unsigned int slot; - struct mhu2_smt_channel *smt_channel; if ((round == 1) && fwk_id_is_type(id, FWK_ID_TYPE_ELEMENT)) { channel_ctx = &ctx.channel_ctx_table[fwk_id_get_element_idx(id)]; for (slot = 0; slot < MHU_SLOT_COUNT_MAX; slot++) { + struct mhu2_bound_channel *bound_channel; if (!(channel_ctx->bound_slots & (UINT32_C(1) << slot))) continue; - smt_channel = &channel_ctx->smt_channel_table[slot]; - - status = fwk_module_bind(smt_channel->id, - FWK_ID_API(FWK_MODULE_IDX_SMT, - MOD_SMT_API_IDX_DRIVER_INPUT), - &smt_channel->api); - if (status != FWK_SUCCESS) { - /* Unable to bind back to SMT channel */ - fwk_unexpected(); - return status; + bound_channel = &channel_ctx->bound_channels_table[slot]; + + if (bound_channel->bound_to_smt_channel) { +#if !defined(BUILD_HAS_MOD_TRANSPORT) + status = fwk_module_bind( + bound_channel->id, + FWK_ID_API( + FWK_MODULE_IDX_SMT, MOD_SMT_API_IDX_DRIVER_INPUT), + &bound_channel->driver_input_api.smt_api); + + if (status != FWK_SUCCESS) { + /* Unable to bind back to SMT channel */ + fwk_unexpected(); + return status; + } +#endif + } else { +#ifdef BUILD_HAS_MOD_TRANSPORT + status = fwk_module_bind( + bound_channel->id, + FWK_ID_API( + FWK_MODULE_IDX_TRANSPORT, + MOD_TRANSPORT_API_IDX_DRIVER_INPUT), + &bound_channel->driver_input_api.transport_api); + + if (status != FWK_SUCCESS) { + /* Unable to bind back to TRANSPORT channel */ + fwk_unexpected(); + return status; + } +#endif } } } @@ -212,6 +443,8 @@ static int mhu2_process_bind_request(fwk_id_t source_id, { struct mhu2_channel_ctx *channel_ctx; unsigned int slot; + enum mod_mhu2_api_idx api_id_type; + api_id_type = (enum mod_mhu2_api_idx)fwk_id_get_api_idx(api_id); if (!fwk_id_is_type(target_id, FWK_ID_TYPE_SUB_ELEMENT)) { /* @@ -224,17 +457,36 @@ static int mhu2_process_bind_request(fwk_id_t source_id, channel_ctx = &ctx.channel_ctx_table[fwk_id_get_element_idx(target_id)]; slot = fwk_id_get_sub_element_idx(target_id); - if (channel_ctx->bound_slots & (1 << slot)) { /* Something tried to bind to a slot that has already been bound to */ fwk_unexpected(); return FWK_E_ACCESS; } - channel_ctx->smt_channel_table[slot].id = source_id; channel_ctx->bound_slots |= 1 << slot; - *api = &mhu2_mod_smt_driver_api; + switch (api_id_type) { +#if !defined(BUILD_HAS_MOD_TRANSPORT) + case MOD_MHU2_API_IDX_SMT_DRIVER: + channel_ctx->bound_channels_table[slot].id = source_id; + channel_ctx->bound_channels_table[slot].bound_to_smt_channel = true; + *api = &mhu2_mod_smt_driver_api; + break; +#endif + +#ifdef BUILD_HAS_MOD_TRANSPORT + case MOD_MHU2_API_IDX_TRANSPORT_DRIVER: + channel_ctx->bound_channels_table[slot].id = source_id; + channel_ctx->bound_channels_table[slot].bound_to_smt_channel = false; + *api = &mhu2_mod_transport_driver_api; + break; +#endif + + default: + /* Invalid config */ + fwk_unexpected(); + return FWK_E_PARAM; + } return FWK_SUCCESS; } diff --git a/module/scmi/include/mod_scmi.h b/module/scmi/include/mod_scmi.h index aacf16d36911846d6eeb333df32db9b8e781c7af..418dc03a44f934c959c05b311a74373caa69fd40 100644 --- a/module/scmi/include/mod_scmi.h +++ b/module/scmi/include/mod_scmi.h @@ -583,8 +583,13 @@ struct mod_scmi_from_protocol_api { * \param payload Payload data to write, or NULL if a payload has already * been written. * \param size Size of the payload. + * + * \retval ::FWK_SUCCESS The operation succeeded. + * \retval ::FWK_E_SUPPORT Transport-specific message not supported. + * \return One of the standard error codes for implementation-defined + * errors. */ - void (*respond)(fwk_id_t service_id, const void *payload, size_t size); + int (*respond)(fwk_id_t service_id, const void *payload, size_t size); /*! * \brief Send a notification to the agent on behalf on an SCMI service. diff --git a/module/scmi/src/mod_scmi.c b/module/scmi/src/mod_scmi.c index 956babbf8031898bfe62bf2675f925e5695ec37a..d6a84f1e974689d26fe38d12e3fb5f76e8586848 100644 --- a/module/scmi/src/mod_scmi.c +++ b/module/scmi/src/mod_scmi.c @@ -254,7 +254,7 @@ static int write_payload(fwk_id_t service_id, size_t offset, offset, payload, size); } -static void respond(fwk_id_t service_id, const void *payload, size_t size) +static int respond(fwk_id_t service_id, const void *payload, size_t size) { int status; const struct scmi_service_ctx *ctx; @@ -314,6 +314,7 @@ static void respond(fwk_id_t service_id, const void *payload, size_t size) fwk_status_str(status)); #endif } + return status; } static void scmi_notify(fwk_id_t id, int protocol_id, int message_id, diff --git a/module/scmi/src/mod_scmi_base.c b/module/scmi/src/mod_scmi_base.c index a348bf26d9afa7483ce4f8a7057b070f77b21d0e..8d7f6031e85382973bb13432bbf090b189363dd3 100644 --- a/module/scmi/src/mod_scmi_base.c +++ b/module/scmi/src/mod_scmi_base.c @@ -15,6 +15,7 @@ #include #include +#include #include #include #include @@ -129,9 +130,8 @@ static int scmi_base_protocol_version_handler( .version = SCMI_PROTOCOL_VERSION_BASE, }; - protocol_api->respond(service_id, &return_values, sizeof(return_values)); - - return FWK_SUCCESS; + return protocol_api->respond( + service_id, &return_values, sizeof(return_values)); } /* @@ -211,9 +211,8 @@ static int scmi_base_protocol_attributes_handler( return_values.attributes = (uint32_t)SCMI_BASE_PROTOCOL_ATTRIBUTES( protocol_count, shared_scmi_ctx->config->agent_count); - protocol_api->respond(service_id, &return_values, sizeof(return_values)); - - return FWK_SUCCESS; + return protocol_api->respond( + service_id, &return_values, sizeof(return_values)); } /* @@ -241,13 +240,11 @@ static int scmi_base_protocol_message_attributes_handler( * has already been set by the initialization of "return_values". */ - protocol_api->respond( + return protocol_api->respond( service_id, &return_values, (return_values.status == SCMI_SUCCESS) ? sizeof(return_values) : sizeof(return_values.status)); - - return FWK_SUCCESS; } /* @@ -268,9 +265,8 @@ static int scmi_base_discover_vendor_handler( sizeof(return_values.vendor_identifier) - 1); } - protocol_api->respond(service_id, &return_values, sizeof(return_values)); - - return FWK_SUCCESS; + return protocol_api->respond( + service_id, &return_values, sizeof(return_values)); } /* @@ -291,9 +287,8 @@ static int scmi_base_discover_sub_vendor_handler( sizeof(return_values.sub_vendor_identifier) - 1); } - protocol_api->respond(service_id, &return_values, sizeof(return_values)); - - return FWK_SUCCESS; + return protocol_api->respond( + service_id, &return_values, sizeof(return_values)); } /* @@ -307,9 +302,8 @@ static int scmi_base_discover_implementation_version_handler( .status = (int32_t)SCMI_SUCCESS, .version = FWK_BUILD_VERSION }; - protocol_api->respond(service_id, &return_values, sizeof(return_values)); - - return FWK_SUCCESS; + return protocol_api->respond( + service_id, &return_values, sizeof(return_values)); } /* @@ -319,7 +313,7 @@ static int scmi_base_discover_list_protocols_handler( fwk_id_t service_id, const uint32_t *payload) { - int status; + int status, respond_status; const struct scmi_base_discover_list_protocols_a2p *parameters; struct scmi_base_discover_list_protocols_p2a return_values = { .status = (int32_t)SCMI_GENERIC_ERROR, @@ -492,16 +486,17 @@ static int scmi_base_discover_list_protocols_handler( payload_size = FWK_ALIGN_NEXT(payload_size, sizeof(uint32_t)); - protocol_api->respond(service_id, NULL, payload_size); - - return status; + return protocol_api->respond(service_id, NULL, payload_size); error: - protocol_api->respond( + respond_status = protocol_api->respond( service_id, &return_values, (return_values.status == SCMI_SUCCESS) ? sizeof(return_values) : sizeof(return_values.status)); + if (respond_status != FWK_SUCCESS) { + FWK_LOG_TRACE("[SCMI_BASE] %s @%d", __func__, __LINE__); + } return status; } @@ -595,13 +590,11 @@ static int scmi_base_discover_agent_handler( sizeof(return_values.name) - 1); exit: - protocol_api->respond( + return protocol_api->respond( service_id, &return_values, (return_values.status == SCMI_SUCCESS) ? sizeof(return_values) : sizeof(return_values.status)); - - return FWK_SUCCESS; } #ifdef BUILD_HAS_MOD_RESOURCE_PERMS @@ -618,6 +611,7 @@ static int scmi_base_set_device_permissions( .status = (int32_t)SCMI_NOT_FOUND, }; int status = FWK_SUCCESS; + int respond_status; parameters = (const struct scmi_base_set_device_permissions_a2p *)payload; @@ -656,12 +650,16 @@ static int scmi_base_set_device_permissions( } exit: - protocol_api->respond( + respond_status = protocol_api->respond( service_id, &return_values, (return_values.status == SCMI_SUCCESS) ? sizeof(return_values) : sizeof(return_values.status)); + if (respond_status != FWK_SUCCESS) { + FWK_LOG_TRACE("[SCMI_BASE] %s @%d", __func__, __LINE__); + } + return status; } @@ -677,6 +675,7 @@ static int scmi_base_set_protocol_permissions( .status = (int32_t)SCMI_NOT_FOUND, }; int status = FWK_SUCCESS; + int respond_status; parameters = (const struct scmi_base_set_protocol_permissions_a2p *)payload; @@ -724,12 +723,16 @@ static int scmi_base_set_protocol_permissions( } exit: - protocol_api->respond( + respond_status = protocol_api->respond( service_id, &return_values, (return_values.status == SCMI_SUCCESS) ? sizeof(return_values) : sizeof(return_values.status)); + if (respond_status != FWK_SUCCESS) { + FWK_LOG_TRACE("[SCMI_BASE] %s @%d", __func__, __LINE__); + } + return status; } @@ -781,13 +784,11 @@ static int scmi_base_reset_agent_config( } exit: - protocol_api->respond( + return protocol_api->respond( service_id, &return_values, (return_values.status == SCMI_SUCCESS) ? sizeof(return_values) : sizeof(return_values.status)); - - return FWK_SUCCESS; } /* @@ -863,9 +864,8 @@ int scmi_base_message_handler( return base_handler_table[message_id](service_id, payload); error: - protocol_api->respond(service_id, &return_value, sizeof(return_value)); - - return FWK_SUCCESS; + return protocol_api->respond( + service_id, &return_value, sizeof(return_value)); } void scmi_base_set_api(const struct mod_scmi_from_protocol_api *api) diff --git a/module/scmi/test/mocks/Mockmod_scmi_extra.c b/module/scmi/test/mocks/Mockmod_scmi_extra.c index 71dd7b653d170737748051c0ce7e565f88f645c4..f0c8aee3bdd16fc1a86d8f6a688d8404f59ff09f 100644 --- a/module/scmi/test/mocks/Mockmod_scmi_extra.c +++ b/module/scmi/test/mocks/Mockmod_scmi_extra.c @@ -208,6 +208,7 @@ typedef struct _CMOCK_mod_scmi_from_protocol_respond_CALL_INSTANCE { UNITY_LINE_TYPE LineNumber; char ExpectAnyArgsBool; + int ReturnVal; fwk_id_t Expected_service_id; const void* Expected_payload; size_t Expected_size; @@ -1788,7 +1789,7 @@ void mod_scmi_from_protocol_write_payload_Stub(CMOCK_mod_scmi_from_protocol_writ Mock.mod_scmi_from_protocol_write_payload_CallbackFunctionPointer = Callback; } -void mod_scmi_from_protocol_respond(fwk_id_t service_id, const void* payload, size_t size) +int mod_scmi_from_protocol_respond(fwk_id_t service_id, const void* payload, size_t size) { UNITY_LINE_TYPE cmock_line = TEST_LINE_NUM; CMOCK_mod_scmi_from_protocol_respond_CALL_INSTANCE* cmock_call_instance; @@ -1798,9 +1799,9 @@ void mod_scmi_from_protocol_respond(fwk_id_t service_id, const void* payload, si if (!Mock.mod_scmi_from_protocol_respond_CallbackBool && Mock.mod_scmi_from_protocol_respond_CallbackFunctionPointer != NULL) { - Mock.mod_scmi_from_protocol_respond_CallbackFunctionPointer(service_id, payload, size, Mock.mod_scmi_from_protocol_respond_CallbackCalls++); + int cmock_cb_ret = Mock.mod_scmi_from_protocol_respond_CallbackFunctionPointer(service_id, payload, size, Mock.mod_scmi_from_protocol_respond_CallbackCalls++); UNITY_CLR_DETAILS(); - return; + return cmock_cb_ret; } UNITY_TEST_ASSERT_NOT_NULL(cmock_call_instance, cmock_line, CMockStringCalledMore); cmock_line = cmock_call_instance->LineNumber; @@ -1824,9 +1825,10 @@ void mod_scmi_from_protocol_respond(fwk_id_t service_id, const void* payload, si } if (Mock.mod_scmi_from_protocol_respond_CallbackFunctionPointer != NULL) { - Mock.mod_scmi_from_protocol_respond_CallbackFunctionPointer(service_id, payload, size, Mock.mod_scmi_from_protocol_respond_CallbackCalls++); + cmock_call_instance->ReturnVal = Mock.mod_scmi_from_protocol_respond_CallbackFunctionPointer(service_id, payload, size, Mock.mod_scmi_from_protocol_respond_CallbackCalls++); } UNITY_CLR_DETAILS(); + return cmock_call_instance->ReturnVal; } void CMockExpectParameters_mod_scmi_from_protocol_respond(CMOCK_mod_scmi_from_protocol_respond_CALL_INSTANCE* cmock_call_instance, fwk_id_t service_id, const void* payload, size_t size); @@ -1839,7 +1841,7 @@ void CMockExpectParameters_mod_scmi_from_protocol_respond(CMOCK_mod_scmi_from_pr sizeof(size_t[sizeof(size) == sizeof(size_t) ? 1 : -1])); /* add size_t to :treat_as_array if this causes an error */ } -void mod_scmi_from_protocol_respond_CMockExpectAnyArgs(UNITY_LINE_TYPE cmock_line) +void mod_scmi_from_protocol_respond_CMockExpectAnyArgsAndReturn(UNITY_LINE_TYPE cmock_line, int cmock_to_return) { CMOCK_MEM_INDEX_TYPE cmock_guts_index = CMock_Guts_MemNew(sizeof(CMOCK_mod_scmi_from_protocol_respond_CALL_INSTANCE)); CMOCK_mod_scmi_from_protocol_respond_CALL_INSTANCE* cmock_call_instance = (CMOCK_mod_scmi_from_protocol_respond_CALL_INSTANCE*)CMock_Guts_GetAddressFor(cmock_guts_index); @@ -1848,10 +1850,11 @@ void mod_scmi_from_protocol_respond_CMockExpectAnyArgs(UNITY_LINE_TYPE cmock_lin Mock.mod_scmi_from_protocol_respond_CallInstance = CMock_Guts_MemChain(Mock.mod_scmi_from_protocol_respond_CallInstance, cmock_guts_index); cmock_call_instance->LineNumber = cmock_line; cmock_call_instance->ExpectAnyArgsBool = (char)0; + cmock_call_instance->ReturnVal = cmock_to_return; cmock_call_instance->ExpectAnyArgsBool = (char)1; } -void mod_scmi_from_protocol_respond_CMockExpect(UNITY_LINE_TYPE cmock_line, fwk_id_t service_id, const void* payload, size_t size) +void mod_scmi_from_protocol_respond_CMockExpectAndReturn(UNITY_LINE_TYPE cmock_line, fwk_id_t service_id, const void* payload, size_t size, int cmock_to_return) { CMOCK_MEM_INDEX_TYPE cmock_guts_index = CMock_Guts_MemNew(sizeof(CMOCK_mod_scmi_from_protocol_respond_CALL_INSTANCE)); CMOCK_mod_scmi_from_protocol_respond_CALL_INSTANCE* cmock_call_instance = (CMOCK_mod_scmi_from_protocol_respond_CALL_INSTANCE*)CMock_Guts_GetAddressFor(cmock_guts_index); @@ -1861,6 +1864,7 @@ void mod_scmi_from_protocol_respond_CMockExpect(UNITY_LINE_TYPE cmock_line, fwk_ cmock_call_instance->LineNumber = cmock_line; cmock_call_instance->ExpectAnyArgsBool = (char)0; CMockExpectParameters_mod_scmi_from_protocol_respond(cmock_call_instance, service_id, payload, size); + cmock_call_instance->ReturnVal = cmock_to_return; } void mod_scmi_from_protocol_respond_AddCallback(CMOCK_mod_scmi_from_protocol_respond_CALLBACK Callback) diff --git a/module/scmi/test/mocks/Mockmod_scmi_extra.h b/module/scmi/test/mocks/Mockmod_scmi_extra.h index 829ee5b848d785ffb0e41233d4b7dfa6b68ac9bf..7ef5d449cfd7e43fe68c1770ec746fde4f30da48 100644 --- a/module/scmi/test/mocks/Mockmod_scmi_extra.h +++ b/module/scmi/test/mocks/Mockmod_scmi_extra.h @@ -164,11 +164,11 @@ typedef int (* CMOCK_mod_scmi_from_protocol_write_payload_CALLBACK)(fwk_id_t ser void mod_scmi_from_protocol_write_payload_AddCallback(CMOCK_mod_scmi_from_protocol_write_payload_CALLBACK Callback); void mod_scmi_from_protocol_write_payload_Stub(CMOCK_mod_scmi_from_protocol_write_payload_CALLBACK Callback); #define mod_scmi_from_protocol_write_payload_StubWithCallback mod_scmi_from_protocol_write_payload_Stub -#define mod_scmi_from_protocol_respond_ExpectAnyArgs() mod_scmi_from_protocol_respond_CMockExpectAnyArgs(__LINE__) -void mod_scmi_from_protocol_respond_CMockExpectAnyArgs(UNITY_LINE_TYPE cmock_line); -#define mod_scmi_from_protocol_respond_Expect(service_id, payload, size) mod_scmi_from_protocol_respond_CMockExpect(__LINE__, service_id, payload, size) -void mod_scmi_from_protocol_respond_CMockExpect(UNITY_LINE_TYPE cmock_line, fwk_id_t service_id, const void* payload, size_t size); -typedef void (* CMOCK_mod_scmi_from_protocol_respond_CALLBACK)(fwk_id_t service_id, const void* payload, size_t size, int cmock_num_calls); +#define mod_scmi_from_protocol_respond_ExpectAnyArgsAndReturn(cmock_retval) mod_scmi_from_protocol_respond_CMockExpectAnyArgsAndReturn(__LINE__, cmock_retval) +void mod_scmi_from_protocol_respond_CMockExpectAnyArgsAndReturn(UNITY_LINE_TYPE cmock_line, int cmock_to_return); +#define mod_scmi_from_protocol_respond_ExpectAndReturn(service_id, payload, size, cmock_retval) mod_scmi_from_protocol_respond_CMockExpectAndReturn(__LINE__, service_id, payload, size, cmock_retval) +void mod_scmi_from_protocol_respond_CMockExpectAndReturn(UNITY_LINE_TYPE cmock_line, fwk_id_t service_id, const void* payload, size_t size, int cmock_to_return); +typedef int (* CMOCK_mod_scmi_from_protocol_respond_CALLBACK)(fwk_id_t service_id, const void* payload, size_t size, int cmock_num_calls); void mod_scmi_from_protocol_respond_AddCallback(CMOCK_mod_scmi_from_protocol_respond_CALLBACK Callback); void mod_scmi_from_protocol_respond_Stub(CMOCK_mod_scmi_from_protocol_respond_CALLBACK Callback); #define mod_scmi_from_protocol_respond_StubWithCallback mod_scmi_from_protocol_respond_Stub diff --git a/module/scmi/test/mod_scmi_extra.h b/module/scmi/test/mod_scmi_extra.h index fbf1d48402c5efd01c7e42f26ab9736d6853e568..4d4ff69fdc7c18318616201af76977f0dd315e50 100644 --- a/module/scmi/test/mod_scmi_extra.h +++ b/module/scmi/test/mod_scmi_extra.h @@ -268,7 +268,7 @@ int mod_scmi_from_protocol_write_payload( * been written. * \param size Size of the payload. */ -void mod_scmi_from_protocol_respond( +int mod_scmi_from_protocol_respond( fwk_id_t service_id, const void *payload, size_t size); diff --git a/module/scmi/test/mod_scmi_unit_test.c b/module/scmi/test/mod_scmi_unit_test.c index 879e840413bd3db0f68b100e98abae76d67f9a7b..a8e2c8629c3bad6ddcdbc2484294ac200aa630b9 100644 --- a/module/scmi/test/mod_scmi_unit_test.c +++ b/module/scmi/test/mod_scmi_unit_test.c @@ -211,7 +211,7 @@ void test_function_scmi_base_discover_sub_vendor_handler(void) fwk_module_get_element_name_ExpectAndReturn(service_id, "OSPM"); #endif - mod_scmi_from_protocol_respond_ExpectAnyArgs(); + mod_scmi_from_protocol_respond_ExpectAnyArgsAndReturn(FWK_SUCCESS); TEST_ASSERT_EQUAL( FWK_SUCCESS, scmi_base_discover_sub_vendor_handler(service_id, NULL)); diff --git a/module/scmi_apcore/src/mod_scmi_apcore.c b/module/scmi_apcore/src/mod_scmi_apcore.c index 96a2f5f280912acc14c3dc2783b472e3afbc6e95..1b7771bb9b46a4ea343645f87ff922c9e0d0f629 100644 --- a/module/scmi_apcore/src/mod_scmi_apcore.c +++ b/module/scmi_apcore/src/mod_scmi_apcore.c @@ -15,6 +15,7 @@ #include #include +#include #include #include #include @@ -127,9 +128,8 @@ static int scmi_apcore_protocol_version_handler(fwk_id_t service_id, .version = MOD_SCMI_PROTOCOL_VERSION_APCORE, }; - scmi_apcore_ctx.scmi_api->respond( + return scmi_apcore_ctx.scmi_api->respond( service_id, &return_values, sizeof(return_values)); - return FWK_SUCCESS; } /* @@ -149,12 +149,8 @@ static int scmi_apcore_protocol_attributes_handler(fwk_id_t service_id, MOD_SCMI_APCORE_PROTOCOL_ATTRIBUTES_64BIT_MASK; } - scmi_apcore_ctx.scmi_api->respond( - service_id, - &return_values, - sizeof(return_values)); - - return FWK_SUCCESS; + return scmi_apcore_ctx.scmi_api->respond( + service_id, &return_values, sizeof(return_values)); } /* @@ -183,10 +179,8 @@ static int scmi_apcore_protocol_message_attributes_handler(fwk_id_t service_id, response_size = (return_values.status == SCMI_SUCCESS) ? sizeof(return_values) : sizeof(return_values.status); - scmi_apcore_ctx.scmi_api->respond( + return scmi_apcore_ctx.scmi_api->respond( service_id, &return_values, response_size); - - return FWK_SUCCESS; } /* @@ -258,9 +252,8 @@ static int scmi_apcore_reset_address_set_handler(fwk_id_t service_id, } exit: - scmi_apcore_ctx.scmi_api->respond( + return scmi_apcore_ctx.scmi_api->respond( service_id, &return_values, sizeof(return_values)); - return status; } /* @@ -269,7 +262,7 @@ exit: static int scmi_apcore_reset_address_get_handler(fwk_id_t service_id, const uint32_t *payload) { - int status; + int status, respond_status; unsigned int agent_id; const struct mod_scmi_apcore_reset_register_group *reg_group; uint64_t reset_address; @@ -314,8 +307,13 @@ static int scmi_apcore_reset_address_get_handler(fwk_id_t service_id, return_values.status = (int32_t)SCMI_SUCCESS; exit: - scmi_apcore_ctx.scmi_api->respond( + respond_status = scmi_apcore_ctx.scmi_api->respond( service_id, &return_values, sizeof(return_values)); + + if (respond_status != FWK_SUCCESS) { + FWK_LOG_TRACE("[SCMI-APCORE] %s @%d", __func__, __LINE__); + } + return status; } @@ -357,12 +355,8 @@ static int scmi_apcore_message_handler( return handler_table[message_id](service_id, payload); error: - scmi_apcore_ctx.scmi_api->respond( - service_id, - &return_value, - sizeof(return_value)); - - return FWK_SUCCESS; + return scmi_apcore_ctx.scmi_api->respond( + service_id, &return_value, sizeof(return_value)); } static struct mod_scmi_to_protocol_api scmi_apcore_mod_scmi_to_protocol_api = { diff --git a/module/scmi_clock/src/mod_scmi_clock.c b/module/scmi_clock/src/mod_scmi_clock.c index bc558c2cc3ab1a8b70e5a4d5ebbcafad495a5659..a3ec6bceb84271813573cc46576874a51191469d 100644 --- a/module/scmi_clock/src/mod_scmi_clock.c +++ b/module/scmi_clock/src/mod_scmi_clock.c @@ -359,6 +359,7 @@ static void get_state_respond(fwk_id_t clock_dev_id, enum mod_clock_state *clock_state, int status) { + int respond_status; size_t response_size; struct scmi_clock_attributes_p2a return_values = { 0 }; @@ -379,9 +380,11 @@ static void get_state_respond(fwk_id_t clock_dev_id, response_size = sizeof(return_values.status); } - scmi_clock_ctx.scmi_api->respond(service_id, - &return_values, - response_size); + respond_status = scmi_clock_ctx.scmi_api->respond( + service_id, &return_values, response_size); + if (respond_status != FWK_SUCCESS) { + FWK_LOG_TRACE("[SCMI-CLK] %s @%d", __func__, __LINE__); + } } /* @@ -391,6 +394,7 @@ static void get_rate_respond(fwk_id_t service_id, uint64_t *rate, int status) { + int respond_status; size_t response_size; struct scmi_clock_rate_get_p2a return_values = { 0 }; @@ -406,14 +410,17 @@ static void get_rate_respond(fwk_id_t service_id, response_size = sizeof(return_values.status); } - scmi_clock_ctx.scmi_api->respond(service_id, - &return_values, - response_size); + respond_status = scmi_clock_ctx.scmi_api->respond( + service_id, &return_values, response_size); + if (respond_status != FWK_SUCCESS) { + FWK_LOG_TRACE("[SCMI-CLK] %s @%d", __func__, __LINE__); + } } static void request_response(int response_status, fwk_id_t service_id) { + int respond_status; struct scmi_clock_generic_p2a return_values = { .status = (int32_t)SCMI_GENERIC_ERROR }; @@ -426,9 +433,11 @@ static void request_response(int response_status, return_values.status = (int32_t)SCMI_INVALID_PARAMETERS; } - scmi_clock_ctx.scmi_api->respond(service_id, - &return_values, - sizeof(return_values.status)); + respond_status = scmi_clock_ctx.scmi_api->respond( + service_id, &return_values, sizeof(return_values.status)); + if (respond_status != FWK_SUCCESS) { + FWK_LOG_TRACE("[SCMI-CLK] %s @%d", __func__, __LINE__); + } } /* @@ -436,6 +445,7 @@ static void request_response(int response_status, */ static void set_request_respond(fwk_id_t service_id, int status) { + int respond_status; struct scmi_clock_generic_p2a return_values = { 0 }; if (status == FWK_E_RANGE || status == FWK_E_PARAM) { @@ -448,9 +458,11 @@ static void set_request_respond(fwk_id_t service_id, int status) return_values.status = (int32_t)SCMI_SUCCESS; } - scmi_clock_ctx.scmi_api->respond(service_id, - &return_values, - sizeof(return_values.status)); + respond_status = scmi_clock_ctx.scmi_api->respond( + service_id, &return_values, sizeof(return_values.status)); + if (respond_status != FWK_SUCCESS) { + FWK_LOG_TRACE("[SCMI-CLK] %s @%d", __func__, __LINE__); + } } FWK_WEAK int mod_scmi_clock_rate_set_policy( @@ -744,9 +756,8 @@ static int scmi_clock_protocol_version_handler(fwk_id_t service_id, .version = SCMI_PROTOCOL_VERSION_CLOCK, }; - scmi_clock_ctx.scmi_api->respond(service_id, &return_values, - sizeof(return_values)); - return FWK_SUCCESS; + return scmi_clock_ctx.scmi_api->respond( + service_id, &return_values, sizeof(return_values)); } /* @@ -755,7 +766,7 @@ static int scmi_clock_protocol_version_handler(fwk_id_t service_id, static int scmi_clock_protocol_attributes_handler(fwk_id_t service_id, const uint32_t *payload) { - int status; + int status, respond_status; const struct mod_scmi_clock_agent *agent; struct scmi_protocol_attributes_p2a return_values = { .status = (int32_t)SCMI_SUCCESS, @@ -773,8 +784,11 @@ static int scmi_clock_protocol_attributes_handler(fwk_id_t service_id, ); exit: - scmi_clock_ctx.scmi_api->respond(service_id, &return_values, - sizeof(return_values)); + respond_status = scmi_clock_ctx.scmi_api->respond( + service_id, &return_values, sizeof(return_values)); + if (respond_status != FWK_SUCCESS) { + FWK_LOG_TRACE("[SCMI-CLK] %s @%d", __func__, __LINE__); + } return status; } @@ -805,8 +819,8 @@ static int scmi_clock_protocol_message_attributes_handler(fwk_id_t service_id, exit: response_size = (return_values.status == SCMI_SUCCESS) ? sizeof(return_values) : sizeof(return_values.status); - scmi_clock_ctx.scmi_api->respond(service_id, &return_values, response_size); - return FWK_SUCCESS; + return scmi_clock_ctx.scmi_api->respond( + service_id, &return_values, response_size); } /* @@ -816,7 +830,7 @@ exit: static int scmi_clock_attributes_handler(fwk_id_t service_id, const uint32_t *payload) { - int status; + int status, respond_status; const struct mod_scmi_clock_agent *agent; const struct mod_scmi_clock_device *clock_device; size_t response_size; @@ -868,7 +882,12 @@ static int scmi_clock_attributes_handler(fwk_id_t service_id, exit: response_size = (return_values.status == SCMI_SUCCESS) ? sizeof(return_values) : sizeof(return_values.status); - scmi_clock_ctx.scmi_api->respond(service_id, &return_values, response_size); + respond_status = scmi_clock_ctx.scmi_api->respond( + service_id, &return_values, response_size); + if (respond_status != FWK_SUCCESS) { + FWK_LOG_TRACE("[SCMI-CLK] %s @%d", __func__, __LINE__); + } + return status; } @@ -878,7 +897,7 @@ exit: static int scmi_clock_rate_get_handler(fwk_id_t service_id, const uint32_t *payload) { - int status; + int status, respond_status; const struct mod_scmi_clock_agent *agent; const struct mod_scmi_clock_device *clock_device; size_t response_size; @@ -930,7 +949,12 @@ static int scmi_clock_rate_get_handler(fwk_id_t service_id, exit: response_size = (return_values.status == SCMI_SUCCESS) ? sizeof(return_values) : sizeof(return_values.status); - scmi_clock_ctx.scmi_api->respond(service_id, &return_values, response_size); + respond_status = scmi_clock_ctx.scmi_api->respond( + service_id, &return_values, response_size); + if (respond_status != FWK_SUCCESS) { + FWK_LOG_TRACE("[SCMI-CLK] %s @%d", __func__, __LINE__); + } + return status; } @@ -1052,8 +1076,8 @@ static int scmi_clock_rate_set_handler(fwk_id_t service_id, exit: response_size = (return_values.status == SCMI_SUCCESS) ? sizeof(return_values) : sizeof(return_values.status); - scmi_clock_ctx.scmi_api->respond(service_id, &return_values, response_size); - return FWK_SUCCESS; + return scmi_clock_ctx.scmi_api->respond( + service_id, &return_values, response_size); } /* @@ -1150,8 +1174,8 @@ static int scmi_clock_config_set_handler(fwk_id_t service_id, exit: response_size = (return_values.status == SCMI_SUCCESS) ? sizeof(return_values) : sizeof(return_values.status); - scmi_clock_ctx.scmi_api->respond(service_id, &return_values, response_size); - return FWK_SUCCESS; + return scmi_clock_ctx.scmi_api->respond( + service_id, &return_values, response_size); } /* @@ -1160,7 +1184,7 @@ exit: static int scmi_clock_describe_rates_handler(fwk_id_t service_id, const uint32_t *payload) { - int status; + int status, respond_status; const struct mod_scmi_clock_agent *agent; const struct mod_scmi_clock_device *clock_device; unsigned int i; @@ -1317,11 +1341,15 @@ static int scmi_clock_describe_rates_handler(fwk_id_t service_id, &return_values, sizeof(return_values)); exit: - scmi_clock_ctx.scmi_api->respond(service_id, - (return_values.status == SCMI_SUCCESS) ? - NULL : &return_values.status, - (return_values.status == SCMI_SUCCESS) ? - payload_size : sizeof(return_values.status)); + respond_status = scmi_clock_ctx.scmi_api->respond( + service_id, + (return_values.status == SCMI_SUCCESS) ? NULL : &return_values.status, + (return_values.status == SCMI_SUCCESS) ? payload_size : + sizeof(return_values.status)); + if (respond_status != FWK_SUCCESS) { + FWK_LOG_TRACE("[SCMI-CLK] %s @%d", __func__, __LINE__); + } + return status; } @@ -1359,9 +1387,8 @@ static int scmi_clock_message_handler(fwk_id_t protocol_id, fwk_id_t service_id, return handler_table[message_id](service_id, payload); error: - scmi_clock_ctx.scmi_api->respond(service_id, - &return_value, sizeof(return_value)); - return FWK_SUCCESS; + return scmi_clock_ctx.scmi_api->respond( + service_id, &return_value, sizeof(return_value)); } static struct mod_scmi_to_protocol_api scmi_clock_mod_scmi_to_protocol_api = { diff --git a/module/scmi_clock/test/mocks/Mockmod_scmi_clock_extra.c b/module/scmi_clock/test/mocks/Mockmod_scmi_clock_extra.c index 070d288abd20816964caa3aae4a29163878e2725..10d06ef57ade3fec342ce21a241f5005d34eeed4 100644 --- a/module/scmi_clock/test/mocks/Mockmod_scmi_clock_extra.c +++ b/module/scmi_clock/test/mocks/Mockmod_scmi_clock_extra.c @@ -96,6 +96,7 @@ typedef struct _CMOCK_mod_scmi_from_protocol_api_respond_CALL_INSTANCE { UNITY_LINE_TYPE LineNumber; char ExpectAnyArgsBool; + int ReturnVal; fwk_id_t Expected_service_id; const void* Expected_payload; size_t Expected_size; @@ -779,7 +780,7 @@ void mod_scmi_from_protocol_api_write_payload_Stub(CMOCK_mod_scmi_from_protocol_ Mock.mod_scmi_from_protocol_api_write_payload_CallbackFunctionPointer = Callback; } -void mod_scmi_from_protocol_api_respond(fwk_id_t service_id, const void* payload, size_t size) +int mod_scmi_from_protocol_api_respond(fwk_id_t service_id, const void* payload, size_t size) { UNITY_LINE_TYPE cmock_line = TEST_LINE_NUM; CMOCK_mod_scmi_from_protocol_api_respond_CALL_INSTANCE* cmock_call_instance; @@ -789,9 +790,9 @@ void mod_scmi_from_protocol_api_respond(fwk_id_t service_id, const void* payload if (!Mock.mod_scmi_from_protocol_api_respond_CallbackBool && Mock.mod_scmi_from_protocol_api_respond_CallbackFunctionPointer != NULL) { - Mock.mod_scmi_from_protocol_api_respond_CallbackFunctionPointer(service_id, payload, size, Mock.mod_scmi_from_protocol_api_respond_CallbackCalls++); + int cmock_cb_ret = Mock.mod_scmi_from_protocol_api_respond_CallbackFunctionPointer(service_id, payload, size, Mock.mod_scmi_from_protocol_api_respond_CallbackCalls++); UNITY_CLR_DETAILS(); - return; + return cmock_cb_ret; } UNITY_TEST_ASSERT_NOT_NULL(cmock_call_instance, cmock_line, CMockStringCalledMore); cmock_line = cmock_call_instance->LineNumber; @@ -815,9 +816,10 @@ void mod_scmi_from_protocol_api_respond(fwk_id_t service_id, const void* payload } if (Mock.mod_scmi_from_protocol_api_respond_CallbackFunctionPointer != NULL) { - Mock.mod_scmi_from_protocol_api_respond_CallbackFunctionPointer(service_id, payload, size, Mock.mod_scmi_from_protocol_api_respond_CallbackCalls++); + cmock_call_instance->ReturnVal = Mock.mod_scmi_from_protocol_api_respond_CallbackFunctionPointer(service_id, payload, size, Mock.mod_scmi_from_protocol_api_respond_CallbackCalls++); } UNITY_CLR_DETAILS(); + return cmock_call_instance->ReturnVal; } void CMockExpectParameters_mod_scmi_from_protocol_api_respond(CMOCK_mod_scmi_from_protocol_api_respond_CALL_INSTANCE* cmock_call_instance, fwk_id_t service_id, const void* payload, size_t size); @@ -830,7 +832,7 @@ void CMockExpectParameters_mod_scmi_from_protocol_api_respond(CMOCK_mod_scmi_fro sizeof(size_t[sizeof(size) == sizeof(size_t) ? 1 : -1])); /* add size_t to :treat_as_array if this causes an error */ } -void mod_scmi_from_protocol_api_respond_CMockExpectAnyArgs(UNITY_LINE_TYPE cmock_line) +void mod_scmi_from_protocol_api_respond_CMockExpectAnyArgsAndReturn(UNITY_LINE_TYPE cmock_line, int cmock_to_return) { CMOCK_MEM_INDEX_TYPE cmock_guts_index = CMock_Guts_MemNew(sizeof(CMOCK_mod_scmi_from_protocol_api_respond_CALL_INSTANCE)); CMOCK_mod_scmi_from_protocol_api_respond_CALL_INSTANCE* cmock_call_instance = (CMOCK_mod_scmi_from_protocol_api_respond_CALL_INSTANCE*)CMock_Guts_GetAddressFor(cmock_guts_index); @@ -839,10 +841,11 @@ void mod_scmi_from_protocol_api_respond_CMockExpectAnyArgs(UNITY_LINE_TYPE cmock Mock.mod_scmi_from_protocol_api_respond_CallInstance = CMock_Guts_MemChain(Mock.mod_scmi_from_protocol_api_respond_CallInstance, cmock_guts_index); cmock_call_instance->LineNumber = cmock_line; cmock_call_instance->ExpectAnyArgsBool = (char)0; + cmock_call_instance->ReturnVal = cmock_to_return; cmock_call_instance->ExpectAnyArgsBool = (char)1; } -void mod_scmi_from_protocol_api_respond_CMockExpect(UNITY_LINE_TYPE cmock_line, fwk_id_t service_id, const void* payload, size_t size) +void mod_scmi_from_protocol_api_respond_CMockExpectAndReturn(UNITY_LINE_TYPE cmock_line, fwk_id_t service_id, const void* payload, size_t size, int cmock_to_return) { CMOCK_MEM_INDEX_TYPE cmock_guts_index = CMock_Guts_MemNew(sizeof(CMOCK_mod_scmi_from_protocol_api_respond_CALL_INSTANCE)); CMOCK_mod_scmi_from_protocol_api_respond_CALL_INSTANCE* cmock_call_instance = (CMOCK_mod_scmi_from_protocol_api_respond_CALL_INSTANCE*)CMock_Guts_GetAddressFor(cmock_guts_index); @@ -852,6 +855,7 @@ void mod_scmi_from_protocol_api_respond_CMockExpect(UNITY_LINE_TYPE cmock_line, cmock_call_instance->LineNumber = cmock_line; cmock_call_instance->ExpectAnyArgsBool = (char)0; CMockExpectParameters_mod_scmi_from_protocol_api_respond(cmock_call_instance, service_id, payload, size); + cmock_call_instance->ReturnVal = cmock_to_return; } void mod_scmi_from_protocol_api_respond_AddCallback(CMOCK_mod_scmi_from_protocol_api_respond_CALLBACK Callback) diff --git a/module/scmi_clock/test/mocks/Mockmod_scmi_clock_extra.h b/module/scmi_clock/test/mocks/Mockmod_scmi_clock_extra.h index 2d815787f7f13f8b8abfb74082cfd0190f8c4942..f9b6512716c9eab62b2d327b3214d8e0b53158a3 100644 --- a/module/scmi_clock/test/mocks/Mockmod_scmi_clock_extra.h +++ b/module/scmi_clock/test/mocks/Mockmod_scmi_clock_extra.h @@ -80,11 +80,11 @@ typedef int (* CMOCK_mod_scmi_from_protocol_api_write_payload_CALLBACK)(fwk_id_t void mod_scmi_from_protocol_api_write_payload_AddCallback(CMOCK_mod_scmi_from_protocol_api_write_payload_CALLBACK Callback); void mod_scmi_from_protocol_api_write_payload_Stub(CMOCK_mod_scmi_from_protocol_api_write_payload_CALLBACK Callback); #define mod_scmi_from_protocol_api_write_payload_StubWithCallback mod_scmi_from_protocol_api_write_payload_Stub -#define mod_scmi_from_protocol_api_respond_ExpectAnyArgs() mod_scmi_from_protocol_api_respond_CMockExpectAnyArgs(__LINE__) -void mod_scmi_from_protocol_api_respond_CMockExpectAnyArgs(UNITY_LINE_TYPE cmock_line); -#define mod_scmi_from_protocol_api_respond_Expect(service_id, payload, size) mod_scmi_from_protocol_api_respond_CMockExpect(__LINE__, service_id, payload, size) -void mod_scmi_from_protocol_api_respond_CMockExpect(UNITY_LINE_TYPE cmock_line, fwk_id_t service_id, const void* payload, size_t size); -typedef void (* CMOCK_mod_scmi_from_protocol_api_respond_CALLBACK)(fwk_id_t service_id, const void* payload, size_t size, int cmock_num_calls); +#define mod_scmi_from_protocol_api_respond_ExpectAnyArgsAndReturn(cmock_retval) mod_scmi_from_protocol_api_respond_CMockExpectAnyArgsAndReturn(__LINE__, cmock_retval) +void mod_scmi_from_protocol_api_respond_CMockExpectAnyArgsAndReturn(UNITY_LINE_TYPE cmock_line, int cmock_to_return); +#define mod_scmi_from_protocol_api_respond_ExpectAndReturn(service_id, payload, size, cmock_retval) mod_scmi_from_protocol_api_respond_CMockExpectAndReturn(__LINE__, service_id, payload, size, cmock_retval) +void mod_scmi_from_protocol_api_respond_CMockExpectAndReturn(UNITY_LINE_TYPE cmock_line, fwk_id_t service_id, const void* payload, size_t size, int cmock_to_return); +typedef int (* CMOCK_mod_scmi_from_protocol_api_respond_CALLBACK)(fwk_id_t service_id, const void* payload, size_t size, int cmock_num_calls); void mod_scmi_from_protocol_api_respond_AddCallback(CMOCK_mod_scmi_from_protocol_api_respond_CALLBACK Callback); void mod_scmi_from_protocol_api_respond_Stub(CMOCK_mod_scmi_from_protocol_api_respond_CALLBACK Callback); #define mod_scmi_from_protocol_api_respond_StubWithCallback mod_scmi_from_protocol_api_respond_Stub diff --git a/module/scmi_clock/test/mod_scmi_clock_extra.h b/module/scmi_clock/test/mod_scmi_clock_extra.h index b798b93a7b688b0f30976621bafdfc68651080e6..af3a20169de93780f419bee1d89fdb5ffdb9b63b 100644 --- a/module/scmi_clock/test/mod_scmi_clock_extra.h +++ b/module/scmi_clock/test/mod_scmi_clock_extra.h @@ -99,7 +99,7 @@ int mod_scmi_from_protocol_api_write_payload(fwk_id_t service_id, size_t offset, * been written. * \param size Size of the payload. */ -void mod_scmi_from_protocol_api_respond(fwk_id_t service_id, const void *payload, size_t size); +int mod_scmi_from_protocol_api_respond(fwk_id_t service_id, const void *payload, size_t size); /*! * \brief Send a notification to the agent on behalf on an SCMI service. diff --git a/module/scmi_perf/src/mod_scmi_perf.c b/module/scmi_perf/src/mod_scmi_perf.c index 35377b1f3d6660bc17dfa51721ede2d9ebaf2458..138a3e0cce432c3e4d57f8943d442d63dd578fd2 100644 --- a/module/scmi_perf/src/mod_scmi_perf.c +++ b/module/scmi_perf/src/mod_scmi_perf.c @@ -577,10 +577,8 @@ static int scmi_perf_protocol_version_handler(fwk_id_t service_id, .version = SCMI_PROTOCOL_VERSION_PERF, }; - scmi_perf_ctx.scmi_api->respond(service_id, &return_values, - sizeof(return_values)); - - return FWK_SUCCESS; + return scmi_perf_ctx.scmi_api->respond( + service_id, &return_values, sizeof(return_values)); } static int scmi_perf_protocol_attributes_handler(fwk_id_t service_id, @@ -608,10 +606,8 @@ static int scmi_perf_protocol_attributes_handler(fwk_id_t service_id, return_values.statistics_address_low = addr_low; return_values.statistics_address_high = addr_high; - scmi_perf_ctx.scmi_api->respond(service_id, &return_values, - sizeof(return_values)); - - return FWK_SUCCESS; + return scmi_perf_ctx.scmi_api->respond( + service_id, &return_values, sizeof(return_values)); } static int scmi_perf_protocol_message_attributes_handler(fwk_id_t service_id, @@ -640,17 +636,17 @@ static int scmi_perf_protocol_message_attributes_handler(fwk_id_t service_id, } #endif - scmi_perf_ctx.scmi_api->respond(service_id, &return_values, - (return_values.status == SCMI_SUCCESS) ? - sizeof(return_values) : sizeof(return_values.status)); - - return FWK_SUCCESS; + return scmi_perf_ctx.scmi_api->respond( + service_id, + &return_values, + (return_values.status == SCMI_SUCCESS) ? sizeof(return_values) : + sizeof(return_values.status)); } static int scmi_perf_domain_attributes_handler(fwk_id_t service_id, const uint32_t *payload) { - int status; + int status, respond_status; unsigned int agent_id; const struct scmi_perf_domain_attributes_a2p *parameters; uint32_t permissions = 0; @@ -736,9 +732,15 @@ static int scmi_perf_domain_attributes_handler(fwk_id_t service_id, sizeof(return_values.name) - 1); exit: - scmi_perf_ctx.scmi_api->respond(service_id, &return_values, - (return_values.status == SCMI_SUCCESS) ? - sizeof(return_values) : sizeof(return_values.status)); + respond_status = scmi_perf_ctx.scmi_api->respond( + service_id, + &return_values, + (return_values.status == SCMI_SUCCESS) ? sizeof(return_values) : + sizeof(return_values.status)); + + if (respond_status != FWK_SUCCESS) { + FWK_LOG_TRACE("[SCMI-PERF] %s @%d", __func__, __LINE__); + } return status; } @@ -746,7 +748,7 @@ exit: static int scmi_perf_describe_levels_handler(fwk_id_t service_id, const uint32_t *payload) { - int status; + int status, respond_status; size_t max_payload_size; const struct scmi_perf_describe_levels_a2p *parameters; fwk_id_t domain_id; @@ -847,11 +849,14 @@ static int scmi_perf_describe_levels_handler(fwk_id_t service_id, &return_values, sizeof(return_values)); exit: - scmi_perf_ctx.scmi_api->respond(service_id, - (return_values.status == SCMI_SUCCESS) ? - NULL : &return_values.status, - (return_values.status == SCMI_SUCCESS) ? - payload_size : sizeof(return_values.status)); + respond_status = scmi_perf_ctx.scmi_api->respond( + service_id, + (return_values.status == SCMI_SUCCESS) ? NULL : &return_values.status, + (return_values.status == SCMI_SUCCESS) ? payload_size : + sizeof(return_values.status)); + if (respond_status != FWK_SUCCESS) { + FWK_LOG_TRACE("[SCMI-PERF] %s @%d", __func__, __LINE__); + } return status; } @@ -859,7 +864,7 @@ exit: static int scmi_perf_limits_set_handler(fwk_id_t service_id, const uint32_t *payload) { - int status; + int status, respond_status; unsigned int agent_id; const struct scmi_perf_limits_set_a2p *parameters; uint32_t range_min, range_max; @@ -921,9 +926,14 @@ static int scmi_perf_limits_set_handler(fwk_id_t service_id, } exit: - scmi_perf_ctx.scmi_api->respond(service_id, &return_values, - (return_values.status == SCMI_SUCCESS) ? - sizeof(return_values) : sizeof(return_values.status)); + respond_status = scmi_perf_ctx.scmi_api->respond( + service_id, + &return_values, + (return_values.status == SCMI_SUCCESS) ? sizeof(return_values) : + sizeof(return_values.status)); + if (respond_status != FWK_SUCCESS) { + FWK_LOG_TRACE("[SCMI-PERF] %s @%d", __func__, __LINE__); + } return status; } @@ -951,19 +961,17 @@ static int scmi_perf_limits_get_handler(fwk_id_t service_id, return_values.range_max = domain_ctx->level_limits.maximum; exit: - scmi_perf_ctx.scmi_api->respond( + return scmi_perf_ctx.scmi_api->respond( service_id, &return_values, (return_values.status == SCMI_SUCCESS) ? sizeof(return_values) : sizeof(return_values.status)); - - return FWK_SUCCESS; } static int scmi_perf_level_set_handler(fwk_id_t service_id, const uint32_t *payload) { - int status; + int status, respond_status; unsigned int agent_id; const struct scmi_perf_level_set_a2p *parameters; fwk_id_t domain_id; @@ -1016,9 +1024,15 @@ static int scmi_perf_level_set_handler(fwk_id_t service_id, } exit: - scmi_perf_ctx.scmi_api->respond(service_id, &return_values, - (return_values.status == SCMI_SUCCESS) ? - sizeof(return_values) : sizeof(return_values.status)); + respond_status = scmi_perf_ctx.scmi_api->respond( + service_id, + &return_values, + (return_values.status == SCMI_SUCCESS) ? sizeof(return_values) : + sizeof(return_values.status)); + + if (respond_status != FWK_SUCCESS) { + FWK_LOG_TRACE("[SCMI-PERF] %s @%d", __func__, __LINE__); + } return status; } @@ -1026,7 +1040,7 @@ exit: static int scmi_perf_level_get_handler(fwk_id_t service_id, const uint32_t *payload) { - int status; + int status, respond_status; const struct scmi_perf_level_get_a2p *parameters; struct scmi_perf_event_parameters *evt_params; struct scmi_perf_level_get_p2a return_values; @@ -1075,9 +1089,15 @@ static int scmi_perf_level_get_handler(fwk_id_t service_id, return FWK_SUCCESS; exit: - scmi_perf_ctx.scmi_api->respond(service_id, &return_values, - (return_values.status == SCMI_SUCCESS) ? - sizeof(return_values) : sizeof(return_values.status)); + respond_status = scmi_perf_ctx.scmi_api->respond( + service_id, + &return_values, + (return_values.status == SCMI_SUCCESS) ? sizeof(return_values) : + sizeof(return_values.status)); + + if (respond_status != FWK_SUCCESS) { + FWK_LOG_TRACE("[SCMI-PERF] %s @%d", __func__, __LINE__); + } return status; } @@ -1087,7 +1107,7 @@ static int scmi_perf_limits_notify(fwk_id_t service_id, const uint32_t *payload) { unsigned int agent_id; - int status; + int status, respond_status; unsigned int id; const struct scmi_perf_notify_limits_a2p *parameters; struct scmi_perf_notify_limits_p2a return_values = { @@ -1138,9 +1158,15 @@ static int scmi_perf_limits_notify(fwk_id_t service_id, return_values.status = (int32_t)SCMI_SUCCESS; exit: - scmi_perf_ctx.scmi_api->respond(service_id, &return_values, - (return_values.status == SCMI_SUCCESS) ? - sizeof(return_values) : sizeof(return_values.status)); + respond_status = scmi_perf_ctx.scmi_api->respond( + service_id, + &return_values, + (return_values.status == SCMI_SUCCESS) ? sizeof(return_values) : + sizeof(return_values.status)); + + if (respond_status != FWK_SUCCESS) { + FWK_LOG_TRACE("[SCMI-PERF] %s @%d", __func__, __LINE__); + } return status; } @@ -1149,7 +1175,7 @@ static int scmi_perf_level_notify(fwk_id_t service_id, const uint32_t *payload) { unsigned int agent_id; - int status; + int status, respond_status; unsigned int id; const struct scmi_perf_notify_level_a2p *parameters; struct scmi_perf_notify_level_p2a return_values = { @@ -1202,9 +1228,15 @@ static int scmi_perf_level_notify(fwk_id_t service_id, return_values.status = (int32_t)SCMI_SUCCESS; exit: - scmi_perf_ctx.scmi_api->respond(service_id, &return_values, - (return_values.status == SCMI_SUCCESS) ? - sizeof(return_values) : sizeof(return_values.status)); + respond_status = scmi_perf_ctx.scmi_api->respond( + service_id, + &return_values, + (return_values.status == SCMI_SUCCESS) ? sizeof(return_values) : + sizeof(return_values.status)); + + if (respond_status != FWK_SUCCESS) { + FWK_LOG_TRACE("[SCMI-PERF] %s @%d", __func__, __LINE__); + } return status; } @@ -1296,11 +1328,11 @@ static int scmi_perf_describe_fast_channels(fwk_id_t service_id, return_values.chan_size = chan_size; exit: - scmi_perf_ctx.scmi_api->respond(service_id, &return_values, - (return_values.status == SCMI_SUCCESS) ? - sizeof(return_values) : sizeof(return_values.status)); - - return FWK_SUCCESS; + return scmi_perf_ctx.scmi_api->respond( + service_id, + &return_values, + (return_values.status == SCMI_SUCCESS) ? sizeof(return_values) : + sizeof(return_values.status)); } /* @@ -1538,10 +1570,8 @@ static int scmi_perf_message_handler(fwk_id_t protocol_id, fwk_id_t service_id, return handler_table[message_id](service_id, payload); error: - scmi_perf_ctx.scmi_api->respond(service_id, &return_value, - sizeof(return_value)); - - return FWK_SUCCESS; + return scmi_perf_ctx.scmi_api->respond( + service_id, &return_value, sizeof(return_value)); } static struct mod_scmi_to_protocol_api scmi_perf_mod_scmi_to_protocol_api = { @@ -1557,6 +1587,7 @@ static void scmi_perf_respond( fwk_id_t domain_id, int size) { + int respond_status; int idx = (int)fwk_id_get_element_idx(domain_id); fwk_id_t service_id; @@ -1566,8 +1597,12 @@ static void scmi_perf_respond( */ service_id = scmi_perf_ctx.perf_ops_table[idx].service_id; - scmi_perf_ctx.scmi_api->respond(service_id, - return_values, size); + respond_status = + scmi_perf_ctx.scmi_api->respond(service_id, return_values, size); + + if (respond_status != FWK_SUCCESS) { + FWK_LOG_TRACE("[SCMI-PERF] %s @%d", __func__, __LINE__); + } /* * Set the service identifier to 'none' to indicate the domain is diff --git a/module/scmi_power_domain/src/mod_scmi_power_domain.c b/module/scmi_power_domain/src/mod_scmi_power_domain.c index 867de064dac315434749c78fba224eede859c179..140b669abbaa65b6112affb6d2850ad0222b4a1c 100644 --- a/module/scmi_power_domain/src/mod_scmi_power_domain.c +++ b/module/scmi_power_domain/src/mod_scmi_power_domain.c @@ -268,13 +268,18 @@ static int pd_state_to_scmi_device_state(unsigned int pd_state, static int scmi_pd_protocol_version_handler(fwk_id_t service_id, const uint32_t *payload) { + int respond_status; struct scmi_protocol_version_p2a return_values = { .status = (int32_t)SCMI_SUCCESS, .version = SCMI_PROTOCOL_VERSION_POWER_DOMAIN, }; - scmi_pd_ctx.scmi_api->respond(service_id, - &return_values, sizeof(return_values)); + respond_status = scmi_pd_ctx.scmi_api->respond( + service_id, &return_values, sizeof(return_values)); + + if (respond_status != FWK_SUCCESS) { + FWK_LOG_TRACE("[SCMI-power] %s @%d", __func__, __LINE__); + } return FWK_SUCCESS; } @@ -288,16 +293,15 @@ static int scmi_pd_protocol_attributes_handler(fwk_id_t service_id, return_values.attributes = scmi_pd_ctx.domain_count; - scmi_pd_ctx.scmi_api->respond(service_id, - &return_values, sizeof(return_values)); - - return FWK_SUCCESS; + return scmi_pd_ctx.scmi_api->respond( + service_id, &return_values, sizeof(return_values)); } static int scmi_pd_power_domain_attributes_handler(fwk_id_t service_id, const uint32_t *payload) { int status = FWK_SUCCESS; + int respond_status; const struct scmi_pd_power_domain_attributes_a2p *parameters; enum mod_pd_type pd_type; unsigned int domain_idx; @@ -392,9 +396,15 @@ static int scmi_pd_power_domain_attributes_handler(fwk_id_t service_id, return_values.status = (int32_t)SCMI_SUCCESS; exit: - scmi_pd_ctx.scmi_api->respond(service_id, &return_values, - (return_values.status == SCMI_SUCCESS) ? - sizeof(return_values) : sizeof(return_values.status)); + respond_status = scmi_pd_ctx.scmi_api->respond( + service_id, + &return_values, + (return_values.status == SCMI_SUCCESS) ? sizeof(return_values) : + sizeof(return_values.status)); + + if (respond_status != FWK_SUCCESS) { + FWK_LOG_TRACE("[SCMI-power] %s @%d", __func__, __LINE__); + } return status; } @@ -415,11 +425,11 @@ static int scmi_pd_protocol_message_attributes_handler( return_values.status = (int32_t)SCMI_SUCCESS; } - scmi_pd_ctx.scmi_api->respond(service_id, &return_values, - (return_values.status == SCMI_SUCCESS) ? - sizeof(return_values) : sizeof(return_values.status)); - - return FWK_SUCCESS; + return scmi_pd_ctx.scmi_api->respond( + service_id, + &return_values, + (return_values.status == SCMI_SUCCESS) ? sizeof(return_values) : + sizeof(return_values.status)); } #ifdef BUILD_HAS_MOD_DEBUG @@ -526,9 +536,8 @@ static int scmi_pd_power_state_set_handler( scmi_return = scmi_pd_power_state_set_parameters_check(scmi_params, &pd_id); if (scmi_return != SCMI_SUCCESS) { return_values.status = scmi_return; - scmi_pd_ctx.scmi_api->respond( + return scmi_pd_ctx.scmi_api->respond( service_id, &return_values, sizeof(return_values.status)); - return FWK_SUCCESS; } /* Type checking */ @@ -536,9 +545,8 @@ static int scmi_pd_power_state_set_handler( service_id, pd_id, &agent_idx, &pd_type); if (scmi_return != SCMI_SUCCESS) { return_values.status = scmi_return; - scmi_pd_ctx.scmi_api->respond( + return scmi_pd_ctx.scmi_api->respond( service_id, &return_values, sizeof(return_values.status)); - return FWK_SUCCESS; } is_sync = @@ -550,9 +558,8 @@ static int scmi_pd_power_state_set_handler( (pd_type == MOD_PD_TYPE_DEVICE_DEBUG)) && (!is_sync)) { return_values.status = (int32_t)SCMI_NOT_SUPPORTED; - scmi_pd_ctx.scmi_api->respond( + return scmi_pd_ctx.scmi_api->respond( service_id, &return_values, sizeof(return_values.status)); - return FWK_SUCCESS; } else if (pd_type == MOD_PD_TYPE_CORE) { /* * Async/sync flag is ignored for core power domains as stated @@ -569,16 +576,14 @@ static int scmi_pd_power_state_set_handler( if (status != FWK_SUCCESS) { return_values.status = (int32_t)SCMI_GENERIC_ERROR; - scmi_pd_ctx.scmi_api->respond( + return scmi_pd_ctx.scmi_api->respond( service_id, &return_values, sizeof(return_values.status)); - return FWK_SUCCESS; } if (policy_status == MOD_SCMI_PD_SKIP_MESSAGE_HANDLER) { return_values.status = (int32_t)SCMI_SUCCESS; - scmi_pd_ctx.scmi_api->respond( + return scmi_pd_ctx.scmi_api->respond( service_id, &return_values, sizeof(return_values)); - return FWK_SUCCESS; } if (!is_sync) { @@ -589,21 +594,24 @@ static int scmi_pd_power_state_set_handler( status = scmi_pd_ctx.pd_api->set_state(pd_id, false, power_state); if (status == FWK_SUCCESS) { return_values.status = (int32_t)SCMI_SUCCESS; - scmi_pd_ctx.scmi_api->respond( + return scmi_pd_ctx.scmi_api->respond( service_id, &return_values, sizeof(return_values)); } else { return_values.status = (int32_t)SCMI_GENERIC_ERROR; - scmi_pd_ctx.scmi_api->respond( + return scmi_pd_ctx.scmi_api->respond( service_id, &return_values, sizeof(return_values.status)); } - return FWK_SUCCESS; } /* Sync request handling */ if (ops_is_busy(pd_id)) { return_values.status = (int32_t)SCMI_BUSY; - scmi_pd_ctx.scmi_api->respond( + int respond_status = scmi_pd_ctx.scmi_api->respond( service_id, &return_values, sizeof(return_values.status)); + + if (respond_status != FWK_SUCCESS) { + FWK_LOG_TRACE("[SCMI-power] %s @%d", __func__, __LINE__); + } return FWK_E_BUSY; } ops_set_busy(pd_id, service_id); @@ -633,6 +641,7 @@ static int scmi_pd_power_state_get_handler(fwk_id_t service_id, const uint32_t *payload) { int status = FWK_SUCCESS; + int respond_status; const struct scmi_pd_power_state_get_a2p *parameters; unsigned int domain_idx; fwk_id_t pd_id; @@ -717,9 +726,15 @@ static int scmi_pd_power_state_get_handler(fwk_id_t service_id, } exit: - scmi_pd_ctx.scmi_api->respond(service_id, &return_values, - (return_values.status == SCMI_SUCCESS) ? - sizeof(return_values) : sizeof(return_values.status)); + respond_status = scmi_pd_ctx.scmi_api->respond( + service_id, + &return_values, + (return_values.status == SCMI_SUCCESS) ? sizeof(return_values) : + sizeof(return_values.status)); + + if (respond_status != FWK_SUCCESS) { + FWK_LOG_TRACE("[SCMI-power] %s @%d", __func__, __LINE__); + } return status; } @@ -806,13 +821,11 @@ static int scmi_pd_power_state_notify_handler( return_values.status = (int32_t)SCMI_SUCCESS; exit: - scmi_pd_ctx.scmi_api->respond( + return scmi_pd_ctx.scmi_api->respond( service_id, &return_values, (return_values.status == SCMI_SUCCESS) ? sizeof(return_values) : sizeof(return_values.status)); - - return FWK_SUCCESS; } static int scmi_pd_power_state_changed_notify_handler( @@ -1010,9 +1023,8 @@ static int scmi_pd_message_handler(fwk_id_t protocol_id, fwk_id_t service_id, return handler_table[message_id](service_id, payload); error: - scmi_pd_ctx.scmi_api->respond(service_id, - &return_value, sizeof(return_value)); - return FWK_SUCCESS; + return scmi_pd_ctx.scmi_api->respond( + service_id, &return_value, sizeof(return_value)); } static struct mod_scmi_to_protocol_api scmi_pd_mod_scmi_to_protocol_api = { @@ -1169,7 +1181,7 @@ static int process_request_event(const struct fwk_event *event) #ifdef BUILD_HAS_MOD_DEBUG bool dbg_enabled; fwk_id_t service_id; - int status; + int status, respond_status; bool state_get; struct scmi_pd_power_state_get_p2a retval_get = { .status = SCMI_GENERIC_ERROR @@ -1227,11 +1239,15 @@ static int process_request_event(const struct fwk_event *event) if (status != FWK_PENDING) { service_id = ops_get_service(pd_id); - scmi_pd_ctx.scmi_api->respond( + respond_status = scmi_pd_ctx.scmi_api->respond( service_id, state_get ? (void *)&retval_get : (void *)&retval_set, state_get ? sizeof(retval_get) : sizeof(retval_set)); + if (respond_status != FWK_SUCCESS) { + FWK_LOG_TRACE("[SCMI-power] %s @%d", __func__, __LINE__); + } + ops_set_idle(pd_id); } @@ -1241,6 +1257,7 @@ static int process_request_event(const struct fwk_event *event) static int process_response_event(const struct fwk_event *event) { + int respond_status; fwk_id_t service_id; unsigned int module_idx; struct scmi_pd_power_state_set_p2a retval_set = { @@ -1263,9 +1280,13 @@ static int process_response_event(const struct fwk_event *event) retval_set.status = (int32_t)SCMI_SUCCESS; } - scmi_pd_ctx.scmi_api->respond( + respond_status = scmi_pd_ctx.scmi_api->respond( service_id, &retval_set, sizeof(retval_set)); + if (respond_status != FWK_SUCCESS) { + FWK_LOG_TRACE("[SCMI-power] %s @%d", __func__, __LINE__); + } + ops_set_idle(event->source_id); return FWK_SUCCESS; @@ -1290,11 +1311,17 @@ static int process_response_event(const struct fwk_event *event) retval_get.power_state = params->enabled ? pd_state_to_scmi_dev_state[MOD_PD_STATE_ON] : pd_state_to_scmi_dev_state[MOD_PD_STATE_OFF]; - scmi_pd_ctx.scmi_api->respond( + respond_status = scmi_pd_ctx.scmi_api->respond( service_id, (void *)&retval_get, sizeof(retval_get)); + if (respond_status != FWK_SUCCESS) { + FWK_LOG_TRACE("[SCMI-power] %s @%d", __func__, __LINE__); + } } else { - scmi_pd_ctx.scmi_api->respond( + respond_status = scmi_pd_ctx.scmi_api->respond( service_id, (void *)&retval_set, sizeof(retval_set)); + if (respond_status != FWK_SUCCESS) { + FWK_LOG_TRACE("[SCMI-power] %s @%d", __func__, __LINE__); + } } ops_set_idle(scmi_pd_ctx.debug_pd_id); return FWK_SUCCESS; diff --git a/module/scmi_reset_domain/src/mod_scmi_reset_domain.c b/module/scmi_reset_domain/src/mod_scmi_reset_domain.c index 4bbdde83e12253053dc786f6b1c4366e6ecfb57c..23e2203cdb94dfc2274790bbff6b012f10cfc352 100644 --- a/module/scmi_reset_domain/src/mod_scmi_reset_domain.c +++ b/module/scmi_reset_domain/src/mod_scmi_reset_domain.c @@ -16,6 +16,7 @@ #include #include +#include #include #include #include @@ -118,9 +119,7 @@ static int protocol_version_handler(fwk_id_t service_id, .version = SCMI_PROTOCOL_VERSION_RESET_DOMAIN, }; - scmi_rd_ctx.scmi_api->respond(service_id, &outmsg, sizeof(outmsg)); - - return FWK_SUCCESS; + return scmi_rd_ctx.scmi_api->respond(service_id, &outmsg, sizeof(outmsg)); } static int protocol_attributes_handler(fwk_id_t service_id, @@ -142,9 +141,7 @@ static int protocol_attributes_handler(fwk_id_t service_id, outmsg.attributes = scmi_rd_ctx.config-> agent_table[agent_id].agent_domain_count; - scmi_rd_ctx.scmi_api->respond(service_id, &outmsg, sizeof(outmsg)); - - return FWK_SUCCESS; + return scmi_rd_ctx.scmi_api->respond(service_id, &outmsg, sizeof(outmsg)); } static int protocol_message_attributes_handler(fwk_id_t service_id, @@ -164,9 +161,7 @@ static int protocol_message_attributes_handler(fwk_id_t service_id, outmsg_size = sizeof(outmsg); } - scmi_rd_ctx.scmi_api->respond(service_id, &outmsg, outmsg_size); - - return FWK_SUCCESS; + return scmi_rd_ctx.scmi_api->respond(service_id, &outmsg, outmsg_size); } /* @@ -256,6 +251,7 @@ static int reset_attributes_handler(fwk_id_t service_id, }; size_t outmsg_size = sizeof(outmsg.status); int status = FWK_SUCCESS; + int respond_status; params = *(const struct scmi_reset_domain_attributes_a2p *)payload; @@ -286,7 +282,12 @@ static int reset_attributes_handler(fwk_id_t service_id, outmsg_size = sizeof(outmsg); exit: - scmi_rd_ctx.scmi_api->respond(service_id, &outmsg, outmsg_size); + respond_status = + scmi_rd_ctx.scmi_api->respond(service_id, &outmsg, outmsg_size); + + if (respond_status != FWK_SUCCESS) { + FWK_LOG_TRACE("[SCMI-RESET] %s @%d", __func__, __LINE__); + } return status; } @@ -294,7 +295,7 @@ exit: static int reset_request_handler(fwk_id_t service_id, const uint32_t *payload) { - int status; + int status, respond_status; unsigned int agent_id; struct mod_reset_domain_dev_config *reset_dev_config; struct scmi_reset_domain_request_a2p params = { 0 }; @@ -417,7 +418,12 @@ static int reset_request_handler(fwk_id_t service_id, outmsg_size = sizeof(outmsg); exit: - scmi_rd_ctx.scmi_api->respond(service_id, &outmsg, outmsg_size); + respond_status = + scmi_rd_ctx.scmi_api->respond(service_id, &outmsg, outmsg_size); + + if (respond_status != FWK_SUCCESS) { + FWK_LOG_TRACE("[SCMI-RESET] %s @%d", __func__, __LINE__); + } return status; } @@ -427,7 +433,7 @@ static int reset_notify_handler(fwk_id_t service_id, const uint32_t *payload) { unsigned int agent_id; - int status; + int status, respond_status; unsigned int domain_id; const struct scmi_reset_domain_notify_a2p *parameters; struct scmi_reset_domain_notify_p2a outmsg = { @@ -470,10 +476,15 @@ static int reset_notify_handler(fwk_id_t service_id, outmsg.status = SCMI_SUCCESS; exit: - scmi_rd_ctx.scmi_api->respond(service_id, &outmsg, - (outmsg.status == SCMI_SUCCESS) ? - sizeof(outmsg) : - sizeof(outmsg.status)); + respond_status = scmi_rd_ctx.scmi_api->respond( + service_id, + &outmsg, + (outmsg.status == SCMI_SUCCESS) ? sizeof(outmsg) : + sizeof(outmsg.status)); + + if (respond_status != FWK_SUCCESS) { + FWK_LOG_TRACE("[SCMI-RESET] %s @%d", __func__, __LINE__); + } return status; } @@ -590,9 +601,8 @@ static int scmi_reset_message_handler(fwk_id_t protocol_id, return msg_handler_table[message_id](service_id, payload); error: - scmi_rd_ctx.scmi_api->respond(service_id, - &return_value, sizeof(return_value)); - return FWK_SUCCESS; + return scmi_rd_ctx.scmi_api->respond( + service_id, &return_value, sizeof(return_value)); } static struct mod_scmi_to_protocol_api scmi_reset_mod_scmi_to_protocol_api = { diff --git a/module/scmi_sensor/src/mod_scmi_sensor.c b/module/scmi_sensor/src/mod_scmi_sensor.c index 8c0c789ad416f55713c6c95ddd6037336ac0638a..7fa1afc552345be6609e81f33d5049852023a686 100644 --- a/module/scmi_sensor/src/mod_scmi_sensor.c +++ b/module/scmi_sensor/src/mod_scmi_sensor.c @@ -160,6 +160,7 @@ static int scmi_sensor_reading_respond( unsigned int payload_size; const void *payload = NULL; int status = FWK_SUCCESS; + int respond_status; unsigned int sensor_idx; fwk_id_t service_id; #ifdef BUILD_HAS_SCMI_SENSOR_V2 @@ -255,7 +256,11 @@ exit_error: payload = &return_values; status = FWK_E_PANIC; exit: - scmi_sensor_ctx.scmi_api->respond(service_id, payload, payload_size); + respond_status = + scmi_sensor_ctx.scmi_api->respond(service_id, payload, payload_size); + if (respond_status != FWK_SUCCESS) { + FWK_LOG_TRACE("[SCMI-SENS] %s @%d", __func__, __LINE__); + } /* * Set the service identifier to 'none' to indicate the sensor is * available again. @@ -275,10 +280,8 @@ static int scmi_sensor_protocol_version_handler(fwk_id_t service_id, .version = SCMI_PROTOCOL_VERSION_SENSOR, }; - scmi_sensor_ctx.scmi_api->respond(service_id, &return_values, - sizeof(return_values)); - - return FWK_SUCCESS; + return scmi_sensor_ctx.scmi_api->respond( + service_id, &return_values, sizeof(return_values)); } static int scmi_sensor_protocol_attributes_handler(fwk_id_t service_id, @@ -290,10 +293,8 @@ static int scmi_sensor_protocol_attributes_handler(fwk_id_t service_id, .sensor_reg_len = 0, /* Unsupported */ }; - scmi_sensor_ctx.scmi_api->respond(service_id, &return_values, - sizeof(return_values)); - - return FWK_SUCCESS; + return scmi_sensor_ctx.scmi_api->respond( + service_id, &return_values, sizeof(return_values)); } static int scmi_sensor_protocol_msg_attributes_handler(fwk_id_t service_id, @@ -316,17 +317,17 @@ static int scmi_sensor_protocol_msg_attributes_handler(fwk_id_t service_id, return_values.status = (int32_t)SCMI_NOT_FOUND; } - scmi_sensor_ctx.scmi_api->respond(service_id, &return_values, - (return_values.status == SCMI_SUCCESS) ? - sizeof(return_values) : sizeof(return_values.status)); - - return FWK_SUCCESS; + return scmi_sensor_ctx.scmi_api->respond( + service_id, + &return_values, + (return_values.status == SCMI_SUCCESS) ? sizeof(return_values) : + sizeof(return_values.status)); } static int scmi_sensor_protocol_desc_get_handler(fwk_id_t service_id, const uint32_t *payload) { - int status; + int status, respond_status; size_t payload_size; size_t max_payload_size; const struct scmi_sensor_protocol_description_get_a2p *parameters = @@ -474,11 +475,15 @@ static int scmi_sensor_protocol_desc_get_handler(fwk_id_t service_id, exit_unexpected: fwk_unexpected(); exit: - scmi_sensor_ctx.scmi_api->respond(service_id, - (return_values.status == SCMI_SUCCESS) ? - NULL : &return_values.status, - (return_values.status == SCMI_SUCCESS) ? - payload_size : sizeof(return_values.status)); + respond_status = scmi_sensor_ctx.scmi_api->respond( + service_id, + (return_values.status == SCMI_SUCCESS) ? NULL : &return_values.status, + (return_values.status == SCMI_SUCCESS) ? payload_size : + sizeof(return_values.status)); + + if (respond_status != FWK_SUCCESS) { + FWK_LOG_TRACE("[SCMI-SENS] %s @%d", __func__, __LINE__); + } return status; } @@ -490,7 +495,7 @@ static int scmi_sensor_trip_point_notify_handler( { uint32_t flags; unsigned int agent_id; - int status; + int status, respond_status; struct scmi_sensor_trip_point_notify_a2p *parameters; struct scmi_sensor_trip_point_notify_p2a return_values = { .status = SCMI_GENERIC_ERROR, @@ -528,11 +533,14 @@ static int scmi_sensor_trip_point_notify_handler( status = FWK_SUCCESS; exit: - scmi_sensor_ctx.scmi_api->respond( + respond_status = scmi_sensor_ctx.scmi_api->respond( service_id, &return_values, (return_values.status == SCMI_SUCCESS) ? sizeof(return_values) : sizeof(return_values.status)); + if (respond_status != FWK_SUCCESS) { + FWK_LOG_TRACE("[SCMI-SENS] %s @%d", __func__, __LINE__); + } return status; } @@ -549,7 +557,7 @@ static int scmi_sensor_trip_point_config_handler( struct mod_sensor_trip_point_params trip_point_param; fwk_id_t sensor_id; uint32_t trip_point_idx; - int status; + int status, respond_status; parameters = (struct scmi_sensor_trip_point_config_a2p *)payload; @@ -598,11 +606,14 @@ static int scmi_sensor_trip_point_config_handler( status = FWK_SUCCESS; exit: - scmi_sensor_ctx.scmi_api->respond( + respond_status = scmi_sensor_ctx.scmi_api->respond( service_id, &return_values, (return_values.status == SCMI_SUCCESS) ? sizeof(return_values) : sizeof(return_values.status)); + if (respond_status != FWK_SUCCESS) { + FWK_LOG_TRACE("[SCMI-SENS] %s @%d", __func__, __LINE__); + } return status; } @@ -613,7 +624,7 @@ static int scmi_sensor_axis_desc_get_handler( fwk_id_t service_id, const uint32_t *payload) { - int status; + int status, respond_status; size_t payload_size; size_t max_payload_size; const struct scmi_sensor_axis_description_get_a2p *parameters = @@ -746,11 +757,14 @@ static int scmi_sensor_axis_desc_get_handler( exit_unexpected: fwk_unexpected(); exit: - scmi_sensor_ctx.scmi_api->respond( + respond_status = scmi_sensor_ctx.scmi_api->respond( service_id, (return_values.status == SCMI_SUCCESS) ? NULL : &return_values.status, (return_values.status == SCMI_SUCCESS) ? payload_size : sizeof(return_values.status)); + if (respond_status != FWK_SUCCESS) { + FWK_LOG_TRACE("[SCMI-SENS] %s @%d", __func__, __LINE__); + } return status; } @@ -764,7 +778,7 @@ static int scmi_sensor_reading_get_handler(fwk_id_t service_id, struct scmi_sensor_event_parameters *params; unsigned int sensor_idx; uint32_t flags; - int status; + int status, respond_status; parameters = (const struct scmi_sensor_protocol_reading_get_a2p *)payload; @@ -827,9 +841,15 @@ static int scmi_sensor_reading_get_handler(fwk_id_t service_id, return FWK_SUCCESS; exit: - scmi_sensor_ctx.scmi_api->respond(service_id, &return_values, - (return_values.status == SCMI_SUCCESS) ? - sizeof(return_values) : sizeof(return_values.status)); + respond_status = scmi_sensor_ctx.scmi_api->respond( + service_id, + &return_values, + (return_values.status == SCMI_SUCCESS) ? sizeof(return_values) : + sizeof(return_values.status)); + + if (respond_status != FWK_SUCCESS) { + FWK_LOG_TRACE("[SCMI-SENS] %s @%d", __func__, __LINE__); + } return status; } @@ -947,9 +967,8 @@ static int scmi_sensor_message_handler(fwk_id_t protocol_id, return handler_table[message_id](service_id, payload); error: - scmi_sensor_ctx.scmi_api->respond(service_id, &return_value, - sizeof(return_value)); - return FWK_SUCCESS; + return scmi_sensor_ctx.scmi_api->respond( + service_id, &return_value, sizeof(return_value)); } static struct mod_scmi_to_protocol_api scmi_sensor_mod_scmi_to_protocol_api = { diff --git a/module/scmi_system_power/src/mod_scmi_system_power.c b/module/scmi_system_power/src/mod_scmi_system_power.c index b8a151d891b9f64f469317d145260804db9a3f0f..ea9da91e37a1c57ece794c687103c882cbfb459b 100644 --- a/module/scmi_system_power/src/mod_scmi_system_power.c +++ b/module/scmi_system_power/src/mod_scmi_system_power.c @@ -202,9 +202,8 @@ static int scmi_sys_power_version_handler(fwk_id_t service_id, .version = SCMI_PROTOCOL_VERSION_SYS_POWER, }; - scmi_sys_power_ctx.scmi_api->respond(service_id, &return_values, - sizeof(return_values)); - return FWK_SUCCESS; + return scmi_sys_power_ctx.scmi_api->respond( + service_id, &return_values, sizeof(return_values)); } /* @@ -218,9 +217,8 @@ static int scmi_sys_power_attributes_handler(fwk_id_t service_id, .attributes = 0, }; - scmi_sys_power_ctx.scmi_api->respond(service_id, &return_values, - sizeof(return_values)); - return FWK_SUCCESS; + return scmi_sys_power_ctx.scmi_api->respond( + service_id, &return_values, sizeof(return_values)); } /* @@ -265,11 +263,11 @@ static int scmi_sys_power_msg_attributes_handler(fwk_id_t service_id, } exit: - scmi_sys_power_ctx.scmi_api->respond(service_id, &return_values, + return scmi_sys_power_ctx.scmi_api->respond( + service_id, + &return_values, (return_values.status == SCMI_SUCCESS) ? sizeof(return_values) : - sizeof(return_values.status)); - - return FWK_SUCCESS; + sizeof(return_values.status)); } /* @@ -279,6 +277,7 @@ static int scmi_sys_power_state_set_handler(fwk_id_t service_id, const uint32_t *payload) { int status = FWK_SUCCESS; + int respond_status; const struct scmi_sys_power_state_set_a2p *parameters; struct scmi_sys_power_state_set_p2a return_values = { .status = (int32_t)SCMI_GENERIC_ERROR, @@ -416,9 +415,15 @@ static int scmi_sys_power_state_set_handler(fwk_id_t service_id, return_values.status = (int32_t)SCMI_SUCCESS; exit: - scmi_sys_power_ctx.scmi_api->respond(service_id, &return_values, + respond_status = scmi_sys_power_ctx.scmi_api->respond( + service_id, + &return_values, (return_values.status == SCMI_SUCCESS) ? sizeof(return_values) : - sizeof(return_values.status)); + sizeof(return_values.status)); + + if (respond_status != FWK_SUCCESS) { + FWK_LOG_TRACE("SCMI_SYS_POWER: %s @%d", __func__, __LINE__); + } return status; } @@ -430,6 +435,7 @@ static int scmi_sys_power_state_get_handler(fwk_id_t service_id, const uint32_t *payload) { int status = FWK_SUCCESS; + int respond_status; struct scmi_sys_power_state_get_p2a return_values = { .status = (int32_t)SCMI_GENERIC_ERROR, }; @@ -467,9 +473,15 @@ static int scmi_sys_power_state_get_handler(fwk_id_t service_id, } exit: - scmi_sys_power_ctx.scmi_api->respond(service_id, &return_values, + respond_status = scmi_sys_power_ctx.scmi_api->respond( + service_id, + &return_values, (return_values.status == SCMI_SUCCESS) ? sizeof(return_values) : - sizeof(return_values.status)); + sizeof(return_values.status)); + + if (respond_status != FWK_SUCCESS) { + FWK_LOG_TRACE("SCMI_SYS_POWER: %s @%d", __func__, __LINE__); + } return status; } @@ -486,7 +498,7 @@ static int scmi_sys_power_state_notify_handler(fwk_id_t service_id, struct scmi_sys_power_state_notify_p2a return_values = { .status = (int32_t)SCMI_GENERIC_ERROR, }; - int status; + int status, respond_status; status = scmi_sys_power_ctx.scmi_api->get_agent_id(service_id, &agent_id); if (status != FWK_SUCCESS) { @@ -509,9 +521,15 @@ static int scmi_sys_power_state_notify_handler(fwk_id_t service_id, return_values.status = (int32_t)SCMI_SUCCESS; exit: - scmi_sys_power_ctx.scmi_api->respond(service_id, &return_values, + respond_status = scmi_sys_power_ctx.scmi_api->respond( + service_id, + &return_values, (return_values.status == SCMI_SUCCESS) ? sizeof(return_values) : - sizeof(return_values.status)); + sizeof(return_values.status)); + + if (respond_status != FWK_SUCCESS) { + FWK_LOG_TRACE("SCMI_SYS_POWER: %s @%d", __func__, __LINE__); + } return FWK_SUCCESS; } @@ -662,9 +680,8 @@ static int scmi_sys_power_handler(fwk_id_t protocol_id, return handler_table[message_id](service_id, payload); error: - scmi_sys_power_ctx.scmi_api->respond(service_id, &return_value, - sizeof(return_value)); - return FWK_SUCCESS; + return scmi_sys_power_ctx.scmi_api->respond( + service_id, &return_value, sizeof(return_value)); } static struct mod_scmi_to_protocol_api scmi_sys_power_mod_scmi_to_protocol = { diff --git a/module/scmi_voltage_domain/src/mod_scmi_voltage_domain.c b/module/scmi_voltage_domain/src/mod_scmi_voltage_domain.c index eb6939a6fd8f8264ae4d14e3098616336c5d84d0..2fccc9c9c12eaba26153078e042d2471bd5c05e6 100644 --- a/module/scmi_voltage_domain/src/mod_scmi_voltage_domain.c +++ b/module/scmi_voltage_domain/src/mod_scmi_voltage_domain.c @@ -227,8 +227,8 @@ static int scmi_voltd_protocol_version_handler(fwk_id_t service_id, .version = SCMI_PROTOCOL_VERSION_VOLTD, }; - scmi_voltd_ctx.scmi_api->respond(service_id, &outmsg, sizeof(outmsg)); - return FWK_SUCCESS; + return scmi_voltd_ctx.scmi_api->respond( + service_id, &outmsg, sizeof(outmsg)); } /* @@ -253,8 +253,7 @@ static int scmi_voltd_protocol_attributes_handler(fwk_id_t service_id, outmsg_size = sizeof(outmsg); exit: - scmi_voltd_ctx.scmi_api->respond(service_id, &outmsg, outmsg_size); - return FWK_SUCCESS; + return scmi_voltd_ctx.scmi_api->respond(service_id, &outmsg, outmsg_size); } /* @@ -278,8 +277,7 @@ static int scmi_voltd_protocol_message_attributes_handler(fwk_id_t service_id, outmsg_size = sizeof(outmsg); } - scmi_voltd_ctx.scmi_api->respond(service_id, &outmsg, outmsg_size); - return FWK_SUCCESS; + return scmi_voltd_ctx.scmi_api->respond(service_id, &outmsg, outmsg_size); } /* @@ -311,8 +309,7 @@ static int scmi_voltd_domain_attributes_handler(fwk_id_t service_id, outmsg_size = sizeof(outmsg); exit: - scmi_voltd_ctx.scmi_api->respond(service_id, &outmsg, outmsg_size); - return FWK_SUCCESS; + return scmi_voltd_ctx.scmi_api->respond(service_id, &outmsg, outmsg_size); } /* @@ -378,8 +375,7 @@ static int scmi_voltd_config_get_handler(fwk_id_t service_id, outmsg.status = SCMI_NOT_FOUND; } - scmi_voltd_ctx.scmi_api->respond(service_id, &outmsg, outmsg_size); - return FWK_SUCCESS; + return scmi_voltd_ctx.scmi_api->respond(service_id, &outmsg, outmsg_size); } static int scmi_voltd_config_set_handler(fwk_id_t service_id, @@ -446,8 +442,7 @@ static int scmi_voltd_config_set_handler(fwk_id_t service_id, outmsg.status = SCMI_NOT_FOUND; } - scmi_voltd_ctx.scmi_api->respond(service_id, &outmsg, outmsg_size); - return FWK_SUCCESS; + return scmi_voltd_ctx.scmi_api->respond(service_id, &outmsg, outmsg_size); } /* @@ -483,8 +478,7 @@ static int scmi_voltd_level_get_handler(fwk_id_t service_id, outmsg_size = sizeof(outmsg); exit: - scmi_voltd_ctx.scmi_api->respond(service_id, &outmsg, outmsg_size); - return FWK_SUCCESS; + return scmi_voltd_ctx.scmi_api->respond(service_id, &outmsg, outmsg_size); } static int scmi_voltd_level_set_handler(fwk_id_t service_id, @@ -521,8 +515,7 @@ static int scmi_voltd_level_set_handler(fwk_id_t service_id, } exit: - scmi_voltd_ctx.scmi_api->respond(service_id, &outmsg, outmsg_size); - return FWK_SUCCESS; + return scmi_voltd_ctx.scmi_api->respond(service_id, &outmsg, outmsg_size); } /* @@ -532,6 +525,7 @@ static int scmi_voltd_describe_levels_handler(fwk_id_t service_id, const uint32_t *payload) { int status = 0; + int respond_status; const struct mod_scmi_voltd_device *device = NULL; const struct scmi_voltd_describe_levels_a2p *inmsg = NULL; struct scmi_voltd_describe_levels_p2a outmsg = { @@ -639,11 +633,16 @@ static int scmi_voltd_describe_levels_handler(fwk_id_t service_id, outmsg.status = SCMI_GENERIC_ERROR; exit: - if (outmsg.status == SCMI_SUCCESS) - scmi_api->respond(service_id, NULL, payload_size); - else - scmi_api->respond(service_id, &outmsg.status, sizeof(&outmsg.status)); + if (outmsg.status == SCMI_SUCCESS) { + respond_status = scmi_api->respond(service_id, NULL, payload_size); + } else { + respond_status = scmi_api->respond( + service_id, &outmsg.status, sizeof(&outmsg.status)); + } + if (respond_status != FWK_SUCCESS) { + FWK_LOG_TRACE("[SCMI-VOLT] %s @%d", __func__, __LINE__); + } // Return status or return FWK_SUCCESS??? return status; } @@ -690,8 +689,8 @@ static int scmi_voltd_message_handler(fwk_id_t protocol_id, fwk_id_t service_id, return handler_table[message_id](service_id, payload); error: - scmi_voltd_ctx.scmi_api->respond(service_id, &outmsg, sizeof(outmsg)); - return FWK_SUCCESS; + return scmi_voltd_ctx.scmi_api->respond( + service_id, &outmsg, sizeof(outmsg)); } static struct mod_scmi_to_protocol_api scmi_voltd_mod_scmi_to_protocol_api = { diff --git a/module/transport/CMakeLists.txt b/module/transport/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..06f45ae3b122bfac98b71f2c3d986d3a520434d7 --- /dev/null +++ b/module/transport/CMakeLists.txt @@ -0,0 +1,22 @@ +# +# Arm SCP/MCP Software +# Copyright (c) 2022, Arm Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +add_library(${SCP_MODULE_TARGET} SCP_MODULE) + +target_include_directories(${SCP_MODULE_TARGET} + PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include") + +target_sources(${SCP_MODULE_TARGET} + PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/src/mod_transport.c") + +if("scmi" IN_LIST SCP_MODULES) + target_link_libraries(${SCP_MODULE_TARGET} PRIVATE module-scmi) +endif() + +if("power-domain" IN_LIST SCP_MODULES) + target_link_libraries(${SCP_MODULE_TARGET} PRIVATE module-power-domain) +endif() diff --git a/module/transport/Module.cmake b/module/transport/Module.cmake new file mode 100644 index 0000000000000000000000000000000000000000..9c152af0a37aa7b7b8da26faac72d57b5119fc9d --- /dev/null +++ b/module/transport/Module.cmake @@ -0,0 +1,9 @@ +# +# Arm SCP/MCP Software +# Copyright (c) 2022, Arm Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +set(SCP_MODULE "transport") +set(SCP_MODULE_TARGET "module-transport") diff --git a/module/transport/doc/transport.md b/module/transport/doc/transport.md new file mode 100644 index 0000000000000000000000000000000000000000..6929c502ce3518f64090988103542b13259ce267 --- /dev/null +++ b/module/transport/doc/transport.md @@ -0,0 +1,401 @@ +\ingroup GroupModules Modules +\defgroup GroupTransport Transport + +# Module Transport Architecture + +Copyright (c) 2022, Arm Limited. All rights reserved. + +# Overview + +This module implements a Hardware Abstraction Layer (HAL) API for sending and +receiving inter-processor messages. + +Note: The SMT module will be replaced by the Transport module in future. + +# Module Design + +The transport module provides an interface for modules to send and receive +messages(both SCMI and firmware) via in-band and out-band communication. + +The transport module defines a driver interface to transfer/receive data from +drivers like MHU, MHUv2, etc. It also defines a signal interface which is used +to notify the client module on receiving a message. + +``` + +--------+ + | Shared | + | Memory | + +--------+ + ^ ++--------+ | +--------+ +-----------------+ +| DRIVER |<-+ | +-->| SCMI |<----->| PROTOCOL MODULE | ++--------+ | | | +--------+ +-----------------+ + | | | ++--------+ | +------+------+ | +| DRIVER |<-+--->| TRANSPORT |<----+ ++--------+ | +-------------+ | + | | +--------+ ++--------+ | +-->| MODULE | +| DRIVER |<-+ +--------+ ++--------+ +``` + +# Flow + +## IN-BAND message communication + +### Sending a message +Messages can be sent using in-band communication - where the driver transmits +the message using the channels(for example, the MHUv2 driver sends the message +using the message status registers in the sender channel) by calling the +`send_message()` function and triggering the interrupt(doorbell in case of MHUs) +on the receiver side by calling the `trigger_event()` function in the driver API. + +``` ++--------+ +---------+ +--------+ +| MODULE | |TRANSPORT| | DRIVER | ++---+----+ +----+----+ +----+---+ + | | | + | | | + | transmit() | | + +----------------------->| send_message() | + | +------------------------->+------+ + | | | | + | | | | Copy message to + | | | | message status + | | | | registers + | | | | + | | return status |<-----+ + | |<-------------------------+ + | | | + | | | + | | trigger_event() | + | +------------------------->+------+ + | | | | + | | | | Raise interrupt + | | | | on the receiver + | | return status |<-----+ + | return status |<-------------------------+ + |<-----------------------+ | + | | | + | | | + | | | + | | | + +``` +### Receiving a message + +When a message is received the transport module is signalled by the driver +module. The transport module then retrieves the message by calling the +`get_message()` function in the driver API. The message is stored in a local +read buffer and the length of the message header and payload is verified and +then the recipient module is signalled by using `signal_message()` function +from the signal API. The recipient module then retrieves the message header +and payload from the transport module and then processes the message. + +``` + +--------+ +-----------+ +--------+ + | DRIVER | | TRANSPORT | | MODULE | + +---+----+ +-----+-----+ +----+---+ + Interrupt | | | +----------->+---+ | | + | | isr() | | + |<--+ | | + | signal_message() | | + +------------------------------>| | + | | | + | get_message() | | + |<------------------------------+ | + | | | + +----+Copy message from | | + | |message status registers | | + |<---+ | | + | return status | | + +------------------------------>| | + | +-----+ | + | | | | + | | | Verify the message | + | | | | + | | | | + | |<----+ | + | | signal_message() | + | +------------------------------------->| + | | return status | + | return status |<-------------------------------------+ + |<------------------------------+ | + | | | + | | get_message_header() | + | |<-------------------------------------+ + | | | + | | get_payload() | + | |<-------------------------------------+ + | | +-----+ + | | | | + | | transport_release_channel_lock() or | | Process the message + | | respond() |<----+ + | |<-------------------------------------+ + | | | + | | return status | + | +------------------------------------->| + | | | +``` +## OUT-BAND message communication + +### Sending a message + +Out-band messages are transmitted by the transport module by copying the message +to a shared memory location and then triggering the interrupt on the receiver by +calling the `trigger_event()` in the driver API. + +``` ++--------+ +---------+ +--------+ +| MODULE | |TRANSPORT| | DRIVER | ++---+----+ +----+----+ +----+---+ + | | | + | | | + | transmit() | | + +----------------------->+-----+ | + | | | | + | | | | + | | | Copy message to | + | | | Shared memory | + | | | | + | | | | + | |<----+ | + | | trigger_event() | + | +------------------------->+----+ + | | | | + | | | |raise interrupt on + | | | |the receiver + | | | | + | | return status |<---+ + | return status |<-------------------------+ + |<-----------------------+ | + | | | + | | | + | | | + | | | + | | | + | | | +``` + +### Receiving a message + +When a message is received the transport module is signalled by the driver +module. The transport module then retrieves the message by reading the shared +memory. The message is stored in a local read buffer and the length of the +message header and the payload is verified and then the recipient module is +signalled by using `signal_message()` function from the signal API. The +recipient module then retrieves the message header and payload from the +transport module and then processes the message. + +``` + +--------+ +---------+ +--------+ + | DRIVER | |TRANSPORT| | MODULE | + +---+----+ +----+----+ +----+---+ + | | | + Interrupt | | | +----------->+---+ | | + | | isr() | | + | | | | + |<--+ | | + | signal_message() | | + +------------------------------->+----+ | + | | |Check mailbox status | + | | |Copy the message header | + | | |Verify & copy the payload | + | |<---+ | + | | signal_message() | + | +------------------------------->| + | | return status | + | return status |<-------------------------------+ + |<-------------------------------+ | + | | get_message_header() | + | |<-------------------------------+ + | | get_payload() | + | |<-------------------------------+ + | | +------+ + | | | | + | | | | Process the message + | |transport_release_channel_lock()| | + | | or transport_respond() |<-----+ + | |<-------------------------------+ + | | return status | + | +------------------------------->| + | | | + +``` + +## Fast Channels communication + +The transport module also supports SCMI Fast Channels communication. Modules +that want to use this mode of communication can bind to the fast channels API +implemented in the transport module - `MOD_TRANSPORT_API_IDX_FAST_CHANNELS` + +The client module must call the functions implemented in the above mentioned API +to retrieve the fast channel and provide a function to the driver(that supports +fast channels) that needs to called back when a message is received on the fast +channel. So, when a message is received on the fast channel, the driver calls +the function implemented in the client module(that was previously registered as +a callback function for the corresponding fast channel). + +``` ++--------+ +----------+ +--------+ +-------+ +| Module | | Transport| | Driver | | Agent | ++----+---+ +-----+----+ +----+---+ +---+---+ + | | | | + | | | | + | | | | + | mod_transport_get_fch() | | | + +--------------------------------------->| driver->get_fch() | | + | +-------------------------------->| | + | | | | + | | return | | + | return |<--------------------------------+ | + |<---------------------------------------+ | | + | | | | + | | | | + | | | | + | | | | + | mod_transport_fch_register_callback() | | | + +--------------------------------------->| driver->fch_register_callback() | | + | +-------------------------------->| | + | | | | + | | return | | + | return |<--------------------------------+ | + |<---------------------------------------+ | +---+ + | | | | | write_fch_memory + | | | Interrupt |<--+ + | fch_callback() | |<--------------------+ + |<---------------------------------------+---------------------------------+ | + | return | | | + +----------------------------------------+-------------------------------->| | + | | | | +``` + +# Use + +In order to send/receive in-band messages, the following dependencies are +required: +* In-band message support enabled in the firmware. + +In order to use SCMI Fast channels communication, the following dependencies are +required: +* Fast Channels message support enabled in the firmware. + +## Firmware messages + +In order to send firmware message, a module needs to bind to the +`mod_transport_firmware_api` and call `transmit()` function. + +## SCMI messages + +Transmission and reception of SCMI messages is handled by the scmi module which +in-turn uses the transport module. So, if a module needs to send an scmi message, +it needs to implement the interfaces defined by the scmi module and call the +`scmi_send_message()` function. + +## Message reception + +The transport module defines the signal interface which must be implemented by +the module so that it can be notified on receiving a message. + +## Fast Channel Messages + +A driver that supports Fast channels communication is required in order to use +this feature. Also the client module must implement a function that should be +used as callback for a particular fast channel. This fast channel needs to be +provided to the driver via the transport module's Fast Channels interface. + +# Configuration Example + +The following example configures the transport module to be used by the scmi +module to send and receive scmi messages via in-band communication and another +module to send and receive firmware messages via out-band communication using +shared memory. + +```C + +static const struct fwk_element transport_element_table[] = { + [0] = { + .name = "SCP2MCP_SCMI_TRANSPORT", + .data = &(( + struct mod_transport_channel_config) { + .transport_type = MOD_TRANSPORT_CHANNEL_TRANSPORT_TYPE_IN_BAND, + .channel_type = MOD_TRANSPORT_CHANNEL_TYPE_REQUESTER, + .in_band_mailbox_size = SCP_SCMI_PAYLOAD_SIZE, + .driver_id = + FWK_ID_SUB_ELEMENT_INIT( + FWK_MODULE_IDX_MHU2, + SCP_PLATFORM_MHU_DEVICE_IDX_SCP2MCP, + 0), + .driver_api_id = + FWK_ID_API_INIT( + FWK_MODULE_IDX_MHU2, + 1), + }), + }, + [1] = { + .name = "SCP2MCP_FIRMWARE_TRANSPORT", + .data = &(( + struct mod_transport_channel_config) { + .transport_type = MOD_TRANSPORT_CHANNEL_TRANSPORT_TYPE_OUT_BAND, + .channel_type = MOD_TRANSPORT_CHANNEL_TYPE_COMPLETER, + .policies = MOD_TRANSPORT_POLICY_INIT_MAILBOX, + .out_band_mailbox_address = (uintptr_t) SCP_PAYLOAD_NS_A2P_BASE, + .out_band_mailbox_size = SCP_PAYLOAD_SIZE, + .signal_api_id = FWK_ID_API_INIT( + FWK_MODULE_IDX_TEST, + 0), + .driver_id = + FWK_ID_SUB_ELEMENT_INIT( + FWK_MODULE_IDX_MHU2, + SCP_PLATFORM_MHU_DEVICE_IDX_SCP2MCP, + 1), + .driver_api_id = + FWK_ID_API_INIT( + FWK_MODULE_IDX_MHU2, + 1), + }), + }, + [2] = { + .name = "SCP2MCP_EVENT", + .data = &(( + struct mod_transport_channel_config) { + .transport_type = MOD_TRANSPORT_CHANNEL_TRANSPORT_TYPE_NONE, + .signal_api_id = FWK_ID_API_INIT( + FWK_MODULE_IDX_TEST, + 0), + .driver_id = + FWK_ID_SUB_ELEMENT_INIT( + FWK_MODULE_IDX_MHU2, + SCP_PLATFORM_MHU_DEVICE_IDX_SCP2MCP, + 2), + .driver_api_id = + FWK_ID_API_INIT( + FWK_MODULE_IDX_MHU2, + 1), + }), + }, + [3] = { 0 }, +}; + +static const struct fwk_element *transport_get_element_table(fwk_id_t module_id) +{ + unsigned int idx = 1; + struct mod_transport_channel_config *config; + + config = (struct mod_transport_channel_config *)(transport_element_table[idx].data); + config->pd_source_id = FWK_ID_ELEMENT( + FWK_MODULE_IDX_POWER_DOMAIN, + platform_get_core_count() + platform_get_cluster_count() + + PD_STATIC_DEV_IDX_SYSTOP); + + return transport_element_table; +} + +const struct fwk_module_config config_transport = { + .elements = FWK_MODULE_DYNAMIC_ELEMENTS(transport_get_element_table), +}; + +``` diff --git a/module/transport/include/internal/transport.h b/module/transport/include/internal/transport.h new file mode 100644 index 0000000000000000000000000000000000000000..008fec9d0e4ac1d6bb797ef4542ea33003f7821d --- /dev/null +++ b/module/transport/include/internal/transport.h @@ -0,0 +1,27 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2022, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef TRANSPORT_INTERNAL_H +#define TRANSPORT_INTERNAL_H + +#include + +#define MOD_TRANSPORT_MAX_CHANNELS 8 + +#define MOD_TRANSPORT_MAILBOX_STATUS_FREE_POS 0 +#define MOD_TRANSPORT_MAILBOX_STATUS_FREE_MASK \ + (UINT32_C(0x1) << MOD_TRANSPORT_MAILBOX_STATUS_FREE_POS) + +#define MOD_TRANSPORT_MAILBOX_FLAGS_IENABLED_POS 0 +#define MOD_TRANSPORT_MAILBOX_FLAGS_IENABLED_MASK \ + (UINT32_C(0x1) << MOD_TRANSPORT_MAILBOX_FLAGS_IENABLED_POS) + +#define MOD_TRANSPORT_MAILBOX_STATUS_ERROR_POS 1 +#define MOD_TRANSPORT_MAILBOX_STATUS_ERROR_MASK \ + (UINT32_C(0x1) << MOD_TRANSPORT_MAILBOX_STATUS_ERROR_POS) + +#endif /* TRANSPORT_INTERNAL_H */ diff --git a/module/transport/include/mod_transport.h b/module/transport/include/mod_transport.h new file mode 100644 index 0000000000000000000000000000000000000000..83caadbd90dcfc5950338ef5528341c192d8ee62 --- /dev/null +++ b/module/transport/include/mod_transport.h @@ -0,0 +1,561 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2022, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * Transport HAL module + */ + +#ifndef MOD_TRANSPORT_H +#define MOD_TRANSPORT_H + +#include +#include +#include +#include +#include + +#include +#include +#include + +/*! + * \addtogroup GroupModules Modules + * @{ + */ + +/*! + * \defgroup GroupTransport Transport + * + * \brief HAL Module used to provide transport for inter-processor messages + * + * + * \details This module can bind to different transport driver modules like i2c, + * mhu2, mhu3, etc and provides a transport agnostic HAL for the other modules + * to send and receive messages. + * @{ + */ + +/*! + * \brief structure used for sending & receiving messages + */ +struct mod_transport_buffer { + /*! Reserved field, must be zero */ + uint32_t reserved0; + /*! Channel status */ + volatile uint32_t status; + /*! Implementation defined field */ + uint64_t reserved1; + /*! Channel flags */ + uint32_t flags; + /*! Length in bytes of the message header and payload */ + volatile uint32_t length; + /*! Message header field */ + uint32_t message_header; + /*! Message payload */ + uint32_t payload[]; +}; + +/*! Interrupt mode enable flag position */ +#define MOD_TRANSPORT_FLAGS_IENABLED_POS 0 +/*! Interrupt mode enable bit mask */ +#define MOD_TRANSPORT_FLAGS_IENABLED_MASK \ + (UINT32_C(0x1) << MOD_TRANSPORT_FLAGS_IENABLED_POS) + +/*! + * \name Channel policies + * + * \details These policies define attributes that affect how the channel is + * treated + * + * @{ + */ + +/*! No policies */ +#define MOD_TRANSPORT_POLICY_NONE ((uint32_t)0) + +/*! This channel is secure */ +#define MOD_TRANSPORT_POLICY_SECURE ((uint32_t)(1U << 0)) + +/*! + * The mailbox for this channel requires initialization. Only relevant for + * out-band type transport channels. + */ +#define MOD_TRANSPORT_POLICY_INIT_MAILBOX ((uint32_t)(1U << 1)) + +/*! + * @} + */ + +/*! + * \brief Channel type + * + * \details Defines the role of an entity in a channel + */ +enum mod_transport_channel_type { + /*! Requester channel */ + MOD_TRANSPORT_CHANNEL_TYPE_REQUESTER, + + /*! Completer channel */ + MOD_TRANSPORT_CHANNEL_TYPE_COMPLETER, + + /*! Channel type count */ + MOD_TRANSPORT_CHANNEL_TYPE_COUNT, +}; + +/*! + * \brief Channel transport type + * + * \details Defines the type of transport used by the channel + */ +enum mod_transport_channel_transport_type { + /*! Out-band transport - SMT */ + MOD_TRANSPORT_CHANNEL_TRANSPORT_TYPE_OUT_BAND, + +#ifdef BUILD_HAS_INBAND_MSG_SUPPORT + /*! In-band transport - MHUv2, MHUv3, I2C, etc*/ + MOD_TRANSPORT_CHANNEL_TRANSPORT_TYPE_IN_BAND, +#endif + + /*! Trigger interrupt only */ + MOD_TRANSPORT_CHANNEL_TRANSPORT_TYPE_NONE, + +#ifdef BUILD_HAS_FAST_CHANNELS + /*! Fast Channel transport */ + MOD_TRANSPORT_CHANNEL_TRANSPORT_TYPE_FAST_CHANNELS, +#endif + + /*! Channel transport type count */ + MOD_TRANSPORT_CHANNEL_TRANSPORT_TYPE_COUNT, +}; + +/*! + * \brief Channel config. + */ +struct mod_transport_channel_config { + /*! Channel transport type (In-band, Out-band, etc.) */ + enum mod_transport_channel_transport_type transport_type; + + /*! Channel role (requester or completer) */ + enum mod_transport_channel_type channel_type; + + /*! + * Out-band shared mailbox address. Only relevant for out-band + * transport type. + */ + uintptr_t out_band_mailbox_address; + + /*! + * Out-band shared mailbox size in bytes. Only relevant for out-band + * transport type. + */ + size_t out_band_mailbox_size; + + /*! + * Internal read & write mailbox size in bytes. Only relevant for + * in-band transport type. + */ + size_t in_band_mailbox_size; + + /*! + * Identifier of the power domain that this channel depends on. + * Applicable for out-band transport channels only. + */ + fwk_id_t pd_source_id; + + /*! + * Identifier of the API to bind to signal message/error for Firmware + * channels. This field is irrelevant for channels that are used for + * SCMI messages. + */ + fwk_id_t signal_api_id; + + /*! Channel policies */ + uint32_t policies; + + /*! Identifier of the driver */ + fwk_id_t driver_id; + + /*! Identifier of the driver API to bind to */ + fwk_id_t driver_api_id; +}; + +#ifdef BUILD_HAS_FAST_CHANNELS +/*! + * \brief Data structure encapsulating address(es) and length of a fast channel + * between two components + */ +struct fast_channel_addr { + /*! Address as seen by the firmware running on current processor */ + uintptr_t local_view_address; + /*! Address as seen by the firmware/OS running on target processor */ + uintptr_t target_view_address; + /*! Length of the fast channel in bytes */ + size_t length; +}; +#endif + +/*! + * \brief Driver API (Implemented by the driver) + * + * \details Interface used for Transport -> driver communication + */ + +struct mod_transport_driver_api { +#ifdef BUILD_HAS_INBAND_MSG_SUPPORT + /*! + * \brief Send in-band message using the driver + * + * \param message Pointer to the message struct + * \param device_id Device identifier + * + * \retval ::FWK_SUCCESS The operation succeeded + * \return One of the standard error codes for implementation-defined + * errors + */ + int (*send_message)( + struct mod_transport_buffer *message, + fwk_id_t device_id); + + /*! + * \brief Retrieve the in-band message from the driver + * + * \param[out] message Pointer to the message struct + * \param device_id Device identifier + * + * \retval ::FWK_SUCCESS The operation succeeded + * \return One of the standard error codes for implementation-defined + * errors + */ + int ( + *get_message)(struct mod_transport_buffer *message, fwk_id_t device_id); +#endif + + /*! + * \brief Raise an interrupt on the receiver + * + * \param device_id Device identifier + * + * \retval ::FWK_SUCCESS The operation succeeded + * \return One of the standard error codes for implementation-defined + * errors + */ + int (*trigger_event)(fwk_id_t device_id); + +#ifdef BUILD_HAS_FAST_CHANNELS + /*! + * \brief Get fast channel. + * + * \param fch_id fast channel identifier + * \param[out] fch Pointer to the requested fast channel + * + * \retval ::FWK_SUCCESS The operation succeeded. + */ + int (*get_fch)(fwk_id_t fch_id, struct fast_channel_addr *fch); + + /*! + * \brief Register a callback function in the driver + * + * \param fch_id fast channel identifier + * \param param Context-specific value + * \param fch_callback Pointer to the callback function + * + * \retval ::FWK_SUCCESS The operation succeeded. + */ + int (*fch_register_callback)( + fwk_id_t fch_id, + uintptr_t param, + void (*fch_callback)(uintptr_t param)); +#endif +}; + +/*! + * \brief Driver input API (Implemented by the transport module) + * + * \details Interface used for driver -> Transport communication. + */ +struct mod_transport_driver_input_api { + /*! + * \brief Signal an incoming message + * + * \param channel_id Channel identifier + * + * \retval ::FWK_SUCCESS The operation succeeded. + * \return One of the standard error codes for implementation-defined + * errors. + */ + int (*signal_message)(fwk_id_t channel_id); +}; + +/*! + * \brief Firmware transport API + * + * \details Interface used for Firmware messages. + */ +struct mod_transport_firmware_api { + /*! + * \brief Check whether a channel is secure or non-secure. + * + * \param channel_id Channel identifier. + * \param[out] secure Channel security state. True if the channel + * is secure, or false if it is non-secure. + * + * \retval ::FWK_SUCCESS The operation succeeded. + * \retval ::FWK_E_PARAM An invalid parameter was encountered: + * - The `secure` parameter was a null pointer value. + * \return One of the standard error codes for implementation-defined + * errors. + */ + int (*get_secure)(fwk_id_t channel_id, bool *secure); + + /*! + * \brief Get the maximum permitted payload size of a channel. + * + * \param channel_id Channel identifier. + * \param[out] size Maximum payload size in bytes. + * + * \retval ::FWK_SUCCESS The operation succeeded. + * \retval ::FWK_E_PARAM An invalid parameter was encountered: + * - The `size` parameter was a null pointer value. + * \return One of the standard error codes for implementation-defined + * errors. + */ + + int (*get_max_payload_size)(fwk_id_t channel_id, size_t *size); + + /*! + * \brief Get the message header from a channel. + * + * \param channel_id Channel identifier. + * \param[out] message_header message header. + * + * \retval ::FWK_SUCCESS The operation succeeded. + * \retval ::FWK_E_PARAM An invalid parameter was encountered: + * - The `message_header` parameter was a null pointer value. + * \retval ::FWK_E_ACCESS No message is available to read. + * \return One of the standard error codes for implementation-defined + * errors. + */ + int (*get_message_header)(fwk_id_t channel_id, uint32_t *message_header); + + /*! + * \brief Get the payload from a channel. + * + * \param channel_id Channel identifier. + * \param[out] payload Pointer to the payload. + * \param[out] size Payload size. May be NULL, in which case the + * parameter should be ignored. + * + * \retval ::FWK_SUCCESS The operation succeeded. + * \retval ::FWK_E_PARAM An invalid parameter was encountered: + * - The `payload` parameter was a null pointer value. + * - The `size` parameter was a null pointer value. + * \retval ::FWK_E_ACCESS No message is available to read. + * \return One of the standard error codes for implementation-defined + * errors. + */ + int (*get_payload)(fwk_id_t channel_id, const void **payload, size_t *size); + + /*! + * \brief Write part of a payload to a channel. + * + * \param channel_id Channel identifier. + * \param offset Offset to begin writing at. + * \param payload Payload data to write. + * \param size Size of the payload data. + * + * \retval ::FWK_SUCCESS The operation succeeded. + * \retval ::FWK_E_PARAM An invalid parameter was encountered: + * - The `payload` parameter was a null pointer value. + * - The offset and size provided are not within the bounds of the + * payload area. + * \retval ::FWK_E_ACCESS No message available to respond to. + * \return One of the standard error codes for implementation-defined + * errors. + */ + int (*write_payload)( + fwk_id_t channel_id, + size_t offset, + const void *payload, + size_t size); + + /*! + * \brief Respond to message on a channel. + * + * \param channel_id Channel identifier. + * \param payload Payload data to write, or NULL if a payload has already + * been written. + * \param size Size of the payload source. + * + * \retval ::FWK_SUCCESS The operation succeeded. + * \retval ::FWK_E_SUPPORT In-band message not supported. + * \return One of the standard error codes for implementation-defined + * errors. + */ + int (*respond)(fwk_id_t channel_id, const void *payload, size_t size); + + /*! + * \brief Send a message on a channel. + * + * \param channel_id Channel identifier. + * \param message_header Message header. + * \param payload Payload data to write. + * \param size Size of the payload source. + * \param request_ack_by_interrupt flag to select whether acknowledgement + * interrupt is required for this message. + * + * \retval ::FWK_SUCCESS The operation succeeded. + * \retval ::FWK_E_BUSY Previous message was not read by agent/platform + * \retval ::FWK_E_SUPPORT In-band message not supported. + * \return One of the standard error codes for implementation-defined + * errors. + */ + int (*transmit)( + fwk_id_t channel_id, + uint32_t message_header, + const void *payload, + size_t size, + bool request_ack_by_interrupt); + + /*! + * \brief Release the transport channel context lock. + * + * \param channel_id Transport channel identifier. + * + * \retval ::FWK_SUCCESS The operation succeeded. + */ + int (*release_transport_channel_lock)(fwk_id_t channel_id); + + /*! + * \brief Trigger interrupt on receiver using the driver. + * + * \param channel_id Transport channel identifier. + * + * \retval ::FWK_SUCCESS The operation succeeded. + * \return One of the standard error codes for implementation-defined + * errors + */ + int (*trigger_interrupt)(fwk_id_t channel_id); +}; + +/*! + * \brief Firmware Signal API + * + * \details Interface used to signal Firmware messages/errors. + */ +struct mod_transport_firmware_signal_api { + /*! + * \brief Signal to a service that a incoming message for it has + * incorrect length and payload size and so the incoming message has + * been dropped. + * + * \note Subscribed service should call the release_transport_channel_lock() + * to free the channel. + * + * \param service_id service identifier. + * + * \retval ::FWK_SUCCESS The operation succeeded. + * \retval ::FWK_E_PARAM The service_id parameter is invalid. + * \return One of the standard error codes for implementation-defined + * errors. + */ + int (*signal_error)(fwk_id_t service_id); + + /*! + * \brief Signal to a service that a message is incoming. + * + * \param service_id Service identifier. + * + * \retval ::FWK_SUCCESS The operation succeeded. + * \retval ::FWK_E_PARAM The `service_id` parameter was not a valid system + * entity identifier. + * \return One of the standard error codes for implementation-defined + * errors. + */ + int (*signal_message)(fwk_id_t service_id); +}; + +#ifdef BUILD_HAS_FAST_CHANNELS +/*! + * \brief Fast Channels API + * + * \details Interface used for Fast Channels + */ +struct mod_transport_fast_channels_api { + /*! + * \brief Get fast channel. + * + * \param fch_id Fast channel identifier + * \param[out] fch Pointer to the requested fast channel + * + * \retval ::FWK_SUCCESS The operation succeeded. + */ + int (*transport_get_fch)(fwk_id_t fch_id, struct fast_channel_addr *fch); + + /*! + * \brief Register a callback function. + * + * \param fch_id Fast channel identifier + * \param param Context-specific value + * \param fch_callback Pointer to the callback function + * + * \retval ::FWK_SUCCESS The operation succeeded. + */ + int (*transport_fch_register_callback)( + fwk_id_t fch_id, + uintptr_t param, + void (*fch_callback)(uintptr_t param)); +}; +#endif + +/*! + * \brief Type of the interfaces exposed by the transport module. + */ +enum mod_transport_api_idx { + /*! Interface for driver module */ + MOD_TRANSPORT_API_IDX_DRIVER_INPUT, +#ifdef BUILD_HAS_MOD_SCMI + /*! Interface for scmi module */ + MOD_TRANSPORT_API_IDX_SCMI_TO_TRANSPORT, +#endif + /*! Interface for MSCP Firmware communication */ + MOD_TRANSPORT_API_IDX_FIRMWARE, +#ifdef BUILD_HAS_FAST_CHANNELS + /*! Interface for scmi protocol modules that use SCMI Fast Channels */ + MOD_TRANSPORT_API_IDX_FAST_CHANNELS, +#endif + /*! Number of defined interfaces */ + MOD_TRANSPORT_API_IDX_COUNT, +}; + +/*! + * \brief Transport notification indices. + */ +enum mod_transport_notification_idx { + /*! The out_band mailbox/channel has been initialized */ + MOD_TRANSPORT_NOTIFICATION_IDX_INITIALIZED, + + /*! Number of defined notifications */ + MOD_TRANSPORT_NOTIFICATION_IDX_COUNT +}; + +/*! + * \brief Identifier for the MOD_TRANSPORT_NOTIFICATION_IDX_INITIALIZED + * notification. + */ +static const fwk_id_t mod_transport_notification_id_initialized = + FWK_ID_NOTIFICATION_INIT( + FWK_MODULE_IDX_TRANSPORT, + MOD_TRANSPORT_NOTIFICATION_IDX_INITIALIZED); + +/*! + * @} + */ + +/*! + * @} + */ + +#endif /* MOD_TRANSPORT_H */ diff --git a/module/transport/src/mod_transport.c b/module/transport/src/mod_transport.c new file mode 100644 index 0000000000000000000000000000000000000000..7e383cf9ad90f21cfbd24184d3a871f7c5ff284e --- /dev/null +++ b/module/transport/src/mod_transport.c @@ -0,0 +1,1034 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2022, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * Transport HAL module for interfacing with transport driver modules. + */ + +#include + +#ifdef BUILD_HAS_MOD_POWER_DOMAIN +# include +#endif + +#ifdef BUILD_HAS_MOD_SCMI +# include +#endif + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define MOD_NAME "[TRANSPORT]" + +struct transport_channel_ctx { + /* Channel identifier */ + fwk_id_t id; + + /* Channel configuration data */ + struct mod_transport_channel_config *config; + + /* Channel read and write buffer areas */ + struct mod_transport_buffer *in, *out; + + /* Flag to indicate message processing in progress */ + volatile bool locked; + + /* Maximum payload size of the channel */ + size_t max_payload_size; + + /* Service bound to the channel */ + fwk_id_t service_id; + + /* Driver API */ + struct mod_transport_driver_api *driver_api; + + /* Service APIs to signal incoming messages or errors */ + union mod_transport_signal_api { +#ifdef BUILD_HAS_MOD_SCMI + /* For SCMI messages or errors */ + struct mod_scmi_from_transport_api *scmi_signal_api; +#endif + /* For Firmware messages or errors */ + struct mod_transport_firmware_signal_api *firmware_signal_api; + } transport_signal; + + /* Flag indicating the service bound to the channel is of type SCMI */ + bool is_scmi; + + /* Flag indicating that the out-band mailbox is ready */ + bool out_band_mailbox_ready; +}; + +struct transport_context { + /* Table of channel contexts */ + struct transport_channel_ctx *channel_ctx_table; + + /* Number of channels */ + unsigned int channel_count; +}; + +static struct transport_context transport_ctx; + +/* + * SCMI module Transport API + */ +static int transport_get_secure(fwk_id_t channel_id, bool *secure) +{ + struct transport_channel_ctx *channel_ctx; + + if (secure == NULL) { + fwk_unexpected(); + return FWK_E_PARAM; + } + + channel_ctx = + &transport_ctx.channel_ctx_table[fwk_id_get_element_idx(channel_id)]; + + *secure = + ((channel_ctx->config->policies & MOD_TRANSPORT_POLICY_SECURE) != + (uint32_t)0); + + return FWK_SUCCESS; +} + +static int transport_get_max_payload_size(fwk_id_t channel_id, size_t *size) +{ + struct transport_channel_ctx *channel_ctx; + + if (size == NULL) { + fwk_unexpected(); + return FWK_E_PARAM; + } + + channel_ctx = + &transport_ctx.channel_ctx_table[fwk_id_get_element_idx(channel_id)]; + + *size = channel_ctx->max_payload_size; + + return FWK_SUCCESS; +} + +static int transport_get_message_header(fwk_id_t channel_id, uint32_t *header) +{ + struct transport_channel_ctx *channel_ctx; + + if (header == NULL) { + fwk_unexpected(); + return FWK_E_PARAM; + } + + channel_ctx = + &transport_ctx.channel_ctx_table[fwk_id_get_element_idx(channel_id)]; + + fwk_assert( + channel_ctx->config->transport_type != + MOD_TRANSPORT_CHANNEL_TRANSPORT_TYPE_NONE); + + if (!channel_ctx->locked) { + return FWK_E_ACCESS; + } + + *header = channel_ctx->in->message_header; + + return FWK_SUCCESS; +} + +static int transport_get_payload( + fwk_id_t channel_id, + const void **payload, + size_t *size) +{ + struct transport_channel_ctx *channel_ctx; + + if (payload == NULL || size == NULL) { + fwk_unexpected(); + return FWK_E_PARAM; + } + + channel_ctx = + &transport_ctx.channel_ctx_table[fwk_id_get_element_idx(channel_id)]; + + fwk_assert( + channel_ctx->config->transport_type != + MOD_TRANSPORT_CHANNEL_TRANSPORT_TYPE_NONE); + + if (!channel_ctx->locked) { + return FWK_E_ACCESS; + } + + *payload = channel_ctx->in->payload; + + *size = channel_ctx->in->length - sizeof(channel_ctx->in->message_header); + + return FWK_SUCCESS; +} + +static int transport_write_payload( + fwk_id_t channel_id, + size_t offset, + const void *payload, + size_t size) +{ + struct transport_channel_ctx *channel_ctx; + + channel_ctx = + &transport_ctx.channel_ctx_table[fwk_id_get_element_idx(channel_id)]; + + fwk_assert( + channel_ctx->config->transport_type != + MOD_TRANSPORT_CHANNEL_TRANSPORT_TYPE_NONE); + + if ((payload == NULL) || + ((offset + size) > channel_ctx->max_payload_size)) { + fwk_unexpected(); + return FWK_E_PARAM; + } + + if (!channel_ctx->locked) { + return FWK_E_ACCESS; + } + + fwk_str_memcpy( + ((uint8_t *)channel_ctx->out->payload) + offset, payload, size); + + return FWK_SUCCESS; +} + +static int transport_respond( + fwk_id_t channel_id, + const void *payload, + size_t size) +{ + struct transport_channel_ctx *channel_ctx; + struct mod_transport_buffer *buffer; + enum mod_transport_channel_transport_type transport_type; + int status = FWK_SUCCESS; + unsigned int flags; + + channel_ctx = + &transport_ctx.channel_ctx_table[fwk_id_get_element_idx(channel_id)]; + + transport_type = channel_ctx->config->transport_type; + + fwk_assert(transport_type != MOD_TRANSPORT_CHANNEL_TRANSPORT_TYPE_NONE); + + if (transport_type == MOD_TRANSPORT_CHANNEL_TRANSPORT_TYPE_OUT_BAND) { + /* Use shared mailbox for out-band messages */ + buffer = ((struct mod_transport_buffer *) + channel_ctx->config->out_band_mailbox_address); + + /* Copy the header and other fields from the write buffer */ + fwk_str_memcpy( + buffer, channel_ctx->out, sizeof(struct mod_transport_buffer)); + + /* + * Copy the payload from either the write buffer or the payload + * parameter. + */ + fwk_str_memcpy( + buffer->payload, + (payload == NULL ? channel_ctx->out->payload : payload), + size); + } else { +#ifdef BUILD_HAS_INBAND_MSG_SUPPORT + /* Use internal write buffer for in-band messages */ + buffer = channel_ctx->out; + + /* Copy the payload from the payload parameter */ + if (payload != NULL) { + fwk_str_memcpy(buffer->payload, payload, size); + } +#else + FWK_LOG_ERR("%s ERROR. IN-BAND MESSAGE NOT SUPPORTED!\n", MOD_NAME); + return FWK_E_SUPPORT; +#endif + } + + /* + * NOTE: Disable interrupts for a brief period to ensure interrupts are not + * erroneously accepted in between unlocking the context, and setting + * the mailbox free bit. The agent should not interrupt during this + * period anyway, but this guard is included to protect against a + * misbehaving agent. + */ + flags = fwk_interrupt_global_disable(); + + channel_ctx->locked = false; + buffer->length = (volatile uint32_t)(sizeof(buffer->message_header) + size); + /* The mailbox status is relevant for out-band transport only */ + buffer->status |= MOD_TRANSPORT_MAILBOX_STATUS_FREE_MASK; + + fwk_interrupt_global_enable(flags); + +#ifdef BUILD_HAS_INBAND_MSG_SUPPORT + if (transport_type == MOD_TRANSPORT_CHANNEL_TRANSPORT_TYPE_IN_BAND) { + /* Send the response message using driver module API */ + status = channel_ctx->driver_api->send_message( + buffer, channel_ctx->config->driver_id); + + if (status != FWK_SUCCESS) { + return status; + } + } +#endif + + if (buffer->flags & MOD_TRANSPORT_MAILBOX_FLAGS_IENABLED_MASK) { + status = channel_ctx->driver_api->trigger_event( + channel_ctx->config->driver_id); + } + + return status; +} + +static int transport_transmit( + fwk_id_t channel_id, + uint32_t message_header, + const void *payload, + size_t size, + bool request_ack_by_interrupt) +{ + struct transport_channel_ctx *channel_ctx; + struct mod_transport_buffer *buffer; +#ifdef BUILD_HAS_INBAND_MSG_SUPPORT + int status; +#endif + enum mod_transport_channel_transport_type transport_type; + + channel_ctx = + &transport_ctx.channel_ctx_table[fwk_id_get_element_idx(channel_id)]; + + transport_type = channel_ctx->config->transport_type; + + fwk_assert(transport_type != MOD_TRANSPORT_CHANNEL_TRANSPORT_TYPE_NONE); + + if (transport_type == MOD_TRANSPORT_CHANNEL_TRANSPORT_TYPE_OUT_BAND) { + /* Use shared mailbox for out-band messages */ + buffer = ((struct mod_transport_buffer *) + channel_ctx->config->out_band_mailbox_address); + /* + * If the agent/platform has not yet read the previous message we + * abandon this transmission. We don't want to poll on the BUSY/FREE + * bit, and while it is probably safe to just overwrite the data + * the agent/platform could be in the process of reading. + */ + if ((buffer->status & MOD_TRANSPORT_MAILBOX_STATUS_FREE_MASK) == + (uint32_t)0) { + return FWK_E_BUSY; + } + } else { +#ifdef BUILD_HAS_INBAND_MSG_SUPPORT + /* Use internal write buffer for in-band messages */ + buffer = channel_ctx->out; + /* reserved fields must be set to zero */ + buffer->reserved0 = 0; + buffer->reserved1 = 0; +#else + FWK_LOG_ERR("%s ERROR. IN-BAND MESSAGES NOT SUPPORTED!\n", MOD_NAME); + return FWK_E_SUPPORT; +#endif + } + + buffer->message_header = message_header; + + if (request_ack_by_interrupt) { + buffer->flags |= MOD_TRANSPORT_MAILBOX_FLAGS_IENABLED_MASK; + } else { + buffer->flags &= ~MOD_TRANSPORT_MAILBOX_FLAGS_IENABLED_MASK; + } + + /* Copy the payload */ + if (payload != NULL && size != 0) { + fwk_str_memcpy(buffer->payload, payload, size); + } + + buffer->length = (volatile uint32_t)(sizeof(buffer->message_header) + size); + /* The mailbox status is relevant for out-band transport only */ + buffer->status &= ~MOD_TRANSPORT_MAILBOX_STATUS_FREE_MASK; + +#ifdef BUILD_HAS_INBAND_MSG_SUPPORT + if (transport_type == MOD_TRANSPORT_CHANNEL_TRANSPORT_TYPE_IN_BAND) { + /* Send the SCMI message using driver module API */ + status = channel_ctx->driver_api->send_message( + channel_ctx->out, channel_ctx->config->driver_id); + + if (status != FWK_SUCCESS) { + return status; + } + } +#endif + + /* Notify the agent/platform and return */ + return channel_ctx->driver_api->trigger_event( + channel_ctx->config->driver_id); +} + +static int transport_release_channel_lock(fwk_id_t channel_id) +{ + struct transport_channel_ctx *channel_ctx; + + channel_ctx = + &transport_ctx.channel_ctx_table[fwk_id_get_element_idx(channel_id)]; + + /* + * If the received message is a response message, then release + * the channel lock so that we can process the next message. + * + * If this is not done, then for messages that don't require client module + * to call the transport_respond() function will lead to situation + * where the channel context is locked and never released since it is the + * transport_respond() function that releases the channel context. + */ + channel_ctx->locked = false; + return FWK_SUCCESS; +} + +static int transport_trigger_interrupt(fwk_id_t channel_id) +{ + struct transport_channel_ctx *channel_ctx; + + channel_ctx = + &transport_ctx.channel_ctx_table[fwk_id_get_element_idx(channel_id)]; + + fwk_assert( + channel_ctx->config->transport_type == + MOD_TRANSPORT_CHANNEL_TRANSPORT_TYPE_NONE); + + return channel_ctx->driver_api->trigger_event( + channel_ctx->config->driver_id); +} + +#ifdef BUILD_HAS_MOD_SCMI +static const struct mod_scmi_to_transport_api + transport_mod_scmi_to_transport_api = { + .get_secure = transport_get_secure, + .get_max_payload_size = transport_get_max_payload_size, + .get_message_header = transport_get_message_header, + .get_payload = transport_get_payload, + .write_payload = transport_write_payload, + .respond = transport_respond, + .transmit = transport_transmit, + .release_transport_channel_lock = transport_release_channel_lock, + }; +#endif + +static const struct mod_transport_firmware_api transport_firmware_api = { + .get_secure = transport_get_secure, + .get_max_payload_size = transport_get_max_payload_size, + .get_message_header = transport_get_message_header, + .get_payload = transport_get_payload, + .write_payload = transport_write_payload, + .respond = transport_respond, + .transmit = transport_transmit, + .release_transport_channel_lock = transport_release_channel_lock, + .trigger_interrupt = transport_trigger_interrupt, +}; + +#ifdef BUILD_HAS_FAST_CHANNELS +static int transport_get_fch(fwk_id_t fch_id, struct fast_channel_addr *fch) +{ + struct transport_channel_ctx *channel_ctx; + + if (fch == NULL) { + return FWK_E_PARAM; + } + + channel_ctx = + &transport_ctx.channel_ctx_table[fwk_id_get_element_idx(fch_id)]; + + fwk_assert( + channel_ctx->config->transport_type == + MOD_TRANSPORT_CHANNEL_TRANSPORT_TYPE_FAST_CHANNELS); + + /* Get fast channel from the driver */ + return channel_ctx->driver_api->get_fch( + channel_ctx->config->driver_id, fch); +} + +static int transport_fch_register_callback( + fwk_id_t fch_id, + uintptr_t param, + void (*fch_callback)(uintptr_t param)) +{ + struct transport_channel_ctx *channel_ctx; + + if (fch_callback == NULL) { + return FWK_E_PARAM; + } + + channel_ctx = + &transport_ctx.channel_ctx_table[fwk_id_get_element_idx(fch_id)]; + + fwk_assert( + channel_ctx->config->transport_type == + MOD_TRANSPORT_CHANNEL_TRANSPORT_TYPE_FAST_CHANNELS); + + /* Provide callback function pointer to driver and get it registered */ + return channel_ctx->driver_api->fch_register_callback( + channel_ctx->config->driver_id, param, fch_callback); +} + +static const struct mod_transport_fast_channels_api + transport_fast_channels_api = { + .transport_get_fch = transport_get_fch, + .transport_fch_register_callback = transport_fch_register_callback, + }; +#endif + +static int transport_message_handler(struct transport_channel_ctx *channel_ctx) +{ + struct mod_transport_buffer *in, *out, *shared_memory; + enum mod_transport_channel_transport_type transport_type; + size_t payload_size; + int status; + + transport_type = channel_ctx->config->transport_type; + + /* Check if we are already processing */ + if (channel_ctx->locked) { + return FWK_E_STATE; + } + + in = channel_ctx->in; + out = channel_ctx->out; + + if (transport_type == MOD_TRANSPORT_CHANNEL_TRANSPORT_TYPE_OUT_BAND) { + shared_memory = ((struct mod_transport_buffer *) + channel_ctx->config->out_band_mailbox_address); + + if (channel_ctx->config->channel_type == + MOD_TRANSPORT_CHANNEL_TYPE_COMPLETER) { + /* + * The completer type channel is used for handling the requests. + * + * Check if we have the ownership of shared mailbox. We don't + * have the mailbox ownership if the mailbox status is 1 (free). + */ + if (shared_memory->status & + MOD_TRANSPORT_MAILBOX_STATUS_FREE_MASK) { + FWK_LOG_ERR( + "%s Mailbox ownership error on completer channel %u", + MOD_NAME, + fwk_id_get_element_idx(channel_ctx->id)); + + return FWK_E_STATE; + } + } else if ( + channel_ctx->config->channel_type == + MOD_TRANSPORT_CHANNEL_TYPE_REQUESTER) { + /* + * The requester type channel is used for handling the responses. + * + * Check if we have the ownership of shared mailbox. We don't + * have the mailbox ownership if the mailbox status is 0 (busy). + */ + if ((shared_memory->status & + MOD_TRANSPORT_MAILBOX_STATUS_FREE_MASK) == 0) { + FWK_LOG_ERR( + "%s Mailbox ownership error on requester channel %u", + MOD_NAME, + fwk_id_get_element_idx(channel_ctx->id)); + + return FWK_E_STATE; + } + } + /* + * Copy the contents from shared mailbox to internal read buffer. + * note: payload is not copied yet. + */ + fwk_str_memcpy(in, shared_memory, sizeof(struct mod_transport_buffer)); + } + /* + * Set the channel context as locked until the bound service completes + * processing the message. + */ + channel_ctx->locked = true; + +#ifdef BUILD_HAS_INBAND_MSG_SUPPORT + if (transport_type == MOD_TRANSPORT_CHANNEL_TRANSPORT_TYPE_IN_BAND) { + /* get the message from the driver */ + channel_ctx->driver_api->get_message( + in, channel_ctx->config->driver_id); + } +#endif + /* mirror contents in the read & write buffers (Payload not copied) */ + fwk_str_memcpy(out, in, sizeof(struct mod_transport_buffer)); + + /* Ensure error bit is not set */ + out->status &= ~MOD_TRANSPORT_MAILBOX_STATUS_ERROR_MASK; + + /* + * Verify: + * 1. The length is at least as large as the message header + * 2. The length, minus the size of the message header, is less than or + * equal to the maximum payload size + * + * Note: the payload size is permitted to be of size zero. + */ + if ((in->length < sizeof(in->message_header)) || + ((in->length - sizeof(in->message_header)) > + channel_ctx->max_payload_size)) { + out->status |= MOD_TRANSPORT_MAILBOX_STATUS_ERROR_MASK; + + if (channel_ctx->is_scmi) { +#ifdef BUILD_HAS_MOD_SCMI + status = + channel_ctx->transport_signal.scmi_signal_api->signal_error( + channel_ctx->service_id); +#else + FWK_LOG_INFO( + "%s Error! SCMI module not included in the build\n", MOD_NAME); + return FWK_E_SUPPORT; +#endif + } else { + status = + channel_ctx->transport_signal.firmware_signal_api->signal_error( + channel_ctx->service_id); + } + } + + if (transport_type == MOD_TRANSPORT_CHANNEL_TRANSPORT_TYPE_OUT_BAND) { + shared_memory = ((struct mod_transport_buffer *) + channel_ctx->config->out_band_mailbox_address); + + payload_size = in->length - sizeof(in->message_header); + if (payload_size != 0) { + /* Copy payload from shared memory to read buffer */ + fwk_str_memcpy(in->payload, shared_memory->payload, payload_size); + } + } + + /* Let the subscribed service handle the message */ + if (channel_ctx->is_scmi) { +#ifdef BUILD_HAS_MOD_SCMI + /* Signal the SCMI service */ + status = channel_ctx->transport_signal.scmi_signal_api->signal_message( + channel_ctx->service_id); +#else + FWK_LOG_INFO( + "%s Error! SCMI module not included in the build\n", MOD_NAME); + return FWK_E_SUPPORT; +#endif + } else { + /* Signal the service */ + status = + channel_ctx->transport_signal.firmware_signal_api->signal_message( + channel_ctx->service_id); + } + + if (status != FWK_SUCCESS) { + return FWK_E_HANDLER; + } + + return status; +} + +/* + * Driver module API + */ +static int transport_signal_message(fwk_id_t channel_id) +{ + int status; + struct transport_channel_ctx *channel_ctx; + + channel_ctx = + &transport_ctx.channel_ctx_table[fwk_id_get_element_idx(channel_id)]; + + /* + * If the channel is used for events only, then signal the module. + * since, there wouldn't be any messages for this channel. + */ + if (channel_ctx->config->transport_type == + MOD_TRANSPORT_CHANNEL_TRANSPORT_TYPE_NONE) { + /* Signal the service */ + status = + channel_ctx->transport_signal.firmware_signal_api->signal_message( + channel_ctx->service_id); + + return status; + } + + if (channel_ctx->config->transport_type == + MOD_TRANSPORT_CHANNEL_TRANSPORT_TYPE_OUT_BAND) { + if (!channel_ctx->out_band_mailbox_ready) { + /* Discard any message in the mailbox when not ready */ + FWK_LOG_ERR("%s Out-band message not valid", MOD_NAME); + + return FWK_SUCCESS; + } + } + return transport_message_handler(channel_ctx); +} + +static const struct mod_transport_driver_input_api driver_input_api = { + .signal_message = transport_signal_message, +}; + +static int transport_mailbox_init(struct transport_channel_ctx *channel_ctx) +{ + int status = FWK_SUCCESS; + + if ((channel_ctx->config->policies & MOD_TRANSPORT_POLICY_INIT_MAILBOX) != + (uint32_t)0) { + unsigned int notifications_sent; + + /* Only the completer channel should initialize the shared mailbox */ + if (channel_ctx->config->channel_type == + MOD_TRANSPORT_CHANNEL_TYPE_COMPLETER) { + /* Initialize mailbox such that the requester has ownership */ + *((struct mod_transport_buffer *) + channel_ctx->config->out_band_mailbox_address) = + (struct mod_transport_buffer){ + .status = (1U << MOD_TRANSPORT_MAILBOX_STATUS_FREE_POS) + }; + } + /* Notify that this mailbox is initialized */ + struct fwk_event transport_channel_initialized_notification = { + .id = mod_transport_notification_id_initialized, + .source_id = channel_ctx->id, + }; + + channel_ctx->out_band_mailbox_ready = true; + + status = fwk_notification_notify( + &transport_channel_initialized_notification, ¬ifications_sent); + } + return status; +} + +/* + * Framework API + */ +static int transport_init( + fwk_id_t module_id, + unsigned int element_count, + const void *data) +{ + transport_ctx.channel_ctx_table = fwk_mm_calloc( + element_count, sizeof(transport_ctx.channel_ctx_table[0])); + transport_ctx.channel_count = element_count; + + return FWK_SUCCESS; +} + +static int transport_channel_init( + fwk_id_t channel_id, + unsigned int unused, + const void *data) +{ + struct transport_channel_ctx *channel_ctx; + + channel_ctx = + &transport_ctx.channel_ctx_table[fwk_id_get_element_idx(channel_id)]; + channel_ctx->config = (struct mod_transport_channel_config *)data; + + /* Validate channel config */ + if ((channel_ctx->config->channel_type >= + MOD_TRANSPORT_CHANNEL_TYPE_COUNT) || + (channel_ctx->config->transport_type >= + MOD_TRANSPORT_CHANNEL_TRANSPORT_TYPE_COUNT)) { + fwk_unexpected(); + return FWK_E_DATA; + } + + /* Validate out-band mailbox address and size */ + if ((channel_ctx->config->transport_type == + MOD_TRANSPORT_CHANNEL_TRANSPORT_TYPE_OUT_BAND) && + ((channel_ctx->config->out_band_mailbox_address == 0) || + (channel_ctx->config->out_band_mailbox_size == 0))) { + fwk_unexpected(); + return FWK_E_DATA; + } + +#ifdef BUILD_HAS_INBAND_MSG_SUPPORT + /* Validate in-band mailbox size */ + if ((channel_ctx->config->transport_type == + MOD_TRANSPORT_CHANNEL_TRANSPORT_TYPE_IN_BAND) && + (channel_ctx->config->in_band_mailbox_size == 0)) { + fwk_unexpected(); + return FWK_E_DATA; + } +#endif + channel_ctx->id = channel_id; + + switch (channel_ctx->config->transport_type) { + case MOD_TRANSPORT_CHANNEL_TRANSPORT_TYPE_OUT_BAND: + channel_ctx->in = + fwk_mm_alloc(1, channel_ctx->config->out_band_mailbox_size); + channel_ctx->out = + fwk_mm_alloc(1, channel_ctx->config->out_band_mailbox_size); + channel_ctx->max_payload_size = + channel_ctx->config->out_band_mailbox_size - + sizeof(struct mod_transport_buffer); + break; + +#ifdef BUILD_HAS_INBAND_MSG_SUPPORT + case MOD_TRANSPORT_CHANNEL_TRANSPORT_TYPE_IN_BAND: + channel_ctx->in = + fwk_mm_alloc(1, channel_ctx->config->in_band_mailbox_size); + channel_ctx->out = + fwk_mm_alloc(1, channel_ctx->config->in_band_mailbox_size); + channel_ctx->max_payload_size = + channel_ctx->config->in_band_mailbox_size - + sizeof(struct mod_transport_buffer); + break; +#endif + + case MOD_TRANSPORT_CHANNEL_TRANSPORT_TYPE_NONE: + /* This channel must be used for sending/receiving events only */ + channel_ctx->in = NULL; + channel_ctx->out = NULL; + channel_ctx->max_payload_size = 0; + break; + +#ifdef BUILD_HAS_FAST_CHANNELS + case MOD_TRANSPORT_CHANNEL_TRANSPORT_TYPE_FAST_CHANNELS: + /* This transport channel is used for Fast channels only */ + channel_ctx->in = NULL; + channel_ctx->out = NULL; + channel_ctx->max_payload_size = 0; + break; +#endif + + default: + return FWK_E_DATA; + } + + return FWK_SUCCESS; +} + +static int transport_bind(fwk_id_t id, unsigned int round) +{ + struct transport_channel_ctx *channel_ctx; + int status; + + /* bind to driver API */ + if (round == 0) { + if (fwk_id_is_type(id, FWK_ID_TYPE_MODULE)) { + return FWK_SUCCESS; + } + channel_ctx = + &transport_ctx.channel_ctx_table[fwk_id_get_element_idx(id)]; + status = fwk_module_bind( + channel_ctx->config->driver_id, + channel_ctx->config->driver_api_id, + &channel_ctx->driver_api); + if (status != FWK_SUCCESS) { + return status; + } + } + + /* bind to module signal API */ + if (round == 1) { + if (!fwk_id_is_type(id, FWK_ID_TYPE_ELEMENT)) { + return FWK_SUCCESS; + } + + channel_ctx = + &transport_ctx.channel_ctx_table[fwk_id_get_element_idx(id)]; + +#ifdef BUILD_HAS_FAST_CHANNELS + if (channel_ctx->config->transport_type == + MOD_TRANSPORT_CHANNEL_TRANSPORT_TYPE_FAST_CHANNELS) { + /* + * Don't bind to signal API for fast channels since the + * driver module will notify the client module directly. + */ + return FWK_SUCCESS; + } +#endif + +#ifdef BUILD_HAS_MOD_SCMI + if (fwk_id_is_equal( + fwk_id_build_module_id(channel_ctx->service_id), + fwk_module_id_scmi)) { + status = fwk_module_bind( + channel_ctx->service_id, + FWK_ID_API(FWK_MODULE_IDX_SCMI, MOD_SCMI_API_IDX_TRANSPORT), + &channel_ctx->transport_signal.scmi_signal_api); + + channel_ctx->is_scmi = true; + return status; + } +#endif + status = fwk_module_bind( + channel_ctx->service_id, + channel_ctx->config->signal_api_id, + &channel_ctx->transport_signal.firmware_signal_api); + + channel_ctx->is_scmi = false; + return status; + } + + return FWK_SUCCESS; +} + +static int transport_process_bind_request( + fwk_id_t source_id, + fwk_id_t target_id, + fwk_id_t api_id, + const void **api) +{ + struct transport_channel_ctx *channel_ctx; + + enum mod_transport_api_idx api_id_type; + + /* Only allow binding to a channel (not the whole module) */ + if (!fwk_id_is_type(target_id, FWK_ID_TYPE_ELEMENT)) { + /* Tried to bind to something other than a specific channel */ + fwk_unexpected(); + return FWK_E_PARAM; + } + + channel_ctx = + &transport_ctx.channel_ctx_table[fwk_id_get_element_idx(target_id)]; + + api_id_type = (enum mod_transport_api_idx)fwk_id_get_api_idx(api_id); + + switch (api_id_type) { + case MOD_TRANSPORT_API_IDX_DRIVER_INPUT: + /* Driver input API */ + + /* + * Make sure that the element that is trying to bind to us is the + * same element that we previously bound to. + * + * NOTE: We bound to an element but a sub-element should be binding + * back to us. This means we cannot use fwk_id_is_equal() because + * the ids have different types. For now we compare the indicies + * manually. + */ + if (fwk_id_get_module_idx(channel_ctx->config->driver_id) == + fwk_id_get_module_idx(source_id) && + fwk_id_get_element_idx(channel_ctx->config->driver_id) == + fwk_id_get_element_idx(source_id)) { + *api = &driver_input_api; + } else { + /* A module that we did not bind to is trying to bind to us */ + fwk_unexpected(); + return FWK_E_ACCESS; + } + break; + +#ifdef BUILD_HAS_MOD_SCMI + case MOD_TRANSPORT_API_IDX_SCMI_TO_TRANSPORT: + /* SCMI transport API */ + *api = &transport_mod_scmi_to_transport_api; + channel_ctx->service_id = source_id; + break; +#endif + + case MOD_TRANSPORT_API_IDX_FIRMWARE: + /* transport API for Firmware messages */ + *api = &transport_firmware_api; + channel_ctx->service_id = source_id; + break; + +#ifdef BUILD_HAS_FAST_CHANNELS + case MOD_TRANSPORT_API_IDX_FAST_CHANNELS: + /* Fast Channels transport API */ + *api = &transport_fast_channels_api; + channel_ctx->service_id = source_id; + break; +#endif + + default: + /* Invalid API */ + fwk_unexpected(); + return FWK_E_PARAM; + } + + return FWK_SUCCESS; +} + +static int transport_start(fwk_id_t id) +{ + int status = FWK_SUCCESS; + struct transport_channel_ctx *channel_ctx; + + if (!fwk_id_is_type(id, FWK_ID_TYPE_ELEMENT)) { + return status; + } + + channel_ctx = &transport_ctx.channel_ctx_table[fwk_id_get_element_idx(id)]; + + if (channel_ctx->config->transport_type == + MOD_TRANSPORT_CHANNEL_TRANSPORT_TYPE_OUT_BAND) { +#ifdef BUILD_HAS_MOD_POWER_DOMAIN + /* Register for power domain state transition notifications */ + return fwk_notification_subscribe( + mod_pd_notification_id_power_state_transition, + channel_ctx->config->pd_source_id, + id); +#else + /* + * Initialize the mailbox immediately, if power domain module + * is not included in the firmware build. + */ + return transport_mailbox_init(channel_ctx); +#endif + } + return status; +} + +#ifdef BUILD_HAS_MOD_POWER_DOMAIN +static int transport_process_notification( + const struct fwk_event *event, + struct fwk_event *resp_event) +{ + struct transport_channel_ctx *channel_ctx; + int status = FWK_SUCCESS; + + channel_ctx = + &transport_ctx + .channel_ctx_table[fwk_id_get_element_idx(event->target_id)]; + + struct mod_pd_power_state_transition_notification_params *params; + + assert(fwk_id_is_equal( + event->id, mod_pd_notification_id_power_state_transition)); + fwk_assert(fwk_id_is_type(event->target_id, FWK_ID_TYPE_ELEMENT)); + + params = (struct mod_pd_power_state_transition_notification_params *) + event->params; + + if (params->state != MOD_PD_STATE_ON) { + if (params->state == MOD_PD_STATE_OFF) { + channel_ctx->out_band_mailbox_ready = false; + } + } else { + status = transport_mailbox_init(channel_ctx); + } + return status; +} +#endif + +const struct fwk_module module_transport = { + .type = FWK_MODULE_TYPE_HAL, + .api_count = (unsigned int)MOD_TRANSPORT_API_IDX_COUNT, + .notification_count = (unsigned int)MOD_TRANSPORT_NOTIFICATION_IDX_COUNT, + .init = transport_init, + .element_init = transport_channel_init, + .bind = transport_bind, + .start = transport_start, + .process_bind_request = transport_process_bind_request, +#ifdef BUILD_HAS_MOD_POWER_DOMAIN + .process_notification = transport_process_notification, +#endif +}; diff --git a/tools/cppcheck_suppress_list.txt b/tools/cppcheck_suppress_list.txt index 12f56eb72f260ca02a7fe4b1ccc1fb5e600fe614..ddde2008df774e2218351f119e529925aae04937 100755 --- a/tools/cppcheck_suppress_list.txt +++ b/tools/cppcheck_suppress_list.txt @@ -63,7 +63,7 @@ nullPointerRedundantCheck:*product/rcar/module/rcar_reg_sensor/src/mod_rcar_reg_ nullPointerRedundantCheck:*module/dmc500/src/mod_dmc500.c:60 nullPointerRedundantCheck:*module/dmc500/src/mod_dmc500.c:61 nullPointerRedundantCheck:*module/dmc500/src/mod_dmc500.c:65 -nullPointerRedundantCheck:*module/mhu2/src/mod_mhu2.c:74 +nullPointerRedundantCheck:*module/mhu2/src/mod_mhu2.c:101 nullPointerRedundantCheck:*module/pl011/src/mod_pl011.c:139 nullPointerRedundantCheck:*module/pl011/src/mod_pl011.c:140 nullPointerRedundantCheck:*module/ppu_v1/src/mod_ppu_v1.c:609