aboutsummaryrefslogtreecommitdiff
path: root/hw/dts.c
diff options
context:
space:
mode:
authorShilpasri G Bhat <shilpa.bhat@linux.vnet.ibm.com>2017-11-20 11:39:37 +0530
committerStewart Smith <stewart@linux.vnet.ibm.com>2017-11-20 20:36:07 -0600
commitcbbd16bfbeef40b9f98d9d457fa024a23bfcc23e (patch)
tree50d77686a5a4f2d7dd22ece23a83464d41e605b0 /hw/dts.c
parent701556d2ea9b890a389183907ae484b78c05c665 (diff)
downloadskiboot-cbbd16bfbeef40b9f98d9d457fa024a23bfcc23e.zip
skiboot-cbbd16bfbeef40b9f98d9d457fa024a23bfcc23e.tar.gz
skiboot-cbbd16bfbeef40b9f98d9d457fa024a23bfcc23e.tar.bz2
sensors: dts: Assert special wakeup on idle cores while reading temperature
In P9, when a core enters a stop state, its clocks will be stopped to save power and hence we will not be able to perform a scom operation to read the DTS temperature sensor. Hence, assert a special wakeup on cores that have entered a stop state in order to successfully complete the scom operation. Signed-off-by: Shilpasri G Bhat <shilpa.bhat@linux.vnet.ibm.com> [rlippert@google.com: Clear special wakeup only when it succeeds] Signed-off-by: Stewart Smith <stewart@linux.vnet.ibm.com>
Diffstat (limited to 'hw/dts.c')
-rw-r--r--hw/dts.c74
1 files changed, 61 insertions, 13 deletions
diff --git a/hw/dts.c b/hw/dts.c
index a10df58..72a392b 100644
--- a/hw/dts.c
+++ b/hw/dts.c
@@ -20,6 +20,9 @@
#include <dts.h>
#include <skiboot.h>
#include <opal-api.h>
+#include <opal-msg.h>
+#include <timer.h>
+#include <timebase.h>
struct dts {
uint8_t valid;
@@ -27,6 +30,14 @@ struct dts {
int16_t temp;
};
+/*
+ * Attributes for the core temperature sensor
+ */
+enum {
+ SENSOR_DTS_ATTR_TEMP_MAX,
+ SENSOR_DTS_ATTR_TEMP_TRIP
+};
+
/* Different sensor locations */
#define P7_CT_ZONE_LSU 0
#define P7_CT_ZONE_ISU 1
@@ -225,8 +236,37 @@ static int dts_read_core_temp_p9(uint32_t pir, struct dts *dts)
return 0;
}
-static int dts_read_core_temp(uint32_t pir, struct dts *dts)
+static void dts_async_read_temp(struct timer *t __unused, void *data,
+ u64 now __unused)
+{
+ struct dts dts;
+ int rc, swkup_rc;
+ struct cpu_thread *cpu = data;
+
+ swkup_rc = dctl_set_special_wakeup(cpu);
+
+ rc = dts_read_core_temp_p9(cpu->pir, &dts);
+ if (!rc) {
+ if (cpu->sensor_attr == SENSOR_DTS_ATTR_TEMP_MAX)
+ *(u32 *)cpu->sensor_data = dts.temp;
+ else if (cpu->sensor_attr == SENSOR_DTS_ATTR_TEMP_TRIP)
+ *(u32 *)cpu->sensor_data = dts.trip;
+ }
+
+ if (!swkup_rc)
+ dctl_clear_special_wakeup(cpu);
+
+ rc = opal_queue_msg(OPAL_MSG_ASYNC_COMP, NULL, NULL, cpu->token, rc);
+ if (rc)
+ prerror("Failed to queue async message\n");
+
+ cpu->dts_read_in_progress = false;
+}
+
+static int dts_read_core_temp(u32 pir, struct dts *dts, u8 attr,
+ int token, u32 *sensor_data)
{
+ struct cpu_thread *cpu;
int rc;
switch (proc_gen) {
@@ -236,8 +276,22 @@ static int dts_read_core_temp(uint32_t pir, struct dts *dts)
case proc_gen_p8:
rc = dts_read_core_temp_p8(pir, dts);
break;
- case proc_gen_p9:
- rc = dts_read_core_temp_p9(pir, dts);
+ case proc_gen_p9: /* Asynchronus read */
+ cpu = find_cpu_by_pir(pir);
+ if (!cpu)
+ return OPAL_PARAMETER;
+ lock(&cpu->dts_lock);
+ if (cpu->dts_read_in_progress) {
+ unlock(&cpu->dts_lock);
+ return OPAL_BUSY;
+ }
+ cpu->dts_read_in_progress = true;
+ cpu->sensor_attr = attr;
+ cpu->sensor_data = sensor_data;
+ cpu->token = token;
+ schedule_timer(&cpu->dts_timer, 0);
+ rc = OPAL_ASYNC_COMPLETION;
+ unlock(&cpu->dts_lock);
break;
default:
rc = OPAL_UNSUPPORTED;
@@ -303,20 +357,12 @@ enum sensor_dts_class {
};
/*
- * Attributes for the core temperature sensor
- */
-enum {
- SENSOR_DTS_ATTR_TEMP_MAX,
- SENSOR_DTS_ATTR_TEMP_TRIP
-};
-
-/*
* Extract the centaur chip id which was truncated to fit in the
* resource identifier field of the sensor handler
*/
#define centaur_get_id(rid) (0x80000000 | ((rid) & 0x3ff))
-int64_t dts_sensor_read(uint32_t sensor_hndl, uint32_t *sensor_data)
+int64_t dts_sensor_read(u32 sensor_hndl, int token, u32 *sensor_data)
{
uint8_t attr = sensor_get_attr(sensor_hndl);
uint32_t rid = sensor_get_rid(sensor_hndl);
@@ -330,7 +376,7 @@ int64_t dts_sensor_read(uint32_t sensor_hndl, uint32_t *sensor_data)
switch (sensor_get_frc(sensor_hndl)) {
case SENSOR_DTS_CORE_TEMP:
- rc = dts_read_core_temp(rid, &dts);
+ rc = dts_read_core_temp(rid, &dts, attr, token, sensor_data);
break;
case SENSOR_DTS_MEM_TEMP:
rc = dts_read_mem_temp(centaur_get_id(rid), &dts);
@@ -403,6 +449,8 @@ bool dts_sensor_create_nodes(struct dt_node *sensors)
dt_add_property_string(node, "sensor-type", "temp");
dt_add_property_cells(node, "ibm,pir", c->pir);
dt_add_property_string(node, "label", "Core");
+ init_timer(&c->dts_timer, dts_async_read_temp, c);
+ c->dts_read_in_progress = false;
}
}