git: 878856b7a109 - main - acpi: Remove support for /dev/apmctl and apmd(8) compatibility

From: John Baldwin <jhb_at_FreeBSD.org>
Date: Wed, 30 Sep 2026 16:27:41 UTC
The branch main has been updated by jhb:

URL: https://cgit.FreeBSD.org/src/commit/?id=878856b7a1093d8b82903358f6104f6582910fdf

commit 878856b7a1093d8b82903358f6104f6582910fdf
Author:     John Baldwin <jhb@FreeBSD.org>
AuthorDate: 2026-09-30 16:22:00 +0000
Commit:     John Baldwin <jhb@FreeBSD.org>
CommitDate: 2026-09-30 16:22:00 +0000

    acpi: Remove support for /dev/apmctl and apmd(8) compatibility
    
    This simplifies the logic around ACKing suspend requests as there is
    no longer the potential for multiple listeners, only devd and the
    acknowledgement via acpiconf -k.
    
    Reviewed by:    imp
    Differential Revision:  https://reviews.freebsd.org/D59942
---
 sys/dev/acpica/acpi.c     |  58 ++++------------
 sys/dev/acpica/acpivar.h  |  20 ------
 sys/x86/acpica/acpi_apm.c | 173 +---------------------------------------------
 3 files changed, 14 insertions(+), 237 deletions(-)

diff --git a/sys/dev/acpica/acpi.c b/sys/dev/acpica/acpi.c
index e5f82b00135e..ed07ca62382c 100644
--- a/sys/dev/acpica/acpi.c
+++ b/sys/dev/acpica/acpi.c
@@ -3416,7 +3416,6 @@ int
 acpi_ReqSleepState(struct acpi_softc *sc, enum power_stype stype)
 {
 #if defined(__amd64__) || defined(__i386__)
-    struct apm_clone_data *clone;
     ACPI_STATUS status;
 
     if (stype < POWER_STYPE_AWAKE || stype >= POWER_STYPE_COUNT)
@@ -3448,15 +3447,6 @@ acpi_ReqSleepState(struct acpi_softc *sc, enum power_stype stype)
 	return (ACPI_SUCCESS(status) ? 0 : ENXIO);
     }
 
-    /* Record the pending state and notify all apm devices. */
-    STAILQ_FOREACH(clone, &sc->apm_cdevs, entries) {
-	clone->notify_status = APM_EV_NONE;
-	if ((clone->flags & ACPI_EVF_DEVD) == 0) {
-	    selwakeuppri(&clone->sel_read, PZERO);
-	    KNOTE_LOCKED(&clone->sel_read.si_note, 0);
-	}
-    }
-
     /* If devd(8) is not running, immediately enter the sleep state. */
     if (!devctl_process_running()) {
 	ACPI_UNLOCK(acpi);
@@ -3468,13 +3458,13 @@ acpi_ReqSleepState(struct acpi_softc *sc, enum power_stype stype)
      * Set a timeout to fire if userland doesn't ack the suspend request
      * in time.  This way we still eventually go to sleep if we were
      * overheating or running low on battery, even if userland is hung.
-     * We cancel this timeout once all userland acks are in or the
-     * suspend request is aborted.
+     * We cancel this timeout once userland acks or the suspend request
+     * is aborted.
      */
     callout_reset(&sc->susp_force_to, 10 * hz, acpi_sleep_force, sc);
     ACPI_UNLOCK(acpi);
 
-    /* Now notify devd(8) also. */
+    /* Now notify devd(8). */
     acpi_UserNotify("Suspend", ACPI_ROOT_OBJECT, stype);
 
     return (0);
@@ -3489,16 +3479,13 @@ acpi_ReqSleepState(struct acpi_softc *sc, enum power_stype stype)
  * Acknowledge (or reject) a pending sleep state.  The caller has
  * prepared for suspend and is now ready for it to proceed.  If the
  * error argument is non-zero, it indicates suspend should be cancelled
- * and gives an errno value describing why.  Once all votes are in,
- * we suspend the system.
+ * and gives an errno value describing why.
  */
-int
-acpi_AckSleepState(struct apm_clone_data *clone, int error)
+static int
+acpi_AckSleepState(struct acpi_softc *sc, int error)
 {
-    struct acpi_softc *sc = clone->acpi_sc;
-
 #if defined(__amd64__) || defined(__i386__)
-    int ret, sleeping;
+    int ret;
 
     /* If no pending sleep type, return an error. */
     ACPI_LOCK(acpi);
@@ -3511,37 +3498,16 @@ acpi_AckSleepState(struct apm_clone_data *clone, int error)
     if (error) {
 	sc->acpi_next_stype = POWER_STYPE_AWAKE;
 	callout_stop(&sc->susp_force_to);
-	device_printf(sc->acpi_dev,
-	    "listener on %s cancelled the pending suspend\n",
-	    devtoname(clone->cdev));
+	device_printf(sc->acpi_dev, "pending suspend cancelled\n");
     	ACPI_UNLOCK(acpi);
 	return (0);
     }
 
-    /*
-     * Mark this device as acking the suspend request.  Then, walk through
-     * all devices, seeing if they agree yet.  We only count devices that
-     * are writable since read-only devices couldn't ack the request.
-     */
-    sleeping = TRUE;
-    clone->notify_status = APM_EV_ACKED;
-    STAILQ_FOREACH(clone, &sc->apm_cdevs, entries) {
-	if ((clone->flags & ACPI_EVF_WRITE) != 0 &&
-	    clone->notify_status != APM_EV_ACKED) {
-	    sleeping = FALSE;
-	    break;
-	}
-    }
-
-    /* If all devices have voted "yes", we will suspend now. */
-    if (sleeping)
-	callout_stop(&sc->susp_force_to);
+    callout_stop(&sc->susp_force_to);
     ACPI_UNLOCK(acpi);
     ret = 0;
-    if (sleeping) {
-	if (ACPI_FAILURE(acpi_EnterSleepState(sc, sc->acpi_next_stype)))
-		ret = ENODEV;
-    }
+    if (ACPI_FAILURE(acpi_EnterSleepState(sc, sc->acpi_next_stype)))
+	    ret = ENODEV;
     return (ret);
 #else
     device_printf(sc->acpi_dev, "ACPI suspend not supported on this platform "
@@ -4604,7 +4570,7 @@ acpiioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *t
 	break;
     case ACPIIO_ACKSLPSTATE:
 	error = *(int *)addr;
-	error = acpi_AckSleepState(sc->acpi_clone, error);
+	error = acpi_AckSleepState(sc, error);
 	break;
     case ACPIIO_SETSLPSTATE:	/* DEPRECATED */
 	sstate = *(int *)addr;
diff --git a/sys/dev/acpica/acpivar.h b/sys/dev/acpica/acpivar.h
index 550c6ceb9c97..2a2c4bcb0a7c 100644
--- a/sys/dev/acpica/acpivar.h
+++ b/sys/dev/acpica/acpivar.h
@@ -48,7 +48,6 @@
 #include <machine/bus.h>
 #include <machine/resource.h>
 
-struct apm_clone_data;
 struct acpi_softc {
     device_t		acpi_dev;
     struct cdev		*acpi_dev_t;
@@ -80,8 +79,6 @@ struct acpi_softc {
     vm_paddr_t		acpi_wakephys;
 
     enum power_stype	acpi_next_stype;	/* Next suspend sleep type. */
-    struct apm_clone_data *acpi_clone;		/* Pseudo-dev for devd(8). */
-    STAILQ_HEAD(,apm_clone_data) apm_cdevs;	/* All apm/apmctl/acpi cdevs. */
     struct callout	susp_force_to;		/* Force suspend if no acks. */
 
     /* System Resources */
@@ -113,22 +110,6 @@ struct intr_map_data_acpi {
 
 #endif
 
-/* Track device (/dev/{apm,apmctl} and /dev/acpi) notification status. */
-struct apm_clone_data {
-    STAILQ_ENTRY(apm_clone_data) entries;
-    struct cdev 	*cdev;
-    int			flags;
-#define	ACPI_EVF_NONE	0	/* /dev/apm semantics */
-#define	ACPI_EVF_DEVD	1	/* /dev/acpi is handled via devd(8) */
-#define	ACPI_EVF_WRITE	2	/* Device instance is opened writable. */
-    int			notify_status;
-#define	APM_EV_NONE	0	/* Device not yet aware of pending sleep. */
-#define	APM_EV_NOTIFIED	1	/* Device saw next sleep state. */
-#define	APM_EV_ACKED	2	/* Device agreed sleep can occur. */
-    struct acpi_softc	*acpi_sc;
-    struct selinfo	sel_read;
-};
-
 #define ACPI_PRW_MAX_POWERRES	8
 
 struct acpi_prw_data {
@@ -398,7 +379,6 @@ ACPI_STATUS	acpi_EvaluateOSC(ACPI_HANDLE handle, uint8_t *uuid,
 ACPI_STATUS	acpi_OverrideInterruptLevel(UINT32 InterruptNumber);
 ACPI_STATUS	acpi_SetIntrModel(int model);
 int		acpi_ReqSleepState(struct acpi_softc *sc, enum power_stype stype);
-int		acpi_AckSleepState(struct apm_clone_data *clone, int error);
 ACPI_STATUS	acpi_SetSleepState(struct acpi_softc *sc, int state);
 int		acpi_wake_set_enable(device_t dev, int enable);
 int		acpi_parse_prw(ACPI_HANDLE h, struct acpi_prw_data *prw);
diff --git a/sys/x86/acpica/acpi_apm.c b/sys/x86/acpica/acpi_apm.c
index e1addc46c38c..ad94bd1296d7 100644
--- a/sys/x86/acpica/acpi_apm.c
+++ b/sys/x86/acpica/acpi_apm.c
@@ -28,13 +28,10 @@
 
 #include <sys/param.h>
 #include <sys/bus.h>
-#include <sys/condvar.h>
 #include <sys/conf.h>
 #include <sys/fcntl.h>
 #include <sys/kernel.h>
 #include <sys/malloc.h>
-#include <sys/poll.h>
-#include <sys/uio.h>
 
 #include <contrib/dev/acpica/include/acpi.h>
 
@@ -53,28 +50,12 @@ static int apm_active;
 
 static MALLOC_DEFINE(M_APMDEV, "apmdev", "APM device emulation");
 
-static d_open_t		apmopen;
-static d_write_t	apmwrite;
 static d_ioctl_t	apmioctl;
-static d_poll_t		apmpoll;
-static d_kqfilter_t	apmkqfilter;
-static void		apmreadfiltdetach(struct knote *kn);
-static int		apmreadfilt(struct knote *kn, long hint);
-static const struct filterops apm_readfiltops = {
-	.f_isfd = 1,
-	.f_detach = apmreadfiltdetach,
-	.f_event = apmreadfilt,
-	.f_copy = knote_triv_copy,
-};
 
 static struct cdevsw apm_cdevsw = {
 	.d_version =	D_VERSION,
-	.d_open =	apmopen,
-	.d_write =	apmwrite,
 	.d_ioctl =	apmioctl,
-	.d_poll =	apmpoll,
 	.d_name =	"apm",
-	.d_kqfilter =	apmkqfilter
 };
 
 static int
@@ -198,85 +179,15 @@ acpi_capm_get_pwstatus(apm_pwstatus_t app)
 	return (0);
 }
 
-/* Create a struct for tracking per-device suspend notification. */
-static struct apm_clone_data *
-apm_create_clone(struct cdev *dev, struct acpi_softc *acpi_sc)
-{
-	struct apm_clone_data *clone;
-
-	clone = malloc(sizeof(*clone), M_APMDEV, M_WAITOK);
-	clone->cdev = dev;
-	clone->acpi_sc = acpi_sc;
-	clone->notify_status = APM_EV_NONE;
-	bzero(&clone->sel_read, sizeof(clone->sel_read));
-	knlist_init_mtx(&clone->sel_read.si_note, &acpi_mutex);
-
-	/*
-	 * The acpi device is always managed by devd(8) and is considered
-	 * writable (i.e., ack is required to allow suspend to proceed.)
-	 */
-	if (strcmp("acpi", devtoname(dev)) == 0)
-		clone->flags = ACPI_EVF_DEVD | ACPI_EVF_WRITE;
-	else
-		clone->flags = ACPI_EVF_NONE;
-
-	ACPI_LOCK(acpi);
-	STAILQ_INSERT_TAIL(&acpi_sc->apm_cdevs, clone, entries);
-	ACPI_UNLOCK(acpi);
-	return (clone);
-}
-
-static void
-apmdtor(void *data)
-{
-	struct	apm_clone_data *clone;
-	struct	acpi_softc *acpi_sc;
-
-	clone = data;
-	acpi_sc = clone->acpi_sc;
-
-	/* We are about to lose a reference so check if suspend should occur */
-	if (acpi_sc->acpi_next_stype != POWER_STYPE_AWAKE &&
-	    clone->notify_status != APM_EV_ACKED)
-		acpi_AckSleepState(clone, 0);
-
-	/* Remove this clone's data from the list and free it. */
-	ACPI_LOCK(acpi);
-	STAILQ_REMOVE(&acpi_sc->apm_cdevs, clone, apm_clone_data, entries);
-	ACPI_UNLOCK(acpi);
-	seldrain(&clone->sel_read);
-	knlist_destroy(&clone->sel_read.si_note);
-	free(clone, M_APMDEV);
-}
-
-static int
-apmopen(struct cdev *dev, int flag, int fmt, struct thread *td)
-{
-	struct	acpi_softc *acpi_sc = dev->si_drv1;
-	struct 	apm_clone_data *clone;
-
-	clone = apm_create_clone(dev, acpi_sc);
-	devfs_set_cdevpriv(clone, apmdtor);
-
-	/* If the device is opened for write, record that. */
-	if ((flag & FWRITE) != 0)
-		clone->flags |= ACPI_EVF_WRITE;
-
-	return (0);
-}
-
 static int
 apmioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *td)
 {
 	int	error;
-	struct	apm_clone_data *clone;
 	struct	acpi_softc *acpi_sc = dev->si_drv1;
 	struct	apm_info info;
-	struct 	apm_event_info *ev_info;
 	apm_info_old_t aiop;
 
 	error = 0;
-	devfs_get_cdevpriv((void **)&clone);
 
 	switch (cmd) {
 	case APMIO_SUSPEND:
@@ -291,8 +202,7 @@ apmioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *td
 			"power off via apm suspend not supported\n");
 				error = ENXIO;
 			}
-		} else
-			error = acpi_AckSleepState(clone, 0);
+		}
 		break;
 	case APMIO_STANDBY:
 		if ((flag & FWRITE) == 0)
@@ -306,26 +216,7 @@ apmioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *td
 			"power off via apm standby not supported\n");
 				error = ENXIO;
 			}
-		} else
-			error = acpi_AckSleepState(clone, 0);
-		break;
-	case APMIO_NEXTEVENT:
-		printf("apm nextevent start\n");
-		ACPI_LOCK(acpi);
-		if (acpi_sc->acpi_next_stype != POWER_STYPE_AWAKE &&
-		    clone->notify_status == APM_EV_NONE) {
-			ev_info = (struct apm_event_info *)addr;
-			/* XXX Check this. */
-			if (acpi_sc->acpi_next_stype == POWER_STYPE_STANDBY)
-				ev_info->type = PMEV_STANDBYREQ;
-			else
-				ev_info->type = PMEV_SUSPENDREQ;
-			ev_info->index = 0;
-			clone->notify_status = APM_EV_NOTIFIED;
-			printf("apm event returning %d\n", ev_info->type);
-		} else
-			error = EAGAIN;
-		ACPI_UNLOCK(acpi);
+		}
 		break;
 	case APMIO_GETINFO_OLD:
 		if (acpi_capm_get_info(&info))
@@ -376,71 +267,12 @@ apmioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *td
 	return (error);
 }
 
-static int
-apmwrite(struct cdev *dev, struct uio *uio, int ioflag)
-{
-	return (uio->uio_resid);
-}
-
-static int
-apmpoll(struct cdev *dev, int events, struct thread *td)
-{
-	struct	apm_clone_data *clone;
-	int revents;
-
-	revents = 0;
-	devfs_get_cdevpriv((void **)&clone);
-	ACPI_LOCK(acpi);
-	if (clone->acpi_sc->acpi_next_stype != POWER_STYPE_AWAKE)
-		revents |= events & (POLLIN | POLLRDNORM);
-	else
-		selrecord(td, &clone->sel_read);
-	ACPI_UNLOCK(acpi);
-	return (revents);
-}
-
-static int
-apmkqfilter(struct cdev *dev, struct knote *kn)
-{
-	struct	apm_clone_data *clone;
-
-	devfs_get_cdevpriv((void **)&clone);
-	kn->kn_hook = clone;
-	kn->kn_fop = &apm_readfiltops;
-	knlist_add(&clone->sel_read.si_note, kn, 0);
-	return (0);
-}
-
-static void
-apmreadfiltdetach(struct knote *kn)
-{
-	struct	apm_clone_data *clone;
-
-	clone = kn->kn_hook;
-	knlist_remove(&clone->sel_read.si_note, kn, 0);
-}
-
-static int
-apmreadfilt(struct knote *kn, long hint)
-{
-	struct	apm_clone_data *clone;
-	int	sleeping;
-
-	clone = kn->kn_hook;
-	sleeping = clone->acpi_sc->acpi_next_stype != POWER_STYPE_AWAKE;
-	return (sleeping);
-}
-
 void
 acpi_apm_init(struct acpi_softc *sc)
 {
 	struct make_dev_args args;
 	struct cdev *dev;
 
-	/* Create a clone for /dev/acpi also. */
-	STAILQ_INIT(&sc->apm_cdevs);
-	sc->acpi_clone = apm_create_clone(sc->acpi_dev_t, sc);
-
 	make_dev_args_init(&args);
 	args.mda_devsw = &apm_cdevsw;
 	args.mda_uid = UID_ROOT;
@@ -448,6 +280,5 @@ acpi_apm_init(struct acpi_softc *sc)
 	args.mda_mode = 0664;
 	args.mda_si_drv1 = sc;
 	args.mda_flags = MAKEDEV_ETERNAL;
-	make_dev_s(&args, &dev, "apmctl");
 	make_dev_s(&args, &dev, "apm");
 }