summaryrefslogtreecommitdiffstats
path: root/sys/dev/ofw
diff options
context:
space:
mode:
authornwhitehorn <nwhitehorn@FreeBSD.org>2010-05-16 15:56:59 +0000
committernwhitehorn <nwhitehorn@FreeBSD.org>2010-05-16 15:56:59 +0000
commit5236db452d5b06e3faf03f1827771f70170b6c71 (patch)
treef0f09cf22154126476afdd90af6bf8dee7567b20 /sys/dev/ofw
parent2f3db6c19db76e7ee197d4431d9d8b7c786c55cd (diff)
downloadFreeBSD-src-5236db452d5b06e3faf03f1827771f70170b6c71.zip
FreeBSD-src-5236db452d5b06e3faf03f1827771f70170b6c71.tar.gz
On PowerMac11,2 and (presumably) PowerMac12,1, we need to quiesce the
firmware in order to take over control of the SMU. Without doing this, the firmware background process doing fan control will run amok as we take over the system and crash the management chip. This is limited to these two machines because our kernel is heavily dependent on firmware accesses, and so quiescing firmware can cause nasty problems.
Diffstat (limited to 'sys/dev/ofw')
-rw-r--r--sys/dev/ofw/ofw_if.m7
-rw-r--r--sys/dev/ofw/ofw_standard.c19
-rw-r--r--sys/dev/ofw/openfirm.c9
-rw-r--r--sys/dev/ofw/openfirm.h1
4 files changed, 36 insertions, 0 deletions
diff --git a/sys/dev/ofw/ofw_if.m b/sys/dev/ofw/ofw_if.m
index 902f071..d2d323b 100644
--- a/sys/dev/ofw/ofw_if.m
+++ b/sys/dev/ofw/ofw_if.m
@@ -340,6 +340,13 @@ METHOD void release {
# Commands for returning control to the firmware
/**
+ * @brief Turn off firmware background activities
+ */
+METHOD void quiesce {
+ ofw_t _ofw;
+};
+
+/**
* @brief Temporarily return control to firmware.
*/
METHOD void enter {
diff --git a/sys/dev/ofw/ofw_standard.c b/sys/dev/ofw/ofw_standard.c
index e521fa0..5eecf77 100644
--- a/sys/dev/ofw/ofw_standard.c
+++ b/sys/dev/ofw/ofw_standard.c
@@ -105,6 +105,7 @@ static ssize_t ofw_std_write(ofw_t ofw, ihandle_t instance, const void *addr,
static int ofw_std_seek(ofw_t ofw, ihandle_t instance, uint64_t pos);
static caddr_t ofw_std_claim(ofw_t ofw, void *virt, size_t size, u_int align);
static void ofw_std_release(ofw_t ofw, void *virt, size_t size);
+static void ofw_std_quiesce(ofw_t ofw);
static void ofw_std_enter(ofw_t ofw);
static void ofw_std_exit(ofw_t ofw);
@@ -133,6 +134,7 @@ static ofw_method_t ofw_std_methods[] = {
OFWMETHOD(ofw_seek, ofw_std_seek),
OFWMETHOD(ofw_claim, ofw_std_claim),
OFWMETHOD(ofw_release, ofw_std_release),
+ OFWMETHOD(ofw_quiesce, ofw_std_quiesce),
OFWMETHOD(ofw_enter, ofw_std_enter),
OFWMETHOD(ofw_exit, ofw_std_exit),
@@ -730,6 +732,23 @@ ofw_std_release(ofw_t ofw, void *virt, size_t size)
* Control transfer functions
*/
+/* Turn off OF background tasks */
+static void
+ofw_std_quiesce(ofw_t ofw)
+{
+ struct {
+ cell_t name;
+ cell_t nargs;
+ cell_t nreturns;
+ } args = {
+ (cell_t)"quiesce",
+ 0,
+ 0,
+ };
+
+ openfirmware(&args);
+}
+
/* Suspend and drop back to the Open Firmware interface. */
static void
ofw_std_enter(ofw_t ofw)
diff --git a/sys/dev/ofw/openfirm.c b/sys/dev/ofw/openfirm.c
index 17cda68..a560e93 100644
--- a/sys/dev/ofw/openfirm.c
+++ b/sys/dev/ofw/openfirm.c
@@ -409,6 +409,15 @@ OF_release(void *virt, size_t size)
* Control transfer functions
*/
+/* Turn off OF background tasks */
+void
+OF_quiesce()
+{
+
+ OFW_QUIESCE(ofw_obj);
+}
+
+
/* Suspend and drop back to the Open Firmware interface. */
void
OF_enter()
diff --git a/sys/dev/ofw/openfirm.h b/sys/dev/ofw/openfirm.h
index 10e8aad..08cbaf3 100644
--- a/sys/dev/ofw/openfirm.h
+++ b/sys/dev/ofw/openfirm.h
@@ -133,6 +133,7 @@ void *OF_claim(void *virtrequest, size_t size, u_int align);
void OF_release(void *virt, size_t size);
/* Control transfer functions */
+void OF_quiesce(void);
void OF_enter(void);
void OF_exit(void) __attribute__((noreturn));
OpenPOWER on IntegriCloud