diff options
| author | jmcneill <jmcneill@NetBSD.org> | 2021-12-31 13:15:00 +0000 |
|---|---|---|
| committer | jmcneill <jmcneill@NetBSD.org> | 2021-12-31 13:15:00 +0000 |
| commit | 312915a9ecd7d45d393eb6c85628005dae80756c (patch) | |
| tree | 1ab8b5f6e90f7acd23673b87e7969d5501903f19 /sys/dev/acpi | |
| parent | f8acca3900c685280203e9384bf8015973ec7b50 (diff) | |
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.
Diffstat (limited to 'sys/dev/acpi')
| -rw-r--r-- | sys/dev/acpi/acpi_util.c | 77 |
1 files changed, 59 insertions, 18 deletions
diff --git a/sys/dev/acpi/acpi_util.c b/sys/dev/acpi/acpi_util.c index 0ce58a997fd..a8610b29b8a 100644 --- a/sys/dev/acpi/acpi_util.c +++ b/sys/dev/acpi/acpi_util.c @@ -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,v 1.28 2021/12/26 14:34:39 jmcneill Exp 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 **cpp, unsigned int count, 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_attach_args * const aa, 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_attach_args * const aa, } 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, const char *prop, char **val) return rv; } + + /* * Device Specific Method (_DSM) support */ |
