diff options
Diffstat (limited to 'src')
-rwxr-xr-x | src/occ_405/amec/amec_data.c | 28 | ||||
-rwxr-xr-x | src/occ_405/amec/amec_freq.c | 120 | ||||
-rw-r--r-- | src/occ_405/amec/amec_init.c | 4 | ||||
-rwxr-xr-x | src/occ_405/amec/amec_master_smh.c | 10 | ||||
-rwxr-xr-x | src/occ_405/amec/amec_oversub.c | 45 | ||||
-rwxr-xr-x | src/occ_405/amec/amec_oversub.h | 17 | ||||
-rwxr-xr-x | src/occ_405/amec/amec_pcap.c | 178 | ||||
-rwxr-xr-x | src/occ_405/amec/amec_pcap.h | 6 | ||||
-rwxr-xr-x | src/occ_405/amec/amec_service_codes.h | 3 | ||||
-rwxr-xr-x | src/occ_405/amec/amec_slave_smh.c | 16 | ||||
-rwxr-xr-x | src/occ_405/cent/centaur_control.c | 18 | ||||
-rwxr-xr-x | src/occ_405/cmdh/cmdh_fsp_cmds_datacnfg.c | 44 | ||||
-rwxr-xr-x | src/occ_405/cmdh/cmdh_fsp_cmds_datacnfg.h | 24 | ||||
-rwxr-xr-x | src/occ_405/cmdh/cmdh_mnfg_intf.c | 79 | ||||
-rwxr-xr-x | src/occ_405/dcom/dcom.c | 9 | ||||
-rw-r--r-- | src/occ_405/dimm/dimm_control.c | 41 | ||||
-rwxr-xr-x | src/occ_405/main.c | 10 | ||||
-rwxr-xr-x | src/occ_405/mode.c | 19 | ||||
-rwxr-xr-x | src/occ_405/mode.h | 5 | ||||
-rw-r--r-- | src/occ_405/occ_service_codes.h | 2 | ||||
-rwxr-xr-x | src/occ_405/occ_sys_config.h | 22 | ||||
-rwxr-xr-x | src/occ_405/rtls/rtls.c | 6 | ||||
-rwxr-xr-x | src/occ_405/state.h | 16 |
23 files changed, 319 insertions, 403 deletions
diff --git a/src/occ_405/amec/amec_data.c b/src/occ_405/amec/amec_data.c index a658f63..c5bde89 100755 --- a/src/occ_405/amec/amec_data.c +++ b/src/occ_405/amec/amec_data.c @@ -1,11 +1,11 @@ /* IBM_PROLOG_BEGIN_TAG */ /* This is an automatically generated prolog. */ /* */ -/* $Source: src/occ/amec/amec_data.c $ */ +/* $Source: src/occ_405/amec/amec_data.c $ */ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2011,2015 */ +/* Contributors Listed Below - COPYRIGHT 2011,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -110,9 +110,10 @@ errlHndl_t AMEC_data_write_fcurr(const OCC_MODE i_mode) } } - // If we are in OpenPower environment, load this new range into DVFS - // min/max for AMEC component - if(G_occ_interrupt_type != FSP_SUPPORTED_OCC) + // If we are in OpenPower environment with OPAL, load this new range into DVFS + // min/max for AMEC component. PowerVM on BMC and FSP the min/max is set above + // in amec_set_freq_range() based on mode + if((G_occ_interrupt_type != FSP_SUPPORTED_OCC) && (G_sysConfigData.system_type.kvm)) { g_amec->sys.fmax = G_proc_fmax; g_amec->sys.fmin = G_proc_fmin; // = G_sysConfigData.sys_mode_freq.table[OCC_MODE_MIN_FREQUENCY] @@ -131,8 +132,7 @@ errlHndl_t AMEC_data_write_fcurr(const OCC_MODE i_mode) // // Description: This function loads data from the Thermal Control Threshold // data packet (format 0x13) into g_amec structure. This function should be -// called when OCC goes active or changes modes or goes in/out of Acoustic -// mode (ITE-only mode). +// called when OCC goes active or changes modes // // Thread: RealTime Loop // @@ -166,8 +166,6 @@ errlHndl_t AMEC_data_write_thrm_thresholds(const OCC_MODE i_mode) l_frudata = l_data->data; - // TODO: Need to check if acoustic mode has been enabled (ITE-only mode) - // Store the processor thermal data if(i_mode == OCC_MODE_NOMINAL) { @@ -346,6 +344,11 @@ errlHndl_t AMEC_data_change(const uint32_t i_data_mask) if(i_data_mask & DATA_MASK_FREQ_PRESENT) { l_err = AMEC_data_write_fcurr(l_cur_mode); + + if(l_err) + { + TRAC_ERR("AMEC_data_change: Error writing frequency range!"); + } } else if(i_data_mask & DATA_MASK_THRM_THRESHOLDS) { @@ -405,13 +408,6 @@ void amec_data_write_pcap(void) memcpy(&(G_sysConfigData.pcap),&(G_dcom_slv_inbox_doorbell_rx.pcap), sizeof(pcap_config_data_t)); - //Affects ITE ONLY: Check if it's ok (1) to exit the oversubscribed state - if(1 == G_sysConfigData.pcap.unthrottle) - { - //Clear throttle flag - g_amec->oversub_status.cmeThrottleLatchAmec = 0; - } - //Check node power cap requested by customer/system. // 0 means there is no pcap for that parameter. if(0 == G_sysConfigData.pcap.current_pcap) diff --git a/src/occ_405/amec/amec_freq.c b/src/occ_405/amec/amec_freq.c index 5cc198f..0f7d764 100755 --- a/src/occ_405/amec/amec_freq.c +++ b/src/occ_405/amec/amec_freq.c @@ -165,52 +165,84 @@ errlHndl_t amec_set_freq_range(const OCC_MODE i_mode) l_freq_max = G_sysConfigData.sys_mode_freq.table[i_mode]; } - // If SMS is set then TMGT wants us to pin to frequency which - // corresponds to input mode. They will use this function - // when powering off and they wish to have us bring the system - // back up to real nominal frequency (without being impacted - // by power caps or thermal actuations) - if(CURRENT_SMS() == SMGR_SMS_STATIC_VF_CHANGE_REQ) + if( (l_freq_min == 0) || (l_freq_max == 0) ) { - l_freq_min = l_freq_max; + // Do not update amec vars with a 0 frequency. + // The frequency limit for each mode should have been set prior + // to calling or the mode passed was invalid + TRAC_ERR("amec_set_freq_range: Freq of 0 found! mode[0x%02x] Fmin[%u] Fmax[%u]", + i_mode, + l_freq_min, + l_freq_max); + + // Log an error if this is PowerVM as this should never happen when OCC + // supports modes + if(!G_sysConfigData.system_type.kvm) + { + /* @ + * @errortype + * @moduleid AMEC_SET_FREQ_RANGE + * @reasoncode INTERNAL_FW_FAILURE + * @userdata1 Mode + * @userdata2 0 + * @userdata4 ERC_FW_ZERO_FREQ_LIMIT + * @devdesc Fmin or Fmax of 0 found for mode + */ + errlHndl_t l_err = createErrl(AMEC_SET_FREQ_RANGE, //modId + INTERNAL_FW_FAILURE, //reasoncode + ERC_FW_ZERO_FREQ_LIMIT, //Extended reason code + ERRL_SEV_PREDICTIVE, //Severity + NULL, //Trace Buf + DEFAULT_TRACE_SIZE, //Trace Size + i_mode, //userdata1 + 0); //userdata2 + + // Callout Firmware + addCalloutToErrl(l_err, + ERRL_CALLOUT_TYPE_COMPONENT_ID, + ERRL_COMPONENT_ID_FIRMWARE, + ERRL_CALLOUT_PRIORITY_LOW + ); + } + } + else + { + g_amec->sys.fmin = l_freq_min; + g_amec->sys.fmax = l_freq_max; + + TRAC_INFO("amec_set_freq_range: Mode[0x%02x] Fmin[%u] Fmax[%u]", + i_mode, + l_freq_min, + l_freq_max); + + // Now determine the max frequency for the PPM structure + l_ppm_freq[OCC_INTERNAL_MODE_NOM].fmax = G_sysConfigData.sys_mode_freq.table[OCC_MODE_NOMINAL]; + l_ppm_freq[OCC_INTERNAL_MODE_DPS].fmax = G_sysConfigData.sys_mode_freq.table[OCC_MODE_DYN_POWER_SAVE]; + l_ppm_freq[OCC_INTERNAL_MODE_DPS_MP].fmax = G_sysConfigData.sys_mode_freq.table[OCC_MODE_DYN_POWER_SAVE_FP]; + + // Determine the min frequency for the PPM structure. This Fmin should + // always be set to the system Fmin + l_ppm_freq[OCC_INTERNAL_MODE_NOM].fmin = G_sysConfigData.sys_mode_freq.table[OCC_MODE_MIN_FREQUENCY]; + l_ppm_freq[OCC_INTERNAL_MODE_DPS].fmin = G_sysConfigData.sys_mode_freq.table[OCC_MODE_MIN_FREQUENCY]; + l_ppm_freq[OCC_INTERNAL_MODE_DPS_MP].fmin = G_sysConfigData.sys_mode_freq.table[OCC_MODE_MIN_FREQUENCY]; + + // Determine the min speed allowed for DPS power policies (this is needed + // by the DPS algorithms) + l_temp = (l_ppm_freq[OCC_INTERNAL_MODE_DPS].fmin * 1000)/l_ppm_freq[OCC_INTERNAL_MODE_DPS].fmax; + l_ppm_freq[OCC_INTERNAL_MODE_DPS].min_speed = l_temp; + + l_temp = (l_ppm_freq[OCC_INTERNAL_MODE_DPS_MP].fmin * 1000)/l_ppm_freq[OCC_INTERNAL_MODE_DPS_MP].fmax; + l_ppm_freq[OCC_INTERNAL_MODE_DPS_MP].min_speed = l_temp; + + // Copy the PPM frequency information into g_amec + memcpy(g_amec->part_mode_freq, l_ppm_freq, sizeof(l_ppm_freq)); + + TRAC_INFO("amec_set_freq_range: PPM Fmin[%u] Fnom[%u] Fmax[%u] min_speed[%u]", + l_ppm_freq[OCC_INTERNAL_MODE_NOM].fmin, + l_ppm_freq[OCC_INTERNAL_MODE_NOM].fmax, + l_ppm_freq[OCC_INTERNAL_MODE_DPS].fmax, + l_ppm_freq[OCC_INTERNAL_MODE_DPS_MP].min_speed); } - - g_amec->sys.fmin = l_freq_min; - g_amec->sys.fmax = l_freq_max; - - TRAC_INFO("amec_set_freq_range: Mode[0x%02x] Fmin[%u] Fmax[%u]", - i_mode, - l_freq_min, - l_freq_max); - - // Now determine the max frequency for the PPM structure - l_ppm_freq[OCC_INTERNAL_MODE_NOM].fmax = G_sysConfigData.sys_mode_freq.table[OCC_MODE_NOMINAL]; - l_ppm_freq[OCC_INTERNAL_MODE_DPS].fmax = G_sysConfigData.sys_mode_freq.table[OCC_MODE_DYN_POWER_SAVE]; - l_ppm_freq[OCC_INTERNAL_MODE_DPS_MP].fmax = G_sysConfigData.sys_mode_freq.table[OCC_MODE_DYN_POWER_SAVE_FP]; - - // Determine the min frequency for the PPM structure. This Fmin should - // always be set to the system Fmin - l_ppm_freq[OCC_INTERNAL_MODE_NOM].fmin = G_sysConfigData.sys_mode_freq.table[OCC_MODE_MIN_FREQUENCY]; - l_ppm_freq[OCC_INTERNAL_MODE_DPS].fmin = G_sysConfigData.sys_mode_freq.table[OCC_MODE_MIN_FREQUENCY]; - l_ppm_freq[OCC_INTERNAL_MODE_DPS_MP].fmin = G_sysConfigData.sys_mode_freq.table[OCC_MODE_MIN_FREQUENCY]; - - // Determine the min speed allowed for DPS power policies (this is needed - // by the DPS algorithms) - l_temp = (l_ppm_freq[OCC_INTERNAL_MODE_DPS].fmin * 1000)/l_ppm_freq[OCC_INTERNAL_MODE_DPS].fmax; - l_ppm_freq[OCC_INTERNAL_MODE_DPS].min_speed = l_temp; - - l_temp = (l_ppm_freq[OCC_INTERNAL_MODE_DPS_MP].fmin * 1000)/l_ppm_freq[OCC_INTERNAL_MODE_DPS_MP].fmax; - l_ppm_freq[OCC_INTERNAL_MODE_DPS_MP].min_speed = l_temp; - - // Copy the PPM frequency information into g_amec - memcpy(g_amec->part_mode_freq, l_ppm_freq, sizeof(l_ppm_freq)); - - TRAC_INFO("amec_set_freq_range: PPM Fmin[%u] Fnom[%u] Fmax[%u] min_speed[%u]", - l_ppm_freq[OCC_INTERNAL_MODE_NOM].fmin, - l_ppm_freq[OCC_INTERNAL_MODE_NOM].fmax, - l_ppm_freq[OCC_INTERNAL_MODE_DPS].fmax, - l_ppm_freq[OCC_INTERNAL_MODE_DPS_MP].min_speed); - return l_err; } diff --git a/src/occ_405/amec/amec_init.c b/src/occ_405/amec/amec_init.c index e0fdd84..b89f038 100644 --- a/src/occ_405/amec/amec_init.c +++ b/src/occ_405/amec/amec_init.c @@ -285,6 +285,10 @@ void amec_init_gamec_struct(void) g_amec->vrhotproc.freq_request = -1; g_amec->vrhotproc.speed_request = 1000; + // Initialize component power caps + g_amec->pcap.active_proc_pcap = 0; + g_amec->pcap.active_mem_level = 0; + // @TODO - TEMP: not ready yet in Phase 1 /* // Initialize partition information diff --git a/src/occ_405/amec/amec_master_smh.c b/src/occ_405/amec/amec_master_smh.c index c49ca06..c980f3a 100755 --- a/src/occ_405/amec/amec_master_smh.c +++ b/src/occ_405/amec/amec_master_smh.c @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2011,2015 */ +/* Contributors Listed Below - COPYRIGHT 2011,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -457,11 +457,13 @@ void amec_mst_check_under_pcap(void) /* Code */ /*------------------------------------------------------------------------*/ - // Check if ppb_fmax = Fmin and PWR250US > Node power cap and - // Node power cap >= hard_min_pcap + // Check if done everything possible to shed power and power still above a hard power cap + // ppb_fmax = Fmin and PWR250US > Node power cap and + // Node power cap >= hard_min_pcap AND memory is throttled if((g_amec->proc[0].pwr_votes.ppb_fmax == g_amec->sys.fmin) && (AMECSENSOR_PTR(PWR250US)->sample > g_amec->pcap.active_node_pcap) && - (g_amec->pcap.active_node_pcap >= G_sysConfigData.pcap.hard_min_pcap)) + (g_amec->pcap.active_node_pcap >= G_sysConfigData.pcap.hard_min_pcap) && + (g_amec->pcap.active_mem_level != 0) ) { G_over_cap_count++; diff --git a/src/occ_405/amec/amec_oversub.c b/src/occ_405/amec/amec_oversub.c index 6b5ab3c..0a5993b 100755 --- a/src/occ_405/amec/amec_oversub.c +++ b/src/occ_405/amec/amec_oversub.c @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2011,2015 */ +/* Contributors Listed Below - COPYRIGHT 2011,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -68,21 +68,17 @@ // Function Specification // -// Name: amec_oversub_pmax_clip +// Name: amec_set_pmax_clip // -// Description: Set Pmax_Clip in PMC to lowest Pstate +// Description: Set Pmax_Clip in PMC to Pstate // // Task Flags: // // End Function Specification -void amec_oversub_pmax_clip(Pstate i_pstate) +void amec_set_pmax_clip(Pstate i_pstate) { - pmc_rail_bounds_register_t prbr; + // TODO: Send IPC cmd to PGPE to set Pmax_Clip - // Set Pmax_Clip in PMC to lowest Pstate - prbr.value = in32(PMC_RAIL_BOUNDS_REGISTER); - prbr.fields.pmax_rail = i_pstate; - out32(PMC_RAIL_BOUNDS_REGISTER, prbr.value); } // Function Specification @@ -107,13 +103,9 @@ void amec_oversub_isr(void) // SSX_IRQ_POLARITY_ACTIVE_LOW means over-subscription is active if(l_polarity == SSX_IRQ_POLARITY_ACTIVE_LOW) { - // If RTL doesn't control it, do it here - if(g_amec->oversub_status.oversubLatchAmec == 0) - { - // TODO: Throttle all Centaurs via PORE-GPE by setting 'Emergency Throttle' - - g_amec->oversub_status.oversubReasonLatchCount = OVERSUB_REASON_DELAY_4MS; - } + // oversub only switches pcap in amec_pcap_calc + // throttling only done if actually needed due to reaching power cap + g_amec->oversub_status.oversubReasonLatchCount = OVERSUB_REASON_DELAY_4MS; // Set oversubPinLive and oversubActiveTime g_amec->oversub_status.oversubPinLive = 1; @@ -159,27 +151,8 @@ void amec_oversub_isr(void) // End Function Specification void amec_oversub_check(void) { - uint8_t l_cme_pin_value = 1; // low active, so set default to high static BOOLEAN l_prev_ovs_state = FALSE; // oversub happened - // Get CME Pin state - // No longer reading gpio from APSS in GA1 due to instability in APSS composite mode - //apss_gpio_get(l_cme_pin, &l_cme_pin_value); - - // Check CME Pin? OR CME Oversub Mnfg Active - if( (l_cme_pin_value == 0) || - (g_amec->oversub_status.cmeThrottlePinMnfg == 1) ) - { - g_amec->oversub_status.cmeThrottlePinLive = 1; - g_amec->oversub_status.cmeThrottleLatchAmec = 1; - } - else - { - // Do not clear cmeThrottleLatchAmec. - // That will only be done via the PowerCa command from TMGT. - g_amec->oversub_status.cmeThrottlePinLive = 0; - } - // oversubscription condition happened? if ( AMEC_INTF_GET_OVERSUBSCRIPTION() == TRUE ) { @@ -226,7 +199,7 @@ void amec_oversub_check(void) // Figure out the over-subscription reason if(g_amec->oversub_status.oversubReasonLatchCount > 1) { - // Try to figure out why we throttled based on APSS GPIO pins + // TODO: Try to figure out why we throttled based on APSS GPIO pins if( g_amec->oversub_status.oversubReasonLatchCount == OVERSUB_REASON_COUNT_TIMEOUT) { g_amec->oversub_status.oversubReason = INDETERMINATE; diff --git a/src/occ_405/amec/amec_oversub.h b/src/occ_405/amec/amec_oversub.h index 6d17a19..8da6f76 100755 --- a/src/occ_405/amec/amec_oversub.h +++ b/src/occ_405/amec/amec_oversub.h @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2011,2015 */ +/* Contributors Listed Below - COPYRIGHT 2011,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -69,10 +69,6 @@ typedef struct oversub_status // Live Status of oversub Pin uint32_t oversubPinLive : 1; - // AMEC status of oversub pin, so it doesn't - // change mid-RTL - uint32_t oversubLatchAmec : 1; - // Used for SRC logging of performance loss, // need to have countdown b/c we don't get // APSS gpio signals as quick as we get @@ -86,15 +82,6 @@ typedef struct oversub_status // For debug, tracks time oversub last went active SsxTimebase oversubActiveTime; - // Live status of CME throttle pin, doesn't change mid-RTL - uint32_t cmeThrottlePinLive :1; - - // Status of CME Throttle, doesn't get cleared until MM/TMGT - // tells us to clear it/un-throttle. - uint32_t cmeThrottleLatchAmec :1; - - // Way to emulate cmeThrottle for MNFG or Developers - uint32_t cmeThrottlePinMnfg :1; }oversub_status_t; /*----------------------------------------------------------------------------*/ @@ -105,7 +92,7 @@ void amec_oversub_isr(void); void amec_oversub_check(void); -void amec_oversub_pmax_clip(Pstate i_pstate); +void amec_set_pmax_clip(Pstate i_pstate); bool apss_gpio_get(uint8_t i_pin_number, uint8_t *o_pin_value); diff --git a/src/occ_405/amec/amec_pcap.c b/src/occ_405/amec/amec_pcap.c index fcc70aa..bf05c04 100755 --- a/src/occ_405/amec/amec_pcap.c +++ b/src/occ_405/amec/amec_pcap.c @@ -1,11 +1,11 @@ /* IBM_PROLOG_BEGIN_TAG */ /* This is an automatically generated prolog. */ /* */ -/* $Source: src/occ/amec/amec_pcap.c $ */ +/* $Source: src/occ_405/amec/amec_pcap.c $ */ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2011,2015 */ +/* Contributors Listed Below - COPYRIGHT 2011,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -81,76 +81,13 @@ uint8_t G_over_pcap_count=0; // Functions //*************************************************************************/ -////////////////////////// -// Function Specification -// -// Name: amec_pmax_clip_controller -// -// Description: Calculate the pmax_clip_freq vote. Initialized to Turbo. -// -// Thread: Real Time Loop -// -// End Function Specification -void amec_pmax_clip_controller(void) -{ -// @TODO - TEMP Pstate functions not defined yet -#if 0 - /*------------------------------------------------------------------------*/ - /* Local Variables */ - /*------------------------------------------------------------------------*/ - uint16_t l_fturbo = G_sysConfigData.sys_mode_freq.table[OCC_MODE_TURBO]; - uint32_t l_pmax_clip_freq = g_amec->proc[0].pwr_votes.pmax_clip_freq; - Pstate l_pstate = 0; - - /*------------------------------------------------------------------------*/ - /* Code */ - /*------------------------------------------------------------------------*/ - - //Note: quickPowerDrop interrupts will not preempt the real time loop - // interrupt. No locking is needed between the two interrupts. - //Note: oversubLatchAmec represents the oversubscription signal - - // See the oversub event and control oversub in AMEC - if(AMEC_INTF_GET_OVERSUBSCRIPTION()&& - (g_amec->oversub_status.oversubLatchAmec==FALSE) ) - { - // ISR already did it but still need to do it again here due to - // l_pmax_clip_freq is incorrect - l_pmax_clip_freq = G_sysConfigData.sys_mode_freq.table[OCC_MODE_MIN_FREQUENCY]; - g_amec->oversub_status.oversubLatchAmec = TRUE; - } - else if( !AMEC_INTF_GET_OVERSUBSCRIPTION() ) - { - // AMEC doesn't control it and let ISR do it - g_amec->oversub_status.oversubLatchAmec = FALSE; - } - - if(l_pmax_clip_freq < l_fturbo) - { - l_pmax_clip_freq += G_mhz_per_pstate; - - if(l_pmax_clip_freq > l_fturbo) - { - l_pmax_clip_freq = l_fturbo; - } - - //call proc_freq2pstate - l_pstate = proc_freq2pstate(l_pmax_clip_freq); - - //Set the pmax_clip register via OCI write. - amec_oversub_pmax_clip(l_pstate); - } - - g_amec->proc[0].pwr_votes.pmax_clip_freq = l_pmax_clip_freq; -#endif // @TODO - TEMP Pstate functions not defined yet -} ////////////////////////// // Function Specification // // Name: amec_pcap_calc // -// Description: Calculate the node power cap and the processor power cap. +// Description: Calculate the node, memory and processor power caps. // // Thread: Real Time Loop // @@ -164,18 +101,23 @@ void amec_pcap_calc(void) uint16_t l_node_pwr = AMECSENSOR_PTR(PWR250US)->sample; uint16_t l_p0_pwr = AMECSENSOR_PTR(PWR250USP0)->sample; int32_t l_avail_power = 0; + uint16_t mem_pwr_diff = 0; uint32_t l_proc_fraction = 0; static uint32_t L_prev_node_pcap = 0; - static bool l_apss_error_traced = FALSE; + static bool L_apss_error_traced = FALSE; /*------------------------------------------------------------------------*/ /* Code */ /*------------------------------------------------------------------------*/ - //TRAC_INFO("amec_pcap_calc: Calculate active_node_pcap, and nom_pcap_fmin."); l_oversub_state = AMEC_INTF_GET_OVERSUBSCRIPTION(); - if(TRUE == l_oversub_state) + // Determine the active power cap. norm_node_pcap is set as lowest + // between sys and user in amec_data_write_pcap() + // when in oversub only use oversub pcap if lower than norm_node_pcap + // to handle user set power cap lower than the oversub power cap + if( (TRUE == l_oversub_state) && + (g_amec->pcap.ovs_node_pcap < g_amec->pcap.norm_node_pcap) ) { g_amec->pcap.active_node_pcap = g_amec->pcap.ovs_node_pcap; } @@ -199,36 +141,78 @@ void amec_pcap_calc(void) if(l_node_pwr != 0) { l_proc_fraction = ((uint32_t)(l_p0_pwr) << 16)/l_node_pwr; - if(l_apss_error_traced) + if(L_apss_error_traced) { TRAC_ERR("PCAP: PWR250US sensor is no longer 0."); - l_apss_error_traced = FALSE; + L_apss_error_traced = FALSE; + } + + // check if allowed to increase power AND memory throttled due to pcap + if((l_avail_power > 0) && (g_amec->pcap.active_mem_level != 0)) + { + // un-throttle memory if there is enough available power between + // current and new throttles + if (CURRENT_MODE() == OCC_MODE_NOMINAL) + { + mem_pwr_diff = g_amec->pcap.nominal_mem_pwr; + } + else + { + mem_pwr_diff = g_amec->pcap.turbo_mem_pwr; + } + + // currently there's only 1 mem pcap throt level so must be pcap1 + mem_pwr_diff -= g_amec->pcap.pcap1_mem_pwr; + + if(l_avail_power >= mem_pwr_diff) + { + TRAC_IMP("PCAP: Un-Throttling memory"); + g_amec->pcap.active_mem_level = 0; + // don't let the proc have any available power this tick + l_avail_power = 0; + } + } + // check if need to reduce power and frequency is already at the min + else if((l_avail_power < 0) && (g_amec->proc[0].pwr_votes.ppb_fmax == g_amec->sys.fmin)) + { + // frequency at min now shed additional power by throttling + // memory if memory is currently un-throttled due to power + if (g_amec->pcap.active_mem_level == 0) + { + TRAC_IMP("PCAP: Throttling memory"); + g_amec->pcap.active_mem_level = 1; + } + } + else + { + // no changes to memory throttles due to power } } else { - if(!l_apss_error_traced) + if(!L_apss_error_traced) { TRAC_ERR("PCAP: PWR250US sensor is showing a value of 0."); - l_apss_error_traced = TRUE; + L_apss_error_traced = TRUE; } } - g_amec->pcap.active_proc_pcap = l_p0_pwr + ((l_proc_fraction * l_avail_power) >> 16); - - //TRAC_INFO("PCAP: calculated active proc pcap: avail_power[0x%X],proc_fraction[0x%X]," - // "active_proc_pcap[0x%X].",l_avail_power,l_proc_fraction,g_amec->pcap.active_proc_pcap); - - //NOTE: Power capping will not affect nominal cores unless a customer power cap is set below the - // max pcap or oversubscription occurs. - // However, nominal cores will drop below nominal if ppb_fmax drops below nominal. - if(g_amec->pcap.active_node_pcap < G_sysConfigData.pcap.max_pcap) + // skip processor changes until memory is un-capped + if(!g_amec->pcap.active_mem_level) { - g_amec->proc[0].pwr_votes.nom_pcap_fmin = G_sysConfigData.sys_mode_freq.table[OCC_MODE_MIN_FREQUENCY]; - } - else - { - g_amec->proc[0].pwr_votes.nom_pcap_fmin = G_sysConfigData.sys_mode_freq.table[OCC_MODE_NOMINAL]; + g_amec->pcap.active_proc_pcap = l_p0_pwr + ((l_proc_fraction * l_avail_power) >> 16); + + //NOTE: Power capping will not affect nominal cores unless a customer pcap + // is set below the max pcap or oversubscription occurs. However, + // nominal cores will drop below nominal if ppb_fmax drops below nominal + if(g_amec->pcap.active_node_pcap < G_sysConfigData.pcap.max_pcap) + { + g_amec->proc[0].pwr_votes.nom_pcap_fmin = G_sysConfigData.sys_mode_freq.table[OCC_MODE_MIN_FREQUENCY]; + } + else + { + g_amec->proc[0].pwr_votes.nom_pcap_fmin = G_sysConfigData.sys_mode_freq.table[OCC_MODE_NOMINAL]; + } } } @@ -510,21 +494,21 @@ void amec_power_control(void) /* Code */ /*------------------------------------------------------------------------*/ - // Call amec pmax clip controller to control the Pmax_clip register setting - // and voting box input. - amec_pmax_clip_controller(); - - // Calculate the power cap for the processor and the power capping limit + // Calculate the pcap for the proc, memory and the power capping limit // for nominal cores. amec_pcap_calc(); - // Calculate the voting box input frequency for staying with the current pcap - amec_pcap_controller(); + // skip processor changes until memory is un-capped + if(!g_amec->pcap.active_mem_level) + { + // Calculate voting box input freq for staying with the current pcap + amec_pcap_controller(); - // Calculate the performance preserving bounds voting box input frequency. - amec_ppb_fmax_calc(); + // Calculate the performance preserving bounds voting box input freq + amec_ppb_fmax_calc(); + } - // Check for connector overcurrent condition and calculate voting box input frequency. + // Check for connector oc condition and calculate voting box input freq amec_conn_oc_controller(); } diff --git a/src/occ_405/amec/amec_pcap.h b/src/occ_405/amec/amec_pcap.h index 47a065b..70c9147 100755 --- a/src/occ_405/amec/amec_pcap.h +++ b/src/occ_405/amec/amec_pcap.h @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2011,2015 */ +/* Contributors Listed Below - COPYRIGHT 2011,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -55,6 +55,10 @@ typedef struct amec_pcap uint16_t norm_node_pcap; //Normal node power cap in 1W units uint16_t active_node_pcap; //Currently active node power cap in 1W units uint16_t active_proc_pcap; //Currently active proc power cap in 1W units + uint16_t nominal_mem_pwr; //Memory power in 1W units for nominal throttles + uint16_t turbo_mem_pwr; //Memory power in 1W units for turbo throttles + uint16_t pcap1_mem_pwr; //Memory power in 1W units for power capping level 1 throttles + uint8_t active_mem_level; //Currently active memory throttles pcap level 0=no active mem pcap } amec_pcap_t; //************************************************************************* diff --git a/src/occ_405/amec/amec_service_codes.h b/src/occ_405/amec/amec_service_codes.h index 73146a2..ddc92e0 100755 --- a/src/occ_405/amec/amec_service_codes.h +++ b/src/occ_405/amec/amec_service_codes.h @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2011,2015 */ +/* Contributors Listed Below - COPYRIGHT 2011,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -65,6 +65,7 @@ enum occAmecModuleId AMEC_HEALTH_CHECK_PROC_TIMEOUT = AMEC_COMP_ID | 0x14, AMEC_HEALTH_CHECK_PROC_VRHOT = AMEC_COMP_ID | 0x15, AMEC_CALC_DTS_SENSORS = AMEC_COMP_ID | 0x16, + AMEC_SET_FREQ_RANGE = AMEC_COMP_ID | 0x17, }; /*----------------------------------------------------------------------------*/ diff --git a/src/occ_405/amec/amec_slave_smh.c b/src/occ_405/amec/amec_slave_smh.c index c42c815..c3f5454 100755 --- a/src/occ_405/amec/amec_slave_smh.c +++ b/src/occ_405/amec/amec_slave_smh.c @@ -245,8 +245,9 @@ void amec_slv_check_apss_fail(void) l_pmax_rail_freq = G_sysConfigData.sys_mode_freq.table[OCC_MODE_NOMINAL]; l_pstate = proc_freq2pstate(l_pmax_rail_freq); - // Set the Pmax_rail register via OCI write - amec_oversub_pmax_clip(l_pstate); + // Set the Pmax clip via PGPE + // There is no Pmax "rail" in P9, just set clips via PGPE + amec_set_pmax_clip(l_pstate); L_lower_pmax_rail = TRUE; L_raise_pmax_rail = FALSE; @@ -260,8 +261,8 @@ void amec_slv_check_apss_fail(void) l_pmax_rail_freq = G_sysConfigData.sys_mode_freq.table[OCC_MODE_TURBO]; l_pstate = proc_freq2pstate(l_pmax_rail_freq); - // Set the Pmax_rail register via OCI write - amec_oversub_pmax_clip(l_pstate); + // Set the Pmax clip via PGPE + amec_set_pmax_clip(l_pstate); L_lower_pmax_rail = FALSE; L_raise_pmax_rail = TRUE; @@ -293,10 +294,6 @@ void amec_slv_common_tasks_pre(void) // Update the FW Worst Case sensors every tick amec_update_fw_sensors(); - // Update the fast core data sensors every tick -// @TODO - TEMP - Not ready yet in Phase 1 -// amec_update_fast_core_data_sensors(); - // Update the sensors that come from the APSS every tick amec_update_apss_sensors(); @@ -324,8 +321,7 @@ void amec_slv_common_tasks_pre(void) amec_update_current_sensor(); // Compute estimate for Vdd output current // Over-subscription check -// @TODO - TEMP - Not ready yet in Phase 1 -// amec_oversub_check(); + amec_oversub_check(); } // Function Specification diff --git a/src/occ_405/cent/centaur_control.c b/src/occ_405/cent/centaur_control.c index 461d7c9..08e3005 100755 --- a/src/occ_405/cent/centaur_control.c +++ b/src/occ_405/cent/centaur_control.c @@ -1,11 +1,11 @@ /* IBM_PROLOG_BEGIN_TAG */ /* This is an automatically generated prolog. */ /* */ -/* $Source: src/occ/cent/centaur_control.c $ */ +/* $Source: src/occ_405/cent/centaur_control.c $ */ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2014,2015 */ +/* Contributors Listed Below - COPYRIGHT 2014,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -178,17 +178,27 @@ void cent_update_nlimits(uint32_t i_cent) l_active_limits01->min_n_per_mba = l_state_limits01->min_n_per_mba; l_active_limits23->min_n_per_mba = l_state_limits23->min_n_per_mba; - if(CURRENT_MODE() == OCC_MODE_NOMINAL) + //Power Capping memory? + if(g_amec->pcap.active_mem_level == 1) + { + l_mba01_mba_maxn = l_state_limits01->pcap_n_per_mba; + l_mba01_chip_maxn = l_state_limits01->pcap_n_per_chip; + l_mba23_mba_maxn = l_state_limits23->pcap_n_per_mba; + l_mba23_chip_maxn = l_state_limits23->pcap_n_per_chip; + } + else if(CURRENT_MODE() == OCC_MODE_NOMINAL) { l_mba01_mba_maxn = l_state_limits01->nom_n_per_mba; l_mba01_chip_maxn = l_state_limits01->nom_n_per_chip; l_mba23_mba_maxn = l_state_limits23->nom_n_per_mba; l_mba23_chip_maxn = l_state_limits23->nom_n_per_chip; } - else //DPS, TURBO, FFO, and SPS modes will use these settings + else //all other modes will use turbo settings { l_mba01_mba_maxn = l_state_limits01->turbo_n_per_mba; + l_mba01_chip_maxn = l_state_limits01->turbo_n_per_chip; l_mba23_mba_maxn = l_state_limits23->turbo_n_per_mba; + l_mba23_chip_maxn = l_state_limits23->turbo_n_per_chip; } l_active_limits01->max_n_per_chip = l_mba01_chip_maxn; diff --git a/src/occ_405/cmdh/cmdh_fsp_cmds_datacnfg.c b/src/occ_405/cmdh/cmdh_fsp_cmds_datacnfg.c index 33cefed..e4e2414 100755 --- a/src/occ_405/cmdh/cmdh_fsp_cmds_datacnfg.c +++ b/src/occ_405/cmdh/cmdh_fsp_cmds_datacnfg.c @@ -1696,6 +1696,9 @@ errlHndl_t data_store_mem_throt(const cmdh_fsp_cmd_t * i_cmd_ptr, uint8_t i; uint16_t l_configured_mbas = 0; bool l_invalid_input = TRUE; //Assume bad input + uint32_t l_total_turbo_mem_power = 0; + uint32_t l_total_nominal_mem_power = 0; + uint32_t l_total_pcap_mem_power = 0; do { @@ -1777,8 +1780,8 @@ errlHndl_t data_store_mem_throt(const cmdh_fsp_cmd_t * i_cmd_ptr, // Copy into a temporary buffer while we check for N values of 0 memcpy(&l_temp_set, &(l_data_set->min_n_per_mba), sizeof(mem_throt_config_data_t)); - // A 0 for any N value is an error - for(l_n_ptr = &l_temp_set.min_n_per_mba; l_n_ptr <= &l_temp_set.reserved_mem_power; l_n_ptr++) + // A 0 for any power or N value is an error + for(l_n_ptr = &l_temp_set.min_n_per_mba; l_n_ptr <= &l_temp_set.nom_mem_power; l_n_ptr++) { if(!(*l_n_ptr)) { @@ -1818,38 +1821,29 @@ errlHndl_t data_store_mem_throt(const cmdh_fsp_cmd_t * i_cmd_ptr, l_configured_mbas |= 1 << ((cent* NUM_MBAS_PER_CENTAUR) + mba); } - } // data_sets for loop - if(l_err) // Invalid Info Parameter? - { - break; - } + // Add memory power + l_total_turbo_mem_power += l_data_set->turbo_mem_power; + l_total_nominal_mem_power += l_data_set->nom_mem_power; + l_total_pcap_mem_power += l_data_set->pcap_mem_power; - } while(0); + } // data_sets for loop + } while(0); if(!l_err) { // If there were no errors, indicate that we got this data G_data_cnfg->data_mask |= DATA_MASK_MEM_THROT; + CMDH_TRAC_IMP("data_store_mem_throt: Got valid mem throt packet. configured_mba_bitmap=0x%04x", + l_configured_mbas); - if(MEM_TYPE_NIMBUS == G_sysConfigData.mem_type) - { - CMDH_TRAC_IMP("data_store_mem_throt: Got valid mem throt packet. " - "configured DIMM bitmap=0x%04x", - l_configured_mbas); - } - else if (MEM_TYPE_CUMULUS == G_sysConfigData.mem_type) - { - CMDH_TRAC_IMP("data_store_mem_throt: Got valid centaur mem throt packet. " - "configured_mba_bitmap=0x%04x", - l_configured_mbas); - - } - - // Update the configured mba bitmap + // Update the configured mba bitmap and save the total memory powers G_configured_mbas = l_configured_mbas; - + // g_amec is in Watts, config data is in cW + g_amec->pcap.nominal_mem_pwr = l_total_nominal_mem_power / 100; + g_amec->pcap.turbo_mem_pwr = l_total_turbo_mem_power / 100; + g_amec->pcap.pcap1_mem_pwr = l_total_pcap_mem_power / 100; } return l_err; @@ -2181,7 +2175,7 @@ errlHndl_t DATA_store_cnfgdata (const cmdh_fsp_cmd_t * i_cmd_ptr, if((!l_errlHndl) && (l_new_data)) { // Notify AMEC component of new data - AMEC_data_change(l_new_data); + l_errlHndl = AMEC_data_change(l_new_data); } if(l_errlHndl) diff --git a/src/occ_405/cmdh/cmdh_fsp_cmds_datacnfg.h b/src/occ_405/cmdh/cmdh_fsp_cmds_datacnfg.h index 4c0f3ad..206bdc5 100755 --- a/src/occ_405/cmdh/cmdh_fsp_cmds_datacnfg.h +++ b/src/occ_405/cmdh/cmdh_fsp_cmds_datacnfg.h @@ -1,11 +1,11 @@ /* IBM_PROLOG_BEGIN_TAG */ /* This is an automatically generated prolog. */ /* */ -/* $Source: src/occ/cmdh/cmdh_fsp_cmds_datacnfg.h $ */ +/* $Source: src/occ_405/cmdh/cmdh_fsp_cmds_datacnfg.h $ */ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2011,2015 */ +/* Contributors Listed Below - COPYRIGHT 2011,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -287,7 +287,7 @@ typedef struct __attribute__ ((packed)) // Provides memory throttle min and max values for Nimbus systems typedef struct __attribute__ ((packed)) { - uint8_t mc_num; // Physical MC: [0=MC01, 2=MC23] + uint8_t mc_num; // Physical MC: [0=MC01, 1=MC23] uint8_t port_num; // Physical port # [0-3] } cmdh_mem_throt_nimbus_info_t; @@ -310,23 +310,23 @@ typedef struct __attribute__ ((packed)) cmdh_mem_throt_info_t mem_throt_info; // Nimbus/Cumulus information header uint16_t min_n_per_mba; // Lowest per MBA allowed numerator - uint16_t min_mem_power; // Max mem Power @min (x0.1W) + uint16_t min_mem_power; // Max mem Power @min (x0.01W) uint16_t turbo_n_per_mba; // Static per MBA numerator @Turbo uint16_t turbo_n_per_chip; // Static per chip numerator @Turbo - uint16_t turbo_mem_power; // Max memory power @Turbo (x0.1W) + uint16_t turbo_mem_power; // Max memory power @Turbo (x0.01W) uint16_t pcap_n_per_mba; // Static per MBA numerator @PCAP uint16_t pcap_n_per_chip; // Static per chip numerator @PCAP - uint16_t pcap_mem_power; // Max memory power @PCAP (x0.1W) + uint16_t pcap_mem_power; // Max memory power @PCAP (x0.01W) - uint16_t nom_n_per_mba; // Static per MBA @Redundant (no ovs) - uint16_t nom_n_per_chip; // Static per chip @Redundant - uint16_t nom_mem_power; // Max memory power @Redundant(x0.1W) + uint16_t nom_n_per_mba; // Static per MBA N for nominal mode + uint16_t nom_n_per_chip; // Static per chip N for nominal mode + uint16_t nom_mem_power; // Max memory power @nominal (x0.01W) - uint16_t reserved_n_per_mba; // reserved - uint16_t reserved_n_per_chip; // reserved - uint16_t reserved_mem_power; // reserved + uint16_t reserved1; // reserved + uint16_t reserved2; // reserved + uint16_t reserved3; // reserved } cmdh_mem_throt_data_set_t; diff --git a/src/occ_405/cmdh/cmdh_mnfg_intf.c b/src/occ_405/cmdh/cmdh_mnfg_intf.c index cd38489..edaf3bb 100755 --- a/src/occ_405/cmdh/cmdh_mnfg_intf.c +++ b/src/occ_405/cmdh/cmdh_mnfg_intf.c @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2011,2015 */ +/* Contributors Listed Below - COPYRIGHT 2011,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -32,8 +32,6 @@ #include "sensor_query_list.h" #include "amec_smh.h" #include "amec_master_smh.h" -#include "centaur_data.h" -#include "centaur_control.h" extern task_t G_task_table[TASK_END]; @@ -237,69 +235,22 @@ uint8_t cmdh_mnfg_mem_slew(const cmdh_fsp_cmd_t * i_cmd_ptr, // If we made it here, that means we are starting up a slew run TRAC_INFO("cmdh_mnfg_mem_slew: We are about to start auto-slewing function"); -// TEMP -- NOT SUPPORTED YET IN PHASE1 -// when implementing see dimm/dimm.c - memory_init() -/* - // Force activation of memory monitoring and control - if(!rtl_task_is_runnable(TASK_ID_CENTAUR_CONTROL)) - { - uint32_t l_cent, l_mba; - - // Only run initialization on an active OCC - if(!IS_OCC_STATE_ACTIVE()) - { - TRAC_ERR("cmdh_mnfg_mem_slew: OCC must be active to start mem slewing"); - l_rc = ERRL_RC_INVALID_STATE; - break; - } - - // Force all MBA's to be present - G_configured_mbas = -1; - - TRAC_INFO("cmdh_mnfg_mem_slew: calling centaur_init()"); - centaur_init(); //no rc, handles errors internally - - // Check if centaur_init resulted in a reset - // since we don't have a return code from centaur_init. - if(isSafeStateRequested()) - { - TRAC_ERR("cmdh_mnfg_mem_slew: OCC is being reset"); - l_rc = ERRL_RC_INTERNAL_FAIL; - break; - } + // If the OCC is active (we can only run auto-slew in active state) the memory control + // task must be running and there is no support (or need) to force activation of + // memory monitoring and control - for(l_cent = 0; l_cent < MAX_NUM_CENTAURS; l_cent++) - { - if(!CENTAUR_PRESENT(l_cent)) - { - continue; - } - - for(l_mba = 0; l_mba < NUM_MBAS_PER_CENTAUR; l_mba++) - { - mem_throt_config_data_t * l_throt_ptr = - &G_sysConfigData.mem_throt_limits[l_cent][l_mba]; - - // Uses values seen on tuleta as defaults - l_throt_ptr->min_n_per_mba = 13; - l_throt_ptr->nom_n_per_mba = 72; - l_throt_ptr->nom_n_per_chip = 72; - l_throt_ptr->pcap1_n_per_mba = 72; - l_throt_ptr->pcap2_n_per_mba = 72; - l_throt_ptr->ovs_n_per_mba = 72; - l_throt_ptr->ovs_n_per_chip = 72; - } - - } - - - // Initialization was successful. - // Set task flags to allow centaur control task to run and - // also to prevent us from doing initialization again. - G_task_table[TASK_ID_CENTAUR_DATA].flags = CENTAUR_DATA_RTL_FLAGS; - G_task_table[TASK_ID_CENTAUR_CONTROL].flags = CENTAUR_CONTROL_RTL_FLAGS; + if(!IS_OCC_STATE_ACTIVE()) + { + TRAC_ERR("cmdh_mnfg_mem_slew: OCC must be active to start mem slewing"); + l_rc = ERRL_RC_INVALID_STATE; + break; + } + if(!rtl_task_is_runnable(TASK_ID_MEMORY_CONTROL)) + { + TRAC_ERR("cmdh_mnfg_mem_slew: memory control task not running"); + l_rc = ERRL_RC_INTERNAL_FAIL; + break; } -*/ // Zero out the slew count g_amec->mnfg_parms.mem_slew_counter = 0; diff --git a/src/occ_405/dcom/dcom.c b/src/occ_405/dcom/dcom.c index 87ae396..df00eeb 100755 --- a/src/occ_405/dcom/dcom.c +++ b/src/occ_405/dcom/dcom.c @@ -450,6 +450,8 @@ void dcom_build_occfw_msg( const dcom_error_type_t i_which_msg ) // End Function Specification void task_dcom_parse_occfwmsg(task_t *i_self) { + errlHndl_t l_errl = NULL; + if(G_occ_role == OCC_MASTER) { // Local slave index counter @@ -549,7 +551,12 @@ void task_dcom_parse_occfwmsg(task_t *i_self) G_data_cnfg->data_mask |= DATA_MASK_FREQ_PRESENT; // Notify AMEC that the frequencies have changed - AMEC_data_change(DATA_MASK_FREQ_PRESENT); + l_errl = AMEC_data_change(DATA_MASK_FREQ_PRESENT); + if(l_errl) + { + // Commit log + commitErrl(&l_errl); + } } } else diff --git a/src/occ_405/dimm/dimm_control.c b/src/occ_405/dimm/dimm_control.c index 1188e76..2b3a43d 100644 --- a/src/occ_405/dimm/dimm_control.c +++ b/src/occ_405/dimm/dimm_control.c @@ -111,7 +111,6 @@ bool dimm_control(uint8_t mc, uint8_t port) // // End Function Specification -#define DIMM_TRACE_THROTTLE_DELAY 8 void dimm_update_nlimits(uint8_t mc, uint8_t port) { /*------------------------------------------------------------------------*/ @@ -123,6 +122,10 @@ void dimm_update_nlimits(uint8_t mc, uint8_t port) /*------------------------------------------------------------------------*/ /* Code */ /*------------------------------------------------------------------------*/ + if (L_trace_throttle_count == 0) + { + L_trace_throttle_count = G_configured_mbas; + } do { @@ -138,12 +141,18 @@ void dimm_update_nlimits(uint8_t mc, uint8_t port) //Minimum N value is not state dependent l_active_limits->min_n_per_mba = l_state_limits->min_n_per_mba; - if(CURRENT_MODE() == OCC_MODE_NOMINAL) + //Power Capping memory? + if(g_amec->pcap.active_mem_level == 1) + { + l_port_dimm_maxn = l_state_limits->pcap_n_per_chip; + l_slot_dimm_maxn = l_state_limits->pcap_n_per_mba; + } + else if(CURRENT_MODE() == OCC_MODE_NOMINAL) { l_port_dimm_maxn = l_state_limits->nom_n_per_chip; l_slot_dimm_maxn = l_state_limits->nom_n_per_mba; } - else //DPS, TURBO, FFO, and SPS modes will use these settings + else //all other modes will use turbo settings { l_port_dimm_maxn = l_state_limits->turbo_n_per_chip; l_slot_dimm_maxn = l_state_limits->turbo_n_per_mba; @@ -156,25 +165,23 @@ void dimm_update_nlimits(uint8_t mc, uint8_t port) { l_active_limits->max_n_per_mba = l_slot_dimm_maxn; - //Don't repeatedly trace same slot changing, just once - if(!L_trace_throttle_count) + //Don't trace all MCAs changing, just trace one they will all + //be the same unless there is a different number of DIMMs behind + //the MCAs or a mix of DIMM sizes is supported + if(L_trace_throttle_count == G_configured_mbas) { - L_trace_throttle_count = DIMM_TRACE_THROTTLE_DELAY; TRAC_IMP("dimm_update_nlimits: New DIMM slot throttle values: " - "MC#|Port:[0x%08x], " - "Max|Min slot Power:[0x%08x], Max port power:[0x%08x] ", - (uint32_t)((mc << 16) | port), - (uint32_t)( l_active_limits->min_n_per_mba | - (l_active_limits->max_n_per_mba << 16)), - l_active_limits->max_n_per_chip << 16); - + "MC#|Port:[0x%04x], " + "Max|Min N_PER_MBA:[0x%08x], Max N_PER_CHIP:[0x%04x] ", + (uint16_t)((mc << 8) | port), + (uint32_t)( (l_active_limits->max_n_per_mba << 16) | + l_active_limits->min_n_per_mba), + l_active_limits->max_n_per_chip); } } - if(L_trace_throttle_count) - { - L_trace_throttle_count--; - } + L_trace_throttle_count &= ~(0x8000 >> ((mc * (MAX_NUM_MCU_PORTS)) + port)); + } // NIMBUS_DIMM_THROTTLING_CONFIGURED ? }while(0); diff --git a/src/occ_405/main.c b/src/occ_405/main.c index b12ad1c..8c26e8f 100755 --- a/src/occ_405/main.c +++ b/src/occ_405/main.c @@ -576,8 +576,7 @@ void slave_occ_init() { // Init the DPSS oversubscription IRQ handler MAIN_DBG("Initializing Oversubscription IRQ..."); - // TEMP -- NO DPSS/ERRL YET -/* + errlHndl_t l_errl = dpss_oversubscription_irq_initialize(); if( l_errl ) @@ -585,15 +584,14 @@ void slave_occ_init() // Trace and commit error MAIN_TRAC_ERR("Initialization of Oversubscription IRQ handler failed"); - // commit log ... log should be deleted by reader mechanism - // TEMP -- NO ERRL YET - //commitErrl( &l_errl ); + // commit log + commitErrl( &l_errl ); } else { MAIN_TRAC_INFO("Oversubscription IRQ initialized"); } -*/ + //Set up doorbell queues dcom_initialize_pbax_queues(); diff --git a/src/occ_405/mode.c b/src/occ_405/mode.c index e4a6715..84bc0e2 100755 --- a/src/occ_405/mode.c +++ b/src/occ_405/mode.c @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2011,2015 */ +/* Contributors Listed Below - COPYRIGHT 2011,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -53,10 +53,6 @@ OCC_MODE G_occ_external_req_mode = OCC_MODE_NOCHANGE; // Mode that TMGT is requesting OCC go to in KVM OCC_MODE G_occ_external_req_mode_kvm = OCC_MODE_NOCHANGE; -// Indicates if OCC must actually change the voltage / frequency during -// a mode change. -SMGR_SMS_CMD_TYPE G_occ_internal_sms = SMGR_SMS_VF_INFO_ONLY; - // Indicates if we are currently in a mode transition bool G_mode_transition_occuring = FALSE; @@ -236,24 +232,11 @@ errlHndl_t SMGR_set_mode(const OCC_MODE i_mode, // Load correct thermal thresholds based on the current mode l_errlHndl = AMEC_data_write_thrm_thresholds(CURRENT_MODE()); - // Update the CPU speed in AME? - // Register the New Mode? - // Update Power Policy Requirements? - // Update CPM Calibration - }while(0); - // If we have a mode change failure, Mode change flag needs to be set, - // otherwise, it needs be be cleared/unset. - if(l_errlHndl) - { - - } - // Unlock critical section ssx_semaphore_post(&G_smgrModeChangeSem); - return l_errlHndl; } diff --git a/src/occ_405/mode.h b/src/occ_405/mode.h index 818cada..dfce6ca 100755 --- a/src/occ_405/mode.h +++ b/src/occ_405/mode.h @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2011,2015 */ +/* Contributors Listed Below - COPYRIGHT 2011,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -38,9 +38,6 @@ #define REQUESTED_MODE() G_occ_internal_req_mode // Returns the 'Requested' SMS Mode -#define CURRENT_SMS() G_occ_internal_sms - -// Returns the 'Requested' SMS Mode #define VALID_MODE(mode) ((mode < OCC_MODE_COUNT) ? 1 : 0) // Typedef of the various modes that TMGT can put OCC into. diff --git a/src/occ_405/occ_service_codes.h b/src/occ_405/occ_service_codes.h index e867cd9..a4633b2 100644 --- a/src/occ_405/occ_service_codes.h +++ b/src/occ_405/occ_service_codes.h @@ -207,6 +207,8 @@ enum occExtReasonCode ERC_MEM_CONTROL_SCHEDULE_FAILURE = 0x0080, ERC_MEM_CONTROL_COMPLETE_FAILURE = 0x0081, + + ERC_FW_ZERO_FREQ_LIMIT = 0x0090, }; // Error log Module Ids diff --git a/src/occ_405/occ_sys_config.h b/src/occ_405/occ_sys_config.h index c065786..8df5579 100755 --- a/src/occ_405/occ_sys_config.h +++ b/src/occ_405/occ_sys_config.h @@ -233,31 +233,33 @@ typedef struct uint8_t source; // source of PCAP value currently in use } pcap_config_data_t; + // source of PCAP value #define OUT_OF_BAND 1 // source is BMC or (H)TMGT #define IN_BAND 2 // source is OPAL -// Memory Centaur Throttle settings + +// Memory Throttle settings typedef struct { uint16_t min_n_per_mba; //minimum value - uint16_t min_mem_power; //Max mem Power @min (x0.1W) + uint16_t min_mem_power; //Max mem Power @min (x0.01W) - uint16_t turbo_n_per_mba; //max mba value for Power Cap @Turbo + uint16_t turbo_n_per_mba; //max mba value for Turbo uint16_t turbo_n_per_chip; //Static per chip numerator @Turbo - uint16_t turbo_mem_power; //max memory power @Turbo L1 + uint16_t turbo_mem_power; //max memory power @Turbo - uint16_t pcap_n_per_mba; //max mba value for Power Cap Level 2 + uint16_t pcap_n_per_mba; //max mba value for Power Cap uint16_t pcap_n_per_chip; //Static per chip numerator @PCAP - uint16_t pcap_mem_power; //max memory power @PCAP L2 + uint16_t pcap_mem_power; //max memory power @PCAP uint16_t nom_n_per_mba; //max mba value for nominal mode uint16_t nom_n_per_chip; //chip setting for nominal mode - uint16_t nom_mem_power; //max memory power @Redundant + uint16_t nom_mem_power; //max memory power @nominal - uint16_t reserved_n_per_mba; //reserved - uint16_t reserved_n_per_chip; //reserved - uint16_t reserved_mem_power; //reserved + uint16_t reserved1; //reserved + uint16_t reserved2; //reserved + uint16_t reserved3; //reserved } mem_throt_config_data_t; diff --git a/src/occ_405/rtls/rtls.c b/src/occ_405/rtls/rtls.c index 51a0bba..5788c69 100755 --- a/src/occ_405/rtls/rtls.c +++ b/src/occ_405/rtls/rtls.c @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2011,2015 */ +/* Contributors Listed Below - COPYRIGHT 2011,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -176,9 +176,9 @@ bool rtl_task_is_runnable(const task_id_t i_task_id) if ( i_task_id < TASK_END ) { - if ( G_task_table[i_task_id].flags & RTL_FLAG_RUN ) + if ( (G_task_table[i_task_id].flags & G_run_mask) == G_run_mask ) { - // Yes, the task CAN run + // Yes, the task CAN run. task's flags match the global run mask task_can_run = TRUE; } } diff --git a/src/occ_405/state.h b/src/occ_405/state.h index 8e8e9ba..16d1940 100755 --- a/src/occ_405/state.h +++ b/src/occ_405/state.h @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2011,2015 */ +/* Contributors Listed Below - COPYRIGHT 2011,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -66,21 +66,8 @@ typedef enum #define OCC_STATE_IS_VALID(state) ((state == OCC_STATE_NOCHANGE) || \ (state == OCC_STATE_OBSERVATION) || \ (state == OCC_STATE_ACTIVE)) -/** - * @enum SMGR_SMS_CMD_TYPE - * @brief SMGR set-mode-state commands version 0 contains a byte that indicates if - * the TPMD must actually change the voltage / frequency during a mode change. - */ -typedef enum -{ - SMGR_SMS_VF_INFO_ONLY = 0x00, - SMGR_SMS_VF_CHANGE_REQ = 0x01, - SMGR_SMS_STATIC_VF_CHANGE_REQ = 0x02, -} SMGR_SMS_CMD_TYPE; -extern SMGR_SMS_CMD_TYPE G_occ_internal_sms; // TODO: Move to state.c /** - * @enum SMGR_SMS_STATUS_TYPE * @brief TMGT Poll contains a byte that indicates status based on this * bitmask */ @@ -171,7 +158,6 @@ typedef struct extern OCC_STATE G_occ_internal_state; extern OCC_STATE G_occ_internal_req_state; -extern SMGR_SMS_CMD_TYPE G_occ_internal_sms; extern OCC_STATE G_occ_master_state; extern OCC_STATE G_occ_external_req_state; |