perf/x86/uncore: Ignore broken units in discovery table
authorKan Liang <kan.liang@linux.intel.com>
Thu, 12 Jan 2023 20:01:03 +0000 (12:01 -0800)
committerPeter Zijlstra <peterz@infradead.org>
Fri, 20 Jan 2023 23:06:12 +0000 (00:06 +0100)
Some units in a discovery table may be broken, e.g., UPI of SPR MCC.
A generic method is required to ignore the broken units.

Add uncore_units_ignore in the struct intel_uncore_init_fun, which
indicates the type ID of broken units. It will be assigned by the
platform-specific code later when the platform has a broken discovery
table.

Signed-off-by: Kan Liang <kan.liang@linux.intel.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Tested-by: Michael Petlan <mpetlan@redhat.com>
Link: https://lore.kernel.org/r/20230112200105.733466-4-kan.liang@linux.intel.com
arch/x86/events/intel/uncore.c
arch/x86/events/intel/uncore.h
arch/x86/events/intel/uncore_discovery.c
arch/x86/events/intel/uncore_discovery.h

index 271c01621303d0ffb297fca495451b4c209071d6..d9a2ef5eb182a63f7ea8cfaf593c07f01ca26287 100644 (file)
@@ -1695,7 +1695,10 @@ struct intel_uncore_init_fun {
        void    (*cpu_init)(void);
        int     (*pci_init)(void);
        void    (*mmio_init)(void);
+       /* Discovery table is required */
        bool    use_discovery;
+       /* The units in the discovery table should be ignored. */
+       int     *uncore_units_ignore;
 };
 
 static const struct intel_uncore_init_fun nhm_uncore_init __initconst = {
@@ -1874,7 +1877,7 @@ static int __init intel_uncore_init(void)
 
        id = x86_match_cpu(intel_uncore_match);
        if (!id) {
-               if (!uncore_no_discover && intel_uncore_has_discovery_tables())
+               if (!uncore_no_discover && intel_uncore_has_discovery_tables(NULL))
                        uncore_init = (struct intel_uncore_init_fun *)&generic_uncore_init;
                else
                        return -ENODEV;
@@ -1882,7 +1885,8 @@ static int __init intel_uncore_init(void)
                uncore_init = (struct intel_uncore_init_fun *)id->driver_data;
                if (uncore_no_discover && uncore_init->use_discovery)
                        return -ENODEV;
-               if (uncore_init->use_discovery && !intel_uncore_has_discovery_tables())
+               if (uncore_init->use_discovery &&
+                   !intel_uncore_has_discovery_tables(uncore_init->uncore_units_ignore))
                        return -ENODEV;
        }
 
index 8d493bea9eb6c807a148d0e6caec8c4ccc135392..bbaa57cd868d34989a7d88ddcecca200f8c64355 100644 (file)
@@ -34,6 +34,8 @@
 
 #define UNCORE_EVENT_CONSTRAINT(c, n) EVENT_CONSTRAINT(c, n, 0xff)
 
+#define UNCORE_IGNORE_END              -1
+
 struct pci_extra_dev {
        struct pci_dev *dev[UNCORE_EXTRA_PCI_DEV_MAX];
 };
index 08af92af2be22ae2f0345ac3ee6d499529f45541..abb51191f5af84570067457995d0a6752d51ee6a 100644 (file)
@@ -190,8 +190,25 @@ free_box_offset:
 
 }
 
+static bool
+uncore_ignore_unit(struct uncore_unit_discovery *unit, int *ignore)
+{
+       int i;
+
+       if (!ignore)
+               return false;
+
+       for (i = 0; ignore[i] != UNCORE_IGNORE_END ; i++) {
+               if (unit->box_type == ignore[i])
+                       return true;
+       }
+
+       return false;
+}
+
 static int parse_discovery_table(struct pci_dev *dev, int die,
-                                u32 bar_offset, bool *parsed)
+                                u32 bar_offset, bool *parsed,
+                                int *ignore)
 {
        struct uncore_global_discovery global;
        struct uncore_unit_discovery unit;
@@ -246,6 +263,9 @@ static int parse_discovery_table(struct pci_dev *dev, int die,
                if (unit.access_type >= UNCORE_ACCESS_MAX)
                        continue;
 
+               if (uncore_ignore_unit(&unit, ignore))
+                       continue;
+
                uncore_insert_box_info(&unit, die, *parsed);
        }
 
@@ -254,7 +274,7 @@ static int parse_discovery_table(struct pci_dev *dev, int die,
        return 0;
 }
 
-bool intel_uncore_has_discovery_tables(void)
+bool intel_uncore_has_discovery_tables(int *ignore)
 {
        u32 device, val, entry_id, bar_offset;
        int die, dvsec = 0, ret = true;
@@ -290,7 +310,7 @@ bool intel_uncore_has_discovery_tables(void)
                        if (die < 0)
                                continue;
 
-                       parse_discovery_table(dev, die, bar_offset, &parsed);
+                       parse_discovery_table(dev, die, bar_offset, &parsed, ignore);
                }
        }
 
index f4439357779a3e91a1255da7cfd00d1e684bbaf8..41637022b5d11692d17349f47cdf85015fe50785 100644 (file)
@@ -122,7 +122,7 @@ struct intel_uncore_discovery_type {
        unsigned int    *box_offset;    /* Box offset */
 };
 
-bool intel_uncore_has_discovery_tables(void);
+bool intel_uncore_has_discovery_tables(int *ignore);
 void intel_uncore_clear_discovery_tables(void);
 void intel_uncore_generic_uncore_cpu_init(void);
 int intel_uncore_generic_uncore_pci_init(void);