summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/dimm_structs.h111
-rwxr-xr-xsrc/gpe_export.h36
-rw-r--r--src/gpe_util.h (renamed from src/occ_gpe0/gpe_util.h)0
-rw-r--r--src/include/proc_shared.h2
-rw-r--r--src/ipc_func_ids.h1
-rwxr-xr-xsrc/occ_405/Makefile3
-rw-r--r--src/occ_405/amec/amec_controller.c4
-rwxr-xr-xsrc/occ_405/amec/amec_freq.c15
-rwxr-xr-xsrc/occ_405/amec/amec_health.c302
-rw-r--r--src/occ_405/amec/amec_sensors_centaur.c5
-rwxr-xr-xsrc/occ_405/amec/amec_slave_smh.c5
-rwxr-xr-xsrc/occ_405/amec/amec_sys.h5
-rwxr-xr-xsrc/occ_405/cent/centaur_control.c362
-rwxr-xr-xsrc/occ_405/cent/centaur_control.h50
-rwxr-xr-xsrc/occ_405/cent/centaur_data.c14
-rwxr-xr-xsrc/occ_405/cent/centaur_data.h19
-rwxr-xr-xsrc/occ_405/cent/centaur_data_service_codes.h7
-rwxr-xr-xsrc/occ_405/cmdh/cmdh_dbug_cmd.c2
-rwxr-xr-xsrc/occ_405/cmdh/cmdh_fsp_cmds.c2
-rwxr-xr-xsrc/occ_405/cmdh/cmdh_fsp_cmds_datacnfg.c199
-rwxr-xr-xsrc/occ_405/cmdh/cmdh_fsp_cmds_datacnfg.h76
-rwxr-xr-xsrc/occ_405/cmdh/cmdh_mnfg_intf.c1
-rwxr-xr-xsrc/occ_405/dimm/dimm.c152
-rw-r--r--src/occ_405/dimm/dimm.h24
-rw-r--r--src/occ_405/dimm/dimm_control.c265
-rw-r--r--src/occ_405/dimm/dimm_control.h39
-rwxr-xr-xsrc/occ_405/dimm/dimm_service_codes.h7
-rw-r--r--src/occ_405/img_defs.mk1
-rwxr-xr-xsrc/occ_405/incl/comp_ids.h3
-rwxr-xr-xsrc/occ_405/main.c25
-rw-r--r--src/occ_405/mem/memory.c411
-rw-r--r--src/occ_405/mem/memory.h76
-rw-r--r--src/occ_405/mem/memory_service_codes.h41
-rw-r--r--src/occ_405/occLinkInputFile3
-rw-r--r--src/occ_405/occ_service_codes.h3
-rwxr-xr-xsrc/occ_405/occ_sys_config.c18
-rwxr-xr-xsrc/occ_405/occ_sys_config.h53
-rwxr-xr-xsrc/occ_405/rtls/rtls.h17
-rwxr-xr-xsrc/occ_405/rtls/rtls_tables.c20
-rwxr-xr-xsrc/occ_405/state.h3
-rw-r--r--src/occ_405/topfiles.mk3
-rwxr-xr-xsrc/occ_405/trac/trac.h10
-rw-r--r--src/occ_gpe1/gpe1_dimm_control.c121
-rw-r--r--src/occ_gpe1/gpe1_dimm_read.c2
-rw-r--r--src/occ_gpe1/gpe1_dimm_reset.c1
-rw-r--r--src/occ_gpe1/ipc_func_tables.c3
-rw-r--r--src/occ_gpe1/topfiles.mk3
47 files changed, 1758 insertions, 767 deletions
diff --git a/src/dimm_structs.h b/src/dimm_structs.h
new file mode 100644
index 0000000..3337cd7
--- /dev/null
+++ b/src/dimm_structs.h
@@ -0,0 +1,111 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/dimm_control_structs.h $ */
+/* */
+/* OpenPOWER OnChipController Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2016 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+
+/* This header file is used by both occ_405 and occ_gpe1. */
+/* Contains common structures and globals. */
+
+#ifndef _DIMM_STRUCTS_H
+#define _DIMM_STRUCTS_H
+
+#include <gpe_export.h>
+#include "gpe_err.h"
+//#include "occ_sys_config.h"
+
+#define WORD_HIGH(data) ((uint32_t)(((uint64_t)data)>>32))
+#define WORD_LOW(data) ((uint32_t)(((uint64_t)data)&0xFFFFFFFF))
+
+// DIMM States (GPE1)
+typedef enum
+{
+ DIMM_STATE_INIT = 0x01, // Init interrupt registers
+ DIMM_STATE_WRITE_MODE = 0x02, // Set the mode (speed and port)
+ DIMM_STATE_WRITE_ADDR = 0x03, // Write the temp sensor address
+ DIMM_STATE_INITIATE_READ = 0x04, // Start the read
+ DIMM_STATE_READ_TEMP = 0x05, // Return the sensor reading
+ DIMM_STATE_RESET_MASTER = 0x06, // Reset master
+ DIMM_STATE_RESET_SLAVE_P0 = 0x07, // Start of slave port 0 reset
+ DIMM_STATE_RESET_SLAVE_P0_WAIT = 0x08,
+ DIMM_STATE_RESET_SLAVE_P0_COMPLETE = 0x09,
+ DIMM_STATE_RESET_SLAVE_P1 = 0x0A, // Start of slave port 1 reset
+ DIMM_STATE_RESET_SLAVE_P1_WAIT = 0x0B,
+ DIMM_STATE_RESET_SLAVE_P1_COMPLETE = 0x0C,
+} DIMM_STATE;
+
+// DIMM State Machine arguments (GPE1)
+typedef struct
+{
+ GpeErrorStruct error;
+ uint8_t state;
+ uint8_t i2cEngine;
+ uint8_t i2cAddr;
+ uint8_t i2cPort;
+ uint8_t dimm;
+ uint8_t maxPorts;
+ uint8_t temp;
+} dimm_sm_args_t;
+
+//convenient format for storing throttle settings
+typedef union
+{
+ uint32_t word32;
+ struct
+ {
+ uint32_t slot_n: 15; // DIMM Slot N Value
+ uint32_t port_n: 16; // DIMM port N Value
+ uint32_t new_n: 1; // New N Value?
+ };
+} dimm_n_value_t;
+
+
+typedef struct
+{
+ GpeErrorStruct error;
+ uint8_t mc;
+ uint8_t port;
+ dimm_n_value_t dimmNumeratorValues;
+} dimm_control_args_t;
+
+
+
+// Base Address of N/M DIMM Throttling Control Register
+#define N_M_DIMM_TCR_BASE 0x07010800
+
+/*
+MC/Port Address N/M Throttling Control Addr SCOM Address
+mc01.port0 0x07010800 + 0x00000116 = 0x07010916
+mc01.port1 0x07010840 + 0x00000116 = 0x07010956
+mc01.port2 0x07010880 + 0x00000116 = 0x07010996
+mc01.port3 0x070108C0 + 0x00000116 = 0x070109D6
+mc23.port0 0x08010800 + 0x00000116 = 0x08010916
+mc23.port1 0x08010840 + 0x00000116 = 0x08010956
+mc23.port2 0x08010880 + 0x00000116 = 0x08010996
+mc23.port3 0x080108C0 + 0x00000116 = 0x080109D6
+ */
+
+// N/M DIMM Throttling Control SCOM Register Addresses macro
+#define N_M_DIMM_TCR(mc,port) (N_M_DIMM_TCR_BASE + 0x116 + \
+ (0x01000000 * (mc)) + ( 0x40 * (port)))
+
+#endif // _DIMM_STRUCTS_H
diff --git a/src/gpe_export.h b/src/gpe_export.h
index 061866f..7f4496d 100755
--- a/src/gpe_export.h
+++ b/src/gpe_export.h
@@ -28,10 +28,6 @@
#include "gpe_err.h"
-#define WORD_HIGH(data) ((uint32_t)(((uint64_t)data)>>32))
-#define WORD_LOW(data) ((uint32_t)(((uint64_t)data)&0xFFFFFFFF))
-
-
// GPE Error structure (common to both GPEs)
typedef struct {
union
@@ -45,38 +41,6 @@ typedef struct {
uint64_t ffdc;
} GpeErrorStruct;
-
-// DIMM States (GPE1)
-typedef enum
-{
- DIMM_STATE_INIT = 0x01, // Init interrupt registers
- DIMM_STATE_WRITE_MODE = 0x02, // Set the mode (speed and port)
- DIMM_STATE_WRITE_ADDR = 0x03, // Write the temp sensor address
- DIMM_STATE_INITIATE_READ = 0x04, // Start the read
- DIMM_STATE_READ_TEMP = 0x05, // Return the sensor reading
- DIMM_STATE_RESET_MASTER = 0x06, // Reset master
- DIMM_STATE_RESET_SLAVE_P0 = 0x07, // Start of slave port 0 reset
- DIMM_STATE_RESET_SLAVE_P0_WAIT = 0x08,
- DIMM_STATE_RESET_SLAVE_P0_COMPLETE = 0x09,
- DIMM_STATE_RESET_SLAVE_P1 = 0x0A, // Start of slave port 1 reset
- DIMM_STATE_RESET_SLAVE_P1_WAIT = 0x0B,
- DIMM_STATE_RESET_SLAVE_P1_COMPLETE = 0x0C,
-} DIMM_STATE;
-
-
-// DIMM State Machine arguments (GPE1)
-typedef struct
-{
- GpeErrorStruct error;
- uint8_t state;
- uint8_t i2cEngine;
- uint8_t i2cAddr;
- uint8_t i2cPort;
- uint8_t dimm;
- uint8_t maxPorts;
- uint8_t temp;
-} dimm_sm_args_t;
-
// Arguments for doing a SCOM from GPE0
typedef struct ipc_scom_op
{
diff --git a/src/occ_gpe0/gpe_util.h b/src/gpe_util.h
index a6a086e..a6a086e 100644
--- a/src/occ_gpe0/gpe_util.h
+++ b/src/gpe_util.h
diff --git a/src/include/proc_shared.h b/src/include/proc_shared.h
index 6b71bff..1c66f25 100644
--- a/src/include/proc_shared.h
+++ b/src/include/proc_shared.h
@@ -26,8 +26,8 @@
#ifndef _PROC_SHARED_H
#define _PROC_SHARED_H
-#include "core_data.h"
#include "gpe_export.h"
+#include "core_data.h"
// Paramaters for gpe_get_core_data()
diff --git a/src/ipc_func_ids.h b/src/ipc_func_ids.h
index c9b98b9..f640674 100644
--- a/src/ipc_func_ids.h
+++ b/src/ipc_func_ids.h
@@ -63,6 +63,7 @@ IPC_FUNCIDS_TABLE_START
//These function ID's can only be sent to GPE1
IPC_FUNCIDS_ST_START(OCCHW_INST_ID_GPE1)
IPC_FUNC_ID(IPC_ST_DIMM_SM_FUNCID)
+ IPC_FUNC_ID(IPC_ST_DIMM_CONTROL_FUNCID)
IPC_FUNCIDS_ST_END(OCCHW_INST_ID_GPE1)
//Functions that are only supported by GPE2 should be defined here
diff --git a/src/occ_405/Makefile b/src/occ_405/Makefile
index d12cada..9a67a1f 100755
--- a/src/occ_405/Makefile
+++ b/src/occ_405/Makefile
@@ -67,7 +67,8 @@ LIB_DIRS = -L$(OBJDIR) \
-L$(OBJDIR)/dcom \
-L$(OBJDIR)/proc \
-L$(OBJDIR)/firdata \
- -L$(OBJDIR)/cent
+ -L$(OBJDIR)/cent \
+ -L$(OBJDIR)/mem
#default target is to make a binary application image
all: $(PPETOOLS_OBJDIR)/ppetracepp $(OBJDIR)/$(IMAGE_NAME).bin $(OBJDIR)/$(IMAGE_NAME).dis
diff --git a/src/occ_405/amec/amec_controller.c b/src/occ_405/amec/amec_controller.c
index 3a91087..fee37bb 100644
--- a/src/occ_405/amec/amec_controller.c
+++ b/src/occ_405/amec/amec_controller.c
@@ -29,12 +29,12 @@
#include <occ_common.h>
#include <sensor.h>
#include <amec_sys.h>
-#include <centaur_data.h>
+#include <memory.h>
//*************************************************************************
// Externs
//*************************************************************************
-extern cent_sensor_flags_t G_dimm_temp_expired_bitmap;
+extern dimm_sensor_flags_t G_dimm_temp_expired_bitmap;
extern uint8_t G_cent_temp_expired_bitmap;
//*************************************************************************
// Macros
diff --git a/src/occ_405/amec/amec_freq.c b/src/occ_405/amec/amec_freq.c
index 93a43fb..5cc198f 100755
--- a/src/occ_405/amec/amec_freq.c
+++ b/src/occ_405/amec/amec_freq.c
@@ -48,13 +48,13 @@
#include <amec_data.h>
#include <amec_freq.h>
#include "pss_constants.h"
-#include <centaur_data.h>
+#include <memory.h>
//*************************************************************************
// Externs
//*************************************************************************
extern uint8_t G_cent_temp_expired_bitmap;
-extern cent_sensor_flags_t G_dimm_temp_expired_bitmap;
+extern dimm_sensor_flags_t G_dimm_temp_expired_bitmap;
//*************************************************************************
// Defines/Enums
@@ -572,20 +572,20 @@ void amec_slv_mem_voting_box(void)
// Start with max allowed speed
l_vote = AMEC_MEMORY_MAX_STEP;
- l_reason = AMEC_MEM_VOTING_REASON_INIT;
+ l_reason = AMEC_MEM_VOTING_REASON_INIT; // 0
// Check vote from Centaur thermal control loop
if (l_vote > g_amec->thermalcent.speed_request)
{
l_vote = g_amec->thermalcent.speed_request;
- l_reason = AMEC_MEM_VOTING_REASON_CENT;
+ l_reason = AMEC_MEM_VOTING_REASON_CENT; // 1
}
// Check vote from DIMM thermal control loop
if (l_vote > g_amec->thermaldimm.speed_request)
{
l_vote = g_amec->thermaldimm.speed_request;
- l_reason = AMEC_MEM_VOTING_REASON_DIMM;
+ l_reason = AMEC_MEM_VOTING_REASON_DIMM; // 2
}
// Check if memory autoslewing is enabled
@@ -606,7 +606,7 @@ void amec_slv_mem_voting_box(void)
}
l_vote = g_amec->mem_speed_request + l_slew_step;
- l_reason = AMEC_MEM_VOTING_REASON_SLEW;
+ l_reason = AMEC_MEM_VOTING_REASON_SLEW; // 3
}
// Store final vote and vote reason in g_amec
@@ -619,7 +619,8 @@ void amec_slv_mem_voting_box(void)
if(!L_throttle_traced)
{
L_throttle_traced = TRUE;
- TRAC_INFO("Memory is being throttled. reason[%d] vote[%d] cent_expired[0x%02x] dimm_expired[0x%08x%08x]",
+ TRAC_INFO("Memory is being throttled. reason[%d] vote[%d] "
+ "cent_expired[0x%02x] dimm_expired[0x%08x%08x]",
l_reason,
l_vote,
G_cent_temp_expired_bitmap,
diff --git a/src/occ_405/amec/amec_health.c b/src/occ_405/amec/amec_health.c
index 7eaa84e..116dd38 100755
--- a/src/occ_405/amec/amec_health.c
+++ b/src/occ_405/amec/amec_health.c
@@ -46,13 +46,13 @@
//*************************************************************************/
// Have we already called out the dimm for overtemp (bitmap of dimms)?
-cent_sensor_flags_t G_dimm_overtemp_logged_bitmap = {0};
+dimm_sensor_flags_t G_dimm_overtemp_logged_bitmap = {0};
// Have we already called out the dimm for timeout (bitmap of dimms)?
-cent_sensor_flags_t G_dimm_timeout_logged_bitmap = {0};
+dimm_sensor_flags_t G_dimm_timeout_logged_bitmap = {0};
// Are any dimms currently in the timedout state (bitmap of dimm)?
-cent_sensor_flags_t G_dimm_temp_expired_bitmap = {0};
+dimm_sensor_flags_t G_dimm_temp_expired_bitmap = {0};
// Have we already called out the centaur for timeout (bitmap of centaurs)?
uint8_t G_cent_timeout_logged_bitmap = 0;
@@ -116,6 +116,18 @@ void amec_mem_mark_logged(uint8_t i_cent,
}
}
+
+/*
+ * Function Specification
+ *
+ * Name: amec_health_check_dimm_temp
+ *
+ * Description: Check if centaur's-dimm/rdimm-modules temperature exceeds the
+ * error temperature as defined in thermal control thresholds
+ * (ERROR field for Centaur/DIMM FRU Type)
+ *
+ * End Function Specification
+ */
void amec_health_check_dimm_temp()
{
/*------------------------------------------------------------------------*/
@@ -123,16 +135,26 @@ void amec_health_check_dimm_temp()
/*------------------------------------------------------------------------*/
uint16_t l_ot_error, l_cur_temp, l_max_temp;
sensor_t *l_sensor;
- uint32_t l_cent, l_dimm;
+ uint8_t l_dimm; // per centaur/port dimms in cumulus/nimbus
+ uint8_t l_index; // tracks centaurs/ports in cumulus/nimbus
+ uint8_t l_max_index; // #centaurs/ports in cumulus/nimbus
uint32_t l_callouts_count = 0;
uint8_t l_new_callouts;
uint64_t l_huid;
errlHndl_t l_err = NULL;
-
/*------------------------------------------------------------------------*/
/* Code */
/*------------------------------------------------------------------------*/
+ if(G_sysConfigData.mem_type == MEM_TYPE_NIMBUS)
+ {
+ l_max_index = NUM_I2C_PORTS;
+ }
+ else // MEM_TYPE_CUMULUS
+ {
+ l_max_index = MAX_NUM_CENTAURS;
+ }
+
// Check to see if any dimms have reached the error temperature that
// haven't been called out already
if(G_dimm_overtemp_bitmap.bigword == G_dimm_overtemp_logged_bitmap.bigword)
@@ -149,12 +171,12 @@ void amec_health_check_dimm_temp()
l_cur_temp,
l_max_temp);
- //iterate over all centaurs
- for(l_cent = 0; l_cent < MAX_NUM_CENTAURS; l_cent++)
+ //iterate over all dimms
+ for(l_index = 0; l_index < l_max_index; l_index++)
{
//only callout a dimm if it hasn't been called out already
- l_new_callouts = G_dimm_overtemp_bitmap.bytes[l_cent] ^
- G_dimm_overtemp_logged_bitmap.bytes[l_cent];
+ l_new_callouts = G_dimm_overtemp_bitmap.bytes[l_index] ^
+ G_dimm_overtemp_logged_bitmap.bytes[l_index];
//skip to next centaur if no new callouts for this one
if(!l_new_callouts)
@@ -165,17 +187,18 @@ void amec_health_check_dimm_temp()
//find the dimm(s) that need to be called out behind this centaur
for(l_dimm = 0; l_dimm < NUM_DIMMS_PER_CENTAUR; l_dimm++)
{
- if(!(l_new_callouts & (DIMM_SENSOR0 >> l_dimm)))
+ if(!(l_new_callouts & (DIMM_SENSOR0 >> l_dimm)) &&
+ G_dimm_overtemp_bitmap.bytes[l_index])
{
continue;
}
- l_huid = amec_mem_get_huid(l_cent, l_dimm);
+ l_huid = amec_mem_get_huid(l_index, l_dimm);
- amec_mem_mark_logged(l_cent,
+ amec_mem_mark_logged(l_index,
l_dimm,
&G_cent_overtemp_logged_bitmap,
- &G_dimm_overtemp_logged_bitmap.bytes[l_cent]);
+ &G_dimm_overtemp_logged_bitmap.bytes[l_index]);
//If we don't have an error log for the callout, create one
if(!l_err)
@@ -236,113 +259,21 @@ void amec_health_check_dimm_temp()
}
}
-void amec_health_check_cent_temp()
-{
- /*------------------------------------------------------------------------*/
- /* Local Variables */
- /*------------------------------------------------------------------------*/
- uint16_t l_ot_error, l_cur_temp, l_max_temp;
- sensor_t *l_sensor;
- uint32_t l_cent;
- uint32_t l_callouts_count = 0;
- uint8_t l_new_callouts;
- uint64_t l_huid;
- errlHndl_t l_err = NULL;
-
- /*------------------------------------------------------------------------*/
- /* Code */
- /*------------------------------------------------------------------------*/
-
- // Check to see if any centaurs have reached the error temperature that
- // haven't been called out already
- l_new_callouts = G_cent_overtemp_bitmap ^ G_cent_overtemp_logged_bitmap;
- if(!l_new_callouts)
- {
- return;
- }
-
- l_ot_error = g_amec->thermalcent.ot_error;
- l_sensor = getSensorByGsid(TEMP2MSCENT);
- l_cur_temp = l_sensor->sample;
- l_max_temp = l_sensor->sample_max;
- TRAC_ERR("amec_health_check_cent_temp: Centaur reached error temp[%d]. cur_max[%d], hist_max[%d] bitmap[0x%02X]",
- l_ot_error,
- l_cur_temp,
- l_max_temp,
- l_new_callouts);
-
- //find the centaur(s) that need to be called out
- for(l_cent = 0; l_cent < MAX_NUM_CENTAURS; l_cent++)
- {
- if(!(l_new_callouts & (CENTAUR0_PRESENT_MASK >> l_cent)))
- {
- continue;
- }
-
- l_huid = amec_mem_get_huid(l_cent, 0xff);
-
- amec_mem_mark_logged(l_cent,
- 0xff,
- &G_cent_overtemp_logged_bitmap,
- &G_dimm_overtemp_logged_bitmap.bytes[l_cent]);
-
- //If we don't have an error log for the callout, create one
- if(!l_err)
- {
- /* @
- * @errortype
- * @moduleid AMEC_HEALTH_CHECK_CENT_TEMP
- * @reasoncode CENT_ERROR_TEMP
- * @userdata1 Maximum centaur temperature
- * @userdata2 Centaur temperature threshold
- * @userdata4 OCC_NO_EXTENDED_RC
- * @devdesc Centaur memory controller(s) exceeded maximum safe
- * temperature.
- */
- l_err = createErrl(AMEC_HEALTH_CHECK_CENT_TEMP, //modId
- CENT_ERROR_TEMP, //reasoncode
- OCC_NO_EXTENDED_RC, //Extended reason code
- ERRL_SEV_PREDICTIVE, //Severity
- NULL, //Trace Buf
- DEFAULT_TRACE_SIZE, //Trace Size
- l_max_temp, //userdata1
- l_ot_error); //userdata2
-
- // Callout the "over temperature" procedure
- addCalloutToErrl(l_err,
- ERRL_CALLOUT_TYPE_COMPONENT_ID,
- ERRL_COMPONENT_ID_OVER_TEMPERATURE,
- ERRL_CALLOUT_PRIORITY_HIGH);
- l_callouts_count = 1;
- }
-
- // Callout centaur
- addCalloutToErrl(l_err,
- ERRL_CALLOUT_TYPE_HUID,
- l_huid,
- ERRL_CALLOUT_PRIORITY_MED);
-
- l_callouts_count++;
-
- //If we've reached the max # of callouts for an error log
- //commit the error log
- if(l_callouts_count == ERRL_MAX_CALLOUTS)
- {
- commitErrl(&l_err);
- }
-
- }//iterate over centaurs
-
- if(l_err)
- {
- commitErrl(&l_err);
- }
-}
-
+/*
+ * Function Specification
+ *
+ * Name: amec_health_check_dimm_timeout
+ *
+ * Description: Check for centaur-dimm/rdimm-modules timeout condition
+ * as defined in thermal control thresholds
+ * (MAX_READ_TIMEOUT field for Centaur/DIMM FRU Type)
+ *
+ * End Function Specification
+ */
void amec_health_check_dimm_timeout()
{
- static cent_sensor_flags_t L_temp_update_bitmap_prev = {0};
- cent_sensor_flags_t l_need_inc, l_need_clr, l_temp_update_bitmap;
+ static dimm_sensor_flags_t L_temp_update_bitmap_prev = {0};
+ dimm_sensor_flags_t l_need_inc, l_need_clr, l_temp_update_bitmap;
uint8_t l_dimm, l_cent;
fru_temp_t* l_fru;
errlHndl_t l_err = NULL;
@@ -363,7 +294,7 @@ void amec_health_check_dimm_timeout()
G_dimm_temp_updated_bitmap.bigword = 0;
//check if we need to increment any timers (haven't been updated in the last second)
- l_need_inc.bigword = G_cent_enabled_sensors.bigword & ~l_temp_update_bitmap.bigword;
+ l_need_inc.bigword = G_dimm_enabled_sensors.bigword & ~l_temp_update_bitmap.bigword;
//check if we need to clear any timers (updated now but not updated previously)
l_need_clr.bigword = l_temp_update_bitmap.bigword & ~L_temp_update_bitmap_prev.bigword;
@@ -448,8 +379,8 @@ void amec_health_check_dimm_timeout()
continue;
}
- TRAC_ERR("Timed out reading dimm temperature on cent[%d] dimm[%d] temp[%d] flags[0x%02X]",
- l_cent, l_dimm, l_fru->cur_temp, l_fru->flags);
+ TRAC_ERR("Timed out reading dimm temperature on cent/port[%d] dimm[%d] temp[%d] flags[0x%02X]",
+ l_cent, l_dimm, l_fru->cur_temp, l_fru->flags);
if(!l_err)
{
@@ -540,7 +471,7 @@ void amec_health_check_dimm_timeout()
//info trace each time we recover
if(L_ran_once)
{
- TRAC_INFO("DIMM temperature collection has resumed on cent[%d] dimm[%d] temp[%d]",
+ TRAC_INFO("DIMM temperature collection has resumed on cent/port[%d] dimm[%d] temp[%d]",
l_cent, l_dimm, l_fru->cur_temp);
}
@@ -550,6 +481,133 @@ void amec_health_check_dimm_timeout()
L_ran_once = TRUE;
}
+
+
+/*
+ * Function Specification
+ *
+ * Name: amec_health_check_cent_dimm_temp
+ *
+ * Description: Check if the centaur's dimm chips temperature exceeds the error
+ * temperature as defined in thermal control thresholds
+ * (ERROR field for Centaur FRU Type)
+ *
+ * End Function Specification
+ */
+void amec_health_check_cent_temp()
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+ uint16_t l_ot_error, l_cur_temp, l_max_temp;
+ sensor_t *l_sensor;
+ uint32_t l_cent;
+ uint32_t l_callouts_count = 0;
+ uint8_t l_new_callouts;
+ uint64_t l_huid;
+ errlHndl_t l_err = NULL;
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+
+ // Check to see if any centaurs have reached the error temperature that
+ // haven't been called out already
+ l_new_callouts = G_cent_overtemp_bitmap ^ G_cent_overtemp_logged_bitmap;
+ if(!l_new_callouts)
+ {
+ return;
+ }
+
+ l_ot_error = g_amec->thermalcent.ot_error;
+ l_sensor = getSensorByGsid(TEMP2MSCENT);
+ l_cur_temp = l_sensor->sample;
+ l_max_temp = l_sensor->sample_max;
+ TRAC_ERR("amec_health_check_cent_temp: Centaur reached error temp[%d]. cur_max[%d], hist_max[%d] bitmap[0x%02X]",
+ l_ot_error,
+ l_cur_temp,
+ l_max_temp,
+ l_new_callouts);
+
+ //find the centaur(s) that need to be called out
+ for(l_cent = 0; l_cent < MAX_NUM_CENTAURS; l_cent++)
+ {
+ if(!(l_new_callouts & (CENTAUR0_PRESENT_MASK >> l_cent)))
+ {
+ continue;
+ }
+
+ l_huid = amec_mem_get_huid(l_cent, 0xff);
+
+ amec_mem_mark_logged(l_cent,
+ 0xff,
+ &G_cent_overtemp_logged_bitmap,
+ &G_dimm_overtemp_logged_bitmap.bytes[l_cent]);
+
+ //If we don't have an error log for the callout, create one
+ if(!l_err)
+ {
+ /* @
+ * @errortype
+ * @moduleid AMEC_HEALTH_CHECK_CENT_TEMP
+ * @reasoncode CENT_ERROR_TEMP
+ * @userdata1 Maximum centaur temperature
+ * @userdata2 Centaur temperature threshold
+ * @userdata4 OCC_NO_EXTENDED_RC
+ * @devdesc Centaur memory controller(s) exceeded maximum safe
+ * temperature.
+ */
+ l_err = createErrl(AMEC_HEALTH_CHECK_CENT_TEMP, //modId
+ CENT_ERROR_TEMP, //reasoncode
+ OCC_NO_EXTENDED_RC, //Extended reason code
+ ERRL_SEV_PREDICTIVE, //Severity
+ NULL, //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ l_max_temp, //userdata1
+ l_ot_error); //userdata2
+
+ // Callout the "over temperature" procedure
+ addCalloutToErrl(l_err,
+ ERRL_CALLOUT_TYPE_COMPONENT_ID,
+ ERRL_COMPONENT_ID_OVER_TEMPERATURE,
+ ERRL_CALLOUT_PRIORITY_HIGH);
+ l_callouts_count = 1;
+ }
+
+ // Callout centaur
+ addCalloutToErrl(l_err,
+ ERRL_CALLOUT_TYPE_HUID,
+ l_huid,
+ ERRL_CALLOUT_PRIORITY_MED);
+
+ l_callouts_count++;
+
+ //If we've reached the max # of callouts for an error log
+ //commit the error log
+ if(l_callouts_count == ERRL_MAX_CALLOUTS)
+ {
+ commitErrl(&l_err);
+ }
+
+ }//iterate over centaurs
+
+ if(l_err)
+ {
+ commitErrl(&l_err);
+ }
+}
+
+/*
+ * Function Specification
+ *
+ * Name: amec_health_check_cent_timeout
+ *
+ * Description: Check for centaur timeout condition
+ * as defined in thermal control thresholds
+ * (MAX_READ_TIMEOUT field for Centaur FRU Type)
+ *
+ * End Function Specification
+ */
void amec_health_check_cent_timeout()
{
static uint8_t L_temp_update_bitmap_prev = 0;
diff --git a/src/occ_405/amec/amec_sensors_centaur.c b/src/occ_405/amec/amec_sensors_centaur.c
index 7be2ef8..3e050f9 100644
--- a/src/occ_405/amec/amec_sensors_centaur.c
+++ b/src/occ_405/amec/amec_sensors_centaur.c
@@ -34,6 +34,7 @@
#include "occ_sys_config.h"
#include "occ_service_codes.h" // for SSX_GENERIC_FAILURE
#include "dcom.h"
+#include "memory.h"
#include "centaur_data.h"
#include "amec_smh.h"
#include "amec_slave_smh.h"
@@ -46,8 +47,8 @@
/******************************************************************************/
/* Globals */
/******************************************************************************/
-cent_sensor_flags_t G_dimm_overtemp_bitmap = {0};
-cent_sensor_flags_t G_dimm_temp_updated_bitmap = {0};
+dimm_sensor_flags_t G_dimm_overtemp_bitmap = {0};
+dimm_sensor_flags_t G_dimm_temp_updated_bitmap = {0};
uint8_t G_cent_overtemp_bitmap = 0;
uint8_t G_cent_temp_updated_bitmap = 0;
extern uint8_t G_centaur_needs_recovery;
diff --git a/src/occ_405/amec/amec_slave_smh.c b/src/occ_405/amec/amec_slave_smh.c
index 1ccef2b..c42c815 100755
--- a/src/occ_405/amec/amec_slave_smh.c
+++ b/src/occ_405/amec/amec_slave_smh.c
@@ -44,6 +44,7 @@
#include "amec_service_codes.h"
#include <amec_sensors_core.h>
#include <amec_sensors_power.h>
+#include <memory.h>
#include <amec_sensors_centaur.h>
#include <amec_sensors_fw.h>
#include <amec_freq.h>
@@ -1211,11 +1212,11 @@ void amec_slv_substate_7_0(void)
//-------------------------------------------------------
amec_update_proc_core_group(3);
-// @TODO - TEMP: Not Ready yet in Phase 1.
-/*
// Call memory thermal controller based on DIMM temperature
amec_controller_dimm_thermal();
+// @TODO - TEMP: Not Ready yet in Phase 1.
+/*
// Call memory thermal controller based on Centaur temperature
amec_controller_centaur_thermal();
*/
diff --git a/src/occ_405/amec/amec_sys.h b/src/occ_405/amec/amec_sys.h
index a8582dd..3a8f634 100755
--- a/src/occ_405/amec/amec_sys.h
+++ b/src/occ_405/amec/amec_sys.h
@@ -40,6 +40,8 @@
#include <amec_amester.h>
#include <amec_pcap.h>
#include <amec_smh.h>
+#include "dimm_structs.h"
+
//*************************************************************************
// Externs
//*************************************************************************
@@ -387,6 +389,9 @@ typedef struct
// Speed step limit
uint16_t speed_step_limit;
+
+ // Memory Throttle Sent Last time to DIMM Throttle Register
+ dimm_n_value_t current_dimm_n_values[NUM_NIMBUS_MC_PAIRS][MAX_NUM_MCU_PORTS];
} amec_systemwide_t;
diff --git a/src/occ_405/cent/centaur_control.c b/src/occ_405/cent/centaur_control.c
index 82fddc9..461d7c9 100755
--- a/src/occ_405/cent/centaur_control.c
+++ b/src/occ_405/cent/centaur_control.c
@@ -26,6 +26,8 @@
//*************************************************************************/
// Includes
//*************************************************************************/
+#include <occ_common.h>
+#include "gpe_export.h"
#include "centaur_control.h"
#include "centaur_data.h"
#include "occhw_async.h"
@@ -38,10 +40,11 @@
#include "rtls.h"
#include "apss.h"
#include "state.h"
-#include "gpe_scom.h"
-#include "centaur_firmware_registers.h"
-#include "centaur_register_addresses.h"
+//#include "gpe_scom.h"
+//#include "centaur_firmware_registers.h"
+//#include "centaur_register_addresses.h"
#include "amec_sys.h"
+#include "memory.h"
//*************************************************************************/
// Externs
@@ -74,24 +77,14 @@ typedef enum
//*************************************************************************/
//Pore flex request for the GPE job that is used for centaur init.
-PoreFlex G_centaur_control_pore_req;
-GPE_BUFFER(GpeScomParms G_centaur_control_reg_parms);
-GPE_BUFFER(scomList_t G_centaurThrottle[NUM_CENT_THROTTLE_SCOMS]);
+GpeRequest G_centaur_control_request;
-//Centaur structures used for task data pointers.
-centaur_control_task_t G_centaur_control_task =
-{
- .startCentaur = 0, // First Centaur
- .prevCentaur = 7, // Previous Centaur written to
- .curCentaur = 0, // Current Centaur
- .endCentaur = 7, // Last Centaur
- .traceThresholdFlags = 0, // Trace Throttle Flags
-};
-
-// Per-MBA N/M Throttle Register "M & N" Values
-centaur_throttle_t G_centaurThrottleLimits[MAX_NUM_CENTAURS][NUM_MBAS_PER_CENTAUR];
+//@TODO TEMP: not ready yet for centaur control data structures
+//GPE_BUFFER(GpeScomParms G_centaur_control_reg_parms);
+//GPE_BUFFER(scomList_t G_centaurThrottle[NUM_CENT_THROTTLE_SCOMS]);
//bitmap of configured MBA's (2 per centaur, lsb is centaur 0/mba 0)
+//same variable used for tracking bit maps of rdimms (4 per mc, 2 mc pairs)
uint16_t G_configured_mbas = 0;
//*************************************************************************/
@@ -119,7 +112,7 @@ uint16_t centaurThrottle_convert2Numerator(uint16_t i_throttle, uint8_t i_cent,
#define CENTAUR_THROTTLE_100_PERCENT_VALUE 1000
uint32_t l_nvalue = 0;
- centaur_throttle_t* l_mba = &G_centaurThrottleLimits[i_cent][i_mba];
+ memory_throttle_t* l_mba = &G_memoryThrottleLimits[i_cent][i_mba];
if(MBA_CONFIGURED(i_cent, i_mba))
{
@@ -141,6 +134,8 @@ uint16_t centaurThrottle_convert2Numerator(uint16_t i_throttle, uint8_t i_cent,
return (uint16_t)l_nvalue;
}
+#if 0 // @TODO TEMP: Not Ready yet for centaur control
+
//////////////////////////
// Function Specification
//
@@ -169,10 +164,11 @@ void cent_update_nlimits(uint32_t i_cent)
do
{
- centaur_throttle_t* l_active_limits01 =
- &G_centaurThrottleLimits[i_cent][0];
- centaur_throttle_t* l_active_limits23 =
- &G_centaurThrottleLimits[i_cent][1];
+ memory_throttle_t* l_active_limits01 =
+ &G_memoryThrottleLimits[i_cent][0];
+ memory_throttle_t* l_active_limits23 =
+ &G_memoryThrottleLimits[i_cent][1];
+
mem_throt_config_data_t* l_state_limits01 =
&G_sysConfigData.mem_throt_limits[i_cent][0];
mem_throt_config_data_t* l_state_limits23 =
@@ -182,15 +178,7 @@ 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;
- //oversubscription?
- if(AMEC_INTF_GET_OVERSUBSCRIPTION())
- {
- l_mba01_mba_maxn = l_state_limits01->ovs_n_per_mba;
- l_mba01_chip_maxn = l_state_limits01->ovs_n_per_chip;
- l_mba23_mba_maxn = l_state_limits23->ovs_n_per_mba;
- l_mba23_chip_maxn = l_state_limits23->ovs_n_per_chip;
- }
- else if(CURRENT_MODE() == OCC_MODE_NOMINAL)
+ 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;
@@ -199,8 +187,8 @@ void cent_update_nlimits(uint32_t i_cent)
}
else //DPS, TURBO, FFO, and SPS modes will use these settings
{
- l_mba01_mba_maxn = l_state_limits01->pcap1_n_per_mba;
- l_mba23_mba_maxn = l_state_limits23->pcap1_n_per_mba;
+ l_mba01_mba_maxn = l_state_limits01->turbo_n_per_mba;
+ l_mba23_mba_maxn = l_state_limits23->turbo_n_per_mba;
}
l_active_limits01->max_n_per_chip = l_mba01_chip_maxn;
@@ -235,29 +223,14 @@ void cent_update_nlimits(uint32_t i_cent)
// Function Specification
//
-// Name: task_centaur_control
+// Name: centaur_control
//
-// Description: Collect centaur data. The task is used for centaur data
-// collection
+// Description: Performs centaur control.
//
// End Function Specification
-#define CENTAUR_CONTROL_SCOM_TIMEOUT 16 //wait up to 16 ticks before logging timeout failure
-void task_centaur_control( task_t * i_task )
+void centaur_control( task_t* i_task )
{
- errlHndl_t l_err = NULL; // Error handler
- int rc = 0; // Return code
- uint32_t l_cent;
amec_centaur_t *l_cent_ptr = NULL;
- static uint8_t L_scom_timeout[MAX_NUM_CENTAURS] = {0}; //track # of consecutive failures
- static bool L_gpe_scheduled = FALSE;
- static uint8_t L_gpe_fail_logged = 0;
- static bool L_gpe_idle_traced = FALSE;
- static bool L_gpe_had_1_tick = FALSE;
-
- // Pointer to the task data structure
- centaur_control_task_t * l_centControlTask =
- (centaur_control_task_t *) i_task->data_ptr;
-
// Pointer to parameter field for GPE request
GpeScomParms * l_parms =
@@ -265,130 +238,8 @@ void task_centaur_control( task_t * i_task )
do
{
- l_cent = l_centControlTask->curCentaur;
l_cent_ptr = &g_amec->proc[0].memctl[l_cent].centaur;
- //First, check to see if the previous GPE request still running
- //A request is considered idle if it is not attached to any of the
- //asynchronous request queues
- if( !(async_request_is_idle(&l_centControlTask->gpe_req.request)) )
- {
- L_scom_timeout[l_cent]++;
- //This can happen due to variability in when the task runs
- if(!L_gpe_idle_traced && L_gpe_had_1_tick)
- {
- TRAC_INFO("task_centaur_control: GPE is still running. cent[%d]", l_cent);
- l_centControlTask->traceThresholdFlags |= CENTAUR_CONTROL_GPE_STILL_RUNNING;
- L_gpe_idle_traced = TRUE;
- }
- L_gpe_had_1_tick = TRUE;
- break;
- }
- else
- {
- //Request is idle
- L_gpe_had_1_tick = FALSE;
- if(L_gpe_idle_traced)
- {
- TRAC_INFO("task_centaur_control: GPE completed. cent[%d]", l_cent);
- L_gpe_idle_traced = FALSE;
- }
- }
-
- //check scom status
- if(L_gpe_scheduled)
- {
- if(!async_request_completed(&l_centControlTask->gpe_req.request) || l_parms->rc)
- {
- if(!(L_gpe_fail_logged & (CENTAUR0_PRESENT_MASK >> l_cent)))
- {
- // Check if the centaur has a channel checkstop. If it does,
- // then do not log any errors. We also don't want to throttle
- // a centaur that is in this condition.
- if(!(cent_chan_checkstop(l_cent)))
- {
- L_gpe_fail_logged |= CENTAUR0_PRESENT_MASK >> l_cent;
- TRAC_ERR("task_centaur_control: gpe_scom_centaur failed. l_cent=%d rc=%x, index=0x%08x", l_cent, l_parms->rc, l_parms->errorIndex);
-
- /* @
- * @errortype
- * @moduleid CENT_TASK_CONTROL_MOD
- * @reasoncode CENT_SCOM_ERROR
- * @userdata1 rc - Return code of scom operation
- * @userdata2 index of scom operation that failed
- * @userdata4 OCC_NO_EXTENDED_RC
- * @devdesc OCC access to centaur failed
- */
- l_err = createErrl(
- CENT_TASK_CONTROL_MOD, // modId
- CENT_SCOM_ERROR, // reasoncode
- OCC_NO_EXTENDED_RC, // Extended reason code
- ERRL_SEV_PREDICTIVE, // Severity
- NULL, // Trace Buf
- DEFAULT_TRACE_SIZE, // Trace Size
- l_parms->rc, // userdata1
- l_parms->errorIndex // userdata2
- );
-
- addUsrDtlsToErrl(l_err, //io_err
- (uint8_t *) &(l_centControlTask->gpe_req.ffdc), //i_dataPtr,
- sizeof(PoreFfdc), //i_size
- ERRL_USR_DTL_STRUCT_VERSION_1, //version
- ERRL_USR_DTL_BINARY_DATA); //type
-
- //callout the centaur
- addCalloutToErrl(l_err,
- ERRL_CALLOUT_TYPE_HUID,
- G_sysConfigData.centaur_huids[l_cent],
- ERRL_CALLOUT_PRIORITY_MED);
-
- //callout the processor
- addCalloutToErrl(l_err,
- ERRL_CALLOUT_TYPE_HUID,
- G_sysConfigData.proc_huid,
- ERRL_CALLOUT_PRIORITY_MED);
-
- commitErrl(&l_err);
- }
- }//if(l_gpe_fail_logged & (CENTAUR0_PRESENT_MASK >> l_cent))
-
- //Request failed. Keep count of failures and request a reset if we reach a
- //max retry count
- L_scom_timeout[l_cent]++;
- if(L_scom_timeout[l_cent] == CENTAUR_CONTROL_SCOM_TIMEOUT)
- {
- break;
- }
-
- }//if(!async_request_completed(&l_centControlTask->gpe_req.request) || l_parms->rc)
- else
- {
- //request completed successfully. reset the timeout.
- L_scom_timeout[l_cent] = 0;
- }
- }//if(L_gpe_scheduled)
-
- //The previous GPE job completed. Now get ready for the next job.
- L_gpe_scheduled = FALSE;
-
- //Update current centaur if we didn't fail
- if ( l_cent >= l_centControlTask->endCentaur )
- {
- l_cent = l_centControlTask->startCentaur;
- }
- else
- {
- l_cent++;
- }
- l_centControlTask->curCentaur = l_cent;
- l_cent_ptr = &g_amec->proc[0].memctl[l_cent].centaur;
-
- //If centaur is not present or neither MBA is configured then skip it.
- if(!CENTAUR_PRESENT(l_cent) ||
- (!MBA_CONFIGURED(l_cent, 0) && !MBA_CONFIGURED(l_cent, 1)))
- {
- break;
- }
//update min/max settings for both MBA's according to ovs and mode
cent_update_nlimits(l_cent);
@@ -399,8 +250,8 @@ void task_centaur_control( task_t * i_task )
centaurThrottle_convert2Numerator(g_amec->mem_speed_request, l_cent, 0);
uint16_t l_mba23_n_per_mba =
centaurThrottle_convert2Numerator(g_amec->mem_speed_request, l_cent, 1);
- uint16_t l_mba01_n_per_chip = G_centaurThrottleLimits[l_cent][0].max_n_per_chip;
- uint16_t l_mba23_n_per_chip = G_centaurThrottleLimits[l_cent][1].max_n_per_chip;
+ uint16_t l_mba01_n_per_chip = G_memoryThrottleLimits[l_cent][0].max_n_per_chip;
+ uint16_t l_mba23_n_per_chip = G_memoryThrottleLimits[l_cent][1].max_n_per_chip;
amec_cent_mem_speed_t l_mba01_speed;
amec_cent_mem_speed_t l_mba23_speed;
@@ -487,95 +338,8 @@ void task_centaur_control( task_t * i_task )
l_cent_ptr->portpair[0].last_mem_speed_sent.word32 = l_mba01_speed.word32;
l_cent_ptr->portpair[1].last_mem_speed_sent.word32 = l_mba23_speed.word32;
-
- // Pore flex schedule gpe_scom_centaur
- // Check pore_flex_schedule return code if error
- // then request OCC reset.
- rc = pore_flex_schedule( &(l_centControlTask->gpe_req) );
- if( rc )
- {
- //Error in schedule gpe get centaur data
- TRAC_ERR("task_centaur_control: Failed to schedule gpe rc=%x", rc);
-
- /* @
- * @errortype
- * @moduleid CENT_TASK_CONTROL_MOD
- * @reasoncode SSX_GENERIC_FAILURE
- * @userdata1 rc - Return code of failing function
- * @userdata2 0
- * @userdata4 ERC_CENTAUR_PORE_FLEX_SCHEDULE_FAILURE
- * @devdesc OCC Failed to schedule a GPE job for centaur
- */
- l_err = createErrl(
- CENT_TASK_CONTROL_MOD, // modId
- SSX_GENERIC_FAILURE, // reasoncode
- ERC_CENTAUR_PORE_FLEX_SCHEDULE_FAILURE, // Extended reason code
- ERRL_SEV_UNRECOVERABLE, // Severity
- NULL, // Trace Buf
- DEFAULT_TRACE_SIZE, // Trace Size
- rc, // userdata1
- l_parms->rc // userdata2
- );
-
- addUsrDtlsToErrl(l_err, //io_err
- (uint8_t *) &(l_centControlTask->gpe_req.ffdc), //i_dataPtr,
- sizeof(PoreFfdc), //i_size
- ERRL_USR_DTL_STRUCT_VERSION_1, //version
- ERRL_USR_DTL_BINARY_DATA); //type
-
- REQUEST_RESET(l_err); //This will add a firmware callout for us
- break;
- }
-
- L_gpe_scheduled = TRUE;
} while(0);
- if(L_scom_timeout[l_cent] == CENTAUR_CONTROL_SCOM_TIMEOUT)
- {
- TRAC_ERR("task_centaur_control: Timeout scomming centaur[%d]", l_cent);
- /* @
- * @errortype
- * @moduleid CENT_TASK_CONTROL_MOD
- * @reasoncode INTERNAL_FAILURE
- * @userdata1 centaur number
- * @userdata2 0
- * @userdata4 OCC_NO_EXTENDED_RC
- * @devdesc Timed out trying to set the memory throttle settings
- * throttle settings.
- */
- l_err = createErrl(
- CENT_TASK_CONTROL_MOD, // modId
- INTERNAL_FAILURE, // reasoncode
- OCC_NO_EXTENDED_RC, // Extended reason code
- ERRL_SEV_PREDICTIVE, // Severity
- NULL, // Trace Buf
- DEFAULT_TRACE_SIZE, // Trace Size
- l_cent, // userdata1
- 0 // userdata2
- );
-
- addUsrDtlsToErrl(l_err, //io_err
- (uint8_t *) &(l_centControlTask->gpe_req.ffdc), //i_dataPtr,
- sizeof(PoreFfdc), //i_size
- ERRL_USR_DTL_STRUCT_VERSION_1, //version
- ERRL_USR_DTL_BINARY_DATA); //type
-
- //callout the centaur
- addCalloutToErrl(l_err,
- ERRL_CALLOUT_TYPE_HUID,
- G_sysConfigData.centaur_huids[l_cent],
- ERRL_CALLOUT_PRIORITY_MED);
-
- //callout the processor
- addCalloutToErrl(l_err,
- ERRL_CALLOUT_TYPE_HUID,
- G_sysConfigData.proc_huid,
- ERRL_CALLOUT_PRIORITY_MED);
-
- REQUEST_RESET(l_err);
- }
-
- return;
}
@@ -599,7 +363,7 @@ void centaur_control_init( void )
do
{
//initialize the active throttle limits
- memset(G_centaurThrottleLimits, 0, sizeof(G_centaurThrottleLimits));
+ memset(G_memoryThrottleLimits, 0, sizeof(G_memoryThrottleLimits));
//Do one-time setup items for the task here.
@@ -628,15 +392,15 @@ void centaur_control_init( void )
// Initializes PoreFlex for Centaur Control Task, but
// doesn't actually run anything until RTL
//--------------------------------------------------
- l_rc_gpe = pore_flex_create(
- &G_centaur_control_task.gpe_req, // gpe_req for the task
- &G_pore_gpe1_queue, // queue
- gpe_scom_centaur, // entry point
+ l_rc_gpe = gpe_request_create(
+ &G_memory_control_task.gpe_req, // gpe_req for the task
+ &G_async_gpe_queue1, // queue
+ IPC_ST_CENTAUR_CONTROL_FUNCID, // Function ID
(uint32_t) &G_centaur_control_reg_parms, // parm for the task
SSX_WAIT_FOREVER, //
NULL, // callback
NULL, // callback argument
- 0 ); // options
+ ASYNC_CALLBACK_IMMEDIATE ); // options
if(l_rc_gpe)
{
break;
@@ -672,7 +436,7 @@ void centaur_control_init( void )
);
addUsrDtlsToErrl(l_err, //io_err
- (uint8_t *) &G_centaur_control_pore_req.ffdc, //i_dataPtr,
+ (uint8_t *) &G_centaur_control_request.ffdc, //i_dataPtr,
sizeof(PoreFfdc), //i_size
ERRL_USR_DTL_STRUCT_VERSION_1, //version
ERRL_USR_DTL_BINARY_DATA); //type
@@ -683,6 +447,64 @@ void centaur_control_init( void )
return;
}
+bool check_centaur_checkstop(uint8_t cent)
+{
+ // Check if the centaur has a channel checkstop. If it does,
+ // then do not log any errors. We also don't want to throttle
+ // a centaur that is in this condition.
+ if(!(cent_chan_checkstop(cent)))
+ {
+ TRAC_ERR("task_memory_control: gpe_scom_centaur failed. "
+ "cent=%d rc=%x, index=0x%08x",
+ cent, G_centaur_control_reg_parms.rc,
+ G_centaur_control_reg_parms.errorIndex);
+
+ /* @
+ * @errortype
+ * @moduleid CENT_TASK_CONTROL_MOD
+ * @reasoncode CENT_SCOM_ERROR
+ * @userdata1 rc - Return code of scom operation
+ * @userdata2 index of scom operation that failed
+ * @userdata4 OCC_NO_EXTENDED_RC
+ * @devdesc OCC access to centaur failed
+ */
+ l_err = createErrl(
+ CENT_TASK_CONTROL_MOD, // modId
+ CENT_SCOM_ERROR, // reasoncode
+ OCC_NO_EXTENDED_RC, // Extended reason code
+ ERRL_SEV_PREDICTIVE, // Severity
+ NULL, // Trace Buf
+ DEFAULT_TRACE_SIZE, // Trace Size
+ G_centaur_control_reg_parms.rc, // userdata1
+ G_centaur_control_reg_parms.errorIndex // userdata2
+ );
+
+ addUsrDtlsToErrl(l_err, //io_err
+ (uint8_t *) &(memControlTask->gpe_req.ffdc), //i_dataPtr,
+ sizeof(PoreFfdc), //i_size
+ ERRL_USR_DTL_STRUCT_VERSION_1, //version
+ ERRL_USR_DTL_BINARY_DATA); //type
+
+ //callout the centaur
+ addCalloutToErrl(l_err,
+ ERRL_CALLOUT_TYPE_HUID,
+ G_sysConfigData.centaur_huids[memIndex],
+ ERRL_CALLOUT_PRIORITY_MED);
+
+ //callout the processor
+ addCalloutToErrl(l_err,
+ ERRL_CALLOUT_TYPE_HUID,
+ G_sysConfigData.proc_huid,
+ ERRL_CALLOUT_PRIORITY_MED);
+
+ commitErrl(&l_err);
+
+ return TRUE; // a centaur channel checkstop error occured
+ }
+ return FALSE; // No centaur channel checkstop errors
+
+}
+#endif // @TODO TEMP: Not Ready yet for centaur control
diff --git a/src/occ_405/cent/centaur_control.h b/src/occ_405/cent/centaur_control.h
index 9b37b0c..afc766e 100755
--- a/src/occ_405/cent/centaur_control.h
+++ b/src/occ_405/cent/centaur_control.h
@@ -34,6 +34,7 @@
#include "rtls.h"
//#include "gpe_data.h"
#include "occ_sys_config.h"
+#include "memory.h"
//*************************************************************************
// Externs
@@ -48,62 +49,23 @@
//*************************************************************************
//*************************************************************************
-// Structures
-//*************************************************************************
-
-typedef enum
-{
- CENTAUR_CONTROL_GPE_STILL_RUNNING = 0x01,
- CENTAUR_CONTROL_RESERVED_1 = 0x02,
- CENTAUR_CONTROL_RESERVED_2 = 0x04,
- CENTAUR_CONTROL_RESERVED_3 = 0x08,
- CENTAUR_CONTROL_RESERVED_4 = 0x10,
- CENTAUR_CONTROL_RESERVED_5 = 0x20,
- CENTAUR_CONTROL_RESERVED_6 = 0x40,
- CENTAUR_CONTROL_RESERVED_7 = 0x80,
-} eCentaurControlTraceFlags;
-
-//Centaur data collect structures used for task data pointers
-// TEMP -- PORE ISSUES
-/*
-struct centaur_control_task {
- uint8_t startCentaur;
- uint8_t prevCentaur;
- uint8_t curCentaur;
- uint8_t endCentaur;
- uint8_t traceThresholdFlags;
- PoreFlex gpe_req;
-} __attribute__ ((__packed__));
-typedef struct centaur_control_task centaur_control_task_t;
-*/
-
-//per mba throttle values
-typedef struct
-{
- uint16_t max_n_per_mba; //mode and OVS dependent, from config data
- uint16_t max_n_per_chip; //mode and OVS dependent, from config data
- uint16_t min_n_per_mba; //from config data
- uint16_t m;
-} centaur_throttle_t;
-
-//*************************************************************************
// Globals
//*************************************************************************
-//Global centaur structures used for task data pointers
-// TEMP -- PORE ISSUES
-//extern centaur_control_task_t G_centaur_control_task;
+//Global memory structures used for centaur task data pointers
+extern memory_control_task_t G_memory_control_task;
//*************************************************************************
// Function Prototypes
//*************************************************************************
//Collect centaur data for all centaur in specified range
-void task_centaur_control( task_t * i_task );
+void centaur_control( task_t* i_task );
//Initialize structures for collecting centaur data.
//void centaur_control_init( void ) INIT_SECTION;
void centaur_control_init( void );
-#endif //_CENTAUR_CONTROL_H
+bool check_centaur_checkstop(uint8_t cent);
+#endif //_CENTAUR_CONTROL_H
diff --git a/src/occ_405/cent/centaur_data.c b/src/occ_405/cent/centaur_data.c
index ef550b6..50d4e9b 100755
--- a/src/occ_405/cent/centaur_data.c
+++ b/src/occ_405/cent/centaur_data.c
@@ -132,7 +132,7 @@ centaur_data_task_t G_centaur_data_task = {
};
#endif
-cent_sensor_flags_t G_cent_enabled_sensors = {0};
+dimm_sensor_flags_t G_dimm_enabled_sensors = {0};
//AMEC needs to know when data for a centaur has been collected.
uint32_t G_updated_centaur_mask = 0;
@@ -214,7 +214,7 @@ bool cent_chan_checkstop(const uint8_t i_cent)
G_present_centaurs &= ~(CENTAUR_BY_MASK(i_cent));
//remove the dimm temperature sensors behind this centaur from presence bitmap
- G_cent_enabled_sensors.bytes[i_cent] = 0x00;
+ G_dimm_enabled_sensors.bytes[i_cent] = 0x00;
TRAC_IMP("Channel checkstop detected on Centaur[%d] scom_addr[0x%08X] G_present_centaurs[0x%08X]",
i_cent,
@@ -222,8 +222,8 @@ bool cent_chan_checkstop(const uint8_t i_cent)
G_present_centaurs);
TRAC_IMP("Updated bitmap of enabled dimm temperature sensors: 0x%08X %08X",
- G_cent_enabled_sensors.words[0],
- G_cent_enabled_sensors.words[1]);
+ G_dimm_enabled_sensors.words[0],
+ G_dimm_enabled_sensors.words[1]);
}
}
}
@@ -979,12 +979,12 @@ int cent_get_enabled_sensors()
//consolidate scom data into a smaller, cacheable 8 byte buffer
for(l_cent = 0; l_cent < MAX_NUM_CENTAURS; l_cent++)
{
- G_cent_enabled_sensors.bytes[l_cent] = ((uint8_t*)(&G_cent_scom_data[l_cent]))[0];
+ G_dimm_enabled_sensors.bytes[l_cent] = ((uint8_t*)(&G_cent_scom_data[l_cent]))[0];
}
TRAC_IMP("bitmap of enabled dimm temperature sensors: 0x%08X %08X",
- G_cent_enabled_sensors.words[0],
- G_cent_enabled_sensors.words[1]);
+ G_dimm_enabled_sensors.words[0],
+ G_dimm_enabled_sensors.words[1]);
}while(0);
return l_rc;
}
diff --git a/src/occ_405/cent/centaur_data.h b/src/occ_405/cent/centaur_data.h
index 63cc264..f6596f0 100755
--- a/src/occ_405/cent/centaur_data.h
+++ b/src/occ_405/cent/centaur_data.h
@@ -34,6 +34,7 @@
#include "rtls.h"
//#include "gpe_data.h"
#include "occ_sys_config.h"
+#include "memory.h"
//*************************************************************************
// Externs
@@ -97,7 +98,7 @@ enum eOccCentaurs
#define DIMM_SENSOR0 0x80
#define CENTAUR_SENSOR_ENABLED(occ_cent_id, sensor_num) \
- (G_cent_enabled_sensors.bytes[occ_cent_id] & (DIMM_SENSOR0 >> (sensor_num)))
+ (G_dimm_enabled_sensors.bytes[occ_cent_id] & (DIMM_SENSOR0 >> (sensor_num)))
#define MBA_CONFIGURED(occ_cent_id, mba_num) \
(G_configured_mbas & (1 << ((occ_cent_id * 2) + mba_num)))
@@ -119,14 +120,6 @@ struct centaur_data_task {
typedef struct centaur_data_task centaur_data_task_t;
*/
-typedef union
-{
- uint64_t bigword;
- uint32_t words[2];
- uint8_t bytes[8];
-}cent_sensor_flags_t;
-
-
//*************************************************************************
// Globals
//*************************************************************************
@@ -142,16 +135,16 @@ extern uint32_t G_present_centaurs;
extern uint32_t G_updated_centaur_mask;
//global bitmap of enabled dimm sensors
-extern cent_sensor_flags_t G_cent_enabled_sensors;
+extern dimm_sensor_flags_t G_dimm_enabled_sensors;
//global bitmap of dimms that have ever gone over the error temperature
-extern cent_sensor_flags_t G_dimm_overtemp_bitmap;
+extern dimm_sensor_flags_t G_dimm_overtemp_bitmap;
//global bitmap of dimms temps that have been updated
-extern cent_sensor_flags_t G_dimm_temp_updated_bitmap;
+extern dimm_sensor_flags_t G_dimm_temp_updated_bitmap;
//global bitmap flagging the dimms which we already calledout due to timeout (bitmap of dimms)
-extern cent_sensor_flags_t G_dimm_timeout_logged_bitmap;
+extern dimm_sensor_flags_t G_dimm_timeout_logged_bitmap;
//global bitmap flagging the centaurs which we already calledout due to timeout (bitmap of centaurs)
extern uint8_t G_cent_timeout_logged_bitmap;
diff --git a/src/occ_405/cent/centaur_data_service_codes.h b/src/occ_405/cent/centaur_data_service_codes.h
index fa4f5b4..c15853a 100755
--- a/src/occ_405/cent/centaur_data_service_codes.h
+++ b/src/occ_405/cent/centaur_data_service_codes.h
@@ -44,10 +44,9 @@
//*************************************************************************
enum centModuleId
{
- CENT_TASK_DATA_MOD = CENT_COMP_ID | 0x00,
- CENTAUR_INIT_MOD = CENT_COMP_ID | 0x01,
- CENT_TASK_CONTROL_MOD = CENT_COMP_ID | 0x02,
- CENT_RECOVERY_MOD = CENT_COMP_ID | 0x03,
+ CENT_TASK_DATA_MOD = CENT_COMP_ID | 0x00,
+ CENTAUR_INIT_MOD = CENT_COMP_ID | 0x01,
+ CENT_RECOVERY_MOD = CENT_COMP_ID | 0x03,
};
//*************************************************************************
diff --git a/src/occ_405/cmdh/cmdh_dbug_cmd.c b/src/occ_405/cmdh/cmdh_dbug_cmd.c
index ff816ff..6469fbf 100755
--- a/src/occ_405/cmdh/cmdh_dbug_cmd.c
+++ b/src/occ_405/cmdh/cmdh_dbug_cmd.c
@@ -34,7 +34,7 @@
#include <cmdh_dbug_cmd.h>
#include <cmdh_fsp.h>
#include <cmdh_fsp_cmds.h>
-#include <centaur_data.h>
+#include <memory.h>
//#include <gpe_data.h>
#include <proc_data.h>
#include <apss.h>
diff --git a/src/occ_405/cmdh/cmdh_fsp_cmds.c b/src/occ_405/cmdh/cmdh_fsp_cmds.c
index bd3f882..791fe6d 100755
--- a/src/occ_405/cmdh/cmdh_fsp_cmds.c
+++ b/src/occ_405/cmdh/cmdh_fsp_cmds.c
@@ -48,7 +48,7 @@
#include "homer.h"
#include <centaur_data.h>
-extern cent_sensor_flags_t G_dimm_temp_expired_bitmap;
+extern dimm_sensor_flags_t G_dimm_temp_expired_bitmap;
// This table contains tunable parameter information that can be exposed to
// customers (only Master OCC should access/control this table)
diff --git a/src/occ_405/cmdh/cmdh_fsp_cmds_datacnfg.c b/src/occ_405/cmdh/cmdh_fsp_cmds_datacnfg.c
index fbe112e..98cc513 100755
--- a/src/occ_405/cmdh/cmdh_fsp_cmds_datacnfg.c
+++ b/src/occ_405/cmdh/cmdh_fsp_cmds_datacnfg.c
@@ -41,6 +41,7 @@
#include "amec_service_codes.h"
#include "amec_sys.h"
#include <centaur_data.h>
+#include "dimm.h"
#define FREQ_FORMAT_PWR_MODE_NUM 6
#define FREQ_FORMAT_BASE_DATA_SZ (sizeof(cmdh_store_mode_freqs_t) - sizeof(cmdh_fsp_cmd_header_t))
@@ -1443,7 +1444,7 @@ errlHndl_t data_store_mem_cfg(const cmdh_fsp_cmd_t * i_cmd_ptr,
for(memctl=0; memctl < MAX_NUM_MEM_CONTROLLERS; ++memctl)
{
g_amec->proc[0].memctl[memctl].centaur.temp_sid = 0;
- for(dimm=0; dimm < NUM_DIMMS_PER_CENTAUR; ++dimm)
+ for(dimm=0; dimm < NUM_DIMMS_PER_MEM_CONTROLLER; ++dimm)
{
g_amec->proc[0].memctl[memctl].centaur.dimm_temps[dimm].temp_sid = 0;
}
@@ -1562,6 +1563,8 @@ errlHndl_t data_store_mem_cfg(const cmdh_fsp_cmd_t * i_cmd_ptr,
// Store the hardware sensor ID
G_sysConfigData.dimm_huids[l_i2c_port][l_dimm_num] = l_data_set->hw_sensor_id;
+ // Set bit vector of enabled DIMM sensors
+ G_dimm_enabled_sensors.bytes[l_i2c_port] |= 0x80 >> l_dimm_num;
// Store the temperature sensor ID
g_amec->proc[0].memctl[l_i2c_port].centaur.dimm_temps[l_dimm_num].temp_sid =
@@ -1681,7 +1684,7 @@ errlHndl_t data_store_mem_throt(const cmdh_fsp_cmd_t * i_cmd_ptr,
cmdh_mem_throt_t* l_cmd_ptr = (cmdh_mem_throt_t*)i_cmd_ptr;
uint16_t l_data_length = 0;
uint16_t l_exp_data_length = 0;
- int i;
+ uint8_t i;
uint16_t l_configured_mbas = 0;
bool l_invalid_input = TRUE; //Assume bad input
@@ -1705,131 +1708,141 @@ errlHndl_t data_store_mem_throt(const cmdh_fsp_cmd_t * i_cmd_ptr,
if(l_invalid_input)
{
- CMDH_TRAC_ERR("data_store_mem_throt: Invalid mem throttle data packet: data_length[%u] exp_length[%u] version[0x%02X] num_data_sets[%u]",
- l_data_length,
- l_exp_data_length,
- l_cmd_ptr->header.version,
- l_cmd_ptr->header.num_data_sets);
+ CMDH_TRAC_ERR("data_store_mem_throt: Invalid mem throttle data packet: "
+ "data_length[%u] exp_length[%u] version[0x%02X] num_data_sets[%u]",
+ l_data_length,
+ l_exp_data_length,
+ l_cmd_ptr->header.version,
+ l_cmd_ptr->header.num_data_sets);
cmdh_build_errl_rsp(i_cmd_ptr, o_rsp_ptr, ERRL_RC_INVALID_DATA, &l_err);
break;
}
- if(l_cmd_ptr->header.version == DATA_MEM_THROT_VERSION_20)
+ // Store the memory throttle settings
+ for(i=0; i<l_cmd_ptr->header.num_data_sets; i++)
{
+ mem_throt_config_data_t l_temp_set;
+ cmdh_mem_throt_data_set_t* l_data_set = &l_cmd_ptr->data_set[i];
+ uint16_t * l_n_ptr;
+
+ uint8_t mc=-1, port=-1, cent=-1, mba=-1; // dimm/centaur Info Parameters
+
if(MEM_TYPE_NIMBUS == G_sysConfigData.mem_type)
{
- // Store the memory throttle settings
- for(i=0; i<l_cmd_ptr->header.num_data_sets; i++)
+ mc = l_data_set->mem_throt_info.nimbus.mc_num;
+ port = l_data_set->mem_throt_info.nimbus.port_num;
+
+ // Validate the Nimbus Info parameters:
+ // - MC num (0 for MC01, and 1 for MC23)
+ // - and Port Number (0-3)
+ if(mc >= NUM_NIMBUS_MC_PAIRS ||
+ port >= MAX_NUM_MCU_PORTS)
{
- nimbus_mem_throt_t* l_data_set = &l_cmd_ptr->data_set[i].nimbus;
- mem_throt_config_data_t l_temp_set;
- uint16_t * l_n_ptr;
-
- // Validate the validity of Nimbus:
- // - MC num (0 for MC01, and 2 for MC23)
- // - and Port Number (0-3)
- if((l_data_set->mc_num != 0 && l_data_set->mc_num != 2) ||
- l_data_set->port_num >= MAX_NUM_MCU_PORTS)
- {
- CMDH_TRAC_ERR("data_store_mem_throt: Invalid MC# or Port#. entry=%d, cent=%d, mba=%d",
- i,
- l_data_set->mc_num,
- l_data_set->port_num);
- cmdh_build_errl_rsp(i_cmd_ptr, o_rsp_ptr, ERRL_RC_INVALID_DATA, &l_err);
- break;
- }
-
- // Copy into a temporary buffer while we check for N values of 0
- memcpy(&l_temp_set, &(l_data_set->min_n_per_port), sizeof(mem_throt_config_data_t));
-
- // A 0 for any N value, or power value, is an error
- for(l_n_ptr = &l_temp_set.min_n_per_mba; l_n_ptr <= &l_temp_set.ovs_mem_power; l_n_ptr++)
- {
- if(!(*l_n_ptr))
- {
- CMDH_TRAC_ERR("data_store_mem_throt: Memory Throttle N/Power value is 0! MC[%d] Port[%d]",
- l_data_set->mc_num, l_data_set->port_num);
- cmdh_build_errl_rsp(i_cmd_ptr, o_rsp_ptr, ERRL_RC_INVALID_DATA, &l_err);
- break;
- }
-
- }
- if(l_err)
- {
- break;
- }
-
- memcpy(&G_sysConfigData.mem_throt_limits[l_data_set->mc_num][l_data_set->port_num],
- &(l_data_set->min_n_per_port),
- sizeof(mem_throt_config_data_t));
-
- l_configured_mbas |= 1 << (((l_data_set->mc_num<<1) * 2) + l_data_set->port_num);
+ CMDH_TRAC_ERR("data_store_mem_throt: Invalid MC or Port numbers."
+ " entry=%d, mc=%d, port=%d",
+ i, mc, port);
+ cmdh_build_errl_rsp(i_cmd_ptr, o_rsp_ptr, ERRL_RC_INVALID_DATA, &l_err);
+ break;
}
}
- else if (MEM_TYPE_CUMULUS == G_sysConfigData.mem_type)
+ else if(MEM_TYPE_CUMULUS == G_sysConfigData.mem_type)
{
- // Store the memory throttle settings
- for(i=0; i<l_cmd_ptr->header.num_data_sets; i++)
+ cent = l_data_set->mem_throt_info.cumulus.centaur_num;
+ mba = l_data_set->mem_throt_info.cumulus.mba_num;
+
+ // Validate the Cumulus Info parameters:
+ // - Centaur num (0-7)
+ // - and MBA num (0 for MBA01, and 1 for MBA23)
+ if(cent >= MAX_NUM_CENTAURS ||
+ mba >= NUM_MBAS_PER_CENTAUR)
{
- cumulus_mem_throt_t* l_data_set = &l_cmd_ptr->data_set[i].cumulus;
- mem_throt_config_data_t l_temp_set;
- uint16_t * l_n_ptr;
+ CMDH_TRAC_ERR("data_store_mem_throt: Invalid mba or centaur number. "
+ "entry=%d, cent=%d, mba=%d",
+ i, cent, mba);
+ cmdh_build_errl_rsp(i_cmd_ptr, o_rsp_ptr, ERRL_RC_INVALID_DATA, &l_err);
+ break;
+ }
+ }
- // Validate the centaur and mba #'s for this data set
- if(l_data_set->centaur_num >= MAX_NUM_CENTAURS ||
- l_data_set->mba_num >= NUM_MBAS_PER_CENTAUR)
- {
- CMDH_TRAC_ERR("data_store_mem_throt: Invalid mba or centaur number. entry=%d, cent=%d, mba=%d",
- i,
- l_data_set->centaur_num,
- l_data_set->mba_num);
- cmdh_build_errl_rsp(i_cmd_ptr, o_rsp_ptr, ERRL_RC_INVALID_DATA, &l_err);
- break;
- }
- // 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));
+ // 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.ovs_mem_power; l_n_ptr++)
+ // 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++)
+ {
+ if(!(*l_n_ptr))
+ {
+ if(MEM_TYPE_NIMBUS == G_sysConfigData.mem_type)
{
- if(!(*l_n_ptr))
- {
- CMDH_TRAC_ERR("data_store_mem_throt: Memory Throttle N value is 0! cent[%d] mba[%d]",
- l_data_set->centaur_num, l_data_set->mba_num);
- cmdh_build_errl_rsp(i_cmd_ptr, o_rsp_ptr, ERRL_RC_INVALID_DATA, &l_err);
- break;
- }
-
+ CMDH_TRAC_ERR("data_store_mem_throt: RDIMM Throttle N value is 0!"
+ " mc[%d] port[%d]", mc, port);
}
- if(l_err)
+ else if(MEM_TYPE_CUMULUS == G_sysConfigData.mem_type)
{
- break;
+ CMDH_TRAC_ERR("data_store_mem_throt: Centaur DIMM Throttle N value is 0!"
+ " cent[%d] mba[%d]", cent, mba);
}
+ cmdh_build_errl_rsp(i_cmd_ptr, o_rsp_ptr, ERRL_RC_INVALID_DATA, &l_err);
+ break;
+ }
+ }
+
+ if(l_err) // zero N Value?
+ {
+ break;
+ }
- memcpy(&G_sysConfigData.mem_throt_limits[l_data_set->centaur_num][l_data_set->mba_num],
- &(l_data_set->min_n_per_mba),
- sizeof(mem_throt_config_data_t));
+ if(MEM_TYPE_NIMBUS == G_sysConfigData.mem_type)
+ {
+ memcpy(&G_sysConfigData.mem_throt_limits[mc][port],
+ &(l_data_set->min_n_per_mba),
+ sizeof(mem_throt_config_data_t));
- l_configured_mbas |= 1 << ((l_data_set->centaur_num * 2) + l_data_set->mba_num);
+ CONFIGURE_NIMBUS_DIMM_THROTTLING(l_configured_mbas, mc, port);
+ }
+ else if(MEM_TYPE_CUMULUS == G_sysConfigData.mem_type)
+ {
+ memcpy(&G_sysConfigData.mem_throt_limits[cent][mba],
+ &(l_data_set->min_n_per_mba),
+ sizeof(mem_throt_config_data_t));
- }
+ l_configured_mbas |= 1 << ((cent* NUM_MBAS_PER_CENTAUR) + mba);
}
+ } // data_sets for loop
+
+ if(l_err) // Invalid Info Parameter?
+ {
+ break;
}
} 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
-// @TEMP @TODO: defined in centaur_control - Not ready yet
-// G_configured_mbas = l_configured_mbas;
+ G_configured_mbas = l_configured_mbas;
+
}
+
return l_err;
}
diff --git a/src/occ_405/cmdh/cmdh_fsp_cmds_datacnfg.h b/src/occ_405/cmdh/cmdh_fsp_cmds_datacnfg.h
index 4857671..4c0f3ad 100755
--- a/src/occ_405/cmdh/cmdh_fsp_cmds_datacnfg.h
+++ b/src/occ_405/cmdh/cmdh_fsp_cmds_datacnfg.h
@@ -287,68 +287,56 @@ 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 port_num; // Physical port # [0-3]
-
- uint16_t min_n_per_port; // Lowest per port allowed numerator
- uint16_t min_mem_power; // Max mem Power @min (x0.1W)
-
- uint16_t pcap1_n_per_port; // Static per port numerator @PCAP1
- uint16_t pcap1_n_per_chip; // Static per chip numerator @PCAP1
- uint16_t pcap1_mem_power; // Max memory power @PCAP1 (x0.1W)
-
- uint16_t pcap2_n_per_port; // Static per port numerator @PCAP2
- uint16_t pcap2_n_per_chip; // Static per chip numerator @PCAP2
- uint16_t pcap2_mem_power; // Max memory power @PCAP2 (x0.1W)
-
- uint16_t nom_n_per_port; // Static per port @Redundant (no ovs)
- uint16_t nom_n_per_slot; // Static per slot @Redundant
- uint16_t nom_mem_power; // Max memory power @Redundant(x0.1W)
-
- uint16_t ovs_n_per_port; // Static per port @Oversubscription
- uint16_t ovs_n_per_slot; // Static per slot @Oversubscription
- uint16_t ovs_mem_power; // Max memory power @Oversubscription (x0.1W)
-}nimbus_mem_throt_t;
+ uint8_t mc_num; // Physical MC: [0=MC01, 2=MC23]
+ uint8_t port_num; // Physical port # [0-3]
+} cmdh_mem_throt_nimbus_info_t;
// Provides memory throttle min and max values for Cumulus systems
typedef struct __attribute__ ((packed))
{
- uint8_t centaur_num; // Physical centaur# [0-7]
- uint8_t mba_num; // Memory Buffer within centaur [0-1]
+ uint8_t centaur_num; // Physical centaur# [0-7]
+ uint8_t mba_num; // Memory Buffer within centaur [0-1]
+} cmdh_mem_throt_cumulus_info_t;
- uint16_t min_n_per_mba; // Lowest per MBA allowed numerator
- uint16_t min_mem_power; // Max mem Power @min (x0.1W)
+// Nimbus/Cumulus dimm/centaur Info
+typedef union cmdh_mem_throt_data_set
+{
+ cmdh_mem_throt_nimbus_info_t nimbus;
+ cmdh_mem_throt_cumulus_info_t cumulus;
+} cmdh_mem_throt_info_t;
- uint16_t pcap1_n_per_mba; // Static per MBA numerator @PCAP1
- uint16_t pcap1_n_per_chip; // Static per chip numerator @PCAP1
- uint16_t pcap1_mem_power; // Max memory power @PCAP1 (x0.1W)
+typedef struct __attribute__ ((packed))
+{
+ cmdh_mem_throt_info_t mem_throt_info; // Nimbus/Cumulus information header
- uint16_t pcap2_n_per_mba; // Static per MBA numerator @PCAP2
- uint16_t pcap2_n_per_chip; // Static per chip numerator @PCAP2
- uint16_t pcap2_mem_power; // Max memory power @PCAP2 (x0.1W)
+ uint16_t min_n_per_mba; // Lowest per MBA allowed numerator
+ uint16_t min_mem_power; // Max mem Power @min (x0.1W)
- 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 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 ovs_n_per_mba; // Static per MBA @Oversubscription
- uint16_t ovs_n_per_chip; // Static per chip @Oversubscription
- uint16_t ovs_mem_power; // Max memory power @Oversubscription (x0.1W)
-}cumulus_mem_throt_t;
+ 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)
-typedef union cmdh_mem_throt_data_set
-{
- nimbus_mem_throt_t nimbus;
- cumulus_mem_throt_t cumulus;
+ 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 reserved_n_per_mba; // reserved
+ uint16_t reserved_n_per_chip; // reserved
+ uint16_t reserved_mem_power; // reserved
} cmdh_mem_throt_data_set_t;
+
// Config packet definition used by TMGT to
// send mem throttle min/max settings.
typedef struct __attribute__ ((packed))
{
cmdh_mem_throt_header_t header;
cmdh_mem_throt_data_set_t data_set[1];
-}cmdh_mem_throt_t;
+} cmdh_mem_throt_t;
// Used to mark present the config data TMGT has sent us.
typedef struct data_cnfg
diff --git a/src/occ_405/cmdh/cmdh_mnfg_intf.c b/src/occ_405/cmdh/cmdh_mnfg_intf.c
index 54bc662..cd38489 100755
--- a/src/occ_405/cmdh/cmdh_mnfg_intf.c
+++ b/src/occ_405/cmdh/cmdh_mnfg_intf.c
@@ -36,7 +36,6 @@
#include "centaur_control.h"
extern task_t G_task_table[TASK_END];
-extern centaur_throttle_t G_centaurThrottleLimits[MAX_NUM_CENTAURS][NUM_MBAS_PER_CENTAUR];
// Function Specification
//
diff --git a/src/occ_405/dimm/dimm.c b/src/occ_405/dimm/dimm.c
index 9453514..1f587e7 100755
--- a/src/occ_405/dimm/dimm.c
+++ b/src/occ_405/dimm/dimm.c
@@ -27,7 +27,7 @@
#include <ssx.h>
#include <occhw_async.h>
-#include <gpe_export.h>
+#include <dimm_structs.h>
#include <trac_interface.h>
#include <trac.h>
@@ -42,10 +42,11 @@
#include "amec_sys.h"
#include "lock.h"
#include "common.h"
+#include "memory.h"
#include "centaur_data.h"
extern bool G_mem_monitoring_allowed;
-extern task_t G_task_table[TASK_END];
+extern memory_control_task_t G_memory_control_task;
uint8_t G_dimm_state = DIMM_STATE_INIT; // Curret state of DIMM state machine
uint8_t G_maxDimmPorts = NUM_DIMM_PORTS;
@@ -54,9 +55,12 @@ bool G_dimm_i2c_reset_required = false;
uint32_t G_dimm_i2c_reset_cause = 0;
#define MAX_CONSECUTIVE_DIMM_RESETS 1
+
// On Nimbus, we are using the centaur number as the I2C port (keep same structure)
// There can be 8 DIMMs under a Centaur and 8 DIMMs per I2C port (max of 2 ports)
-#define NUM_DIMMS_PER_I2CPORT NUM_DIMMS_PER_CENTAUR
+// DIMM code assumed that NUM_DIMMS_PER_I2CPORT == NUM_DIMMS_PER_CENTAUR
+#define NUM_DIMMS_PER_I2CPORT 8
+
typedef struct {
bool disabled;
uint8_t errorCount;
@@ -69,8 +73,10 @@ dimmData_t G_dimm[NUM_DIMM_PORTS][NUM_DIMMS_PER_I2CPORT] = {{{false,0}}};
#define DIMM_AND_PORT ((G_dimm_sm_args.i2cPort<<8) | G_dimm_sm_args.dimm)
// GPE Requests
GpeRequest G_dimm_sm_request;
+
// GPE arguments
GPE_BUFFER(dimm_sm_args_t G_dimm_sm_args);
+GPE_BUFFER(dimm_control_args_t G_dimm_control_args);
@@ -121,79 +127,83 @@ uint8_t get_dimm_addr(uint8_t i_dimm)
return 0x30 | (i_dimm<<1);
}
-
-// Initialize the memory task data
-void memory_init()
+// Create DIMM state machine IPC request
+void memory_nimbus_init()
{
- if(G_mem_monitoring_allowed)
- {
- // Check if memory task is running (default task is for NIMBUS)
- const task_id_t mem_task = TASK_ID_DIMM_SM;
- if(!rtl_task_is_runnable(mem_task))
+ errlHndl_t l_err = NULL; // Error handler
+ int rc_dimm_sm = 0, rc_dimm_ctl = 0; // rcs from gpe ipc request creation commands
+ int rc_dimm = 0;
+
+ do {
+ // Initializes GPE request for DIMM temperature reading IPC Task,
+ DIMM_DBG("memory_nimbus_init: Creating request GPE1 DIMM data IPC task");
+ rc_dimm_sm = gpe_request_create(
+ &G_dimm_sm_request,
+ &G_async_gpe_queue1, // queue
+ IPC_ST_DIMM_SM_FUNCID, // entry_point
+ &G_dimm_sm_args, // entry_point arg
+ SSX_WAIT_FOREVER, // no timeout
+ NULL, // callback
+ NULL, // callback arg
+ ASYNC_CALLBACK_IMMEDIATE); // options
+ if(rc_dimm_sm)
{
- if (MEM_TYPE_NIMBUS == G_sysConfigData.mem_type)
- {
- // Init DIMM state manager IPC request
- memory_nimbus_init();
- }
- else
- {
- // TODO CUMULUS NOT SUPPORTED YET IN PHASE1
-#if 0
- TRAC_INFO("memory_init: calling centaur_init()");
- centaur_init(); //no rc, handles errors internally
-#endif
- TRAC_ERR("memory_init: invalid memory type 0x%02X", G_sysConfigData.mem_type);
- /*
- * @errortype
- * @moduleid DIMM_MID_MEMORY_INIT
- * @reasoncode MEMORY_INIT_FAILED
- * @userdata1 memory type
- * @userdata2 0
- * @devdesc Invalid memory type detected
- */
- errlHndl_t err = createErrl(DIMM_MID_MEMORY_INIT,
- MEMORY_INIT_FAILED,
- OCC_NO_EXTENDED_RC,
- ERRL_SEV_PREDICTIVE,
- NULL,
- DEFAULT_TRACE_SIZE,
- G_sysConfigData.mem_type,
- 0);
- REQUEST_RESET(err);
- }
+ TRAC_ERR("memory_control_init: Failed to initialize dimm state"
+ " machine IPC task [rc_dimm_sm=0x%x]",
+ rc_dimm_sm);
+ rc_dimm = rc_dimm_sm;
+ break;
+ }
- // check if the init resulted in a reset
- if(isSafeStateRequested())
- {
- TRAC_ERR("memory_init: OCC is being reset, memory init failed (type=0x%02X)",
- G_sysConfigData.mem_type);
- }
- else
- {
- // Initialization was successful. Set task flags to allow memory
- // tasks to run and also prevent from doing initialization again.
- G_task_table[mem_task].flags = MEMORY_DATA_RTL_FLAGS;
- //G_task_table[mem_task].flags = MEMORY_CONTROL_RTL_FLAGS;
- }
+ // Initializes GPE request for DIMM Control IPC Task,
+ DIMM_DBG("memory_nimbus_init: Creating request GPE1 DIMM control IPC task");
+ rc_dimm_ctl = gpe_request_create(
+ &G_memory_control_task.gpe_req, // gpe_req for the task
+ &G_async_gpe_queue1, // queue
+ IPC_ST_DIMM_CONTROL_FUNCID, // Function ID
+ &G_dimm_control_args, // parm for the task
+ SSX_WAIT_FOREVER, // no timeout
+ NULL, // callback
+ NULL, // callback argument
+ ASYNC_CALLBACK_IMMEDIATE ); // options
+
+ if(rc_dimm_ctl)
+ {
+ TRAC_ERR("memory_control_init: Failed to initialize dimm control"
+ " IPC task [rc_dimm_ctl=0x%x]",
+ rc_dimm_ctl);
+ rc_dimm = rc_dimm_sm;
+ break;
}
}
+ while(0);
-} // end memory_init()
+ if(rc_dimm) // Either dimm sm or dimm control gpe request creation failed.
+ {
+ /* @
+ * @errortype
+ * @moduleid DIMM_MID_NIMBUS_INIT
+ * @reasoncode SSX_GENERIC_FAILURE
+ * @userdata1 l_rc_gpe - Return code of failing function
+ * @userdata2 0
+ * @userdata4 ERC_CENTAUR_GPE_REQUEST_CREATE_FAILURE
+ * @devdesc Failed to initialize GPE1 DIMM IPC job
+ */
+ l_err = createErrl(
+ DIMM_MID_NIMBUS_INIT, //modId
+ SSX_GENERIC_FAILURE, //reasoncode
+ OCC_NO_EXTENDED_RC, //Extended reason code
+ ERRL_SEV_PREDICTIVE, //Severity
+ NULL, //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ rc_dimm, //userdata1
+ 0 //userdata2
+ );
+
+ REQUEST_RESET(l_err);
+ }
-// Create DIMM state machine IPC request
-void memory_nimbus_init()
-{
- DIMM_DBG("memory_nimbus_init: Creating request GPE1 DIMM request objects");
- gpe_request_create(&G_dimm_sm_request,
- &G_async_gpe_queue1, // queue
- IPC_ST_DIMM_SM_FUNCID, // entry_point
- &G_dimm_sm_args, // entry_point arg
- SSX_WAIT_FOREVER, // no timeout
- NULL, // callback
- NULL, // callback arg
- ASYNC_CALLBACK_IMMEDIATE); // options
}
@@ -613,8 +623,8 @@ void SIMULATE_HOST()
// End Function Specification
void process_dimm_temp()
{
- const uint8_t port = G_dimm_sm_args.i2cPort;
- const uint8_t dimm = G_dimm_sm_args.dimm;
+ const uint8_t port = G_dimm_sm_args.i2cPort;
+ const uint8_t dimm = G_dimm_sm_args.dimm;
uint8_t l_dimm_temp = G_dimm_sm_args.temp;
#define MIN_VALID_DIMM_TEMP 1
@@ -893,7 +903,7 @@ void task_dimm_sm(struct task *i_self)
if ((DIMM_TICK == 0) || (DIMM_TICK == 8))
{
// If DIMM has huid/sensor then it should be present
- if ((0 != G_sysConfigData.dimm_huids[L_dimmPort][L_dimmIndex]) &&
+ if (NIMBUS_DIMM_PRESENT(L_dimmPort,L_dimmIndex) &&
(G_dimm[L_dimmPort][L_dimmIndex].disabled == false))
{
G_dimm_sm_args.i2cPort = L_dimmPort;
diff --git a/src/occ_405/dimm/dimm.h b/src/occ_405/dimm/dimm.h
index c453e9a..15ea5d6 100644
--- a/src/occ_405/dimm/dimm.h
+++ b/src/occ_405/dimm/dimm.h
@@ -31,6 +31,30 @@
#include <errl.h>
#include <rtls.h>
+// If DIMM has huid/sensor then it is present
+#define NIMBUS_DIMM_PRESENT(port,dimm) (0 != G_sysConfigData.dimm_huids[port][dimm])
+
+// A bit vector that indicated the dimms (mbas) configured in a system.
+// Bit 0 (MSB) encodes the configuration status for port 0 on MC01
+// (or mba01 on centaur 0) a 1 indicated a dimm (mba) is configured
+// for throttling. Only most significant 8 bits used in Nimbus.
+extern uint16_t G_configured_mbas;
+
+// DIMM Throttle Limits have been configured?
+#define NIMBUS_DIMM_THROTTLING_CONFIGURED(vector,mc,port) \
+ (0 != (vector & (0x8000 >> ((port) + ((mc) * (MAX_NUM_MCU_PORTS))))))
+
+#define NIMBUS_DIMM_INDEX_THROTTLING_CONFIGURED(memIndex) \
+ (0 != (G_configured_mbas & (0x8000 >> memIndex)))
+
+#define NIMBUS_DIMM_PORT_THROTTLING_CONFIGURED(mc,port) \
+ (0 != (G_configured_mbas & (0x8000 >> ((mc) * (MAX_NUM_MCU_PORTS)))))
+
+// Configure NIMBUS_DIMM Throttling data on MC01/MC02's (0/1) port (0-3)
+#define CONFIGURE_NIMBUS_DIMM_THROTTLING(vector,mc,port) \
+ vector |= (0x8000 >> ((port) + (mc) * (MAX_NUM_MCU_PORTS)))
+
+
#define NUM_DIMM_PORTS 2
#define DIMM_TICK (CURRENT_TICK % MAX_NUM_TICKS)
diff --git a/src/occ_405/dimm/dimm_control.c b/src/occ_405/dimm/dimm_control.c
new file mode 100644
index 0000000..1188e76
--- /dev/null
+++ b/src/occ_405/dimm/dimm_control.c
@@ -0,0 +1,265 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/occ/cent/centaur_control.c $ */
+/* */
+/* OpenPOWER OnChipController Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2015,2016 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+
+//*************************************************************************/
+// Includes
+//*************************************************************************/
+#include "dimm_control.h"
+#include "dimm_structs.h"
+#include "errl.h"
+#include "trac.h"
+#include "rtls.h"
+#include "apss.h"
+#include "state.h"
+#include "amec_sys.h"
+#include "memory.h"
+
+//GPE IPC request and parms for the GPE job used for DIMM modules control.
+//extern GpeRequest G_dimm_control_request;
+extern dimm_control_args_t G_dimm_control_args;
+
+extern memory_control_task_t G_memory_control_task;
+
+// A bit vector that indicated that the dimms (mbas) are configured
+// in a nimbus (cumulus) system.
+// Bit 0 (MSB) encodes the configuration status for port 0 on MC01
+// (mba01 on centaur 0).
+// a 1 indicated a dimm (mba) is configured for throttling.
+// most significant 8 bits are used to cover nimbus' two MC pairs of 4 ports each.
+// Initialized to 0, sat by the FSP memory throttling configuration command
+// (0x21, format 0x12)
+extern uint16_t G_configured_mbas;
+
+
+//////////////////////////
+// Function Specification
+//
+// Name: dimm_control
+//
+// Description: RDIMM modules control.
+// Schedule a GPE IPC task to control the DIMMs whose
+// speed requested by the thermal controller has changed.
+//
+// Thread: RTL
+//
+// End Function Specification
+
+bool dimm_control(uint8_t mc, uint8_t port)
+{
+ DIMM_DBG("dimm_control: called at tick %d", CURRENT_TICK);
+
+ //update the min/max settings for all DIMMs according to mode
+ dimm_update_nlimits(mc, port);
+
+ // Convert speed request to N value, load N values into
+ // GPE1 G_dimm_control_args.dimmNumeratorValues struct
+ // and populate G_dimm_control_args.mc/port values
+ // corresponding to dimm to be throttled.
+ G_dimm_control_args.dimmNumeratorValues.new_n = FALSE; // Reset New N Value Flag prior to calling
+ populate_dimm_control_args(g_amec->mem_speed_request, mc, port,
+ &G_dimm_control_args);
+
+ // Check if the throttle value has been updated since the last time we
+ // sent it. If it has, then send a new value, otherwise do nothing.
+ if(G_dimm_control_args.dimmNumeratorValues.new_n)
+ {
+ DIMM_DBG("dimm throttle control changed: MC=%d. port=%d , Throttle=%d",
+ mc, port, g_amec->mem_speed_request);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+
+
+//////////////////////////
+// Function Specification
+//
+// Name: dimm_update_nlimits
+//
+// Description: Updates all memory dimms throttle settings, including:
+// 1) new settings from FSP
+// 2) change to/from TURBO or DPS mode
+// 3) enter/exit oversubscription
+//
+//
+// Thread: RTL
+//
+// End Function Specification
+
+#define DIMM_TRACE_THROTTLE_DELAY 8
+void dimm_update_nlimits(uint8_t mc, uint8_t port)
+{
+ /*------------------------------------------------------------------------*/
+ /* Local Variables */
+ /*------------------------------------------------------------------------*/
+ static uint32_t L_trace_throttle_count = 0;
+ uint16_t l_port_dimm_maxn = 0, l_slot_dimm_maxn = 0;
+
+ /*------------------------------------------------------------------------*/
+ /* Code */
+ /*------------------------------------------------------------------------*/
+
+ do
+ {
+ memory_throttle_t* l_active_limits;
+ mem_throt_config_data_t* l_state_limits;
+
+ // convert N Values for configured DIMMs only
+ if(NIMBUS_DIMM_THROTTLING_CONFIGURED(G_configured_mbas,mc,port))
+ {
+ l_active_limits = &G_memoryThrottleLimits[mc][port];
+ l_state_limits = &G_sysConfigData.mem_throt_limits[mc][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)
+ {
+ 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
+ {
+ l_port_dimm_maxn = l_state_limits->turbo_n_per_chip;
+ l_slot_dimm_maxn = l_state_limits->turbo_n_per_mba;
+ }
+
+ l_active_limits->max_n_per_chip = l_port_dimm_maxn;
+
+ //Trace when the dimm slot max N value changes
+ if(l_slot_dimm_maxn != l_active_limits->max_n_per_mba)
+ {
+ 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)
+ {
+ 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);
+
+ }
+ }
+
+ if(L_trace_throttle_count)
+ {
+ L_trace_throttle_count--;
+ }
+ } // NIMBUS_DIMM_THROTTLING_CONFIGURED ?
+
+ }while(0);
+}
+
+
+//////////////////////////
+// Function Specification
+//
+// Name: populate_dimm_control_args
+//
+// Description: Converts dimm throttle percentage into 'N' value
+// that can be written to the hardware, load N values
+// into GPE1 G_dimm_control_args.dimmNumeratorValue,
+// and populate G_dimm_control_args.mc/port for the
+// corresponding dimm.
+//
+//
+// Thread: RTL
+//
+// End Function Specification
+
+#define DIMM_THROTTLE_100_PERCENT_VALUE 1000
+void populate_dimm_control_args(uint16_t i_throttle, uint8_t mc, uint8_t port,
+ dimm_control_args_t * dimm_control_args)
+{
+ dimm_n_value_t dimm_nvalue;
+ memory_throttle_t* l_dimm_throttle;
+
+ // MC01 = 0, MC23 = 1
+ l_dimm_throttle = &G_memoryThrottleLimits[mc][port];
+
+ // a DIMM is configured?
+ if(NIMBUS_DIMM_THROTTLING_CONFIGURED(G_configured_mbas,mc,port))
+ {
+ // Convert the dimm throttle (in units of 0.1 %) to "N" value
+ dimm_nvalue.slot_n =
+ convert_speed2numerator(i_throttle,
+ l_dimm_throttle->min_n_per_mba,
+ l_dimm_throttle->max_n_per_mba);
+
+ dimm_nvalue.port_n = l_dimm_throttle->max_n_per_chip;
+
+ // A change in the N value for dimm control args(mc,port)?
+ if(dimm_nvalue.word32 !=
+ g_amec->sys.current_dimm_n_values[mc][port].word32)
+ {
+ dimm_control_args->dimmNumeratorValues.word32 = dimm_nvalue.word32;
+ g_amec->sys.current_dimm_n_values[mc][port].word32 =
+ dimm_nvalue.word32;
+ dimm_control_args->dimmNumeratorValues.new_n = 1;
+ dimm_control_args->mc = mc;
+ dimm_control_args->port = port;
+ }
+ }
+}
+
+//////////////////////////
+// Function Specification
+//
+// Name: convertSpeed2Numerator
+//
+// Description: Converts dimm throttle percentages into 'N' value
+// that can be written to the hardware.
+//
+// Thread: RTL
+//
+// End Function Specification
+
+uint16_t convert_speed2numerator(uint16_t i_throttle, uint16_t min_n_value, uint16_t max_n_value)
+{
+ uint16_t l_nvalue = 0;
+
+ // Convert the throttle (in units of 0.1 %) to "N" value
+ l_nvalue = (max_n_value * i_throttle) / DIMM_THROTTLE_100_PERCENT_VALUE;
+
+ //Clip to DIMM's per-slot min and max values
+ if(l_nvalue < min_n_value)
+ {
+ l_nvalue = min_n_value;
+ }
+ if(l_nvalue > max_n_value)
+ {
+ l_nvalue = max_n_value;
+ }
+
+ return l_nvalue;
+}
diff --git a/src/occ_405/dimm/dimm_control.h b/src/occ_405/dimm/dimm_control.h
new file mode 100644
index 0000000..6e9f02d
--- /dev/null
+++ b/src/occ_405/dimm/dimm_control.h
@@ -0,0 +1,39 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/occ_405/dimm/dimm_control.h $ */
+/* */
+/* OpenPOWER OnChipController Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2016 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+
+#include <occ_common.h>
+#include "dimm_structs.h"
+#include "rtls.h"
+
+#ifndef _DIMM_CONTROL_H
+#define _DIMM_CONTROL_H
+
+bool dimm_control(uint8_t mc, uint8_t port);
+void dimm_update_nlimits(uint8_t mc, uint8_t port);
+void populate_dimm_control_args(uint16_t i_throttle, uint8_t mc, uint8_t port,
+ dimm_control_args_t * dimm_control_args);
+uint16_t convert_speed2numerator(uint16_t i_throttle, uint16_t min_n_value, uint16_t max_n_value);
+
+#endif //_DIMM_CONTROL_H
diff --git a/src/occ_405/dimm/dimm_service_codes.h b/src/occ_405/dimm/dimm_service_codes.h
index 9261d04..fb2a157 100755
--- a/src/occ_405/dimm/dimm_service_codes.h
+++ b/src/occ_405/dimm/dimm_service_codes.h
@@ -31,10 +31,9 @@
enum dimmModuleId
{
DIMM_MID_STATE_MACHINE = DIMM_COMP_ID | 0x00,
- DIMM_MID_MEMORY_INIT = DIMM_COMP_ID | 0x01,
- DIMM_MID_NIMBUS_INIT = DIMM_COMP_ID | 0x02,
- DIMM_MID_DIMM_SM = DIMM_COMP_ID | 0x03,
- DIMM_MID_MARK_DIMM_FAILED = DIMM_COMP_ID | 0x04,
+ DIMM_MID_NIMBUS_INIT = DIMM_COMP_ID | 0x01,
+ DIMM_MID_DIMM_SM = DIMM_COMP_ID | 0x02,
+ DIMM_MID_MARK_DIMM_FAILED = DIMM_COMP_ID | 0x03,
};
#endif /* #ifndef _DIMM_SERVICE_CODES_H_ */
diff --git a/src/occ_405/img_defs.mk b/src/occ_405/img_defs.mk
index bdcc2d9..15daba6 100644
--- a/src/occ_405/img_defs.mk
+++ b/src/occ_405/img_defs.mk
@@ -224,6 +224,7 @@ APP_INCLUDES = -I$(IMAGE_SRCDIR)/rtls \
-I$(IMAGE_SRCDIR)/cent \
-I$(IMAGE_SRCDIR)/firdata \
-I$(IMAGE_SRCDIR)/dimm \
+ -I$(IMAGE_SRCDIR)/mem \
-I$(IMAGE_SRCDIR)/lock \
-I$(IMAGE_SRCDIR)/../occ_gpe0 \
diff --git a/src/occ_405/incl/comp_ids.h b/src/occ_405/incl/comp_ids.h
index e6ff8b6..0845754 100755
--- a/src/occ_405/incl/comp_ids.h
+++ b/src/occ_405/incl/comp_ids.h
@@ -84,5 +84,8 @@
#define DIMM_COMP_ID 0x0F00
#define DIMM_COMP_NAME "DIMM"
+// MEMORY Control
+#define MEM_COMP_ID 0x1000
+#define MEM_COMP_NAME "MEM"
#endif
diff --git a/src/occ_405/main.c b/src/occ_405/main.c
index 40de571..b12ad1c 100755
--- a/src/occ_405/main.c
+++ b/src/occ_405/main.c
@@ -507,26 +507,31 @@ void hmon_routine()
commitErrl(&l_err);
}
- //if we are in activate state, then monitor the processor temperature for
- //timeout conditions and the processor VRHOT signal.
- if (IS_OCC_STATE_ACTIVE())
+ //if we are in observation or activate state, then monitor the processor temperature
+ //for timeout conditions and the processor VRHOT signal.
+ if (IS_OCC_STATE_OBSERVATION() || IS_OCC_STATE_ACTIVE())
{
amec_health_check_proc_timeout();
amec_health_check_proc_vrhot();
}
-#if 0 // Memory thermal control loop is not ready yet
- //if we are in active state with memory temperature data being collected
+ //if we are in observation or active state with memory temperature data being collected
//then monitor the temperature collections for overtemp and timeout conditions
- if(IS_OCC_STATE_ACTIVE() &&
- rtl_task_is_runnable(TASK_ID_CENTAUR_DATA))
+ if((IS_OCC_STATE_OBSERVATION() || IS_OCC_STATE_ACTIVE()) &&
+ rtl_task_is_runnable(TASK_ID_DIMM_SM))
{
- amec_health_check_cent_timeout();
- amec_health_check_cent_temp();
+ // For Cumulus systems only, check for centaur timeout and overtemp errors
+ if (MEM_TYPE_CUMULUS == G_sysConfigData.mem_type)
+ {
+ amec_health_check_cent_timeout();
+ amec_health_check_cent_temp();
+ }
+
+ // For both Nimbus and Cumulus systems, check for rdimm-modules/centaur-dimm
+ // timeout and overtemp
amec_health_check_dimm_timeout();
amec_health_check_dimm_temp();
}
-#endif // Memory thermal control loop is not ready yet
}
diff --git a/src/occ_405/mem/memory.c b/src/occ_405/mem/memory.c
new file mode 100644
index 0000000..fe338ed
--- /dev/null
+++ b/src/occ_405/mem/memory.c
@@ -0,0 +1,411 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/occ_405/mem/memory.c $ */
+/* */
+/* OpenPOWER OnChipController Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2014,2016 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+
+#include <trac_interface.h>
+#include <trac.h>
+
+#include "memory.h"
+#include "dimm_control.h"
+#include "centaur_control.h"
+#include "centaur_data.h"
+#include "memory_service_codes.h"
+#include <occ_service_codes.h> // for SSX_GENERIC_FAILURE
+
+extern bool G_mem_monitoring_allowed;
+extern dimm_control_args_t G_dimm_control_args;
+extern task_t G_task_table[TASK_END];
+
+
+// @TODO: TEMP - uncomment when Centaur code is enabled
+//extern GpeScomParms G_centaur_control_reg_parms;
+
+// This array identifies dimm throttle limits for both Centaurs (Cumulus) and
+// rdimms (Nimbus) based systems.
+//
+// For Nimbus systems, only the first two rows (corresponding to memory controller
+// pairs M01 and M23) are used.
+//
+// For Cumulus systems, only the first two columns (corresponding to the two mba
+// pairs mba01 and mba23) are used.
+memory_throttle_t G_memoryThrottleLimits[MAX_NUM_MEM_CONTROLLERS][MAX_NUM_MCU_PORTS] =
+{
+ {{0}, {0}, {0}, {0}},
+ {{0}, {0}, {0}, {0}},
+ {{0}, {0}, {0}, {0}},
+ {{0}, {0}, {0}, {0}},
+ {{0}, {0}, {0}, {0}},
+ {{0}, {0}, {0}, {0}},
+ {{0}, {0}, {0}, {0}},
+ {{0}, {0}, {0}, {0}}
+};
+
+//Memory structure used for task data pointers in both Cumulus (Centaur)
+//and Nimbus (RDIMM) systems.
+memory_control_task_t G_memory_control_task =
+{
+ .startMemIndex = 0, // First Memory Control Index (Centaur/MC_pair|port)
+ .prevMemIndex = 7, // Previous Memory Control Index written to
+ .curMemIndex = 0, // Current Memory Control Index
+ .endMemIndex = 7, // Last Memory Control Index
+ .traceThresholdFlags = 0, // Trace Throttle Flags
+};
+
+
+// Function Specification
+//
+// Name: task_memory_control
+//
+// Description: Performs system memory control:
+// - for Nimbus: calls dimm_control() to control dimms power
+// - for Cumulus: calls centaur_control() to control centaur power
+//
+// End Function Specification
+
+// wait up to 16 ticks before logging timeout failure
+#define MEMORY_CONTROL_SCOM_TIMEOUT 16
+
+void task_memory_control( task_t * i_task )
+{
+ //track # of consecutive failures on a specific Centaur/RDIMM
+ static uint8_t L_scom_timeout[MAX_NUM_MEM_CONTROLLERS] = {0};
+
+ errlHndl_t l_err = NULL; // Error handler
+ int rc = 0; // Return code
+ uint8_t memIndex;
+ static bool L_gpe_scheduled = FALSE;
+ static uint8_t L_gpe_fail_logged = 0;
+ static bool L_gpe_idle_traced = FALSE;
+ static bool L_gpe_had_1_tick = FALSE;
+
+ uint32_t gpe_rc = 0;
+
+ // Pointer to the task data structure
+ memory_control_task_t* memControlTask = (memory_control_task_t*) i_task->data_ptr;
+
+
+ if (MEM_TYPE_NIMBUS == G_sysConfigData.mem_type)
+ {
+ gpe_rc = G_dimm_control_args.error.rc;
+ }
+ else if (MEM_TYPE_CUMULUS == G_sysConfigData.mem_type)
+ {
+// @TODO: TEMP - uncomment when Centaur code is enabled
+// gpe_rc = G_centaur_control_reg_parms.rc;
+ }
+
+ do
+ {
+ memIndex = memControlTask->curMemIndex;
+
+ //First, check to see if the previous GPE request still running
+ //A request is considered idle if it is not attached to any of the
+ //asynchronous request queues
+ if( !(async_request_is_idle(&memControlTask->gpe_req.request)) )
+ {
+ L_scom_timeout[memIndex]++;
+ //This can happen due to variability in when the task runs
+ if(!L_gpe_idle_traced && L_gpe_had_1_tick)
+ {
+ TRAC_INFO("task_memory_control: GPE is still running. memIndex[%d]", memIndex);
+ memControlTask->traceThresholdFlags |= MEMORY_CONTROL_GPE_STILL_RUNNING;
+ L_gpe_idle_traced = TRUE;
+ }
+ L_gpe_had_1_tick = TRUE;
+ break;
+ }
+ else
+ {
+ //Request is idle
+ L_gpe_had_1_tick = FALSE;
+ if(L_gpe_idle_traced)
+ {
+ TRAC_INFO("task_memory_control: GPE completed. memIndex[%d]", memIndex);
+ L_gpe_idle_traced = FALSE;
+ }
+ }
+
+ //check scom status
+ if(L_gpe_scheduled)
+ {
+ if(!async_request_completed(&memControlTask->gpe_req.request) || gpe_rc)
+ {
+ if (MEM_TYPE_CUMULUS == G_sysConfigData.mem_type)
+ {
+ if(!(L_gpe_fail_logged & (CENTAUR0_PRESENT_MASK >> memIndex)))
+ {
+// @TODO: TEMP - uncomment when Centaur code is enabled
+/* if (!check_centaur_checkstop(memIndex))
+ {
+ L_gpe_fail_logged |= CENTAUR0_PRESENT_MASK >> memIndex;
+ }
+*/
+ }
+ }
+ //Request failed. Keep count of failures and request a reset if we reach a
+ //max retry count
+ L_scom_timeout[memIndex]++;
+ if(L_scom_timeout[memIndex] == MEMORY_CONTROL_SCOM_TIMEOUT)
+ {
+ break;
+ }
+
+ }//if(!async_request_completed(&memControlTask->gpe_req.request) || l_parms->rc)
+ else
+ {
+ //request completed successfully. reset the timeout.
+ L_scom_timeout[memIndex] = 0;
+ }
+ }//if(L_gpe_scheduled)
+
+ //The previous GPE job completed. Now get ready for the next job.
+ L_gpe_scheduled = FALSE;
+
+
+ //Update current dimm/centaur index if we didn't fail
+ memControlTask->prevMemIndex = memIndex;
+ if ( memIndex >= memControlTask->endMemIndex )
+ {
+ memIndex = memControlTask->startMemIndex;
+ }
+ else
+ {
+ memIndex++;
+ }
+ memControlTask->curMemIndex = memIndex;
+
+
+ if (MEM_TYPE_NIMBUS == G_sysConfigData.mem_type)
+ {
+ if(!NIMBUS_DIMM_INDEX_THROTTLING_CONFIGURED(memIndex))
+ {
+ break;
+ }
+
+ // control dimm specified by mc,port
+ uint8_t mc = memIndex>>2;
+ uint8_t port = memIndex&3;
+
+ // Do the update_nlimit, calculate new N values, check whether throttle values
+ // were updated, then Schedule GPE request, rc if problem, else L_gpe_schedule
+ rc = dimm_control(mc, port);
+
+ MEM_DBG("memIndex=%d, mc|port=0x%%04X, rc=%d",
+ memIndex, mc<<8| port, rc);
+
+ }
+ else if (MEM_TYPE_CUMULUS == G_sysConfigData.mem_type)
+ {
+ //If centaur is not present or neither MBA is configured then skip it.
+ if(!CENTAUR_PRESENT(memIndex) ||
+ (!MBA_CONFIGURED(memIndex, 0) && !MBA_CONFIGURED(memIndex, 1)))
+ {
+ break;
+ }
+// @TODO TEMP: centaur code not ready yet
+// rc = centaur_control(memIndex); // Control one centaur
+ }
+
+ if(rc)
+ {
+ rc = gpe_request_schedule(&G_memory_control_task.gpe_req);
+
+ if( rc )
+ {
+ if (MEM_TYPE_NIMBUS == G_sysConfigData.mem_type)
+ {
+ gpe_rc = G_dimm_control_args.error.rc;
+ }
+ else if (MEM_TYPE_CUMULUS == G_sysConfigData.mem_type)
+ {
+// @TODO: TEMP - uncomment when Centaur code is enabled
+// gpe_rc = G_centaur_control_reg_parms.rc;
+ }
+
+ //Error in schedule gpe memory (dimm/centaur) control
+ TRAC_ERR("task_memory_control: Failed to schedule memory control gpe rc=%x",
+ rc);
+
+ /* @
+ * @errortype
+ * @moduleid MEM_MID_TASK_MEMORY_CONTROL
+ * @reasoncode SSX_GENERIC_FAILURE
+ * @userdata1 rc - Return code of failing function
+ * @userdata2 0
+ * @userdata4 ERC_MEM_CONTROL_SCHEDULE_FAILURE
+ * @devdesc OCC Failed to schedule a GPE job for memory control
+ */
+ l_err = createErrl(
+ MEM_MID_TASK_MEMORY_CONTROL, // modId
+ SSX_GENERIC_FAILURE, // reasoncode
+ ERC_MEM_CONTROL_SCHEDULE_FAILURE, // Extended reason code
+ ERRL_SEV_UNRECOVERABLE, // Severity
+ NULL, // Trace Buf
+ DEFAULT_TRACE_SIZE, // Trace Size
+ rc, // userdata1
+ gpe_rc // userdata2
+ );
+
+ addUsrDtlsToErrl(
+ l_err, //io_err
+ (uint8_t *) &(memControlTask->gpe_req.ffdc), //i_dataPtr,
+ sizeof(memControlTask->gpe_req.ffdc), //i_size
+ ERRL_USR_DTL_STRUCT_VERSION_1, //version
+ ERRL_USR_DTL_BINARY_DATA); //type
+
+ REQUEST_RESET(l_err); //This will add a firmware callout for us
+ break;
+ }
+
+ L_gpe_scheduled = TRUE;
+ }
+
+ } while(0);
+
+
+//Global centaur structures used for task data pointers
+
+
+ if(L_scom_timeout[memIndex] == MEMORY_CONTROL_SCOM_TIMEOUT)
+ {
+ if (MEM_TYPE_NIMBUS == G_sysConfigData.mem_type)
+ {
+ if(memIndex>>2)
+ {
+ TRAC_ERR("task_memory_control: Timeout scomming MC23:port[%d]", memIndex&3);
+ }
+ else
+ {
+ TRAC_ERR("task_memory_control: Timeout scomming MC01:port[%d]", memIndex&3);
+ }
+ }
+ else if (MEM_TYPE_CUMULUS == G_sysConfigData.mem_type)
+ {
+ TRAC_ERR("task_memory_control: Timeout scomming centaur[%d]", memIndex);
+ }
+ /* @
+ * @errortype
+ * @moduleid MEM_MID_TASK_MEMORY_CONTROL
+ * @reasoncode INTERNAL_FAILURE
+ * @userdata1 centaur/memIndex number
+ * @userdata2 0
+ * @userdata4 OCC_NO_EXTENDED_RC
+ * @devdesc Timed out trying to set the memory throttle settings
+ * throttle settings.
+ */
+ l_err = createErrl(
+ MEM_MID_TASK_MEMORY_CONTROL, // modId
+ INTERNAL_FAILURE, // reasoncode
+ OCC_NO_EXTENDED_RC, // Extended reason code
+ ERRL_SEV_PREDICTIVE, // Severity
+ NULL, // Trace Buf
+ DEFAULT_TRACE_SIZE, // Trace Size
+ memIndex, // userdata1
+ 0 // userdata2
+ );
+
+ addUsrDtlsToErrl(l_err, //io_err
+ (uint8_t *) &(memControlTask->gpe_req.ffdc), //i_dataPtr,
+ sizeof(memControlTask->gpe_req.ffdc), //i_size
+ ERRL_USR_DTL_STRUCT_VERSION_1, //version
+ ERRL_USR_DTL_BINARY_DATA); //type
+
+ //callout the centaur
+ addCalloutToErrl(l_err,
+ ERRL_CALLOUT_TYPE_HUID,
+ G_sysConfigData.centaur_huids[memIndex],
+ ERRL_CALLOUT_PRIORITY_MED);
+
+ //callout the processor
+ addCalloutToErrl(l_err,
+ ERRL_CALLOUT_TYPE_HUID,
+ G_sysConfigData.proc_huid,
+ ERRL_CALLOUT_PRIORITY_MED);
+
+ REQUEST_RESET(l_err);
+ }
+
+ return;
+}
+
+
+// Initialize the memory task data
+void memory_init()
+{
+ if(G_mem_monitoring_allowed)
+ {
+ // Check if memory task is running (default task is for NIMBUS)
+ const task_id_t mem_task = TASK_ID_DIMM_SM;
+ if(!rtl_task_is_runnable(mem_task))
+ {
+ if (MEM_TYPE_NIMBUS == G_sysConfigData.mem_type)
+ {
+ // Init DIMM state manager IPC request
+ memory_nimbus_init();
+ }
+ else
+ {
+ // TODO CUMULUS NOT SUPPORTED YET IN PHASE1
+#if 0
+ TRAC_INFO("memory_init: calling centaur_init()");
+ centaur_init(); //no rc, handles errors internally
+#endif
+ TRAC_ERR("memory_init: invalid memory type 0x%02X", G_sysConfigData.mem_type);
+ /*
+ * @errortype
+ * @moduleid MEM_MID_MEMORY_INIT
+ * @reasoncode MEMORY_INIT_FAILED
+ * @userdata1 memory type
+ * @userdata2 0
+ * @devdesc Invalid memory type detected
+ */
+ errlHndl_t err = createErrl(MEM_MID_MEMORY_INIT,
+ MEMORY_INIT_FAILED,
+ OCC_NO_EXTENDED_RC,
+ ERRL_SEV_PREDICTIVE,
+ NULL,
+ DEFAULT_TRACE_SIZE,
+ G_sysConfigData.mem_type,
+ 0);
+ REQUEST_RESET(err);
+ }
+
+ // check if the init resulted in a reset
+ if(isSafeStateRequested())
+ {
+ TRAC_ERR("memory_init: OCC is being reset, memory init failed (type=0x%02X)",
+ G_sysConfigData.mem_type);
+ }
+ else
+ {
+ // Initialization was successful. Set task flags to allow memory
+ // tasks to run and also prevent from doing initialization again.
+ G_task_table[mem_task].flags = MEMORY_DATA_RTL_FLAGS;
+ G_task_table[TASK_ID_MEMORY_CONTROL].flags = MEMORY_CONTROL_RTL_FLAGS;
+ }
+ }
+ }
+
+} // end memory_init()
+
diff --git a/src/occ_405/mem/memory.h b/src/occ_405/mem/memory.h
new file mode 100644
index 0000000..1314823
--- /dev/null
+++ b/src/occ_405/mem/memory.h
@@ -0,0 +1,76 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/occ_405/mem/memory.h $ */
+/* */
+/* OpenPOWER OnChipController Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2014,2016 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+
+#ifndef _MEMORY_H
+#define _MEMORY_H
+
+#include "occ_sys_config.h"
+
+typedef enum
+{
+ MEMORY_CONTROL_GPE_STILL_RUNNING = 0x01,
+ MEMORY_CONTROL_RESERVED_1 = 0x02,
+ MEMORY_CONTROL_RESERVED_2 = 0x04,
+ MEMORY_CONTROL_RESERVED_3 = 0x08,
+ MEMORY_CONTROL_RESERVED_4 = 0x10,
+ MEMORY_CONTROL_RESERVED_5 = 0x20,
+ MEMORY_CONTROL_RESERVED_6 = 0x40,
+ MEMORY_CONTROL_RESERVED_7 = 0x80,
+} eMemoryControlTraceFlags;
+
+//per slot/mba throttle values used for rdimm/centaur-dimm control
+typedef struct
+{
+ uint16_t max_n_per_mba; //mode and OVS dependent, from config data
+ uint16_t max_n_per_chip; //mode and OVS dependent, from config data
+ uint16_t min_n_per_mba; //from config data
+} memory_throttle_t;
+
+// 64 bits encoding different bit fields corresponding to dimms
+// either on centaurs or on I2C ports, up to 8 dimms on 8 centaurs/ports
+typedef union
+{
+ uint64_t bigword;
+ uint32_t words[2];
+ uint8_t bytes[8];
+}dimm_sensor_flags_t;
+
+
+//Memory data collect structures used for task data pointers
+struct memory_control_task {
+ uint8_t startMemIndex;
+ uint8_t prevMemIndex;
+ uint8_t curMemIndex;
+ uint8_t endMemIndex;
+ uint8_t traceThresholdFlags;
+ GpeRequest gpe_req;
+} __attribute__ ((__packed__));
+typedef struct memory_control_task memory_control_task_t;
+
+extern memory_throttle_t G_memoryThrottleLimits[MAX_NUM_MEM_CONTROLLERS][MAX_NUM_MCU_PORTS];
+
+void task_memory_control( task_t * i_task );
+
+#endif // _MEMORY_H
diff --git a/src/occ_405/mem/memory_service_codes.h b/src/occ_405/mem/memory_service_codes.h
new file mode 100644
index 0000000..1934b12
--- /dev/null
+++ b/src/occ_405/mem/memory_service_codes.h
@@ -0,0 +1,41 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/occ_405/cent/centaur_control.h $ */
+/* */
+/* OpenPOWER OnChipController Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2015 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+
+#ifndef _MEMORY_SERVICE_CODES_H
+#define _MEMORY_SERVICE_CODES_H
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+#include <comp_ids.h>
+
+
+enum memModuleId
+{
+ MEM_MID_TASK_MEMORY_CONTROL = MEM_COMP_ID | 0x00,
+ MEM_MID_MEMORY_INIT = MEM_COMP_ID | 0x01,
+};
+
+#endif // _MEMORY_SERVICE_CODES_H
diff --git a/src/occ_405/occLinkInputFile b/src/occ_405/occLinkInputFile
index b95e116..5322089 100644
--- a/src/occ_405/occLinkInputFile
+++ b/src/occ_405/occLinkInputFile
@@ -18,6 +18,7 @@ INPUT ( amec_amester.o
amec_slave_smh.o
amec_tasks.o
apss.o
+ centaur_control.o
centaur_data.o
cmdh_dbug_cmd.o
cmdh_fsp_cmds_datacnfg.o
@@ -33,6 +34,7 @@ INPUT ( amec_amester.o
dcomSlaveRx.o
dcomSlaveTx.o
dimm.o
+ dimm_control.o
dpss.o
errl.o
ffdc.o
@@ -41,6 +43,7 @@ INPUT ( amec_amester.o
ll_ffdc.o
lock.o
main.o
+ memory.o
mode.o
occ_sys_config.o
occbuildname.o
diff --git a/src/occ_405/occ_service_codes.h b/src/occ_405/occ_service_codes.h
index aa6d243..c7699f5 100644
--- a/src/occ_405/occ_service_codes.h
+++ b/src/occ_405/occ_service_codes.h
@@ -204,6 +204,9 @@ enum occExtReasonCode
ERC_DIMM_SCHEDULE_FAILURE = 0x00000080,
ERC_DIMM_COMPLETE_FAILURE = 0x00000081,
+
+ ERC_MEM_CONTROL_SCHEDULE_FAILURE = 0x00000080,
+ ERC_MEM_CONTROL_COMPLETE_FAILURE = 0x00000081,
};
// Error log Module Ids
diff --git a/src/occ_405/occ_sys_config.c b/src/occ_405/occ_sys_config.c
index 448692f..d6dac89 100755
--- a/src/occ_405/occ_sys_config.c
+++ b/src/occ_405/occ_sys_config.c
@@ -189,10 +189,20 @@ occSysConfigData_t G_sysConfigData =
.mem_type = MEM_TYPE_NIMBUS,
.dimm_i2c_engine = PIB_I2C_ENGINE_E,
- // -----------------------------------------------------------
- // Memory Throttle Limits
- // -----------------------------------------------------------
- .mem_throt_limits = {{{0},{0}},{{0},{0}},{{0},{0}},{{0},{0}},{{0},{0}},{{0},{0}},{{0},{0}},{{0},{0}}},
+ // -------------------------------------------------------------------
+ // Memory Throttle Limits Initialization (for both Nimbus and Cumulus)
+ // -------------------------------------------------------------------
+ .mem_throt_limits =
+ {
+ {{0}, {0}, {0}, {0}},
+ {{0}, {0}, {0}, {0}},
+ {{0}, {0}, {0}, {0}},
+ {{0}, {0}, {0}, {0}},
+ {{0}, {0}, {0}, {0}},
+ {{0}, {0}, {0}, {0}},
+ {{0}, {0}, {0}, {0}},
+ {{0}, {0}, {0}, {0}}
+ },
// --------------------------------------
// Vdd/Vcs Uplift vid codes
diff --git a/src/occ_405/occ_sys_config.h b/src/occ_405/occ_sys_config.h
index ae52556..2fd7535 100755
--- a/src/occ_405/occ_sys_config.h
+++ b/src/occ_405/occ_sys_config.h
@@ -45,12 +45,21 @@
#define MAX_NUM_MEM_CONTROLLERS 8
#define MAX_NUM_CENTAURS 8
#define NUM_PROC_VRMS 2
+
#define MAX_NUM_MCU_PORTS 4
+#define MC01 0
+#define MC23 1
+#define NUM_NIMBUS_MC_PAIRS 2
+
+#define NUM_DIMMS_PER_MEM_CONTROLLER 8
+#define NUM_I2C_PORTS 2
+
#define NUM_PROC_CHIPS_PER_OCC 1
#define NUM_CENTAURS_PER_MEM_CONTROLLER 1
#define NUM_PORT_PAIRS_PER_CENTAUR 2
-#define NUM_DIMMS_PER_CENTAUR 8
+#define NUM_DIMMS_PER_CENTAUR \
+ (NUM_DIMMS_PER_MEM_CONTROLLER/NUM_CENTAURS_PER_MEM_CONTROLLER)
#define NUM_MBAS_PER_CENTAUR 2
#define UPPER_LIMIT_PROC_FREQ_MHZ 6000
@@ -223,27 +232,30 @@ typedef struct
uint8_t pcap_data_count; // Used by OCC only. Initialized to 0 and incremented by 1 with every new packet.
} pcap_config_data_t;
-// Memory Throttle settings
+// Memory Centaur 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_n_per_mba; //minimum value
+ uint16_t min_mem_power; //Max mem Power @min (x0.1W)
- uint16_t pcap1_n_per_mba; //max mba value for Power Cap Level 1
- uint16_t pcap1_mem_power; //max memory power @PCAP L1
+ uint16_t turbo_n_per_mba; //max mba value for Power Cap @Turbo
+ uint16_t turbo_n_per_chip; //Static per chip numerator @Turbo
+ uint16_t turbo_mem_power; //max memory power @Turbo L1
- uint16_t pcap2_n_per_mba; //max mba value for Power Cap Level 2
- uint16_t pcap2_mem_power; //max memory power @PCAP L2
+ uint16_t pcap_n_per_mba; //max mba value for Power Cap Level 2
+ uint16_t pcap_n_per_chip; //Static per chip numerator @PCAP
+ uint16_t pcap_mem_power; //max memory power @PCAP L2
- 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_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 ovs_n_per_mba; //max mba value for oversubscription
- uint16_t ovs_n_per_chip; //chip setting for oversubscription
- uint16_t ovs_mem_power; //max memory power @oversubscription
+ uint16_t reserved_n_per_mba; //reserved
+ uint16_t reserved_n_per_chip; //reserved
+ uint16_t reserved_mem_power; //reserved
} mem_throt_config_data_t;
+
// Sys Config Structure
// Needs to be 128 bytes aligned so we can do a DMA to transfer this to SRAM from
@@ -353,7 +365,18 @@ typedef struct
// --------------------------------------
// Memory Throttle limits
// --------------------------------------
- mem_throt_config_data_t mem_throt_limits[MAX_NUM_CENTAURS][NUM_MBAS_PER_CENTAUR];
+ // This array holds throttle configuration parameters for
+ // both nimbus and cumulus systems.
+
+ // Throttle limits are layout:
+ // - Nimbus: mem_throt_limits[mc_pair][port]
+ // mc_pair = 0/1 for MC01/MC23, port=0-3
+ // (only first two rows populated)
+
+ // - Cumulus mem_throt_limits[cent][mba]
+ // cent=0-8, mba = 0/1 for mba01/mba23
+ // (only first two columns populated)
+ mem_throt_config_data_t mem_throt_limits[MAX_NUM_MEM_CONTROLLERS][MAX_NUM_MCU_PORTS];
// --------------------------------------
// Vdd/Vcs Uplift vid codes
diff --git a/src/occ_405/rtls/rtls.h b/src/occ_405/rtls/rtls.h
index 7ec3c2e..56849fb 100755
--- a/src/occ_405/rtls/rtls.h
+++ b/src/occ_405/rtls/rtls.h
@@ -47,18 +47,19 @@ typedef enum {
TASK_ID_APSS_DONE,
TASK_ID_DCOM_RX_INBX,
TASK_ID_DCOM_TX_INBX,
- TASK_ID_POKE_WDT, // Reset ppc405 watchdog and OCB timer
+ TASK_ID_POKE_WDT, // Reset ppc405 watchdog and OCB timer
TASK_ID_DCOM_WAIT_4_MSTR,
TASK_ID_DCOM_RX_OUTBX,
TASK_ID_DCOM_TX_OUTBX,
- TASK_ID_MISC_405_CHECKS, // Miscellaneous checks to be done by 405
+ TASK_ID_MISC_405_CHECKS, // Miscellaneous checks to be done by 405
TASK_ID_DCOM_PARSE_FW_MSG,
- TASK_ID_AMEC_SLAVE, // AMEC SMH tasks
- TASK_ID_AMEC_MASTER, // AMEC SMH tasks
-// TASK_ID_CORE_DATA_CONTROL,
-// TASK_ID_GPU_SM, // GPU State Machine
- TASK_ID_DIMM_SM, // DIMM State Machine
-// TASK_ID_MEM_DEADMAN, // Memory deadman timer
+ TASK_ID_AMEC_SLAVE, // AMEC SMH tasks
+ TASK_ID_AMEC_MASTER, // AMEC SMH tasks
+// TASK_ID_CORE_DATA_CONTROL,
+// TASK_ID_GPU_SM, // GPU State Machine
+ TASK_ID_DIMM_SM, // DIMM State Machine
+// TASK_ID_MEM_DEADMAN, // Memory deadman timer
+ TASK_ID_MEMORY_CONTROL, // Memory (centaur/dimm) control task
TASK_END // This must always be the last enum in this list,
// so that TASK_END always equals the last task ID + 1.
} task_id_t;
diff --git a/src/occ_405/rtls/rtls_tables.c b/src/occ_405/rtls/rtls_tables.c
index 5f08b17..00ccf3d 100755
--- a/src/occ_405/rtls/rtls_tables.c
+++ b/src/occ_405/rtls/rtls_tables.c
@@ -32,6 +32,7 @@
#include "proc_data_control.h"
#include <centaur_data.h>
#include <centaur_control.h>
+#include "memory.h"
#include "amec_master_smh.h"
#include "dimm.h"
#include <common.h>
@@ -116,7 +117,8 @@ task_t G_task_table[TASK_END] = {
// { FLAGS_GPU_SM, task_gpu_sm, NULL }, // TASK_ID_GPU_SM
{ FLAGS_MEMORY_DATA, task_dimm_sm, NULL }, // TASK_ID_DIMM_SM
// TEMP -- NOT YET IMPLEMENTED
-// { FLAGS_MEM_DEADMAN, task_mem_deadman, NULL }, // TASK_ID_MEM_DEADMAN
+// { FLAGS_MEM_DEADMAN, task_mem_deadman, NULL }, // TASK_ID_MEM_DEADMAN
+ { FLAGS_MEMORY_CONTROL, task_memory_control, (void *) &G_memory_control_task }, // TASK_ID_MEMORY_CONTROL
};
const uint8_t G_tick0_seq[] = {
@@ -126,6 +128,7 @@ const uint8_t G_tick0_seq[] = {
TASK_ID_APSS_CONT,
TASK_ID_CORE_DATA_HIGH,
TASK_ID_APSS_DONE,
+ TASK_ID_MEMORY_CONTROL,
//TASK_ID_CORE_DATA_CONTROL,
TASK_ID_DCOM_WAIT_4_MSTR,
TASK_ID_DCOM_RX_INBX,
@@ -145,6 +148,7 @@ const uint8_t G_tick1_seq[] = {
//TASK_ID_GPU_SM,
TASK_ID_APSS_CONT,
TASK_ID_APSS_DONE,
+ TASK_ID_MEMORY_CONTROL,
//TASK_ID_MEM_DEADMAN,
//TASK_ID_CORE_DATA_CONTROL,
TASK_ID_DCOM_WAIT_4_MSTR,
@@ -165,6 +169,7 @@ const uint8_t G_tick2_seq[] = {
TASK_ID_APSS_CONT,
TASK_ID_CORE_DATA_HIGH,
TASK_ID_APSS_DONE,
+ TASK_ID_MEMORY_CONTROL,
//TASK_ID_CORE_DATA_CONTROL,
TASK_ID_DCOM_WAIT_4_MSTR,
TASK_ID_DCOM_RX_INBX,
@@ -183,6 +188,7 @@ const uint8_t G_tick3_seq[] = {
TASK_ID_APSS_CONT,
TASK_ID_CORE_DATA_HIGH,
TASK_ID_APSS_DONE,
+ TASK_ID_MEMORY_CONTROL,
//TASK_ID_MEM_DEADMAN,
//TASK_ID_CORE_DATA_CONTROL,
TASK_ID_DCOM_WAIT_4_MSTR,
@@ -203,6 +209,7 @@ const uint8_t G_tick4_seq[] = {
TASK_ID_APSS_CONT,
TASK_ID_CORE_DATA_HIGH,
TASK_ID_APSS_DONE,
+ TASK_ID_MEMORY_CONTROL,
//TASK_ID_CORE_DATA_CONTROL,
TASK_ID_DCOM_WAIT_4_MSTR,
TASK_ID_DCOM_RX_INBX,
@@ -222,6 +229,7 @@ const uint8_t G_tick5_seq[] = {
//TASK_ID_GPU_SM,
TASK_ID_APSS_CONT,
TASK_ID_APSS_DONE,
+ TASK_ID_MEMORY_CONTROL,
//TASK_ID_MEM_DEADMAN,
//TASK_ID_CORE_DATA_CONTROL,
TASK_ID_DCOM_WAIT_4_MSTR,
@@ -242,6 +250,7 @@ const uint8_t G_tick6_seq[] = {
TASK_ID_APSS_CONT,
TASK_ID_CORE_DATA_HIGH,
TASK_ID_APSS_DONE,
+ TASK_ID_MEMORY_CONTROL,
//TASK_ID_CORE_DATA_CONTROL,
TASK_ID_DCOM_WAIT_4_MSTR,
TASK_ID_DCOM_RX_INBX,
@@ -260,6 +269,7 @@ const uint8_t G_tick7_seq[] = {
TASK_ID_APSS_CONT,
TASK_ID_CORE_DATA_HIGH,
TASK_ID_APSS_DONE,
+ TASK_ID_MEMORY_CONTROL,
//TASK_ID_MEM_DEADMAN,
//TASK_ID_CORE_DATA_CONTROL,
TASK_ID_DCOM_WAIT_4_MSTR,
@@ -280,6 +290,7 @@ const uint8_t G_tick8_seq[] = {
TASK_ID_APSS_CONT,
TASK_ID_CORE_DATA_HIGH,
TASK_ID_APSS_DONE,
+ TASK_ID_MEMORY_CONTROL,
//TASK_ID_CORE_DATA_CONTROL,
TASK_ID_DCOM_WAIT_4_MSTR,
TASK_ID_DCOM_RX_INBX,
@@ -299,6 +310,7 @@ const uint8_t G_tick9_seq[] = {
//TASK_ID_GPU_SM,
TASK_ID_APSS_CONT,
TASK_ID_APSS_DONE,
+ TASK_ID_MEMORY_CONTROL,
//TASK_ID_MEM_DEADMAN,
//TASK_ID_CORE_DATA_CONTROL,
TASK_ID_DCOM_WAIT_4_MSTR,
@@ -319,6 +331,7 @@ const uint8_t G_tick10_seq[] = {
TASK_ID_APSS_CONT,
TASK_ID_CORE_DATA_HIGH,
TASK_ID_APSS_DONE,
+ TASK_ID_MEMORY_CONTROL,
//TASK_ID_CORE_DATA_CONTROL,
TASK_ID_DCOM_WAIT_4_MSTR,
TASK_ID_DCOM_RX_INBX,
@@ -337,6 +350,7 @@ const uint8_t G_tick11_seq[] = {
TASK_ID_APSS_CONT,
TASK_ID_CORE_DATA_HIGH,
TASK_ID_APSS_DONE,
+ TASK_ID_MEMORY_CONTROL,
//TASK_ID_MEM_DEADMAN,
//TASK_ID_CORE_DATA_CONTROL,
TASK_ID_DCOM_WAIT_4_MSTR,
@@ -357,6 +371,7 @@ const uint8_t G_tick12_seq[] = {
TASK_ID_APSS_CONT,
TASK_ID_CORE_DATA_HIGH,
TASK_ID_APSS_DONE,
+ TASK_ID_MEMORY_CONTROL,
//TASK_ID_CORE_DATA_CONTROL,
TASK_ID_DCOM_WAIT_4_MSTR,
TASK_ID_DCOM_RX_INBX,
@@ -376,6 +391,7 @@ const uint8_t G_tick13_seq[] = {
//TASK_ID_GPU_SM,
TASK_ID_APSS_CONT,
TASK_ID_APSS_DONE,
+ TASK_ID_MEMORY_CONTROL,
//TASK_ID_MEM_DEADMAN,
//TASK_ID_CORE_DATA_CONTROL,
TASK_ID_DCOM_WAIT_4_MSTR,
@@ -396,6 +412,7 @@ const uint8_t G_tick14_seq[] = {
TASK_ID_APSS_CONT,
TASK_ID_CORE_DATA_HIGH,
TASK_ID_APSS_DONE,
+ TASK_ID_MEMORY_CONTROL,
//TASK_ID_CORE_DATA_CONTROL,
TASK_ID_DCOM_WAIT_4_MSTR,
TASK_ID_DCOM_RX_INBX,
@@ -414,6 +431,7 @@ const uint8_t G_tick15_seq[] = {
TASK_ID_APSS_CONT,
TASK_ID_CORE_DATA_HIGH,
TASK_ID_APSS_DONE,
+ TASK_ID_MEMORY_CONTROL,
//TASK_ID_MEM_DEADMAN,
//TASK_ID_CORE_DATA_CONTROL,
TASK_ID_DCOM_WAIT_4_MSTR,
diff --git a/src/occ_405/state.h b/src/occ_405/state.h
index 16609e5..8e8e9ba 100755
--- a/src/occ_405/state.h
+++ b/src/occ_405/state.h
@@ -153,6 +153,9 @@ extern SMGR_SMS_CMD_TYPE G_occ_internal_sms; // TODO: Move to state.c
// Returns true if OCC State is active
#define IS_OCC_STATE_ACTIVE() ( (OCC_STATE_ACTIVE == G_occ_internal_state)? 1 : 0 )
+// Returns true if OCC State is observation
+#define IS_OCC_STATE_OBSERVATION() ( (OCC_STATE_OBSERVATION == G_occ_internal_state)? 1 : 0 )
+
/**
* @struct smgr_state_trans_t
* @brief Used by the "Set State" command to call the correct transition
diff --git a/src/occ_405/topfiles.mk b/src/occ_405/topfiles.mk
index 994dac1..54a09fd 100644
--- a/src/occ_405/topfiles.mk
+++ b/src/occ_405/topfiles.mk
@@ -43,6 +43,7 @@ TOP-C-SOURCES = amec/amec_analytics.c \
amec/amec_slave_smh.c \
amec/amec_tasks.c \
amec/sensor_power.c \
+ cent/centaur_control.c \
cent/centaur_data.c \
cmdh/cmdh_dbug_cmd.c \
cmdh/cmdh_fsp_cmds_datacnfg.c \
@@ -61,11 +62,13 @@ TOP-C-SOURCES = amec/amec_analytics.c \
dcom/dcomSlaveRx.c \
dcom/dcomSlaveTx.c \
dimm/dimm.c \
+ dimm/dimm_control.c \
errl/errl.c \
firdata/fir_data_collect.c \
homer.c \
lock/lock.c \
main.c \
+ mem/memory.c \
mode.c \
occ_sys_config.c \
occbuildname.c \
diff --git a/src/occ_405/trac/trac.h b/src/occ_405/trac/trac.h
index 601d3a8..747cd25 100755
--- a/src/occ_405/trac/trac.h
+++ b/src/occ_405/trac/trac.h
@@ -300,6 +300,16 @@ extern void dumpHexString(const void *i_data, const unsigned int len, const char
#define DIMM_DBG_HEXDUMP(data, len, string)
#endif
+#ifdef MEM_DEBUG
+ #define MEM_DBG(frmt,args...) \
+ DBG_PRINT(frmt,##args)
+ #define MEM_DBG_HEXDUMP(data, len, string) \
+ DEBUG_HEXDUMP(data, len, string)
+#else
+ #define MEM_DBG(frmt,args...)
+ #define MEM_DBG_HEXDUMP(data, len, string)
+#endif
+
#else // NO_TRAC_STRINGS
#define TRAC_ERR(frmt,args...)
diff --git a/src/occ_gpe1/gpe1_dimm_control.c b/src/occ_gpe1/gpe1_dimm_control.c
new file mode 100644
index 0000000..99d5395
--- /dev/null
+++ b/src/occ_gpe1/gpe1_dimm_control.c
@@ -0,0 +1,121 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/occ_gpe1/gpe1_dimm_control.c $ */
+/* */
+/* OpenPOWER OnChipController Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2015,2016 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+
+#include "pk.h"
+#include "ppe42_scom.h"
+#include "ipc_api.h"
+#include "ipc_async_cmd.h"
+#include "gpe_err.h"
+#include "gpe_util.h"
+#include "dimm_structs.h"
+#include "gpe1.h"
+
+/*
+ * Function Specifications:
+ *
+ * Name: gpe_dimm_control
+ *
+ * Description: DIMM control code on the GPE
+ *
+ * Inputs: cmd is a pointer to IPC msg's cmd and cmd_data struct
+ *
+ * Outputs: error: sets rc, address, and ffdc in the cmd_data's
+ * GpeErrorStruct
+ *
+ * End Function Specification
+ */
+
+#define NUM_NIMBUS_MC_PAIRS 2
+#define MAX_NUM_MCU_PORTS 4
+
+void gpe_dimm_control(ipc_msg_t* cmd, void* arg)
+{
+ // Note: arg was set to 0 in ipc func table (ipc_func_tables.c), so don't use it.
+ // the ipc arguments passed through the ipc_msg_t structure, has a pointer
+ // to the G_gpe_start_pwr_meas_read_args struct.
+
+ int rc;
+ uint64_t regValue; // a pointer to hold the putscom_abs register value
+ ipc_async_cmd_t *async_cmd = (ipc_async_cmd_t*)cmd;
+ dimm_control_args_t *args = (dimm_control_args_t*)async_cmd->cmd_data;
+
+ int mc = args->mc, port = args->port; // memory controller pair and port
+
+ args->error.error = 0;
+ args->error.ffdc = 0;
+
+ do
+ { // read N/M DIMM Throttling Control SCOM Register for specified MC pair and port numbers
+ rc = getscom_abs(N_M_DIMM_TCR(mc,port), &regValue);
+ if(rc)
+ {
+ PK_TRACE("gpe_dimm_control: N/M DIMM Throttling Control Register read fails"
+ "MC#|Port:0x%08x, Address:0x%08x, rc:0x%08x",
+ (uint32_t)((mc << 16) | port),
+ N_M_DIMM_TCR(mc,port), rc);
+
+ gpe_set_ffdc(&(args->error), N_M_DIMM_TCR(mc,port),
+ GPE_RC_SCOM_GET_FAILED, rc);
+ break;
+ }
+
+ // Clear old N values for slot and port
+ regValue &= 0x1FFFFFFFF;
+ // copy slot and port N values (31 bits) from passed dimmNumeratorValues
+ regValue |= ((uint64_t) (args->dimmNumeratorValues.word32 & 0xFFFFFFFE)) << 32 ;
+
+ // Write new slot and port N Values
+ rc = putscom_abs(N_M_DIMM_TCR(mc,port), regValue);
+ if(rc)
+ {
+ PK_TRACE("gpe_dimm_control: N/M DIMM Throttling Control Register write fails"
+ "dimm#:%d, Address:0x%04x, Nvalues:0x%08x, rc:0x%08x",
+ (uint16_t)((mc << 8) | port),
+ N_M_DIMM_TCR(mc,port), regValue, rc);
+
+ gpe_set_ffdc(&(args->error), N_M_DIMM_TCR(mc,port),
+ GPE_RC_SCOM_GET_FAILED, rc);
+ break;
+ }
+ else
+ {
+ GPE1_DIMM_DBG("gpe_dimm_control: N/M DIMM Throttling Control Register write"
+ "mc|port#:0x%04x, Address:0x%08x, Nvalues:0x%08x",
+ (uint16_t)((mc << 8) | port),
+ N_M_DIMM_TCR(mc,port), regValue);
+ }
+ } while(0);
+
+ // send back a response, IPC success even if ffdc/rc are non zeros
+ rc = ipc_send_rsp(cmd, IPC_RC_SUCCESS);
+ if(rc)
+ {
+ PK_TRACE("gpe_dimm_control: Failed to send response back. Halting GPE1", rc);
+ gpe_set_ffdc(&(args->error), 0x00, GPE_RC_IPC_SEND_FAILED, rc);
+ pk_halt();
+ }
+}
+
+
diff --git a/src/occ_gpe1/gpe1_dimm_read.c b/src/occ_gpe1/gpe1_dimm_read.c
index d89b0bf..8f542d6 100644
--- a/src/occ_gpe1/gpe1_dimm_read.c
+++ b/src/occ_gpe1/gpe1_dimm_read.c
@@ -34,7 +34,7 @@
#include "ipc_async_cmd.h"
#include "gpe1.h"
#include "gpe1_dimm.h"
-
+#include "dimm_structs.h"
void dimm_write_int_mask(ipc_msg_t* cmd, void* arg);
void dimm_write_mode(ipc_msg_t* cmd, void* arg);
diff --git a/src/occ_gpe1/gpe1_dimm_reset.c b/src/occ_gpe1/gpe1_dimm_reset.c
index eedc917..0463977 100644
--- a/src/occ_gpe1/gpe1_dimm_reset.c
+++ b/src/occ_gpe1/gpe1_dimm_reset.c
@@ -34,6 +34,7 @@
#include "ipc_async_cmd.h"
#include "gpe1.h"
#include "gpe1_dimm.h"
+#include "dimm_structs.h"
/*
diff --git a/src/occ_gpe1/ipc_func_tables.c b/src/occ_gpe1/ipc_func_tables.c
index 113dacd..ab352c6 100644
--- a/src/occ_gpe1/ipc_func_tables.c
+++ b/src/occ_gpe1/ipc_func_tables.c
@@ -25,6 +25,7 @@
#include "ipc_api.h"
#include "gpe1_dimm.h"
+void gpe_dimm_control(ipc_msg_t* cmd, void* arg);
// Function table for multi target (common) functions
IPC_MT_FUNC_TABLE_START
@@ -41,7 +42,7 @@ IPC_MT_FUNC_TABLE_END
// Function table for single target (processor-specific) functions
IPC_ST_FUNC_TABLE_START
IPC_HANDLER(gpe_dimm_sm, 0) // 0 - IPC_ST_DIMM_SM_FUNCID
-IPC_HANDLER_DEFAULT // 1
+IPC_HANDLER(gpe_dimm_control, 0) // 1 - IPC_ST_DIMM_CONTROL_FUNCID
IPC_HANDLER_DEFAULT // 2
IPC_HANDLER_DEFAULT // 3
IPC_HANDLER_DEFAULT // 4
diff --git a/src/occ_gpe1/topfiles.mk b/src/occ_gpe1/topfiles.mk
index d1a957c..4499c81 100644
--- a/src/occ_gpe1/topfiles.mk
+++ b/src/occ_gpe1/topfiles.mk
@@ -23,7 +23,8 @@
#
# IBM_PROLOG_END_TAG
-TOP-C-SOURCES = gpe1_main.c gpe1_dimm_read.c gpe1_dimm_reset.c pk_app_irq_table.c ipc_func_tables.c
+TOP-C-SOURCES = gpe1_main.c gpe1_dimm_read.c gpe1_dimm_reset.c \
+ pk_app_irq_table.c ipc_func_tables.c gpe1_dimm_control.c
TOP-S-SOURCES =
TOP_OBJECTS = $(TOP-C-SOURCES:.c=.o) $(TOP-S-SOURCES:.S=.o)
OpenPOWER on IntegriCloud