Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev/acpi Introduce weighted matching for ACPI autoconfig...



details:   https://anonhg.NetBSD.org/src/rev/e3908de22db5
branches:  trunk
changeset: 958987:e3908de22db5
user:      thorpej <thorpej%NetBSD.org@localhost>
date:      Wed Jan 27 05:11:54 2021 +0000

description:
Introduce weighted matching for ACPI autoconfiguration, and provide
acpi_compatible_match() based around device_compatible_entry.  Matches
against _HID score big, matches against _CID are weighted in the
standard most-to-least-specific ordering, less than _HID.

Also provide a maching value for _CLS, that's always less than _HID
and _CID matches, and use that in acpi_match_class().

Also provide acpi_compatible_lookup(), that returing the matching
entry based on the same criteria.

diffstat:

 sys/dev/acpi/acpi_util.c |  146 ++++++++++++++++++++++++++++++++++++++--------
 sys/dev/acpi/acpivar.h   |   14 ++++-
 2 files changed, 133 insertions(+), 27 deletions(-)

diffs (238 lines):

diff -r a3aa7616242f -r e3908de22db5 sys/dev/acpi/acpi_util.c
--- a/sys/dev/acpi/acpi_util.c  Wed Jan 27 05:00:15 2021 +0000
+++ b/sys/dev/acpi/acpi_util.c  Wed Jan 27 05:11:54 2021 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: acpi_util.c,v 1.22 2021/01/26 00:23:16 jmcneill Exp $ */
+/*     $NetBSD: acpi_util.c,v 1.23 2021/01/27 05:11:54 thorpej 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.22 2021/01/26 00:23:16 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: acpi_util.c,v 1.23 2021/01/27 05:11:54 thorpej Exp $");
 
 #include <sys/param.h>
 #include <sys/kmem.h>
@@ -306,7 +306,7 @@
 }
 
 /*
- * Pack _HID and _CID ID strings into an OpenFirmware-like
+ * Pack _HID and _CID ID strings into an OpenFirmware-style
  * string list.
  */
 char *
@@ -314,50 +314,144 @@
 {
        KASSERT(sizep != NULL);
 
-       char *strlist, *cp;
-       size_t len = 0;
+       char *sl = NULL;
+       size_t slsize = 0;
        uint32_t i;
 
-       /*
-        * First calculate the total size required.
-        * N.B. PNP Device ID length includes terminating NUL.
-        */
        if ((ad->Valid & ACPI_VALID_HID) != 0) {
-               len += ad->HardwareId.Length;
+               strlist_append(&sl, &slsize, ad->HardwareId.String);
        }
 
        if ((ad->Valid & ACPI_VALID_CID) != 0) {
                for (i = 0; i < ad->CompatibleIdList.Count; i++) {
-                       len += ad->CompatibleIdList.Ids[i].Length;
+                       strlist_append(&sl, &slsize,
+                           ad->CompatibleIdList.Ids[i].String);
                }
        }
 
-       *sizep = len;
-       if (len == 0) {
+       *sizep = slsize;
+       return sl;
+}
+
+/*
+ * The ACPI_PNP_DEVICE_ID type is somewhat inconvenient for us to
+ * use.  We'll need some temporary space to pack it into an array
+ * of C strings.  Room for 8 should be plenty, but we can allocate
+ * more if necessary.
+ */
+#define        ACPI_COMPATSTR_MAX      8
+
+static const char **
+acpi_compatible_alloc_strarray(ACPI_PNP_DEVICE_ID *ids,
+    unsigned int count, const char **buf)
+{
+       unsigned int i;
+
+       buf = kmem_tmpbuf_alloc(count * sizeof(const char *),
+           buf, ACPI_COMPATSTR_MAX * sizeof(const char *), KM_SLEEP);
+       for (i = 0; i < count; i++) {
+               buf[i] = ids[i].String;
+       }
+       return buf;
+}
+
+static void
+acpi_compatible_free_strarray(const char **cpp, unsigned int count,
+    const char **buf)
+{
+       kmem_tmpbuf_free(cpp, count * sizeof(const char *), buf);
+}
+
+/*
+ * acpi_compatible_match --
+ *
+ *     Returns a weighted match value, comparing the _HID and _CID
+ *     IDs against a driver's compatbility data.
+ */
+int
+acpi_compatible_match(const struct acpi_attach_args * const aa,
+    const struct device_compatible_entry * const dce)
+{
+       const char *strings[ACPI_COMPATSTR_MAX * sizeof(const char *)];
+       const char **cpp;
+
+       if (aa->aa_node->ad_type != ACPI_TYPE_DEVICE) {
+               return 0;
+       }
+
+       ACPI_DEVICE_INFO *ad = aa->aa_node->ad_devinfo;
+
+       if ((ad->Valid & ACPI_VALID_HID) != 0) {
+               strings[0] = ad->HardwareId.String;
+
+               /* Matching _HID wins big. */
+               if (device_compatible_pmatch(strings, 1, dce) != 0) {
+                       return ACPI_MATCHSCORE_HID;
+               }
+       }
+
+       if ((ad->Valid & ACPI_VALID_CID) != 0) {
+               cpp = acpi_compatible_alloc_strarray(ad->CompatibleIdList.Ids,
+                   ad->CompatibleIdList.Count, strings);
+               int rv;
+
+               rv = device_compatible_pmatch(cpp,
+                   ad->CompatibleIdList.Count, dce);
+               acpi_compatible_free_strarray(cpp, ad->CompatibleIdList.Count,
+                   strings);
+               if (rv) {
+                       rv = (rv - 1) + ACPI_MATCHSCORE_CID;
+                       if (rv > ACPI_MATCHSCORE_CID_MAX) {
+                               rv = ACPI_MATCHSCORE_CID_MAX;
+                       }
+                       return rv;
+               }
+       }
+
+       return 0;
+}
+
+/*
+ * acpi_compatible_lookup --
+ *
+ *     Returns the device_compatible_entry that matches the _HID
+ *     or _CID ID.
+ */
+const struct device_compatible_entry *
+acpi_compatible_lookup(const struct acpi_attach_args * const aa,
+    const struct device_compatible_entry * const dce)
+{
+       const struct device_compatible_entry *rv = NULL;
+       const char *strings[ACPI_COMPATSTR_MAX];
+       const char **cpp;
+
+       if (aa->aa_node->ad_type != ACPI_TYPE_DEVICE) {
                return NULL;
        }
 
-       cp = strlist = kmem_alloc(len, KM_SLEEP);
+       ACPI_DEVICE_INFO *ad = aa->aa_node->ad_devinfo;
 
        if ((ad->Valid & ACPI_VALID_HID) != 0) {
-               memcpy(cp, ad->HardwareId.String, ad->HardwareId.Length);
-               cp += ad->HardwareId.Length;
+               strings[0] = ad->HardwareId.String;
+
+               rv = device_compatible_plookup(strings, 1, dce);
+               if (rv != NULL)
+                       return rv;
        }
 
        if ((ad->Valid & ACPI_VALID_CID) != 0) {
-               for (i = 0; i < ad->CompatibleIdList.Count; i++) {
-                       memcpy(cp, ad->CompatibleIdList.Ids[i].String,
-                           ad->CompatibleIdList.Ids[i].Length);
-                       cp += ad->CompatibleIdList.Ids[i].Length;
-               }
+               cpp = acpi_compatible_alloc_strarray(ad->CompatibleIdList.Ids,
+                   ad->CompatibleIdList.Count, strings);
+
+               rv = device_compatible_plookup(cpp,
+                   ad->CompatibleIdList.Count, dce);
+               acpi_compatible_free_strarray(cpp, ad->CompatibleIdList.Count,
+                   strings);
        }
 
-       KASSERT((size_t)(cp - strlist) == len);
-
-       return strlist;
+       return rv;
 }
 
-
 /*
  * Match given IDs against _HID and _CIDs.
  */
@@ -428,7 +522,7 @@
 done:
        if (buf.Pointer)
                ACPI_FREE(buf.Pointer);
-       return match;
+       return match ? ACPI_MATCHSCORE_CLS : 0;
 }
 
 /*
diff -r a3aa7616242f -r e3908de22db5 sys/dev/acpi/acpivar.h
--- a/sys/dev/acpi/acpivar.h    Wed Jan 27 05:00:15 2021 +0000
+++ b/sys/dev/acpi/acpivar.h    Wed Jan 27 05:11:54 2021 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: acpivar.h,v 1.83 2020/12/06 11:38:28 jmcneill Exp $    */
+/*     $NetBSD: acpivar.h,v 1.84 2021/01/27 05:11:54 thorpej Exp $     */
 
 /*
  * Copyright 2001 Wasabi Systems, Inc.
@@ -195,6 +195,12 @@
        bus_dma_tag_t aa_dmat64;        /* PCI 64bit DMA tag */
 };
 
+/* ACPI driver matching scores. */
+#define        ACPI_MATCHSCORE_HID             100     /* matched _HID */
+#define        ACPI_MATCHSCORE_CID_MAX         49
+#define        ACPI_MATCHSCORE_CID             10      /* matched _CID */
+#define        ACPI_MATCHSCORE_CLS             1       /* matched _CLS */
+
 /*
  * ACPI resources:
  *
@@ -306,6 +312,12 @@
 void           acpi_disable(void);
 int            acpi_check(device_t, const char *);
 
+int            acpi_compatible_match(const struct acpi_attach_args *,
+                   const struct device_compatible_entry *);
+const struct device_compatible_entry *
+               acpi_compatible_lookup(const struct acpi_attach_args *,
+                   const struct device_compatible_entry *);
+
 bool           acpi_device_present(ACPI_HANDLE);
 
 int            acpi_reset(void);



Home | Main Index | Thread Index | Old Index