aboutsummaryrefslogtreecommitdiff
path: root/hw/occ.c
diff options
context:
space:
mode:
authorShilpasri G Bhat <shilpa.bhat@linux.vnet.ibm.com>2017-12-22 10:34:08 +0530
committerStewart Smith <stewart@linux.vnet.ibm.com>2018-02-21 13:28:08 +1100
commit99505c03f49312c5cc7d40a90728b048857a1078 (patch)
tree819d3ccc264b514f4760f55627d189683116bcb6 /hw/occ.c
parentad0861c914e8b1b7d81da2cbb7decad5b183200e (diff)
downloadskiboot-99505c03f49312c5cc7d40a90728b048857a1078.zip
skiboot-99505c03f49312c5cc7d40a90728b048857a1078.tar.gz
skiboot-99505c03f49312c5cc7d40a90728b048857a1078.tar.bz2
sensor-groups: occ: Add support to disable/enable sensor group
This patch adds a new opal call to enable/disable a sensor group. This call is used to select the sensor groups that needs to be copied to main memory by OCC at runtime. Signed-off-by: Shilpasri G Bhat <shilpa.bhat@linux.vnet.ibm.com> [stewart: rebase and bump OPAL API number] Signed-off-by: Stewart Smith <stewart@linux.vnet.ibm.com>
Diffstat (limited to 'hw/occ.c')
-rw-r--r--hw/occ.c137
1 files changed, 122 insertions, 15 deletions
diff --git a/hw/occ.c b/hw/occ.c
index eae03cd..3e92b9a 100644
--- a/hw/occ.c
+++ b/hw/occ.c
@@ -31,6 +31,7 @@
#include <powercap.h>
#include <psr.h>
#include <sensor.h>
+#include <occ-sensor.h>
/* OCC Communication Area for PStates */
@@ -954,7 +955,7 @@ enum occ_cmd {
OCC_CMD_CLEAR_SENSOR_DATA,
OCC_CMD_SET_POWER_CAP,
OCC_CMD_SET_POWER_SHIFTING_RATIO,
- OCC_CMD_LAST
+ OCC_CMD_SELECT_SENSOR_GROUP,
};
struct opal_occ_cmd_info {
@@ -989,6 +990,13 @@ static struct opal_occ_cmd_info occ_cmds[] = {
PPC_BIT16(OCC_STATE_CHARACTERIZATION),
PPC_BIT8(OCC_ROLE_MASTER) | PPC_BIT8(OCC_ROLE_SLAVE)
},
+ { OCC_CMD_SELECT_SENSOR_GROUP,
+ 0xD3, 2, 2, 1000,
+ PPC_BIT16(OCC_STATE_OBSERVATION) |
+ PPC_BIT16(OCC_STATE_ACTIVE) |
+ PPC_BIT16(OCC_STATE_CHARACTERIZATION),
+ PPC_BIT8(OCC_ROLE_MASTER) | PPC_BIT8(OCC_ROLE_SLAVE)
+ },
};
enum occ_response_status {
@@ -1018,6 +1026,7 @@ static struct cmd_interface {
u8 *valid;
u32 chip_id;
u32 token;
+ u16 enabled_sensor_mask;
u8 occ_role;
u8 request_id;
bool cmd_in_progress;
@@ -1212,6 +1221,10 @@ static void handle_occ_rsp(uint32_t chip_id)
goto exit;
}
+ if (rsp->cmd == occ_cmds[OCC_CMD_SELECT_SENSOR_GROUP].cmd_value &&
+ rsp->status == OCC_RSP_SUCCESS)
+ chip->enabled_sensor_mask = *(u16 *)chip->cdata->data;
+
chip->cmd_in_progress = false;
queue_occ_rsp_msg(chip->token, read_occ_rsp(chip->rsp));
exit:
@@ -1252,6 +1265,7 @@ static void occ_cmd_interface_init(void)
init_lock(&chips[i].queue_lock);
chips[i].cmd_in_progress = false;
chips[i].request_id = 0;
+ chips[i].enabled_sensor_mask = OCC_ENABLED_SENSOR_MASK;
init_timer(&chips[i].timeout, occ_cmd_timeout_handler,
&chips[i]);
i++;
@@ -1503,16 +1517,93 @@ int occ_sensor_group_clear(u32 group_hndl, int token)
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)
+static u16 sensor_enable;
+static struct opal_occ_cmd_data sensor_mask_data = {
+ .data = (u8 *)&sensor_enable,
+ .cmd = OCC_CMD_SELECT_SENSOR_GROUP,
+};
+
+int occ_sensor_group_enable(u32 group_hndl, int token, bool enable)
+{
+ u16 type = sensor_get_rid(group_hndl);
+ u8 i = sensor_get_attr(group_hndl);
+
+ if (i > nr_occs)
+ return OPAL_UNSUPPORTED;
+
+ switch (type) {
+ case OCC_SENSOR_TYPE_GENERIC:
+ case OCC_SENSOR_TYPE_CURRENT:
+ case OCC_SENSOR_TYPE_VOLTAGE:
+ case OCC_SENSOR_TYPE_TEMPERATURE:
+ case OCC_SENSOR_TYPE_UTILIZATION:
+ case OCC_SENSOR_TYPE_TIME:
+ case OCC_SENSOR_TYPE_FREQUENCY:
+ case OCC_SENSOR_TYPE_POWER:
+ case OCC_SENSOR_TYPE_PERFORMANCE:
+ break;
+ default:
+ return OPAL_UNSUPPORTED;
+ }
+
+ if (!(*chips[i].valid))
+ return OPAL_HARDWARE;
+
+ if (enable && (type & chips[i].enabled_sensor_mask))
+ return OPAL_SUCCESS;
+ else if (!enable && !(type & chips[i].enabled_sensor_mask))
+ return OPAL_SUCCESS;
+
+ sensor_enable = enable ? type | chips[i].enabled_sensor_mask :
+ ~type & chips[i].enabled_sensor_mask;
+
+ return opal_occ_command(&chips[i], token, &sensor_mask_data);
+}
+
+void occ_add_sensor_groups(struct dt_node *sg, u32 *phandles, u32 *ptype,
+ int nr_phandles, int chipid)
{
- struct limit_group_info {
- int limit;
+ struct group_info {
+ int type;
const char *str;
- } limits[] = {
- { OCC_SENSOR_LIMIT_GROUP_CSM, "csm" },
- { OCC_SENSOR_LIMIT_GROUP_PROFILER, "profiler" },
- { OCC_SENSOR_LIMIT_GROUP_JOB_SCHED, "js" },
+ u32 ops;
+ } groups[] = {
+ { OCC_SENSOR_LIMIT_GROUP_CSM, "csm",
+ OPAL_SENSOR_GROUP_CLEAR
+ },
+ { OCC_SENSOR_LIMIT_GROUP_PROFILER, "profiler",
+ OPAL_SENSOR_GROUP_CLEAR
+ },
+ { OCC_SENSOR_LIMIT_GROUP_JOB_SCHED, "js",
+ OPAL_SENSOR_GROUP_CLEAR
+ },
+ { OCC_SENSOR_TYPE_GENERIC, "generic",
+ OPAL_SENSOR_GROUP_ENABLE
+ },
+ { OCC_SENSOR_TYPE_CURRENT, "current",
+ OPAL_SENSOR_GROUP_ENABLE
+ },
+ { OCC_SENSOR_TYPE_VOLTAGE, "voltage",
+ OPAL_SENSOR_GROUP_ENABLE
+ },
+ { OCC_SENSOR_TYPE_TEMPERATURE, "temperature",
+ OPAL_SENSOR_GROUP_ENABLE
+ },
+ { OCC_SENSOR_TYPE_UTILIZATION, "utilization",
+ OPAL_SENSOR_GROUP_ENABLE
+ },
+ { OCC_SENSOR_TYPE_TIME, "time",
+ OPAL_SENSOR_GROUP_ENABLE
+ },
+ { OCC_SENSOR_TYPE_FREQUENCY, "frequency",
+ OPAL_SENSOR_GROUP_ENABLE
+ },
+ { OCC_SENSOR_TYPE_POWER, "power",
+ OPAL_SENSOR_GROUP_ENABLE
+ },
+ { OCC_SENSOR_TYPE_PERFORMANCE, "performance",
+ OPAL_SENSOR_GROUP_ENABLE
+ },
};
int i, j;
@@ -1520,14 +1611,14 @@ void occ_add_sensor_groups(struct dt_node *sg, u32 *phandles, int nr_phandles,
if (chips[i].chip_id == chipid)
break;
- for (j = 0; j < ARRAY_SIZE(limits); j++) {
+ for (j = 0; j < ARRAY_SIZE(groups); j++) {
struct dt_node *node;
char name[20];
u32 handle;
- snprintf(name, 20, "occ-%s", limits[j].str);
+ snprintf(name, 20, "occ-%s", groups[j].str);
handle = sensor_make_handler(SENSOR_OCC, 0,
- limits[j].limit, i);
+ groups[j].type, i);
node = dt_new_addr(sg, name, handle);
if (!node) {
prerror("Failed to create sensor group nodes\n");
@@ -1535,11 +1626,27 @@ void occ_add_sensor_groups(struct dt_node *sg, u32 *phandles, int nr_phandles,
}
dt_add_property_cells(node, "sensor-group-id", handle);
- dt_add_property_string(node, "type", limits[j].str);
+ dt_add_property_string(node, "type", groups[j].str);
dt_add_property_cells(node, "ibm,chip-id", chipid);
- dt_add_property(node, "sensors", phandles, nr_phandles);
- dt_add_property_cells(node, "ops", OPAL_SENSOR_GROUP_CLEAR);
dt_add_property_cells(node, "reg", handle);
+ if (groups[j].ops == OPAL_SENSOR_GROUP_ENABLE) {
+ u32 *_phandles;
+ int k, pcount = 0;
+
+ _phandles = malloc(sizeof(u32) * nr_phandles);
+ assert(_phandles);
+ for (k = 0; k < nr_phandles; k++)
+ if (ptype[k] == groups[j].type)
+ _phandles[pcount++] = phandles[k];
+ if (pcount)
+ dt_add_property(node, "sensors", _phandles,
+ pcount);
+ free(_phandles);
+ } else {
+ dt_add_property(node, "sensors", phandles,
+ nr_phandles);
+ }
+ dt_add_property_cells(node, "ops", groups[j].ops);
}
}