summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoel Stanley <joel@jms.id.au>2014-09-24 14:44:20 +1000
committerJeremy Kerr <jk@ozlabs.org>2015-03-04 16:02:20 +0800
commit81791e5da50b9804a19f2bfbc25916791b28d499 (patch)
treec6a4922b4a687f9353c7246cb9bab6b7712c6f52
parent0f2343075276a6bcc15c679b4270d0843e002da0 (diff)
downloadtalos-skiboot-81791e5da50b9804a19f2bfbc25916791b28d499.tar.gz
talos-skiboot-81791e5da50b9804a19f2bfbc25916791b28d499.zip
hw/ipmi: Add API for setting sensors
This allows setting a given IPMI sensor to a given value. There are helpers for setting the firmware boot progress that will be used for updating the BMC with the host boot progress. The sensor ids are parsed from the device tree. If the sensor cannot be found we will silently continue. Signed-off-by: Joel Stanley <joel@jms.id.au>
-rw-r--r--hw/ipmi/Makefile.inc3
-rw-r--r--hw/ipmi/ipmi-sensor.c102
-rw-r--r--include/ipmi.h9
3 files changed, 113 insertions, 1 deletions
diff --git a/hw/ipmi/Makefile.inc b/hw/ipmi/Makefile.inc
index 1c358a91..06cdc96c 100644
--- a/hw/ipmi/Makefile.inc
+++ b/hw/ipmi/Makefile.inc
@@ -1,6 +1,7 @@
SUBDIRS += hw/ipmi
IPMI_OBJS = ipmi-rtc.o ipmi-power.o ipmi-opal.o ipmi-fru.o ipmi-sel.o
-IPMI_OBJS += ipmi-watchdog.o
+IPMI_OBJS += ipmi-watchdog.o ipmi-sensor.o
+
IPMI = hw/ipmi/built-in.o
$(IPMI): $(IPMI_OBJS:%=hw/ipmi/%)
diff --git a/hw/ipmi/ipmi-sensor.c b/hw/ipmi/ipmi-sensor.c
new file mode 100644
index 00000000..9b08d306
--- /dev/null
+++ b/hw/ipmi/ipmi-sensor.c
@@ -0,0 +1,102 @@
+/* Copyright 2013-2014 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <device.h>
+#include <ipmi.h>
+#include <opal.h>
+#include <skiboot.h>
+#include <string.h>
+
+/* This field controls whether the sensor reading byte is written or left
+ * unchanged according to the sensor */
+#define IPMI_WRITE_SENSOR 0x01
+
+#define FW_PROGRESS_SENSOR 0x0F
+
+/* Ghetto. TODO: Do something smarter */
+int16_t sensors[255];
+
+struct set_sensor_req {
+ u8 sensor;
+ u8 operation;
+ u8 reading[8];
+};
+
+int ipmi_set_fw_progress_sensor(uint8_t state)
+{
+ int fw_sensor_id = sensors[FW_PROGRESS_SENSOR];
+
+ if (fw_sensor_id < 0) {
+ prlog(PR_DEBUG, "SENSOR: fw progress set but not present\n");
+ return OPAL_HARDWARE;
+ }
+
+ return ipmi_set_sensor(fw_sensor_id, &state, sizeof(state));
+}
+
+int ipmi_set_sensor(uint8_t sensor, uint8_t *reading, size_t len)
+{
+ struct ipmi_msg *msg;
+ struct set_sensor_req request;
+
+ if (!ipmi_present())
+ return OPAL_CLOSED;
+
+ if (len > 8) {
+ prlog(PR_ERR, "IPMI: sensor setting length %zd invalid\n",
+ len);
+ return OPAL_PARAMETER;
+ }
+
+ memset(&request, 0, sizeof(request));
+
+ request.sensor = sensor;
+ request.operation = IPMI_WRITE_SENSOR;
+ memcpy(request.reading, reading, len);
+
+ prlog(PR_INFO, "IPMI: setting sensor %02x to %02x ...\n",
+ request.sensor, request.reading[0]);
+
+ /* Send the minimial length message: header plus the reading bytes */
+ msg = ipmi_mkmsg_simple(IPMI_SET_SENSOR_READING, &request, len + 2);
+ if (!msg)
+ return OPAL_HARDWARE;
+
+ return ipmi_queue_msg(msg);
+}
+
+void ipmi_sensor_init(void)
+{
+ struct dt_node *n;
+ const struct dt_property *type, *num;
+
+ memset(sensors, -1, sizeof(sensors));
+
+ dt_for_each_compatible(dt_root, n, "ibm,ipmi-sensor") {
+ type = dt_find_property(n, "ipmi-sensor-type");
+ if (!type) {
+ prerror("IPMI: sensor doesn't have ipmi-sensor-type\n");
+ continue;
+ }
+
+ num = dt_find_property(n, "reg");
+ if (!num) {
+ prerror("IPMI: sensor doesn't have reg property\n");
+ continue;
+ }
+ sensors[(uint8_t)num->prop[0]] = type->prop[0];
+ }
+}
diff --git a/include/ipmi.h b/include/ipmi.h
index de5a61b6..0b403ebc 100644
--- a/include/ipmi.h
+++ b/include/ipmi.h
@@ -89,6 +89,7 @@
#define IPMI_NETFN(code) ((code) >> 8 & 0xff)
#define IPMI_NETFN_CHASSIS 0x00
+#define IPMI_NETFN_SE 0x04
#define IPMI_NETFN_STORAGE 0x0a
#define IPMI_NETFN_APP 0x06
@@ -108,6 +109,7 @@
#define IPMI_GET_MESSAGE_FLAGS IPMI_CODE(IPMI_NETFN_APP, 0x31)
#define IPMI_GET_MESSAGE IPMI_CODE(IPMI_NETFN_APP, 0x33)
#define IPMI_READ_EVENT IPMI_CODE(IPMI_NETFN_APP, 0x35)
+#define IPMI_SET_SENSOR_READING IPMI_CODE(IPMI_NETFN_SE, 0x30)
/* AMI OEM comamnds. AMI uses NETFN 0x3a and 0x32 */
#define IPMI_PARTIAL_ADD_ESEL IPMI_CODE(0x32, 0xf0)
@@ -210,6 +212,10 @@ int ipmi_chassis_control(uint8_t request);
* use chassis control to perform power off and reboot. */
int ipmi_set_power_state(uint8_t system, uint8_t device);
+/* 35.17 Set Sensor Reading Command */
+int ipmi_set_sensor(uint8_t sensor, uint8_t *reading, size_t len);
+int ipmi_set_fw_progress_sensor(uint8_t state);
+
/* Register a backend with the ipmi core. Currently we only support one. */
void ipmi_register_backend(struct ipmi_backend *backend);
@@ -239,4 +245,7 @@ void ipmi_wdt_stop(void);
* reset and does not schedule future resets. */
void ipmi_wdt_final_reset(void);
+/* Discover id of settable ipmi sensors */
+void ipmi_sensor_init(void);
+
#endif
OpenPOWER on IntegriCloud