[Skiboot] [PATCH 2/2] dts: add DIMM temperature sensors

Cedric Le Goater clg at fr.ibm.com
Wed Jun 24 07:50:33 AEST 2015


On 06/23/2015 12:07 AM, Benjamin Herrenschmidt wrote:
> On Mon, 2015-06-22 at 13:53 +0200, Cédric Le Goater wrote:
>> The DIMM temperatures are stored in the Centaur's sensor cache. This 
>> patch adds the necessary interface to read theses values and expose
>> them to the host OS through the sensor framework of OPAL.
> 
> So you are reading the cache via SCOMs to the Centaur. Isn't the cache
> also readable on the PowerBus using MMIOs ? AFAIK that's the path the 
> OCC takes no ?

Yes. This is what the OCC does and it is quite complex ... Do you think 
we should collect the Centaur sensor cache data through a PowerBus 
mapping ? 

Are there some risks of collision using SCOM on the centaur ? I should 
probably add an extra check to see if the cache is enabled or not when 
reading the data or use centaur->scache_disable_count from your recent 
patchset.

The OCC does collect a lot of sensor values which would be interesting
to expose in OPAL, and Linux. But, maybe, using a table in SRAM and/or 
extend the sapphire_table whould be more appropriate.  

Cheers,

C. 

 
>> Signed-off-by: Cédric Le Goater <clg at fr.ibm.com>
>> ---
>>  hw/dts.c |  149 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>>  1 file changed, 149 insertions(+)
>>
>> Index: skiboot.git/hw/dts.c
>> ===================================================================
>> --- skiboot.git.orig/hw/dts.c
>> +++ skiboot.git/hw/dts.c
>> @@ -42,6 +42,7 @@ struct dts {
>>  	uint8_t		valid;
>>  	uint8_t		trip;
>>  	int16_t		temp;
>> +	int8_t		status;
>>  };
>>  
>>  /* Different sensor locations */
>> @@ -209,6 +210,98 @@ static int dts_read_core_temp(uint32_t p
>>  	return rc;
>>  }
>>  
>> +/*
>> + * Centaur Sensor Cache Registers
>> + */
>> +#define CENTAUR_SCAC_DATA0_3	0x020115CA
>> +#define CENTAUR_SCAC_DATA4_7	0x020115CB
>> +#define CENTAUR_SCAC_ENABLE	0x020115CC
>> +#define CENTAUR_SCAC_LFIR	0x020115C0
>> +
>> +enum centaur_scac_status {
>> +	SCAC_STATUS_STALLED_OR_DISABLED	= 0x0, /* should check LFIR */
>> +	SCAC_STATUS_ERROR		= 0x1, /* should check LFIR */
>> +	SCAC_STATUS_VALID_READING	= 0x2,
>> +	SCAC_STATUS_VALID_READING_NEW	= 0x3  /* First read */
>> +};
>> +
>> +/*
>> + * 0		Critical Trip Alarm
>> + * 1		Above Window Alarm
>> + * 2		Below Window Alarm
>> + * 3		Temperature Sign Bit
>> + * [4:13]	Temperature = A(4:11) + B(12:13) (Celsius)
>> + * [14:15]	Status Indicator (see enum centaur_scac_status)
>> + */
>> +static void dts_decode_one_dimm_dts(uint16_t raw, struct dts *dts)
>> +{
>> +	uint8_t sign;
>> +
>> +	dts->status = raw & 0x3;
>> +	dts->valid  = raw & 0x2;
>> +	dts->temp   = ((raw >> 4) & 0xff) + ((raw >> 2) & 0x3);
>> +	dts->trip   = (raw >> 13) & 0x7;
>> +
>> +	sign = (raw >> 12) & 0x1;
>> +	if (sign)
>> +		dts->temp *= -1;
>> +}
>> +
>> +#define MAX_DIMMS 8
>> +
>> +static const uint64_t scac_data_addrs[MAX_DIMMS] = {
>> +	[0 ... 3] = CENTAUR_SCAC_DATA0_3,
>> +	[4 ... 7] = CENTAUR_SCAC_DATA4_7
>> +};
>> +
>> +static int dts_read_dimm_temp(uint32_t chip_id, uint8_t dimm_id,
>> +			      struct dts *dts)
>> +{
>> +	uint64_t data;
>> +	uint64_t enable;
>> +	int rc;
>> +	struct dts temps[4];
>> +
>> +	if (dimm_id >= MAX_DIMMS) {
>> +		prerror("DTS: Chip %x Dimm %x does not exist\n", chip_id,
>> +		       dimm_id);
>> +		return OPAL_PARAMETER;
>> +	}
>> +
>> +	rc = xscom_read(chip_id, CENTAUR_SCAC_ENABLE, &enable);
>> +	if (rc)
>> +		return rc;
>> +
>> +	if (!(enable & PPC_BIT(dimm_id))) {
>> +		prerror("DTS: Chip %x Dimm %x is disabled\n", chip_id,
>> +		       dimm_id);
>> +		return OPAL_RESOURCE;
>> +	}
>> +
>> +	rc = xscom_read(chip_id, scac_data_addrs[dimm_id], &data);
>> +	if (rc)
>> +		return rc;
>> +
>> +	dts_decode_one_dimm_dts(data >> 48, &temps[0]);
>> +	dts_decode_one_dimm_dts(data >> 32, &temps[1]);
>> +	dts_decode_one_dimm_dts(data >> 16, &temps[2]);
>> +	dts_decode_one_dimm_dts(data >> 0,  &temps[3]);
>> +
>> +	memcpy(dts, &temps[dimm_id % 4], sizeof(*dts));
>> +
>> +	if (!dts->valid) {
>> +		uint64_t lfir;
>> +
>> +		xscom_read(chip_id, CENTAUR_SCAC_LFIR, &lfir);
>> +		prerror("DTS: Chip %x Dimm %x invalid status:%x fir:%016llx\n",
>> +			chip_id, dimm_id, dts->status, lfir);
>> +		return OPAL_HARDWARE;
>> +	}
>> +
>> +	prlog(PR_TRACE, "DTS: Chip %x Dimm %x temp:%dC trip:%x status:%x\n",
>> +	      chip_id, dimm_id, dts->temp, dts->trip, dts->status);
>> +	return 0;
>> +}
>>  
>>  /* Different sensor locations */
>>  #define P8_MEM_DTS0	0
>> @@ -261,6 +354,7 @@ static int dts_read_mem_temp(uint32_t ch
>>  enum sensor_dts_class {
>>  	SENSOR_DTS_CORE_TEMP,
>>  	SENSOR_DTS_MEM_TEMP,
>> +	SENSOR_DTS_DIMM_TEMP,
>>  	/* To be continued */
>>  };
>>  
>> @@ -277,6 +371,7 @@ enum {
>>   * resource identifier field of the sensor handler
>>   */
>>  #define centaur_get_id(rid) (0x80000000 | ((rid) & 0x3ff))
>> +#define dimm_get_id(rid) ((rid) >> 10)
>>  
>>  int64_t dts_sensor_read(uint32_t sensor_hndl, uint32_t *sensor_data)
>>  {
>> @@ -297,6 +392,10 @@ int64_t dts_sensor_read(uint32_t sensor_
>>  	case SENSOR_DTS_MEM_TEMP:
>>  		rc = dts_read_mem_temp(centaur_get_id(rid), &dts);
>>  		break;
>> +	case SENSOR_DTS_DIMM_TEMP:
>> +		rc = dts_read_dimm_temp(centaur_get_id(rid), dimm_get_id(rid),
>> +					&dts);
>> +		break;
>>  	default:
>>  		rc = OPAL_PARAMETER;
>>  		break;
>> @@ -333,11 +432,16 @@ int64_t dts_sensor_read(uint32_t sensor_
>>  	sensor_make_handler(SENSOR_DTS_MEM_TEMP|SENSOR_DTS,		\
>>  			    centaur_make_id(chip_id, 0), attr_id)
>>  
>> +#define dimm_handler(cen_id, dimm_id, attr_id)				\
>> +	sensor_make_handler(SENSOR_DTS_DIMM_TEMP|SENSOR_DTS,		\
>> +			    centaur_make_id(chip_id, i), attr_id)
>> +
>>  bool dts_sensor_create_nodes(struct dt_node *sensors)
>>  {
>>  	struct proc_chip *chip;
>>  	struct dt_node *cn;
>>  	char name[64];
>> +	int dimm_num = 1;
>>  
>>  	/* build the device tree nodes :
>>  	 *
>> @@ -375,6 +479,9 @@ bool dts_sensor_create_nodes(struct dt_n
>>  		uint32_t chip_id;
>>  		struct dt_node *node;
>>  		uint32_t handler;
>> +		uint64_t enable;
>> +		int rc;
>> +		int i;
>>  
>>  		chip_id = dt_prop_get_u32(cn, "ibm,chip-id");
>>  
>> @@ -391,6 +498,48 @@ bool dts_sensor_create_nodes(struct dt_n
>>  		dt_add_property_string(node, "sensor-type", "temp");
>>  		dt_add_property_cells(node, "ibm,chip-id", chip_id);
>>  		dt_add_property_string(node, "label", "Centaur");
>> +
>> +		rc = xscom_read(chip_id, CENTAUR_SCAC_ENABLE, &enable);
>> +		if (rc) {
>> +			prerror("DTS: Chip %x failed to create nodes for DIMMs",
>> +			       chip_id);
>> +			continue;
>> +		}
>> +
>> +		for (i = 0; i < MAX_DIMMS; i++, dimm_num++) {
>> +			if (!(enable & PPC_BIT(i))) {
>> +				prlog(PR_INFO, "DTS: Chip %x Dimm %x is disabled\n",
>> +					chip_id, i);
>> +				continue;
>> +			}
>> +
>> +			snprintf(name, sizeof(name), "dimm-temp@%x-%x",
>> +				 chip_id, i);
>> +
>> +			/*
>> +			 * We only have two bytes for the resource
>> +			 * identifier. Let's trunctate the centaur chip id
>> +			 */
>> +			handler = dimm_handler(chip_id, i,
>> +					       SENSOR_DTS_ATTR_TEMP_MAX);
>> +			node = dt_new(sensors, name);
>> +			dt_add_property_string(node, "compatible",
>> +					       "ibm,opal-sensor");
>> +			dt_add_property_cells(node, "sensor-data", handler);
>> +
>> +			handler = dimm_handler(chip_id, i,
>> +					       SENSOR_DTS_ATTR_TEMP_TRIP);
>> +			dt_add_property_cells(node, "sensor-status", handler);
>> +			dt_add_property_string(node, "sensor-type", "temp");
>> +
>> +			/*
>> +			 *  Use a global increment for the DIMMs. It
>> +			 *  gives a quick idea on how slots are
>> +			 *  populated on the system.
>> +			 */
>> +			snprintf(name, sizeof(name), "Dimm %d", dimm_num);
>> +			dt_add_property_string(node, "label", name);
>> +		}
>>  	}
>>  
>>  	return true;
>>
>> _______________________________________________
>> Skiboot mailing list
>> Skiboot at lists.ozlabs.org
>> https://lists.ozlabs.org/listinfo/skiboot
> 
> 



More information about the Skiboot mailing list