Index: head/usr.sbin/powerd/powerd.8
===================================================================
--- head/usr.sbin/powerd/powerd.8
+++ head/usr.sbin/powerd/powerd.8
@@ -24,7 +24,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd July 4, 2013
+.Dd January 6, 2019
 .Dt POWERD 8
 .Os
 .Sh NAME
@@ -41,6 +41,7 @@
 .Op Fl p Ar ival
 .Op Fl P Ar pidfile
 .Op Fl r Ar percent
+.Op Fl s Ar source
 .Op Fl v
 .Sh DESCRIPTION
 The
@@ -117,6 +118,14 @@
 Specifies the CPU load percent level where adaptive
 mode should consider the CPU running and increase performance.
 The default is 75% or higher.
+.It Fl s Ar source
+Enforces method for AC line state refresh; by default, it is chosen
+automatically.
+The set of valid methods is
+.Cm sysctl , devd
+and
+.Cm apm
+(i386 only).
 .It Fl v
 Verbose mode.
 Messages about power changes will be printed to stdout and
Index: head/usr.sbin/powerd/powerd.c
===================================================================
--- head/usr.sbin/powerd/powerd.c
+++ head/usr.sbin/powerd/powerd.c
@@ -113,14 +113,16 @@
 
 static volatile sig_atomic_t exit_requested;
 static power_src_t acline_status;
-static enum {
+typedef enum {
 	ac_none,
 	ac_sysctl,
 	ac_acpi_devd,
 #ifdef USE_APM
 	ac_apm,
 #endif
-} acline_mode;
+} acline_mode_t;
+static acline_mode_t acline_mode;
+static acline_mode_t acline_mode_user = ac_none;
 #ifdef USE_APM
 static int	apm_fd = -1;
 #endif
@@ -286,21 +288,28 @@
 static void
 acline_init(void)
 {
+	int skip_source_check;
+
 	acline_mib_len = 4;
 	acline_status = SRC_UNKNOWN;
+	skip_source_check = (acline_mode_user == ac_none ||
+			     acline_mode_user == ac_acpi_devd);
 
-	if (sysctlnametomib(ACPIAC, acline_mib, &acline_mib_len) == 0) {
+	if ((skip_source_check || acline_mode_user == ac_sysctl) &&
+	    sysctlnametomib(ACPIAC, acline_mib, &acline_mib_len) == 0) {
 		acline_mode = ac_sysctl;
 		if (vflag)
 			warnx("using sysctl for AC line status");
 #ifdef __powerpc__
-	} else if (sysctlnametomib(PMUAC, acline_mib, &acline_mib_len) == 0) {
+	} else if ((skip_source_check || acline_mode_user == ac_sysctl) &&
+		   sysctlnametomib(PMUAC, acline_mib, &acline_mib_len) == 0) {
 		acline_mode = ac_sysctl;
 		if (vflag)
 			warnx("using sysctl for AC line status");
 #endif
 #ifdef USE_APM
-	} else if ((apm_fd = open(APMDEV, O_RDONLY)) >= 0) {
+	} else if ((skip_source_check || acline_mode_user == ac_apm) &&
+		   (apm_fd = open(APMDEV, O_RDONLY)) >= 0) {
 		if (vflag)
 			warnx("using APM for AC line status");
 		acline_mode = ac_apm;
@@ -360,7 +369,17 @@
 	}
 #endif
 	/* try to (re)connect to devd */
-	if (acline_mode == ac_sysctl) {
+#ifdef USE_APM
+	if ((acline_mode == ac_sysctl &&
+	    (acline_mode_user == ac_none ||
+	     acline_mode_user == ac_acpi_devd)) ||
+	    (acline_mode == ac_apm &&
+	     acline_mode_user == ac_acpi_devd)) {
+#else
+	if (acline_mode == ac_sysctl &&
+	    (acline_mode_user == ac_none ||
+	     acline_mode_user == ac_acpi_devd)) {
+#endif
 		struct timeval now;
 
 		gettimeofday(&now, NULL);
@@ -426,6 +445,21 @@
 }
 
 static void
+parse_acline_mode(char *arg, int ch)
+{
+	if (strcmp(arg, "sysctl") == 0)
+		acline_mode_user = ac_sysctl;
+	else if (strcmp(arg, "devd") == 0)
+		acline_mode_user = ac_acpi_devd;
+#ifdef USE_APM
+	else if (strcmp(arg, "apm") == 0)
+		acline_mode_user = ac_apm;
+#endif
+	else
+		errx(1, "bad option: -%c %s", (char)ch, optarg);
+}
+
+static void
 handle_sigs(int __unused sig)
 {
 
@@ -437,7 +471,7 @@
 {
 
 	fprintf(stderr,
-"usage: powerd [-v] [-a mode] [-b mode] [-i %%] [-m freq] [-M freq] [-n mode] [-p ival] [-r %%] [-P pidfile]\n");
+"usage: powerd [-v] [-a mode] [-b mode] [-i %%] [-m freq] [-M freq] [-n mode] [-p ival] [-r %%] [-s source] [-P pidfile]\n");
 	exit(1);
 }
 
@@ -468,13 +502,16 @@
 	if (geteuid() != 0)
 		errx(1, "must be root to run");
 
-	while ((ch = getopt(argc, argv, "a:b:i:m:M:n:p:P:r:v")) != -1)
+	while ((ch = getopt(argc, argv, "a:b:i:m:M:n:p:P:r:s:v")) != -1)
 		switch (ch) {
 		case 'a':
 			parse_mode(optarg, &mode_ac, ch);
 			break;
 		case 'b':
 			parse_mode(optarg, &mode_battery, ch);
+			break;
+		case 's':
+			parse_acline_mode(optarg, ch);
 			break;
 		case 'i':
 			cpu_idle_mark = atoi(optarg);