summaryrefslogtreecommitdiffstats
path: root/src/occ_405/cmdh/cmdh_snapshot.c
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/cmdh/cmdh_snapshot.c
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/cmdh/cmdh_snapshot.c')
-rwxr-xr-xsrc/occ_405/cmdh/cmdh_snapshot.c476
1 files changed, 476 insertions, 0 deletions
diff --git a/src/occ_405/cmdh/cmdh_snapshot.c b/src/occ_405/cmdh/cmdh_snapshot.c
new file mode 100755
index 0000000..5d73174
--- /dev/null
+++ b/src/occ_405/cmdh/cmdh_snapshot.c
@@ -0,0 +1,476 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/occ_405/cmdh/cmdh_snapshot.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_snapshot.h"
+#include "cmdh_service_codes.h"
+#include "cmdh_fsp_cmds.h"
+#include "dcom.h"
+#include "threadSch.h"
+
+// Array of snapshot buffers to return to TMGT
+cmdh_snapshot_buffer_t g_cmdh_snapshot_array[CMDH_SNAPSHOT_MAX];
+
+// Current snapshot id.
+uint8_t g_cmdh_snapshot_cur_id = 0;
+
+// Current index into array for newest entry
+uint8_t g_cmdh_snapshot_cur_index = CMDH_SNAPSHOT_DEFAULT_CUR_INDEX;
+
+// This global is set to TRUE by default to get a clean start, and is also
+// set to TRUE in case of a resync request.
+bool g_cmdh_snapshot_reset = TRUE;
+
+SsxTimer G_snapshotTimer;
+
+// Max, min power, and accumulated frequency average over 30seconds
+pwr250us_over30sec_t g_pwr250us_over30sec;
+
+// Function Specification
+//
+// Name: cmdh_snapshot_find_oldest_newest
+//
+// Description: Returns the index of the oldest and newest snapshot in the
+// g_cmdh_snapshot_array.
+//
+// End Function Specification
+
+VOID cmdh_snapshot_find_oldest_newest(uint8_t *o_oldest,
+ uint8_t *o_newest)
+{
+ uint8_t l_index = 0;
+
+ do
+ {
+ // We wont be called if no snapshots are available so we know at least
+ // one is available
+
+ // If our current index is 0, it's id is 0, and the last entry has
+ // an id of 0 then we know we haven't wrapped yet since 2 entries
+ // can not have the same current_id and 0 was what's written in
+ // as an initializer
+ if((g_cmdh_snapshot_cur_index == 0) &&
+ (g_cmdh_snapshot_array[0].current_id == 0) &&
+ (g_cmdh_snapshot_array[CMDH_SNAPSHOT_MAX_INDEX].current_id == 0))
+ {
+ TRAC_INFO("cmdh_snapshot_find_oldest_newest: Entry 0 is the oldest and newest");
+ *o_oldest = 0;
+ *o_newest = 0;
+ break;
+ }
+
+ // Newest will be g_cmdh_snapshot_cur_index
+ *o_newest = g_cmdh_snapshot_cur_index;
+
+ // n = newest, o=oldest, x=used, _=empty
+ //________________________________________
+ //|x|x|x|x|x|x|x|x|x|x|x|n|o|x|x|x|x|x|x|x|
+ // Start by assuming that the oldest snapshot is right after the newest.
+ l_index = g_cmdh_snapshot_cur_index+1;
+
+ //________________________________________
+ //|o|x|x|x|x|x|x|x|x|x|x|x|x|x|x|x|x|x|x|n|
+ //Check on whether the newest was at the end of the array. That would
+ //mean that the oldest entry is at index 0.
+ if(l_index > CMDH_SNAPSHOT_MAX_INDEX)
+ {
+ l_index = 0;
+ }
+ //________________________________________
+ //|o|x|x|x|x|x|x|x|x|x|x|n|_|_|_|_|_|_|_|_|
+ //Check on whether the last entry in the array is empty and so is the one
+ //right after the newest entry. If so, that means oldest is at index 0 since
+ //we haven't wrapped yet.
+ else if((g_cmdh_snapshot_array[l_index].current_id == 0) &&
+ (g_cmdh_snapshot_array[CMDH_SNAPSHOT_MAX_INDEX].current_id == 0))
+ {
+ l_index = 0;
+ }
+ // else oldest is just equal to l_index
+ *o_oldest = l_index;
+
+ }while(FALSE);
+
+
+ return;
+}
+
+
+// Function Specification
+//
+// Name: cmdh_snapshot_buffer_nonite
+//
+// Description: Returns the requested snapshot buffer to tmgt.
+//
+// End Function Specification
+ERRL_RC cmdh_snapshot_buffer_nonite(const cmdh_fsp_cmd_t *i_cmd_ptr,
+ cmdh_fsp_rsp_t *o_rsp_ptr)
+{
+ cmdh_get_snapshot_query_t *l_cmd_ptr = (cmdh_get_snapshot_query_t *) i_cmd_ptr;
+ ERRL_RC l_rc = ERRL_RC_SUCCESS;
+ cmdh_get_snapshot_resp_v0_t *l_rsp_ptr = (cmdh_get_snapshot_resp_v0_t*) o_rsp_ptr;
+ uint8_t l_newest = 0;
+ uint8_t l_oldest = 0;
+ uint8_t l_req_idx = 0;
+ uint8_t i = 0;
+
+ do
+ {
+
+ // Check case where there are no snapshot buffers available.
+ if (g_cmdh_snapshot_cur_index == CMDH_SNAPSHOT_DEFAULT_CUR_INDEX)
+ {
+ TRAC_INFO("cmdh_snapshot_buffer_nonite: No snapshot buffer available.");
+ break;
+ }
+
+ // Determine newest and oldest buffer.
+ cmdh_snapshot_find_oldest_newest(&l_oldest, &l_newest);
+
+ l_rsp_ptr->oldest_id = g_cmdh_snapshot_array[l_oldest].current_id;
+ l_rsp_ptr->newest_id = g_cmdh_snapshot_array[l_newest].current_id;
+
+ // Determine which snapshot buffer is requested by TMGT
+ if (l_cmd_ptr->getnewest)
+ {
+ l_req_idx = l_newest;
+ }
+ else
+ {
+ // Find requested snapshot, or if not available grab latest.
+ for (i =0; i< CMDH_SNAPSHOT_MAX; i++)
+ {
+ if (g_cmdh_snapshot_array[i].current_id == l_cmd_ptr->requested_id)
+ {
+ l_req_idx = i;
+ break;
+ }
+ }
+
+ if (i == CMDH_SNAPSHOT_MAX)
+ {
+ TRAC_INFO("cmdh_snapshot_buffer_nonite: Requested buffer:%u not found so sending back %u",
+ l_cmd_ptr->requested_id, l_rsp_ptr->newest_id);
+ l_req_idx = l_newest;
+ }
+ }
+
+ // Copy the requested snapshot buffer into the response buffer.
+ memcpy(&(l_rsp_ptr->snapshot),
+ &(g_cmdh_snapshot_array[l_req_idx]),
+ sizeof(cmdh_snapshot_buffer_t));
+
+ // Calculate returned data size.
+ uint16_t l_size = 2 + sizeof(cmdh_snapshot_buffer_t); // 2 bytes for newest and oldest + size of snapshots.
+ o_rsp_ptr->data_length[0] = ((uint8_t *)&l_size)[0];
+ o_rsp_ptr->data_length[1] = ((uint8_t *)&l_size)[1];
+
+
+ } while (0);
+
+ return(l_rc);
+}
+
+// Function Specification
+//
+// Name: cmdh_get_snapshot_buffer
+//
+// Description: Returns requested snapshot buffer to tmgt when requested.
+//
+// End Function Specification
+errlHndl_t cmdh_get_snapshot_buffer(const cmdh_fsp_cmd_t * i_cmd_ptr,
+ cmdh_fsp_rsp_t * o_rsp_ptr)
+{
+ cmdh_get_snapshot_query_t *l_cmd_ptr = (cmdh_get_snapshot_query_t *) i_cmd_ptr;
+ ERRL_RC l_rc = ERRL_RC_SUCCESS;
+ uint16_t l_query_sz = 0;
+ errlHndl_t l_err = NULL;
+
+ do
+ {
+
+
+ // Command is only supported on Master OCC
+ if (G_occ_role == OCC_SLAVE)
+ {
+ TRAC_ERR("cmdh_get_snapshot_buffer: Get snapshot buffer command not supported on Slave OCCs!");
+ l_rc = ERRL_RC_INVALID_CMD;
+ break;
+ }
+
+ // Function Inputs Sanity Check
+ if( (NULL == i_cmd_ptr) || (NULL == o_rsp_ptr) )
+ {
+ TRAC_ERR("cmdh_get_snapshot_buffer: Received invalid inputs.");
+ l_rc = ERRL_RC_INTERNAL_FAIL;
+ break;
+ }
+
+ l_query_sz = CMDH_DATALEN_FIELD_UINT16(i_cmd_ptr);
+ // Command Length Check. Should have 4 bytes total
+ if(l_query_sz != CMDH_GET_SNAPSHOT_QUERY_DATALEN)
+ {
+ TRAC_ERR("cmdh_get_snapshot_buffer: Received an invalid packet size. Expecting 4 bytes, received:%i",
+ l_query_sz);
+ l_rc = ERRL_RC_INVALID_CMD_LEN;
+ break;
+ }
+
+ // Call appropriate function based on version.
+ switch (l_cmd_ptr->version)
+ {
+ case CMDH_GET_SNAPSHOT_NONITE_VERSION:
+ l_rc = cmdh_snapshot_buffer_nonite(i_cmd_ptr, o_rsp_ptr);
+ break;
+
+ case CMDH_GET_SNAPSHOT_ITE_VERSION:
+ default:
+ TRAC_ERR("cmdh_get_snapshot_buffer: Version %i cmd is not supported.", l_cmd_ptr->version);
+ l_rc = ERRL_RC_INVALID_DATA;
+ break;
+ }
+
+ } while(0);
+
+ if (l_rc)
+ {
+ // Build Error Response packet
+ cmdh_build_errl_rsp(i_cmd_ptr, o_rsp_ptr, l_rc, &l_err);
+ }
+
+ return l_err;
+}
+
+
+#define CMDH_SNAPSHOT_SYNC_DATA_SIZE 1
+// Function Specification
+//
+// Name: cmdh_snapshot_sync
+//
+// Description: Resets the snapshot buffer array and starts a new snapshot buffer from time 0.
+//
+// End Function Specification
+errlHndl_t cmdh_snapshot_sync(const cmdh_fsp_cmd_t * i_cmd_ptr,
+ cmdh_fsp_rsp_t * o_rsp_ptr)
+{
+ cmdh_snapshot_sync_query_t *l_cmd_ptr = (cmdh_snapshot_sync_query_t *) i_cmd_ptr;
+ cmdh_snapshot_sync_resp_t *l_resp_ptr = (cmdh_snapshot_sync_resp_t *) o_rsp_ptr;
+ errlHndl_t l_err = NULL;
+ uint8_t l_query_sz = 0;
+ ERRL_RC l_rc = 0;
+
+ do
+ {
+ l_query_sz = CMDH_DATALEN_FIELD_UINT16(i_cmd_ptr);
+ // Verify query data size
+ if(l_query_sz != CMDH_SNAPSHOT_SYNC_DATA_SIZE)
+ {
+ TRAC_ERR("cmdh_snapshot_sync: Received an invalid packet size. Expecting 1 byte, received:%i",
+ l_query_sz);
+ l_rc = ERRL_RC_INVALID_CMD_LEN;
+ break;
+ }
+
+ l_cmd_ptr = (cmdh_snapshot_sync_query_t *)i_cmd_ptr;
+
+ // Check received packet version
+ if (CMDH_SNAPSHOT_SYNC_VERSION != l_cmd_ptr->version)
+ {
+ TRAC_ERR("cmdh_snapshot_sync: Version %i cmd is not supported.", l_cmd_ptr->version);
+ l_rc = ERRL_RC_INVALID_DATA;
+ break;
+ }
+
+ // Set the global reset flag, that will cause all saved data to be cleared in the
+ // next callback that is done every 30 seconds via a timer.
+ g_cmdh_snapshot_reset = TRUE;
+
+ // Reset current index to stop any possible calls from tmgt to get snapshot buffers.
+ g_cmdh_snapshot_cur_index = CMDH_SNAPSHOT_DEFAULT_CUR_INDEX;
+
+ // Reset timer and start counting from now. This will cause a call to the snapshot_callback
+ // function below which will reset the other globals based on the fact that g_cmdh_snapshot_reset
+ // is set to true.
+ l_rc = ssx_timer_schedule(&G_snapshotTimer, 0, SSX_SECONDS(30));
+ if (l_rc != SSX_OK)
+ {
+ TRAC_ERR("cmdh_snapshot_sync: reseting the snapshot timer failed.");
+ break;
+ }
+
+ TRAC_INFO("cmdh_snapshot_sync: Snapshot buffer has been reset!");
+
+ l_resp_ptr->data_length[0] = 0;
+ l_resp_ptr->data_length[1] = 0;
+ l_resp_ptr->rc = 0;
+ }while(FALSE);
+
+ if (l_rc)
+ {
+ // Build Error Response packet
+ cmdh_build_errl_rsp(i_cmd_ptr, o_rsp_ptr, l_rc, &l_err);
+ }
+ return(l_err);
+}
+
+// Function Specification
+//
+// Name: cmdh_
+//
+// Description: Called from timer every 30seconds to store cimp data into
+// an array of 20 cimp snapshots. Then it triggers the generation
+// of a new snapshot in the g_cmdh_sna
+//
+// End Function Specification
+void cmdh_snapshot_callback(void * arg)
+{
+ static cmdh_snapshot_cimp_entry_t L_cim_buf[CMDH_CIMP_MAX]; // Holds the earlier cim data snapshots.
+ static uint8_t L_cim_seq_number = 0; // Holds the next cim seq number to be used.
+ static uint32_t L_prev_pwr_accum = 0; // Holds the previous power sensor accumulator
+ static uint32_t L_prev_pwr_update_tag = 0; // Holds the previous power sensor update tag.
+
+ uint32_t l_pwr_accum = AMECSENSOR_PTR(PWR250US)->accumulator;
+ uint32_t l_pwr_update_tag = AMECSENSOR_PTR(PWR250US)->update_tag;
+ uint32_t l_avg_pwr = 0;
+ uint32_t l_min_pwr = g_pwr250us_over30sec.min;
+ uint32_t l_max_pwr = g_pwr250us_over30sec.max;
+ uint32_t l_freq_accum = g_pwr250us_over30sec.freqaAccum;
+ uint32_t l_freq_cnt = g_pwr250us_over30sec.count;
+ uint16_t l_avg_freq = 0;
+
+ cmdh_snapshot_cimp_entry_t l_cim_buf_temp[CMDH_CIMP_MAX - 1];
+ cmdh_snapshot_buffer_t l_30s_snapshot; // Used to temporarily hold new snapshot data.
+
+
+ // Clear data that is calculated every 250us to prep for next callback in 30seconds.
+ // Reset max and min over 30 seconds.
+ memset(&g_pwr250us_over30sec,0,sizeof(g_pwr250us_over30sec));
+
+ if (g_cmdh_snapshot_reset)
+ {
+ TRAC_INFO("cmdh_snapshot_callback: Initializing snapshot buffer and data.");
+
+ memset(g_cmdh_snapshot_array, 0, sizeof(g_cmdh_snapshot_array));
+ g_cmdh_snapshot_cur_id = 0;
+ memset(L_cim_buf,0,sizeof(cmdh_snapshot_buffer_t));
+ L_cim_seq_number = 0;
+ L_prev_pwr_accum = l_pwr_accum;
+ L_prev_pwr_update_tag = l_pwr_update_tag;
+ // Clear reset flag. - This should be the only place that clears it.
+ g_cmdh_snapshot_reset = FALSE;
+ g_cmdh_snapshot_cur_index = CMDH_SNAPSHOT_DEFAULT_CUR_INDEX;
+ }
+ else
+ {
+
+ uint32_t l_pwr_accum_diff = 0;
+ uint32_t l_pwr_uptag_diff = 0;
+
+ // Calculate the accumulator difference.
+ if(l_pwr_accum >= L_prev_pwr_accum)
+ {
+ l_pwr_accum_diff = l_pwr_accum - L_prev_pwr_accum;
+ }
+ else
+ {
+ l_pwr_accum_diff = l_pwr_accum + (~L_prev_pwr_accum);
+ }
+
+ // Calculate the update tag difference.
+ if(l_pwr_update_tag >= L_prev_pwr_update_tag)
+ {
+ l_pwr_uptag_diff = l_pwr_update_tag - L_prev_pwr_update_tag;
+ }
+ else if(l_pwr_update_tag < L_prev_pwr_update_tag) // accum must have wrapped.
+ {
+ l_pwr_uptag_diff = l_pwr_update_tag + (~L_prev_pwr_update_tag);
+ }
+
+ // Make sure we don't divide by 0
+ if(l_pwr_uptag_diff == 0)
+ {
+ // This should never happen.
+ TRAC_INFO("cmdh_snapshot_callback: update tag difference should not be 0. current:%i, previous:%i.",
+ l_pwr_update_tag, L_prev_pwr_update_tag);
+ l_avg_pwr = 0;
+ }
+ else
+ {
+ // Calculate average power since previous callback.
+ l_avg_pwr = l_pwr_accum_diff / l_pwr_uptag_diff;
+ }
+
+ if(l_freq_cnt == 0)
+ {
+ // This should never happen.
+ TRAC_INFO("cmdh_snapshot_callback: No frequency data has been accumulated. Returning 0 for frequency. count:%i.",
+ l_freq_cnt);
+ l_avg_freq = 0;
+ }
+ else
+ {
+ // Calculate average frequency of all Cores for the whole Node (all OCCs)
+ l_avg_freq = (uint16_t)(l_freq_accum / l_freq_cnt);
+ }
+
+ // Save power sensor accumulator and update tag values for next callback.
+ L_prev_pwr_accum = l_pwr_accum;
+ L_prev_pwr_update_tag = l_pwr_update_tag;
+
+ // Append the new cim buffer entry to the front of the local static array of cim buffers.
+ memcpy(l_cim_buf_temp, L_cim_buf, sizeof(cmdh_snapshot_cimp_entry_t) * (CMDH_CIMP_MAX - 1));
+
+ L_cim_buf[0].seq_number = L_cim_seq_number;
+ memcpy(L_cim_buf[0].avg_dc, &l_avg_pwr,sizeof(L_cim_buf[0].avg_dc));
+ memcpy(L_cim_buf[0].min_dc, &l_min_pwr,sizeof(L_cim_buf[0].min_dc));
+ memcpy(L_cim_buf[0].max_dc, &l_max_pwr,sizeof(L_cim_buf[0].max_dc));
+ memcpy(L_cim_buf[0].avg_cpu_freq, &l_avg_freq,sizeof(L_cim_buf[0].avg_cpu_freq));
+
+ memcpy(&(L_cim_buf[1]), l_cim_buf_temp, sizeof(cmdh_snapshot_cimp_entry_t) * (CMDH_CIMP_MAX - 1));
+
+ // Populate the local 30s snapshot buffer before writing it out to the global array. Reason is
+ // we don't want the buffer data to be read by tmgt cmd while we are filling it.
+
+ // Copy cim data to snapshot buffer.
+ memcpy(l_30s_snapshot.cim, L_cim_buf, sizeof(cmdh_snapshot_cimp_entry_t) * CMDH_CIMP_MAX);
+ l_30s_snapshot.current_id = g_cmdh_snapshot_cur_id;
+
+ // Increment current index to signify that we are going to add a new snapshot.
+ g_cmdh_snapshot_cur_index++;
+ if (g_cmdh_snapshot_cur_index > CMDH_SNAPSHOT_MAX_INDEX)
+ {
+ // Wrap back to start
+ g_cmdh_snapshot_cur_index = 0;
+ }
+
+ // Write buffer to the current index in the global array g_cmdh_snapshot_array.
+ memcpy(&(g_cmdh_snapshot_array[g_cmdh_snapshot_cur_index]),&l_30s_snapshot, sizeof(cmdh_snapshot_buffer_t));
+
+ // Increment snapshot id.
+ g_cmdh_snapshot_cur_id++;
+
+ // Increment sequence count.
+ L_cim_seq_number ++;
+ }
+}
OpenPOWER on IntegriCloud