Skip to content

Commit

Permalink
EDAC, {skx,i10nm}: Make some configurations CPU model specific
Browse files Browse the repository at this point in the history
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 <[email protected]>
Signed-off-by: Tony Luck <[email protected]>
Reviewed-by: Borislav Petkov <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
  • Loading branch information
qzhuo2 authored and aegl committed Apr 27, 2020
1 parent 8f3d9f3 commit ee5340a
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 14 deletions.
17 changes: 13 additions & 4 deletions drivers/edac/i10nm_base.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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};
Expand All @@ -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) {
Expand Down
13 changes: 11 additions & 2 deletions drivers/edac/skx_base.c
Original file line number Diff line number Diff line change
Expand Up @@ -157,8 +157,14 @@ static int get_all_munits(const struct munit *m)
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);
Expand Down Expand Up @@ -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};
Expand All @@ -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) {
Expand Down
11 changes: 5 additions & 6 deletions drivers/edac/skx_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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++;
Expand All @@ -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");
Expand All @@ -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);
Expand Down
11 changes: 9 additions & 2 deletions drivers/edac/skx_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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);

Expand Down

0 comments on commit ee5340a

Please sign in to comment.