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 */