summaryrefslogtreecommitdiffstats
path: root/src/occ_405/thread
diff options
context:
space:
mode:
authorWilliam Bryan <wilbryan@us.ibm.com>2015-08-03 12:38:58 -0500
committerWilliam A. Bryan <wilbryan@us.ibm.com>2015-08-03 15:32:27 -0500
commit420e6d248cc6d2b3c39bc3970e3bb6747b3bddc3 (patch)
treec9f6691eddba39193e39aa769367e1267fb9fc86 /src/occ_405/thread
parentadade8c8ef30ed519322674c762d95663009c5d4 (diff)
downloadtalos-occ-420e6d248cc6d2b3c39bc3970e3bb6747b3bddc3.tar.gz
talos-occ-420e6d248cc6d2b3c39bc3970e3bb6747b3bddc3.zip
new ssx and lib files
Change-Id: I2328b1e86d59e3788910687d762fb70ec680058f Reviewed-on: http://gfw160.aus.stglabs.ibm.com:8080/gerrit/19503 Reviewed-by: William A. Bryan <wilbryan@us.ibm.com> Tested-by: William A. Bryan <wilbryan@us.ibm.com>
Diffstat (limited to 'src/occ_405/thread')
-rwxr-xr-xsrc/occ_405/thread/chom.c451
-rwxr-xr-xsrc/occ_405/thread/chom.h231
-rwxr-xr-xsrc/occ_405/thread/test/Makefile64
-rwxr-xr-xsrc/occ_405/thread/test/app.mk79
-rwxr-xr-xsrc/occ_405/thread/test/threadtest.c317
-rwxr-xr-xsrc/occ_405/thread/thread.h88
-rwxr-xr-xsrc/occ_405/thread/threadSch.c322
-rwxr-xr-xsrc/occ_405/thread/threadSch.h49
-rwxr-xr-xsrc/occ_405/thread/thread_service_codes.h48
-rwxr-xr-xsrc/occ_405/thread/thrm_thread.c459
-rwxr-xr-xsrc/occ_405/thread/thrm_thread.h62
11 files changed, 2170 insertions, 0 deletions
diff --git a/src/occ_405/thread/chom.c b/src/occ_405/thread/chom.c
new file mode 100755
index 0000000..b75bda8
--- /dev/null
+++ b/src/occ_405/thread/chom.c
@@ -0,0 +1,451 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/occ/thread/chom.c $ */
+/* */
+/* OpenPOWER OnChipController Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2011,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 */
+
+#include <occ_common.h>
+#include <comp_ids.h>
+#include <sensor.h>
+#include <trac.h>
+#include <chom.h>
+#include <mode.h>
+#include <dcom.h>
+#include <amec_sys.h>
+#include <occ_service_codes.h>
+#include <thread_service_codes.h>
+
+extern amec_sys_t g_amec_sys;
+
+#define CHOM_SENSOR_DATA(index,data) [index] = data
+
+// chom timer
+uint32_t g_chom_gen_periodic_log_timer;
+// track which power mode has been during the polling period
+uint8_t g_chom_pwr_modes[OCC_INTERNAL_MODE_MAX_NUM]; // Nominal, SPS, DPS, DPS-MP, FFO
+// force immediate chom log flag
+uint8_t g_chom_force;
+// chom data log
+ChomLogData_t g_chom_log;
+ChomLogData_t * g_chom = &g_chom_log;
+
+// Make sure that the size of chom log is less than 3kB
+// otherwise cause error on the compile.
+STATIC_ASSERT( sizeof(ChomLogData_t) > CHOM_LOG_DATA_MAX );
+
+// Chom Sensors Table
+// Some of the chom sensors need multiple mini-sensor to calculate
+// the max, summstion of temperature or bandwidth
+// mark those mini-sensor "NULL" and will be updated
+// from "chom_update_sensors()"
+
+const uint16_t * g_chom_sensor_table[CHOM_NUM_OF_SENSORS] =
+{ // Node total power (DC)
+ &g_amec_sys.sys.pwr250us.sample,
+ // Socket power
+ &g_amec_sys.proc[0].pwr250us.sample,
+ &G_dcom_slv_outbox_rx[1].pwr250usp0,
+ &G_dcom_slv_outbox_rx[2].pwr250usp0,
+ &G_dcom_slv_outbox_rx[3].pwr250usp0,
+ &G_dcom_slv_outbox_rx[4].pwr250usp0,
+ &G_dcom_slv_outbox_rx[5].pwr250usp0,
+ &G_dcom_slv_outbox_rx[6].pwr250usp0,
+ &G_dcom_slv_outbox_rx[7].pwr250usp0,
+ // Memory power
+ &G_dcom_slv_outbox_rx[0].pwr250usmemp0,
+ &G_dcom_slv_outbox_rx[1].pwr250usmemp0,
+ &G_dcom_slv_outbox_rx[2].pwr250usmemp0,
+ &G_dcom_slv_outbox_rx[3].pwr250usmemp0,
+ &G_dcom_slv_outbox_rx[4].pwr250usmemp0,
+ &G_dcom_slv_outbox_rx[5].pwr250usmemp0,
+ &G_dcom_slv_outbox_rx[6].pwr250usmemp0,
+ &G_dcom_slv_outbox_rx[7].pwr250usmemp0,
+ // Fan power
+ &g_amec_sys.fan.pwr250usfan.sample,
+ // Processor frequency
+ &G_dcom_slv_outbox_rx[0].freqa2msp0,
+ &G_dcom_slv_outbox_rx[1].freqa2msp0,
+ &G_dcom_slv_outbox_rx[2].freqa2msp0,
+ &G_dcom_slv_outbox_rx[3].freqa2msp0,
+ &G_dcom_slv_outbox_rx[4].freqa2msp0,
+ &G_dcom_slv_outbox_rx[5].freqa2msp0,
+ &G_dcom_slv_outbox_rx[6].freqa2msp0,
+ &G_dcom_slv_outbox_rx[7].freqa2msp0,
+ // Processor utilization sensor
+ &G_dcom_slv_outbox_rx[0].util2msp0,
+ &G_dcom_slv_outbox_rx[1].util2msp0,
+ &G_dcom_slv_outbox_rx[2].util2msp0,
+ &G_dcom_slv_outbox_rx[3].util2msp0,
+ &G_dcom_slv_outbox_rx[4].util2msp0,
+ &G_dcom_slv_outbox_rx[5].util2msp0,
+ &G_dcom_slv_outbox_rx[6].util2msp0,
+ &G_dcom_slv_outbox_rx[7].util2msp0,
+ // Max Core temperature for all processors in the node
+ NULL,
+ // Max Centaur temperature for all Centaurs in the node
+ NULL,
+ // Max Dimm temperature for all Dimms in the node
+ NULL,
+ // Instructions per second sensor
+ NULL,
+ // Memory bandwidth for process memory controller
+ // P0M0 ~ P0M7
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ // P1M0 ~ P1M7
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ // P2M0 ~ P2M7
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ // P3M0 ~ P3M7
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ // P4M0 ~ P4M7
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ // P5M0 ~ P5M7
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ // P6M0 ~ P6M7
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ // P7M0 ~ P7M7
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+};
+
+// Function Specification
+//
+// Name: chom_data_init
+//
+// Description: Init chom data
+//
+// End Function Specification
+void chom_data_init()
+{
+ // chom data reset
+ chom_data_reset();
+ // update eyecatcher
+ memcpy(&g_chom->nodeData.eyecatcher, "CHOM", 0x04);
+ // update chom version
+ g_chom->nodeData.version = CHOM_VERSION;
+ // update num of sensors
+ g_chom->nodeData.numSensors = CHOM_NUM_OF_SENSORS;
+}
+
+
+// Function Specification
+//
+// Name: chom_data_reset
+//
+// Description: Reset chom data
+//
+// End Function Specification
+void chom_data_reset()
+{
+ // reset chom data log
+ memset(g_chom, 0x00, sizeof(*g_chom));
+ // reset chom modes in log
+ memset(g_chom_pwr_modes, 0x00, sizeof(g_chom_pwr_modes));
+ // reset chom timer
+ g_chom_gen_periodic_log_timer = 0;
+ // reset flag
+ g_chom_force = FALSE;
+
+}
+
+
+// Function Specification
+//
+// Name: chom_update_sensors
+//
+// Description: Update chom sensor data
+//
+// End Function Specification
+void chom_update_sensors()
+{
+ uint16_t l_max_core_temp = 0;
+ uint16_t l_max_cent_temp = 0;
+ uint16_t l_max_dimm_temp = 0;
+ uint16_t l_mips = 0;
+ uint16_t l_mem_rw = 0;
+ uint16_t l_sample = 0;
+ uint16_t i = 0, j = 0, k = 0;
+
+ // Is the current mode different than previous poll
+ if (g_chom->nodeData.curPwrMode != CURRENT_MODE())
+ {
+ // update current power mode
+ g_chom->nodeData.curPwrMode = CURRENT_MODE();
+ // copy the current mode data to previous mode
+ memcpy(&g_chom->sensorData[1], &g_chom->sensorData[0], sizeof(ChomSensorData_t));
+ // reset all fields in the current chom sensors
+ memset(&g_chom->sensorData[0], 0x00, sizeof(ChomSensorData_t));
+ // update power saving mode of sensor data
+ g_chom->sensorData[0].pwrMode.mode = g_chom->nodeData.curPwrMode;
+
+ // initial min value of chom sensors
+ for (i=0 ; i<CHOM_NUM_OF_SENSORS ; i++)
+ {
+ g_chom->sensorData[0].sensor[i].sampleMin = 0xffff;
+ }
+
+ // update the number of power modes during the polling period
+ switch (g_chom->nodeData.curPwrMode)
+ {
+ case OCC_MODE_NOMINAL:
+ g_chom_pwr_modes[OCC_INTERNAL_MODE_NOM] = 1;
+ break;
+
+ case OCC_MODE_PWRSAVE:
+ g_chom_pwr_modes[OCC_INTERNAL_MODE_SPS] = 1;
+ break;
+
+ case OCC_MODE_DYN_POWER_SAVE:
+ g_chom_pwr_modes[OCC_INTERNAL_MODE_DPS] = 1;
+ break;
+
+ case OCC_MODE_DYN_POWER_SAVE_FP:
+ g_chom_pwr_modes[OCC_INTERNAL_MODE_DPS_MP] = 1;
+ break;
+
+ case OCC_MODE_FFO:
+ g_chom_pwr_modes[OCC_INTERNAL_MODE_FFO] = 1;
+ break;
+
+ default:
+ TRAC_INFO("chom_update_sensors: Cannot record chom data for mode 0x%02X",
+ g_chom->sensorData[0].pwrMode.mode);
+ break;
+ }
+ }
+
+ // update number of samples
+ g_chom->sensorData[0].pwrMode.numOfSamples++;
+
+ // update chom sensors which has multiple mini-sensor source
+ for (i = 0 ; i<MAX_OCCS ; i++)
+ {
+ if (G_dcom_slv_outbox_rx[i].temp2msp0peak > l_max_core_temp)
+ {
+ l_max_core_temp = G_dcom_slv_outbox_rx[i].temp2msp0peak;
+ }
+
+ if (G_dcom_slv_outbox_rx[i].temp2mscent > l_max_cent_temp)
+ {
+ l_max_cent_temp = G_dcom_slv_outbox_rx[i].temp2mscent;
+ }
+
+ if (G_dcom_slv_outbox_rx[i].temp2msdimm > l_max_dimm_temp)
+ {
+ l_max_dimm_temp = G_dcom_slv_outbox_rx[i].temp2msdimm;
+ }
+ }
+ g_chom->sensorData[0].sensor[CHOMTEMPPROC].sample = l_max_core_temp;
+ g_chom->sensorData[0].sensor[CHOMTEMPCENT].sample = l_max_cent_temp;
+ g_chom->sensorData[0].sensor[CHOMTEMPDIMM].sample = l_max_dimm_temp;
+
+ // update MIPS
+ k = 0;
+ for (i=0 ; i<MAX_OCCS ; i++)
+ {
+ if (0 != G_dcom_slv_outbox_rx[i].ips2msp0)
+ {
+ l_mips += G_dcom_slv_outbox_rx[i].ips2msp0;
+ k++;
+ }
+ }
+ if (k != 0)
+ {
+ g_chom->sensorData[0].sensor[CHOMIPS].sample = (l_mips/k);
+ }
+
+ // update memory bandwidth
+ k = CHOMBWP0M0;
+ for (i=0 ; i<MAX_OCCS ; i++)
+ {
+ for (j=0 ; j<MAX_NUM_MEM_CONTROLLERS ; j++)
+ {
+ // TODO: Need to take a snapshot of the "max" field for that sensor and
+ // redefine the mini-sensor information that we pass back to the Master
+ l_mem_rw = G_dcom_slv_outbox_rx[i].mrd2msp0mx[j]+G_dcom_slv_outbox_rx[i].mwr2msp0mx[j];
+ g_chom->sensorData[0].sensor[k].sample = l_mem_rw;
+ k++;
+ }
+ }
+
+ // loop through all sensors and update data from mini-sensors
+ for (i = 0 ; i<CHOM_NUM_OF_SENSORS ; i++)
+ { // update sample, min, max, average sensor data
+ if (NULL != g_chom_sensor_table[i])
+ {
+ //Report all sensors listed in g_chom_sensor_table, unless
+ //we have a Murano (DCM), then we only report the power from the
+ //OCC_DCM_MASTER occ. The DCM occ pairs (OCC_DCM_MASTER,OCC_DCM_SLAVE) are
+ //((0,1),(2,3),(4,5),(6,7)).
+ if( ((i >= CHOMPWRS0) && (i <= CHOMPWRS7)) &&
+ (CFAM_CHIP_TYPE_MURANO == cfam_chip_type()) &&
+ (((i-CHOMPWRS0) % 2) == 1) )
+ {
+ //Do nothing
+ }
+ else
+ {
+ // directly mapping to mini-sensor
+ g_chom->sensorData[0].sensor[i].sample = *g_chom_sensor_table[i];
+ }
+ }
+
+ l_sample = g_chom->sensorData[0].sensor[i].sample;
+
+ if (g_chom->sensorData[0].sensor[i].sampleMin > l_sample)
+ {
+ g_chom->sensorData[0].sensor[i].sampleMin = l_sample;
+ }
+ if (g_chom->sensorData[0].sensor[i].sampleMax < l_sample)
+ {
+ g_chom->sensorData[0].sensor[i].sampleMax = l_sample;
+ }
+ g_chom->sensorData[0].sensor[i].accumulator += l_sample;
+ g_chom->sensorData[0].sensor[i].average = (g_chom->sensorData[0].sensor[i].accumulator/
+ g_chom->sensorData[0].pwrMode.numOfSamples);
+ }
+}
+
+
+// Function Specification
+//
+// Name: chom_collect_cpi_data
+//
+// Description: collect CPI data
+//
+// End Function Specification
+void chom_collect_cpi_data(void)
+{
+ // TODO
+}
+
+
+// Function Specification
+//
+// Name: chom_gen_periodic_log
+//
+// Description: Create call home data logs
+//
+// End Function Specification
+void chom_gen_periodic_log()
+{
+ uint8_t i = 0;
+ errlHndl_t l_errlHndl = NULL;
+
+ TRAC_INFO("Enter chom_gen_periodic_log");
+
+ // update total time
+ g_chom->nodeData.totalTime = g_chom_gen_periodic_log_timer;
+
+ // update the number of different power modes
+ for (i=0 ; i<OCC_INTERNAL_MODE_MAX_NUM ; i++)
+ {
+ if (g_chom_pwr_modes[i] == 1)
+ {
+ g_chom->nodeData.modeInLog++;
+ }
+ }
+
+ // collect CPI data
+ chom_collect_cpi_data();
+
+ /* @
+ * @errortype
+ * @moduleid THRD_MID_GEN_CALLHOME_LOG
+ * @reasoncode GEN_CALLHOME_LOG
+ * @userdata1 0
+ * @userdata2 0
+ * @userdata4 OCC_NO_EXTENDED_RC
+ * @devdesc Generating periodic call-home log, which contains critical power/thermal/performance data since the last log was generated (or the last OCC reset)
+ */
+ l_errlHndl = createErrl(
+ THRD_MID_GEN_CALLHOME_LOG, // modId
+ GEN_CALLHOME_LOG, // reasoncode
+ OCC_NO_EXTENDED_RC, // Extended reason code
+ ERRL_SEV_CALLHOME_DATA, // Severity; will be changed to informational in errl.c
+ NULL, // Trace Buf
+ 0, // Trace Size
+ 0, // userdata1
+ 0 // userdata2
+ );
+
+ // add chom data
+ addUsrDtlsToErrl(l_errlHndl,
+ (uint8_t*)g_chom,
+ sizeof(*g_chom),
+ ERRL_STRUCT_VERSION_1,
+ ERRL_USR_DTL_CALLHOME_DATA);
+
+ // commit error log
+ if (l_errlHndl != NULL)
+ {
+ commitErrl(&l_errlHndl);
+ }
+}
+
+
+// Function Specification
+//
+// Name: chom_force_gen_log()
+//
+// Description: immediate chom log
+//
+// End Function Specification
+void chom_force_gen_log()
+{
+ g_chom_force = TRUE;
+}
+
+
+// Function Specification
+//
+// Name: chom_main
+//
+// Description: Call home data routine
+//
+// End Function Specification
+void chom_main()
+{
+ MAIN_DBG("CHOM routine processing...");
+
+ // check if this is the first time we run
+ if (memcmp(&g_chom->nodeData.eyecatcher, "CHOM", 0x04) != 0)
+ {
+ chom_data_init();
+ }
+
+ // only update chom sensors on an active OCC
+ if (IS_OCC_STATE_ACTIVE())
+ {
+ chom_update_sensors();
+ }
+
+ // increase chom timer
+ g_chom_gen_periodic_log_timer++;
+
+ // check if the timer expired
+ if ((g_chom_gen_periodic_log_timer >= CHOM_GEN_LOG_PERIODIC_TIME) ||
+ (TRUE == g_chom_force))
+ {
+ chom_gen_periodic_log();
+ chom_data_reset();
+ }
+}
diff --git a/src/occ_405/thread/chom.h b/src/occ_405/thread/chom.h
new file mode 100755
index 0000000..b899e9e
--- /dev/null
+++ b/src/occ_405/thread/chom.h
@@ -0,0 +1,231 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/occ/thread/chom.h $ */
+/* */
+/* OpenPOWER OnChipController Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2011,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 _CHOM_H
+#define _CHOM_H
+
+#include <occ_common.h>
+#include <trac_interface.h>
+
+#define CHOM_GEN_LOG_PERIODIC_TIME 86400 // seconds in a day
+#define CHOM_VERSION 0x00
+// Max size of chom data log
+#define CHOM_LOG_DATA_MAX 3072
+
+// List of call home sensors
+enum
+{
+ // Node total power (DC)
+ CHOMPWR = 0,
+ // Socket power
+ CHOMPWRS0,
+ CHOMPWRS1,
+ CHOMPWRS2,
+ CHOMPWRS3,
+ CHOMPWRS4,
+ CHOMPWRS5,
+ CHOMPWRS6,
+ CHOMPWRS7,
+ // Memory power
+ CHOMPWRM0,
+ CHOMPWRM1,
+ CHOMPWRM2,
+ CHOMPWRM3,
+ CHOMPWRM4,
+ CHOMPWRM5,
+ CHOMPWRM6,
+ CHOMPWRM7,
+ // Fan power
+ CHOMPWRFAN,
+ // Processor frequency
+ CHOMFREQP0,
+ CHOMFREQP1,
+ CHOMFREQP2,
+ CHOMFREQP3,
+ CHOMFREQP4,
+ CHOMFREQP5,
+ CHOMFREQP6,
+ CHOMFREQP7,
+ // Processor utilization sensor
+ CHOMUTILP0,
+ CHOMUTILP1,
+ CHOMUTILP2,
+ CHOMUTILP3,
+ CHOMUTILP4,
+ CHOMUTILP5,
+ CHOMUTILP6,
+ CHOMUTILP7,
+ // Max core temperature for all processors in the node
+ CHOMTEMPPROC,
+ // Max Centaur temperature for all Centaurs in the node
+ CHOMTEMPCENT,
+ // Max Dimm temperature for all Dimms in the node
+ CHOMTEMPDIMM,
+ // Instructions per second sensor
+ CHOMIPS,
+ // Memory bandwidth for process memory controller
+ CHOMBWP0M0,
+ CHOMBWP0M1,
+ CHOMBWP0M2,
+ CHOMBWP0M3,
+ CHOMBWP0M4,
+ CHOMBWP0M5,
+ CHOMBWP0M6,
+ CHOMBWP0M7,
+ CHOMBWP1M0,
+ CHOMBWP1M1,
+ CHOMBWP1M2,
+ CHOMBWP1M3,
+ CHOMBWP1M4,
+ CHOMBWP1M5,
+ CHOMBWP1M6,
+ CHOMBWP1M7,
+ CHOMBWP2M0,
+ CHOMBWP2M1,
+ CHOMBWP2M2,
+ CHOMBWP2M3,
+ CHOMBWP2M4,
+ CHOMBWP2M5,
+ CHOMBWP2M6,
+ CHOMBWP2M7,
+ CHOMBWP3M0,
+ CHOMBWP3M1,
+ CHOMBWP3M2,
+ CHOMBWP3M3,
+ CHOMBWP3M4,
+ CHOMBWP3M5,
+ CHOMBWP3M6,
+ CHOMBWP3M7,
+ CHOMBWP4M0,
+ CHOMBWP4M1,
+ CHOMBWP4M2,
+ CHOMBWP4M3,
+ CHOMBWP4M4,
+ CHOMBWP4M5,
+ CHOMBWP4M6,
+ CHOMBWP4M7,
+ CHOMBWP5M0,
+ CHOMBWP5M1,
+ CHOMBWP5M2,
+ CHOMBWP5M3,
+ CHOMBWP5M4,
+ CHOMBWP5M5,
+ CHOMBWP5M6,
+ CHOMBWP5M7,
+ CHOMBWP6M0,
+ CHOMBWP6M1,
+ CHOMBWP6M2,
+ CHOMBWP6M3,
+ CHOMBWP6M4,
+ CHOMBWP6M5,
+ CHOMBWP6M6,
+ CHOMBWP6M7,
+ CHOMBWP7M0,
+ CHOMBWP7M1,
+ CHOMBWP7M2,
+ CHOMBWP7M3,
+ CHOMBWP7M4,
+ CHOMBWP7M5,
+ CHOMBWP7M6,
+ CHOMBWP7M7,
+
+ // The number of chom sensors reported
+ CHOM_NUM_OF_SENSORS
+};
+
+// Call home sensor Structure
+struct ChomSensor
+{
+ uint16_t sample; // last sample value during the polling period
+ uint16_t sampleMin; // min sample value recorded during polling period
+ uint16_t sampleMax; // max sample value recorded during polling period
+ uint16_t average; // average sample value during polling period
+ uint32_t accumulator; // accumulator register to computer the average
+} __attribute__ ((__packed__));
+
+typedef struct ChomSensor ChomSensor_t;
+
+// CPI data structure
+struct ChomCpiData
+{
+ uint8_t proc;
+ uint32_t cpi;
+}__attribute__ ((__packed__));
+
+typedef struct ChomCpiData ChomCpiData_t;
+
+// Power mode structure
+struct ChomPwrMode
+{
+ uint8_t mode; // OCC power mode
+ uint32_t numOfSamples; // Number of times samples were polled while in this mode
+}__attribute__ ((__packed__));
+
+typedef struct ChomPwrMode ChomPwrMode_t;
+
+// Call home data structure
+struct ChomNodeData
+{
+ uint32_t eyecatcher; // "CHOM" will mark the beginning of the data
+ uint8_t version; // version of call home data being reported
+ uint8_t curPwrMode; // the current power mode at the time of the polling event
+ uint32_t totalTime; // duration of the polling period
+ uint8_t modeInLog; // the number of different power mode in the polling period
+ ChomCpiData_t cpiData[MAX_OCCS]; // Chip Packing Interface data, 5 bytes per processor
+ uint16_t numSensors; // the number of sensors for which call home data was collected
+} __attribute__ ((__packed__));
+
+typedef struct ChomNodeData ChomNodeData_t;
+
+// Call home sensor data
+struct ChomSensorData
+{
+ ChomPwrMode_t pwrMode;
+ ChomSensor_t sensor[CHOM_NUM_OF_SENSORS];
+}__attribute__ ((__packed__));
+
+typedef struct ChomSensorData ChomSensorData_t;
+
+// Call home log data
+struct ChomLogData
+{
+ ChomNodeData_t nodeData; // general node data
+ ChomSensorData_t sensorData[2]; // sensors data (current and previous power mode)
+}__attribute__ ((__packed__));
+
+typedef struct ChomLogData ChomLogData_t;
+
+extern uint32_t g_chom_gen_periodic_log_timer;
+extern ChomLogData_t * g_chom;
+extern uint8_t g_chom_force;
+
+void chom_data_init();
+void chom_update_sensors();
+void chom_gen_periodic_log();
+void chom_data_reset();
+void chom_force_gen_log();
+void chom_main();
+
+#endif //_CHOM_H
diff --git a/src/occ_405/thread/test/Makefile b/src/occ_405/thread/test/Makefile
new file mode 100755
index 0000000..62863ba
--- /dev/null
+++ b/src/occ_405/thread/test/Makefile
@@ -0,0 +1,64 @@
+# IBM_PROLOG_BEGIN_TAG
+# This is an automatically generated prolog.
+#
+# $Source: src/occ_405/thread/test/Makefile $
+#
+# OpenPOWER OnChipController Project
+#
+# Contributors Listed Below - COPYRIGHT 2011,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
+
+threadtest_CFILES = \
+ ../../common.c \
+ ../../errl/errl.c \
+ ../threadSch.c \
+ threadtest.c
+
+all_cfiles = ${threadtest_CFILES}
+
+APP = threadtest
+APP_INCLUDES += -I../../../ssx
+APP_INCLUDES += -I../../../lib
+APP_INCLUDES += -I../../incl
+APP_INCLUDES += -I../../trac
+APP_INCLUDES += -I../../errl
+APP_INCLUDES += -I../../thread
+APP_INCLUDES += -I../../aplt/incl
+APP_INCLUDES += -I.
+
+
+
+#D = -DVERIFICATION=1 \
+ -DSSX_STACK_CHECK=0 \
+ -DINITIALIZE_PMC=0 \
+ -DINITIALIZE_SIMICS_IO=0 \
+ -DINITIALIZE_RTX_IO=1 \
+ -DINITIALIZE_PBA=1 \
+ -DSIMICS_MAGIC_PANIC=1 \
+ -DSSX_KERNEL_TRACE_ENABLE=1
+
+
+SOURCES = ${all_cfiles}
+MODE = validation
+
+PGP_ASYNC_SUPPORT = 1
+
+include ./app.mk
+
+pgas:
+ $(CC) $(CFLAGS) -c -Wa,-al -Wa,--listing-cont-lines='10'
diff --git a/src/occ_405/thread/test/app.mk b/src/occ_405/thread/test/app.mk
new file mode 100755
index 0000000..b5001d5
--- /dev/null
+++ b/src/occ_405/thread/test/app.mk
@@ -0,0 +1,79 @@
+# IBM_PROLOG_BEGIN_TAG
+# This is an automatically generated prolog.
+#
+# $Source: src/occ_405/thread/test/app.mk $
+#
+# OpenPOWER OnChipController Project
+#
+# Contributors Listed Below - COPYRIGHT 2011,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
+
+OCC = ../../
+SSX = ../../../ssx
+LIB = ../../../lib
+PGP = $(SSX)/pgp
+
+ifeq "$(MODE)" "firmware"
+SSX_TIMER_SUPPORT = 0
+SSX_THREAD_SUPPORT = 0
+endif
+
+export SSX_TIMER_SUPPORT
+export SSX_THREAD_SUPPORT
+export PPC405_MMU_SUPPORT
+export PGP_ASYNC_SUPPORT
+
+INCLUDES = -I $(OCC) -I$(LIB)
+
+include $(PGP)/ssx.mk
+
+C-OBJECTS = $(SOURCES:.c=.o)
+OBJECTS = $(C-OBJECTS:.S=.o)
+
+LDFLAGS = -L $(SSX)/ssx -L $(SSX)/ppc32 -L $(SSX)/ppc405 -L $(SSX)/pgp \
+ -L $(OCC) -L $(LIB) -lssx -lppc32
+
+DEFS += $(D)
+
+all: $(OBJECTS) libssx.a
+ $(MAKE) -C $(PGP) DEFS="$(DEFS)" -e
+ $(CPP) -P $(DEFS) < $(OCC)/linkocc.cmd > linkscript
+ $(LD) $(OBJECTS) \
+ -Tlinkscript $(LDFLAGS) -Map $(APP).map -Bstatic -o $(APP).out
+ $(OBJCOPY) -O binary $(APP).out $(APP).bin
+ $(OBJDUMP) -d $(APP).out > $(APP).dis
+
+libssx.a:
+ $(MAKE) -C $(LIB) DEFS="$(DEFS)" -e
+
+
+.PHONY : clean
+clean:
+ rm -f *.o *.d *.d.* *.out *.bin *.srec *.dis *.map linkscript
+ rm -f ./*/*.o ./*/*.d ./*/*.d.*
+
+.PHONY : clean_all
+clean_all:
+ $(MAKE) clean
+ $(MAKE) -C $(PGP) clean
+
+.PHONY : doc
+doc:
+ doxygen doc/Doxyfile
+
+-include $(OBJECTS:.o=.d)
diff --git a/src/occ_405/thread/test/threadtest.c b/src/occ_405/thread/test/threadtest.c
new file mode 100755
index 0000000..0aced6c
--- /dev/null
+++ b/src/occ_405/thread/test/threadtest.c
@@ -0,0 +1,317 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/occ_405/thread/test/threadtest.c $ */
+/* */
+/* OpenPOWER OnChipController Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2011,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 */
+
+#include "ssx.h"
+#include "ssx_io.h"
+#include "simics_stdio.h"
+#include <errl.h>
+#include <rand.h>
+#include <thread.h>
+#include <threadSch.h>
+#include <appletId.h>
+
+extern void __ssx_boot;
+
+IMAGE_HEADER (G_mainAppImageHdr,__ssx_boot,MAIN_APP_ID,OCC_APLT_TEST);
+
+// Period in which to run timer_routine
+#define TIMER_INTERVAL (SsxInterval) SSX_MICROSECONDS(5000)
+
+SsxSemaphore prcd_sem;
+
+int g_j = 0;
+int g_k = 0;
+/*----------------------------------------------------------------------------*/
+/* noncrtical/critical stack */
+/*----------------------------------------------------------------------------*/
+uint8_t noncritical_stack[NONCRITICAL_STACK_SIZE];
+uint8_t critical_stack[CRITICAL_STACK_SIZE];
+SimicsStdio simics_stdout;
+SimicsStdio simics_stderr;
+
+SsxTimer G_test_timer;
+
+extern void timer_routine(void *private);
+extern void rtloop_ocb_init(void);
+
+
+// Function Specification
+//
+// Name: pgp_validation_ssx_main_hook
+//
+// Description: TODO Add description
+//
+// End Function Specification
+void pgp_validation_ssx_main_hook(void)
+{
+
+}
+
+// Function Specification
+//
+// Name: Cmd_Hndl_thread_routine
+//
+// Description: TODO Add description
+//
+// End Function Specification
+//TODO placeholder
+void Cmd_Hndl_thread_routine(void *arg)
+{
+ do
+ {
+ int x=0;
+ for(x=0; x < 1000; x++)
+ {
+
+ }
+ }while(1);
+
+}
+
+// Function Specification
+//
+// Name: App_thread_routine
+//
+// Description: TODO Add description
+//
+// End Function Specification
+void App_thread_routine(void *arg)
+{
+ int z=0;
+ do
+ {
+ int x=0;
+ for(x=0; x < 10000; x++)
+ {
+ z++;
+ }
+ }while(1);
+
+}
+
+// Function Specification
+//
+// Name: Thermal_Monitor_thread_routine
+//
+// Description: TODO Add description
+//
+// End Function Specification
+void Thermal_Monitor_thread_routine(void *arg)
+{
+ int z=0;
+ do
+ {
+ int x=0;
+ for(x=0; x < 10000; x++)
+ {
+ z++;
+ }
+ }while(1);
+
+}
+
+// Function Specification
+//
+// Name: Hlth_Monitor_thread_routine
+//
+// Description: TODO Add description
+//
+// End Function Specification
+void Hlth_Monitor_thread_routine(void *arg)
+{
+ int z=0;
+ do
+ {
+ int x=0;
+ for(x=0; x < 10000; x++)
+ {
+ z++;
+ }
+ }while(1);
+
+}
+
+// Function Specification
+//
+// Name: FFDC_thread_routine
+//
+// Description: TODO Add description
+//
+// End Function Specification
+void FFDC_thread_routine(void *arg)
+{
+ int z=0;
+ do
+ {
+ int x=0;
+ for(x=0; x < 10000; x++)
+ {
+ z++;
+ }
+ }while(1);
+
+}
+
+// Function Specification
+//
+// Name: main_thread_routine
+//
+// Description: This thread currently just looks as the lowest priority thread,
+// handling the lowest priority tasks.
+//
+// End Function Specification
+void main_thread_routine(void *private)
+{
+ // Start the critical 250uS timer
+ ssx_timer_schedule(&timer, 1, TIMER_INTERVAL);
+
+ while(1)
+ {
+ // Only trace the first XX times that this function loops
+ if(g_k < 3)
+ {
+ g_k++;
+
+ // TRACE: Main Thread
+ }
+
+ // Sleep for 1000 before we run the loop again
+ ssx_sleep_absolute(1000);
+ }
+}
+
+// Function Specification
+//
+// Name: timer_routine
+//
+// Description: TODO Add description
+//
+// End Function Specification
+void timer_routine (void *arg)
+{
+
+}
+
+// Function Specification
+//
+// Name: dump_thread_info
+//
+// Description: TODO Add description
+//
+// End Function Specification
+void dump_thread_info(void *arg)
+{
+
+ printf("dumping thread info--------------------------\n");
+ int l_rc = 0;
+ SsxThreadState l_state = 0;
+ SsxThreadPriority l_pri = 0;
+ int l_runnable=0;
+ int x=0;
+ for(x=0; x < THREADS_TO_SCHEDULE; x++)
+ {
+ l_rc = ssx_thread_info_get(G_scheduledThreads[x],
+ &l_state,
+ &l_pri,
+ &l_runnable);
+
+ printf("Thread %p: State %x priority %x runnable %x rc %x Global index %x\n",G_scheduledThreads[x],
+ l_state,
+ l_pri,
+ l_runnable,
+ l_rc,
+ G_threadSchedulerIndex);
+
+ }
+
+}
+
+// Function Specification
+//
+// Name: main
+//
+// Description: Initializes the trace buffer, along with creating threads and timers
+// for execution. Note that once main runs with ssx_start_threads, we
+// never return as the SSX kernel takes over.
+//
+// End Function Specification
+int main(int argc, char **argv)
+{
+ // Locals
+ errlHndl_t l_errl = INVALID_ERR_HNDL;
+
+ // Initialize Trace Buffers immediately, so they can be used
+ // from this point on.
+
+ // Initialize stdout so we can do printf from within simics env
+ simics_stdout_create(&simics_stdout);
+ simics_stderr_create(&simics_stderr);
+ stdout = (FILE *)(&simics_stdout);
+ stderr = (FILE *)(&simics_stderr);
+
+ // Initialize SSX Stacks (note that this also reinitializes the time base to 0)
+ ssx_initialize((SsxAddress)noncritical_stack, NONCRITICAL_STACK_SIZE,
+ (SsxAddress)critical_stack, CRITICAL_STACK_SIZE, 0);
+
+ // Create Global Semaphores
+ ssx_semaphore_create(&prcd_sem, 0, 13);
+
+ ssx_timer_create(&timer, timer_routine, 0);
+
+ // Create thread with already mapped priority
+ // Create Threads
+ ssx_thread_create(&main_thread,
+ main_thread_routine,
+ (void *)0,
+ (SsxAddress)main_thread_stack,
+ THREAD_STACK_SIZE,
+ 0);
+
+ // Make Threads runnable
+ ssx_thread_resume(&main_thread);
+
+ //Initialize the thread scheduler
+ l_errl = initThreadScheduler();
+
+ if(l_errl)
+ {
+ // TODO Trace the error
+
+ // Commit log
+ // NOTE: log should be deleted by reader mechanism
+ commitErrl( &l_errl );
+ }
+
+ // Kick off timer
+ ssx_timer_create(&G_test_timer, dump_thread_info, 0);
+ ssx_timer_schedule(&G_test_timer, 1, 500000000);
+
+
+ // Enter SSX Kernel
+ ssx_start_threads();
+
+ return 0;
+}
+
diff --git a/src/occ_405/thread/thread.h b/src/occ_405/thread/thread.h
new file mode 100755
index 0000000..3106a7c
--- /dev/null
+++ b/src/occ_405/thread/thread.h
@@ -0,0 +1,88 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/occ_405/thread/thread.h $ */
+/* */
+/* OpenPOWER OnChipController Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2011,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 _THREAD_H
+#define _THREAD_H
+
+#include <occ_common.h>
+#include "ssx.h"
+
+// Thread priorities for Thread creation.
+typedef enum
+{
+ THREAD_PRIORITY_0, // Reserved for high priority
+ THREAD_PRIORITY_1, // Reserved for high priority
+ THREAD_PRIORITY_2,
+ THREAD_PRIORITY_3,
+ THREAD_PRIORITY_4,
+ THREAD_PRIORITY_5,
+ THREAD_PRIORITY_6,
+ THREAD_PRIORITY_7,
+ THREAD_PRIORITY_8,
+}THREAD_PRIORITY;
+
+// NOTE: Stack sizes are defined by entity
+// - Non-Critical Stack used by non-critical interrupt handlers, including timer callbacks
+// - Critical Stack used for critical interrupts
+// - Stacks for each thread
+#define NONCRITICAL_STACK_SIZE 8192 // 8kB
+#define CRITICAL_STACK_SIZE 4096 // 4kB
+#define THREAD_STACK_SIZE 4096 // 4kB
+
+extern uint8_t main_thread_stack[THREAD_STACK_SIZE];
+extern uint8_t Cmd_hndl_thread_stack[THREAD_STACK_SIZE];
+extern uint8_t App_thread_stack[THREAD_STACK_SIZE];
+extern uint8_t testAppletThreadStack[THREAD_STACK_SIZE];
+
+/*----------------------------------------------------------*/
+/* SsxThread Declaration */
+/*----------------------------------------------------------*/
+
+// Our idle thread. See main_thread_routine
+extern SsxThread Main_thread;
+
+// Command handler thread
+extern SsxThread Cmd_Hndl_thread;
+
+// Application manager thread
+extern SsxThread App_thread;
+
+// Test applet thread
+extern SsxThread TestAppletThread;
+
+// Application manager thread
+extern SsxThread Dcom_thread;
+
+void Main_thread_routine(void *private);
+
+void Cmd_Hndl_thread_routine(void *arg);
+
+void App_thread_routine(void *arg);
+
+void Dcom_thread_routine(void *arg);
+
+void testAppletThreadRoutine(void *arg);
+
+#endif //_THREAD_H
diff --git a/src/occ_405/thread/threadSch.c b/src/occ_405/thread/threadSch.c
new file mode 100755
index 0000000..cfb996e
--- /dev/null
+++ b/src/occ_405/thread/threadSch.c
@@ -0,0 +1,322 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/occ_405/thread/threadSch.c $ */
+/* */
+/* OpenPOWER OnChipController Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2011,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 */
+
+#include <occ_common.h>
+#include <threadSch.h>
+#include "ssx.h"
+#include "thread_service_codes.h"
+#include "occ_service_codes.h"
+#include <appletManager.h>
+#include <trac.h>
+#include <state.h>
+#include "cmdh_snapshot.h"
+
+// Numbers of threads to schedule
+#define THREADS_TO_SCHEDULE (sizeof(G_scheduledThreads)/sizeof(SsxThread*))
+
+#define THREAD_TIME_SLICE (SsxInterval) SSX_MILLISECONDS(10) // 10ms
+
+// Thread Timer to reprioritize the threads
+SsxTimer G_threadSchTimer;
+
+// Index of highest priority thread in G_scheduledThreads
+uint16_t G_threadSchedulerIndex = 0;
+
+// Array that holds the threads that need scheduling
+SsxThread* G_scheduledThreads[] =
+{
+ &Main_thread,
+ &Cmd_Hndl_thread,
+ &App_thread,
+ &TestAppletThread,
+ &Dcom_thread,
+};
+
+// Error log counter for the callback so that only 1 error log is created
+uint8_t G_threadSwapErrlCounter = 0;
+
+// Global for the parameter to the applet thread routine
+OCC_APLT_TYPE G_apltPdtType = APLT_TYPE_PRODUCT;
+OCC_APLT_TYPE G_apltTestType = APLT_TYPE_TEST;
+
+//Thread Stacks
+uint8_t main_thread_stack[THREAD_STACK_SIZE];
+uint8_t Cmd_hndl_thread_stack[THREAD_STACK_SIZE];
+uint8_t App_thread_stack[THREAD_STACK_SIZE];
+uint8_t testAppletThreadStack[THREAD_STACK_SIZE];
+uint8_t dcomThreadStack[THREAD_STACK_SIZE];
+
+// Our idle thread. See main_thread_routine
+SsxThread Main_thread;
+
+// Command handler thread
+SsxThread Cmd_Hndl_thread;
+
+// Application manager thread
+SsxThread App_thread;
+
+// Test applet thread
+SsxThread TestAppletThread;
+
+// Dcom thread
+SsxThread Dcom_thread;
+
+// Function Specification
+//
+// Name: createAndResumeThreadHelper
+//
+// Description: create and resume thread helper
+//
+// End Function Specification
+int createAndResumeThreadHelper(SsxThread *io_thread,
+ SsxThreadRoutine i_thread_routine,
+ void *io_arg,
+ SsxAddress i_stack,
+ size_t i_stack_size,
+ THREAD_PRIORITY i_priority)
+{
+
+ // Locals
+ int l_rc = SSX_OK;
+
+ // Thread creation
+ l_rc = ssx_thread_create(io_thread,
+ i_thread_routine,
+ io_arg,
+ i_stack,
+ i_stack_size,
+ (SsxThreadPriority)i_priority);
+
+ //check for errors creating a thread
+ if(l_rc != SSX_OK)
+ {
+ TRAC_ERR("Failure creating thread. rc: 0x%x", -l_rc);
+ }
+ else
+ {
+ //resume thread once created
+ l_rc = ssx_thread_resume(io_thread);
+ }
+
+
+ return l_rc;
+}
+
+// Function Specification
+//
+// Name: initThreadScheduler
+//
+// Description: Init the threads in the scheduler and start the
+// timer.
+//
+// End Function Specification
+void initThreadScheduler(void)
+{
+ // Locals
+ int l_appThreadRc = SSX_OK;
+ int l_cmdThreadRc = SSX_OK;
+ int l_timerRc = SSX_OK;
+ int l_testAppletThreadRc = SSX_OK;
+ int l_dcomThreadRc = SSX_OK;
+ int l_snapshotTimerRc = SSX_OK;
+
+ // Creating threads that need to be scheduled
+ // Thread priority range should match scheduled
+ // threads in G_scheduledThreads ie highest priority thread should be
+ // index 0 of G_scheduledThreads
+
+ l_cmdThreadRc = createAndResumeThreadHelper(&Cmd_Hndl_thread,
+ Cmd_Hndl_thread_routine,
+ (void *)0,
+ (SsxAddress)Cmd_hndl_thread_stack,
+ THREAD_STACK_SIZE,
+ THREAD_PRIORITY_3);
+
+ l_appThreadRc = createAndResumeThreadHelper(&App_thread,
+ App_thread_routine,
+ (void *)&G_apltPdtType,
+ (SsxAddress)App_thread_stack,
+ THREAD_STACK_SIZE,
+ THREAD_PRIORITY_4);
+
+ l_testAppletThreadRc = createAndResumeThreadHelper(&TestAppletThread,
+ App_thread_routine,
+ (void *)&G_apltTestType,
+ (SsxAddress)testAppletThreadStack,
+ THREAD_STACK_SIZE,
+ THREAD_PRIORITY_5);
+
+ l_dcomThreadRc = createAndResumeThreadHelper(&Dcom_thread,
+ Dcom_thread_routine,
+ (void *)0,
+ (SsxAddress)dcomThreadStack,
+ THREAD_STACK_SIZE,
+ THREAD_PRIORITY_6);
+
+ // Create the thread scheduler timer
+ l_timerRc = ssx_timer_create(&G_threadSchTimer, threadSwapcallback, 0);
+
+ // Check for errors creating the timer
+ if(l_timerRc == SSX_OK)
+ {
+ TRAC_INFO("timer created and scheduled");
+ //schedule the timer so that it runs every THREAD_TIME_SLICE
+ l_timerRc = ssx_timer_schedule(&G_threadSchTimer, 1, THREAD_TIME_SLICE);
+ }
+ else
+ {
+ TRAC_INFO("Error creating timer: RC: %d", l_timerRc);
+ }
+
+ // Create snapshot timer
+ l_snapshotTimerRc = ssx_timer_create(&G_snapshotTimer, cmdh_snapshot_callback, 0);
+
+ // Check for errors creating the timer
+ if(l_snapshotTimerRc == SSX_OK)
+ {
+ // Schedule the timer so that it runs every 30 seconds.
+ l_snapshotTimerRc = ssx_timer_schedule(&G_snapshotTimer, 0, SSX_SECONDS(30));
+ if (l_snapshotTimerRc != SSX_OK)
+ {
+ TRAC_ERR("cmdh_snapshot_sync: reseting the snapshot timer failed.");
+ }
+ }
+ else
+ {
+ TRAC_INFO("Error creating timer: RC: %d", l_snapshotTimerRc);
+ }
+
+ // If there are any errors creating the threads or starting the
+ // timer create an error log to pass back.
+ if( l_appThreadRc
+ || l_testAppletThreadRc
+ || l_cmdThreadRc
+ || l_dcomThreadRc
+ || l_timerRc
+ || l_snapshotTimerRc )
+ {
+ TRAC_ERR("Error creating thread: l_appThreadRc: %d, "
+ "l_testAppletThreadRc: %d, l_cmdThreadRc: %d, "
+ "l_dcomThreadRc: %d", l_appThreadRc,l_testAppletThreadRc,
+ l_timerRc,l_cmdThreadRc,l_dcomThreadRc);
+ TRAC_ERR("Error starting timers: timerRc: %d, snapshotTimerRc: %d.",
+ l_timerRc, l_snapshotTimerRc);
+ // Create error log and log it
+ // TODO use correct trace
+ tracDesc_t l_trace = NULL;
+
+ /* @
+ * @errortype
+ * @moduleid THRD_MID_INIT_THREAD_SCHDLR
+ * @reasoncode SSX_GENERIC_FAILURE
+ * @userdata1 Schedule timer return code
+ * @userdata2 Snapshot timer return code
+ * @userdata4 OCC_NO_EXTENDED_RC
+ * @devdesc SSX thread related failure
+ */
+ errlHndl_t l_rc = createErrl(THRD_MID_INIT_THREAD_SCHDLR, // ModId
+ SSX_GENERIC_FAILURE, // Reasoncode
+ OCC_NO_EXTENDED_RC, // Extended reasoncode
+ ERRL_SEV_UNRECOVERABLE, // Severity
+ l_trace, // Trace Buf
+ DEFAULT_TRACE_SIZE, // Trace Size
+ l_timerRc, // Userdata1
+ l_snapshotTimerRc); // Userdata2
+
+ REQUEST_RESET(l_rc);
+ }
+}
+
+
+// Function Specification
+//
+// Name: threadSwapcallback
+//
+// Description: a periodic timer callback to swap prorities of scheduled threads
+//
+// End Function Specification
+void threadSwapcallback(void * arg)
+{
+ // Locals
+ int l_rc = SSX_OK;
+
+ // Current location of index in scheduled thread array
+ int l_threadAIndex = G_threadSchedulerIndex;
+
+ // If global index == last item swap priorities with 1st
+ int l_threadBIndex = (G_threadSchedulerIndex == (THREADS_TO_SCHEDULE-1)) ? 0 : ++G_threadSchedulerIndex;
+
+ // Swap priorities with global index +1
+ l_rc = ssx_thread_priority_swap(G_scheduledThreads[l_threadAIndex],G_scheduledThreads[l_threadBIndex]);
+
+ if(l_rc != SSX_OK)
+ {
+ // TODO trace error
+
+ // Create and commit error log
+ if(G_threadSwapErrlCounter == 0)
+ {
+ // TODO use correct trace
+ tracDesc_t l_trace = NULL;
+
+ /*
+ * @errortype
+ * @moduleid THRD_MID_THREAD_SWAP_CALLBACK
+ * @reasoncode SSX_GENERIC_FAILURE
+ * @userdata1 Return code of thread priority swap
+ * @userdata2 Current location of index in scheduled thread array
+ * @userdata4 OCC_NO_EXTENDED_RC
+ * @devdesc SSX thread related failure
+ */
+ errlHndl_t l_err = createErrl(
+ THRD_MID_THREAD_SWAP_CALLBACK, // ModId
+ SSX_GENERIC_FAILURE, // Reasoncode
+ OCC_NO_EXTENDED_RC, // Extended reasoncode
+ ERRL_SEV_PREDICTIVE, // Severity
+ l_trace, // Trace Buf
+ DEFAULT_TRACE_SIZE, // Trace Size
+ l_rc, // Userdata1
+ l_threadAIndex // Userdata2
+ );
+
+ // Commit log
+ // NOTE: Log should be deleted by reader mechanism
+ commitErrl( &l_err );
+
+ // Increment errl counter
+ G_threadSwapErrlCounter++;
+
+ }// End thread swap counter if
+ }
+ else
+ {
+ // Reset counter since it started working again
+ G_threadSwapErrlCounter = 0;
+
+ // Set the global to the new location of the highest priority thread
+ G_threadSchedulerIndex = l_threadBIndex;
+ }
+}
+
diff --git a/src/occ_405/thread/threadSch.h b/src/occ_405/thread/threadSch.h
new file mode 100755
index 0000000..124d460
--- /dev/null
+++ b/src/occ_405/thread/threadSch.h
@@ -0,0 +1,49 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/occ_405/thread/threadSch.h $ */
+/* */
+/* OpenPOWER OnChipController Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2011,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 _THREADSCH_H
+#define _THREADSCH_H
+
+#include <occ_common.h>
+#include <thread.h>
+#include "ssx.h"
+#include <errl.h>
+
+// Function to reprioritize the threads in the array
+void threadSwapcallback(void * arg);
+
+// Function to initilize the threads and the thread schedule timer
+void initThreadScheduler(void) INIT_SECTION;
+
+// Function to create and resume thread. Externalizing as it is used to
+// create main thread
+int createAndResumeThreadHelper(SsxThread *io_thread,
+ SsxThreadRoutine i_thread_routine,
+ void *io_arg,
+ SsxAddress i_stack,
+ size_t i_stack_size,
+ THREAD_PRIORITY i_priority);
+
+#endif //_THREADSCH_H
diff --git a/src/occ_405/thread/thread_service_codes.h b/src/occ_405/thread/thread_service_codes.h
new file mode 100755
index 0000000..6d13baa
--- /dev/null
+++ b/src/occ_405/thread/thread_service_codes.h
@@ -0,0 +1,48 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/occ_405/thread/thread_service_codes.h $ */
+/* */
+/* OpenPOWER OnChipController Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2011,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 */
+
+// NOTE: The thread component will not actually generate errors
+// using the thread component. This is due to the fact that will
+// use trace so therefore we can induce non-ending recursion if trace
+// were to use ERRL.
+
+// A trace failure is not a system critical failure which is why we
+// can get away with it not reporting errors.
+
+#ifndef _THREAD_SERVICE_CODES_H_
+#define _THREAD_SERVICE_CODES_H_
+
+#include <comp_ids.h>
+
+enum thrdModuleId
+{
+ THRD_MID_INIT_THREAD_SCHDLR = THRD_COMP_ID | 0x00,
+ THRD_MID_THREAD_SWAP_CALLBACK = THRD_COMP_ID | 0x01,
+ THRD_MID_GEN_CALLHOME_LOG = THRD_COMP_ID | 0x02,
+ THRD_THERMAL_VRM_FAN_CONTROL = THRD_COMP_ID | 0x03,
+ THRD_THERMAL_MAIN = THRD_COMP_ID | 0x04,
+};
+
+#endif /* #ifndef _THREAD_SERVICE_CODES_H_ */
diff --git a/src/occ_405/thread/thrm_thread.c b/src/occ_405/thread/thrm_thread.c
new file mode 100755
index 0000000..13d9423
--- /dev/null
+++ b/src/occ_405/thread/thrm_thread.c
@@ -0,0 +1,459 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/occ_405/thread/thrm_thread.c $ */
+/* */
+/* OpenPOWER OnChipController Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2011,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 */
+
+#include <cmdh_fsp_cmds_datacnfg.h>
+#include <thrm_thread.h>
+#include <trac.h>
+#include <state.h>
+#include <occ_service_codes.h>
+#include <thread_service_codes.h>
+#include <occ_sys_config.h>
+
+// Global for notifying the thermal thread if it needs to update its copy
+// of the thermal threshold data packet (format 0x13)
+BOOLEAN G_thrm_parms_need_update = FALSE;
+
+// Fan control loop time in seconds sent by TMGT (format 0x13)
+uint8_t G_thrm_loop_time = 0;
+
+// Cooling request status (0=no request; 1=send request)
+uint8_t G_thrm_cooling_request = 0;
+
+// Local copy of thermal thresholds sent by TMGT (format 0x13)
+thrm_fru_control_t G_thrm_fru_control[DATA_FRU_MAX];
+
+// Global array to store dynamic information for each FRU
+thrm_fru_data_t G_thrm_fru_data[DATA_FRU_MAX];
+
+// Function Specification
+//
+// Name: THRM_thread_update_thresholds
+//
+// Description: Notify thermal thread to update its local copy of the
+// thermal threshold data packet.
+//
+// End Function Specification
+void THRM_thread_update_thresholds()
+{
+ G_thrm_parms_need_update = TRUE;
+}
+
+// Function Specification
+//
+// Name: THRM_thread_get_cooling_request
+//
+// Description: Get the status of the cooling request from the thermal
+// thread.
+//
+// End Function Specification
+uint8_t THRM_thread_get_cooling_request()
+{
+ return G_thrm_cooling_request;
+}
+
+// Function Specification
+//
+// Name: thrm_thread_load_thresholds
+//
+// Description: Read thermal thresholds sent by TMGT (data format 0x13)
+// and store them for thermal thread consumption.
+//
+// End Function Specification
+errlHndl_t thrm_thread_load_thresholds()
+{
+ errlHndl_t l_err = NULL;
+ cmdh_thrm_thresholds_t *l_data = NULL;
+ uint8_t i = 0;
+
+ do
+ {
+ // Get thermal threshold data sent by TMGT
+ l_err = DATA_get_thrm_thresholds(&l_data);
+ if(l_err)
+ {
+ TRAC_ERR("thrm_thread_load_thresholds: Thermal control thresholds not available!");
+
+ // This is a critical failure since we can't run the fan control
+ // without the thermal thresholds. Make the fan control loop time
+ // zero so that we don't execute any fan control
+ G_thrm_loop_time = 0;
+ break;
+ }
+
+ // Load fan control loop time
+ G_thrm_loop_time = l_data->fan_control_loop_time;
+
+ TRAC_INFO("thrm_thread_load_thresholds: Fan Control loop time[%u]",
+ G_thrm_loop_time);
+
+ // Load FRU data
+ for (i=0; i<DATA_FRU_MAX; i++)
+ {
+ // Load data that is not dependant on the system mode
+ G_thrm_fru_control[i].warning = l_data->data[i].warning;
+ G_thrm_fru_control[i].warning_reset = l_data->data[i].warning_reset;
+ G_thrm_fru_control[i].t_inc_zone[0] = l_data->data[i].t_inc_zone1;
+ G_thrm_fru_control[i].t_inc_zone[1] = l_data->data[i].t_inc_zone2;
+ G_thrm_fru_control[i].t_inc_zone[2] = l_data->data[i].t_inc_zone3;
+ G_thrm_fru_control[i].t_inc_zone[3] = l_data->data[i].t_inc_zone4;
+ G_thrm_fru_control[i].t_inc_zone[4] = l_data->data[i].t_inc_zone5;
+ G_thrm_fru_control[i].t_inc_zone[5] = l_data->data[i].t_inc_zone6;
+ G_thrm_fru_control[i].t_inc_zone[6] = l_data->data[i].t_inc_zone7;
+ G_thrm_fru_control[i].t_inc_zone[7] = l_data->data[i].t_inc_zone8;
+
+ // Load data that depends on the system mode
+ // Acoustic mode takes priority
+ if (0) // TODO: Need to implement acoustic mode
+ {
+ G_thrm_fru_control[i].t_control = l_data->data[i].acoustic_t_control;
+ G_thrm_fru_control[i].error = l_data->data[i].acoustic_error;
+ }
+ // ...then nominal mode
+ else if (CURRENT_MODE() == OCC_MODE_NOMINAL)
+ {
+ G_thrm_fru_control[i].t_control = l_data->data[i].t_control;
+ G_thrm_fru_control[i].error = l_data->data[i].error;
+ }
+ // ...then any other power management mode
+ else
+ {
+ G_thrm_fru_control[i].t_control = l_data->data[i].pm_t_control;
+ G_thrm_fru_control[i].error = l_data->data[i].pm_error;
+ }
+
+ TRAC_INFO("thrm_thread_load_thresholds: Using t_control[%u] error[%u] for FRU[0x%02X]",
+ G_thrm_fru_control[i].t_control,
+ G_thrm_fru_control[i].error,
+ i);
+ }
+ }while(0);
+
+ return(l_err);
+
+}
+
+
+// Function Specification
+//
+// Name: thrm_thread_fan_control
+//
+// Description: Execute the fan control algorithm for the specified FRU.
+// Returns TRUE or FALSE depending whether we need to increase fan speeds
+// or not.
+//
+// End Function Specification
+BOOLEAN thrm_thread_fan_control(const uint8_t i_fru_type,
+ const uint16_t i_fru_temperature)
+{
+ eConfigDataFruType k = i_fru_type;
+ BOOLEAN l_IncreaseFans = FALSE;
+ uint8_t i = 0;
+ uint16_t l_delta_temp = 0;
+
+ //If there's a read error, assume temperature is t_control + 1
+ if(G_thrm_fru_data[k].read_failure)
+ {
+ G_thrm_fru_data[k].Tcurrent = G_thrm_fru_control[k].t_control + 1;
+ }
+ else
+ {
+ // Collect the current FRU temperature
+ G_thrm_fru_data[k].Tcurrent = i_fru_temperature;
+ }
+
+ // Is the current FRU temperature bigger than the FRU T_control?
+ if (G_thrm_fru_data[k].Tcurrent > G_thrm_fru_control[k].t_control)
+ {
+ // Is the current temperature below the previous temperature?
+ if (G_thrm_fru_data[k].Tcurrent < G_thrm_fru_data[k].Tprevious)
+ {
+ // Temperature is decreasing so we don't need to request any
+ // additional cooling
+ G_thrm_fru_data[k].temp_increasing = FALSE;
+ }
+ else if (G_thrm_fru_data[k].Tcurrent > G_thrm_fru_data[k].Tprevious)
+ {
+ // Temperature is increasing and we need to request more cooling
+ G_thrm_fru_data[k].temp_increasing = TRUE;
+ l_IncreaseFans = TRUE;
+ }
+ else
+ {
+ // Temperature is the same as previous iteration. Check the trend
+ // to see whether is increasing or decreasing
+ if (G_thrm_fru_data[k].temp_increasing == TRUE)
+ {
+ // Need to request additional cooling
+ l_IncreaseFans = TRUE;
+ }
+ else
+ {
+ // No need to request additional cooling
+ }
+ }
+ }
+
+ // Prepare the cooling requests for all Zones
+ l_delta_temp = G_thrm_fru_data[k].Tcurrent - G_thrm_fru_control[k].t_control;
+
+ if (l_IncreaseFans == TRUE)
+ {
+ for (i = 0; i < THRM_MAX_NUM_ZONES; i++)
+ {
+ G_thrm_fru_data[k].FanIncZone[i] = l_delta_temp *
+ G_thrm_fru_control[k].t_inc_zone[i];
+ }
+ }
+ else
+ {
+ for (i = 0; i < THRM_MAX_NUM_ZONES; i++)
+ {
+ G_thrm_fru_data[k].FanIncZone[i] = 0;
+ }
+ }
+
+ // Store the current temperature for next iteration
+ G_thrm_fru_data[k].Tprevious = G_thrm_fru_data[k].Tcurrent;
+
+ return(l_IncreaseFans);
+}
+
+
+// Function Specification
+//
+// Name: thrm_thread_vrm_fan_control
+//
+// Description: Execute the fan control algorithm for VRM based on the
+// VR_FAN signal. Returns TRUE or FALSE depending whether we need to increase
+// fan speeds or not.
+//
+// End Function Specification
+BOOLEAN thrm_thread_vrm_fan_control(const uint16_t i_vrfan)
+{
+ BOOLEAN l_IncreaseFans = FALSE;
+ static BOOLEAN L_error_logged = FALSE;
+ uint8_t i = 0;
+ errlHndl_t l_err = NULL;
+
+ if ((i_vrfan == 1) || (G_thrm_fru_data[DATA_FRU_VRM].read_failure == 1))
+ {
+ // If VR_FAN has been asserted or we cannot read it, request one T_INC
+ // for each zone to be controlled
+ l_IncreaseFans = TRUE;
+
+ for (i = 0; i < THRM_MAX_NUM_ZONES; i++)
+ {
+ G_thrm_fru_data[DATA_FRU_VRM].FanIncZone[i] =
+ G_thrm_fru_control[DATA_FRU_VRM].t_inc_zone[i];
+ }
+
+ // Log an informational error the first time VR_FAN was asserted (this
+ // is for manufacturing mode IPLs)
+ if (i_vrfan == 1)
+ {
+ if (!L_error_logged)
+ {
+ L_error_logged = TRUE;
+
+ TRAC_ERR("thrm_thread_vrm_fan_control: VR_FAN for this regulator has been asserted!");
+
+ /* @
+ * @errortype
+ * @moduleid THRD_THERMAL_VRM_FAN_CONTROL
+ * @reasoncode VRM_VRFAN_ASSERTED
+ * @userdata1 state of VR_FAN signal
+ * @userdata2 0
+ * @userdata4 OCC_NO_EXTENDED_RC
+ * @devdesc VR_FAN signal from regulator has been asserted.
+ *
+ */
+ l_err = createErrl(THRD_THERMAL_VRM_FAN_CONTROL, //modId
+ VRM_VRFAN_ASSERTED, //reasoncode
+ OCC_NO_EXTENDED_RC, //Extended reason code
+ ERRL_SEV_INFORMATIONAL, //Severity
+ NULL, //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ i_vrfan, //userdata1
+ 0); //userdata2
+
+ // Set the manufacturing error flag in the log
+ setErrlActions(l_err, ERRL_ACTIONS_MANUFACTURING_ERROR);
+
+ // Commit the error
+ commitErrl(&l_err);
+ }
+ }
+ }
+ else
+ {
+ // If VR_FAN is de-asserted, don't send any cooling requests
+ l_IncreaseFans = FALSE;
+
+ for (i = 0; i < THRM_MAX_NUM_ZONES; i++)
+ {
+ G_thrm_fru_data[DATA_FRU_VRM].FanIncZone[i] = 0;
+ }
+ }
+
+ return(l_IncreaseFans);
+}
+
+// Function Specification
+//
+// Name: thrm_thread_main
+//
+// Description: Main thermal thread routine
+//
+// End Function Specification
+void thrm_thread_main()
+{
+ errlHndl_t l_err = NULL;
+ BOOLEAN l_IncreaseFans = FALSE;
+ sensor_t *l_sensor = NULL;
+ static uint8_t L_counter = 0;
+ static BOOLEAN L_full_speed_log = FALSE;
+
+ // Execute fan control loop if OCC is in observation state or active state
+ // AND if we have received the thermal threshold data packet
+ if (((CURRENT_STATE() == OCC_STATE_OBSERVATION) ||
+ (CURRENT_STATE() == OCC_STATE_ACTIVE)) &&
+ (DATA_get_present_cnfgdata() & DATA_MASK_THRM_THRESHOLDS))
+ {
+ // Check if we need to update our local copy of the thermal threshold
+ // data packet
+ if (G_thrm_parms_need_update)
+ {
+ // Clear this flag now that we are going to update our local copy
+ G_thrm_parms_need_update = FALSE;
+
+ // Update our local copy of the thermal thresholds
+ l_err = thrm_thread_load_thresholds();
+
+ if (l_err)
+ {
+ // Commit error log for failing to load thermal thresholds
+ commitErrl(&l_err);
+ }
+ else
+ {
+ // Clear our counter that determines when to run the fan
+ // control loop
+ L_counter = 0;
+ }
+ }
+
+ // Increment our counter and make sure it doesn't wrap
+ L_counter++;
+ // The fan control loop time is only 1-byte long. A loop time of 0
+ // indicates that we shouldn't run the fan control loop.
+ if (L_counter == 0)
+ {
+ L_counter = 0xFF;
+ }
+
+ // Is it time to execute the fan control loop?
+ if (L_counter == G_thrm_loop_time)
+ {
+ // Reset our counter
+ L_counter = 0;
+
+ // Determine if additional cooling is required for VRMs
+ l_sensor = getSensorByGsid(VRFAN250USPROC);
+ l_IncreaseFans |= thrm_thread_vrm_fan_control(l_sensor->sample);
+
+ // Determine if additional cooling is required for processors
+ // For processors, use the hottest of the core averages
+ l_sensor = getSensorByGsid(TEMP2MSP0PEAK);
+ l_IncreaseFans |= thrm_thread_fan_control(DATA_FRU_PROC,
+ l_sensor->sample);
+
+ // Determine if additional cooling is required for centaurs
+ l_sensor = getSensorByGsid(TEMP2MSCENT);
+ l_IncreaseFans |= thrm_thread_fan_control(DATA_FRU_CENTAUR,
+ l_sensor->sample);
+
+ // Determine if additional cooling is required for dimms
+ l_sensor = getSensorByGsid(TEMP2MSDIMM);
+ l_IncreaseFans |= thrm_thread_fan_control(DATA_FRU_DIMM,
+ l_sensor->sample);
+
+ // Do we need to request a fan increase?
+ if (l_IncreaseFans == TRUE)
+ {
+ // Set 'Cooling Request' for the poll response
+ G_thrm_cooling_request = 1;
+
+ // Send 'Service' attention to FSP to force TMGT to send poll
+ // command
+ cmdh_fsp_attention(OCC_ALERT_FSP_SERVICE_REQD);
+
+ // Check if fans are currently already at max (known from APSS)
+ // log informational B1812A08 and have the "Manufacturing error"
+ // bit in the actions field set so that TMGT will flag this in manufacturing.
+ // ** No longer reading gpio from APSS in GA1 due to instability in APSS composite mode
+ uint8_t l_full_speed = 1; // low active
+ // TODO: Should we continue to not read gpio from APSS?
+ if( (L_full_speed_log == FALSE) &&
+ FALSE) //apss_gpio_get(l_full_speed_pin,&l_full_speed) )
+ {
+ if(l_full_speed == 0) //low active
+ {
+ L_full_speed_log = TRUE; // log this error ONLY ONCE per IPL
+ TRAC_ERR("thrm_thread_main: Request a fan increase and fan is already in full speed");
+
+ /* @
+ * @errortype
+ * @moduleid THRD_THERMAL_MAIN
+ * @reasoncode FAN_FULL_SPEED
+ * @userdata1 0
+ * @userdata2 0
+ * @userdata4 OCC_NO_EXTENDED_RC
+ * @devdesc Request a fan increase and fan is already in full speed
+ *
+ */
+ l_err = createErrl(THRD_THERMAL_MAIN, //modId
+ FAN_FULL_SPEED, //reasoncode
+ OCC_NO_EXTENDED_RC, //Extended reason code
+ ERRL_SEV_INFORMATIONAL, //Severity
+ NULL, //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ 0, //userdata1
+ 0); //userdata2
+
+ // Set the manufacturing error flag in the log
+ setErrlActions(l_err, ERRL_ACTIONS_MANUFACTURING_ERROR);
+ commitErrl(&l_err);
+ }
+ }
+ //
+ }
+ else
+ {
+ // Reset the 'Cooling Request' since we don't need a fan increase
+ G_thrm_cooling_request = 0;
+ }
+ }
+ }
+}
diff --git a/src/occ_405/thread/thrm_thread.h b/src/occ_405/thread/thrm_thread.h
new file mode 100755
index 0000000..21a8b8e
--- /dev/null
+++ b/src/occ_405/thread/thrm_thread.h
@@ -0,0 +1,62 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/occ_405/thread/thrm_thread.h $ */
+/* */
+/* OpenPOWER OnChipController Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2011,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 THRM_THREAD_H
+#define THRM_THREAD_H
+
+#define THRM_MAX_NUM_ZONES 8
+
+typedef struct thrm_fru_control
+{
+ uint8_t t_control;
+ uint8_t error;
+ uint8_t warning;
+ uint8_t warning_reset;
+ uint16_t t_inc_zone[THRM_MAX_NUM_ZONES];
+}thrm_fru_control_t;
+
+typedef struct thrm_fru_data
+{
+ // Flag to indicate that we have timed out trying to read this thermal sensor
+ uint8_t read_failure;
+ // Current temperature of this FRU
+ uint16_t Tcurrent;
+ // Previous temperature of this FRU
+ uint16_t Tprevious;
+ // Coooling requests to be sent back to TMGT
+ uint16_t FanIncZone[THRM_MAX_NUM_ZONES];
+ // Flag to indicate if the temperature for this FRU is increasing or not
+ BOOLEAN temp_increasing;
+}thrm_fru_data_t;
+
+errlHndl_t thrm_thread_load_thresholds();
+void THRM_thread_update_thresholds();
+uint8_t THRM_thread_get_cooling_request();
+BOOLEAN thrm_thread_fan_control(const uint8_t i_frutype,
+ const uint16_t i_fru_temperature);
+BOOLEAN thrm_thread_vrm_fan_control(const uint16_t i_vrfan);
+void thrm_thread_main();
+
+#endif
OpenPOWER on IntegriCloud