EDAC, {skx,i10nm}: Make some configurations CPU model specific
authorQiuxu Zhuo <qiuxu.zhuo@intel.com>
Fri, 24 Apr 2020 12:18:14 +0000 (20:18 +0800)
committerTony Luck <tony.luck@intel.com>
Mon, 27 Apr 2020 16:29:41 +0000 (09:29 -0700)
The device ID for configuration agent PCI device and the offset for
bus number configuration register can be CPU model specific. So add
a new structure res_config to make them configurable and pass res_config
to {skx,i10nm}_init() and skx_get_all_bus_mappings() for use.

Signed-off-by: Qiuxu Zhuo <qiuxu.zhuo@intel.com>
Signed-off-by: Tony Luck <tony.luck@intel.com>
Reviewed-by: Borislav Petkov <bp@suse.de>
Link: https://lore.kernel.org/r/20200427083246.GB11036@zn.tnic
drivers/edac/i10nm_base.c
drivers/edac/skx_base.c
drivers/edac/skx_common.c
drivers/edac/skx_common.h

index df08de963d1017607de5df515108e445bf3cd79e..20859dcf52398a0bb042d863968964d09a3688a1 100644 (file)
@@ -122,10 +122,16 @@ static int i10nm_get_all_munits(void)
        return 0;
 }
 
+static struct res_config i10nm_cfg = {
+       .type                   = I10NM,
+       .decs_did               = 0x3452,
+       .busno_cfg_offset       = 0xcc,
+};
+
 static const struct x86_cpu_id i10nm_cpuids[] = {
-       X86_MATCH_INTEL_FAM6_MODEL(ATOM_TREMONT_D,      NULL),
-       X86_MATCH_INTEL_FAM6_MODEL(ICELAKE_X,           NULL),
-       X86_MATCH_INTEL_FAM6_MODEL(ICELAKE_D,           NULL),
+       X86_MATCH_INTEL_FAM6_MODEL(ATOM_TREMONT_D,      &i10nm_cfg),
+       X86_MATCH_INTEL_FAM6_MODEL(ICELAKE_X,           &i10nm_cfg),
+       X86_MATCH_INTEL_FAM6_MODEL(ICELAKE_D,           &i10nm_cfg),
        {}
 };
 MODULE_DEVICE_TABLE(x86cpu, i10nm_cpuids);
@@ -234,6 +240,7 @@ static int __init i10nm_init(void)
 {
        u8 mc = 0, src_id = 0, node_id = 0;
        const struct x86_cpu_id *id;
+       struct res_config *cfg;
        const char *owner;
        struct skx_dev *d;
        int rc, i, off[3] = {0xd0, 0xc8, 0xcc};
@@ -249,11 +256,13 @@ static int __init i10nm_init(void)
        if (!id)
                return -ENODEV;
 
+       cfg = (struct res_config *)id->driver_data;
+
        rc = skx_get_hi_lo(0x09a2, off, &tolm, &tohm);
        if (rc)
                return rc;
 
-       rc = skx_get_all_bus_mappings(0x3452, 0xcc, I10NM, &i10nm_edac_list);
+       rc = skx_get_all_bus_mappings(cfg, &i10nm_edac_list);
        if (rc < 0)
                goto fail;
        if (rc == 0) {
index 46a3a3440f5e7f1225b161ca38fc9bb5728d8e6c..94c942fd06c13eaaf1523c0601ce34e48d86d9bf 100644 (file)
@@ -157,8 +157,14 @@ fail:
        return -ENODEV;
 }
 
+static struct res_config skx_cfg = {
+       .type                   = SKX,
+       .decs_did               = 0x2016,
+       .busno_cfg_offset       = 0xcc,
+};
+
 static const struct x86_cpu_id skx_cpuids[] = {
-       X86_MATCH_INTEL_FAM6_MODEL(SKYLAKE_X,   NULL),
+       X86_MATCH_INTEL_FAM6_MODEL(SKYLAKE_X,   &skx_cfg),
        { }
 };
 MODULE_DEVICE_TABLE(x86cpu, skx_cpuids);
@@ -641,6 +647,7 @@ static inline void teardown_skx_debug(void) {}
 static int __init skx_init(void)
 {
        const struct x86_cpu_id *id;
+       struct res_config *cfg;
        const struct munit *m;
        const char *owner;
        int rc = 0, i, off[3] = {0xd0, 0xd4, 0xd8};
@@ -657,11 +664,13 @@ static int __init skx_init(void)
        if (!id)
                return -ENODEV;
 
+       cfg = (struct res_config *)id->driver_data;
+
        rc = skx_get_hi_lo(0x2034, off, &skx_tolm, &skx_tohm);
        if (rc)
                return rc;
 
-       rc = skx_get_all_bus_mappings(0x2016, 0xcc, SKX, &skx_edac_list);
+       rc = skx_get_all_bus_mappings(cfg, &skx_edac_list);
        if (rc < 0)
                goto fail;
        if (rc == 0) {
index 99bbaf629b8d90ee18a321b68bac0edd55f62049..abc9ddd2b7d18eb31ecf8c64ee451b40b2a85b7d 100644 (file)
@@ -197,12 +197,11 @@ static int get_width(u32 mtr)
 }
 
 /*
- * We use the per-socket device @did to count how many sockets are present,
+ * We use the per-socket device @cfg->did to count how many sockets are present,
  * and to detemine which PCI buses are associated with each socket. Allocate
  * and build the full list of all the skx_dev structures that we need here.
  */
-int skx_get_all_bus_mappings(unsigned int did, int off, enum type type,
-                            struct list_head **list)
+int skx_get_all_bus_mappings(struct res_config *cfg, struct list_head **list)
 {
        struct pci_dev *pdev, *prev;
        struct skx_dev *d;
@@ -211,7 +210,7 @@ int skx_get_all_bus_mappings(unsigned int did, int off, enum type type,
 
        prev = NULL;
        for (;;) {
-               pdev = pci_get_device(PCI_VENDOR_ID_INTEL, did, prev);
+               pdev = pci_get_device(PCI_VENDOR_ID_INTEL, cfg->decs_did, prev);
                if (!pdev)
                        break;
                ndev++;
@@ -221,7 +220,7 @@ int skx_get_all_bus_mappings(unsigned int did, int off, enum type type,
                        return -ENOMEM;
                }
 
-               if (pci_read_config_dword(pdev, off, &reg)) {
+               if (pci_read_config_dword(pdev, cfg->busno_cfg_offset, &reg)) {
                        kfree(d);
                        pci_dev_put(pdev);
                        skx_printk(KERN_ERR, "Failed to read bus idx\n");
@@ -230,7 +229,7 @@ int skx_get_all_bus_mappings(unsigned int did, int off, enum type type,
 
                d->bus[0] = GET_BITFIELD(reg, 0, 7);
                d->bus[1] = GET_BITFIELD(reg, 8, 15);
-               if (type == SKX) {
+               if (cfg->type == SKX) {
                        d->seg = pci_domain_nr(pdev->bus);
                        d->bus[2] = GET_BITFIELD(reg, 16, 23);
                        d->bus[3] = GET_BITFIELD(reg, 24, 31);
index 60d1ea669afd49e46b0212cc2fe5436fabbc4b40..19dd8c0995200cfcae257ddc203bcca700d8f40b 100644 (file)
@@ -112,6 +112,14 @@ struct decoded_addr {
        int     bank_group;
 };
 
+struct res_config {
+       enum type type;
+       /* Configuration agent device ID */
+       unsigned int decs_did;
+       /* Default bus number configuration register offset */
+       int busno_cfg_offset;
+};
+
 typedef int (*get_dimm_config_f)(struct mem_ctl_info *mci);
 typedef bool (*skx_decode_f)(struct decoded_addr *res);
 typedef void (*skx_show_retry_log_f)(struct decoded_addr *res, char *msg, int len);
@@ -123,8 +131,7 @@ void skx_set_decode(skx_decode_f decode, skx_show_retry_log_f show_retry_log);
 int skx_get_src_id(struct skx_dev *d, int off, u8 *id);
 int skx_get_node_id(struct skx_dev *d, u8 *id);
 
-int skx_get_all_bus_mappings(unsigned int did, int off, enum type,
-                            struct list_head **list);
+int skx_get_all_bus_mappings(struct res_config *cfg, struct list_head **list);
 
 int skx_get_hi_lo(unsigned int did, int off[], u64 *tolm, u64 *tohm);