diff options
author | Shilpasri G Bhat <shilpa.bhat@linux.vnet.ibm.com> | 2017-11-20 11:39:37 +0530 |
---|---|---|
committer | Stewart Smith <stewart@linux.vnet.ibm.com> | 2017-11-20 20:36:07 -0600 |
commit | cbbd16bfbeef40b9f98d9d457fa024a23bfcc23e (patch) | |
tree | 50d77686a5a4f2d7dd22ece23a83464d41e605b0 /hw | |
parent | 701556d2ea9b890a389183907ae484b78c05c665 (diff) | |
download | skiboot-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')
-rw-r--r-- | hw/dts.c | 74 |
1 files changed, 61 insertions, 13 deletions
@@ -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; } } |