diff --git a/src/occ_405/amec/amec_pcap.c b/src/occ_405/amec/amec_pcap.c index b5cad525..512a82c4 100755 --- a/src/occ_405/amec/amec_pcap.c +++ b/src/occ_405/amec/amec_pcap.c @@ -50,7 +50,7 @@ //*************************************************************************/ // Globals //*************************************************************************/ -extern bool G_apss_present; +extern PWR_READING_TYPE G_pwr_reading_type; //Number of ticks to wait before dropping below nominal frequency #define PWR_SETTLED_TICKS 4 @@ -374,7 +374,7 @@ void amec_power_control(void) /* Code */ /*------------------------------------------------------------------------*/ - if(G_apss_present) + if(G_pwr_reading_type == PWR_READING_TYPE_APSS) { // Calculate the pcap for the proc, memory and the power capping limit // for nominal cores. diff --git a/src/occ_405/amec/amec_sensors_power.c b/src/occ_405/amec/amec_sensors_power.c index ab6f1ee9..4e4f240a 100755 --- a/src/occ_405/amec/amec_sensors_power.c +++ b/src/occ_405/amec/amec_sensors_power.c @@ -72,7 +72,7 @@ uint32_t G_curr_num_gpus_sys = 0; extern uint8_t G_occ_interrupt_type; extern bool G_vrm_thermal_monitoring; -extern bool G_apss_present; +extern PWR_READING_TYPE G_pwr_reading_type; //*************************************************************************/ // Code @@ -195,7 +195,7 @@ void amec_update_apss_sensors(void) { // Need to check to make sure APSS data has been received // via slave inbox first - if (G_slv_inbox_received && G_apss_present) + if (G_slv_inbox_received && (G_pwr_reading_type == PWR_READING_TYPE_APSS)) { uint8_t l_proc = G_pbax_id.chip_id; uint32_t temp32 = 0; @@ -571,12 +571,12 @@ void update_avsbus_power_sensors(const avsbus_type_e i_type) // = v(100uV) * i(10mA) / 1,000,000 const uint32_t l_power = l_chip_voltage_100uv * l_current_10ma / 1000000; sensor_update(AMECSENSOR_PTR(l_powerSensor), (uint16_t)l_power); - if(!G_apss_present) + if(G_pwr_reading_type != PWR_READING_TYPE_APSS) { // no APSS, update the processor power sensor with total processor power - // TODO RTC 160889 add in processor power for parts not measured (i.e. Vddr, Vcs, Vio etc) + // Vdd + Vdn + fixed adder for parts not measured (i.e. Vddr, Vcs, Vio etc) sensor_t *l_sensor2 = getSensorByGsid(l_powerSensor2); - const uint16_t l_proc_power = (uint16_t)l_power + l_sensor2->sample; + const uint16_t l_proc_power = (uint16_t)l_power + l_sensor2->sample + G_sysConfigData.proc_power_adder; sensor_update(AMECSENSOR_PTR(PWRPROC), l_proc_power); } } diff --git a/src/occ_405/amec/amec_sys.h b/src/occ_405/amec/amec_sys.h index 40afd494..d72a49bf 100755 --- a/src/occ_405/amec/amec_sys.h +++ b/src/occ_405/amec/amec_sys.h @@ -471,9 +471,15 @@ typedef struct sensor_t temp2mscent; sensor_t tempdimmthrm; sensor_t memsp2ms_tls; + // Nimbus DIMM Sensors sensor_t tempdimm[NUM_DIMM_PORTS*NUM_DIMMS_PER_I2CPORT]; + // GPU Sensors + sensor_t tempgpu0; + sensor_t tempgpu1; + sensor_t tempgpu2; + sensor_t curvdn; sensor_t pwrvdd; sensor_t pwrvdn; diff --git a/src/occ_405/cmdh/cmdh_fsp_cmds.c b/src/occ_405/cmdh/cmdh_fsp_cmds.c index d3786437..4c561fee 100755 --- a/src/occ_405/cmdh/cmdh_fsp_cmds.c +++ b/src/occ_405/cmdh/cmdh_fsp_cmds.c @@ -47,6 +47,7 @@ #include #include "homer.h" #include +#include #include "cmdh_dbug_cmd.h" #include "wof.h" extern dimm_sensor_flags_t G_dimm_temp_expired_bitmap; @@ -141,7 +142,7 @@ errlHndl_t cmdh_tmgt_poll (const cmdh_fsp_cmd_t * i_cmd_ptr, ERRL_RC cmdh_poll_v20(cmdh_fsp_rsp_t * o_rsp_ptr) { ERRL_RC l_rc = ERRL_RC_INTERNAL_FAIL; - uint8_t k = 0; + uint8_t k = 0, l_max_sensors = 0; cmdh_poll_sensor_db_t l_sensorHeader; // Set pointer to start of o_rsp_ptr @@ -244,7 +245,9 @@ ERRL_RC cmdh_poll_v20(cmdh_fsp_rsp_t * o_rsp_ptr) l_sensorHeader.count = 0; //Initialize to max number of possible temperature sensors. - cmdh_poll_temp_sensor_t l_tempSensorList[MAX_NUM_CORES + MAX_NUM_MEM_CONTROLLERS + (MAX_NUM_MEM_CONTROLLERS * NUM_DIMMS_PER_CENTAUR)]; + l_max_sensors = MAX_NUM_CORES + MAX_NUM_MEM_CONTROLLERS + (MAX_NUM_MEM_CONTROLLERS * NUM_DIMMS_PER_CENTAUR) + MAX_NUM_GPU_PER_DOMAIN; + l_max_sensors++; // +1 for VRM + cmdh_poll_temp_sensor_t l_tempSensorList[l_max_sensors]; memset(l_tempSensorList, 0x00, sizeof(l_tempSensorList)); // Add the core temperatures @@ -342,6 +345,18 @@ ERRL_RC cmdh_poll_v20(cmdh_fsp_rsp_t * o_rsp_ptr) } } + // Add GPU temperatures + for (k=0; kipmi_sid; + l_tempSensorList[l_sensorHeader.count].fru_type = DATA_FRU_GPU; + l_tempSensorList[l_sensorHeader.count].value = (G_amec_sensor_list[TEMPGPU0 + k]->sample) & 0xFF; + l_sensorHeader.count++; + } + } + // Copy header first. memcpy ((void *) &(o_rsp_ptr->data[l_rsp_index]), (void *)&l_sensorHeader, sizeof(l_sensorHeader)); // Increment index into response buffer. @@ -395,8 +410,10 @@ ERRL_RC cmdh_poll_v20(cmdh_fsp_rsp_t * o_rsp_ptr) ///////////////////// // POWR Sensors: - // Generate datablock header for power sensors and sensor data. RETURNED by MASTER ONLY. - if (G_occ_role == OCC_MASTER) + // Generate datablock header for power sensors and sensor data. + // If APSS is present return format version 0x02 by MASTER ONLY. + // If no APSS present return format version 0xA0 by all OCCs. + if ( (G_occ_role == OCC_MASTER) && (G_pwr_reading_type == PWR_READING_TYPE_APSS) ) { memset((void*) &l_sensorHeader, 0, (size_t)sizeof(cmdh_poll_sensor_db_t)); memcpy ((void *) &(l_sensorHeader.eyecatcher[0]), SENSOR_POWR, 4); @@ -439,6 +456,58 @@ ERRL_RC cmdh_poll_v20(cmdh_fsp_rsp_t * o_rsp_ptr) } } + else if (G_pwr_reading_type != PWR_READING_TYPE_APSS) + { + memset((void*) &l_sensorHeader, 0, (size_t)sizeof(cmdh_poll_sensor_db_t)); + memcpy ((void *) &(l_sensorHeader.eyecatcher[0]), SENSOR_POWR, 4); + l_sensorHeader.format = 0xA0; + l_sensorHeader.length = sizeof(cmdh_poll_power_no_apss_sensor_t); + l_sensorHeader.count = 1; + + cmdh_poll_power_no_apss_sensor_t l_pwrData; + memset((void*) &l_pwrData, 0, (size_t)sizeof(cmdh_poll_power_no_apss_sensor_t)); + + // if there is a non-APSS chip for system power fill in system power else return 0's + if(G_pwr_reading_type != PWR_READING_TYPE_NONE) + { + l_pwrData.sys_pwr_id = G_amec_sensor_list[PWRSYS]->ipmi_sid; + l_pwrData.sys_pwr_update_time = G_mics_per_tick; // system power is read every tick + l_pwrData.sys_pwr_current = G_amec_sensor_list[PWRSYS]->sample; + l_pwrData.sys_pwr_update_tag = G_amec_sensor_list[PWRSYS]->update_tag; + l_pwrData.sys_pwr_accumul = G_amec_sensor_list[PWRSYS]->accumulator; + } + + // Proc power is from AVS bus, return readings if reading Vdd and Vdn else return 0's + if( (G_avsbus_vdd_monitoring) && (G_avsbus_vdn_monitoring) ) + { + // when no APSS present proc readings are updated based on AVS timing use PWRVDD/N timing (2 ticks) + l_pwrData.proc_pwr_update_time = G_mics_per_tick * 2; + l_pwrData.proc_pwr_current = G_amec_sensor_list[PWRPROC]->sample; + l_pwrData.proc_pwr_update_tag = G_amec_sensor_list[PWRPROC]->update_tag; + l_pwrData.proc_pwr_accumul = G_amec_sensor_list[PWRPROC]->accumulator; + l_pwrData.vdd_pwr_current = G_amec_sensor_list[PWRVDD]->sample; + l_pwrData.vdd_pwr_update_tag = G_amec_sensor_list[PWRVDD]->update_tag; + l_pwrData.vdd_pwr_accumul = G_amec_sensor_list[PWRVDD]->accumulator; + l_pwrData.vdn_pwr_current = G_amec_sensor_list[PWRVDN]->sample; + l_pwrData.vdn_pwr_update_tag = G_amec_sensor_list[PWRVDN]->update_tag; + l_pwrData.vdn_pwr_accumul = G_amec_sensor_list[PWRVDN]->accumulator; + } + + // Copy header to response buffer. + memcpy ((void *) &(o_rsp_ptr->data[l_rsp_index]), + (void *)&l_sensorHeader, sizeof(l_sensorHeader)); + // Increment index into response buffer. + l_rsp_index += sizeof(l_sensorHeader); + + // Copy sensor data into response buffer. + memcpy ((void *) &(o_rsp_ptr->data[l_rsp_index]), + (void *)&(l_pwrData), sizeof(cmdh_poll_power_no_apss_sensor_t)); + // Increment index into response buffer. + l_rsp_index += sizeof(cmdh_poll_power_no_apss_sensor_t); + + l_poll_rsp->sensor_dblock_count +=1; + } + //////////////////////// // POWER CAPS: // Generate datablock header for power caps. RETURNED by MASTER ONLY. @@ -448,18 +517,24 @@ ERRL_RC cmdh_poll_v20(cmdh_fsp_rsp_t * o_rsp_ptr) memcpy ((void *) &(l_sensorHeader.eyecatcher[0]), SENSOR_CAPS, 4); l_sensorHeader.format = 0x03; l_sensorHeader.length = sizeof(cmdh_poll_pcaps_sensor_t); - + l_sensorHeader.count = 1; cmdh_poll_pcaps_sensor_t l_pcapData; - l_pcapData.current = g_amec->pcap.active_node_pcap; - l_pcapData.system = G_amec_sensor_list[PWRSYS]->sample; - l_pcapData.n = G_sysConfigData.pcap.oversub_pcap; - l_pcapData.max = G_sysConfigData.pcap.max_pcap; - l_pcapData.hard_min = G_sysConfigData.pcap.hard_min_pcap; - l_pcapData.soft_min = G_sysConfigData.pcap.soft_min_pcap; - l_pcapData.user = G_sysConfigData.pcap.current_pcap; - l_pcapData.source = G_sysConfigData.pcap.source; - l_sensorHeader.count = 1; + memset((void*) &l_pcapData, 0, (size_t)sizeof(cmdh_poll_pcaps_sensor_t)); + + // Return 0's for power cap section if there is no system power reading + // OCC can't support power capping without knowing the system power + if(G_pwr_reading_type != PWR_READING_TYPE_NONE) + { + l_pcapData.current = g_amec->pcap.active_node_pcap; + l_pcapData.system = G_amec_sensor_list[PWRSYS]->sample; + l_pcapData.n = G_sysConfigData.pcap.oversub_pcap; + l_pcapData.max = G_sysConfigData.pcap.max_pcap; + l_pcapData.hard_min = G_sysConfigData.pcap.hard_min_pcap; + l_pcapData.soft_min = G_sysConfigData.pcap.soft_min_pcap; + l_pcapData.user = G_sysConfigData.pcap.current_pcap; + l_pcapData.source = G_sysConfigData.pcap.source; + } // Copy header to response buffer. memcpy ((void *) &(o_rsp_ptr->data[l_rsp_index]), @@ -467,18 +542,15 @@ ERRL_RC cmdh_poll_v20(cmdh_fsp_rsp_t * o_rsp_ptr) // Increment index into response buffer. l_rsp_index += sizeof(l_sensorHeader); - uint8_t l_sensordataSz = l_sensorHeader.count * l_sensorHeader.length; // Copy sensor data into response buffer. memcpy ((void *) &(o_rsp_ptr->data[l_rsp_index]), - (void *)&(l_pcapData), l_sensordataSz); + (void *)&(l_pcapData), sizeof(cmdh_poll_pcaps_sensor_t)); // Increment index into response buffer. - l_rsp_index += l_sensordataSz; + l_rsp_index += sizeof(cmdh_poll_pcaps_sensor_t); l_poll_rsp->sensor_dblock_count +=1; - } - /////////////////// // EXTN Sensors: // Generate datablock header for freq sensors and sensor data. diff --git a/src/occ_405/cmdh/cmdh_fsp_cmds.h b/src/occ_405/cmdh/cmdh_fsp_cmds.h index b7a13cd7..7e63f925 100755 --- a/src/occ_405/cmdh/cmdh_fsp_cmds.h +++ b/src/occ_405/cmdh/cmdh_fsp_cmds.h @@ -202,6 +202,26 @@ typedef struct __attribute__ ((packed)) cmdh_poll_powr_sensor uint16_t current; // Most recent 250us reading in watts. } cmdh_poll_power_sensor_t; +typedef struct __attribute__ ((packed)) cmdh_poll_powr_no_apss_sensor +{ + uint32_t sys_pwr_id; // Sensor id - to represent total system power. + uint16_t sys_pwr_update_time; // Time in us that system power is read + uint16_t sys_pwr_current; // Most recent system power reading in watts + uint32_t sys_pwr_update_tag; // Count of number of samples represented by sys pwr accumulator + uint64_t sys_pwr_accumul; // Accumulation of system power readings + uint32_t reserved; + uint16_t proc_pwr_update_time; // Time in us that processor power is updated + uint16_t proc_pwr_current; // Most recent processor power reading in watts + uint32_t proc_pwr_update_tag; // Count of number of samples represented by proc accumulator + uint64_t proc_pwr_accumul; // Accumulation of processor power readings + uint16_t vdd_pwr_current; // Most recent processor Vdd power reading in watts + uint32_t vdd_pwr_update_tag; // Count of number of samples represented by Vdd accumulator + uint64_t vdd_pwr_accumul; // Accumulation of processor Vdd power readings + uint16_t vdn_pwr_current; // Most recent processor Vdn power reading in watts + uint32_t vdn_pwr_update_tag; // Count of number of samples represented by Vdn accumulator + uint64_t vdn_pwr_accumul; // Accumulation of processor Vdn power readings +} cmdh_poll_power_no_apss_sensor_t; + // Only available from master occ. typedef struct __attribute__ ((packed)) cmdh_poll_caps_sensor { diff --git a/src/occ_405/cmdh/cmdh_fsp_cmds_datacnfg.c b/src/occ_405/cmdh/cmdh_fsp_cmds_datacnfg.c index 4bb2b6b1..fa6aab94 100755 --- a/src/occ_405/cmdh/cmdh_fsp_cmds_datacnfg.c +++ b/src/occ_405/cmdh/cmdh_fsp_cmds_datacnfg.c @@ -91,6 +91,7 @@ const data_req_table_t G_data_pri_table[] = {DATA_MASK_AVSBUS_CONFIG, DATA_FORMAT_AVSBUS_CONFIG}, {DATA_MASK_SET_ROLE, DATA_FORMAT_SET_ROLE}, {DATA_MASK_MEM_CFG, DATA_FORMAT_MEM_CFG}, + {DATA_MASK_GPU, DATA_FORMAT_GPU}, {DATA_MASK_THRM_THRESHOLDS, DATA_FORMAT_THRM_THRESHOLDS}, {DATA_MASK_FREQ_PRESENT, DATA_FORMAT_FREQ}, {DATA_MASK_PCAP_PRESENT, DATA_FORMAT_POWER_CAP}, @@ -104,8 +105,8 @@ bool G_mem_monitoring_allowed = FALSE; // Flag will get enabled when OCC receives Thermal Threshold data bool G_vrm_thermal_monitoring = FALSE; -// Will get set to true when receiving APSS config data -bool G_apss_present = FALSE; +// Will get set when receiving APSS config data +PWR_READING_TYPE G_pwr_reading_type = PWR_READING_TYPE_NONE; // Function Specification // @@ -938,15 +939,19 @@ errlHndl_t data_store_apss_config_v20(const cmdh_apss_config_v20_t * i_cmd_ptr, cmdh_fsp_rsp_t * o_rsp_ptr) { errlHndl_t l_err = NULL; - uint16_t l_channel = 0, l_port = 0, l_pin = 0; - - // Set to default value - memset(&G_sysConfigData.apss_adc_map, SYSCFG_INVALID_ADC_CHAN, sizeof(G_sysConfigData.apss_adc_map)); - memset(&G_sysConfigData.apss_gpio_map, SYSCFG_INVALID_PIN, sizeof(G_sysConfigData.apss_gpio_map)); - G_apss_present = FALSE; + uint16_t l_channel = 0, l_port = 0, l_pin = 0, l_num_channels = MAX_APSS_ADC_CHANNELS; // ADC channels info - for(l_channel=0;(l_channel < MAX_APSS_ADC_CHANNELS) && (NULL == l_err);l_channel++) + if(G_pwr_reading_type == PWR_READING_TYPE_2_CHANNEL) + l_num_channels = 2; + else + { + // This must be APSS type, however it is possible that xml and/or HTMGT doesn't support + // indication of no APSS so we will default to none and then set to APSS if valid channel found + G_pwr_reading_type = PWR_READING_TYPE_NONE; + } + + for(l_channel=0;(l_channel < l_num_channels) && (NULL == l_err);l_channel++) { G_sysConfigData.apss_cal[l_channel].gnd_select = i_cmd_ptr->adc[l_channel].gnd_select; G_sysConfigData.apss_cal[l_channel].gain = i_cmd_ptr->adc[l_channel].gain; @@ -960,8 +965,11 @@ errlHndl_t data_store_apss_config_v20(const cmdh_apss_config_v20_t * i_cmd_ptr, apss_store_ipmi_sensor_id(l_channel, &(i_cmd_ptr->adc[l_channel])); // APSS is present if there is at least one channel with a valid assignment - if(i_cmd_ptr->adc[l_channel].assignment != ADC_RESERVED) - G_apss_present = TRUE; + if( (i_cmd_ptr->adc[l_channel].assignment != ADC_RESERVED) && + (G_pwr_reading_type == PWR_READING_TYPE_NONE) ) + { + G_pwr_reading_type = PWR_READING_TYPE_APSS; + } } CNFG_DBG("data_store_apss_config_v20: Channel %d: FuncID[0x%02X] SID[0x%08X]", l_channel, i_cmd_ptr->adc[l_channel].assignment, i_cmd_ptr->adc[l_channel].ipmisensorId); @@ -970,7 +978,7 @@ errlHndl_t data_store_apss_config_v20(const cmdh_apss_config_v20_t * i_cmd_ptr, G_sysConfigData.apss_cal[l_channel].offset); } - if(NULL == l_err) + if( (NULL == l_err) && (G_pwr_reading_type == PWR_READING_TYPE_APSS) ) // only APSS has GPIO config { // GPIO Ports @@ -988,13 +996,6 @@ errlHndl_t data_store_apss_config_v20(const cmdh_apss_config_v20_t * i_cmd_ptr, } } - - if(NULL == l_err) - { - // Change Data Request Mask to indicate we got this data - G_data_cnfg->data_mask |= DATA_MASK_APSS_CONFIG; - CMDH_TRAC_IMP("Got valid APSS Config data via TMGT; APSS present = %d", G_apss_present); - } } return l_err; @@ -1011,14 +1012,46 @@ errlHndl_t data_store_apss_config(const cmdh_fsp_cmd_t * i_cmd_ptr, cmdh_fsp_rsp_t * o_rsp_ptr) { errlHndl_t l_err = NULL; + bool l_invalid_data = FALSE; cmdh_apss_config_v20_t *l_cmd_ptr = (cmdh_apss_config_v20_t *)i_cmd_ptr; uint16_t l_data_length = CMDH_DATALEN_FIELD_UINT16(l_cmd_ptr); //Command length uint32_t l_v20_data_sz = sizeof(cmdh_apss_config_v20_t) - sizeof(cmdh_fsp_cmd_header_t); - if( !( (l_cmd_ptr->version == DATA_APSS_VERSION20) && (l_v20_data_sz == l_data_length) ) ) + + // Set to default value + memset(&G_sysConfigData.apss_adc_map, SYSCFG_INVALID_ADC_CHAN, sizeof(G_sysConfigData.apss_adc_map)); + memset(&G_sysConfigData.apss_gpio_map, SYSCFG_INVALID_PIN, sizeof(G_sysConfigData.apss_gpio_map)); + + // only version 0x20 supported and data length must be at least 4 + if( (l_cmd_ptr->version != DATA_APSS_VERSION20) || (l_data_length < 4)) { - CMDH_TRAC_ERR("data_store_apss_config: Invalid System Data packet. Given Version:0x%X", - l_cmd_ptr->version); + l_invalid_data = TRUE; + } + else + { + // verify the data length and process the data based on power reading type + // PWR_READING_TYPE_APSS --> full size of structure + // PWR_READING_TYPE_2_CHANNEL --> 0x20 bytes (2 ADC channels, no GPIOs) + // PWR_READING_TYPE_NONE --> 4 bytes (no channel or GPIO data) + + G_pwr_reading_type = l_cmd_ptr->type; + + if( ( (G_pwr_reading_type == PWR_READING_TYPE_2_CHANNEL) && (l_data_length == 0x20) ) || + ( (G_pwr_reading_type == PWR_READING_TYPE_APSS) && (l_v20_data_sz == l_data_length) ) ) + { + l_err = data_store_apss_config_v20(l_cmd_ptr, o_rsp_ptr); + } + else if( (G_pwr_reading_type != PWR_READING_TYPE_NONE) || (l_data_length != 4) ) + { + l_invalid_data = TRUE; + } + } + + if(l_invalid_data) + { + G_pwr_reading_type = PWR_READING_TYPE_NONE; + CMDH_TRAC_ERR("data_store_apss_config: Invalid System Data packet. Given Version:0x%02X length:0x%04X", + l_cmd_ptr->version, l_data_length); /* @ * @errortype @@ -1031,9 +1064,11 @@ errlHndl_t data_store_apss_config(const cmdh_fsp_cmd_t * i_cmd_ptr, */ cmdh_build_errl_rsp(i_cmd_ptr, o_rsp_ptr, ERRL_RC_INVALID_DATA, &l_err); } - else // Version 0x20 + else if(NULL == l_err) { - l_err = data_store_apss_config_v20(l_cmd_ptr, o_rsp_ptr); + // Change Data Request Mask to indicate we got this data + G_data_cnfg->data_mask |= DATA_MASK_APSS_CONFIG; + CMDH_TRAC_IMP("Got valid APSS Config data via TMGT; Pwr reading type = %d", G_pwr_reading_type); } return l_err; @@ -1152,6 +1187,8 @@ errlHndl_t data_store_avsbus_config(const cmdh_fsp_cmd_t * i_cmd_ptr, } else { + G_sysConfigData.proc_power_adder = l_cmd_ptr->proc_power_adder; + // We can use vdd/vdn. Clear NO_VDD_VDN_READ mask set_clear_wof_disabled( CLEAR, WOF_RC_INVALID_VDD_VDN ); avsbus_init(); @@ -1168,6 +1205,48 @@ errlHndl_t data_store_avsbus_config(const cmdh_fsp_cmd_t * i_cmd_ptr, } // end data_store_avsbus_config() +// Function Specification +// +// Name: data_store_gpu +// +// Description: GPU information +// +// End Function Specification +errlHndl_t data_store_gpu(const cmdh_fsp_cmd_t * i_cmd_ptr, + cmdh_fsp_rsp_t * o_rsp_ptr) +{ + errlHndl_t l_err = NULL; + const uint8_t GPU_VERSION = 0x01; + const uint16_t GPU_LENGTH = sizeof(cmdh_gpu_config_t) - sizeof(cmdh_fsp_cmd_header_t); + + cmdh_gpu_config_t *l_cmd_ptr = (cmdh_gpu_config_t *)i_cmd_ptr; + uint16_t l_data_length = CMDH_DATALEN_FIELD_UINT16(l_cmd_ptr); + + if ((GPU_VERSION == l_cmd_ptr->version) && (GPU_LENGTH == l_data_length)) + { + G_sysConfigData.total_non_gpu_max_pwr_watts = l_cmd_ptr->total_non_gpu_max_pwr_watts; + G_sysConfigData.total_proc_mem_pwr_drop_watts = l_cmd_ptr->total_proc_mem_pwr_drop_watts; + G_sysConfigData.gpu_sensor_ids[0] = l_cmd_ptr->gpu0_sid; + AMECSENSOR_PTR(TEMPGPU0)->ipmi_sid = l_cmd_ptr->gpu0_temp_sid; + G_sysConfigData.gpu_sensor_ids[1] = l_cmd_ptr->gpu1_sid; + AMECSENSOR_PTR(TEMPGPU1)->ipmi_sid = l_cmd_ptr->gpu1_temp_sid; + G_sysConfigData.gpu_sensor_ids[2] = l_cmd_ptr->gpu2_sid; + AMECSENSOR_PTR(TEMPGPU2)->ipmi_sid = l_cmd_ptr->gpu2_temp_sid; + + G_data_cnfg->data_mask |= DATA_MASK_GPU; + CMDH_TRAC_IMP("data_store_gpu: Got valid GPU data packet"); + } + else + { + CMDH_TRAC_ERR("data_store_gpu: Invalid GPU version/length (0x%02X/0x%04X))", + l_cmd_ptr->version, l_data_length); + cmdh_build_errl_rsp(i_cmd_ptr, o_rsp_ptr, ERRL_RC_INVALID_DATA, &l_err); + } + + return l_err; + +} // end data_store_gpu() + // Function Specification // // Name: data_store_role @@ -1208,7 +1287,7 @@ errlHndl_t data_store_role(const cmdh_fsp_cmd_t * i_cmd_ptr, rtl_set_run_mask_deferred(RTL_FLAG_MSTR); // Allow APSS tasks to run on OCC master if APSS is present - if(G_apss_present) + if(G_pwr_reading_type == PWR_READING_TYPE_APSS) rtl_clr_run_mask_deferred(RTL_FLAG_APSS_NOT_INITD); CMDH_TRAC_IMP("data_store_role: OCC Role set to Master via TMGT"); @@ -1248,7 +1327,7 @@ errlHndl_t data_store_role(const cmdh_fsp_cmd_t * i_cmd_ptr, } // Allow APSS tasks to run on OCC backup - if(G_apss_present) + if(G_pwr_reading_type == PWR_READING_TYPE_APSS) rtl_clr_run_mask_deferred(RTL_FLAG_APSS_NOT_INITD); CMDH_TRAC_IMP("data_store_role: OCC Role set to Backup Master via TMGT"); } @@ -2252,6 +2331,16 @@ errlHndl_t DATA_store_cnfgdata (const cmdh_fsp_cmd_t * i_cmd_ptr, } break; + case DATA_FORMAT_GPU: + // Store GPU information + l_errlHndl = data_store_gpu(i_cmd_ptr, o_rsp_ptr); + if(NULL == l_errlHndl) + { + // Notify AMEC of the new data + l_new_data = DATA_MASK_GPU; + } + break; + case DATA_FORMAT_POWER_CAP: // Store the pcap data in G_master_pcap_data l_errlHndl = data_store_power_cap(i_cmd_ptr, o_rsp_ptr); diff --git a/src/occ_405/cmdh/cmdh_fsp_cmds_datacnfg.h b/src/occ_405/cmdh/cmdh_fsp_cmds_datacnfg.h index f5c24954..4a2679cc 100755 --- a/src/occ_405/cmdh/cmdh_fsp_cmds_datacnfg.h +++ b/src/occ_405/cmdh/cmdh_fsp_cmds_datacnfg.h @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2011,2016 */ +/* Contributors Listed Below - COPYRIGHT 2011,2017 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -51,6 +51,7 @@ typedef enum DATA_FORMAT_MEM_THROT = 0x12, DATA_FORMAT_THRM_THRESHOLDS = 0x13, DATA_FORMAT_AVSBUS_CONFIG = 0x14, + DATA_FORMAT_GPU = 0x15, } eConfigDataFormatVersion; // Enum of the various Cnfg Data Masks that are used @@ -67,6 +68,7 @@ typedef enum DATA_MASK_IPS_CNFG = 0x00000100, DATA_MASK_MEM_CFG = 0x00000200, DATA_MASK_MEM_THROT = 0x00000400, + DATA_MASK_GPU = 0x00000800, } eConfigDataPriorityMask; typedef enum @@ -75,9 +77,19 @@ typedef enum DATA_FRU_CENTAUR = 0x01, DATA_FRU_DIMM = 0x02, DATA_FRU_VRM = 0x03, + DATA_FRU_GPU = 0x04, DATA_FRU_MAX, } eConfigDataFruType; +typedef enum +{ + PWR_READING_TYPE_APSS = 0x00, + PWR_READING_TYPE_2_CHANNEL = 0x02, + PWR_READING_TYPE_NONE = 0xFF, +} PWR_READING_TYPE; + +extern PWR_READING_TYPE G_pwr_reading_type; + // Set OCC Role Masks #define OCC_ROLE_MASTER_MASK 0x01 #define OCC_ROLE_FIR_MASTER_MASK 0x40 @@ -86,6 +98,9 @@ typedef enum // it is running in simulation. #define OCC_SIMICS_ENVIRONMENT 0x08 +// Bit mask in poll for indicating OCC owns PMCR +#define OCC_PMCR_OWNER_POLL_STATUS_MASK 0x10 + // Used by TMGT to send OCC the frequencies for each mode. typedef struct __attribute__ ((packed)) { @@ -127,7 +142,8 @@ typedef struct __attribute__ ((packed)) struct cmdh_fsp_cmd_header; uint8_t format; uint8_t version; - uint8_t reserved[2]; + uint8_t type; + uint8_t reserved; apss_cfg_adc_v20_t adc[MAX_APSS_ADC_CHANNELS]; apss_cfg_gpio_t gpio[MAX_APSS_GPIO_PORTS]; }cmdh_apss_config_v20_t; //New for P9 @@ -143,9 +159,26 @@ typedef struct __attribute__ ((packed)) uint16_t reserved1; uint8_t vdn_bus; uint8_t vdn_rail; - uint16_t reserved2; + uint16_t proc_power_adder; }cmdh_avsbus_config_t; +// Used by TMGT to send OCC GPU data. +typedef struct __attribute__ ((packed)) +{ + struct cmdh_fsp_cmd_header; + uint8_t format; + uint8_t version; + uint16_t total_non_gpu_max_pwr_watts; + uint16_t total_proc_mem_pwr_drop_watts; + uint16_t reserved; + uint32_t gpu0_sid; // GPU0 Sensor ID + uint32_t gpu0_temp_sid; // GPU0 Temperature Sensor ID + uint32_t gpu1_sid; // GPU1 Sensor ID + uint32_t gpu1_temp_sid; // GPU1 Temperature Sensor ID + uint32_t gpu2_sid; // GPU2 Sensor ID + uint32_t gpu2_temp_sid; // GPU2 Temperature Sensor ID +}cmdh_gpu_config_t; + // Used by TMGT to send OCC the PCAP config data. typedef struct __attribute__ ((packed)) { diff --git a/src/occ_405/dcom/dcomMasterTx.c b/src/occ_405/dcom/dcomMasterTx.c index 32854421..53b7b330 100644 --- a/src/occ_405/dcom/dcomMasterTx.c +++ b/src/occ_405/dcom/dcomMasterTx.c @@ -39,7 +39,7 @@ #include extern UINT8 g_amec_tb_record; // From amec_amester.c for syncronized traces -extern bool G_apss_present; +extern PWR_READING_TYPE G_pwr_reading_type; // SSX Block Copy Request for the Slave Inbox Transmit Queue BceRequest G_slv_inbox_tx_pba_request; @@ -241,7 +241,7 @@ void task_dcom_tx_slv_inbox( task_t *i_self) { // If we are in standby or no APSS present, we need to fake out // the APSS data since we aren't talking to APSS. - if( (OCC_STATE_STANDBY == CURRENT_STATE()) || !G_apss_present ) + if( (OCC_STATE_STANDBY == CURRENT_STATE()) || (G_pwr_reading_type != PWR_READING_TYPE_APSS) ) { G_ApssPwrMeasCompleted = TRUE; } diff --git a/src/occ_405/main.c b/src/occ_405/main.c index 9b13641d..36bf4cee 100755 --- a/src/occ_405/main.c +++ b/src/occ_405/main.c @@ -86,7 +86,7 @@ extern uint32_t G_khz_per_pstate; extern uint8_t G_proc_pmin; extern uint8_t G_proc_pmax; -extern bool G_apss_present; +extern PWR_READING_TYPE G_pwr_reading_type; IMAGE_HEADER (G_mainAppImageHdr,__ssx_boot,MAIN_APP_ID,ID_NUM_INVALID); @@ -1312,14 +1312,16 @@ void master_occ_init() errlHndl_t l_err = NULL; // Only do APSS initialization if APSS is present - if(G_apss_present) + if(G_pwr_reading_type == PWR_READING_TYPE_APSS) + { l_err = initialize_apss(); - if( (NULL != l_err)) - { - MAIN_TRAC_ERR("master_occ_init: Error initializing APSS"); - // commit & delete. CommitErrl handles NULL error log handle - REQUEST_RESET(l_err); + if( (NULL != l_err)) + { + MAIN_TRAC_ERR("master_occ_init: Error initializing APSS"); + // commit & delete. CommitErrl handles NULL error log handle + REQUEST_RESET(l_err); + } } // Reinitialize the PBAX Queues diff --git a/src/occ_405/occ_sys_config.c b/src/occ_405/occ_sys_config.c index f92010a8..2335220b 100755 --- a/src/occ_405/occ_sys_config.c +++ b/src/occ_405/occ_sys_config.c @@ -165,6 +165,8 @@ occSysConfigData_t G_sysConfigData = .rail = 0, }, + .proc_power_adder = 0, + // ----------------------------------------------------------- // Power Cap Initializations // ----------------------------------------------------------- diff --git a/src/occ_405/occ_sys_config.h b/src/occ_405/occ_sys_config.h index 40416a72..14c2645d 100755 --- a/src/occ_405/occ_sys_config.h +++ b/src/occ_405/occ_sys_config.h @@ -103,6 +103,14 @@ typedef union #define MAX_GPU_DOMAINS 2 #define MAX_NUM_GPU_PER_DOMAIN 3 +//Returns non-0 if the specified GPU behind this OCC (not system wide) is present. Otherwise, returns zero. +// NOTE: This is looking at the first GPU config, GPU config should not change after first determined, if +// current GPU config is wanted to compare to the first check G_curr_proc_gpu_config +extern uint32_t G_first_proc_gpu_config; +#define GPU_PRESENT(occ_gpu_id) \ + ((0x01 << occ_gpu_id) & G_first_proc_gpu_config) + + // List of all possible APSS Channel assignments (Function IDs) // Each channel in the APSS will be associated with only one of these // function ids for each system type as defined in the mrw. @@ -365,6 +373,7 @@ typedef struct // AVS Bus config avsbusData_t avsbus_vdd; avsbusData_t avsbus_vdn; + uint16_t proc_power_adder; // ------------------------------------ // Power Cap Configuration Data updated by Slaves @@ -421,6 +430,13 @@ typedef struct // (only first two columns populated) mem_throt_config_data_t mem_throt_limits[MAX_NUM_MEM_CONTROLLERS][MAX_NUM_MCU_PORTS]; + // -------------------------------------- + // GPU Information for error callout and GPU power capping + // -------------------------------------- + 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; + } occSysConfigData_t; __attribute__ ((__aligned__ (128))) extern occSysConfigData_t G_sysConfigData; diff --git a/src/occ_405/occbuildname.c b/src/occ_405/occbuildname.c index 761f1a6e..5887e1ba 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"))) = /**/ "op_occ_170519a\0" /**/ ; +volatile const char G_occ_buildname[16] __attribute__((section(".buildname"))) = /**/ "op_occ_170607a\0" /**/ ; #endif diff --git a/src/occ_405/proc/proc_pstate.c b/src/occ_405/proc/proc_pstate.c index 90a9deba..0381dbbd 100755 --- a/src/occ_405/proc/proc_pstate.c +++ b/src/occ_405/proc/proc_pstate.c @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2011,2015 */ +/* Contributors Listed Below - COPYRIGHT 2011,2017 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -63,7 +63,7 @@ pstateStatus G_proc_pstate_status = PSTATES_DISABLED; // A Global parameter indicating the owner of the PMCR. -PMCR_OWNER G_proc_pmcr_owner = G_sysConfigData.system_type.kvm? PMCR_OWNER_HOST: PMCR_OWNER_HOST; +PMCR_OWNER G_proc_pmcr_owner = PMCR_OWNER_HOST; // OPAL Dynamic data, updated whenever any OCC G_opal_table.dynamic parameter change DMA_BUFFER( opal_dynamic_table_t G_opal_dynamic_table ) = {{0}}; diff --git a/src/occ_405/sensor/sensor.h b/src/occ_405/sensor/sensor.h index 535b4343..7b498657 100755 --- a/src/occ_405/sensor/sensor.h +++ b/src/occ_405/sensor/sensor.h @@ -93,6 +93,7 @@ typedef enum AMEC_SENSOR_LOC_VRM = 0x0010, AMEC_SENSOR_LOC_OCC = 0x0020, AMEC_SENSOR_LOC_CORE = 0x0040, + AMEC_SENSOR_LOC_GPU = 0x0080, AMEC_SENSOR_LOC_ALL = 0xffff, }AMEC_SENSOR_LOC; diff --git a/src/occ_405/sensor/sensor_enum.h b/src/occ_405/sensor/sensor_enum.h index b41e9e49..3937f7de 100755 --- a/src/occ_405/sensor/sensor_enum.h +++ b/src/occ_405/sensor/sensor_enum.h @@ -726,6 +726,13 @@ enum e_gsid TEMPDIMMTHRM, MEMSP2MS, + // ------------------------------------------------------ + // GPU Sensors + // ------------------------------------------------------ + TEMPGPU0, + TEMPGPU1, + TEMPGPU2, + // ------------------------------------------------------ // Partition Sensors // ------------------------------------------------------ diff --git a/src/occ_405/sensor/sensor_info.c b/src/occ_405/sensor/sensor_info.c index 6ee5da48..926ccedc 100755 --- a/src/occ_405/sensor/sensor_info.c +++ b/src/occ_405/sensor/sensor_info.c @@ -370,6 +370,11 @@ const sensor_info_t G_sensor_info[] = SENSOR_INFO_T_ENTRY( TEMPDIMMTHRM, "C\0", AMEC_SENSOR_TYPE_TEMP, AMEC_SENSOR_LOC_MEM, AMEC_SENSOR_NONUM, AMEEFP_32MS_IN_HZ, AMEFP( 1, 0) ), SENSOR_INFO_T_ENTRY( MEMSP2MS, "%\0", AMEC_SENSOR_TYPE_PERF, AMEC_SENSOR_LOC_MEM, AMEC_SENSOR_NONUM, AMEEFP_250US_IN_HZ, AMEFP( 1, 0) ), + /* ==GPUSensors== NameString Units Type Location Number Freq ScaleFactor */ + SENSOR_INFO_T_ENTRY( TEMPGPU0, "C\0", AMEC_SENSOR_TYPE_TEMP, AMEC_SENSOR_LOC_GPU, AMEC_SENSOR_NONUM, AMEEFP_32MS_IN_HZ, AMEFP( 1, 0) ), + SENSOR_INFO_T_ENTRY( TEMPGPU1, "C\0", AMEC_SENSOR_TYPE_TEMP, AMEC_SENSOR_LOC_GPU, AMEC_SENSOR_NONUM, AMEEFP_32MS_IN_HZ, AMEFP( 1, 0) ), + SENSOR_INFO_T_ENTRY( TEMPGPU2, "C\0", AMEC_SENSOR_TYPE_TEMP, AMEC_SENSOR_LOC_GPU, AMEC_SENSOR_NONUM, AMEEFP_32MS_IN_HZ, AMEFP( 1, 0) ), + /* ==PartSummarySensors== NameString Units Type Location Number Freq ScaleFactor */ SENSOR_INFO_T_ENTRY( UTIL2MSSLCG000, "%\0", AMEC_SENSOR_TYPE_UTIL, AMEC_SENSOR_LOC_LPAR, AMEC_SENSOR_NONUM, AMEEFP_2MS_IN_HZ, AMEFP_SCALE_0_16384), SENSOR_INFO_T_ENTRY( UTIL2MSSLCG001, "%\0", AMEC_SENSOR_TYPE_UTIL, AMEC_SENSOR_LOC_LPAR, AMEC_SENSOR_NONUM, AMEEFP_2MS_IN_HZ, AMEFP_SCALE_0_16384), diff --git a/src/occ_405/sensor/sensor_table.c b/src/occ_405/sensor/sensor_table.c index 1cb2ac64..e5f92cac 100755 --- a/src/occ_405/sensor/sensor_table.c +++ b/src/occ_405/sensor/sensor_table.c @@ -416,6 +416,13 @@ const sensor_ptr_t G_amec_sensor_list[] = SENSOR_PTR(TEMPDIMMTHRM, &g_amec_sys.proc[0].tempdimmthrm), SENSOR_PTR(MEMSP2MS, &g_amec_sys.proc[0].memsp2ms_tls), + // ------------------------------------------------------ + // GPU Sensors + // ------------------------------------------------------ + SENSOR_PTR(TEMPGPU0, &g_amec_sys.proc[0].tempgpu0), + SENSOR_PTR(TEMPGPU1, &g_amec_sys.proc[0].tempgpu1), + SENSOR_PTR(TEMPGPU2, &g_amec_sys.proc[0].tempgpu2), + // ------------------------------------------------------ // Regulator Sensors // ------------------------------------------------------ diff --git a/src/occ_405/state.c b/src/occ_405/state.c index b79b7349..5170c5bc 100755 --- a/src/occ_405/state.c +++ b/src/occ_405/state.c @@ -1230,7 +1230,7 @@ errlHndl_t SMGR_set_state(OCC_STATE i_new_state) // // Name: SMGR_validate_get_valid_states // -// Description: Return a byte of status masks that correspond to the v10 poll +// Description: Return a byte of status masks that correspond to the v20 poll // response definition status byte. // // End Function Specification @@ -1277,6 +1277,11 @@ uint8_t SMGR_validate_get_valid_states(void) l_valid_states |= OCC_SIMICS_ENVIRONMENT; } + if(G_proc_pmcr_owner == PMCR_OWNER_OCC) + { + l_valid_states |= OCC_PMCR_OWNER_POLL_STATUS_MASK; + } + return l_valid_states; }