Re: git: a9880bfe1181 - main - acpi_ged: New driver to ACPI generic event device

From: Jessica Clarke <jrtc27_at_freebsd.org>
Date: Mon, 24 Oct 2022 15:35:55 UTC
On 24 Oct 2022, at 11:02, Takanori Watanabe <takawata@FreeBSD.org> wrote:
> 
> The branch main has been updated by takawata:
> 
> URL: https://cgit.FreeBSD.org/src/commit/?id=a9880bfe1181b7a32d026339bae113f24300e5e1
> 
> commit a9880bfe1181b7a32d026339bae113f24300e5e1
> Author:     Takanori Watanabe <takawata@FreeBSD.org>
> AuthorDate: 2022-10-18 05:41:53 +0000
> Commit:     Takanori Watanabe <takawata@FreeBSD.org>
> CommitDate: 2022-10-24 09:57:36 +0000
> 
>    acpi_ged:  New driver to ACPI generic event device
> 
>     New driver to ACPI generic event device, defined in ACPI spec.
>    Some ACPI power button may not work without this.
> 
>    In qemu arm64 with "virt" machine, with ACPI firmware,
>    enable devd check devd message by
>    and invoke following command in qemu monitor
>    (qemu) system_powerdown
>    and make sure some power button input event appear.
>    (setting sysctl hw.acpi.power_button_state=S5 is not work,
>    because ACPI tree does not have \_S5 object.)
> 
>    Reviewed by: andrew, hrs
>    Differential Revision: https://reviews.freebsd.org/D37032
> ---
> share/man/man4/acpi_ged.4          |  64 +++++++++
> sys/arm64/conf/std.virt            |   1 +
> sys/conf/files                     |   1 +
> sys/dev/acpica/acpi_ged.c          | 267 +++++++++++++++++++++++++++++++++++++
> sys/modules/acpi/Makefile          |   2 +-
> sys/modules/acpi/acpi_ged/Makefile |  11 ++
> 6 files changed, 345 insertions(+), 1 deletion(-)
> 
> diff --git a/share/man/man4/acpi_ged.4 b/share/man/man4/acpi_ged.4
> new file mode 100644
> index 000000000000..dd62e172ae8d
> --- /dev/null
> +++ b/share/man/man4/acpi_ged.4
> @@ -0,0 +1,64 @@
> +.\" Copyright (c) 2022 Takanori Watanabe
> +.\"
> +.\" Redistribution and use in source and binary forms, with or without
> +.\" modification, are permitted provided that the following conditions
> +.\" are met:
> +.\" 1. Redistributions of source code must retain the above copyright
> +.\"    notice, this list of conditions and the following disclaimer.
> +.\" 2. Redistributions in binary form must reproduce the above copyright
> +.\"    notice, this list of conditions and the following disclaimer in the
> +.\"    documentation and/or other materials provided with the distribution.
> +.\"
> +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
> +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
> +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
> +.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
> +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
> +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
> +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
> +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
> +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
> +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
> +.\" SUCH DAMAGE.
> +.\"
> +.\" $FreeBSD$
> +.\"
> +.Dd October 18, 2022
> +.Dt ACPI_GED 4
> +.Os
> +.Sh NAME
> +.Nm acpi_ged
> +.Nd "ACPI Generic Event Device"
> +.Sh SYNOPSIS
> +To compile this driver into the kernel,
> +place the following line in your
> +kernel configuration file:
> +.Bd -ragged -offset indent
> +.Cd "device acpi_ged"
> +.Ed
> +.Pp
> +Alternatively, to load the driver as a
> +module at boot time, place the following line in
> +.Xr loader.conf 5 :
> +.Bd -literal -offset indent
> +acpi_ged_load="YES"
> +.Ed
> +.Sh DESCRIPTION
> +The
> +.Nm
> +driver provides support for generic events interface.
> +This handles interrupts and evaluates the specific ACPI method.
> +This may generate optionally ACPI notify for another device.
> +.Sh SEE ALSO
> +.Xr acpi 4
> +.Sh HISTORY
> +The
> +.Nm
> +device driver first appeared in
> +.Fx 14.0 .
> +.Sh AUTHORS
> +.An -nosplit
> +The
> +.Nm
> +driver was written by
> +.An Takanori Watanabe Aq Mt takawata@FreeBSD.org
> diff --git a/sys/arm64/conf/std.virt b/sys/arm64/conf/std.virt
> index 507e1321f3d1..1b7d7ad8ab0a 100644
> --- a/sys/arm64/conf/std.virt
> +++ b/sys/arm64/conf/std.virt
> @@ -24,3 +24,4 @@ device		vtnet			# VirtIO Ethernet device
> 
> options 	FDT
> device		acpi
> +device		acpi_ged
> diff --git a/sys/conf/files b/sys/conf/files
> index 39e6d4aaf0a8..563054bbac3b 100644
> --- a/sys/conf/files
> +++ b/sys/conf/files
> @@ -806,6 +806,7 @@ dev/acpica/acpi_button.c	optional acpi
> dev/acpica/acpi_cmbat.c		optional acpi
> dev/acpica/acpi_cpu.c		optional acpi
> dev/acpica/acpi_ec.c		optional acpi
> +dev/acpica/acpi_ged.c		optional acpi_ged acpi
> dev/acpica/acpi_isab.c		optional acpi isa
> dev/acpica/acpi_lid.c		optional acpi
> dev/acpica/acpi_package.c	optional acpi
> diff --git a/sys/dev/acpica/acpi_ged.c b/sys/dev/acpica/acpi_ged.c
> new file mode 100644
> index 000000000000..9459ccc3525b
> --- /dev/null
> +++ b/sys/dev/acpica/acpi_ged.c
> @@ -0,0 +1,267 @@
> +/*-
> + * Copyright (c) 2022 Takanori Watanabe
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + * 1. Redistributions of source code must retain the above copyright
> + *    notice, this list of conditions and the following disclaimer.
> + * 2. Redistributions in binary form must reproduce the above copyright
> + *    notice, this list of conditions and the following disclaimer in the
> + *    documentation and/or other materials provided with the distribution.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
> + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
> + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
> + * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
> + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
> + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
> + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
> + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
> + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
> + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
> + * SUCH DAMAGE.
> + */
> +
> +#include <sys/cdefs.h>
> +__FBSDID("$FreeBSD$");
> +
> +#include "opt_acpi.h"
> +
> +#include <sys/param.h>
> +#include <sys/bus.h>
> +#include <sys/kernel.h>
> +#include <sys/malloc.h>
> +#include <sys/module.h>
> +#include <sys/rman.h>
> +
> +#include <contrib/dev/acpica/include/acpi.h>
> +#include <contrib/dev/acpica/include/accommon.h>
> +#include <dev/acpica/acpivar.h>
> +
> +/* Hooks for the ACPI CA debugging infrastructure */
> +#define _COMPONENT ACPI_GED
> +ACPI_MODULE_NAME("GED")
> +
> +static MALLOC_DEFINE(M_ACPIGED, "acpiged", "ACPI Generic event data");
> +
> +struct acpi_ged_event {
> +	device_t dev;
> +	struct resource *r;
> +	int rid;
> +	void *cookie;
> +	ACPI_HANDLE ah;
> +	ACPI_OBJECT_LIST args;
> +	ACPI_OBJECT arg1;
> +};
> +
> +struct acpi_ged_softc {
> +	int numevts;
> +	struct acpi_ged_event *evts;
> +};
> +
> +static int acpi_ged_probe(device_t dev);
> +static int acpi_ged_attach(device_t dev);
> +static int acpi_ged_detach(device_t dev);
> +
> +static char *ged_ids[] = { "ACPI0013", NULL };
> +
> +static device_method_t acpi_ged_methods[] = {
> +	/* Device interface */
> +	DEVMETHOD(device_probe, acpi_ged_probe),
> +	DEVMETHOD(device_attach, acpi_ged_attach),
> +	DEVMETHOD(device_detach, acpi_ged_detach),
> +	DEVMETHOD_END
> +};
> +
> +static driver_t acpi_ged_driver = {
> +	"acpi_ged",
> +	acpi_ged_methods,
> +	sizeof(struct acpi_ged_softc),
> +};
> +
> +DRIVER_MODULE(acpi_ged, acpi, acpi_ged_driver, 0, 0);
> +MODULE_DEPEND(acpi_ged, acpi, 1, 1, 1);
> +
> +static void
> +acpi_ged_evt(void *arg)
> +{
> +	struct acpi_ged_event *evt = arg;
> +
> +	AcpiEvaluateObject(evt->ah, NULL, &evt->args, NULL);
> +}
> +
> +static void
> +acpi_ged_intr(void *arg)
> +{
> +	AcpiOsExecute(OSL_GPE_HANDLER, acpi_ged_evt, arg);
> +}
> +static int

Missing newline

> +acpi_ged_probe(device_t dev)
> +{
> +	int rv;
> +
> +	if (acpi_disabled("ged"))
> +		return (ENXIO);
> +	rv = ACPI_ID_PROBE(device_get_parent(dev), dev, ged_ids, NULL);
> +	if (rv > 0)
> +		return (ENXIO);

Why not return rv? Or just mirror most other uses and guard
device_set_desc with rv <= 0.

> +
> +	device_set_desc(dev, "Generic Event Device");
> +	return (rv);
> +}
> +
> +/*this should be in acpi_resource.*/

Spaces around the comment, and why not just put it there?

> +static int
> +acpi_get_trigger(ACPI_RESOURCE *res)
> +{
> +	int trig;
> +
> +	switch (res->Type) {
> +	case ACPI_RESOURCE_TYPE_IRQ:
> +		KASSERT(res->Data.Irq.InterruptCount == 1,
> +			("%s: multiple interrupts", __func__));
> +		trig = res->Data.Irq.Triggering;
> +		break;
> +	case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
> +		KASSERT(res->Data.ExtendedIrq.InterruptCount == 1,
> +			("%s: multiple interrupts", __func__));
> +		trig = res->Data.ExtendedIrq.Triggering;
> +		break;
> +	default:
> +		panic("%s: bad resource type %u", __func__, res->Type);
> +	}
> +
> +	return (trig == ACPI_EDGE_SENSITIVE)
> +		? INTR_TRIGGER_EDGE : INTR_TRIGGER_LEVEL;

Parentheses should be around the whole expression not the condition.

> +}
> +
> +static int
> +acpi_ged_attach(device_t dev)
> +{
> +	struct acpi_ged_softc *sc = device_get_softc(dev);
> +	struct resource_list *rl;
> +	struct resource_list_entry *rle;
> +	ACPI_RESOURCE ares;
> +	ACPI_HANDLE evt_method;
> +	int i;
> +	int rawirq, trig;
> +	char name[] = "_Xnn";
> +
> +	ACPI_FUNCTION_TRACE((char *)(uintptr_t) __func__);
> +
> +	if (ACPI_FAILURE(AcpiGetHandle(acpi_get_handle(dev), "_EVT",
> +				       &evt_method))) {
> +		device_printf(dev, "_EVT not found\n");
> +		evt_method = NULL;
> +	}
> +
> +	rl = BUS_GET_RESOURCE_LIST(device_get_parent(dev), dev);
> +	STAILQ_FOREACH(rle, rl, link) {
> +		if (rle->type == SYS_RES_IRQ) {
> +			sc->numevts++;
> +		}
> +	}
> +	sc->evts = mallocarray(sc->numevts, sizeof(*sc->evts), M_ACPIGED,
> +	    M_WAITOK | M_ZERO);
> +	for (i = 0; i < sc->numevts; i++) {
> +		sc->evts[i].dev = dev;
> +		sc->evts[i].rid = i;
> +		sc->evts[i].r = bus_alloc_resource_any(dev, SYS_RES_IRQ,
> +		    &sc->evts[i].rid,  RF_ACTIVE | RF_SHAREABLE);
> +		if (sc->evts[i].r == NULL) {
> +			device_printf(dev, "Cannot alloc %dth irq\n", i);

Not correct for i being 1 or 2 (or 21, 22, etc). Use “irq %d” instead?

> +			continue;
> +		}
> +#ifdef INTRNG
> +		{
> +			struct intr_map_data_acpi *ima;
> +			ima = rman_get_virtual(sc->evts[i].r);
> +			if (ima == NULL) {
> +				device_printf(dev, "map not found"
> +					      " non-intrng?\n");

This existing seems dubious, how would it be hit?

> +				rawirq = rman_get_start(sc->evts[i].r);
> +				trig = INTR_TRIGGER_LEVEL;
> +				if (ACPI_SUCCESS(acpi_lookup_irq_resource
> +					(dev, sc->evts[i].rid,
> +					 sc->evts[i].r, &ares))) {
> +					trig = acpi_get_trigger(&ares);
> +				}
> +			} else if (ima->hdr.type == INTR_MAP_DATA_ACPI) {
> +				device_printf(dev, "Raw IRQ %d\n", ima->irq);

This is a debug print.

> +				rawirq = ima->irq;
> +				trig = ima->trig;
> +			} else {
> +				device_printf(dev, "Not supported intr"
> +					      " type%d\n", ima->hdr.type);

Space after type?

> +				continue;
> +			}
> +		}
> +#else
> +		rawirq = rman_get_start(sc->evt[i].r);
> +		trig = INTR_TRIGGER_LEVEL;
> +		if (ACPI_SUCCESS(acpi_lookup_irq_resource
> +				(dev, sc->evts[i].rid,
> +				 sc->evts[i].r, &ares))) {
> +			trig = acpi_get_trigger(&ares);
> +		}
> +#endif
> +		if (rawirq < 0x100) {
> +			sprintf(name, "_%c%02X",
> +				((trig == INTR_TRIGGER_EDGE) ? 'E' : 'L'),

Condition parentheses are redundant.

> +				rawirq);
> +			if (ACPI_SUCCESS(AcpiGetHandle
> +					(acpi_get_handle(dev),
> +					 name, &sc->evts[i].ah))) {
> +				sc->evts[i].args.Count = 0; /* ensure */

These “ensure” comments seem meaningless?

> +			} else {
> +				sc->evts[i].ah = NULL; /* ensure */
> +			}
> +		}
> +
> +		if (sc->evts[i].ah == NULL) {
> +			if (evt_method != NULL) {
> +				sc->evts[i].ah = evt_method;
> +				sc->evts[i].arg1.Type = ACPI_TYPE_INTEGER;
> +				sc->evts[i].arg1.Integer.Value = rawirq;
> +				sc->evts[i].args.Count = 1;
> +				sc->evts[i].args.Pointer = &sc->evts[i].arg1;
> +			} else{

Space before {

> +				device_printf
> +					(dev,
> +					 "Cannot find handler method %d\n",
> +					 i);

I don’t think this conforms to style(9).

> +				continue;
> +			}
> +		}
> +
> +		if (bus_setup_intr(dev, sc->evts[i].r,
> +			INTR_TYPE_MISC | INTR_MPSAFE, NULL, acpi_ged_intr,
> +			&sc->evts[i], &sc->evts[i].cookie) != 0) {
> +			device_printf(dev, "Failed to setup intr %d\n", i);
> +		}
> +	}
> +
> +	return_VALUE(0);

Existing uses of return_VALUE put a space like return.

> +}
> +
> +static int
> +acpi_ged_detach(device_t dev)
> +{
> +	struct acpi_ged_softc *sc = device_get_softc(dev);
> +	int i;
> +
> +	for (i = 0; i < sc->numevts; i++) {
> +		if (sc->evts[i].cookie) {

!= NULL

> +			bus_teardown_intr(dev, sc->evts[i].r,
> +			    sc->evts[i].cookie);
> +		}
> +		if (sc->evts[i].r) {

!= NULL

Jess

> +			bus_release_resource(dev, SYS_RES_IRQ, sc->evts[i].rid,
> +			    sc->evts[i].r);
> +		}
> +	}
> +	free(sc->evts, M_ACPIGED);
> +
> +	return (0);
> +}
> diff --git a/sys/modules/acpi/Makefile b/sys/modules/acpi/Makefile
> index 552c4d2cbba0..71e083fef700 100644
> --- a/sys/modules/acpi/Makefile
> +++ b/sys/modules/acpi/Makefile
> @@ -1,7 +1,7 @@
> # $FreeBSD$
> 
> SUBDIR=		acpi_asus acpi_asus_wmi acpi_dock acpi_fujitsu acpi_hp	\
> -		acpi_ibm acpi_panasonic acpi_sony acpi_toshiba		\
> +		acpi_ged acpi_ibm acpi_panasonic acpi_sony acpi_toshiba	\
> 		acpi_video acpi_wmi aibs
> 
> .include <bsd.subdir.mk>
> diff --git a/sys/modules/acpi/acpi_ged/Makefile b/sys/modules/acpi/acpi_ged/Makefile
> new file mode 100644
> index 000000000000..a937249357f4
> --- /dev/null
> +++ b/sys/modules/acpi/acpi_ged/Makefile
> @@ -0,0 +1,11 @@
> +#	$FreeBSD$
> +
> +.PATH:	${SRCTOP}/sys/dev/acpica
> +.if ${TARGET_ARCH} == aarch64
> +CFLAGS += -DINTRNG
> +.endif
> +KMOD=	acpi_ged
> +SRCS=	acpi_ged.c
> +SRCS+=	opt_acpi.h opt_evdev.h acpi_if.h bus_if.h device_if.h
> +
> +.include <bsd.kmod.mk>