summaryrefslogtreecommitdiffstats
path: root/src/occ_405/amec/amec_pcap.c
diff options
context:
space:
mode:
authormbroyles <mbroyles@us.ibm.com>2016-09-19 11:54:55 -0500
committerMartha Broyles <mbroyles@us.ibm.com>2016-09-29 11:28:53 -0400
commita57f623c26bdf3889703ed63334745c966c6096d (patch)
treeb2f81389aa3bf5a420c6a115d8c10ae787375ede /src/occ_405/amec/amec_pcap.c
parentd137bd848a05d5afd8a9ee5c9803f421ebd0a922 (diff)
downloadtalos-occ-a57f623c26bdf3889703ed63334745c966c6096d.tar.gz
talos-occ-a57f623c26bdf3889703ed63334745c966c6096d.zip
Enable power capping and oversubscription. RTC:137621 RTC:133156
Change-Id: I98b745ccb56d89d066508d4195250b1bf446dbc6 Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/29898 Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com> Reviewed-by: Christopher J. Cain <cjcain@us.ibm.com> Reviewed-by: Martha Broyles <mbroyles@us.ibm.com>
Diffstat (limited to 'src/occ_405/amec/amec_pcap.c')
-rwxr-xr-xsrc/occ_405/amec/amec_pcap.c178
1 files changed, 81 insertions, 97 deletions
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();
}
OpenPOWER on IntegriCloud