Skip to content

Commit

Permalink
sensor-groups: occ: Add support to disable/enable sensor group
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
shilpasri authored and stewartsmith committed Feb 21, 2018
1 parent ad0861c commit 99505c0
Show file tree
Hide file tree
Showing 7 changed files with 465 additions and 267 deletions.
14 changes: 13 additions & 1 deletion core/sensor.c
@@ -1,4 +1,4 @@
/* Copyright 2013-2015 IBM Corp.
/* Copyright 2013-2018 IBM Corp.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -126,6 +126,17 @@ static int opal_sensor_group_clear(u32 group_hndl, int token)
return OPAL_UNSUPPORTED;
}

static int opal_sensor_group_enable(u32 group_hndl, int token, bool enable)
{
switch (sensor_get_family(group_hndl)) {
case SENSOR_OCC:
return occ_sensor_group_enable(group_hndl, token, enable);
default:
break;
}

return OPAL_UNSUPPORTED;
}
void sensor_init(void)
{
sensor_node = dt_new(opal_node, "sensors");
Expand All @@ -139,4 +150,5 @@ void sensor_init(void)
opal_register(OPAL_SENSOR_READ, opal_sensor_read, 3);
opal_register(OPAL_SENSOR_GROUP_CLEAR, opal_sensor_group_clear, 2);
opal_register(OPAL_SENSOR_READ_U64, opal_sensor_read_u64, 3);
opal_register(OPAL_SENSOR_GROUP_ENABLE, opal_sensor_group_enable, 3);
}
46 changes: 46 additions & 0 deletions doc/opal-api/opal-sensor-group-enable-160.rst
@@ -0,0 +1,46 @@
.. _opal-sensor-groups-enable:

OPAL_SENSOR_GROUP_ENABLE
==========================
OPAL call to enable/disable the sensor group using a handle to identify
the type of sensor group provided in the device tree.

For example this call is used to disable/enable copying of sensor
group by OCC to main memory.

The call can be asynchronus, where the token parameter is used to wait
for the completion.

Parameters
----------
::
u32 handle
int token
bool enable

Returns
-------
OPAL_SUCCESS
Success

OPAL_UNSUPPORTED
No support to enable/disable 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
263 changes: 15 additions & 248 deletions hw/occ-sensor.c
@@ -1,4 +1,4 @@
/* Copyright 2017 IBM Corp.
/* Copyright 2017-2018 IBM Corp.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -20,245 +20,7 @@
#include <sensor.h>
#include <device.h>
#include <cpu.h>

/*
* OCC Sensor Data
*
* OCC sensor data will use BAR2 (OCC Common is per physical drawer).
* Starting address is at offset 0x00580000 from BAR2 base address.
* Maximum size is 1.5MB.
*
* -------------------------------------------------------------------------
* | Start (Offset from | End | Size |Description |
* | BAR2 base address) | | | |
* -------------------------------------------------------------------------
* | 0x00580000 | 0x005A57FF |150kB |OCC 0 Sensor Data Block|
* | 0x005A5800 | 0x005CAFFF |150kB |OCC 1 Sensor Data Block|
* | : | : | : | : |
* | 0x00686800 | 0x006ABFFF |150kB |OCC 7 Sensor Data Block|
* | 0x006AC000 | 0x006FFFFF |336kB |Reserved |
* -------------------------------------------------------------------------
*
*
* OCC N Sensor Data Block Layout (150kB)
*
* The sensor data block layout is the same for each OCC N. It contains
* sensor-header-block, sensor-names buffer, sensor-readings-ping buffer and
* sensor-readings-pong buffer.
*
* ----------------------------------------------------------------------------
* | Start (Offset from OCC | End | Size |Description |
* | N Sensor Data Block) | | | |
* ----------------------------------------------------------------------------
* | 0x00000000 | 0x000003FF |1kB |Sensor Data Header Block |
* | 0x00000400 | 0x0000CBFF |50kB |Sensor Names |
* | 0x0000CC00 | 0x0000DBFF |4kB |Reserved |
* | 0x0000DC00 | 0x00017BFF |40kB |Sensor Readings ping buffer|
* | 0x00017C00 | 0x00018BFF |4kB |Reserved |
* | 0x00018C00 | 0x00022BFF |40kB |Sensor Readings pong buffer|
* | 0x00022C00 | 0x000257FF |11kB |Reserved |
* ----------------------------------------------------------------------------
*
* Sensor Data Header Block : This is written once by the OCC during
* initialization after a load or reset. Layout is defined in 'struct
* occ_sensor_data_header'
*
* Sensor Names : This is written once by the OCC during initialization after a
* load or reset. It contains static information for each sensor. The number of
* sensors, format version and length of each sensor is defined in
* 'Sensor Data Header Block'. Format of each sensor name is defined in
* 'struct occ_sensor_name'. The first sensor starts at offset 0 followed
* immediately by the next sensor.
*
* Sensor Readings Ping/Pong Buffer:
* There are two 40kB buffers to store the sensor readings. One buffer that
* is currently being updated by the OCC and one that is available to be read.
* Each of these buffers will be of the same format. The number of sensors and
* the format version of the ping and pong buffers is defined in the
* 'Sensor Data Header Block'.
*
* Each sensor within the ping and pong buffers may be of a different format
* and length. For each sensor the length and format is determined by its
* 'struct occ_sensor_name.structure_type' in the Sensor Names buffer.
*
* --------------------------------------------------------------------------
* | Offset | Byte0 | Byte1 | Byte2 | Byte3 | Byte4 | Byte5 | Byte6 | Byte7 |
* --------------------------------------------------------------------------
* | 0x0000 |Valid | Reserved |
* | |(0x01) | |
* --------------------------------------------------------------------------
* | 0x0008 | Sensor Readings |
* --------------------------------------------------------------------------
* | : | : |
* --------------------------------------------------------------------------
* | 0xA000 | End of Data |
* --------------------------------------------------------------------------
*
*/

#define MAX_OCCS 8
#define MAX_CHARS_SENSOR_NAME 16
#define MAX_CHARS_SENSOR_UNIT 4

#define OCC_SENSOR_DATA_BLOCK_OFFSET 0x00580000
#define OCC_SENSOR_DATA_BLOCK_SIZE 0x00025800

/*
* These should match the definitions inside the OCC source:
* occ/src/occ_405/sensor/sensor_info.c
*/

enum occ_sensor_type {
OCC_SENSOR_TYPE_GENERIC = 0x0001,
OCC_SENSOR_TYPE_CURRENT = 0x0002,
OCC_SENSOR_TYPE_VOLTAGE = 0x0004,
OCC_SENSOR_TYPE_TEMPERATURE = 0x0008,
OCC_SENSOR_TYPE_UTILIZATION = 0x0010,
OCC_SENSOR_TYPE_TIME = 0x0020,
OCC_SENSOR_TYPE_FREQUENCY = 0x0040,
OCC_SENSOR_TYPE_POWER = 0x0080,
OCC_SENSOR_TYPE_PERFORMANCE = 0x0200,
};

enum occ_sensor_location {
OCC_SENSOR_LOC_SYSTEM = 0x0001,
OCC_SENSOR_LOC_PROCESSOR = 0x0002,
OCC_SENSOR_LOC_PARTITION = 0x0004,
OCC_SENSOR_LOC_MEMORY = 0x0008,
OCC_SENSOR_LOC_VRM = 0x0010,
OCC_SENSOR_LOC_OCC = 0x0020,
OCC_SENSOR_LOC_CORE = 0x0040,
OCC_SENSOR_LOC_GPU = 0x0080,
OCC_SENSOR_LOC_QUAD = 0x0100,
};

enum sensor_struct_type {
OCC_SENSOR_READING_FULL = 0x01,
OCC_SENSOR_READING_COUNTER = 0x02,
};

/**
* struct occ_sensor_data_header - Sensor Data Header Block
* @valid: When the value is 0x01 it indicates
* that this header block and the sensor
* names buffer are ready
* @version: Format version of this block
* @nr_sensors: Number of sensors in names, ping and
* pong buffer
* @reading_version: Format version of the Ping/Pong buffer
* @names_offset: Offset to the location of names buffer
* @names_version: Format version of names buffer
* @names_length: Length of each sensor in names buffer
* @reading_ping_offset: Offset to the location of Ping buffer
* @reading_pong_offset: Offset to the location of Pong buffer
* @pad/reserved: Unused data
*/
struct occ_sensor_data_header {
u8 valid;
u8 version;
u16 nr_sensors;
u8 reading_version;
u8 pad[3];
u32 names_offset;
u8 names_version;
u8 name_length;
u16 reserved;
u32 reading_ping_offset;
u32 reading_pong_offset;
} __packed;

/**
* struct occ_sensor_name - Format of Sensor Name
* @name: Sensor name
* @units: Sensor units of measurement
* @gsid: Global sensor id (OCC)
* @freq: Update frequency
* @scale_factor: Scaling factor
* @type: Sensor type as defined in
* 'enum occ_sensor_type'
* @location: Sensor location as defined in
* 'enum occ_sensor_location'
* @structure_type: Indicates type of data structure used
* for the sensor readings in the ping and
* pong buffers for this sensor as defined
* in 'enum sensor_struct_type'
* @reading_offset: Offset from the start of the ping/pong
* reading buffers for this sensor
* @sensor_data: Sensor specific info
* @pad: Padding to fit the size of 48 bytes.
*/
struct occ_sensor_name {
char name[MAX_CHARS_SENSOR_NAME];
char units[MAX_CHARS_SENSOR_UNIT];
u16 gsid;
u32 freq;
u32 scale_factor;
u16 type;
u16 location;
u8 structure_type;
u32 reading_offset;
u8 sensor_data;
u8 pad[8];
} __packed;

/**
* struct occ_sensor_record - Sensor Reading Full
* @gsid: Global sensor id (OCC)
* @timestamp: Time base counter value while updating
* the sensor
* @sample: Latest sample of this sensor
* @sample_min: Minimum value since last OCC reset
* @sample_max: Maximum value since last OCC reset
* @csm_min: Minimum value since last reset request
* by CSM (CORAL)
* @csm_max: Maximum value since last reset request
* by CSM (CORAL)
* @profiler_min: Minimum value since last reset request
* by profiler (CORAL)
* @profiler_max: Maximum value since last reset request
* by profiler (CORAL)
* @job_scheduler_min: Minimum value since last reset request
* by job scheduler(CORAL)
* @job_scheduler_max: Maximum value since last reset request
* by job scheduler (CORAL)
* @accumulator: Accumulator for this sensor
* @update_tag: Count of the number of ticks that have
* passed between updates
* @pad: Padding to fit the size of 48 bytes
*/
struct occ_sensor_record {
u16 gsid;
u64 timestamp;
u16 sample;
u16 sample_min;
u16 sample_max;
u16 csm_min;
u16 csm_max;
u16 profiler_min;
u16 profiler_max;
u16 job_scheduler_min;
u16 job_scheduler_max;
u64 accumulator;
u32 update_tag;
u8 pad[8];
} __packed;

/**
* struct occ_sensor_counter - Sensor Reading Counter
* @gsid: Global sensor id (OCC)
* @timestamp: Time base counter value while updating
* the sensor
* @accumulator: Accumulator/Counter
* @sample: Latest sample of this sensor (0/1)
* @pad: Padding to fit the size of 24 bytes
*/
struct occ_sensor_counter {
u16 gsid;
u64 timestamp;
u64 accumulator;
u8 sample;
u8 pad[5];
} __packed;
#include <occ-sensor.h>

enum sensor_attr {
SENSOR_SAMPLE,
Expand Down Expand Up @@ -696,8 +458,8 @@ static bool check_sensor_sample(struct occ_sensor_data_header *hb, u32 offset)
}

static void add_sensor_node(const char *loc, const char *type, int i, int attr,
struct occ_sensor_name *md, u32 *phandle, u32 pir,
u32 occ_num, u32 chipid)
struct occ_sensor_name *md, u32 *phandle, u32 *ptype,
u32 pir, u32 occ_num, u32 chipid)
{
char name[30];
struct dt_node *node;
Expand All @@ -715,6 +477,8 @@ static void add_sensor_node(const char *loc, const char *type, int i, int attr,
if (md->location == OCC_SENSOR_LOC_CORE)
dt_add_property_cells(node, "ibm,pir", pir);

*ptype = md->type;

if (attr == SENSOR_SAMPLE) {
handler = sensor_handler(occ_num, i, SENSOR_CSM_MAX);
dt_add_property_cells(node, "sensor-data-max", handler);
Expand Down Expand Up @@ -762,7 +526,7 @@ void occ_sensors_init(void)
for_each_chip(chip) {
struct occ_sensor_data_header *hb;
struct occ_sensor_name *md;
u32 *phandles, phcount = 0;
u32 *phandles, *ptype, phcount = 0;

hb = get_sensor_header_block(occ_num);
md = get_names_block(hb);
Expand All @@ -773,6 +537,8 @@ void occ_sensors_init(void)

phandles = malloc(hb->nr_sensors * sizeof(u32));
assert(phandles);
ptype = malloc(hb->nr_sensors * sizeof(u32));
assert(ptype);

for (i = 0; i < hb->nr_sensors; i++) {
const char *type, *loc;
Expand Down Expand Up @@ -805,24 +571,25 @@ void occ_sensors_init(void)
loc = get_sensor_loc_string(md[i].location);

add_sensor_node(loc, type, i, SENSOR_SAMPLE, &md[i],
&phandles[phcount], c->pir, occ_num,
chip->id);
&phandles[phcount], &ptype[phcount],
c->pir, occ_num, chip->id);
phcount++;

/* Add energy sensors */
if (md[i].type == OCC_SENSOR_TYPE_POWER &&
md[i].structure_type == OCC_SENSOR_READING_FULL) {
add_sensor_node(loc, "energy", i,
SENSOR_ACCUMULATOR, &md[i],
&phandles[phcount], c->pir,
occ_num, chip->id);
&phandles[phcount], &ptype[phcount],
c->pir, occ_num, chip->id);
phcount++;
}

}
occ_num++;
occ_add_sensor_groups(sg, phandles, phcount, chip->id);
occ_add_sensor_groups(sg, phandles, ptype, phcount, chip->id);
free(phandles);
free(ptype);
}

if (!occ_num)
Expand Down

0 comments on commit 99505c0

Please sign in to comment.