svn commit: r345789 - head/sys/powerpc/powernv
Justin Hibbits
jhibbits at FreeBSD.org
Tue Sep 3 14:06:23 UTC 2019
Author: jhibbits
Date: Tue Apr 2 04:00:01 2019
New Revision: 345789
URL: https://svnweb.freebsd.org/changeset/base/345789
Log:
powerpc/powernv: Add OPAL heartbeat thread
Summary:
OPAL needs to be kicked periodically in order for the firmware to make
progress on its tasks. To do so, create a heartbeat thread to perform this task
every N milliseconds, defined by the device tree. This task is also a central
location to handle all messages received from OPAL.
Reviewed By: luporl
Differential Revision: https://reviews.freebsd.org/D19743
Modified:
head/sys/powerpc/powernv/opal.h
head/sys/powerpc/powernv/opal_dev.c
Modified: head/sys/powerpc/powernv/opal.h
==============================================================================
--- head/sys/powerpc/powernv/opal.h Mon Apr 1 23:37:21 2019 (r345788)
+++ head/sys/powerpc/powernv/opal.h Tue Apr 2 04:00:01 2019 (r345789)
@@ -31,6 +31,7 @@
#include <sys/cdefs.h>
#include <sys/types.h>
+#include <sys/eventhandler.h>
/* Check if OPAL is correctly instantiated. Will try to instantiate it. */
int opal_check(void);
@@ -72,6 +73,7 @@ int opal_call(uint64_t token, ...);
#define OPAL_RETURN_CPU 69
#define OPAL_REINIT_CPUS 70
#define OPAL_CHECK_TOKEN 80
+#define OPAL_GET_MSG 85
#define OPAL_CHECK_ASYNC_COMPLETION 86
#define OPAL_SENSOR_READ 88
#define OPAL_HANDLE_HMI 98
@@ -140,6 +142,19 @@ int opal_call(uint64_t token, ...);
#define OPAL_TOKEN_ABSENT 0
#define OPAL_TOKEN_PRESENT 1
+#define OPAL_EVENT_OPAL_INTERNAL 0x1
+#define OPAL_EVENT_NVRAM 0x2
+#define OPAL_EVENT_RTC 0x4
+#define OPAL_EVENT_CONSOLE_INPUT 0x8
+#define OPAL_EVENT_CONSOLE_OUTPUT 0x10
+#define OPAL_EVENT_ERROR_LOG_AVAIL 0x20
+#define OPAL_EVENT_ERROR_LOG 0x40
+#define OPAL_EVENT_EPOW 0x80
+#define OPAL_EVENT_LED_STATUS 0x100
+#define OPAL_EVENT_PCI_ERROR 0x200
+#define OPAL_EVENT_DUMP_AVAIL 0x400
+#define OPAL_EVENT_MSG_PENDING 0x800
+
#define OPAL_HMI_FLAGS_TB_RESYNC (1ull << 0)
#define OPAL_HMI_FLAGS_DEC_LOST (1ull << 1)
#define OPAL_HMI_FLAGS_HDEC_LOST (1ull << 2)
@@ -188,4 +203,17 @@ int opal_alloc_async_token(void);
void opal_free_async_token(int);
int opal_wait_completion(void *, uint64_t, uint64_t);
+typedef void (*opal_msg_handler_fn)(void *, struct opal_msg *);
+EVENTHANDLER_DECLARE(OPAL_ASYNC_COMP, opal_msg_handler_fn);
+EVENTHANDLER_DECLARE(OPAL_EPOW, opal_msg_handler_fn);
+EVENTHANDLER_DECLARE(OPAL_SHUTDOWN, opal_msg_handler_fn);
+EVENTHANDLER_DECLARE(OPAL_HMI_EVT, opal_msg_handler_fn);
+EVENTHANDLER_DECLARE(OPAL_DPO, opal_msg_handler_fn);
+EVENTHANDLER_DECLARE(OPAL_OCC, opal_msg_handler_fn);
+EVENTHANDLER_LIST_DECLARE(OPAL_ASYNC_COMP);
+EVENTHANDLER_LIST_DECLARE(OPAL_EPOW);
+EVENTHANDLER_LIST_DECLARE(OPAL_SHUTDOWN);
+EVENTHANDLER_LIST_DECLARE(OPAL_HMI_EVT);
+EVENTHANDLER_LIST_DECLARE(OPAL_DPO);
+EVENTHANDLER_LIST_DECLARE(OPAL_OCC);
#endif
Modified: head/sys/powerpc/powernv/opal_dev.c
==============================================================================
--- head/sys/powerpc/powernv/opal_dev.c Mon Apr 1 23:37:21 2019 (r345788)
+++ head/sys/powerpc/powernv/opal_dev.c Tue Apr 2 04:00:01 2019 (r345789)
@@ -35,6 +35,7 @@ __FBSDID("$FreeBSD$");
#include <sys/clock.h>
#include <sys/cpu.h>
#include <sys/kernel.h>
+#include <sys/kthread.h>
#include <sys/reboot.h>
#include <sys/sysctl.h>
#include <sys/endian.h>
@@ -59,6 +60,8 @@ static const struct ofw_bus_devinfo *opaldev_get_devin
device_t child);
static void opal_shutdown(void *arg, int howto);
+static void opal_handle_shutdown_message(void *unused,
+ struct opal_msg *msg);
static void opal_intr(void *);
static device_method_t opaldev_methods[] = {
@@ -94,6 +97,49 @@ static devclass_t opaldev_devclass;
DRIVER_MODULE(opaldev, ofwbus, opaldev_driver, opaldev_devclass, 0, 0);
+static void opal_heartbeat(void);
+static void opal_handle_messages(void);
+
+static struct proc *opal_hb_proc;
+static struct kproc_desc opal_heartbeat_kp = {
+ "opal_heartbeat",
+ opal_heartbeat,
+ &opal_hb_proc
+};
+
+SYSINIT(opal_heartbeat_setup, SI_SUB_KTHREAD_IDLE, SI_ORDER_ANY, kproc_start,
+ &opal_heartbeat_kp);
+
+static int opal_heartbeat_ms;
+EVENTHANDLER_LIST_DEFINE(OPAL_ASYNC_COMP);
+EVENTHANDLER_LIST_DEFINE(OPAL_EPOW);
+EVENTHANDLER_LIST_DEFINE(OPAL_SHUTDOWN);
+EVENTHANDLER_LIST_DEFINE(OPAL_HMI_EVT);
+EVENTHANDLER_LIST_DEFINE(OPAL_DPO);
+EVENTHANDLER_LIST_DEFINE(OPAL_OCC);
+
+#define OPAL_SOFT_OFF 0
+#define OPAL_SOFT_REBOOT 1
+
+static void
+opal_heartbeat(void)
+{
+ uint64_t events;
+
+ if (opal_heartbeat_ms == 0)
+ kproc_exit(0);
+
+ while (1) {
+ events = 0;
+ /* Turn the OPAL state crank */
+ opal_call(OPAL_POLL_EVENTS, vtophys(&events));
+ if (events & OPAL_EVENT_MSG_PENDING)
+ opal_handle_messages();
+ tsleep(opal_hb_proc, 0, "opal",
+ MSEC_2_TICKS(opal_heartbeat_ms));
+ }
+}
+
static int
opaldev_probe(device_t dev)
{
@@ -150,9 +196,13 @@ opaldev_attach(device_t dev)
if (rv == OPAL_SUCCESS)
clock_register(dev, 2000);
+ EVENTHANDLER_REGISTER(OPAL_SHUTDOWN, opal_handle_shutdown_message,
+ NULL, EVENTHANDLER_PRI_ANY);
EVENTHANDLER_REGISTER(shutdown_final, opal_shutdown, NULL,
SHUTDOWN_PRI_LAST);
+ OF_getencprop(ofw_bus_get_node(dev), "ibm,heartbeat-ms",
+ &opal_heartbeat_ms, sizeof(opal_heartbeat_ms));
/* Bind to interrupts */
for (i = 0; (irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &i,
RF_ACTIVE)) != NULL; i++)
@@ -306,13 +356,68 @@ opal_shutdown(void *arg, int howto)
}
static void
+opal_handle_shutdown_message(void *unused, struct opal_msg *msg)
+{
+ int howto;
+
+ switch (be64toh(msg->params[0])) {
+ case OPAL_SOFT_OFF:
+ howto = RB_POWEROFF;
+ break;
+ case OPAL_SOFT_REBOOT:
+ howto = RB_REROOT;
+ break;
+ }
+ shutdown_nice(howto);
+}
+
+static void
+opal_handle_messages(void)
+{
+ static struct opal_msg msg;
+ uint64_t rv;
+ uint32_t type;
+
+ rv = opal_call(OPAL_GET_MSG, vtophys(&msg), sizeof(msg));
+
+ if (rv != OPAL_SUCCESS)
+ return;
+
+ type = be32toh(msg.msg_type);
+ switch (type) {
+ case OPAL_MSG_ASYNC_COMP:
+ EVENTHANDLER_DIRECT_INVOKE(OPAL_ASYNC_COMP, &msg);
+ break;
+ case OPAL_MSG_EPOW:
+ EVENTHANDLER_DIRECT_INVOKE(OPAL_EPOW, &msg);
+ break;
+ case OPAL_MSG_SHUTDOWN:
+ EVENTHANDLER_DIRECT_INVOKE(OPAL_SHUTDOWN, &msg);
+ break;
+ case OPAL_MSG_HMI_EVT:
+ EVENTHANDLER_DIRECT_INVOKE(OPAL_HMI_EVT, &msg);
+ break;
+ case OPAL_MSG_DPO:
+ EVENTHANDLER_DIRECT_INVOKE(OPAL_DPO, &msg);
+ break;
+ case OPAL_MSG_OCC:
+ EVENTHANDLER_DIRECT_INVOKE(OPAL_OCC, &msg);
+ break;
+ default:
+ printf("Unknown OPAL message type %d\n", type);
+ }
+}
+
+static void
opal_intr(void *xintr)
{
uint64_t events = 0;
opal_call(OPAL_HANDLE_INTERRUPT, (uint32_t)(uint64_t)xintr,
vtophys(&events));
- /* XXX: do something useful with this information */
+ /* Wake up the heartbeat, if it's been setup. */
+ if (events != 0 && opal_hb_proc != NULL)
+ wakeup(opal_hb_proc);
}
More information about the svn-src-all
mailing list