Page MenuHomeFreeBSD

D18506.id51846.diff
No OneTemporary

D18506.id51846.diff

Index: sys/dev/efidev/efirt.c
===================================================================
--- sys/dev/efidev/efirt.c
+++ sys/dev/efidev/efirt.c
@@ -34,6 +34,7 @@
#include <sys/param.h>
#include <sys/efi.h>
+#include <sys/eventhandler.h>
#include <sys/kernel.h>
#include <sys/linker.h>
#include <sys/lock.h>
@@ -41,6 +42,7 @@
#include <sys/mutex.h>
#include <sys/clock.h>
#include <sys/proc.h>
+#include <sys/reboot.h>
#include <sys/rwlock.h>
#include <sys/sched.h>
#include <sys/sysctl.h>
@@ -95,6 +97,7 @@
static int efi_enter(void);
static void efi_leave(void);
+static int _efi_reset_system(enum efi_reset);
static int
efi_status_to_errno(efi_status status)
@@ -106,6 +109,10 @@
}
static struct mtx efi_lock;
+static SYSCTL_NODE(_hw, OID_AUTO, efi, CTLFLAG_RWTUN, NULL, "EFI");
+static bool efi_poweroff = true;
+SYSCTL_BOOL(_hw_efi, OID_AUTO, poweroff, CTLFLAG_RWTUN, &efi_poweroff, 0,
+ "If true, use EFI runtime services to shutdown in preference to ACPI");
static bool
efi_is_in_map(struct efi_md *map, int ndesc, int descsz, vm_offset_t addr)
@@ -126,6 +133,19 @@
return (false);
}
+static void
+efi_shutdown_final(void *dummy __unused, int howto)
+{
+
+ /*
+ * On some systems, ACPI S5 is missing or does not function properly.
+ * When present, shutdown via EFI Runtime Services instead, unless
+ * disabled.
+ */
+ if ((howto & RB_POWEROFF) != 0 && efi_poweroff)
+ (void)_efi_reset_system(EFI_RESET_SHUTDOWN);
+}
+
static int
efi_init(void)
{
@@ -214,6 +234,12 @@
}
#endif
+ /*
+ * We use SHUTDOWN_PRI_LAST - 1 to trigger after IPMI, but before ACPI.
+ */
+ EVENTHANDLER_REGISTER(shutdown_final, efi_shutdown_final, NULL,
+ SHUTDOWN_PRI_LAST - 1);
+
return (0);
}
@@ -410,8 +436,8 @@
return (error);
}
-int
-efi_reset_system(void)
+static int
+_efi_reset_system(enum efi_reset type)
{
struct efirt_callinfo ec;
@@ -420,7 +446,7 @@
bzero(&ec, sizeof(ec));
ec.ec_name = "rt_reset";
ec.ec_argcnt = 4;
- ec.ec_arg1 = (uintptr_t)EFI_RESET_WARM;
+ ec.ec_arg1 = (uintptr_t)type;
ec.ec_arg2 = (uintptr_t)0;
ec.ec_arg3 = (uintptr_t)0;
ec.ec_arg4 = (uintptr_t)NULL;
@@ -428,6 +454,13 @@
return (efi_call(&ec));
}
+int
+efi_reset_system(void)
+{
+
+ return (_efi_reset_system(EFI_RESET_WARM));
+}
+
static int
efi_set_time_locked(struct efi_tm *tm)
{
Index: sys/dev/ipmi/ipmi.c
===================================================================
--- sys/dev/ipmi/ipmi.c
+++ sys/dev/ipmi/ipmi.c
@@ -938,14 +938,14 @@
} else if (!on)
(void)ipmi_set_watchdog(sc, 0);
/*
- * Power cycle the system off using IPMI. We use last - 1 since we don't
+ * Power cycle the system off using IPMI. We use last - 2 since we don't
* handle all the other kinds of reboots. We'll let others handle them.
* We only try to do this if the BMC supports the Chassis device.
*/
if (sc->ipmi_dev_support & IPMI_ADS_CHASSIS) {
device_printf(dev, "Establishing power cycle handler\n");
sc->ipmi_power_cycle_tag = EVENTHANDLER_REGISTER(shutdown_final,
- ipmi_power_cycle, sc, SHUTDOWN_PRI_LAST - 1);
+ ipmi_power_cycle, sc, SHUTDOWN_PRI_LAST - 2);
}
}
Index: sys/sys/efi.h
===================================================================
--- sys/sys/efi.h
+++ sys/sys/efi.h
@@ -43,7 +43,8 @@
enum efi_reset {
EFI_RESET_COLD,
- EFI_RESET_WARM
+ EFI_RESET_WARM,
+ EFI_RESET_SHUTDOWN,
};
typedef uint16_t efi_char;

File Metadata

Mime Type
text/plain
Expires
Mon, Feb 9, 3:36 PM (21 h, 35 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28595015
Default Alt Text
D18506.id51846.diff (3 KB)

Event Timeline