git: 7dd1f0dcd134 - main - acpica: add domain ivar

From: Konstantin Belousov <kib_at_FreeBSD.org>
Date: Tue, 26 Nov 2024 22:00:34 UTC
The branch main has been updated by kib:

URL: https://cgit.FreeBSD.org/src/commit/?id=7dd1f0dcd134de52c5ace8da5876b3bd518cee7e

commit 7dd1f0dcd134de52c5ace8da5876b3bd518cee7e
Author:     Konstantin Belousov <kib@FreeBSD.org>
AuthorDate: 2024-10-26 10:12:37 +0000
Commit:     Konstantin Belousov <kib@FreeBSD.org>
CommitDate: 2024-11-26 21:56:25 +0000

    acpica: add domain ivar
    
    Specialize acpi bus_get_domain method to read ivar.
    Execute and cache the _PXM result in the ivar at namespace enumeration
    time.
    
    If there is no _PXM, driver for the child can set the ivar to the value
    obtained by other means.
    
    Move acpi_get_domain() to acpi_pci.c, it now serves pci buses and
    devices on them.
    
    Suggested and reviewed by:      jhb
    Sponsored by:   Advanced Micro Devices (AMD)
    Sponsored by:   The FreeBSD Foundation
    MFC after:      1 week
    Differential revision:  https://reviews.freebsd.org/D47291
---
 sys/dev/acpica/acpi.c     | 43 +++++++++++++++++++++----------------------
 sys/dev/acpica/acpi_pci.c | 28 +++++++++++++++++++++++++++-
 sys/dev/acpica/acpivar.h  |  9 ++++++++-
 3 files changed, 56 insertions(+), 24 deletions(-)

diff --git a/sys/dev/acpica/acpi.c b/sys/dev/acpica/acpi.c
index d4fbec7552f1..a7ff4e302bed 100644
--- a/sys/dev/acpica/acpi.c
+++ b/sys/dev/acpica/acpi.c
@@ -142,6 +142,7 @@ static bus_child_location_t	acpi_child_location_method;
 static bus_hint_device_unit_t	acpi_hint_device_unit;
 static bus_get_property_t	acpi_bus_get_prop;
 static bus_get_device_path_t	acpi_get_device_path;
+static bus_get_domain_t		acpi_get_domain_method;
 
 static acpi_id_probe_t		acpi_device_id_probe;
 static acpi_evaluate_object_t	acpi_device_eval_obj;
@@ -219,7 +220,7 @@ static device_method_t acpi_methods[] = {
     DEVMETHOD(bus_teardown_intr,	bus_generic_teardown_intr),
     DEVMETHOD(bus_hint_device_unit,	acpi_hint_device_unit),
     DEVMETHOD(bus_get_cpus,		acpi_get_cpus),
-    DEVMETHOD(bus_get_domain,		acpi_get_domain),
+    DEVMETHOD(bus_get_domain,		acpi_get_domain_method),
     DEVMETHOD(bus_get_property,		acpi_bus_get_prop),
     DEVMETHOD(bus_get_device_path,	acpi_get_device_path),
 
@@ -819,6 +820,7 @@ acpi_add_child(device_t bus, u_int order, const char *name, int unit)
     if ((ad = malloc(sizeof(*ad), M_ACPIDEV, M_NOWAIT | M_ZERO)) == NULL)
 	return (NULL);
 
+    ad->ad_domain = ACPI_DEV_DOMAIN_UNKNOWN;
     resource_list_init(&ad->ad_rl);
 
     child = device_add_child_ordered(bus, order, name, unit);
@@ -1055,6 +1057,9 @@ acpi_read_ivar(device_t dev, device_t child, int index, uintptr_t *result)
     case ACPI_IVAR_FLAGS:
 	*(int *)result = ad->ad_flags;
 	break;
+    case ACPI_IVAR_DOMAIN:
+	*(int *)result = ad->ad_domain;
+	break;
     case ISA_IVAR_VENDORID:
     case ISA_IVAR_SERIAL:
     case ISA_IVAR_COMPATID:
@@ -1099,6 +1104,9 @@ acpi_write_ivar(device_t dev, device_t child, int index, uintptr_t value)
     case ACPI_IVAR_FLAGS:
 	ad->ad_flags = (int)value;
 	break;
+    case ACPI_IVAR_DOMAIN:
+	ad->ad_domain = (int)value;
+	break;
     default:
 	panic("bad ivar write request (%d)", index);
 	return (ENOENT);
@@ -1297,29 +1305,16 @@ acpi_get_cpus(device_t dev, device_t child, enum cpu_sets op, size_t setsize,
 	}
 }
 
-/*
- * Fetch the NUMA domain for the given device 'dev'.
- *
- * If a device has a _PXM method, map that to a NUMA domain.
- * Otherwise, pass the request up to the parent.
- * If there's no matching domain or the domain cannot be
- * determined, return ENOENT.
- */
-int
-acpi_get_domain(device_t dev, device_t child, int *domain)
+static int
+acpi_get_domain_method(device_t dev, device_t child, int *domain)
 {
-	int d;
+	int error;
 
-	d = acpi_pxm_parse(child);
-	if (d >= 0) {
-		*domain = d;
+	error = acpi_read_ivar(dev, child, ACPI_IVAR_DOMAIN,
+	    (uintptr_t *)domain);
+	if (error == 0 && *domain != ACPI_DEV_DOMAIN_UNKNOWN)
 		return (0);
-	}
-	if (d == -1)
-		return (ENOENT);
-
-	/* No _PXM node; go up a level */
-	return (bus_generic_get_domain(dev, child, domain));
+	return (ENOENT);
 }
 
 static struct rman *
@@ -2348,7 +2343,7 @@ acpi_probe_child(ACPI_HANDLE handle, UINT32 level, void *context, void **status)
     ACPI_HANDLE h;
     device_t bus, child;
     char *handle_str;
-    int order;
+    int d, order;
 
     ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
 
@@ -2456,6 +2451,10 @@ acpi_probe_child(ACPI_HANDLE handle, UINT32 level, void *context, void **status)
 		}
 		AcpiOsFree(devinfo);
 	    }
+
+	    d = acpi_pxm_parse(child);
+	    if (d >= 0)
+		ad->ad_domain = d;
 	    break;
 	}
     }
diff --git a/sys/dev/acpica/acpi_pci.c b/sys/dev/acpica/acpi_pci.c
index a1ac3499662d..6411af02ee58 100644
--- a/sys/dev/acpica/acpi_pci.c
+++ b/sys/dev/acpica/acpi_pci.c
@@ -93,6 +93,7 @@ static int	acpi_pci_set_powerstate_method(device_t dev, device_t child,
 		    int state);
 static void	acpi_pci_update_device(ACPI_HANDLE handle, device_t pci_child);
 static bus_dma_tag_t acpi_pci_get_dma_tag(device_t bus, device_t child);
+static int	acpi_pci_get_domain(device_t dev, device_t child, int *domain);
 
 static device_method_t acpi_pci_methods[] = {
 	/* Device interface */
@@ -108,7 +109,7 @@ static device_method_t acpi_pci_methods[] = {
 	DEVMETHOD(bus_get_device_path,	acpi_pci_get_device_path),
 	DEVMETHOD(bus_get_cpus,		acpi_get_cpus),
 	DEVMETHOD(bus_get_dma_tag,	acpi_pci_get_dma_tag),
-	DEVMETHOD(bus_get_domain,	acpi_get_domain),
+	DEVMETHOD(bus_get_domain,	acpi_pci_get_domain),
 
 	/* PCI interface */
 	DEVMETHOD(pci_alloc_devinfo,	acpi_pci_alloc_devinfo),
@@ -206,6 +207,31 @@ acpi_pci_get_device_path(device_t bus, device_t child, const char *locator, stru
 	return 	(pci_get_device_path_method(bus, child, locator, sb));
 }
 
+/*
+ * Fetch the NUMA domain for the given device 'dev'.
+ *
+ * If a device has a _PXM method, map that to a NUMA domain.
+ * Otherwise, pass the request up to the parent.
+ * If there's no matching domain or the domain cannot be
+ * determined, return ENOENT.
+ */
+static int
+acpi_pci_get_domain(device_t dev, device_t child, int *domain)
+{
+	int d;
+
+	d = acpi_pxm_parse(child);
+	if (d >= 0) {
+		*domain = d;
+		return (0);
+	}
+	if (d == -1)
+		return (ENOENT);
+
+	/* No _PXM node; go up a level */
+	return (bus_generic_get_domain(dev, child, domain));
+}
+
 /*
  * PCI power manangement
  */
diff --git a/sys/dev/acpica/acpivar.h b/sys/dev/acpica/acpivar.h
index d3def7c7e17b..668d0b51a1f3 100644
--- a/sys/dev/acpica/acpivar.h
+++ b/sys/dev/acpica/acpivar.h
@@ -89,6 +89,7 @@ struct acpi_device {
     void			*ad_private;
     int				ad_flags;
     int				ad_cls_class;
+    int				ad_domain;
 
     ACPI_BUFFER			dsd;	/* Device Specific Data */
     const ACPI_OBJECT	*dsd_pkg;
@@ -272,6 +273,12 @@ extern int	acpi_override_isa_irq_polarity;
 #define ACPI_IVAR_UNUSED	0x101	/* Unused/reserved. */
 #define ACPI_IVAR_PRIVATE	0x102
 #define ACPI_IVAR_FLAGS		0x103
+#define	ACPI_IVAR_DOMAIN	0x104
+
+/*
+ * ad_domain NUMA domain special value.
+ */
+#define	ACPI_DEV_DOMAIN_UNKNOWN	(-1)
 
 /*
  * Accessor functions for our ivars.  Default value for BUS_READ_IVAR is
@@ -297,6 +304,7 @@ static __inline void varp ## _set_ ## var(device_t dev, type t)	\
 __ACPI_BUS_ACCESSOR(acpi, handle, ACPI, HANDLE, ACPI_HANDLE)
 __ACPI_BUS_ACCESSOR(acpi, private, ACPI, PRIVATE, void *)
 __ACPI_BUS_ACCESSOR(acpi, flags, ACPI, FLAGS, int)
+__ACPI_BUS_ACCESSOR(acpi, domain, ACPI, DOMAIN, int)
 
 void acpi_fake_objhandler(ACPI_HANDLE h, void *data);
 static __inline device_t
@@ -594,7 +602,6 @@ int		acpi_pxm_parse(device_t dev);
  */
 int		acpi_map_pxm_to_vm_domainid(int pxm);
 bus_get_cpus_t		acpi_get_cpus;
-bus_get_domain_t	acpi_get_domain;
 
 #ifdef __aarch64__
 /*