@@ -41,6 +41,18 @@ static int64_t opal_sensor_read(uint32_t sensor_hndl, int token,
return OPAL_UNSUPPORTED;
}
+static int opal_sensor_group_clear(u32 group_hndl, int token)
+{
+ switch (sensor_get_family(group_hndl)) {
+ case SENSOR_OCC:
+ return occ_sensor_group_clear(group_hndl, token);
+ default:
+ break;
+ }
+
+ return OPAL_UNSUPPORTED;
+}
+
void sensor_init(void)
{
sensor_node = dt_new(opal_node, "sensors");
@@ -50,4 +62,5 @@ void sensor_init(void)
/* Register OPAL interface */
opal_register(OPAL_SENSOR_READ, opal_sensor_read, 3);
+ opal_register(OPAL_SENSOR_GROUP_CLEAR, opal_sensor_group_clear, 2);
}
new file mode 100644
@@ -0,0 +1,40 @@
+ibm,opal/sensor-groups
+----------------------
+
+This node contains all sensor groups defined in the system.
+Each child node here represents a sensor group.
+
+For example : ::
+ occ-csm@1c00020/
+
+The compatible property is set to "ibm,opal-occ-sensor-group"
+
+Each child node has below properties:
+
+`type`
+ string to indicate the sensor group
+
+`sensor-group-id`
+ Uniquely identifies a sensor group.
+
+`ibm,chip-id`
+ This property is added if the sensor group is chip specific
+
+`sensors`
+ Phandles of all sensors belonging to this sensor group
+
+.. code-block:: dts
+
+ ibm,opal {
+ sensor-groups {
+ compatible = "ibm,opal-occ-sensor-group";
+
+ occ-csm@1c00020 {
+ name = "occ-csm"
+ type = "csm"
+ sensor-group-id = <0x01c00020>
+ ibm,chip-id = <0x00000008>
+ phandles = <
+ };
+ };
+ };
new file mode 100644
@@ -0,0 +1,42 @@
+.. _opal-sensor-groups-clear:
+
+OPAL_SENSOR_GROUP_CLEAR
+==============================
+OPAL call to clear the sensor groups data using a handle to identify
+the type of sensor group which is exported via DT.
+
+The call can be asynchronus, where the token parameter is used to wait
+for the completion.
+
+Parameters
+----------
+::
+ u32 handle
+ int token
+
+Returns
+-------
+OPAL_SUCCESS
+ Success
+
+OPAL_UNSUPPORTED
+ No support for clearing the sensor group
+
+OPAL_HARDWARE
+ Unable to procced due to the current hardware state
+
+OPAL_PERMISSION
+ Hardware cannot take the request
+
+OPAL_ASYNC_COMPLETION
+ Request was sent and an async completion message will be sent with
+ token and status of the request.
+
+OPAL_BUSY
+ Previous request in progress
+
+OPAL_INTERNAL_ERROR
+ Error in request response
+
+OPAL_TIMEOUT
+ Timeout in request completion
@@ -546,6 +546,7 @@ static const char *get_sensor_loc_string(enum occ_sensor_location loc)
void occ_sensors_init(void)
{
struct proc_chip *chip;
+ struct dt_node *sg;
int occ_num = 0, i;
/* OCC inband sensors is only supported in P9 */
@@ -561,9 +562,17 @@ void occ_sensors_init(void)
occ_sensor_base = chip->occ_common_base + OCC_SENSOR_DATA_BLOCK_OFFSET;
+ sg = dt_new(opal_node, "sensor-groups");
+ if (!sg) {
+ prerror("OCC: Failed to create sensor groups node\n");
+ return;
+ }
+ dt_add_property_string(sg, "compatible", "ibm,opal-occ-sensor-group");
+
for_each_chip(chip) {
struct occ_sensor_data_header *hb;
struct occ_sensor_name *md;
+ u32 *phandles, phcount = 0;
hb = get_sensor_header_block(occ_num);
md = get_names_block(hb);
@@ -572,6 +581,9 @@ void occ_sensors_init(void)
if (!occ_sensor_sanity(hb, chip->id))
continue;
+ phandles = malloc(hb->nr_sensors * sizeof(u32));
+ assert(phandles);
+
for (i = 0; i < hb->nr_sensors; i++) {
char name[30];
const char *type, *loc;
@@ -615,7 +627,10 @@ void occ_sensors_init(void)
if (md[i].location == OCC_SENSOR_LOC_CORE)
dt_add_property_cells(node, "ibm,pir", c->pir);
+ phandles[phcount++] = node->phandle;
}
occ_num++;
+ occ_add_sensor_groups(sg, phandles, phcount, chip->id);
+ free(phandles);
}
}
@@ -30,6 +30,7 @@
#include <i2c.h>
#include <powercap.h>
#include <psr.h>
+#include <sensor.h>
/* OCC Communication Area for PStates */
@@ -1459,6 +1460,82 @@ static void occ_add_psr_sensors(struct dt_node *power_mgt)
}
}
+/* OCC clear sensor limits CSM/Profiler/Job-scheduler */
+
+enum occ_sensor_limit_group {
+ OCC_SENSOR_LIMIT_GROUP_CSM = 0x10,
+ OCC_SENSOR_LIMIT_GROUP_PROFILER = 0x20,
+ OCC_SENSOR_LIMIT_GROUP_JOB_SCHED = 0x40,
+};
+
+static u32 sensor_limit;
+static struct opal_occ_cmd_data slimit_data = {
+ .data = (u8 *)&sensor_limit,
+ .cmd = OCC_CMD_CLEAR_SENSOR_DATA,
+};
+
+int occ_sensor_group_clear(u32 group_hndl, int token)
+{
+ u32 limit = sensor_get_rid(group_hndl);
+ u8 i = sensor_get_attr(group_hndl);
+
+ if (i > nr_occs)
+ return OPAL_UNSUPPORTED;
+
+ switch (limit) {
+ case OCC_SENSOR_LIMIT_GROUP_CSM:
+ case OCC_SENSOR_LIMIT_GROUP_PROFILER:
+ case OCC_SENSOR_LIMIT_GROUP_JOB_SCHED:
+ break;
+ default:
+ return OPAL_UNSUPPORTED;
+ }
+
+ if (!(*chips[i].valid))
+ return OPAL_HARDWARE;
+
+ sensor_limit = limit << 24;
+ return opal_occ_command(&chips[i], token, &slimit_data);
+}
+
+void occ_add_sensor_groups(struct dt_node *sg, u32 *phandles, int nr_phandles,
+ int chipid)
+{
+ struct limit_group_info {
+ int limit;
+ const char *str;
+ } limits[] = {
+ { OCC_SENSOR_LIMIT_GROUP_CSM, "csm" },
+ { OCC_SENSOR_LIMIT_GROUP_PROFILER, "profiler" },
+ { OCC_SENSOR_LIMIT_GROUP_JOB_SCHED, "js" },
+ };
+ int i, j;
+
+ for (i = 0; i < nr_occs; i++)
+ if (chips[i].chip_id == chipid)
+ break;
+
+ for (j = 0; j < ARRAY_SIZE(limits); j++) {
+ struct dt_node *node;
+ char name[20];
+ u32 handle;
+
+ snprintf(name, 20, "occ-%s", limits[j].str);
+ handle = sensor_make_handler(SENSOR_OCC, 0,
+ limits[j].limit, i);
+ node = dt_new_addr(sg, name, handle);
+ if (!node) {
+ prerror("Failed to create sensor group nodes\n");
+ return;
+ }
+
+ dt_add_property_cells(node, "sensor-group-id", handle);
+ dt_add_property_string(node, "type", limits[j].str);
+ dt_add_property_cells(node, "ibm,chip-id", chipid);
+ dt_add_property(node, "sensors", phandles, nr_phandles);
+ }
+}
+
/* CPU-OCC PState init */
/* Called after OCC init on P8 and P9 */
void occ_pstates_init(void)
@@ -212,7 +212,8 @@
#define OPAL_SET_POWERCAP 153
#define OPAL_GET_POWER_SHIFT_RATIO 154
#define OPAL_SET_POWER_SHIFT_RATIO 155
-#define OPAL_LAST 155
+#define OPAL_SENSOR_GROUP_CLEAR 156
+#define OPAL_LAST 156
/* Device tree flags */
@@ -313,5 +313,8 @@ extern int fake_nvram_write(uint32_t offset, void *src, uint32_t size);
/* OCC Inband Sensors */
extern void occ_sensors_init(void);
extern int occ_sensor_read(u32 handle, u32 *data);
+extern int occ_sensor_group_clear(u32 group_hndl, int token);
+extern void occ_add_sensor_groups(struct dt_node *sg, u32 *phandles,
+ int nr_phandles, int chipid);
#endif /* __SKIBOOT_H */
Adds a generic API to clear sensor groups. OCC inband sensor groups such as CSM, Profiler and Job Scheduler can be cleared using this API. It will clear the min/max of all sensors belonging to OCC sensor groups. Signed-off-by: Shilpasri G Bhat <shilpa.bhat@linux.vnet.ibm.com> --- Changes from V8: - Add "sensors" phandle array of all sensors belonging to the sensor group - s/OPAL_SENSOR_GROUPS_CLEAR/OPAL_SENSOR_GROUP_CLEAR core/sensor.c | 13 +++++ doc/device-tree/ibm,opal/sensor-groups.rst | 40 +++++++++++++++ doc/opal-api/opal-sensor-group-clear-156.rst | 42 +++++++++++++++ hw/occ-sensor.c | 15 ++++++ hw/occ.c | 77 ++++++++++++++++++++++++++++ include/opal-api.h | 3 +- include/skiboot.h | 3 ++ 7 files changed, 192 insertions(+), 1 deletion(-) create mode 100644 doc/device-tree/ibm,opal/sensor-groups.rst create mode 100644 doc/opal-api/opal-sensor-group-clear-156.rst