diff options
author | Thi Tran <thi@us.ibm.com> | 2015-12-11 12:49:53 -0600 |
---|---|---|
committer | Daniel M. Crowell <dcrowell@us.ibm.com> | 2016-02-26 16:37:55 -0600 |
commit | cbad4d5317005943ccfcca132724ae9f380e0bd8 (patch) | |
tree | 18a3101e25a0cc8de0198646e71f0b9c45294a93 | |
parent | 6607738643fbe1af6e849b877765779e15298ccc (diff) | |
download | talos-hostboot-cbad4d5317005943ccfcca132724ae9f380e0bd8.tar.gz talos-hostboot-cbad4d5317005943ccfcca132724ae9f380e0bd8.zip |
L2 - p9_build_smp HWPs
Change-Id: Ic3b000e1c9844499c478e29f2d370d037a8fc262
Reviewed-on: http://gfw160.aus.stglabs.ibm.com:8080/gerrit/22704
Tested-by: Jenkins Server
Reviewed-by: Joseph J. McGill <jmcgill@us.ibm.com>
Tested-by: Auto Mirror
Tested-by: PPE CI
Tested-by: Hostboot CI
Reviewed-by: CHRISTINA L. GRAVES <clgraves@us.ibm.com>
Reviewed-by: Jennifer A. Stofer <stofer@us.ibm.com>
Reviewed-on: http://gfw160.aus.stglabs.ibm.com:8080/gerrit/24636
Reviewed-by: Daniel M. Crowell <dcrowell@us.ibm.com>
3 files changed, 1236 insertions, 41 deletions
diff --git a/src/import/chips/p9/procedures/hwp/nest/p9_build_smp.C b/src/import/chips/p9/procedures/hwp/nest/p9_build_smp.C index fc3677e26..81557b6ad 100644 --- a/src/import/chips/p9/procedures/hwp/nest/p9_build_smp.C +++ b/src/import/chips/p9/procedures/hwp/nest/p9_build_smp.C @@ -7,7 +7,7 @@ /* */ /* EKB Project */ /* */ -/* COPYRIGHT 2015 */ +/* COPYRIGHT 2015,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -20,35 +20,1071 @@ /// @file p9_build_smp.C /// @brief Perform fabric configuration (FAPI2) /// -/// @author Joe McGill <jmcgill@us.ibm.com> -/// @author Christy Graves <clgraves@us.ibm.com> +/// *HWP HWP Owner: Joe McGill <jmcgill@us.ibm.com> +/// *HWP FW Owner: Thi Tran <thi@us.ibm.com> +/// *HWP Team: Nest +/// *HWP Level: 2 +/// *HWP Consumed by: HB,FSP /// -// -// *HWP HWP Owner: Joe McGill <jmcgill@us.ibm.com> -// *HWP FW Owner: Thi Tran <thi@us.ibm.com> -// *HWP Team: Nest -// *HWP Level: 1 -// *HWP Consumed by: HB,FSP -// - //------------------------------------------------------------------------------ // Includes //------------------------------------------------------------------------------ #include <p9_build_smp.H> +#include <p9_build_smp_fbc_ab.H> +#include <p9_build_smp_epsilon.H> +#include <p9_build_smp_fbc_nohp.H> +#include <p9_build_smp_fbc_ab.H> +#include <p9_build_smp_fbc_cd.H> +extern "C" { //------------------------------------------------------------------------------ // Function definitions //------------------------------------------------------------------------------ +/// +/// @brief Calculate SMP ratio and delay settings from input SMP info. +/// Output will be written to the same in/out structure. +/// +/// @param[in/out] io_smp Input/Output p9_build_smp_system data +/// +/// @return FAPI2_RC_SUCCESS if success, else error code. +/// + fapi2::ReturnCode p9_calc_ratio_delay_settings(p9_build_smp_system& io_smp) + { + FAPI_DBG("Start"); + fapi2::ReturnCode l_rc; + + // Determine epsilon table index based on pb/core floor frequency ratio + // Breakpoint ratio: core floor 4.0, pb 2.0 (cache floor :: pb = 8/8) + if ((io_smp.freq_core_floor) >= (2 * io_smp.freq_pb)) + { + io_smp.core_floor_ratio = P9_BUILD_SMP_CORE_RATIO_8_8; + } + // breakpoint ratio: core floor 3.5, pb 2.0 (cache floor :: pb = 7/8) + else if ((4 * io_smp.freq_core_floor) >= (7 * io_smp.freq_pb)) + { + io_smp.core_floor_ratio = P9_BUILD_SMP_CORE_RATIO_7_8; + } + // breakpoint ratio: core floor 3.0, pb 2.0 (cache floor :: pb = 6/8) + else if ((2 * io_smp.freq_core_floor) >= (3 * io_smp.freq_pb)) + { + io_smp.core_floor_ratio = P9_BUILD_SMP_CORE_RATIO_6_8; + } + // breakpoint ratio: core floor 2.5, pb 2.0 (cache floor :: pb = 5/8) + else if ((4 * io_smp.freq_core_floor) >= (5 * io_smp.freq_pb)) + { + io_smp.core_floor_ratio = P9_BUILD_SMP_CORE_RATIO_5_8; + } + // breakpoint ratio: core floor 2.0, pb 2.0 (cache floor :: pb = 4/8) + else if (io_smp.freq_core_floor >= io_smp.freq_pb) + { + io_smp.core_floor_ratio = P9_BUILD_SMP_CORE_RATIO_4_8; + } + // breakpoint ratio: core floor 1.0, pb 2.0 (cache floor :: pb = 2/8) + else if ((2 * io_smp.freq_core_floor) >= io_smp.freq_pb) + { + io_smp.core_floor_ratio = P9_BUILD_SMP_CORE_RATIO_2_8; + } + // Under-range, raise error + else + { + FAPI_ASSERT(false, + fapi2::PROC_BUILD_SMP_CORE_FLOOR_FREQ_RATIO_ERR() + .set_FREQ_PB(io_smp.freq_pb) + .set_FREQ_CORE_FLOOR(io_smp.freq_core_floor), + "Unsupported core floor/PB frequency " + "ratio (=%d/%d)", io_smp.freq_core_floor, io_smp.freq_pb); + } + + FAPI_INF("Core floor to nest frequency ratio %d", io_smp.core_floor_ratio); + + + // TODO: RTC 147511 - No epsilon core ceilling data available yet. + // Need to init values in structure whenever values are available. + + // Determine table index based on pb/core ceiling frequency ratio + // Breakpoint ratio: core ceiling 4.8, pb 2.4 (cache ceiling :: pb = 8/8) + if ((io_smp.freq_core_ceiling) >= (2 * io_smp.freq_pb)) + { + io_smp.core_ceiling_ratio = P9_BUILD_SMP_CORE_RATIO_8_8; + } + // breakpoint ratio: core ceiling 4.2, pb 2.4 (cache ceiling :: pb = 7/8) + else if ((4 * io_smp.freq_core_ceiling) >= (7 * io_smp.freq_pb)) + { + io_smp.core_ceiling_ratio = P9_BUILD_SMP_CORE_RATIO_7_8; + } + // breakpoint ratio: core ceiling 3.6, pb 2.4 (cache ceiling :: pb = 6/8) + else if ((2 * io_smp.freq_core_ceiling) >= (3 * io_smp.freq_pb)) + { + io_smp.core_ceiling_ratio = P9_BUILD_SMP_CORE_RATIO_6_8; + } + // breakpoint ratio: core ceiling 3.0, pb 2.4 (cache ceiling :: pb = 5/8) + else if ((4 * io_smp.freq_core_ceiling) >= (5 * io_smp.freq_pb)) + { + io_smp.core_ceiling_ratio = P9_BUILD_SMP_CORE_RATIO_5_8; + } + // breakpoint ratio: core ceiling 2.4, pb 2.4 (cache ceiling :: pb = 4/8) + else if (io_smp.freq_core_ceiling >= io_smp.freq_pb) + { + io_smp.core_ceiling_ratio = P9_BUILD_SMP_CORE_RATIO_4_8; + } + // breakpoint ratio: core ceiling 1.2, pb 2.4 (cache ceiling :: pb = 2/8) + else if ((2 * io_smp.freq_core_ceiling) >= io_smp.freq_pb) + { + io_smp.core_ceiling_ratio = P9_BUILD_SMP_CORE_RATIO_2_8; + } + // under-range, raise error + else + { + FAPI_ASSERT(false, + fapi2::PROC_BUILD_SMP_CORE_CEILING_FREQ_RATIO_ERR() + .set_FREQ_PB(io_smp.freq_pb) + .set_FREQ_CORE_CEILING(io_smp.freq_core_ceiling), + "Unsupported core ceiling/PB frequency ratio (=%d/%d)", + io_smp.freq_core_ceiling, io_smp.freq_pb); + } + + FAPI_INF("Core ceiling to nest frequency ratio %d", io_smp.core_ceiling_ratio); + + // TODO: RTC 147511 - No CPU delay settings available yet + // Need to init values in structure whenever values are available. + + // Determine full CPU delay settings + if ((2400 * io_smp.freq_core_ceiling) >= (4800 * io_smp.freq_pb)) + { + io_smp.full_cpu_delay = P9_BUILD_SMP_CPU_DELAY_4800_2400; + } + else if ((2400 * io_smp.freq_core_ceiling) >= (4431 * io_smp.freq_pb)) + { + io_smp.full_cpu_delay = P9_BUILD_SMP_CPU_DELAY_4431_2400; + } + else if ((2400 * io_smp.freq_core_ceiling) >= (4114 * io_smp.freq_pb)) + { + io_smp.full_cpu_delay = P9_BUILD_SMP_CPU_DELAY_4114_2400; + } + else if ((2400 * io_smp.freq_core_ceiling) >= (3840 * io_smp.freq_pb)) + { + io_smp.full_cpu_delay = P9_BUILD_SMP_CPU_DELAY_3840_2400; + } + else if ((2400 * io_smp.freq_core_ceiling) >= (3338 * io_smp.freq_pb)) + { + io_smp.full_cpu_delay = P9_BUILD_SMP_CPU_DELAY_3338_2400; + } + else if ((2400 * io_smp.freq_core_ceiling) >= (3032 * io_smp.freq_pb)) + { + io_smp.full_cpu_delay = P9_BUILD_SMP_CPU_DELAY_3032_2400; + } + else + { + io_smp.full_cpu_delay = P9_BUILD_SMP_CPU_DELAY_2743_2400; + } + + FAPI_INF("CPU delay %d", io_smp.full_cpu_delay); + + // Determine nominal CPU delay settings + if ((2400 * io_smp.freq_core_nom) >= (4800 * io_smp.freq_pb)) + { + // shift to avoid equivalent index + io_smp.nom_cpu_delay = P9_BUILD_SMP_CPU_DELAY_4431_2400; + } + else if ((2400 * io_smp.freq_core_nom) >= (4431 * io_smp.freq_pb)) + { + io_smp.nom_cpu_delay = P9_BUILD_SMP_CPU_DELAY_4431_2400; + + // shift to avoid equivalent index + if (io_smp.nom_cpu_delay == io_smp.full_cpu_delay) + { + io_smp.nom_cpu_delay = P9_BUILD_SMP_CPU_DELAY_4114_2400; + } + } + else if ((2400 * io_smp.freq_core_nom) >= (4114 * io_smp.freq_pb)) + { + io_smp.nom_cpu_delay = P9_BUILD_SMP_CPU_DELAY_4114_2400; + + // shift to avoid equivalent index + if (io_smp.nom_cpu_delay == io_smp.full_cpu_delay) + { + io_smp.nom_cpu_delay = P9_BUILD_SMP_CPU_DELAY_3840_2400; + } + } + else if ((2400 * io_smp.freq_core_nom) >= (3840 * io_smp.freq_pb)) + { + io_smp.nom_cpu_delay = P9_BUILD_SMP_CPU_DELAY_3840_2400; + + // shift to avoid equivalent index + if (io_smp.nom_cpu_delay == io_smp.full_cpu_delay) + { + io_smp.nom_cpu_delay = P9_BUILD_SMP_CPU_DELAY_3338_2400; + } + } + else if ((2400 * io_smp.freq_core_nom) >= (3338 * io_smp.freq_pb)) + { + io_smp.nom_cpu_delay = P9_BUILD_SMP_CPU_DELAY_3338_2400; + + // shift to avoid equivalent index + if (io_smp.nom_cpu_delay == io_smp.full_cpu_delay) + { + io_smp.nom_cpu_delay = P9_BUILD_SMP_CPU_DELAY_3032_2400; + } + } + else if ((2400 * io_smp.freq_core_nom) >= (3032 * io_smp.freq_pb)) + { + io_smp.nom_cpu_delay = P9_BUILD_SMP_CPU_DELAY_3032_2400; + + // shift to avoid equivalent index + if (io_smp.nom_cpu_delay == io_smp.full_cpu_delay) + { + io_smp.nom_cpu_delay = P9_BUILD_SMP_CPU_DELAY_2743_2400; + } + } + else if ((2400 * io_smp.freq_core_nom) >= (2743 * io_smp.freq_pb)) + { + io_smp.nom_cpu_delay = P9_BUILD_SMP_CPU_DELAY_2743_2400; + + // shift to avoid equivalent index + if (io_smp.nom_cpu_delay == io_smp.full_cpu_delay) + { + io_smp.nom_cpu_delay = P9_BUILD_SMP_CPU_DELAY_2504_2400; + } + } + else + { + io_smp.nom_cpu_delay = P9_BUILD_SMP_CPU_DELAY_2504_2400; + } + + FAPI_INF("Nominal delay %d", io_smp.nom_cpu_delay); + + fapi_try_exit: + FAPI_DBG("End"); + return fapi2::current_err; + } + + +/// +/// @brief Fill in p9_build_smp_system structure with info such as +/// fabric configuration/frequencies/etc based on attribute settings. +/// The structure will then be used for the SMP build operation later. +/// +/// @param[out] o_smp Output p9_build_smp_system data +/// +/// @return FAPI2_RC_SUCCESS if success, else error code. +/// + fapi2::ReturnCode p9_build_smp_process_system(p9_build_smp_system& o_smp) + { + FAPI_DBG("Start"); + fapi2::ReturnCode l_rc; + const fapi2::Target<fapi2::TARGET_TYPE_SYSTEM> FAPI_SYSTEM; + uint8_t l_tempAttr = 0; + + // Get Nest freq attribute + FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_FREQ_PB, FAPI_SYSTEM, o_smp.freq_pb), + "Error getting ATTR_FREQ_PB, l_rc 0x%.8X", + (uint64_t)fapi2::current_err); + FAPI_DBG("ATTR_FREQ_PB 0x%.8X", o_smp.freq_pb); + + // Get A bus frequency attribute + FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_FREQ_A, FAPI_SYSTEM, o_smp.freq_a), + "Error getting ATTR_FREQ_A, l_rc 0x%.8X", + (uint64_t)fapi2::current_err); + FAPI_DBG("ATTR_FREQ_A 0x%.8X", o_smp.freq_a); + + // Get X bus frequency attribute + FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_FREQ_X, FAPI_SYSTEM, o_smp.freq_x), + "Error getting ATTR_FREQ_X, l_rc 0x%.8X", + (uint64_t)fapi2::current_err); + FAPI_DBG("ATTR_FREQ_X 0x%.8X", o_smp.freq_x); + + // Get core floor frequency attribute + FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_FREQ_CORE_FLOOR, FAPI_SYSTEM, + o_smp.freq_core_floor), + "Error getting ATTR_FREQ_CORE_FLOOR, l_rc 0x%.8X", + (uint64_t)fapi2::current_err); + FAPI_DBG("ATTR_FREQ_CORE_FLOOR 0x%.8X", o_smp.freq_core_floor); + + // Get core nominal frequency attribute + FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_FREQ_CORE_NOMINAL, FAPI_SYSTEM, + o_smp.freq_core_nom), + "Error getting ATTR_FREQ_CORE_NOMINAL, l_rc 0x%.8X", + (uint64_t)fapi2::current_err); + FAPI_DBG("ATTR_FREQ_CORE_NOMINAL 0x%.8X", o_smp.freq_core_nom); + + // Get core ceiling frequency attribute + FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_FREQ_CORE_CEILING, FAPI_SYSTEM, + o_smp.freq_core_ceiling), + "Error getting ATTR_FREQ_CORE_CEILING, l_rc 0x%.8X", + (uint64_t)fapi2::current_err); + FAPI_DBG("ATTR_FREQ_CORE_CEILING 0x%.8X", o_smp.freq_core_ceiling); + + // Verify the floor/nominal/ceiling frequencies + // Expect ceiling >= nominal, nominal >= floor + FAPI_ASSERT( ((o_smp.freq_core_ceiling >= o_smp.freq_core_nom) && + (o_smp.freq_core_nom >= o_smp.freq_core_floor)), + fapi2::PROC_BUILD_SMP_CORE_FREQ_RANGE_ERR() + .set_FREQ_CORE_CEILING(o_smp.freq_core_ceiling) + .set_FREQ_CORE_NOM(o_smp.freq_core_nom) + .set_FREQ_CORE_FLOOR(o_smp.freq_core_floor), + "Invalid core frequency ranges: FLOOR: 0x%.8X, NOMINAL: 0x%.8X, CEILING: 0x%.8X", + o_smp.freq_core_floor, o_smp.freq_core_nom, o_smp.freq_core_ceiling); + + // Get PCIe frequency attribute + FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_FREQ_PCIE, FAPI_SYSTEM, + o_smp.freq_pcie), + "Error getting ATTR_FREQ_PCIE, l_rc 0x%.8X", + (uint64_t)fapi2::current_err); + FAPI_DBG("ATTR_FREQ_PCIE 0x%.8X", o_smp.freq_pcie); + + // Get PB pump type attribute + FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_PROC_FABRIC_PUMP_MODE, FAPI_SYSTEM, + l_tempAttr), + "error getting ATTR_PROC_FABRIC_PUMP_MODE, l_rc 0x%.8X", + (uint64_t)fapi2::current_err); + FAPI_DBG("ATTR_PROC_FABRIC_PUMP_MODE 0x%.8X", l_tempAttr); + + switch (l_tempAttr) + { + case fapi2::ENUM_ATTR_PROC_FABRIC_PUMP_MODE_MODE1: + case fapi2::ENUM_ATTR_PROC_FABRIC_PUMP_MODE_MODE2: + o_smp.pump_mode = static_cast<p9_fab_smp_pump_mode>(l_tempAttr); + break; + + default: + FAPI_ASSERT(false, + fapi2::P9_FAB_SMP_PUMP_MODE_ATTR_ERR() + .set_ATTR_DATA(l_tempAttr), + "Invalid fabric pump mode value 0x%02X", l_tempAttr); + break; + } + + // Get Epsilon attribute + FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_PROC_EPS_TABLE_TYPE, + FAPI_SYSTEM, l_tempAttr), + "Error getting ATTR_PROC_EPS_TABLE_TYPE, l_rc 0x%.8X", + (uint64_t)fapi2::current_err); + FAPI_DBG("ATTR_PROC_EPS_TABLE_TYPE 0x%.8X", l_tempAttr); + + switch (l_tempAttr) + { + case fapi2::ENUM_ATTR_PROC_EPS_TABLE_TYPE_EPS_TYPE_LE: + case fapi2::ENUM_ATTR_PROC_EPS_TABLE_TYPE_EPS_TYPE_HE: + o_smp.eps_cfg.table_type = + static_cast<p9_fab_smp_eps_table_type>(l_tempAttr); + break; + + default: + FAPI_ASSERT(false, + fapi2::P9_FAB_SMP_EPSILON_TABLE_TYPE_ATTR_ERR() + .set_ATTR_DATA(l_tempAttr), + "Invalid epsilon table type attribute value 0x%02X", l_tempAttr); + break; + } + + // Set Guardband default value to +20% + o_smp.eps_cfg.gb_percentage = +20; + FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_PROC_EPS_GB_PERCENTAGE, FAPI_SYSTEM, + o_smp.eps_cfg.gb_percentage), + "Error setting ATTR_PROC_EPS_GB_PERCENTAGE, l_rc 0x%.8X", + (uint64_t)fapi2::current_err); + + // Get Gardband attributes + // Note: if a user makes an attribute override with CONST, it would + // override the above default value settings. This mechanism is to + // allow users to change the default settings for testings. + FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_PROC_EPS_GB_PERCENTAGE, + FAPI_SYSTEM, o_smp.eps_cfg.gb_percentage), + "Error getting ATTR_PROC_EPS_GB_PERCENTAGE, l_rc 0x%.8X", + (uint64_t)fapi2::current_err); + + FAPI_DBG("ATTR_PROC_EPS_GB_PERCENTAGE %s%d, ", + (o_smp.eps_cfg.gb_percentage >= 0) ? ("+") : ("-"), + o_smp.eps_cfg.gb_percentage); + + // Call function to calculate ratio and delay setting + FAPI_TRY(p9_calc_ratio_delay_settings(o_smp), + "p9_build_smp: p9_calc_ratio_delay_settings returns an error, " + "l_rc 0x%.8X", (uint64_t)fapi2::current_err); + + // Optic configuration + FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_PROC_FABRIC_SMP_OPTICS_MODE, FAPI_SYSTEM, + o_smp.smpOpticsMode), + "Error getting ATTR_PROC_FABRIC_SMP_OPTICS_MODE, l_rc 0x%.8X", + (uint64_t)fapi2::current_err); + + fapi_try_exit: + FAPI_DBG("End"); + return fapi2::current_err; + } + +/// +/// @brief Query all chip attribute query functions +/// (fabric configuration/node/position) +/// +/// @param[in] i_proc_chip Pointer to HWP input structure for this chip +/// @param[in] io_smp_chip Structure encapsulating single chip in SMP +/// topology +/// +/// @return FAPI2_RC_SUCCESS if success, else error code. +/// + fapi2::ReturnCode p9_build_smp_process_chip(p9_build_smp_proc_chip* i_proc_chip, + p9_build_smp_chip& io_smp_chip) + { + FAPI_DBG("Start"); + fapi2::ReturnCode l_rc; + + // Set HWP input pointer + io_smp_chip.chip = i_proc_chip; + + // Display target information for this proc + char l_targetStr[fapi2::MAX_ECMD_STRING_LEN]; + fapi2::toString(io_smp_chip.chip->this_chip, l_targetStr, + sizeof(l_targetStr)); + FAPI_INF("Target: %s", l_targetStr); + + // Get node ID attribute + FAPI_TRY(p9_fab_smp_get_node_id_attr( io_smp_chip.chip->this_chip, + io_smp_chip.node_id ), + "p9_fab_smp_get_node_id_attr() returns an error, l_rc 0x%.8X", + (uint64_t)fapi2::current_err); + + // Get chip ID attribute + FAPI_TRY(p9_fab_smp_get_chip_id_attr( io_smp_chip.chip->this_chip, + io_smp_chip.chip_id ), + "p9_fab_smp_get_chip_id_attr() returns an error, l_rc 0x%.8X", + (uint64_t)fapi2::current_err); + + fapi_try_exit: + FAPI_DBG("End"); + return fapi2::current_err; + } + + +/// +/// @brief Set chip master status (node/system) for PB operations. +/// +/// @param[in] i_first_chip_in_node First chip processed in node? +/// @param[in] i_op Procedure operation phase/mode +/// @param[in] io_smp_chip Structure encapsulating single chip in SMP +/// topology +/// @param[in] io_smp Fully specified structure encapsulating SMP +/// +/// @return FAPI2_RC_SUCCESS if success, else error code. +/// + fapi2::ReturnCode p9_build_smp_set_master_config( + const bool i_first_chip_in_node, + const p9_build_smp_operation i_op, + p9_build_smp_chip& io_smp_chip, + p9_build_smp_system& io_smp) + { + + FAPI_DBG("Start"); + fapi2::ReturnCode l_rc; + fapi2::buffer<uint64_t> l_scomData; + bool l_err = false; + + // Retrieve CURR state of node/system master designation from HW + FAPI_TRY(p9_build_smp_get_hotplug_curr_reg(io_smp_chip, true, l_scomData), + "p9_build_smp_get_hotplug_curr_reg() returns an error, l_rc 0x%.8X", + (uint64_t)fapi2::current_err); + + io_smp_chip.master_chip_sys_curr = + l_scomData.getBit<PB_HP_MODE_MASTER_CHIP_BIT>(); + io_smp_chip.master_chip_node_curr = + l_scomData.getBit<PB_HP_MODE_CHG_RATE_GP_MASTER_BIT>(); + + FAPI_DBG("Current reg: 0x%.16llX", l_scomData); + FAPI_DBG(" master_chip_sys_curr 0x%.8X, master_chip_node_curr 0x%.8X", + io_smp_chip.master_chip_sys_curr, + io_smp_chip.master_chip_node_curr); + + + // Check/set expectation for CURR/NEXT states based on HW state + // as well as input parameters + + // Call from HBI to initialize scope of HBI drawer + if (i_op == SMP_ACTIVATE_PHASE1) + { + FAPI_DBG("SMP_ACTIVATE_PHASE1"); + + // Each chip should match the flush state of the fabric logic + if (!io_smp_chip.master_chip_sys_curr || + io_smp_chip.master_chip_node_curr) + { + l_err = true; + } + else + { + // Set next state + io_smp_chip.master_chip_node_next = i_first_chip_in_node; + } + } + // Call from FSP used to stitch drawers/CCM + else if (i_op == SMP_ACTIVATE_PHASE2) + { + FAPI_DBG("SMP_ACTIVATE_PHASE2"); + // Set next state + io_smp_chip.master_chip_node_next = io_smp_chip.master_chip_node_curr; + } + // Unsupported operation + else + { + FAPI_ASSERT(false, + fapi2::PROC_BUILD_SMP_INVALID_OPERATION_ERR() + .set_OP(i_op), + "Unsupported input SMP operation 0x%.8X", i_op); + } + + // Mark system master for launching fabric reconfiguration operations + // also track which slave fabrics will be quiesced + FAPI_DBG("master_chip_sys_next 0x%.8X", io_smp_chip.chip->master_chip_sys_next); + + if (io_smp_chip.chip->master_chip_sys_next) + { + // this chip will not be quiesced, to enable switch AB + io_smp_chip.issue_quiesce_next = false; + + // in both activation scenarios, we expect that: + // - only a single chip is designated to be the new master + // - the newly designated master is currently configured + // as a master within the scope of its current enclosing fabric + if (!io_smp.master_chip_curr_set && + io_smp_chip.master_chip_sys_curr) + { + io_smp.master_chip_curr_set = true; + io_smp.master_chip_curr_node_id = io_smp_chip.node_id; + io_smp.master_chip_curr_chip_id = io_smp_chip.chip_id; + } + else + { + l_err = true; + } + } + else + { + // This chip will not be the new master, but is one now + // use it to quiesce all chips in its fabric + if (io_smp_chip.master_chip_sys_curr) + { + io_smp_chip.issue_quiesce_next = true; + } + else + { + io_smp_chip.issue_quiesce_next = false; + } + } + + // Assert if local error is set + FAPI_ASSERT(l_err == false, + fapi2::PROC_BUILD_SMP_MASTER_DESIGNATION_ERR() + .set_TARGET(io_smp_chip.chip->this_chip) + .set_OP(i_op) + .set_MASTER_CHIP_SYS_CURR(io_smp_chip.master_chip_sys_curr) + .set_MASTER_CHIP_NODE_CURR(io_smp_chip.master_chip_node_curr) + .set_MASTER_CHIP_SYS_NEXT(io_smp_chip.chip->master_chip_sys_next) + .set_MASTER_CHIP_NODE_NEXT(io_smp_chip.master_chip_node_next) + .set_SYS_RECONFIG_MASTER_SET(io_smp.master_chip_curr_set), + "Node/system master designation error"); + + fapi_try_exit: + FAPI_DBG("End"); + return fapi2::current_err; + } + +/// +/// @brief Insert chip structure into proper position within SMP model based +/// on its fabric node/chip ID +/// +/// @param[in/out] io_smp_chip Structure encapsulating single chip in +/// SMP topology. +/// @param[in] i_op Procedure operation phase/mode +/// @param[in/out] io_smp Fully specified structure encapsulating SMP +/// +/// @return FAPI2_RC_SUCCESS if success, else error code. +/// + fapi2::ReturnCode p9_build_smp_insert_chip(p9_build_smp_chip& io_smp_chip, + const p9_build_smp_operation i_op, + p9_build_smp_system& io_smp) + { + FAPI_DBG("Start"); + fapi2::ReturnCode l_rc; + + // Node/chip ID + p9_fab_smp_node_id l_nodeId = io_smp_chip.node_id; + p9_fab_smp_chip_id l_chipId = io_smp_chip.chip_id; + + // Chip/Node map iterators + std::map<p9_fab_smp_node_id, p9_build_smp_node>::iterator n_iter; + std::map<p9_fab_smp_chip_id, p9_build_smp_chip>::iterator p_iter; + + // First chip found in node? + bool l_firstChipInNode = false; + + FAPI_INF("Inserting n%d p%d", l_nodeId, l_chipId); + + // Search to see if node structure already exists for the node ID + // associated with this chip + n_iter = io_smp.nodes.find(l_nodeId); + + // If no matching node found, create one + if (n_iter == io_smp.nodes.end()) + { + FAPI_DBG("proc_build_smp_insert_chip: No matching node found, " + "inserting new node structure"); + + p9_build_smp_node l_smpNode; + l_smpNode.node_id = io_smp_chip.node_id; + + std::pair<std::map<p9_fab_smp_node_id, p9_build_smp_node>::iterator, + bool> l_ret; + l_ret = io_smp.nodes.insert( + std::pair<p9_fab_smp_node_id, p9_build_smp_node> + (l_nodeId, l_smpNode) ); + n_iter = l_ret.first; + + FAPI_ASSERT(l_ret.second, + fapi2::PROC_BUILD_SMP_NODE_ADD_INTERNAL_ERR() + .set_TARGET(io_smp_chip.chip->this_chip) + .set_NODE_ID(l_nodeId), + "Error encountered adding node to SMP"); + + // First chip in node + l_firstChipInNode = true; + } + + // Search to see if match exists in this node for the chip ID associated + // with this chip + p_iter = io_smp.nodes[l_nodeId].chips.find(l_chipId); + + // Matching chip ID & node ID already found, flag an error + FAPI_ASSERT(p_iter == io_smp.nodes[l_nodeId].chips.end(), + fapi2::PROC_BUILD_SMP_DUPLICATE_FABRIC_ID_ERR() + .set_TARGET1(io_smp_chip.chip->this_chip) + .set_TARGET2(p_iter->second.chip->this_chip) + .set_NODE_ID(l_nodeId) + .set_CHIP_ID(l_chipId), + "Duplicate fabric nodeID/chipID " + "found"); + + // Determine node/system master status + FAPI_TRY(p9_build_smp_set_master_config(l_firstChipInNode, i_op, + io_smp_chip, io_smp), + "p9_build_smp_set_master_config() returns an error, l_rc 0x%.8X", + (uint64_t)fapi2::current_err); + + // Insert chip into SMP + io_smp.nodes[l_nodeId].chips[l_chipId] = io_smp_chip; + + fapi_try_exit: + FAPI_DBG("End"); + return fapi2::current_err; + } + +/// +/// @brief Process X/A links of a proc chip. +/// +/// @param[in] i_smp_proc_chip Structure defining properties of a proc chip +/// @param[in] i_smp_chip Structure encapsulating single chip in SMP +/// @param[in] i_local_node_id This chip's node ID +/// @param[in] i_local_chip_id This chip's chip ID +/// @param[in] i_nodeIdsInSystem Bit-wise marking the existed nodes in system. +/// @param[in] i_chipIdsInNode Bit-wise marking the existed chips in the +/// node where this chip resides. +/// +/// +/// @return FAPI2_RC_SUCCESS if success, else error code. +/// + fapi2::ReturnCode p9_process_proc_links( + p9_build_smp_proc_chip& i_smp_proc_chip, + const p9_build_smp_chip& i_smp_chip, + const p9_fab_smp_node_id i_local_node_id, + const p9_fab_smp_chip_id i_local_chip_id, + const fapi2::buffer<uint8_t> i_nodeIdsInSystem, + const fapi2::buffer<uint8_t> i_chipIdsInNode) + { + FAPI_DBG("Start"); + fapi2::ReturnCode l_rc; + + bool internode_set_match = false; + bool intranode_set_match = false; + + fapi2::buffer<uint8_t> l_xConnectedChipIds; + fapi2::buffer<uint8_t> l_aConnectedNodeIds; + std::vector<fapi2::Target<fapi2::TARGET_TYPE_XBUS>*> l_xLinkTargets; + std::vector<fapi2::Target<fapi2::TARGET_TYPE_OBUS>*> l_oLinkTargets; + + // Process X-connected chips + l_xLinkTargets.push_back(&i_smp_proc_chip.x0_chip); + l_xLinkTargets.push_back(&i_smp_proc_chip.x1_chip); + l_xLinkTargets.push_back(&i_smp_proc_chip.x2_chip); + + for (auto l_xbusItr = l_xLinkTargets.begin(); + l_xbusItr != l_xLinkTargets.end(); + ++l_xbusItr) + { + bool l_linkIsEnabled = false; + p9_fab_smp_node_id dest_node_id; + p9_fab_smp_chip_id dest_chip_id; + + FAPI_TRY(p9_build_smp_query_link_state(i_smp_chip, + (l_xbusItr - l_xLinkTargets.begin()), + **l_xbusItr, + l_linkIsEnabled, + dest_node_id, + dest_chip_id), + "(XBUS): p9_build_smp_query_link_state() returns an error, l_rc 0x%.8X", + (uint64_t)fapi2::current_err); + + if (l_linkIsEnabled) + { + if (dest_node_id == i_local_node_id) + { + FAPI_TRY(l_xConnectedChipIds.setBit(dest_chip_id), + "(XBUS): (l_xConnectedChipIds.setBit() returns an error, " + "l_rc 0x%.8X", (uint64_t)fapi2::current_err); + } + else + { + FAPI_TRY(l_xConnectedChipIds.clearBit(dest_chip_id), + "(XBUS): (l_xConnectedChipIds.clearBit() returns an error, " + "l_rc 0x%.8X", (uint64_t)fapi2::current_err); + } + + FAPI_INF("(XBUS): n%d:p%d X%zd -> n%d:p%d", + i_local_node_id, i_local_chip_id, + (l_xbusItr - l_xLinkTargets.begin()), + dest_node_id, dest_chip_id); + } + } + + // OBUS targets + l_oLinkTargets.push_back(&i_smp_proc_chip.o0_chip); + l_oLinkTargets.push_back(&i_smp_proc_chip.o1_chip); + l_oLinkTargets.push_back(&i_smp_proc_chip.o2_chip); + l_oLinkTargets.push_back(&i_smp_proc_chip.o3_chip); + + // Process O-connected chips + for (auto l_obusItr = l_oLinkTargets.begin(); + l_obusItr != l_oLinkTargets.end(); + ++l_obusItr) + { + bool l_linkIsEnabled = false; + p9_fab_smp_node_id dest_node_id; + p9_fab_smp_chip_id dest_chip_id; + + FAPI_TRY(p9_build_smp_query_link_state(i_smp_chip, + (l_obusItr - l_oLinkTargets.begin()), + **l_obusItr, + l_linkIsEnabled, + dest_node_id, + dest_chip_id), + "(OBUS): p9_build_smp_query_link_state() returns an error, l_rc 0x%.8X", + (uint64_t)fapi2::current_err); + + if (l_linkIsEnabled) + { + // Optic configured as XBUS + if (i_smp_chip.smpOpticsMode == + fapi2::ENUM_ATTR_PROC_FABRIC_SMP_OPTICS_MODE_OPTICS_IS_X_BUS) + { + // Additional X links from optic + // Set bit #3 thru 6 to indicate more X-links + if (dest_node_id == i_local_node_id) + { + FAPI_TRY(l_xConnectedChipIds.setBit(dest_chip_id + + P9_FAB_SMP_NUM_X_LINKS), + "(OBUS): (l_xConnectedChipIds.setBit() returns an error, " + "l_rc 0x%.8X", (uint64_t)fapi2::current_err); + } + else + { + FAPI_TRY(l_xConnectedChipIds.clearBit(dest_chip_id + + P9_FAB_SMP_NUM_X_LINKS), + "(OBUS): (l_xConnectedChipIds.clearBit() returns an error, " + "l_rc 0x%.8X", + (uint64_t)fapi2::current_err); + } + + FAPI_INF("(OBUS): n%d:p%d X%zd -> n%d:p%d", + i_local_node_id, i_local_chip_id, + (l_obusItr - l_oLinkTargets.begin()), + dest_node_id, dest_chip_id); + } + // Optic configured as ABUS + else + { + if (dest_chip_id == i_local_chip_id) + { + FAPI_TRY(l_aConnectedNodeIds.setBit(dest_node_id), + "(OBUS): l_aConnectedNodeIds.setBit() returns an error, " + "l_rc 0x%.8X", (uint64_t)fapi2::current_err); + } + else + { + FAPI_TRY(l_aConnectedNodeIds.clearBit(dest_node_id), + "(OBUS): (l_aConnectedNodeIds.clearBit() returns an error, " + "l_rc 0x%.8X", (uint64_t)fapi2::current_err); + } + + FAPI_INF("(OBUS): n%d:p%d X%zd -> n%d:p%d", + i_local_node_id, i_local_chip_id, + (l_obusItr - l_oLinkTargets.begin()), + dest_node_id, dest_chip_id); + } + } + } + + // Add IDs associated with current chip, to make direct set comparison easy + FAPI_DBG("Checking connectivity for n%d:p%d", i_local_node_id, i_local_chip_id); + + FAPI_TRY(l_xConnectedChipIds.setBit(i_local_chip_id), + "l_xConnectedChipIds.setBit() returns an error, l_rc 0x%.8X", + (uint64_t)fapi2::current_err); + + FAPI_TRY(l_aConnectedNodeIds.setBit(i_local_node_id), + "l_xConnectedChipIds.setBit() returns an error, l_rc 0x%.8X", + (uint64_t)fapi2::current_err); + + // Compare ID sets, exit if they don't match + internode_set_match = (i_nodeIdsInSystem == l_aConnectedNodeIds); + intranode_set_match = (i_chipIdsInNode == l_xConnectedChipIds); + + if (!internode_set_match || + !intranode_set_match) + { + // Display target information + char l_targetStr[fapi2::MAX_ECMD_STRING_LEN]; + fapi2::toString(i_smp_proc_chip.this_chip, l_targetStr, + sizeof(l_targetStr)); + + if (!intranode_set_match) + { + FAPI_ERR("Target %s is not fully connected (X) to all other chips " + "in its node", l_targetStr); + } + + if (!internode_set_match) + { + FAPI_ERR("Target %s is not fully connected (A) to all other nodes", + l_targetStr); + } + + FAPI_ASSERT(false, + fapi2::PROC_BUILD_SMP_INVALID_TOPOLOGY() + .set_TARGET(i_smp_proc_chip.this_chip) + .set_A_CONNECTIONS_OK(internode_set_match) + .set_A_CONNECTED_NODE_IDS(l_aConnectedNodeIds) + .set_X_CONNECTIONS_OK(intranode_set_match) + .set_X_CONNECTED_CHIP_IDS(l_xConnectedChipIds), + "Invalid fabric topology detected!!"); + } + + fapi_try_exit: + FAPI_DBG("End"); + return fapi2::current_err; + } + +/// +/// @brief Process all HWP input structures and build SMP data structure +/// +/// @param[in] i_proc_chips Vector of HWP input structures (one entry per +/// chip in SMP) +/// @param[in] i_op Procedure operation phase/mode +/// @param[in] io_smp Fully specified structure encapsulating SMP +/// +/// @return FAPI2_RC_SUCCESS if success, else error code. +/// + fapi2::ReturnCode p9_build_smp_process_chips( + std::vector<p9_build_smp_proc_chip>& i_proc_chips, + const p9_build_smp_operation i_op, + p9_build_smp_system& io_smp) + { + FAPI_DBG("Start"); + fapi2::ReturnCode l_rc; + const fapi2::Target<fapi2::TARGET_TYPE_SYSTEM> FAPI_SYSTEM; + + // Mapping of node/chip id vs smp info data + std::map<p9_fab_smp_node_id, p9_build_smp_node>::iterator n_iter; + std::map<p9_fab_smp_chip_id, p9_build_smp_chip>::iterator p_iter; + + fapi2::buffer<uint8_t> l_nodeIdsInSystem; + fapi2::buffer<uint8_t> l_chipIdsInNode; + + std::vector<fapi2::Target<fapi2::TARGET_TYPE_XBUS>*> l_xLinkTargets; + std::vector<fapi2::Target<fapi2::TARGET_TYPE_OBUS>*> l_oLinkTargets; + + io_smp.master_chip_curr_set = false; + + // Loop over input proc chips + for (auto itr = i_proc_chips.begin(); itr != i_proc_chips.end(); ++itr) + { + // Process platform provided data in chip argument, + // Query chip specific attributes + p9_build_smp_chip smp_chip; + FAPI_TRY(p9_build_smp_process_chip( &(*itr), smp_chip ), + "p9_build_smp_process_chip() returns an error, l_rc 0x%.8X", + (uint64_t)fapi2::current_err); + + // Copy system attribute to chip structure for later use + smp_chip.smpOpticsMode = io_smp.smpOpticsMode; + + // Insert chip into SMP data structure given node & chip ID + FAPI_TRY(p9_build_smp_insert_chip( smp_chip, i_op, io_smp ), + "p9_build_smp_insert_chip() returns an error, l_rc 0x%.8X", + (uint64_t)fapi2::current_err); + + // Set attached chips' attributes + FAPI_TRY(p9_fab_set_attached_chip_attr(itr->this_chip), + "p9_fab_set_attached_chip_attr() returns an error, l_rc 0x%.8X", + (uint64_t)fapi2::current_err); + } + + // Ensure that new master was designated + FAPI_ASSERT(io_smp.master_chip_curr_set, + fapi2::PROC_BUILD_SMP_NO_MASTER_SPECIFIED_ERR() + .set_OP(i_op), + "No system master specified!"); + + + // Based on master designation, and operation phase, + // determine whether each chip will be quiesced as a result + // of switch activity + for (n_iter = io_smp.nodes.begin(); + n_iter != io_smp.nodes.end(); + n_iter++) + { + for (p_iter = n_iter->second.chips.begin(); + p_iter != n_iter->second.chips.end(); + p_iter++) + { + if (((i_op == SMP_ACTIVATE_PHASE1) && + (p_iter->second.issue_quiesce_next)) || + ((i_op == SMP_ACTIVATE_PHASE2) && + (n_iter->first != io_smp.master_chip_curr_node_id))) + { + p_iter->second.quiesced_next = true; + } + else + { + p_iter->second.quiesced_next = false; + } + } + } + + // Check that fabric topology is logically valid + // 1) In a given node, all chips are connected to every other + // chip in the node, by an X bus + // 2) Each chip is connected to its partner chip (with same chip id) + // in every other node, by an A bus + + // Build set of all valid node ids in system + for (n_iter = io_smp.nodes.begin(); + n_iter != io_smp.nodes.end(); + n_iter++) + { + FAPI_INF("Adding n%d", n_iter->first); + FAPI_TRY(l_nodeIdsInSystem.setBit(n_iter->first), + "l_nodeIdsInSystem.setBit() returns an error, l_rc 0x%.8X", + (uint64_t)fapi2::current_err); + + } + + // Iterate over all nodes + for (n_iter = io_smp.nodes.begin(); + n_iter != io_smp.nodes.end(); + n_iter++) + { + // Build set of all valid chip ids in node + for (p_iter = n_iter->second.chips.begin(); + p_iter != n_iter->second.chips.end(); + p_iter++) + { + FAPI_INF("Adding n%d:p%d", n_iter->first, p_iter->first); + FAPI_TRY(l_chipIdsInNode.setBit(p_iter->first), + "l_chipIdsInNode.setBit() returns an error, l_rc 0x%.8X", + (uint64_t)fapi2::current_err); + } + + // Iterate over all chips in current node + for (p_iter = n_iter->second.chips.begin(); + p_iter != n_iter->second.chips.end(); + p_iter++) + { + FAPI_INF("Processing links for n%d:p%d", n_iter->first, p_iter->first); + + // Process X/A links + FAPI_TRY(p9_process_proc_links(*p_iter->second.chip, + p_iter->second, + n_iter->first, + p_iter->first, + l_nodeIdsInSystem, + l_chipIdsInNode), + "p9_process_proc_links() returns an error, l_rc 0x%.8X", + (uint64_t)fapi2::current_err); + } + } + + fapi_try_exit: + FAPI_DBG("End"); + return fapi2::current_err; + } + +/// +/// @brief p9_build_smp procedure entry point +/// See doxygen in p9_build_smp.H +/// + fapi2::ReturnCode p9_build_smp( + std::vector<p9_build_smp_proc_chip>& i_proc_chips, + const p9_build_smp_operation i_op) + + { + FAPI_DBG("Start"); + fapi2::ReturnCode l_rc; + p9_build_smp_system l_smp; + + // Get the p9 target attributes needed to perform grouping + FAPI_TRY(p9_build_smp_process_system(l_smp), + "p9_build_smp_process_system() returns an error, l_rc 0x%.8X", + (uint64_t)fapi2::current_err); + + // Process HWP input vector of chip structures + FAPI_TRY(p9_build_smp_process_chips(i_proc_chips, i_op, l_smp), + "p9_build_smp_process_chips() returns an error, l_rc 0x%.8X", + (uint64_t)fapi2::current_err); + + // Initialize fabric configuration + if (i_op == SMP_ACTIVATE_PHASE1) + { + // Program nest epsilon attributes/registers + FAPI_TRY(p9_build_smp_set_epsilons(l_smp), + "p9_build_smp_set_epsilons() returns an error, l_rc 0x%.8X", + (uint64_t)fapi2::current_err); + + // Set fabric configuration registers (non-hotplug) + FAPI_TRY(p9_build_smp_set_fbc_nohp(l_smp), + "p9_build_smp_set_fbc_nohp() returns an error, l_rc 0x%.8X", + (uint64_t)fapi2::current_err); + + // Set fabric configuration registers (hotplug, switch CD set) + FAPI_TRY(p9_build_smp_set_fbc_cd(l_smp), + "p9_build_smp_set_fbc_nohp() returns an error, l_rc 0x%.8X", + (uint64_t)fapi2::current_err); + } + + // Set fabric trace configuration registers (non-hotplug) + FAPI_TRY(p9_build_smp_set_fbc_nohp_trace(l_smp), + "p9_build_smp_set_fbc_nohp_trace() returns an error, l_rc 0x%.8X", + (uint64_t)fapi2::current_err); + + + // Activate SMP + // Set fabric configuration registers (hotplug, switch AB set) + FAPI_TRY(p9_build_smp_set_fbc_ab(l_smp, i_op), + "p9_build_smp_set_fbc_ab() returns an error, l_rc 0x%.8X", + (uint64_t)fapi2::current_err); -fapi2::ReturnCode -p9_build_smp(std::vector<p9_build_smp_proc_chip>& i_proc_chips, - const p9_build_smp_operation i_op) + fapi_try_exit: + FAPI_DBG("End"); + return fapi2::current_err; + } -{ - FAPI_INF("Start"); - FAPI_INF("End"); - return fapi2::current_err; -} +} // extern "C" diff --git a/src/import/chips/p9/procedures/hwp/nest/p9_build_smp.H b/src/import/chips/p9/procedures/hwp/nest/p9_build_smp.H index 23b8adaad..12a8b99a5 100755 --- a/src/import/chips/p9/procedures/hwp/nest/p9_build_smp.H +++ b/src/import/chips/p9/procedures/hwp/nest/p9_build_smp.H @@ -7,7 +7,7 @@ /* */ /* EKB Project */ /* */ -/* COPYRIGHT 2015 */ +/* COPYRIGHT 2015,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -41,18 +41,13 @@ /// o join collection of drawer level SMPs into full system SMP /// (switch A/B) /// -/// @author Joe McGill <jmcgill@us.ibm.com> -/// @author Christy Graves <clgraves@us.ibm.com> +/// *HWP HWP Owner: Joe McGill <jmcgill@us.ibm.com> +/// *HWP FW Owner: Thi Tran <thi@us.ibm.com> +/// *HWP Team: Nest +/// *HWP Level: 2 +/// *HWP Consumed by: HB,FSP /// -// -// *HWP HWP Owner: Joe McGill <jmcgill@us.ibm.com> -// *HWP FW Owner: Thi Tran <thi@us.ibm.com> -// *HWP Team: Nest -// *HWP Level: 1 -// *HWP Consumed by: HB,FSP -// - #ifndef _P9_BUILD_SMP_H_ #define _P9_BUILD_SMP_H_ @@ -61,39 +56,195 @@ // Includes //------------------------------------------------------------------------------ #include <fapi2.H> +#include <map> +#include <p9_fab_smp_utils.H> //------------------------------------------------------------------------------ -// Structure definitions +// Constant definitions //------------------------------------------------------------------------------ +// PB shadow register constant definition +const uint8_t P9_BUILD_SMP_NUM_SHADOWS = 3; // HWP argument, define supported execution modes enum p9_build_smp_operation { - // call from HB (init epsilons, switch C/D + A/B) + // Call from HB (init epsilons, switch C/D + A/B), // used to initialize scope of HBI drawer SMP_ACTIVATE_PHASE1 = 1, - // call from FSP (only switch A/B) - // used to stitch drawers/CCM + // Call from FSP (only switch A/B), used to stitch drawers/CCM SMP_ACTIVATE_PHASE2 = 2 }; +// Core/nest frequency ratio cutpoints (epsilon) +enum p9_build_smp_core_ratio +{ + P9_BUILD_SMP_CORE_RATIO_8_8 = 0, + P9_BUILD_SMP_CORE_RATIO_7_8 = 1, + P9_BUILD_SMP_CORE_RATIO_6_8 = 2, + P9_BUILD_SMP_CORE_RATIO_5_8 = 3, + P9_BUILD_SMP_CORE_RATIO_4_8 = 4, + P9_BUILD_SMP_CORE_RATIO_2_8 = 5 +}; + +// Core floor/nest frequency ratio cutpoints (CPU delay) +enum p9_build_smp_cpu_delay +{ + P9_BUILD_SMP_CPU_DELAY_4800_2400 = 0, + P9_BUILD_SMP_CPU_DELAY_4431_2400 = 1, + P9_BUILD_SMP_CPU_DELAY_4114_2400 = 2, + P9_BUILD_SMP_CPU_DELAY_3840_2400 = 3, + P9_BUILD_SMP_CPU_DELAY_3600_2400 = 4, + P9_BUILD_SMP_CPU_DELAY_3338_2400 = 5, + P9_BUILD_SMP_CPU_DELAY_3200_2400 = 6, + P9_BUILD_SMP_CPU_DELAY_3032_2400 = 7, + P9_BUILD_SMP_CPU_DELAY_2880_2400 = 8, + P9_BUILD_SMP_CPU_DELAY_2743_2400 = 9, + P9_BUILD_SMP_CPU_DELAY_2618_2400 = 10, + P9_BUILD_SMP_CPU_DELAY_2504_2400 = 11, + P9_BUILD_SMP_CPU_DELAY_2400_2400 = 12 +}; + +//------------------------------------------------------------------------------ +// Structure definitions +//------------------------------------------------------------------------------ + // HWP argument structure defining properties of this chip +// and links which should be considered struct p9_build_smp_proc_chip { - // target for this chip + // Target for this chip fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> this_chip; - // set if this chip should be designated fabric + + // Set if this chip should be designated fabric // master post-reconfiguration // NOTE: this chip must currently be designated a // master in its enclosing fabric // PHASE1/HB: any chip // PHASE2/FSP: any current drawer master - bool is_master_chip_sys_next; + bool master_chip_sys_next; + + // XBUS chiplet targets connected to X links + fapi2::Target<fapi2::TARGET_TYPE_XBUS> x0_chip; + fapi2::Target<fapi2::TARGET_TYPE_XBUS> x1_chip; + fapi2::Target<fapi2::TARGET_TYPE_XBUS> x2_chip; + + // Obus chiplet targets, connected to either A or X links + fapi2::Target<fapi2::TARGET_TYPE_OBUS> o0_chip; + fapi2::Target<fapi2::TARGET_TYPE_OBUS> o1_chip; + fapi2::Target<fapi2::TARGET_TYPE_OBUS> o2_chip; + fapi2::Target<fapi2::TARGET_TYPE_OBUS> o3_chip; + +}; + +// Structure to encapsulate system epsilon configuration + +const uint8_t NUMBER_OF_EPSILON_READ_TIERS = 3; +const uint8_t NUMBER_OF_EPSILON_WRITE_TIERS = 3; + +struct p9_build_smp_eps_cfg +{ + // Epsilon configuration inputs + int8_t gb_percentage; + p9_fab_smp_eps_table_type table_type; + + // Epsilon protection count + // read, tier0 (LN) + // read, tier1 (NN/G) + // read, tier2 (RN/VG) + // write, tier1 (LN/NN/G) + // write, tier2 (RN/VG) + uint32_t r_t[NUMBER_OF_EPSILON_READ_TIERS]; // Read, index is tier + uint32_t w_t[NUMBER_OF_EPSILON_WRITE_TIERS]; // Write, index is tier +}; + +// Structure to represent fabric connectivty & properites for a single chip +// in the SMP topology +struct p9_build_smp_chip +{ + // associated HWP input structure + p9_build_smp_proc_chip* chip; + + // Fabric chip/node ID + p9_fab_smp_chip_id chip_id; + p9_fab_smp_node_id node_id; + + // Optic mode (A or X) + uint8_t smpOpticsMode; + + // TODO: RTC 147511 - Need to set enabled based on ATTR_PG attributes. + // This is to prevent issuing SCOMs to a region that might be deconfigured, + // and we can't use the state of a unit target (XBUS/OBUS) to make the + // determination. + bool nv_enabled = false; + bool x_enabled = true; + bool o_enabled = true; + + // Node/system master designation (curr) + bool master_chip_node_curr; + bool master_chip_sys_curr; + + // Node/system master designation (next) + bool master_chip_node_next; + bool issue_quiesce_next; + bool quiesced_next; + +}; + +// Structure to represent properties for a single node in the SMP topology +struct p9_build_smp_node +{ + // Chips which reside in this node + std::map<p9_fab_smp_chip_id, p9_build_smp_chip> chips; + + // Node properties/attributes: + // fabric node ID + p9_fab_smp_node_id node_id; +}; + +// Structure to represent collection of nodes in SMP topology +struct p9_build_smp_system +{ + // nodes which reside in this SMP + std::map<p9_fab_smp_node_id, p9_build_smp_node> nodes; + + // current system master for the purpose of launching + // fabric reconfiguration operations + bool master_chip_curr_set; + p9_fab_smp_node_id master_chip_curr_node_id; + p9_fab_smp_chip_id master_chip_curr_chip_id; + + // Indicate if optic is configured as A or X + uint8_t smpOpticsMode; + + // System properties/attributes: + // system frequencies (MHz): + uint32_t freq_pb; + uint32_t freq_a; + uint32_t freq_x; + uint32_t freq_core_floor; + uint32_t freq_core_nom; + uint32_t freq_core_ceiling; + uint32_t freq_pcie; + + // Core/pb frequency ratios + p9_build_smp_core_ratio core_floor_ratio; + p9_build_smp_core_ratio core_ceiling_ratio; + + // CPU delay/RCMD highwater settings + p9_build_smp_cpu_delay nom_cpu_delay; + p9_build_smp_cpu_delay full_cpu_delay; + + // Fabric pump mode + p9_fab_smp_pump_mode pump_mode; + + // System epsilon configuration + p9_build_smp_eps_cfg eps_cfg; }; /// function pointer typedef definition for HWP call support -typedef fapi2::ReturnCode (*p9_build_smp_FP_t) (std::vector<p9_build_smp_proc_chip>&, - const p9_build_smp_operation); +typedef fapi2::ReturnCode (*p9_build_smp_FP_t) +(std::vector<p9_build_smp_proc_chip>&, + const p9_build_smp_operation); //------------------------------------------------------------------------------ // Function prototypes @@ -107,7 +258,8 @@ extern "C" /// /// @param[in] i_proc_chips Vector of structures defining properties of each chip /// @param[op] i_op Enumerated type representing SMP build phase (HB or FSP) -/// @return fapi::ReturnCode. FAPI2_RC_SUCCESS if success, else error code. +/// +/// @return fapi2:ReturnCode. FAPI2_RC_SUCCESS if success, else error code. /// fapi2::ReturnCode p9_build_smp(std::vector<p9_build_smp_proc_chip>& i_proc_chips, const p9_build_smp_operation i_op); diff --git a/src/import/chips/p9/procedures/hwp/nest/p9_build_smp.mk b/src/import/chips/p9/procedures/hwp/nest/p9_build_smp.mk index e50914778..06549fa08 100644 --- a/src/import/chips/p9/procedures/hwp/nest/p9_build_smp.mk +++ b/src/import/chips/p9/procedures/hwp/nest/p9_build_smp.mk @@ -7,7 +7,7 @@ # # EKB Project # -# COPYRIGHT 2015 +# COPYRIGHT 2015,2016 # [+] International Business Machines Corp. # # @@ -17,4 +17,11 @@ # # IBM_PROLOG_END_TAG PROCEDURE=p9_build_smp +OBJS+=p9_fab_smp_utils.o +OBJS+=p9_build_smp_fbc_ab.o +OBJS+=p9_build_smp_epsilon.o +OBJS+=p9_build_smp_fbc_nohp.o +OBJS+=p9_build_smp_fbc_cd.o +OBJS+=p9_build_smp_adu.o +OBJS+=p9_adu_coherent_utils.o $(call BUILD_PROCEDURE) |