diff options
author | Stephen Glancy <sglancy@us.ibm.com> | 2018-09-13 14:05:32 -0500 |
---|---|---|
committer | Christian R. Geddes <crgeddes@us.ibm.com> | 2018-09-27 09:44:14 -0500 |
commit | 99d8a2ec0d3f4e83b1089f7358a8d930dddf2bee (patch) | |
tree | f6f52a8423c0b8f31979b2a476f3292a2f514f87 /src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4 | |
parent | 0fb82ef1a41044a7dce49adee8215e8fbf448d0e (diff) | |
download | talos-hostboot-99d8a2ec0d3f4e83b1089f7358a8d930dddf2bee.tar.gz talos-hostboot-99d8a2ec0d3f4e83b1089f7358a8d930dddf2bee.zip |
Adds insert function space helpers for LRDIMM
Change-Id: I2ad35dc3d1a72606b7a0ce72ad407fe7ce10e0c2
Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/66086
Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com>
Tested-by: HWSV CI <hwsv-ci+hostboot@us.ibm.com>
Tested-by: Hostboot CI <hostboot-ci+hostboot@us.ibm.com>
Reviewed-by: ANDRE A. MARIN <aamarin@us.ibm.com>
Reviewed-by: Louis Stermole <stermole@us.ibm.com>
Reviewed-by: Jennifer A. Stofer <stofer@us.ibm.com>
Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/66097
Tested-by: Jenkins OP Build CI <op-jenkins+hostboot@us.ibm.com>
Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com>
Tested-by: Jenkins OP HW <op-hw-jenkins+hostboot@us.ibm.com>
Reviewed-by: Christian R. Geddes <crgeddes@us.ibm.com>
Diffstat (limited to 'src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4')
-rw-r--r-- | src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/control_word_ddr4.H | 241 | ||||
-rw-r--r-- | src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/data_buffer_ddr4.H | 130 |
2 files changed, 299 insertions, 72 deletions
diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/control_word_ddr4.H b/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/control_word_ddr4.H index e35d143ad..bbef1f8c9 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/control_word_ddr4.H +++ b/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/control_word_ddr4.H @@ -46,6 +46,9 @@ namespace mss { +/// +/// @brief Control word types +/// enum control_word { // buffer control words @@ -56,6 +59,10 @@ enum control_word RCW_4BIT, RCW_8BIT, }; + +// Constexprs to make our lives easier +static constexpr uint64_t CW4_DATA_LEN = 4; +static constexpr uint64_t CW8_DATA_LEN = 8; } /// @@ -80,7 +87,7 @@ class cwTraits< mss::BCW_8BIT > // Address bits denoted by A // Data settings are set by A[7:0] - static constexpr uint64_t DATA_LEN = 8; + static constexpr uint64_t DATA_LEN = mss::CW8_DATA_LEN; // Control words are set by A[11:4] static constexpr uint64_t WORD_LEN = 4; @@ -107,7 +114,7 @@ class cwTraits< mss::BCW_4BIT > // Address bits denoted by A // Data settings are set by A[3:0] - static constexpr uint64_t DATA_LEN = 4; + static constexpr uint64_t DATA_LEN = mss::CW4_DATA_LEN; // Control words are set by A[11:4] // Word length is technically 8 @@ -136,7 +143,7 @@ class cwTraits< mss::RCW_8BIT > // Address bits denoted by A // Data settings are set by A[7:0] - static constexpr uint64_t DATA_LEN = 8; + static constexpr uint64_t DATA_LEN = mss::CW8_DATA_LEN; // Control words are set by A[12:8] // Word length is technically 5 @@ -165,7 +172,7 @@ class cwTraits< mss::RCW_4BIT > // Address bits denoted by A // Data settings are set by A[3:0] - static constexpr uint64_t DATA_LEN = 4; + static constexpr uint64_t DATA_LEN = mss::CW4_DATA_LEN; // Control words are set by A[12:4] // Word length is technically 9 @@ -215,7 +222,12 @@ struct cw_data } /// - /// @brief default ctor for attribute driven data + /// @brief default dtor + /// + ~cw_data() = default; + + /// + /// @brief default ctor /// cw_data() = default; @@ -267,16 +279,17 @@ struct cw_data /// @tparam OT the TargetType of the CCS instruction /// @param[in] i_target a DIMM target /// @param[in] i_data control word data to send -/// @param[in,out] io_inst a vector of CCS instructions we should add to -/// @param[in] i_turn_on_cke flag that states whether we want CKE on for this RCW (defaulted to true) +/// @param[in] i_sim true if in simulation mode +/// @param[in] i_turn_on_cke flag that states whether we want CKE on for this RCW +/// @param[out] o_instruction CCS instruction we created /// @return FAPI2_RC_SUCCESS if and only if ok /// template< control_word T, typename TT = cwTraits<T>, fapi2::TargetType OT > fapi2::ReturnCode control_word_engine(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, const cw_data& i_data, const bool i_sim, - std::vector< ccs::instruction_t<OT> >& io_inst, - const bool i_turn_on_cke = true) + const bool i_turn_on_cke, + ccs::instruction_t<OT>& o_instruction) { // You're probably asking "Why always turn off CKE's? What is this madness?" // Well, due to a vendor sensitivity, we need to have the CKE's off until we run RC09 at the very end @@ -285,7 +298,7 @@ fapi2::ReturnCode control_word_engine(const fapi2::Target<fapi2::TARGET_TYPE_DIM // Therefore, we want to setup all RCW commands to have CKE's off across both DIMM's // We then manually turn on the CKE's associated with a specific DIMM constexpr bool CKE_OFF = false; - ccs::instruction_t<OT> l_inst = ccs::rcd_command<OT>(i_target, i_sim, CKE_OFF); + ccs::instruction_t<OT> l_inst = ccs::rcd_command<OT>(i_target, i_sim, CKE_OFF); // Turn on the CKE's for the ranks we're not touching, if it's needed // Note: we only have the whole CKE field, not the per DIMM one by default @@ -332,10 +345,39 @@ fapi2::ReturnCode control_word_engine(const fapi2::Target<fapi2::TARGET_TYPE_DIM i_data.iv_delay, uint64_t(l_inst.arr0), uint64_t(l_inst.arr1), mss::c_str(i_target)); - - io_inst.push_back(l_inst); } + // All setup now, output it + o_instruction = l_inst; + +fapi_try_exit: + return fapi2::current_err; +} + + +/// +/// @brief Control word engine that sets the CCS instruction +/// @tparam T the buffer control word type (4 bit or 8 bit) +/// @tparam TT traits type defaults to cwTraits<T> +/// @tparam OT the TargetType of the CCS instruction +/// @param[in] i_target a DIMM target +/// @param[in] i_data control word data to send +/// @param[in] i_sim true if in simulation mode +/// @param[in,out] io_inst a vector of CCS instructions we should add to +/// @param[in] i_turn_on_cke flag that states whether we want CKE on for this RCW (defaulted to true) +/// @return FAPI2_RC_SUCCESS if and only if ok +/// +template< control_word T, typename TT = cwTraits<T>, fapi2::TargetType OT > +fapi2::ReturnCode control_word_engine(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, + const cw_data& i_data, + const bool i_sim, + std::vector< ccs::instruction_t<OT> >& io_inst, + const bool i_turn_on_cke = true) +{ + ccs::instruction_t<OT> l_inst; + FAPI_TRY(control_word_engine<T>(i_target, i_data, i_sim, i_turn_on_cke, l_inst)); + io_inst.push_back(l_inst); + fapi_try_exit: return fapi2::current_err; } @@ -347,6 +389,7 @@ fapi_try_exit: /// @tparam OT the TargetType of the CCS instruction /// @param[in] i_target a DIMM target /// @param[in] i_data_list a vector of control word data to send +/// @param[in] i_sim true if in simulation mode /// @param[in,out] io_inst a vector of CCS instructions we should add to /// @param[in] i_turn_on_cke flag that states whether we want CKE on for all RCWs in the vector (defaulted to true) /// @return FAPI2_RC_SUCCESS if and only if ok @@ -358,11 +401,11 @@ fapi2::ReturnCode control_word_engine(const fapi2::Target<fapi2::TARGET_TYPE_DIM std::vector< ccs::instruction_t<OT> >& io_inst, const bool i_turn_on_cke = true) { - if( i_data_list.empty() ) - { - FAPI_ERR("%s. cw_data vector is empty!", mss::c_str(i_target) ); - fapi2::Assert(false); - } + FAPI_ASSERT( !i_data_list.empty(), + fapi2::MSS_EMPTY_VECTOR(). + set_FUNCTION(CW_DATA_ENGINE). + set_TARGET(i_target), + "%s. cw_data vector is empty!", mss::c_str(i_target) ); for (const auto& data : i_data_list) { @@ -373,6 +416,170 @@ fapi_try_exit: return fapi2::current_err; } +///////////////////////////////////////////////// +// Now for the API related to CW information +///////////////////////////////////////////////// + +/// +/// @class cw_info +/// @brief class that represents (register/buffer) control word data as well as length and RCW vs BCW +/// @note used to store all CW data to move the knowledge of 4-bit vs 8-bit to runtime +/// +struct cw_info +{ +// Values of A12 which determines BCW vs RCW +// A12 is 1 for BCW and 0 for RCW + static constexpr bool BCW = true; + static constexpr bool RCW = false; + + // CW data + cw_data iv_cw_data; + + // Data length 4 vs 8 bits + uint64_t iv_data_len; + + // Boolean that controls BCW vs RCW - true if BCW + bool iv_is_bcw; + + /// + /// @brief default dtor + /// + ~cw_info() = default; + + /// + /// @brief default ctor + /// + cw_info() = default; + + /// + /// @brief ctor for attribute driven data + /// @param[in] i_func_space the function space number + /// @param[in] i_number register control word number + /// @param[in] i_func attribute accessor function pointer + /// @param[in] i_delay delay in cycles after current RCW + /// @param[in] i_data_len data length + /// @param[in] i_bcw buffer control word + /// + cw_info( const uint64_t i_func_space, + const uint64_t i_number, + fapi2::ReturnCode (*i_func)(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>&, uint8_t&), + const uint64_t i_delay, + const uint64_t i_data_len, + const bool i_bcw ): + iv_cw_data(i_func_space, i_number, i_func, i_delay), + iv_data_len(i_data_len), + iv_is_bcw(i_bcw) + {} + + /// + /// @brief ctor for custom data + /// @param[in] i_func_space the function space number + /// @param[in] i_number register control word number + /// @param[in] i_data RCW data to write + /// @param[in] i_delay delay in cycles after current RCW + /// @param[in] i_data_len data length + /// @param[in] i_bcw buffer control word + /// + cw_info( const uint64_t i_func_space, + const uint64_t i_number, + const uint64_t i_data, + const uint64_t i_delay, + const uint64_t i_data_len, + const bool i_bcw ): + iv_cw_data(i_func_space, i_number, i_data, i_delay), + iv_data_len(i_data_len), + iv_is_bcw(i_bcw) + {} + +}; + +/// +/// @brief Control word engine that sets the CCS instruction +/// @tparam OT the TargetType of the CCS instruction +/// @param[in] i_target a DIMM target +/// @param[in] i_info control word data and information about how to send it +/// @param[in] i_sim true if in simulation mode +/// @param[in] i_turn_on_cke flag that states whether we want CKE on for this RCW +/// @param[out] o_instruction CCS instruction we created +/// @return FAPI2_RC_SUCCESS if and only if ok +/// +template< fapi2::TargetType OT > +fapi2::ReturnCode control_word_engine(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, + const cw_info& i_info, + const bool i_sim, + const bool i_turn_on_cke, + ccs::instruction_t<OT>& o_instruction) +{ + // BCW 4-bit + if(i_info.iv_is_bcw && i_info.iv_data_len == CW4_DATA_LEN) + { + FAPI_TRY(control_word_engine<BCW_4BIT>(i_target, i_info.iv_cw_data, i_sim, i_turn_on_cke, o_instruction)); + } + // BCW 8-bit + else if(i_info.iv_is_bcw && i_info.iv_data_len == CW8_DATA_LEN) + { + FAPI_TRY(control_word_engine<BCW_8BIT>(i_target, i_info.iv_cw_data, i_sim, i_turn_on_cke, o_instruction)); + } + // RCW 4-bit + else if(!i_info.iv_is_bcw && i_info.iv_data_len == CW4_DATA_LEN) + { + FAPI_TRY(control_word_engine<RCW_4BIT>(i_target, i_info.iv_cw_data, i_sim, i_turn_on_cke, o_instruction)); + } + // RCW 8-bit + else if(!i_info.iv_is_bcw && i_info.iv_data_len == CW8_DATA_LEN) + { + FAPI_TRY(control_word_engine<RCW_8BIT>(i_target, i_info.iv_cw_data, i_sim, i_turn_on_cke, o_instruction)); + } + // Error case + else + { + FAPI_ASSERT(false, + fapi2::MSS_INVALID_CW_ENCODING() + .set_CW_DATA_LEN(i_info.iv_data_len) + .set_BCW(i_info.iv_is_bcw) + .set_TARGET(i_target), + "%s data_len: %u and %s are an invalid combination", + mss::c_str(i_target), i_info.iv_data_len, i_info.iv_is_bcw ? "BCW" : "RCW"); + } + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Control word engine that sets the CCS instruction +/// @tparam OT the TargetType of the CCS instruction +/// @param[in] i_target a DIMM target +/// @param[in] i_info_list a vector of control word data to send +/// @param[in] i_sim true if in simulation mode +/// @param[in,out] io_inst a vector of CCS instructions we should add to +/// @param[in] i_turn_on_cke flag that states whether we want CKE on for all RCWs in the vector (defaulted to true) +/// @return FAPI2_RC_SUCCESS if and only if ok +/// +template< fapi2::TargetType OT > +fapi2::ReturnCode control_word_engine(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, + const std::vector<cw_info>& i_info_list, + const bool i_sim, + std::vector< ccs::instruction_t<OT> >& io_inst, + const bool i_turn_on_cke = true) +{ + FAPI_ASSERT( !i_info_list.empty(), + fapi2::MSS_EMPTY_VECTOR(). + set_FUNCTION(CW_INFO_ENGINE). + set_TARGET(i_target), + "%s. cw_info vector is empty!", mss::c_str(i_target) ); + + for (const auto& l_info : i_info_list) + { + ccs::instruction_t<OT> l_inst; + FAPI_TRY( control_word_engine(i_target, l_info, i_sim, i_turn_on_cke, l_inst) ); + io_inst.push_back(l_inst); + } + +fapi_try_exit: + return fapi2::current_err; +} + }// mss #endif diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/data_buffer_ddr4.H b/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/data_buffer_ddr4.H index 638122ea6..db26abc36 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/data_buffer_ddr4.H +++ b/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/data_buffer_ddr4.H @@ -73,6 +73,9 @@ enum db02_def : size_t FUNC_SPACE_6 = 6, FUNC_SPACE_7 = 7, + // From DB02 spec - F[3:0]BC7x control word + MAX_FUNC_SPACE = 7, + // 4 bit BCWs DQ_RTT_NOM_CW = 0x0, DQ_RTT_WR_CW = 0x1, @@ -125,89 +128,106 @@ enum command : size_t /// /// @brief Sets the function space for the BCW -/// @tparam T the functon space number we want /// @param[in] i_target a DIMM target +/// @param[in] i_func_space the functon space number we want /// @param[in,out] io_inst a vector of CCS instructions we should add to /// @return FAPI2_RC_SUCCESS if and only if ok /// -template< uint64_t T > inline fapi2::ReturnCode function_space_select(const fapi2::Target< fapi2::TARGET_TYPE_DIMM >& i_target, + const uint64_t i_func_space, std::vector< ccs::instruction_t<fapi2::TARGET_TYPE_MCBIST> >& io_inst) { - // From DB02 spec - F[3:0]BC7x control word - constexpr size_t MAX_FUNC_SPACE = 7; - - uint8_t l_sim = 0; - mss::is_simulation(l_sim); - - // Function spaces are typically user selected. - // Sometimes function spaces are selected based on rank number - // or MDQ lane number which currently are also user inputs. - - // We assert out for user programming erros - static_assert( T <= MAX_FUNC_SPACE, "Invalid function space selection received. Must be <= 7"); + FAPI_ASSERT(i_func_space <= MAX_FUNC_SPACE, + fapi2::MSS_LRDIMM_FUNC_SPACE_OUT_OF_RANGE() + .set_TARGET(i_target) + .set_MAX_FUNC_SPACE(MAX_FUNC_SPACE) + .set_FUNC_SPACE(i_func_space), + "%s function space (%u) greater than maximum range (%u)", + mss::c_str(i_target), i_func_space, MAX_FUNC_SPACE); // function space bits for the function space selector are // don't cares (XXX). We choose 0 for simplicity. - cw_data l_data( FUNC_SPACE_0, FUNC_SPACE_SELECT_CW, T, mss::tmrd() ); + { + uint8_t l_sim = 0; + mss::is_simulation(l_sim); - FAPI_TRY( control_word_engine<BCW_8BIT>(i_target, l_data, l_sim, io_inst), - "%s. Failed control_word_engine for 8-bit BCW (F%dBC%02lxX)", - mss::c_str(i_target), uint8_t(l_data.iv_func_space), uint8_t(l_data.iv_number) ); + cw_data l_data( FUNC_SPACE_0, FUNC_SPACE_SELECT_CW, i_func_space, mss::tmrd() ); - // I don't know what already existed in this ccs instruction vector beforehand so - // I use the back() method to access the last added ccs instruction of interest - FAPI_INF("%s. F%dBC%02lx ccs inst 0x%016llx:0x%016llx, data: %d", - mss::c_str(i_target), uint8_t(l_data.iv_func_space), uint8_t(l_data.iv_number), - uint64_t(io_inst.back().arr0), uint64_t(io_inst.back().arr1), uint8_t(l_data.iv_data) ); + FAPI_TRY( control_word_engine<BCW_8BIT>(i_target, l_data, l_sim, io_inst), + "%s. Failed control_word_engine for 8-bit BCW (F%dBC%02lxX)", + mss::c_str(i_target), uint8_t(l_data.iv_func_space), uint8_t(l_data.iv_number) ); + + // I don't know what already existed in this ccs instruction vector beforehand so + // I use the back() method to access the last added ccs instruction of interest + FAPI_INF("%s. F%dBC%02lx ccs inst 0x%016llx:0x%016llx, data: %d", + mss::c_str(i_target), uint8_t(l_data.iv_func_space), uint8_t(l_data.iv_number), + uint64_t(io_inst.back().arr0), uint64_t(io_inst.back().arr1), uint8_t(l_data.iv_data) ); + } fapi_try_exit: return fapi2::current_err; } /// -/// @brief Sets the function space for the BCW -/// @param[in] i_target a DIMM target +/// @brief Inserts a function space selector into a vector of cw_info functions /// @param[in] i_func_space the functon space number we want -/// @param[in,out] io_inst a vector of CCS instructions we should add to +/// @param[in] i_iterator an iterator to a vector of cw_info structures +/// @param[in,out] io_vector vector in which to insert the function space selector /// @return FAPI2_RC_SUCCESS if and only if ok /// -inline fapi2::ReturnCode function_space_select(const fapi2::Target< fapi2::TARGET_TYPE_DIMM >& i_target, - const uint64_t i_func_space, - std::vector< ccs::instruction_t<fapi2::TARGET_TYPE_MCBIST> >& io_inst) +inline fapi2::ReturnCode insert_function_space_select(const uint64_t i_func_space, + const std::vector< cw_info >::iterator& i_iterator, + std::vector< cw_info >& io_vector) { - // From DB02 spec - F[3:0]BC7x control word - constexpr size_t MAX_FUNC_SPACE = 7; - - if( i_func_space > MAX_FUNC_SPACE ) + FAPI_ASSERT(i_func_space <= MAX_FUNC_SPACE, + fapi2::MSS_LRDIMM_INSERT_FUNC_SPACE_OUT_OF_RANGE() + .set_MAX_FUNC_SPACE(MAX_FUNC_SPACE) + .set_FUNC_SPACE(i_func_space), + "function space (%u) greater than maximum range (%u)", + i_func_space, MAX_FUNC_SPACE); { - // Function spaces are typically user selected. - // Sometimes function spaces are selected based on rank number - // or MDQ lane number which currently are also user inputs. - - // We assert out for user programming erros - FAPI_ERR("%s. Invalid function space selection: %d, max valid function space is %d", - mss::c_str(i_target), i_func_space, MAX_FUNC_SPACE); - - fapi2::Assert(false); + constexpr uint64_t FUNC_SPACE_LEN = 8; + cw_info l_info( FUNC_SPACE_0, FUNC_SPACE_SELECT_CW, i_func_space, mss::tmrd(), FUNC_SPACE_LEN, cw_info::BCW ); + io_vector.insert(i_iterator, l_info); } + return fapi2::FAPI2_RC_SUCCESS; - uint8_t l_sim = 0; - mss::is_simulation(l_sim); +fapi_try_exit: + return fapi2::current_err; +} - // function space bits for the function space selector are - // don't cares (XXX). We choose 0 for simplicity. - cw_data l_data( FUNC_SPACE_0, FUNC_SPACE_SELECT_CW, i_func_space, mss::tmrd() ); +/// +/// @brief Inserts all needed function space selects into a vector of cw_info functions +/// @param[in,out] io_vector vector in which to insert the function space selector +/// @return FAPI2_RC_SUCCESS if and only if ok +/// +inline fapi2::ReturnCode insert_function_space_select(std::vector< cw_info >& io_vector) +{ + fapi2::buffer<uint8_t> l_func_space(FUNC_SPACE_0); - FAPI_TRY( control_word_engine<BCW_8BIT>(i_target, l_data, l_sim, io_inst), - "%s. Failed control_word_engine for 8-bit BCW (F%dBC%02lxX)", - mss::c_str(i_target), uint8_t(l_data.iv_func_space), uint8_t(l_data.iv_number) ); + // Looping on numbers here as using iterators creates memfaults due to the insert + for(uint64_t i = 0; i < io_vector.size(); ++i) + { + // If the current function space is different than our desired one... + if(l_func_space != io_vector[i].iv_cw_data.iv_func_space) + { + // Add in a CW to do the function space change + l_func_space = io_vector[i].iv_cw_data.iv_func_space; + auto l_it = io_vector.begin() + i; + FAPI_TRY(insert_function_space_select(l_func_space, l_it, io_vector)); + } + } - // I don't know what already existed in this ccs instruction vector beforehand so - // I use the back() method to access the last added ccs instruction of interest - FAPI_INF("%s. F%dBC%02lx ccs inst 0x%016llx:0x%016llx, data: %d", - mss::c_str(i_target), uint8_t(l_data.iv_func_space), uint8_t(l_data.iv_number), - uint64_t(io_inst.back().arr0), uint64_t(io_inst.back().arr1), uint8_t(l_data.iv_data) ); + // So, we always want to know what function space we're in + // The way to do that is to always return to one function space + // The LR spec recommends that we return to the default function space - function space 0 + // If the vector is not at our default function space of function space 0, return to function space 0 + if(l_func_space != FUNC_SPACE_0) + { + FAPI_TRY(insert_function_space_select(FUNC_SPACE_0, io_vector.end(), io_vector)); + } + + return fapi2::FAPI2_RC_SUCCESS; fapi_try_exit: return fapi2::current_err; |