diff options
-rw-r--r-- | core/sensor.c | 13 | ||||
-rw-r--r-- | doc/device-tree/ibm,opal/sensor-groups.rst | 40 | ||||
-rw-r--r-- | doc/opal-api/opal-sensor-group-clear-156.rst | 42 | ||||
-rw-r--r-- | hw/occ-sensor.c | 15 | ||||
-rw-r--r-- | hw/occ.c | 77 | ||||
-rw-r--r-- | include/opal-api.h | 3 | ||||
-rw-r--r-- | include/skiboot.h | 3 |
7 files changed, 192 insertions, 1 deletions
diff --git a/core/sensor.c b/core/sensor.c index b0d3c5e..57b21bc 100644 --- a/core/sensor.c +++ b/core/sensor.c @@ -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); } diff --git a/doc/device-tree/ibm,opal/sensor-groups.rst b/doc/device-tree/ibm,opal/sensor-groups.rst new file mode 100644 index 0000000..af21e7d --- /dev/null +++ b/doc/device-tree/ibm,opal/sensor-groups.rst @@ -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 = < + }; + }; + }; diff --git a/doc/opal-api/opal-sensor-group-clear-156.rst b/doc/opal-api/opal-sensor-group-clear-156.rst new file mode 100644 index 0000000..cf874af --- /dev/null +++ b/doc/opal-api/opal-sensor-group-clear-156.rst @@ -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 diff --git a/hw/occ-sensor.c b/hw/occ-sensor.c index 87886db..a55acac 100644 --- a/hw/occ-sensor.c +++ b/hw/occ-sensor.c @@ -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) diff --git a/include/opal-api.h b/include/opal-api.h index 8d33c08..12716c5 100644 --- a/include/opal-api.h +++ b/include/opal-api.h @@ -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 */ diff --git a/include/skiboot.h b/include/skiboot.h index db4ca36..4b7d519 100644 --- a/include/skiboot.h +++ b/include/skiboot.h @@ -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 */ |