summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authormbroyles <mbroyles@us.ibm.com>2017-06-23 20:13:06 -0500
committerWilliam A. Bryan <wilbryan@us.ibm.com>2017-06-30 16:10:39 -0400
commit82156a8c51a11cf1173c5c4064cad903339b07ed (patch)
treeac60f96955ed414bcf71cfcc58e68b09f8818c33 /src
parentcfb296e1b662022f9f0f86a0a566eae67196f414 (diff)
downloadtalos-occ-82156a8c51a11cf1173c5c4064cad903339b07ed.tar.gz
talos-occ-82156a8c51a11cf1173c5c4064cad903339b07ed.zip
Support new in-band command/response interface and clear sensor command
Change-Id: Ic53e27d851023d99440aa1bfbdf5307920af3397 RTC: 158812 Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/42512 Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com> Reviewed-by: Shawn M. McCarney <shawnmm@us.ibm.com> Reviewed-by: Christopher J. Cain <cjcain@us.ibm.com> Reviewed-by: William A. Bryan <wilbryan@us.ibm.com>
Diffstat (limited to 'src')
-rwxr-xr-xsrc/occ_405/amec/amec_slave_smh.c71
-rwxr-xr-xsrc/occ_405/amec/amec_slave_smh.h6
-rwxr-xr-xsrc/occ_405/cmdh/cmdh_fsp_cmds.c342
-rwxr-xr-xsrc/occ_405/cmdh/cmdh_fsp_cmds.h99
-rwxr-xr-xsrc/occ_405/homer.h9
-rw-r--r--src/occ_405/occLinkInputFile1
-rw-r--r--src/occ_405/occ_service_codes.h9
-rwxr-xr-xsrc/occ_405/occ_sys_config.c8
-rwxr-xr-xsrc/occ_405/occ_sys_config.h1
-rwxr-xr-xsrc/occ_405/occbuildname.c2
-rwxr-xr-xsrc/occ_405/proc/proc_pstate.c4
-rwxr-xr-xsrc/occ_405/sensor/sensor.h21
-rwxr-xr-xsrc/occ_405/sensor/sensor_inband_cmd.c557
-rw-r--r--src/occ_405/sensor/sensor_inband_cmd.h112
-rw-r--r--src/occ_405/sensor/sensor_main_memory.h1
-rwxr-xr-xsrc/occ_405/sensor/sensor_service_codes.h6
-rw-r--r--src/occ_405/topfiles.mk1
17 files changed, 1202 insertions, 48 deletions
diff --git a/src/occ_405/amec/amec_slave_smh.c b/src/occ_405/amec/amec_slave_smh.c
index b37ab45..cb349f8 100755
--- a/src/occ_405/amec/amec_slave_smh.c
+++ b/src/occ_405/amec/amec_slave_smh.c
@@ -62,6 +62,7 @@
#include <state.h> // For CURRENT_STATE(), OCC_STATE_*
#include <cmdh_fsp_cmds_datacnfg.h> // For DATA_get_present_cnfgdata()
#include <sensor_main_memory.h> // For main_mem_sensors_*()
+#include <sensor_inband_cmd.h> // For inband_command_*()
//*************************************************************************/
// Externs
@@ -181,6 +182,25 @@ const smh_tbl_t amec_slv_state_5_substate_table[AMEC_SMH_STATES_PER_LVL] =
};
// --------------------------------------------------------
+// AMEC Slave State 6 Substate Table
+// --------------------------------------------------------
+// Each function inside this state table runs once every 16ms.
+//
+// No Substates
+//
+const smh_tbl_t amec_slv_state_6_substate_table[AMEC_SMH_STATES_PER_LVL] =
+{
+ {NULL, NULL}, // Substate 6.0 (not used)
+ {amec_slv_substate_6_1, NULL}, // Substate 6.1
+ {NULL, NULL}, // Substate 6.2 (not used)
+ {amec_slv_substate_6_3, NULL}, // Substate 6.3
+ {NULL, NULL}, // Substate 6.4 (not used)
+ {amec_slv_substate_6_5, NULL}, // Substate 6.5
+ {NULL, NULL}, // Substate 6.6 (not used)
+ {amec_slv_substate_6_7, NULL}, // Substate 6.7
+};
+
+// --------------------------------------------------------
// AMEC Slave State 7 Substate Table
// --------------------------------------------------------
// Each function inside this state table runs once every 16ms.
@@ -213,12 +233,11 @@ const smh_tbl_t amec_slv_state_table[AMEC_SMH_STATES_PER_LVL] =
{amec_slv_state_3, amec_slv_state_3_substate_table},
{amec_slv_state_4, NULL},
{amec_slv_state_5, amec_slv_state_5_substate_table},
- {amec_slv_state_6, NULL},
+ {amec_slv_state_6, amec_slv_state_6_substate_table},
{amec_slv_state_7, amec_slv_state_7_substate_table},
};
-
// This sets up the function pointer that will be called to update the
// fw timings when the AMEC Slave State Machine finishes.
smh_state_timing_t G_amec_slv_state_timings = {amec_slv_update_smh_sensors};
@@ -431,6 +450,7 @@ void amec_slv_common_tasks_post(void)
// Call the 250us trace recording if it has been configured via Amester.
// If not configured, this call will return immediately.
amec_tb_record(AMEC_TB_250US);
+
}
else
L_active_1tick = TRUE;
@@ -443,6 +463,16 @@ void amec_slv_common_tasks_post(void)
G_amec_opal_proc_throt_reason = MANUFACTURING_OVERRIDE;
ssx_semaphore_post(&G_dcomThreadWakeupSem);
}
+ // Check if an inband command is being processed
+ if(G_inband_occ_cmd_state != INBAND_OCC_CMD_NONE)
+ {
+ // call inband command handler if in active, char or obs state
+ if ( (IS_OCC_STATE_ACTIVE() && L_active_1tick) || IS_OCC_STATE_OBSERVATION() ||
+ IS_OCC_STATE_CHARACTERIZATION() )
+ {
+ inband_command_handler();
+ }
+ }
}
// Function Specification
@@ -1227,6 +1257,43 @@ void amec_slv_substate_5_7(void)
amec_update_proc_core_group(6);
}
+// Function Specification
+//
+// Name: amec_slv_substate_6_1
+// amec_slv_substate_6_3
+// amec_slv_substate_6_5
+// amec_slv_substate_6_7
+//
+// Description: slave substate amec_slv_substate_6_1
+// slave substate amec_slv_substate_6_3
+// slave substate amec_slv_substate_6_5
+// slave substate amec_slv_substate_6_7
+// other substates of state 6 are not currently used
+//
+// End Function Specification
+void amec_slv_substate_6_1(void)
+{
+ AMEC_DBG("\tAMEC Slave State 6.1\n");
+ inband_command_check();
+}
+
+void amec_slv_substate_6_3(void)
+{
+ AMEC_DBG("\tAMEC Slave State 6.3\n");
+ inband_command_check();
+}
+
+void amec_slv_substate_6_5(void)
+{
+ AMEC_DBG("\tAMEC Slave State 6.5\n");
+ inband_command_check();
+}
+
+void amec_slv_substate_6_7(void)
+{
+ AMEC_DBG("\tAMEC Slave State 6.7\n");
+ inband_command_check();
+}
// Function Specification
//
diff --git a/src/occ_405/amec/amec_slave_smh.h b/src/occ_405/amec/amec_slave_smh.h
index a10f419..6cca955 100755
--- a/src/occ_405/amec/amec_slave_smh.h
+++ b/src/occ_405/amec/amec_slave_smh.h
@@ -124,6 +124,12 @@ void amec_slv_substate_5_5(void);
void amec_slv_substate_5_6(void);
void amec_slv_substate_5_7(void);
+// Slave SubState 6 (4 SubStates unused) check for inband cmd every 4ms
+void amec_slv_substate_6_1(void);
+void amec_slv_substate_6_3(void);
+void amec_slv_substate_6_5(void);
+void amec_slv_substate_6_7(void);
+
// Slave SubState 7
void amec_slv_substate_7_0(void);
void amec_slv_substate_7_1(void);
diff --git a/src/occ_405/cmdh/cmdh_fsp_cmds.c b/src/occ_405/cmdh/cmdh_fsp_cmds.c
index c047d15..0933372 100755
--- a/src/occ_405/cmdh/cmdh_fsp_cmds.c
+++ b/src/occ_405/cmdh/cmdh_fsp_cmds.c
@@ -50,6 +50,7 @@
#include <avsbus.h>
#include "cmdh_dbug_cmd.h"
#include "wof.h"
+#include "sensor_main_memory.h"
extern dimm_sensor_flags_t G_dimm_temp_expired_bitmap;
extern bool G_vrm_thermal_monitoring;
@@ -1824,74 +1825,101 @@ errlHndl_t cmdh_tmgt_get_field_debug_data(const cmdh_fsp_cmd_t * i_cmd_ptr,
// Function Specification
//
-// Name: cmdh_set_user_pcap
+// Name: cmdh_set_user_pcap_common
//
-// Description: Implements the Set Use Power Cap command.
+// Description: Implements the common part of Set Use Power Cap cmd from inband or out of band
//
// End Function Specification
-errlHndl_t cmdh_set_user_pcap(const cmdh_fsp_cmd_t * i_cmd_ptr,
- cmdh_fsp_rsp_t * o_rsp_ptr)
+uint8_t cmdh_set_user_pcap_common(uint16_t i_pcap,
+ uint8_t i_source)
{
- errlHndl_t l_err = NULL;
- ERRL_RC l_rc = ERRL_RC_SUCCESS;
-
-
- G_rsp_status = ERRL_RC_SUCCESS;
- o_rsp_ptr->data_length[0] = 0;
- o_rsp_ptr->data_length[1] = 0;
+ uint8_t l_rc = ERRL_RC_SUCCESS;
do
{
// Can't send this command to a slave
if (OCC_SLAVE == G_occ_role)
{
+ TRAC_ERR("From source %d User PCAP %d must be sent to master OCC",
+ i_source, i_pcap);
l_rc = ERRL_RC_INVALID_CMD;
break;
}
- if (CMDH_DATALEN_FIELD_UINT16(i_cmd_ptr) != CMDH_SET_USER_PCAP_DATALEN)
- {
- l_rc = ERRL_RC_INVALID_CMD_LEN;
- break;
- }
-
- uint16_t l_pcap = CONVERT_UINT8_ARRAY_UINT16(i_cmd_ptr->data[0],
- i_cmd_ptr->data[1]);
-
//A value of 0 means this pcap has been deactivated, otherwise
//make sure it's within the min & max.
- if ((l_pcap != 0) && (l_pcap < G_master_pcap_data.soft_min_pcap))
+ if ((i_pcap != 0) && (i_pcap < G_master_pcap_data.soft_min_pcap))
{
- TRAC_ERR("User PCAP %d is below the minimum allowed (%d)",
- l_pcap, G_master_pcap_data.soft_min_pcap);
+ TRAC_ERR("From source %d User PCAP %d is below the minimum allowed (%d)",
+ i_source, i_pcap, G_master_pcap_data.soft_min_pcap);
l_rc = ERRL_RC_INVALID_DATA;
break;
}
- else if ((l_pcap > G_master_pcap_data.system_pcap) &&
+ else if ((i_pcap > G_master_pcap_data.system_pcap) &&
(G_master_pcap_data.system_pcap != 0))
{
- TRAC_ERR("User PCAP %d is above the maximum allowed (%d)",
- l_pcap, G_master_pcap_data.system_pcap);
+ TRAC_ERR("From source %d User PCAP %d is above the maximum allowed (%d)",
+ i_source, i_pcap, G_master_pcap_data.system_pcap);
l_rc = ERRL_RC_INVALID_DATA;
break;
}
else
{
- G_master_pcap_data.current_pcap = l_pcap;
+ G_master_pcap_data.current_pcap = i_pcap;
//Indicate there is new PCAP data available
G_master_pcap_data.pcap_data_count++;
-
- G_master_pcap_data.source = OUT_OF_BAND; // BMC/(H)TMGT
+ // if user pcap was just disabled set source to 0 (no user pcap)
+ if(i_pcap == 0)
+ {
+ G_master_pcap_data.source = 0;
+ }
+ else
+ {
+ G_master_pcap_data.source = i_source;
+ }
}
- TRAC_INFO("User selected power limit = %d",
- G_master_pcap_data.current_pcap);
+ TRAC_INFO("User selected power limit = %d set from source %d",
+ G_master_pcap_data.current_pcap, i_source);
} while (0);
+ return l_rc;
+}
+
+// Function Specification
+//
+// Name: cmdh_set_user_pcap
+//
+// Description: Implements the Set Use Power Cap command from out of band interface
+//
+// End Function Specification
+errlHndl_t cmdh_set_user_pcap(const cmdh_fsp_cmd_t * i_cmd_ptr,
+ cmdh_fsp_rsp_t * o_rsp_ptr)
+{
+ errlHndl_t l_err = NULL;
+ ERRL_RC l_rc = ERRL_RC_SUCCESS;
+
+
+ G_rsp_status = ERRL_RC_SUCCESS;
+ o_rsp_ptr->data_length[0] = 0;
+ o_rsp_ptr->data_length[1] = 0;
+
+ if (CMDH_DATALEN_FIELD_UINT16(i_cmd_ptr) != CMDH_SET_USER_PCAP_DATALEN)
+ {
+ TRAC_ERR("cmdh_set_user_pcap: Invalid command length %u, expected %u ",
+ CMDH_DATALEN_FIELD_UINT16(i_cmd_ptr), CMDH_SET_USER_PCAP_DATALEN);
+ l_rc = ERRL_RC_INVALID_CMD_LEN;
+ }
+ else
+ {
+ uint16_t l_pcap = CONVERT_UINT8_ARRAY_UINT16(i_cmd_ptr->data[0],
+ i_cmd_ptr->data[1]);
+ l_rc = cmdh_set_user_pcap_common(l_pcap, OUT_OF_BAND);
+ }
if (ERRL_RC_SUCCESS != l_rc)
{
@@ -1901,3 +1929,255 @@ errlHndl_t cmdh_set_user_pcap(const cmdh_fsp_cmd_t * i_cmd_ptr,
return l_err;
}
+
+// Function Specification
+//
+// Name: cmdh_clear_sensor_data
+//
+// Description: Implements the Clear sensor data command
+//
+// End Function Specification
+uint8_t cmdh_clear_sensor_data(const uint16_t i_cmd_data_length,
+ const uint8_t* i_cmd_data_ptr,
+ const uint16_t i_max_rsp_data_length,
+ uint16_t* o_rsp_data_length,
+ uint8_t* o_rsp_data_ptr)
+{
+ uint8_t l_rc = ERRL_RC_SUCCESS;
+ cmdh_clear_sensor_cmd_data_t *l_cmd_ptr = (cmdh_clear_sensor_cmd_data_t *) i_cmd_data_ptr;
+ cmdh_clear_sensor_rsp_data_t *l_rsp_ptr = (cmdh_clear_sensor_rsp_data_t*) o_rsp_data_ptr;
+ *o_rsp_data_length = 0;
+
+ do
+ {
+ // Command Length Check
+ if( i_cmd_data_length != sizeof(cmdh_clear_sensor_cmd_data_t) )
+ {
+ TRAC_ERR("cmdh_clear_sensor_data: Invalid command length %u, expected %u ",
+ i_cmd_data_length, sizeof(cmdh_clear_sensor_cmd_data_t));
+ l_rc = ERRL_RC_INVALID_CMD_LEN;
+ break;
+ }
+ // Make sure there is enough room in response buffer
+ if( sizeof(cmdh_clear_sensor_rsp_data_t) > i_max_rsp_data_length )
+ {
+ TRAC_ERR("cmdh_clear_sensor_data: Response size %u is larger than buffer size %u ",
+ sizeof(cmdh_clear_sensor_rsp_data_t), i_max_rsp_data_length);
+ l_rc = ERRL_RC_INTERNAL_FAIL;
+ break;
+ }
+ // Check that the owner(s) to clear sensors for are valid
+ if( (l_cmd_ptr->sensor_owner_id & ~(VALID_CLEAR_SENSOR_OWNER_MASK) ) ||
+ (l_cmd_ptr->sensor_owner_id == 0) )
+ {
+ TRAC_ERR("cmdh_clear_sensor_data: Invalid sensor owners = 0x%02X",
+ l_cmd_ptr->sensor_owner_id);
+ l_rc = ERRL_RC_INVALID_DATA;
+ break;
+ }
+
+ // clear min/max fields of all sensors for the given owner(s)
+ sensor_t *l_sensor_ptr = NULL;
+ uint16_t i = 0;
+ for( i = 0;i < G_amec_sensor_count; i++)
+ {
+ l_sensor_ptr = getSensorByGsid(i);
+ sensor_clear_minmax(l_sensor_ptr, l_cmd_ptr->sensor_owner_id);
+ }
+
+ // copy the owner_id to the response buffer and set the rsp length
+ l_rsp_ptr->sensor_owner_id = l_cmd_ptr->sensor_owner_id;
+ *o_rsp_data_length = (uint16_t) sizeof(cmdh_clear_sensor_rsp_data_t);
+ TRAC_INFO("cmdh_clear_sensor_data: Sensor min/max cleared for owners = 0x%02X",
+ l_rsp_ptr->sensor_owner_id);
+ } while (0);
+
+ return l_rc;
+}
+
+// Function Specification
+//
+// Name: cmdh_set_pcap_inband
+//
+// Description: Implements setting a power cap from the inband interface
+//
+// End Function Specification
+uint8_t cmdh_set_pcap_inband(const uint16_t i_cmd_data_length,
+ const uint8_t* i_cmd_data_ptr,
+ const uint16_t i_max_rsp_data_length,
+ uint16_t* o_rsp_data_length,
+ uint8_t* o_rsp_data_ptr)
+{
+ uint8_t l_rc = ERRL_RC_SUCCESS;
+ cmdh_set_inband_pcap_cmd_data_t *l_cmd_ptr = (cmdh_set_inband_pcap_cmd_data_t *) i_cmd_data_ptr;
+ cmdh_set_inband_pcap_rsp_data_t *l_rsp_ptr = (cmdh_set_inband_pcap_rsp_data_t*) o_rsp_data_ptr;
+ *o_rsp_data_length = 0;
+
+ do
+ {
+ // Command Length Check
+ if( i_cmd_data_length != sizeof(cmdh_set_inband_pcap_cmd_data_t) )
+ {
+ TRAC_ERR("cmdh_set_pcap_inband: Invalid command length %u, expected %u ",
+ i_cmd_data_length, sizeof(cmdh_set_inband_pcap_cmd_data_t));
+ l_rc = ERRL_RC_INVALID_CMD_LEN;
+ break;
+ }
+
+ // Make sure there is enough room in response buffer
+ if( sizeof(cmdh_set_inband_pcap_rsp_data_t) > i_max_rsp_data_length )
+ {
+ TRAC_ERR("cmdh_set_pcap_inband: Response size %u is larger than buffer size %u ",
+ sizeof(cmdh_set_inband_pcap_rsp_data_t), i_max_rsp_data_length);
+ l_rc = ERRL_RC_INTERNAL_FAIL;
+ break;
+ }
+
+ uint16_t l_pcap = CONVERT_UINT8_ARRAY_UINT16(l_cmd_ptr->power_cap[0],
+ l_cmd_ptr->power_cap[1]);
+ l_rc = cmdh_set_user_pcap_common(l_pcap, IN_BAND);
+
+ // if successful copy the power cap to the response buffer and set the rsp length
+ if(l_rc == ERRL_RC_SUCCESS)
+ {
+ l_rsp_ptr->power_cap[0] = l_cmd_ptr->power_cap[0];
+ l_rsp_ptr->power_cap[1] = l_cmd_ptr->power_cap[1];
+ *o_rsp_data_length = (uint16_t) sizeof(cmdh_set_inband_pcap_rsp_data_t);
+ }
+ } while (0);
+
+ return l_rc;
+}
+
+// Function Specification
+//
+// Name: cmdh_write_psr
+//
+// Description: Implements the Write Power Shifting Ratio command
+//
+// End Function Specification
+uint8_t cmdh_write_psr(const uint16_t i_cmd_data_length,
+ const uint8_t* i_cmd_data_ptr,
+ const uint16_t i_max_rsp_data_length,
+ uint16_t* o_rsp_data_length,
+ uint8_t* o_rsp_data_ptr)
+{
+ uint8_t l_rc = ERRL_RC_SUCCESS;
+ cmdh_write_psr_cmd_data_t *l_cmd_ptr = (cmdh_write_psr_cmd_data_t *) i_cmd_data_ptr;
+ cmdh_write_psr_rsp_data_t *l_rsp_ptr = (cmdh_write_psr_rsp_data_t*) o_rsp_data_ptr;
+ *o_rsp_data_length = 0;
+
+ do
+ {
+ // Command Length Check
+ if( i_cmd_data_length != sizeof(cmdh_write_psr_cmd_data_t) )
+ {
+ TRAC_ERR("cmdh_write_psr: Invalid command length %u, expected %u ",
+ i_cmd_data_length, sizeof(cmdh_write_psr_cmd_data_t));
+ l_rc = ERRL_RC_INVALID_CMD_LEN;
+ break;
+ }
+ // Make sure there is enough room in response buffer
+ if( sizeof(cmdh_write_psr_rsp_data_t) > i_max_rsp_data_length )
+ {
+ TRAC_ERR("cmdh_write_psr: Response size %u is larger than buffer size %u ",
+ sizeof(cmdh_write_psr_rsp_data_t), i_max_rsp_data_length);
+ l_rc = ERRL_RC_INTERNAL_FAIL;
+ break;
+ }
+ // Verify PSR is within range 0-100%
+ if(l_cmd_ptr->psr > 100)
+ {
+ TRAC_ERR("cmdh_write_psr: Invalid PSR %u",
+ l_cmd_ptr->psr);
+ l_rc = ERRL_RC_INVALID_DATA;
+ break;
+ }
+
+ // PSR is valid
+ TRAC_INFO("cmdh_write_psr: PSR changed from %u to %u", G_sysConfigData.psr, l_cmd_ptr->psr);
+ G_sysConfigData.psr = l_cmd_ptr->psr;
+
+ // copy the PSR to the response buffer and set the rsp length
+ l_rsp_ptr->psr = l_cmd_ptr->psr;
+ *o_rsp_data_length = (uint16_t) sizeof(cmdh_write_psr_rsp_data_t);
+ } while (0);
+
+ return l_rc;
+}
+
+// Function Specification
+//
+// Name: cmdh_select_sensor_groups
+//
+// Description: Implements the Select sensor Groups command to select
+// sensor types that will be copied to main memory
+//
+// End Function Specification
+uint8_t cmdh_select_sensor_groups(const uint16_t i_cmd_data_length,
+ const uint8_t* i_cmd_data_ptr,
+ const uint16_t i_max_rsp_data_length,
+ uint16_t* o_rsp_data_length,
+ uint8_t* o_rsp_data_ptr)
+{
+ uint8_t l_rc = ERRL_RC_SUCCESS;
+ uint16_t l_sensor_groups = 0;
+ cmdh_select_sensor_groups_cmd_data_t *l_cmd_ptr = (cmdh_select_sensor_groups_cmd_data_t *) i_cmd_data_ptr;
+ cmdh_select_sensor_groups_rsp_data_t *l_rsp_ptr = (cmdh_select_sensor_groups_rsp_data_t*) o_rsp_data_ptr;
+ *o_rsp_data_length = 0;
+ do
+ {
+ // Command Length Check
+ if( i_cmd_data_length != sizeof(cmdh_select_sensor_groups_cmd_data_t) )
+ {
+ TRAC_ERR("cmdh_select_sensor_groups: Invalid command length %u, expected %u ",
+ i_cmd_data_length, sizeof(cmdh_select_sensor_groups_cmd_data_t));
+ l_rc = ERRL_RC_INVALID_CMD_LEN;
+ break;
+ }
+ // Make sure there is enough room in response buffer
+ if( sizeof(cmdh_select_sensor_groups_rsp_data_t) > i_max_rsp_data_length )
+ {
+ TRAC_ERR("cmdh_select_sensor_groups: Response size %u is larger than buffer size %u ",
+ sizeof(cmdh_select_sensor_groups_rsp_data_t), i_max_rsp_data_length);
+ l_rc = ERRL_RC_INTERNAL_FAIL;
+ break;
+ }
+ // Check that the sensor group(s) to select are valid
+ // 0 is valid and means not to copy any sensors to main memory
+ l_sensor_groups = CONVERT_UINT8_ARRAY_UINT16(l_cmd_ptr->sensor_groups[0],
+ l_cmd_ptr->sensor_groups[1]);
+ if(l_sensor_groups & ~(VALID_SET_SENSOR_GROUPS_MASK))
+ {
+ TRAC_ERR("cmdh_select_sensor_groups: Invalid sensor groups = 0x%04X",
+ l_sensor_groups);
+ l_rc = ERRL_RC_INVALID_DATA;
+ break;
+ }
+
+ // Loop thru 16 bits to check all possible sensor types
+ uint8_t l_bit = 0;
+ uint16_t l_sensor_type = 0;
+ bool l_enabled = false;
+ for(l_bit = 0; l_bit < 16; l_bit++)
+ {
+ l_sensor_type = 0x0001 << l_bit;
+ // only set eanbled for sensor types that are valid
+ if( l_sensor_type & (VALID_SET_SENSOR_GROUPS_MASK) )
+ {
+ // type is valid now set enabled based on sensor groups selected
+ l_enabled = (l_sensor_groups & l_sensor_type) ? true : false;
+ main_mem_sensors_set_enabled(l_sensor_type, l_enabled);
+ }
+ }
+
+ // copy the sensor groups to the response buffer and set the rsp length
+ l_rsp_ptr->sensor_groups[0] = l_cmd_ptr->sensor_groups[0];
+ l_rsp_ptr->sensor_groups[1] = l_cmd_ptr->sensor_groups[1];
+ *o_rsp_data_length = (uint16_t) sizeof(cmdh_select_sensor_groups_rsp_data_t);
+ TRAC_INFO("cmdh_select_sensor_groups: Sensor groups 0x%04X selected",
+ l_sensor_groups);
+ } while (0);
+
+ return l_rc;
+}
diff --git a/src/occ_405/cmdh/cmdh_fsp_cmds.h b/src/occ_405/cmdh/cmdh_fsp_cmds.h
index 7e63f92..254c42a 100755
--- a/src/occ_405/cmdh/cmdh_fsp_cmds.h
+++ b/src/occ_405/cmdh/cmdh_fsp_cmds.h
@@ -34,13 +34,11 @@
#include "occ_common.h"
#include "state.h"
#include "cmdh_fsp.h"
-//#include "gpsm.h"
-//#include "pstates.h"
#include "cmdh_fsp_cmds_datacnfg.h"
#include "sensor.h"
#include "apss.h"
-// Enum of the various commands that TMGT may send to OCC
+// Enum of the various commands that may be sent to OCC
typedef enum
{
CMDH_POLL = 0x00,
@@ -56,6 +54,10 @@ typedef enum
CMDH_GET_FIELD_DEBUG_DATA = 0x42,
CMDH_MFG_TEST_CMD = 0x53,
CMDH_TUNABLE_PARMS = 0x60,
+ CMDH_CLEAR_SENSOR_DATA = 0xD0,
+ CMDH_SET_PCAP_INBAND = 0xD1,
+ CMDH_WRITE_PSR = 0xD2,
+ CMDH_SELECT_SENSOR_GROUPS = 0xD3,
} eCmdhCommands;
#define SENSOR_TEMP "TEMP"
@@ -64,7 +66,7 @@ typedef enum
#define SENSOR_CAPS "CAPS"
#define SENSOR_EXTN "EXTN"
#define EXTN_NAME_FMIN 0x464D494E // "FMIN"
-#define EXTN_NAME_FNOM 0x464E4F00 // "FNOM"
+#define EXTN_NAME_FNOM 0x464E4F4D // "FNOM"
#define EXTN_NAME_FTURBO 0x46540000 // "FT"
#define EXTN_NAME_FUTURBO 0x46555400 // "FUT"
@@ -605,6 +607,65 @@ extern cmdh_tunable_param_table_t G_mst_tunable_parameter_table[CMDH_DEFAULT_TUN
#define CMDH_SET_USER_PCAP_DATALEN 2
+//---------------------------------------------------------
+// Clear Sensor Data Command
+//---------------------------------------------------------
+
+typedef struct __attribute__ ((packed))
+{
+ uint8_t sensor_owner_id;
+ uint8_t reserved[3];
+}cmdh_clear_sensor_cmd_data_t;
+
+typedef struct __attribute__ ((packed))
+{
+ uint8_t sensor_owner_id;
+ uint8_t reserved[3];
+}cmdh_clear_sensor_rsp_data_t;
+
+//---------------------------------------------------------
+// Set Power Cap In-band Command
+//---------------------------------------------------------
+
+typedef struct __attribute__ ((packed))
+{
+ uint8_t power_cap[2];
+}cmdh_set_inband_pcap_cmd_data_t;
+
+typedef struct __attribute__ ((packed))
+{
+ uint8_t power_cap[2];
+}cmdh_set_inband_pcap_rsp_data_t;
+
+//---------------------------------------------------------
+// Write Power Shifting Ratio Command
+//---------------------------------------------------------
+
+typedef struct __attribute__ ((packed))
+{
+ uint8_t psr;
+}cmdh_write_psr_cmd_data_t;
+
+typedef struct __attribute__ ((packed))
+{
+ uint8_t psr;
+}cmdh_write_psr_rsp_data_t;
+
+//---------------------------------------------------------
+// Select Sensor Groups Command
+//---------------------------------------------------------
+
+typedef struct __attribute__ ((packed))
+{
+ uint8_t sensor_groups[2];
+}cmdh_select_sensor_groups_cmd_data_t;
+
+typedef struct __attribute__ ((packed))
+{
+ uint8_t sensor_groups[2];
+}cmdh_select_sensor_groups_rsp_data_t;
+
+
errlHndl_t cmdh_tmgt_setmodestate(const cmdh_fsp_cmd_t * i_cmd_ptr,
cmdh_fsp_rsp_t * i_rsp_ptr);
@@ -629,5 +690,35 @@ errlHndl_t cmdh_tmgt_get_field_debug_data(const cmdh_fsp_cmd_t * i_cmd_ptr,
errlHndl_t cmdh_set_user_pcap(const cmdh_fsp_cmd_t * i_cmd_ptr,
cmdh_fsp_rsp_t * o_rsp_ptr);
+
+//------------------------------------------------------------------------------------
+// Commands supported via in-band interface must have additional inputs/output/return
+// Any out of band commands that are to be supported in-band should change to this
+// common format to allow calling by either i.e. AMESTER pass thru is supported on both
+//------------------------------------------------------------------------------------
+uint8_t cmdh_clear_sensor_data(const uint16_t i_cmd_data_length,
+ const uint8_t* i_cmd_data_ptr,
+ const uint16_t i_max_rsp_data_length,
+ uint16_t* o_rsp_data_length,
+ uint8_t* o_rsp_data_ptr);
+
+uint8_t cmdh_set_pcap_inband(const uint16_t i_cmd_data_length,
+ const uint8_t* i_cmd_data_ptr,
+ const uint16_t i_max_rsp_data_length,
+ uint16_t* o_rsp_data_length,
+ uint8_t* o_rsp_data_ptr);
+
+uint8_t cmdh_write_psr(const uint16_t i_cmd_data_length,
+ const uint8_t* i_cmd_data_ptr,
+ const uint16_t i_max_rsp_data_length,
+ uint16_t* o_rsp_data_length,
+ uint8_t* o_rsp_data_ptr);
+
+uint8_t cmdh_select_sensor_groups(const uint16_t i_cmd_data_length,
+ const uint8_t* i_cmd_data_ptr,
+ const uint16_t i_max_rsp_data_length,
+ uint16_t* o_rsp_data_length,
+ uint8_t* o_rsp_data_ptr);
+
#endif
diff --git a/src/occ_405/homer.h b/src/occ_405/homer.h
index b634701..4f2061e 100755
--- a/src/occ_405/homer.h
+++ b/src/occ_405/homer.h
@@ -46,6 +46,15 @@
#define OPAL_STATIC_ADDRESS_HOMER OPAL_ADDRESS_HOMER // OPAL's Static Address
#define OPAL_DYNAMIC_ADDRESS_HOMER (OPAL_ADDRESS_HOMER+OPAL_DYNAMIC_OFFSET) // OPAL's Dynamic Address
+
+// Inband OCC command buffer offset in HOMER from the start of OPAL data
+#define INBAND_OCC_CMD_OFFSET_HOMER 0x00000C00
+#define INBAND_OCC_CMD_ADDRESS_HOMER (OPAL_ADDRESS_HOMER+INBAND_OCC_CMD_OFFSET_HOMER)
+
+// Inband OCC response buffer offset in HOMER from the start of OPAL data
+#define INBAND_OCC_RSP_OFFSET_HOMER 0x00001C00
+#define INBAND_OCC_RSP_ADDRESS_HOMER (OPAL_ADDRESS_HOMER+INBAND_OCC_RSP_OFFSET_HOMER)
+
// OCC/HTMGT command buffer offset in HOMER
#define OCC_HTMGT_CMD_OFFSET_HOMER 0x000E0000
#define OCC_HTMGT_CMD_ADDRESS_HOMER (HOMER_BASE_ADDRESS+OCC_HTMGT_CMD_OFFSET_HOMER)
diff --git a/src/occ_405/occLinkInputFile b/src/occ_405/occLinkInputFile
index 0ee9eca..378fe57 100644
--- a/src/occ_405/occLinkInputFile
+++ b/src/occ_405/occLinkInputFile
@@ -80,6 +80,7 @@ INPUT ( amec_amester.o
rtls_tables.o
rtls.o
scom.o
+ sensor_inband_cmd.o
sensor_info.o
sensor_main_memory.o
sensor_query_list.o
diff --git a/src/occ_405/occ_service_codes.h b/src/occ_405/occ_service_codes.h
index a39d31a..2b066df 100644
--- a/src/occ_405/occ_service_codes.h
+++ b/src/occ_405/occ_service_codes.h
@@ -135,8 +135,14 @@ enum occReasonCode
INVALID_FREQUENCY = 0xDE,
WOF_RE_ENABLED = 0xDF,
+// NOTE: 0xE0 - 0xEF can NOT be used these are reserved for critical
+// OCC errors. (H)TMGT will be looking for 0xEy ERRL_RC in cmd response RC
+// and create an OCC error log with OCC component ID and 0xEy RC if found
+
/// Error copying sensors to main memory
- SENSOR_MAIN_MEM_ERROR = 0xE0,
+ SENSOR_MAIN_MEM_ERROR = 0xF0,
+
+ INBAND_CMD_ERROR = 0xF1,
/// Success!
OCC_SUCCESS_REASON_CODE = 0xFF,
@@ -226,6 +232,7 @@ enum occExtReasonCode
ERC_BCE_REQ_SCHED_INPROG_FAILURE = 0x0073,
ERC_BCE_REQ_CREATE_WRITE_FAILURE = 0x0074,
ERC_BCE_REQ_SCHED_WRITE_FAILURE = 0x0075,
+ ERC_BCE_REQ_CALLBACK_TIMEOUT = 0x0076,
ERC_DIMM_SCHEDULE_FAILURE = 0x0080,
ERC_DIMM_COMPLETE_FAILURE = 0x0081,
diff --git a/src/occ_405/occ_sys_config.c b/src/occ_405/occ_sys_config.c
index 2335220..79a2fd0 100755
--- a/src/occ_405/occ_sys_config.c
+++ b/src/occ_405/occ_sys_config.c
@@ -222,6 +222,14 @@ occSysConfigData_t G_sysConfigData =
{{0}, {0}, {0}, {0}},
{{0}, {0}, {0}, {0}}
},
+
+ // -----------------------------------------------------------
+ // GPU Initialization
+ // -----------------------------------------------------------
+ .gpu_sensor_ids = {0},
+ .total_non_gpu_max_pwr_watts = 0,
+ .total_proc_mem_pwr_drop_watts = 0,
+ .psr = 100, // default to 100% take all possible power away from CPU/memory first
};
diff --git a/src/occ_405/occ_sys_config.h b/src/occ_405/occ_sys_config.h
index 14c2645..951690a 100755
--- a/src/occ_405/occ_sys_config.h
+++ b/src/occ_405/occ_sys_config.h
@@ -436,6 +436,7 @@ typedef struct
uint32_t gpu_sensor_ids[MAX_NUM_GPU_PER_DOMAIN];
uint16_t total_non_gpu_max_pwr_watts;
uint16_t total_proc_mem_pwr_drop_watts;
+ uint8_t psr; // power shifting ratio for power capping between GPU/Proc&mem
} occSysConfigData_t; __attribute__ ((__aligned__ (128)))
diff --git a/src/occ_405/occbuildname.c b/src/occ_405/occbuildname.c
index 5887e1b..c285868 100755
--- a/src/occ_405/occbuildname.c
+++ b/src/occ_405/occbuildname.c
@@ -34,6 +34,6 @@ volatile const char G_occ_buildname[16] __attribute__((section(".buildname"))) =
#else
-volatile const char G_occ_buildname[16] __attribute__((section(".buildname"))) = /*<BuildName>*/ "op_occ_170607a\0" /*</BuildName>*/ ;
+volatile const char G_occ_buildname[16] __attribute__((section(".buildname"))) = /*<BuildName>*/ "op_occ_170630a\0" /*</BuildName>*/ ;
#endif
diff --git a/src/occ_405/proc/proc_pstate.c b/src/occ_405/proc/proc_pstate.c
index 986fd2b..277399d 100755
--- a/src/occ_405/proc/proc_pstate.c
+++ b/src/occ_405/proc/proc_pstate.c
@@ -209,7 +209,7 @@ void populate_opal_dynamic_data()
G_opal_dynamic_table.dynamic.mem_throt_status = G_amec_opal_mem_throt_reason;
G_opal_dynamic_table.dynamic.quick_power_drop = AMEC_INTF_GET_OVERSUBSCRIPTION();
- G_opal_dynamic_table.dynamic.power_shift_ratio = 50; // @TODO: Power Shift Ratio is not Implemented yet RTC:133825
+ G_opal_dynamic_table.dynamic.power_shift_ratio = G_sysConfigData.psr;
G_opal_dynamic_table.dynamic.power_cap_type = G_master_pcap_data.source;
G_opal_dynamic_table.dynamic.min_power_cap = G_master_pcap_data.soft_min_pcap;
G_opal_dynamic_table.dynamic.max_power_cap = G_master_pcap_data.max_pcap;
@@ -419,7 +419,7 @@ void check_for_opal_updates(void)
// else, if a dynamic OPAL parameter changed, update OPAL dynamic table and OPAL data in memory
else if(G_opal_dynamic_table.dynamic.occ_state != CURRENT_STATE() ||
G_opal_dynamic_table.dynamic.quick_power_drop != AMEC_INTF_GET_OVERSUBSCRIPTION() ||
- G_opal_dynamic_table.dynamic.power_shift_ratio != 50 || // @TODO: Power Shift Ratio is not Implemented yet RTC:133825
+ G_opal_dynamic_table.dynamic.power_shift_ratio != G_sysConfigData.psr ||
G_opal_dynamic_table.dynamic.power_cap_type != G_master_pcap_data.source ||
G_opal_dynamic_table.dynamic.min_power_cap != G_master_pcap_data.soft_min_pcap ||
G_opal_dynamic_table.dynamic.max_power_cap != G_master_pcap_data.max_pcap ||
diff --git a/src/occ_405/sensor/sensor.h b/src/occ_405/sensor/sensor.h
index c28b0cd..3b301d9 100755
--- a/src/occ_405/sensor/sensor.h
+++ b/src/occ_405/sensor/sensor.h
@@ -75,6 +75,12 @@ typedef enum
AMEC_SENSOR_TYPE_PERF = 0x0200,
AMEC_SENSOR_TYPE_ALL = 0xffff,
}AMEC_SENSOR_TYPE;
+// Changes to sensor type bits would require changes to select sensor groups command
+// Define the sensor types allowed to be selected via select sensor groups command
+#define VALID_SET_SENSOR_GROUPS_MASK (AMEC_SENSOR_TYPE_GENERIC | AMEC_SENSOR_TYPE_CURRENT | \
+ AMEC_SENSOR_TYPE_VOLTAGE | AMEC_SENSOR_TYPE_TEMP | AMEC_SENSOR_TYPE_UTIL | \
+ AMEC_SENSOR_TYPE_TIME | AMEC_SENSOR_TYPE_FREQ | AMEC_SENSOR_TYPE_POWER | \
+ AMEC_SENSOR_TYPE_PERF)
// AMEC_SENSOR_LOC_INVALID can not be used to identify sensor location.
// A bit vector mask is used to specify sensor locations that AMESTER is
@@ -113,13 +119,16 @@ typedef enum
// AMEC_SENSOR_CLEAR_ALL_MINMAX clears all min/max values in the sensor.
typedef enum
{
- AMEC_SENSOR_CLEAR_SAMPLE_MINMAX = 0x0001,
- AMEC_SENSOR_CLEAR_CSM_SAMPLE_MINMAX = 0x0002,
- AMEC_SENSOR_CLEAR_PROFILER_SAMPLE_MINMAX = 0x0004,
- AMEC_SENSOR_CLEAR_JOB_S_SAMPLE_MINMAX = 0x0008,
- AMEC_SENSOR_CLEAR_ALL_MINMAX = 0xffff,
+ AMEC_SENSOR_CLEAR_SAMPLE_MINMAX = 0x01,
+ AMEC_SENSOR_CLEAR_CSM_SAMPLE_MINMAX = 0x10,
+ AMEC_SENSOR_CLEAR_PROFILER_SAMPLE_MINMAX = 0x20,
+ AMEC_SENSOR_CLEAR_JOB_S_SAMPLE_MINMAX = 0x40,
+ AMEC_SENSOR_CLEAR_ALL_MINMAX = 0xff,
} AMEC_SENSOR_CLEAR_TYPE;
-
+// The bits for types must match the defined owners in the clear sensor data command
+// Define the owners allowed to be cleared via clear sensor data command
+#define VALID_CLEAR_SENSOR_OWNER_MASK (AMEC_SENSOR_CLEAR_CSM_SAMPLE_MINMAX | \
+ AMEC_SENSOR_CLEAR_PROFILER_SAMPLE_MINMAX | AMEC_SENSOR_CLEAR_JOB_S_SAMPLE_MINMAX)
/*****************************************************************************/
// Forward declaration as used in vectorSensor
struct sensor;
diff --git a/src/occ_405/sensor/sensor_inband_cmd.c b/src/occ_405/sensor/sensor_inband_cmd.c
new file mode 100755
index 0000000..15a8967
--- /dev/null
+++ b/src/occ_405/sensor/sensor_inband_cmd.c
@@ -0,0 +1,557 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/occ_405/sensor/sensor_inband_cmd.c $ */
+/* */
+/* OpenPOWER OnChipController Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2017,2017 */
+/* [+] 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 <cmdh_fsp_cmds.h>
+#include <sensor_inband_cmd.h>
+#include <homer.h>
+#include <occ_service_codes.h>
+#include <sensor_service_codes.h>
+#include <trac.h>
+#include <occhw_async.h>
+#include <common.h>
+
+
+//******************************************************************************
+// Block Copy Engine (BCE) Defines/Globals
+//******************************************************************************
+
+// Buffer in SRAM to copy larger commands cmd/rsp buffer from/to main memory using the BCE
+DMA_BUFFER(inband_max_cmd_t G_inband_cmd_max_data_bce_buff) = {{0}};
+
+// Buffer in SRAM to copy smaller commands cmd/rsp buffer from/to main memory using the BCE
+DMA_BUFFER(inband_min_cmd_t G_inband_cmd_min_data_bce_buff) = {{0}};
+
+// BCE request structure. Used by BCE functions to schedule copy request.
+BceRequest G_inband_cmd_bce_req;
+
+/**
+ * Specifies whether the BCE request was scheduled. If false, the request
+ * finished or has never been scheduled/initialized.
+ */
+bool G_inband_cmd_req_scheduled = false;
+
+// Number of tics passed waiting for BCE callback
+uint8_t G_bce_callback_wait = 0;
+
+volatile uint8_t G_inband_occ_cmd_state = INBAND_OCC_CMD_NONE;
+volatile uint8_t G_inband_occ_bce_saved_state = INBAND_OCC_CMD_NONE;
+
+//******************************************************************************
+// Functions
+//******************************************************************************
+
+
+/**
+ * Logs an error caused by the Block Copy Engine. Does nothing if a BCE error
+ * has already been logged.
+ *
+ * Note that the required error log comment containing tags like 'userdata4' and
+ * 'devdesc' must be located by the call to this function. It is not located
+ * inside this function because the value of those tags varies.
+ *
+ * @param i_modId Module ID
+ * @param i_extReasonCode Extended reason code
+ * @param i_userData1 Userdata1 value
+ * @param i_userData2 Userdata2 value
+ */
+void inband_cmd_log_bce_error(uint16_t i_modId, uint16_t i_extReasonCode,
+ uint32_t i_userData1, uint32_t i_userData2)
+{
+ static bool L_error_logged = false;
+ if (!L_error_logged)
+ {
+ // Create and commit error
+ errlHndl_t l_errl = createErrl(i_modId, // Module ID
+ INBAND_CMD_ERROR, // Reason code
+ i_extReasonCode, // Extended reason code
+ ERRL_SEV_INFORMATIONAL, // Severity
+ NULL, // Trace Buffers
+ DEFAULT_TRACE_SIZE, // Trace Size
+ i_userData1, // Userdata1
+ i_userData2); // Userdata2
+ commitErrl(&l_errl);
+ L_error_logged = true;
+ }
+}
+
+
+/**
+ * Returns whether the global BCE request struct is idle and ready for re-use.
+ * Returns true immediately if the request was not scheduled. If the request
+ * was scheduled, checks to see if it has finished.
+ *
+ * @param i_caller_mod_id Module ID of calling function in case an error occurs
+ * @return True if BCE request is idle, false otherwise
+ */
+bool inband_cmd_is_bce_req_idle(uint16_t i_caller_mod_id)
+{
+ // Number of times we've waited for current request to finish
+ static uint8_t L_wait_count = 0;
+
+ // If the request was not previously scheduled, then it is idle. This also
+ // handles the case where the request has not been initialized yet.
+ if (!G_inband_cmd_req_scheduled)
+ {
+ return true;
+ }
+
+ // Request was scheduled; check if it finished and is now idle
+ if (async_request_is_idle(&G_inband_cmd_bce_req.request))
+ {
+ // Request is now idle and ready for re-use
+ G_inband_cmd_req_scheduled = false;
+
+ // If we were waiting for request to finish, trace and clear wait count
+ if (L_wait_count > 0)
+ {
+ TRAC_INFO("inband_cmd_is_bce_req_idle: "
+ "Request finished after waiting %u times: caller=0x%04X",
+ L_wait_count, i_caller_mod_id);
+ L_wait_count = 0;
+ }
+ return true;
+ }
+
+ // Request was scheduled but has not finished. Increment wait count unless
+ // we are already at the max (to avoid overflow).
+ if (L_wait_count < UINT8_MAX)
+ {
+ ++L_wait_count;
+ }
+
+ // If this is the first time we've waited for this request, trace it
+ if (L_wait_count == 1)
+ {
+ TRAC_INFO("inband_cmd_is_bce_req_idle: "
+ "Waiting for request to finish: caller=0x%04X",
+ i_caller_mod_id);
+ }
+
+ // If this is the second time we've waited for this request, log BCE error
+ if (L_wait_count == 2)
+ {
+ /* @
+ * @errortype
+ * @moduleid INBAND_CMD_IS_BCE_REQ_IDLE_MOD
+ * @reasoncode INBAND_CMD_ERROR
+ * @userdata1 Caller module ID
+ * @userdata2 0
+ * @userdata4 ERC_GENERIC_TIMEOUT
+ * @devdesc BCE request not finished after waiting twice
+ */
+ inband_cmd_log_bce_error(INBAND_CMD_IS_BCE_REQ_IDLE_MOD, ERC_GENERIC_TIMEOUT,
+ i_caller_mod_id, 0);
+ }
+
+ // Return false since request is not idle
+ return false;
+}
+
+/**
+ * inband_cmd_bce_callback
+ *
+ * Description: Callback function for G_inband_cmd_bce_req BCE request
+ * NO TRACING OR CALLING FUNCTIONS THAT TRACE ALLOWED
+ */
+void inband_cmd_bce_callback( void )
+{
+ static bool L_processed_at_least_one_cmd = FALSE;
+ static uint8_t L_last_seq_num_processed = 0;
+ uint8_t seq_num = 0;
+ uint8_t cmd_flags = 0;
+
+ // Decide what to do next for processing an in-band command for the BCE that finished
+ switch (G_inband_occ_cmd_state)
+ {
+ case INBAND_OCC_CMD_CHECK_FOR_CMD:
+ // check for command uses min bce data buffer
+ // If we processed at least one cmd it is not a new command if same seq number
+ cmd_flags = G_inband_cmd_min_data_bce_buff.header.flags;
+ seq_num = G_inband_cmd_min_data_bce_buff.header.seq;
+ if( ( (!L_processed_at_least_one_cmd) ||
+ (L_processed_at_least_one_cmd && (seq_num != L_last_seq_num_processed)) ) &&
+ ( (cmd_flags & IN_BAND_CMD_READY_MASK) == IN_BAND_CMD_READY_MASK) )
+ {
+ // There is a command to process
+ G_inband_occ_cmd_state = INBAND_OCC_CMD_START;
+ // now that we have a cmd save seq num so we don't keep processing the same cmd
+ L_processed_at_least_one_cmd = TRUE;
+ L_last_seq_num_processed = seq_num;
+ }
+ else
+ {
+ // No command
+ G_inband_occ_cmd_state = INBAND_OCC_CMD_NONE;
+ }
+ break;
+
+ case INBAND_OCC_CMD_RSP_READY:
+ // response is ready send interrupt
+ G_inband_occ_cmd_state = INBAND_OCC_CMD_RSP_INT;
+ break;
+
+ default:
+ // Invalid state. Can't trace here set state to invalid to trace later
+ G_inband_occ_bce_saved_state = G_inband_occ_cmd_state;
+ G_inband_occ_cmd_state = INBAND_OCC_INVALID_BCE_CALLBACK;
+ break;
+ }
+}
+
+/**
+ * Copies the specified number of bytes either to main mem or down from main mem
+ * for handling an inband command using the Block Copy Engine (BCE).
+ *
+ * @param i_main_mem_addr Main memory address for copy. Must be 128-byte aligned
+ * @param i_sram_addr SRAM address for copy. Must be 128-byte aligned
+ * @param i_byte_count Number of bytes to copy. Must be multiple of 128.
+ * Must be <= INBAND_OCC_CMD_BCE_BUF_SIZE. 0 bytes is not valid
+ * @param i_to_main_mem TRUE indicates copy is sram to main memory
+ * FALSE indicates copy is main memory to sram
+ * @param i_caller_mod_id Module ID of the calling function in case an error occurs
+ * @return True if BCE request was successfully scheduled, false otherwise
+ */
+bool inband_cmd_bce_copy(uint32_t i_main_mem_addr, uint32_t i_sram_addr,
+ size_t i_byte_count, bool i_to_main_mem, uint16_t i_caller_mod_id)
+{
+ int l_rc = 0;
+
+ // Verify address and byte count are valid
+ static bool L_traced_param_error = false;
+ if (((i_main_mem_addr % 128) != 0) || ((i_sram_addr % 128) != 0) ||
+ ((i_byte_count % 128) != 0) || (i_byte_count > INBAND_CMD_MAX_BCE_BUF_SIZE) ||
+ (i_byte_count == 0) )
+ {
+ if (!L_traced_param_error)
+ {
+ TRAC_ERR("inband_cmd_bce_copy: Input parameter error: "
+ "address=0x%08X SRAM=0x%08X length=%u caller=0x%04X",
+ i_main_mem_addr, i_sram_addr, i_byte_count, i_caller_mod_id);
+ L_traced_param_error = true;
+ }
+ return false;
+ }
+
+ // Check if a copy request was previously scheduled and is not yet finished
+ static bool L_traced_sched_error = false;
+ if (!inband_cmd_is_bce_req_idle(i_caller_mod_id))
+ {
+ if (!L_traced_sched_error)
+ {
+ TRAC_ERR("inband_cmd_bce_copy: Previous request not finished: caller=0x%04X",
+ i_caller_mod_id);
+ L_traced_sched_error = true;
+ }
+ return false;
+ }
+
+ // Create BCE request based on if copy is up or down from main memory
+ if (i_to_main_mem)
+ {
+ l_rc = bce_request_create(&G_inband_cmd_bce_req, // Block copy request
+ &G_pba_bcue_queue, // SRAM up to mainstore
+ i_main_mem_addr, // Mainstore address
+ i_sram_addr, // SRAM start address
+ i_byte_count, // Size of copy
+ SSX_WAIT_FOREVER, // No timeout
+ (AsyncRequestCallback) inband_cmd_bce_callback,
+ NULL, // No call back args
+ ASYNC_CALLBACK_IMMEDIATE);
+ }
+ else
+ {
+ l_rc = bce_request_create(&G_inband_cmd_bce_req, // Block copy request
+ &G_pba_bcde_queue, // mainstore down to SRAM
+ i_main_mem_addr, // Mainstore address
+ i_sram_addr, // SRAM start address
+ i_byte_count, // Size of copy
+ SSX_WAIT_FOREVER, // No timeout
+ (AsyncRequestCallback) inband_cmd_bce_callback,
+ NULL, // No call back args
+ ASYNC_CALLBACK_IMMEDIATE);
+ }
+
+ if (l_rc != SSX_OK) // fail to create BCE request?
+ {
+ TRAC_ERR("inband_cmd_bce_copy: Request create failure: rc=0x%08X caller=0x%04X",
+ -l_rc, i_caller_mod_id);
+ /* @
+ * @errortype
+ * @moduleid INBAND_CMD_BCE_COPY_MOD
+ * @reasoncode INBAND_CMD_ERROR
+ * @userdata1 Return code from bce_request_create()
+ * @userdata2 Caller module ID
+ * @userdata4 ERC_BCE_REQUEST_CREATE_FAILURE
+ * @devdesc Failed to create BCE request
+ */
+ inband_cmd_log_bce_error(INBAND_CMD_BCE_COPY_MOD, ERC_BCE_REQUEST_CREATE_FAILURE,
+ -l_rc, i_caller_mod_id);
+ return false;
+ }
+
+ // Schedule BCE request
+ l_rc = bce_request_schedule(&G_inband_cmd_bce_req);
+ if (l_rc != SSX_OK)
+ {
+ TRAC_ERR("inband_cmd_bce_copy: Request schedule failure: rc=0x%08X caller=0x%04X",
+ -l_rc, i_caller_mod_id);
+ /* @
+ * @errortype
+ * @moduleid INBAND_CMD_BCE_COPY_MOD
+ * @reasoncode INBAND_CMD_ERROR
+ * @userdata1 Return code from bce_request_schedule()
+ * @userdata2 Caller module ID
+ * @userdata4 ERC_BCE_REQUEST_SCHEDULE_FAILURE
+ * @devdesc Failed to schedule BCE request
+ */
+ inband_cmd_log_bce_error(INBAND_CMD_BCE_COPY_MOD, ERC_BCE_REQUEST_SCHEDULE_FAILURE,
+ -l_rc, i_caller_mod_id);
+ return false;
+ }
+
+ // Successfully scheduled request. Copy is not blocking, so need to check
+ // whether it finished later. Set flag indicating request is scheduled.
+ G_inband_cmd_req_scheduled = true;
+ return true;
+}
+
+
+// Function Specification
+//
+// Name: inband_command_check
+//
+// Description: Check for command from the inband interface
+//
+// End Function Specification
+void inband_command_check(void)
+{
+ // Only check for a new command if not currently processing an inband command
+ if (G_inband_occ_cmd_state == INBAND_OCC_CMD_NONE)
+ {
+ // Create and Schedule BCE to read minimum bytes of OCC inband command buffer in HOMER
+ memset((void*)&G_inband_cmd_min_data_bce_buff, 0x00, sizeof(inband_min_cmd_t));
+ bool i_to_main_mem = FALSE; // this request is main mem down to SRAM
+ G_inband_occ_cmd_state = INBAND_OCC_CMD_CHECK_FOR_CMD;
+ G_bce_callback_wait = 0;
+ if (inband_cmd_bce_copy(INBAND_OCC_CMD_ADDRESS_HOMER, (uint32_t)&G_inband_cmd_min_data_bce_buff,
+ INBAND_CMD_MIN_BCE_BUF_SIZE, i_to_main_mem, INBAND_CMD_CHECK_MOD))
+ {
+ // Copy succeeded. The BCE callback will handle next
+ }
+ else
+ {
+ // copy failed try again next time
+ G_inband_occ_cmd_state = INBAND_OCC_CMD_NONE;
+ }
+ }
+}
+
+// Function Specification
+//
+// Name: inband_command_handler
+//
+// Description: Command handler for inband commands this should only be called if
+// it is already known that there is an in-band command in process
+// This is checked to be called on every tick
+//
+// End Function Specification
+void inband_command_handler(void)
+{
+ uint8_t l_reason_code = ERRL_RC_INTERNAL_FAIL;
+ uint16_t l_cmd_data_len = 0;
+ uint8_t l_seq_num = 0;
+ uint8_t l_cmd_type = 0xFF;
+ uint16_t l_rsp_data_length = 0;
+ uint16_t l_bce_copy_size = 0;
+ uint8_t l_bce_padding = 0;
+ bool l_to_main_mem = TRUE; // BCE requests from here are going SRAM to main memory
+ bool l_bce_scheduled = FALSE;
+
+ // Decide what to do next for processing an in-band command
+ if(G_inband_occ_cmd_state == INBAND_OCC_CMD_START)
+ {
+ // We use the max buffer for response
+ memset((void*)&G_inband_cmd_max_data_bce_buff, 0x00, INBAND_CMD_MAX_BCE_BUF_SIZE);
+
+ // When we check for command we used the minimum bce buffer
+ l_seq_num = G_inband_cmd_min_data_bce_buff.header.seq;
+ l_cmd_type = G_inband_cmd_min_data_bce_buff.header.cmd_type;
+ l_cmd_data_len = CONVERT_UINT8_ARRAY_UINT16(G_inband_cmd_min_data_bce_buff.header.data_length[0],
+ G_inband_cmd_min_data_bce_buff.header.data_length[1]);
+
+ // if data is more than min we will need to do another BCE to read the rest of the cmd
+ if(l_cmd_data_len > INBAND_MIN_DATA_LENGTH)
+ {
+ // invalid command, currently no cmd supported is larger than min requiring 2nd BCE
+ l_reason_code = ERRL_RC_INVALID_CMD_LEN;
+ }
+ else
+ {
+ // Have the full command, process it based on command type.
+ // cmd data is in min data BCE buffer the rsp data will go in the max data BCE buffer
+ uint8_t* l_cmd_data_ptr = (uint8_t*) &G_inband_cmd_min_data_bce_buff.data;
+ uint8_t* l_rsp_data_ptr = (uint8_t*) &G_inband_cmd_max_data_bce_buff.data;
+
+ switch(l_cmd_type)
+ {
+ case CMDH_CLEAR_SENSOR_DATA:
+ l_reason_code = cmdh_clear_sensor_data(l_cmd_data_len,
+ l_cmd_data_ptr,
+ INBAND_MAX_DATA_LENGTH,
+ &l_rsp_data_length,
+ l_rsp_data_ptr);
+ break;
+
+ case CMDH_SET_PCAP_INBAND:
+ l_reason_code = cmdh_set_pcap_inband(l_cmd_data_len,
+ l_cmd_data_ptr,
+ INBAND_MAX_DATA_LENGTH,
+ &l_rsp_data_length,
+ l_rsp_data_ptr);
+ break;
+
+ case CMDH_WRITE_PSR:
+ l_reason_code = cmdh_write_psr(l_cmd_data_len,
+ l_cmd_data_ptr,
+ INBAND_MAX_DATA_LENGTH,
+ &l_rsp_data_length,
+ l_rsp_data_ptr);
+ break;
+
+ case CMDH_SELECT_SENSOR_GROUPS:
+ l_reason_code = cmdh_select_sensor_groups(l_cmd_data_len,
+ l_cmd_data_ptr,
+ INBAND_MAX_DATA_LENGTH,
+ &l_rsp_data_length,
+ l_rsp_data_ptr);
+ break;
+
+ default:
+ l_reason_code = ERRL_RC_INVALID_CMD;
+ break;
+ } // end switch
+ } // end cmd process
+
+ // fill in response header in G_inband_cmd_max_data_bce_buff
+ G_inband_cmd_max_data_bce_buff.header.flags = IN_BAND_RSP_READY_MASK;
+ G_inband_cmd_max_data_bce_buff.header.seq = l_seq_num;
+ G_inband_cmd_max_data_bce_buff.header.cmd_type = l_cmd_type;
+ G_inband_cmd_max_data_bce_buff.header.reserved_rc = l_reason_code;
+ G_inband_cmd_max_data_bce_buff.header.data_length[0] = ((uint8_t *)&l_rsp_data_length)[0];
+ G_inband_cmd_max_data_bce_buff.header.data_length[1] = ((uint8_t *)&l_rsp_data_length)[1];
+
+ // Copy the response from SRAM to main memory
+ // Determine BCE copy size, must be factor of 128
+ l_bce_copy_size = sizeof(inband_occ_cmd_header_t) + l_rsp_data_length;
+ l_bce_padding = l_bce_copy_size % 128;
+ if(l_bce_padding)
+ {
+ l_bce_copy_size += (128 - l_bce_padding);
+ }
+
+ G_bce_callback_wait = 0;
+ G_inband_occ_cmd_state = INBAND_OCC_CMD_RSP_READY;
+ l_bce_scheduled = inband_cmd_bce_copy(INBAND_OCC_RSP_ADDRESS_HOMER,
+ (uint32_t)&G_inband_cmd_max_data_bce_buff,
+ l_bce_copy_size,
+ l_to_main_mem,
+ INBAND_CMD_HANDLER_MOD);
+ if (!l_bce_scheduled)
+ {
+ // failed to copy response
+ G_inband_occ_cmd_state = INBAND_OCC_CMD_NONE;
+ }
+ else
+ {
+ TRAC_INFO("inband_command_handler: Command 0x%02X with "
+ "seq_num 0x%02X finished with RC 0x%02X",
+ l_cmd_type, l_seq_num, l_reason_code);
+ }
+
+ } // INBAND_OCC_CMD_START
+
+ else if(G_inband_occ_cmd_state == INBAND_OCC_CMD_RSP_INT)
+ {
+ // Send interrupt to indciate response is ready in main mem
+ notify_host(INTR_REASON_OPAL_SHARED_MEM_CHANGE);
+ G_inband_occ_cmd_state = INBAND_OCC_CMD_NONE;
+ }
+
+ else if( (G_inband_occ_cmd_state == INBAND_OCC_CMD_CHECK_FOR_CMD) ||
+ (G_inband_occ_cmd_state == INBAND_OCC_CMD_RSP_READY) )
+ {
+ // Waiting for BCE to finish, these states are handled by BCE callback
+ // if the callback is never called (BCE failure) for a max wait log error
+ G_bce_callback_wait++;
+ if(G_bce_callback_wait == MAX_TICS_INBAND_BCE_CALLBACK_WAIT)
+ {
+ TRAC_ERR("inband_command_handler: Timeout waiting for BCE callback cmd state 0x%02X",
+ G_inband_occ_cmd_state);
+ G_inband_occ_cmd_state = INBAND_OCC_CMD_NONE;
+ /* @
+ * @errortype
+ * @moduleid INBAND_CMD_HANDLER_MOD
+ * @reasoncode INBAND_CMD_ERROR
+ * @userdata1 Inband command state
+ * @userdata2 Caller module ID
+ * @userdata4 ERC_BCE_REQ_CALLBACK_TIMEOUT
+ * @devdesc Timeout waiting for BCE callback
+ */
+ inband_cmd_log_bce_error(INBAND_CMD_HANDLER_MOD, ERC_BCE_REQ_CALLBACK_TIMEOUT,
+ G_inband_occ_cmd_state, INBAND_CMD_HANDLER_MOD);
+ }
+ }
+
+ else if(G_inband_occ_cmd_state == INBAND_OCC_INVALID_BCE_CALLBACK)
+ {
+ // BCE callback was called with invalid state, trace now and set state to none
+ static bool L_traced_bce_bad_state = FALSE;
+ if (!L_traced_bce_bad_state)
+ {
+ TRAC_ERR("inband_command_handler: inband_cmd_bce_callback detected invalid state %u",
+ G_inband_occ_bce_saved_state);
+ L_traced_bce_bad_state = TRUE;
+ }
+ G_inband_occ_cmd_state = INBAND_OCC_CMD_NONE;
+ G_inband_occ_bce_saved_state = INBAND_OCC_CMD_NONE;
+ }
+
+ else
+ {
+ // Invalid state
+ static bool L_traced_bad_state = FALSE;
+ if (!L_traced_bad_state)
+ {
+ TRAC_ERR("inband_command_handler: Called with invalid state %u",
+ G_inband_occ_cmd_state);
+ L_traced_bad_state = TRUE;
+ }
+ G_inband_occ_cmd_state = INBAND_OCC_CMD_NONE;
+ }
+}
diff --git a/src/occ_405/sensor/sensor_inband_cmd.h b/src/occ_405/sensor/sensor_inband_cmd.h
new file mode 100644
index 0000000..4e39f84
--- /dev/null
+++ b/src/occ_405/sensor/sensor_inband_cmd.h
@@ -0,0 +1,112 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/occ_405/sensor/sensor_inband_cmd.h $ */
+/* */
+/* OpenPOWER OnChipController Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2017,2017 */
+/* [+] 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 _SENSOR_INBAND_CMD_H
+#define _SENSOR_INBAND_CMD_H
+
+/**
+ * @file sensor_inband_cmd.h
+ *
+ * This file declares the functions and global variables for supporting the inband
+ * command protocol defined in the OCC Firmware Interface spec
+ *
+ */
+
+//******************************************************************************
+// Defines/Structs/Globals
+//******************************************************************************
+
+// States of inband OCC command processing
+typedef enum
+{
+ INBAND_OCC_CMD_NONE = 0x00, // No inband command in process
+ INBAND_OCC_CMD_CHECK_FOR_CMD = 0x01, // Check for cmd when BCE read finishes
+ INBAND_OCC_CMD_START = 0x02, // Start processing the command
+ INBAND_OCC_CMD_RSP_READY = 0x03, // Response ready
+ INBAND_OCC_CMD_RSP_INT = 0x04, // Send Response Interrupt
+ INBAND_OCC_INVALID_BCE_CALLBACK = 0x05, // BCE callback called with invalid OCC cmd state
+} INBAND_OCC_CMD_STATE;
+
+// Current state of inband OCC command processing
+extern volatile uint8_t G_inband_occ_cmd_state;
+// Last state saved for error handling
+extern volatile uint8_t G_inband_occ_bce_saved_state;
+
+#define MAX_TICS_INBAND_BCE_CALLBACK_WAIT 0x03
+#define IN_BAND_CMD_READY_MASK 0x80
+#define IN_BAND_RSP_IN_PROGRESS_MASK 0x02
+#define IN_BAND_RSP_READY_MASK 0x01
+
+typedef struct __attribute__ ((packed))
+{
+ uint8_t flags;
+ uint8_t seq;
+ uint8_t cmd_type;
+ uint8_t reserved_rc; // as a command reserved, as a response RC
+ uint8_t data_length[2];
+} inband_occ_cmd_header_t;
+
+// Data Size is Block Copy Engine dependent, 128 min to 4kB max
+#define INBAND_CMD_MIN_BCE_BUF_SIZE 128
+#define INBAND_CMD_MAX_BCE_BUF_SIZE 4096
+#define INBAND_MAX_DATA_LENGTH INBAND_CMD_MAX_BCE_BUF_SIZE - sizeof(inband_occ_cmd_header_t)
+#define INBAND_MIN_DATA_LENGTH INBAND_CMD_MIN_BCE_BUF_SIZE - sizeof(inband_occ_cmd_header_t)
+
+typedef struct __attribute__ ((packed))
+{
+ inband_occ_cmd_header_t header;
+ // Data bytes
+ uint8_t data[INBAND_MIN_DATA_LENGTH];
+}inband_min_cmd_t;
+
+typedef struct __attribute__ ((packed))
+{
+ inband_occ_cmd_header_t header;
+ // Data bytes
+ uint8_t data[INBAND_MAX_DATA_LENGTH];
+}inband_max_cmd_t;
+
+//******************************************************************************
+// Function Prototypes
+//******************************************************************************
+
+/**
+ * Check for a command from the inband command/response interface
+ *
+ * There are inband commands to select sensors to write to main memory and
+ * clear sensors min/max by user
+ *
+ * This function is called from amec_slv_common_tasks_post()
+ */
+void inband_command_check(void);
+
+/**
+ * Handle a command from the inband command/response interface
+ *
+ * This function is called from amec_slv_substate_6_x
+ */
+void inband_command_handler(void);
+
+#endif // _SENSOR_INBAND_CMD_H
diff --git a/src/occ_405/sensor/sensor_main_memory.h b/src/occ_405/sensor/sensor_main_memory.h
index f9cd29f..f989e13 100644
--- a/src/occ_405/sensor/sensor_main_memory.h
+++ b/src/occ_405/sensor/sensor_main_memory.h
@@ -302,5 +302,4 @@ void main_mem_sensors_update(void);
*/
void main_mem_sensors_set_enabled(AMEC_SENSOR_TYPE i_sensor_type, bool i_enabled);
-
#endif // _SENSOR_MAIN_MEMORY_H
diff --git a/src/occ_405/sensor/sensor_service_codes.h b/src/occ_405/sensor/sensor_service_codes.h
index 397a2d5..f511edf 100755
--- a/src/occ_405/sensor/sensor_service_codes.h
+++ b/src/occ_405/sensor/sensor_service_codes.h
@@ -44,6 +44,12 @@ enum occSensorModuleId
MM_SENSORS_WRITE_NAMES_MOD = SNSR_COMP_ID | 0x16,
MM_SENSORS_WRITE_READINGS_MOD = SNSR_COMP_ID | 0x17,
MM_SENSORS_VALIDATE_READINGS_MOD = SNSR_COMP_ID | 0x18,
+
+ // Inband commands
+ INBAND_CMD_IS_BCE_REQ_IDLE_MOD = SNSR_COMP_ID | 0x20,
+ INBAND_CMD_BCE_COPY_MOD = SNSR_COMP_ID | 0x21,
+ INBAND_CMD_HANDLER_MOD = SNSR_COMP_ID | 0x22,
+ INBAND_CMD_CHECK_MOD = SNSR_COMP_ID | 0x23,
};
#endif /* #ifndef _SENSOR_SERVICE_CODES_H_ */
diff --git a/src/occ_405/topfiles.mk b/src/occ_405/topfiles.mk
index 61f9348..ca38569 100644
--- a/src/occ_405/topfiles.mk
+++ b/src/occ_405/topfiles.mk
@@ -93,6 +93,7 @@ TOP-C-SOURCES = amec/amec_analytics.c \
rtls/rtls_tables.c \
rtls/rtls.c \
scom.c \
+ sensor/sensor_inband_cmd.c \
sensor/sensor_info.c \
sensor/sensor_main_memory.c \
sensor/sensor_query_list.c \
OpenPOWER on IntegriCloud