[V3] sensors: dts: Assert special wakeup on idle cores while reading temperature

Message ID 1506061379-23881-1-git-send-email-shilpa.bhat@linux.vnet.ibm.com
State Changes Requested
Headers show
Series
  • [V3] sensors: dts: Assert special wakeup on idle cores while reading temperature
Related show

Commit Message

Shilpasri G Bhat Sept. 22, 2017, 6:22 a.m.
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>
---
Changes from V2:
- Rebase on msater to use dctl_{set/clear}_special_wakeup()

 core/direct-controls.c |  4 +--
 core/sensor.c          |  2 +-
 hw/dts.c               | 83 +++++++++++++++++++++++++++++++++++++++++---------
 include/cpu.h          |  3 ++
 include/dts.h          |  2 +-
 5 files changed, 76 insertions(+), 18 deletions(-)

Comments

Stewart Smith Oct. 31, 2017, 2:56 a.m. | #1
Shilpasri G Bhat <shilpa.bhat@linux.vnet.ibm.com> writes:
> 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>
> ---
> Changes from V2:
> - Rebase on msater to use dctl_{set/clear}_special_wakeup()
>
>  core/direct-controls.c |  4 +--
>  core/sensor.c          |  2 +-
>  hw/dts.c               | 83 +++++++++++++++++++++++++++++++++++++++++---------
>  include/cpu.h          |  3 ++
>  include/dts.h          |  2 +-
>  5 files changed, 76 insertions(+), 18 deletions(-)
>
> diff --git a/core/direct-controls.c b/core/direct-controls.c
> index 9acdab5..1f44bc7 100644
> --- a/core/direct-controls.c
> +++ b/core/direct-controls.c
> @@ -217,7 +217,7 @@ static int p9_sreset_thread(struct cpu_thread *cpu)
>  	return 0;
>  }
>  
> -static int dctl_set_special_wakeup(struct cpu_thread *t)
> +int dctl_set_special_wakeup(struct cpu_thread *t)
>  {
>  	struct cpu_thread *c = t->primary;
>  	int rc = OPAL_SUCCESS;
> @@ -235,7 +235,7 @@ static int dctl_set_special_wakeup(struct cpu_thread *t)
>  	return rc;
>  }
>  
> -static int dctl_clear_special_wakeup(struct cpu_thread *t)
> +int dctl_clear_special_wakeup(struct cpu_thread *t)
>  {
>  	struct cpu_thread *c = t->primary;
>  	int rc = OPAL_SUCCESS;
> diff --git a/core/sensor.c b/core/sensor.c
> index 57b21bc..0e2a5ca 100644
> --- a/core/sensor.c
> +++ b/core/sensor.c
> @@ -28,7 +28,7 @@ static int64_t opal_sensor_read(uint32_t sensor_hndl, int token,
>  {
>  	switch (sensor_get_family(sensor_hndl)) {
>  	case SENSOR_DTS:
> -		return dts_sensor_read(sensor_hndl, sensor_data);
> +		return dts_sensor_read(sensor_hndl, token, sensor_data);
>  	case SENSOR_OCC:
>  		return occ_sensor_read(sensor_hndl, sensor_data);
>  	default:
> diff --git a/hw/dts.c b/hw/dts.c
> index a10df58..2fda769 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
> @@ -196,7 +207,7 @@ static int dts_read_core_temp_p8(uint32_t pir, struct dts *dts)
>   * Returns the temperature as the max of all zones and a global trip
>   * attribute.
>   */
> -static int dts_read_core_temp_p9(uint32_t pir, struct dts *dts)
> +static int _dts_read_core_temp_p9(u32 pir, struct dts *dts)
>  {
>  	int32_t chip_id = pir_to_chip_id(pir);
>  	int32_t core = pir_to_core_id(pir);
> @@ -225,7 +236,52 @@ 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 struct timer dts_timer;
> +static struct dts_async_data {
> +	struct cpu_thread *cpu;
> +	u32 *sensor_data;
> +	int token;
> +	u8 attr;
> +} dts_async_data;

this means that only one concurrent request can be going on.

We should *not* put that limit here (where we would silently overwrite
previous attempts and end up somewhere really weird)..

Please fix.

Patch

diff --git a/core/direct-controls.c b/core/direct-controls.c
index 9acdab5..1f44bc7 100644
--- a/core/direct-controls.c
+++ b/core/direct-controls.c
@@ -217,7 +217,7 @@  static int p9_sreset_thread(struct cpu_thread *cpu)
 	return 0;
 }
 
-static int dctl_set_special_wakeup(struct cpu_thread *t)
+int dctl_set_special_wakeup(struct cpu_thread *t)
 {
 	struct cpu_thread *c = t->primary;
 	int rc = OPAL_SUCCESS;
@@ -235,7 +235,7 @@  static int dctl_set_special_wakeup(struct cpu_thread *t)
 	return rc;
 }
 
-static int dctl_clear_special_wakeup(struct cpu_thread *t)
+int dctl_clear_special_wakeup(struct cpu_thread *t)
 {
 	struct cpu_thread *c = t->primary;
 	int rc = OPAL_SUCCESS;
diff --git a/core/sensor.c b/core/sensor.c
index 57b21bc..0e2a5ca 100644
--- a/core/sensor.c
+++ b/core/sensor.c
@@ -28,7 +28,7 @@  static int64_t opal_sensor_read(uint32_t sensor_hndl, int token,
 {
 	switch (sensor_get_family(sensor_hndl)) {
 	case SENSOR_DTS:
-		return dts_sensor_read(sensor_hndl, sensor_data);
+		return dts_sensor_read(sensor_hndl, token, sensor_data);
 	case SENSOR_OCC:
 		return occ_sensor_read(sensor_hndl, sensor_data);
 	default:
diff --git a/hw/dts.c b/hw/dts.c
index a10df58..2fda769 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
@@ -196,7 +207,7 @@  static int dts_read_core_temp_p8(uint32_t pir, struct dts *dts)
  * Returns the temperature as the max of all zones and a global trip
  * attribute.
  */
-static int dts_read_core_temp_p9(uint32_t pir, struct dts *dts)
+static int _dts_read_core_temp_p9(u32 pir, struct dts *dts)
 {
 	int32_t chip_id = pir_to_chip_id(pir);
 	int32_t core = pir_to_core_id(pir);
@@ -225,7 +236,52 @@  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 struct timer dts_timer;
+static struct dts_async_data {
+	struct cpu_thread *cpu;
+	u32 *sensor_data;
+	int token;
+	u8 attr;
+} dts_async_data;
+
+static void dts_async_read_temp(struct timer *t __unused, void *data __unused,
+				u64 now __unused)
+{
+	struct dts dts;
+	int rc;
+
+	rc = dctl_set_special_wakeup(dts_async_data.cpu);
+	if (rc)
+		prerror("Failed to set special wakeup on %d (%d)\n",
+			dts_async_data.cpu->pir, rc);
+
+	rc = _dts_read_core_temp_p9(dts_async_data.cpu->pir, &dts);
+	if (!rc) {
+		if (dts_async_data.attr == SENSOR_DTS_ATTR_TEMP_MAX)
+			*dts_async_data.sensor_data = dts.temp;
+		else if (dts_async_data.attr == SENSOR_DTS_ATTR_TEMP_TRIP)
+			*dts_async_data.sensor_data = dts.trip;
+	}
+
+	rc = opal_queue_msg(OPAL_MSG_ASYNC_COMP, NULL, NULL,
+			    dts_async_data.token, rc);
+	if (rc)
+		prerror("Failed to queue async message\n");
+
+	rc = dctl_clear_special_wakeup(dts_async_data.cpu);
+	if (rc)
+		prerror("Failed to clear special wakeup on %d (%d)\n",
+			dts_async_data.cpu->pir, rc);
+}
+
+static int dts_read_core_temp_p9(void)
+{
+	schedule_timer(&dts_timer, usecs_to_tb(1));
+	return OPAL_ASYNC_COMPLETION;
+}
+
+static int dts_read_core_temp(u32 pir, struct dts *dts, u8 attr,
+			      int token, u32 *sensor_data)
 {
 	int rc;
 
@@ -236,8 +292,14 @@  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 */
+		dts_async_data.attr = attr;
+		dts_async_data.cpu = find_cpu_by_pir(pir);
+		if (!dts_async_data.cpu)
+			return OPAL_PARAMETER;
+		dts_async_data.sensor_data = sensor_data;
+		dts_async_data.token = token;
+		rc = dts_read_core_temp_p9();
 		break;
 	default:
 		rc = OPAL_UNSUPPORTED;
@@ -303,20 +365,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 +384,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);
@@ -431,5 +485,6 @@  bool dts_sensor_create_nodes(struct dt_node *sensors)
 		dt_add_property_string(node, "label", "Centaur");
 	}
 
+	init_timer(&dts_timer, dts_async_read_temp, NULL);
 	return true;
 }
diff --git a/include/cpu.h b/include/cpu.h
index 1b622a5..24d7742 100644
--- a/include/cpu.h
+++ b/include/cpu.h
@@ -280,4 +280,7 @@  extern void cpu_idle_delay(unsigned long delay, unsigned long min_pm);
 extern void cpu_set_radix_mode(void);
 extern void cpu_fast_reboot_complete(void);
 
+int dctl_set_special_wakeup(struct cpu_thread *t);
+int dctl_clear_special_wakeup(struct cpu_thread *t);
+
 #endif /* __CPU_H */
diff --git a/include/dts.h b/include/dts.h
index b37919f..17e2e15 100644
--- a/include/dts.h
+++ b/include/dts.h
@@ -19,7 +19,7 @@ 
 
 #include <stdint.h>
 
-extern int64_t dts_sensor_read(uint32_t sensor_hndl, uint32_t *sensor_data);
+extern int64_t dts_sensor_read(u32 sensor_hndl, int token, u32 *sensor_data);
 extern bool dts_sensor_create_nodes(struct dt_node *sensors);
 
 #endif /* __DTS_H */