Module Name:    src
Committed By:   jmcneill
Date:           Fri Dec 31 13:15:00 UTC 2021

Modified Files:
        src/sys/dev/acpi: acpi_util.c

Log Message:
acpi: Support DT link compat string lists

A "compatible" DSD property may either be a string, or a package of
strings. Support both variants in acpi_compatible_match.


To generate a diff of this commit:
cvs rdiff -u -r1.28 -r1.29 src/sys/dev/acpi/acpi_util.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/dev/acpi/acpi_util.c
diff -u src/sys/dev/acpi/acpi_util.c:1.28 src/sys/dev/acpi/acpi_util.c:1.29
--- src/sys/dev/acpi/acpi_util.c:1.28	Sun Dec 26 14:34:39 2021
+++ src/sys/dev/acpi/acpi_util.c	Fri Dec 31 13:15:00 2021
@@ -1,4 +1,4 @@
-/*	$NetBSD: acpi_util.c,v 1.28 2021/12/26 14:34:39 jmcneill Exp $ */
+/*	$NetBSD: acpi_util.c,v 1.29 2021/12/31 13:15:00 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2003, 2007, 2021 The NetBSD Foundation, Inc.
@@ -65,7 +65,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: acpi_util.c,v 1.28 2021/12/26 14:34:39 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: acpi_util.c,v 1.29 2021/12/31 13:15:00 jmcneill Exp $");
 
 #include <sys/param.h>
 #include <sys/kmem.h>
@@ -83,6 +83,8 @@ __KERNEL_RCSID(0, "$NetBSD: acpi_util.c,
 ACPI_MODULE_NAME	("acpi_util")
 
 static void		acpi_clean_node(ACPI_HANDLE, void *);
+static ACPI_STATUS	acpi_dsd_property(ACPI_HANDLE, const char *,
+			    ACPI_BUFFER *, ACPI_OBJECT_TYPE, ACPI_OBJECT **);
 
 static const char * const acpicpu_ids[] = {
 	"ACPI0007",
@@ -438,6 +440,58 @@ acpi_compatible_free_strarray(const char
 	kmem_tmpbuf_free(cpp, count * sizeof(const char *), buf);
 }
 
+static int
+acpi_compatible_match_dtlink(const struct acpi_attach_args * const aa,
+    const struct device_compatible_entry * const dce)
+{
+	const char *strings[ACPI_COMPATSTR_MAX * sizeof(const char *)];
+	ACPI_HANDLE handle = aa->aa_node->ad_handle;
+	ACPI_BUFFER buf;
+	char *compatible;
+	ACPI_STATUS ret;
+	ACPI_OBJECT *obj;
+	int rv = 0, n;
+
+	buf.Pointer = NULL;
+	buf.Length = ACPI_ALLOCATE_BUFFER;
+
+	/* Match a single string _DSD value */
+	ret = acpi_dsd_string(handle, "compatible", &compatible);
+	if (ACPI_SUCCESS(ret)) {
+		strings[0] = compatible;
+		rv = device_compatible_pmatch(strings, 1, dce);
+		kmem_strfree(compatible);
+		goto done;
+	}
+
+	/* Match from a list of strings in a _DSD value */
+	ret = acpi_dsd_property(handle, "compatible", &buf,
+	    ACPI_TYPE_PACKAGE, &obj);
+	if (ACPI_FAILURE(ret)) {
+		goto done;
+	}
+	if (obj->Package.Count == 0) {
+		goto done;
+	}
+	for (n = 0; n < imin(obj->Package.Count, ACPI_COMPATSTR_MAX); n++) {
+		if (obj->Package.Elements[n].Type != ACPI_TYPE_STRING) {
+			goto done;
+		}
+		strings[n] = obj->Package.Elements[n].String.Pointer;
+	}
+	rv = device_compatible_pmatch(strings, n, dce);
+
+done:
+	if (buf.Pointer != NULL) {
+		ACPI_FREE(buf.Pointer);
+	}
+	if (rv) {
+		rv = (rv - 1) + ACPI_MATCHSCORE_CID;
+		return imin(rv, ACPI_MATCHSCORE_CID_MAX);
+	}
+	return 0;
+}
+
 /*
  * acpi_compatible_match --
  *
@@ -451,7 +505,6 @@ acpi_compatible_match(const struct acpi_
 	const char *strings[ACPI_COMPATSTR_MAX * sizeof(const char *)];
 	const char **cpp;
 	bool dtlink = false;
-	ACPI_STATUS ret;
 	int rv;
 
 	if (aa->aa_node->ad_type != ACPI_TYPE_DEVICE) {
@@ -494,21 +547,7 @@ acpi_compatible_match(const struct acpi_
 	}
 
 	if (dtlink) {
-		char *compatible;
-
-		ret = acpi_dsd_string(aa->aa_node->ad_handle,
-		    "compatible", &compatible);
-		if (ACPI_FAILURE(ret)) {
-			return 0;
-		}
-
-		strings[0] = compatible;
-		rv = device_compatible_pmatch(strings, 1, dce);
-		kmem_strfree(compatible);
-		if (rv) {
-			rv = (rv - 1) + ACPI_MATCHSCORE_CID;
-			return imin(rv, ACPI_MATCHSCORE_CID_MAX);
-		}
+		return acpi_compatible_match_dtlink(aa, dce);
 	}
 
 	return 0;
@@ -979,6 +1018,8 @@ acpi_dsd_string(ACPI_HANDLE handle, cons
 	return rv;
 }
 
+
+
 /*
  * Device Specific Method (_DSM) support
  */

Reply via email to