// Function Specification // // Name: cmdh_mnfg_read_pstate_table // // Description: This function handles the manufacturing command to read // the generated Pstate table from main memory 3K blocks at a time // // End Function Specification uint8_t cmdh_mnfg_read_pstate_table(const cmdh_fsp_cmd_t * i_cmd_ptr, cmdh_fsp_rsp_t * o_rsp_ptr) { uint8_t l_rc = ERRL_RC_SUCCESS; uint16_t l_datalength = 0; uint16_t l_resp_data_length = 0; uint32_t block_offset = 0; uint32_t main_mem_address = 0; int l_ssxrc = SSX_OK; mnfg_read_pstate_table_cmd_t *l_cmd_ptr = (mnfg_read_pstate_table_cmd_t*) i_cmd_ptr; do { // Check command packet data length l_datalength = CMDH_DATALEN_FIELD_UINT16(i_cmd_ptr); if(l_datalength != (sizeof(mnfg_read_pstate_table_cmd_t) - sizeof(cmdh_fsp_cmd_header_t))) { TRAC_ERR("cmdh_mnfg_read_pstate_table: incorrect data length. exp[%d] act[%d]", (sizeof(mnfg_read_pstate_table_cmd_t) - sizeof(cmdh_fsp_cmd_header_t)), l_datalength); l_rc = ERRL_RC_INVALID_CMD_LEN; break; } // Process request if(l_cmd_ptr->request == MFG_PSTATE_READ_REQUEST_QUERY) { memcpy(&o_rsp_ptr->data[0], &G_pgpe_header.generated_pstate_table_homer_offset, 4); memcpy(&o_rsp_ptr->data[4], &G_pgpe_header.generated_pstate_table_length, 4); l_resp_data_length = MFG_PSTATE_READ_QUERY_RSP_SIZE; TRAC_INFO("cmdh_mnfg_read_pstate_table: Query table memory offset[0x%08x] table length[%d]", G_pgpe_header.generated_pstate_table_homer_offset, G_pgpe_header.generated_pstate_table_length); break; } // Calculate the starting main memory address for block to read block_offset = MFG_PSTATE_READ_MAX_RSP_SIZE * l_cmd_ptr->request; if(block_offset > G_pgpe_header.generated_pstate_table_length) { TRAC_ERR("cmdh_mnfg_read_pstate_table: Block request %d out of range. Pstate Table size %d", l_cmd_ptr->request, G_pgpe_header.generated_pstate_table_length); l_rc = ERRL_RC_INVALID_DATA; break; } main_mem_address = G_pgpe_header.generated_pstate_table_homer_offset + block_offset; // Copy Pstate table from main memory to SRAM // Set up a copy request l_ssxrc = bce_request_create(&G_mfg_pba_request, // block copy object &G_pba_bcde_queue, // mainstore to sram copy engine main_mem_address, // mainstore address (uint32_t)&G_mfg_read_pstate_table, // sram starting address sizeof(mfg_read_pstate_table_t), // size of copy SSX_SECONDS(1), // timeout NULL, // no call back NULL, // no call back arguments ASYNC_REQUEST_BLOCKING); // blocking request if(l_ssxrc != SSX_OK) { TRAC_ERR("cmdh_mnfg_read_pstate_table: BCDE request create failure rc=[%08X]", -l_ssxrc); l_rc = ERRL_RC_INTERNAL_FAIL; break; } // Do actual copying l_ssxrc = bce_request_schedule(&G_mfg_pba_request); if(l_ssxrc != SSX_OK) { TRAC_ERR("cmdh_mnfg_read_pstate_table: BCE request schedule failure rc=[%08X]", -l_ssxrc); l_rc = ERRL_RC_INTERNAL_FAIL; break; } // Determine the rsp data length l_resp_data_length = MFG_PSTATE_READ_MAX_RSP_SIZE; if((block_offset + MFG_PSTATE_READ_MAX_RSP_SIZE) > G_pgpe_header.generated_pstate_table_length) { l_resp_data_length = G_pgpe_header.generated_pstate_table_length - block_offset; } // Copy to response buffer memcpy(o_rsp_ptr->data, &G_mfg_read_pstate_table, l_resp_data_length); TRAC_INFO("cmdh_mnfg_read_pstate_table: Read from main memory[0x%08x] block offset[%d] length[%d]", main_mem_address, block_offset, l_resp_data_length); }while(0); // Populate the response data header G_rsp_status = l_rc; o_rsp_ptr->data_length[0] = ((uint8_t *)&l_resp_data_length)[0]; o_rsp_ptr->data_length[1] = ((uint8_t *)&l_resp_data_length)[1]; return l_rc; }
// Function Specification // // Name: cmdh_mnfg_request_quad_pstate // // Description: This function handles the manufacturing command to request // a Pstate per Quad. // // End Function Specification uint8_t cmdh_mnfg_request_quad_pstate(const cmdh_fsp_cmd_t * i_cmd_ptr, cmdh_fsp_rsp_t * o_rsp_ptr) { uint8_t l_rc = ERRL_RC_SUCCESS; uint16_t l_datalength = 0; uint16_t l_resp_data_length = 0; uint8_t l_pmin = 0xFF; uint8_t l_pmax = 0xFF; uint8_t l_pstate_request = 0xFF; uint8_t l_quad = 0; mnfg_quad_pstate_cmd_t *l_cmd_ptr = (mnfg_quad_pstate_cmd_t*) i_cmd_ptr; mnfg_quad_pstate_rsp_t *l_rsp_ptr = (mnfg_quad_pstate_rsp_t*) o_rsp_ptr; do { if(!IS_OCC_STATE_ACTIVE()) { TRAC_ERR("cmdh_mnfg_request_quad_pstate: OCC must be active to request pstate"); l_rc = ERRL_RC_INVALID_STATE; break; } if(G_sysConfigData.system_type.kvm) { TRAC_ERR("cmdh_mnfg_request_quad_pstate: Must be PowerVM to request pstate"); l_rc = ERRL_RC_INVALID_CMD; break; } // Check command packet data length l_datalength = CMDH_DATALEN_FIELD_UINT16(i_cmd_ptr); if(l_datalength != (sizeof(mnfg_quad_pstate_cmd_t) - sizeof(cmdh_fsp_cmd_header_t))) { TRAC_ERR("cmdh_mnfg_request_quad_pstate: incorrect data length. exp[%d] act[%d]", (sizeof(mnfg_quad_pstate_cmd_t) - sizeof(cmdh_fsp_cmd_header_t)), l_datalength); l_rc = ERRL_RC_INVALID_CMD_LEN; break; } // Check version if(l_cmd_ptr->version != MFG_QUAD_PSTATE_VERSION) { TRAC_ERR("cmdh_mnfg_request_quad_pstate: incorrect version. exp[%d] act[%d]", MFG_QUAD_PSTATE_VERSION, l_cmd_ptr->version); l_rc = ERRL_RC_INVALID_DATA; break; } // only allow a Pstate within the current range based on mode l_pmin = proc_freq2pstate(g_amec->sys.fmin); l_pmax = proc_freq2pstate(g_amec->sys.fmax); // Process each quad Pstate request, clip any request to min/max // 0xFF has special meaning that OCC is in control for(l_quad = 0; l_quad < MAXIMUM_QUADS; l_quad++) { l_pstate_request = l_cmd_ptr->quad_pstate_in[l_quad]; if(l_pstate_request != 0xFF) { // pmin is lowest frequency corresponding to highest pState value if(l_pstate_request > l_pmin) l_pstate_request = l_pmin; // pmax is highest frequency corresponding to lowest pState value else if(l_pstate_request < l_pmax) l_pstate_request = l_pmax; } // save the quad pState request for amec and return in rsp data g_amec->mnfg_parms.quad_pstate[l_quad] = l_pstate_request; l_rsp_ptr->quad_pstate_out[l_quad] = l_pstate_request; TRAC_INFO("cmdh_mnfg_request_quad_pstate: Quad %d Pstate in = 0x%02x Pstate out = 0x%02x", l_quad, l_cmd_ptr->quad_pstate_in[l_quad], l_rsp_ptr->quad_pstate_out[l_quad]); } }while(0); // Populate the response data header G_rsp_status = l_rc; l_resp_data_length = sizeof(mnfg_quad_pstate_rsp_t) - sizeof(cmdh_fsp_rsp_header_t); l_rsp_ptr->data_length[0] = ((uint8_t *)&l_resp_data_length)[0]; l_rsp_ptr->data_length[1] = ((uint8_t *)&l_resp_data_length)[1]; return l_rc; }
// Function Specification // // Name: cmdh_mnfg_get_sensor // // Description: Returns a list of selected sensors // // End Function Specification uint8_t cmdh_mnfg_get_sensor(const cmdh_fsp_cmd_t * i_cmd_ptr, cmdh_fsp_rsp_t * o_rsp_ptr) { uint8_t l_rc = ERRL_RC_SUCCESS; uint16_t l_gsid; uint16_t l_resp_data_length = 0; uint16_t l_datalength; uint16_t l_num_of_sensors = 1; cmdh_mfg_get_sensor_query_t *l_cmd_ptr = (cmdh_mfg_get_sensor_query_t*) i_cmd_ptr; cmdh_mfg_get_sensor_resp_t *l_resp_ptr = (cmdh_mfg_get_sensor_resp_t*) o_rsp_ptr; sensor_info_t l_sensor_info; errlHndl_t l_err = NULL; sensor_t* l_sensor_ptr; do { // Do sanity check on the function inputs if ((NULL == i_cmd_ptr) || (NULL == o_rsp_ptr)) { TRAC_ERR("cmdh_mnfg_get_sensor: invalid pointers. cmd[0x%08x] rsp[0x%08x]", (uint32_t) i_cmd_ptr, (uint32_t) o_rsp_ptr); l_rc = ERRL_RC_INTERNAL_FAIL; break; } // Check packet data length l_datalength = CMDH_DATALEN_FIELD_UINT16(i_cmd_ptr); if(l_datalength < (sizeof(cmdh_mfg_get_sensor_query_t) - sizeof(cmdh_fsp_cmd_header_t))) { TRAC_ERR("cmdh_mnfg_get_sensor: incorrect data length. exp[%d] act[%d]", (sizeof(cmdh_mfg_get_sensor_query_t) - sizeof(cmdh_fsp_cmd_header_t)), l_datalength); l_rc = ERRL_RC_INVALID_CMD_LEN; break; } // Check version if(l_cmd_ptr->version != MFG_LIST_SENSOR_VERSION) { TRAC_ERR("cmdh_mnfg_get_sensor: incorrect version. exp[%d] act[%d]", MFG_GET_SENSOR_VERSION, l_cmd_ptr->version); l_rc = ERRL_RC_INVALID_DATA; break; } // Capture user inputs l_gsid = l_cmd_ptr->gsid; TRAC_INFO("cmdh_mnfg_get_sensor: gsid[0x%04x]", l_gsid); // Initialize the sensor query arguments querySensorListArg_t l_qsl_arg = { l_gsid, // i_startGsid - passed by the caller 0, // i_present - passed by the caller AMEC_SENSOR_TYPE_ALL, // i_type AMEC_SENSOR_LOC_ALL, // i_loc &l_num_of_sensors, // io_numOfSensors NULL, // o_sensors - not needed &l_sensor_info // o_sensorInfoPtr }; // Get the sensor list l_err = querySensorList(&l_qsl_arg); if (NULL != l_err) { // Query failure TRAC_ERR("cmdh_mnfg_get_sensor: Failed to get sensor list. Error status is: 0x%x", l_err->iv_reasonCode); // Commit error log commitErrl(&l_err); l_rc = ERRL_RC_INTERNAL_FAIL; break; } else { l_resp_ptr->gsid = l_gsid; // Some of the response comes from the sensor l_sensor_ptr = getSensorByGsid(l_gsid); if (l_sensor_ptr == NULL) { TRAC_INFO("cmdh_mnfg_get_sensor: Didn't find sensor with gsid[0x%.4X]. Min/Max values won't be accurate.", l_gsid); l_resp_ptr->sample = 0; l_resp_ptr->min = 0xFFFF; l_resp_ptr->max = 0; l_resp_ptr->accumulator = 0; l_resp_ptr->status = 0; } else { l_resp_ptr->sample = l_sensor_ptr->sample; l_resp_ptr->min = l_sensor_ptr->sample_min; l_resp_ptr->max = l_sensor_ptr->sample_max; // Truncate accumulator to 4 bytes (should not be used) l_resp_ptr->accumulator = (uint32_t)l_sensor_ptr->accumulator; l_resp_ptr->status = *(uint8_t*)(&l_sensor_ptr->status); } // The rest of the response comes from the sensor info memcpy(l_resp_ptr->name, l_sensor_info.name, sizeof(l_resp_ptr->name)); memcpy(l_resp_ptr->units, l_sensor_info.sensor.units, sizeof(l_resp_ptr->units)); l_resp_ptr->freq = l_sensor_info.sensor.freq; l_resp_ptr->scalefactor = l_sensor_info.sensor.scalefactor; l_resp_ptr->location = l_sensor_info.sensor.location; l_resp_ptr->type = l_sensor_info.sensor.type; } }while(0); // Populate the response data header l_resp_data_length = sizeof(cmdh_mfg_get_sensor_resp_t) - sizeof(cmdh_fsp_rsp_header_t); G_rsp_status = l_rc; o_rsp_ptr->data_length[0] = ((uint8_t *)&l_resp_data_length)[0]; o_rsp_ptr->data_length[1] = ((uint8_t *)&l_resp_data_length)[1]; return l_rc; }
// Function Specification // // Name: cmdh_mnfg_list_sensors // // Description: Returns a list of selected sensors // // End Function Specification uint8_t cmdh_mnfg_list_sensors(const cmdh_fsp_cmd_t * i_cmd_ptr, cmdh_fsp_rsp_t * o_rsp_ptr) { uint8_t l_rc = ERRL_RC_SUCCESS; uint16_t l_type = 0; uint16_t l_location = 0; uint16_t l_start_gsid; uint16_t i = 0; uint16_t l_resp_data_length = 0; uint16_t l_datalength; uint16_t l_num_of_sensors = MFG_MAX_NUM_SENSORS + 1; cmdh_mfg_list_sensors_query_t *l_cmd_ptr = (cmdh_mfg_list_sensors_query_t*) i_cmd_ptr; cmdh_mfg_list_sensors_resp_t *l_resp_ptr = (cmdh_mfg_list_sensors_resp_t*) o_rsp_ptr; sensorQueryList_t l_sensor_list[MFG_MAX_NUM_SENSORS + 1]; errlHndl_t l_err = NULL; do { // Do sanity check on the function inputs if ((NULL == i_cmd_ptr) || (NULL == o_rsp_ptr)) { TRAC_ERR("cmdh_mnfg_list_sensors: invalid pointers. cmd[0x%08x] rsp[0x%08x]", (uint32_t) i_cmd_ptr, (uint32_t) o_rsp_ptr); l_rc = ERRL_RC_INTERNAL_FAIL; break; } // Check packet data length l_datalength = CMDH_DATALEN_FIELD_UINT16(i_cmd_ptr); if(l_datalength < (sizeof(cmdh_mfg_list_sensors_query_t) - sizeof(cmdh_fsp_cmd_header_t))) { TRAC_ERR("cmdh_mnfg_list_sensors: incorrect data length. exp[%d] act[%d]", (sizeof(cmdh_mfg_list_sensors_query_t) - sizeof(cmdh_fsp_cmd_header_t)), l_datalength); l_rc = ERRL_RC_INVALID_CMD_LEN; break; } // Check version if(l_cmd_ptr->version != MFG_LIST_SENSOR_VERSION) { TRAC_ERR("cmdh_mnfg_list_sensors: incorrect version. exp[%d] act[%d]", MFG_LIST_SENSOR_VERSION, l_cmd_ptr->version); l_rc = ERRL_RC_INVALID_DATA; break; } // Capture user inputs l_type = l_cmd_ptr->type; l_location = l_cmd_ptr->location; l_start_gsid = l_cmd_ptr->start_gsid; TRAC_INFO("cmdh_mnfg_list_sensors: Type[0x%04x] Location[0x%04x]", l_type, l_location); // Initialize the sensor query arguments const querySensorListArg_t l_qsl_arg = { l_start_gsid, // i_startGsid - passed by the caller l_cmd_ptr->present, // i_present - passed by the caller l_type, // i_type - passed by the caller l_location, // i_loc - passed by the caller &l_num_of_sensors, // io_numOfSensors l_sensor_list, // o_sensors NULL // o_sensorInfoPtr - not needed }; // Get the list of sensors l_err = querySensorList(&l_qsl_arg); if (NULL != l_err) { // Query failure TRAC_ERR("cmdh_mnfg_list_sensors: Failed to query sensor list. Error status is: 0x%x", l_err->iv_reasonCode); // Commit error log commitErrl(&l_err); l_rc = ERRL_RC_INTERNAL_FAIL; break; } else { TRAC_INFO("cmdh_mnfg_list_sensors: Numbers of sensors found[%u]", l_num_of_sensors); if (l_num_of_sensors > MFG_MAX_NUM_SENSORS) { // Got too many sensors back, need to truncate the list TRAC_INFO("cmdh_mnfg_list_sensors: Got too many sensors back[%u]. Truncating number of sensors to %u", l_num_of_sensors, MFG_MAX_NUM_SENSORS); l_num_of_sensors = MFG_MAX_NUM_SENSORS; l_resp_ptr->truncated = 1; } else { l_resp_ptr->truncated = 0; } // Clear out the sensor fields memset((void*) &(l_resp_ptr->sensor[0]), 0, (sizeof(cmdh_dbug_sensor_list_t)*l_num_of_sensors) ); // Populate the response data packet l_resp_ptr->num_sensors = l_num_of_sensors; for (i=0; i<l_num_of_sensors; i++) { l_resp_ptr->sensor[i].gsid = l_sensor_list[i].gsid; l_resp_ptr->sensor[i].sample = l_sensor_list[i].sample; strcpy(l_resp_ptr->sensor[i].name, l_sensor_list[i].name); } } }while(0); // Populate the response data header l_resp_data_length = 2 + l_num_of_sensors * sizeof(cmdh_mfg_sensor_rec_t); G_rsp_status = l_rc; o_rsp_ptr->data_length[0] = ((uint8_t *)&l_resp_data_length)[0]; o_rsp_ptr->data_length[1] = ((uint8_t *)&l_resp_data_length)[1]; return l_rc; }
// 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; G_rsp_status = 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_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; }