Currently, the vendor detection is implemented using a series of
hard-coded "if/else if" string comparisons, which does not support ARM,
as the ARM implementer is indicated by other sequences in /proc/cpuinfo.

This commit refactors the vendor detection to be data-driven and
extensible.  It introduces a lookup table to define all vendor-specific
detection rules.  This separates the detection algorithm from the data.

The new lookup table is implemented as a variable-length array of nested
anonymous structs to to map a file to a sequence of string and vendor.

This makes the code cleaner, maintainable, and simplifies the addition
of support for new vendors (e.g., ARM) in the future.

Signed-off-by: Yifan Wu <[email protected]>
---
 .../testing/selftests/resctrl/resctrl_tests.c | 82 ++++++++++++++-----
 1 file changed, 60 insertions(+), 22 deletions(-)

diff --git a/tools/testing/selftests/resctrl/resctrl_tests.c 
b/tools/testing/selftests/resctrl/resctrl_tests.c
index dbcd5eea9fbc..419d876a97c2 100644
--- a/tools/testing/selftests/resctrl/resctrl_tests.c
+++ b/tools/testing/selftests/resctrl/resctrl_tests.c
@@ -23,39 +23,77 @@ static struct resctrl_test *resctrl_tests[] = {
        &l2_noncont_cat_test,
 };
 
+#define VENDOR_ENTRY struct {\
+       unsigned int vendor_id; \
+       void *arg; \
+       }
+
+#define SEQ_ENTRY struct {\
+       char *format; \
+       VENDOR_ENTRY *vendor; \
+       }
+
+#define DETECTION_ENTRY struct {\
+       char *pathname; \
+       SEQ_ENTRY *seq; \
+       }
+
+static DETECTION_ENTRY vendor_detection[] = {
+       {
+               .pathname = "/proc/cpuinfo",
+               .seq = (SEQ_ENTRY[]) {
+                       {
+                               .format = "vendor_id\t: %s\n",
+                               .vendor = (VENDOR_ENTRY[]) {
+                                       { .vendor_id = ARCH_INTEL,      .arg = 
"GenuineIntel" },
+                                       { .vendor_id = ARCH_AMD,        .arg = 
"AuthenticAMD" },
+                                       { .vendor_id = ARCH_HYGON,      .arg = 
"HygonGenuine" },
+                                       { .vendor_id = 0,       .arg = NULL }
+                               }
+                       }
+               }
+       },
+       { .pathname = NULL, .seq = NULL}
+};
+
 static unsigned int detect_vendor(void)
 {
        static unsigned int vendor_id;
        static bool initialized;
-       char *s = NULL;
+       char s[64];
        FILE *inf;
        char *res;
 
        if (initialized)
                return vendor_id;
 
-       inf = fopen("/proc/cpuinfo", "r");
-       if (!inf) {
-               vendor_id = 0;
-               initialized = true;
-               return vendor_id;
+       for (DETECTION_ENTRY *dentry = &vendor_detection[0];
+                dentry && dentry->pathname;
+                dentry++) {
+               inf = fopen(dentry->pathname, "r");
+               if (!inf)
+                       continue;
+               for (SEQ_ENTRY *sentry = &dentry->seq[0];
+                        sentry && sentry->format;
+                        sentry++) {
+                       for (VENDOR_ENTRY *ventry = &sentry->vendor[0];
+                                ventry && ventry->vendor_id;
+                                ventry++) {
+                               snprintf(s, sizeof(s), sentry->format, 
ventry->arg);
+                               char *res = fgrep(inf, s);
+
+                               if (res) {
+                                       free(res);
+                                       fclose(inf);
+                                       vendor_id = ventry->vendor_id;
+                                       goto out;
+                               }
+                               rewind(inf);
+                       }
+               }
+               fclose(inf);
        }
-
-       res = fgrep(inf, "vendor_id");
-
-       if (res)
-               s = strchr(res, ':');
-
-       if (s && !strcmp(s, ": GenuineIntel\n"))
-               vendor_id = ARCH_INTEL;
-       else if (s && !strcmp(s, ": AuthenticAMD\n"))
-               vendor_id = ARCH_AMD;
-       else if (s && !strcmp(s, ": HygonGenuine\n"))
-               vendor_id = ARCH_HYGON;
-
-       fclose(inf);
-       free(res);
-
+out:
        initialized = true;
        return vendor_id;
 }
-- 
2.33.0


Reply via email to