Commit 26d3a77d authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'edac_for_4.13' of git://git.kernel.org/pub/scm/linux/kernel/git/bp/bp

Pull EDAC updates from Borislav Petkov:
 "Nothing earth-shattering - just the normal development flow of
  cleanups, improvements, fixes and such.

  Summary:

   - i31200_edac: Add Kabylake support (Jason Baron)

   - sb_edac: resolve memory controller detection issues on asymmetric
     setups with not all DIMM slots being populated (Tony Luck and Qiuxu
     Zhuo)

   - misc cleanups and fixlets all over"

* tag 'edac_for_4.13' of git://git.kernel.org/pub/scm/linux/kernel/git/bp/bp: (22 commits)
  EDAC, pnd2: Fix Apollo Lake DIMM detection
  EDAC, i5000, i5400: Fix definition of NRECMEMB register
  EDAC, pnd2: Make function sbi_send() static
  EDAC, pnd2: Return proper error value from apl_rd_reg()
  EDAC, altera: Simplify calculation of total memory
  EDAC, sb_edac: Avoid creating SOCK memory controller
  EDAC, mce_amd: Fix typo in SMCA error description
  EDAC, mv64x60: Sanity check edac_op_state before registering
  EDAC, thunderx: Fix a warning during l2c debugfs node creation
  EDAC, mv64x60: Check driver registration success
  EDAC, ie31200: Add Intel Kaby Lake CPU support
  EDAC, mv64x60: Replace in_le32()/out_le32() with readl()/writel()
  EDAC, mv64x60: Fix pdata->name
  EDAC, sb_edac: Bump driver version and do some cleanups
  EDAC, sb_edac: Check if ECC enabled when at least one DIMM is present
  EDAC, sb_edac: Drop NUM_CHANNELS from 8 back to 4
  EDAC, sb_edac: Carve out dimm-populating loop
  EDAC, sb_edac: Fix mod_name
  EDAC, sb_edac: Assign EDAC memory controller per h/w controller
  EDAC, sb_edac: Don't use "Socket#" in the memory controller name
  ...
parents c6b1e36c 164c2924
...@@ -214,24 +214,16 @@ static void altr_sdr_mc_create_debugfs_nodes(struct mem_ctl_info *mci) ...@@ -214,24 +214,16 @@ static void altr_sdr_mc_create_debugfs_nodes(struct mem_ctl_info *mci)
static unsigned long get_total_mem(void) static unsigned long get_total_mem(void)
{ {
struct device_node *np = NULL; struct device_node *np = NULL;
const unsigned int *reg, *reg_end; struct resource res;
int len, sw, aw; int ret;
unsigned long start, size, total_mem = 0; unsigned long total_mem = 0;
for_each_node_by_type(np, "memory") { for_each_node_by_type(np, "memory") {
aw = of_n_addr_cells(np); ret = of_address_to_resource(np, 0, &res);
sw = of_n_size_cells(np); if (ret)
reg = (const unsigned int *)of_get_property(np, "reg", &len); continue;
reg_end = reg + (len / sizeof(u32));
total_mem += resource_size(&res);
total_mem = 0;
do {
start = of_read_number(reg, aw);
reg += aw;
size = of_read_number(reg, sw);
reg += sw;
total_mem += size;
} while (reg < reg_end);
} }
edac_dbg(0, "total_mem 0x%lx\n", total_mem); edac_dbg(0, "total_mem 0x%lx\n", total_mem);
return total_mem; return total_mem;
...@@ -1839,7 +1831,7 @@ static int a10_eccmgr_irqdomain_map(struct irq_domain *d, unsigned int irq, ...@@ -1839,7 +1831,7 @@ static int a10_eccmgr_irqdomain_map(struct irq_domain *d, unsigned int irq,
return 0; return 0;
} }
static struct irq_domain_ops a10_eccmgr_ic_ops = { static const struct irq_domain_ops a10_eccmgr_ic_ops = {
.map = a10_eccmgr_irqdomain_map, .map = a10_eccmgr_irqdomain_map,
.xlate = irq_domain_xlate_twocell, .xlate = irq_domain_xlate_twocell,
}; };
......
...@@ -227,7 +227,7 @@ ...@@ -227,7 +227,7 @@
#define NREC_RDWR(x) (((x)>>11) & 1) #define NREC_RDWR(x) (((x)>>11) & 1)
#define NREC_RANK(x) (((x)>>8) & 0x7) #define NREC_RANK(x) (((x)>>8) & 0x7)
#define NRECMEMB 0xC0 #define NRECMEMB 0xC0
#define NREC_CAS(x) (((x)>>16) & 0xFFFFFF) #define NREC_CAS(x) (((x)>>16) & 0xFFF)
#define NREC_RAS(x) ((x) & 0x7FFF) #define NREC_RAS(x) ((x) & 0x7FFF)
#define NRECFGLOG 0xC4 #define NRECFGLOG 0xC4
#define NREEECFBDA 0xC8 #define NREEECFBDA 0xC8
...@@ -371,7 +371,7 @@ struct i5000_error_info { ...@@ -371,7 +371,7 @@ struct i5000_error_info {
/* These registers are input ONLY if there was a /* These registers are input ONLY if there was a
* Non-Recoverable Error */ * Non-Recoverable Error */
u16 nrecmema; /* Non-Recoverable Mem log A */ u16 nrecmema; /* Non-Recoverable Mem log A */
u16 nrecmemb; /* Non-Recoverable Mem log B */ u32 nrecmemb; /* Non-Recoverable Mem log B */
}; };
...@@ -407,7 +407,7 @@ static void i5000_get_error_info(struct mem_ctl_info *mci, ...@@ -407,7 +407,7 @@ static void i5000_get_error_info(struct mem_ctl_info *mci,
NERR_FAT_FBD, &info->nerr_fat_fbd); NERR_FAT_FBD, &info->nerr_fat_fbd);
pci_read_config_word(pvt->branchmap_werrors, pci_read_config_word(pvt->branchmap_werrors,
NRECMEMA, &info->nrecmema); NRECMEMA, &info->nrecmema);
pci_read_config_word(pvt->branchmap_werrors, pci_read_config_dword(pvt->branchmap_werrors,
NRECMEMB, &info->nrecmemb); NRECMEMB, &info->nrecmemb);
/* Clear the error bits, by writing them back */ /* Clear the error bits, by writing them back */
......
...@@ -368,7 +368,7 @@ struct i5400_error_info { ...@@ -368,7 +368,7 @@ struct i5400_error_info {
/* These registers are input ONLY if there was a Non-Rec Error */ /* These registers are input ONLY if there was a Non-Rec Error */
u16 nrecmema; /* Non-Recoverable Mem log A */ u16 nrecmema; /* Non-Recoverable Mem log A */
u16 nrecmemb; /* Non-Recoverable Mem log B */ u32 nrecmemb; /* Non-Recoverable Mem log B */
}; };
...@@ -458,7 +458,7 @@ static void i5400_get_error_info(struct mem_ctl_info *mci, ...@@ -458,7 +458,7 @@ static void i5400_get_error_info(struct mem_ctl_info *mci,
NERR_FAT_FBD, &info->nerr_fat_fbd); NERR_FAT_FBD, &info->nerr_fat_fbd);
pci_read_config_word(pvt->branchmap_werrors, pci_read_config_word(pvt->branchmap_werrors,
NRECMEMA, &info->nrecmema); NRECMEMA, &info->nrecmema);
pci_read_config_word(pvt->branchmap_werrors, pci_read_config_dword(pvt->branchmap_werrors,
NRECMEMB, &info->nrecmemb); NRECMEMB, &info->nrecmemb);
/* Clear the error bits, by writing them back */ /* Clear the error bits, by writing them back */
......
...@@ -18,10 +18,12 @@ ...@@ -18,10 +18,12 @@
* 0c04: Xeon E3-1200 v3/4th Gen Core Processor DRAM Controller * 0c04: Xeon E3-1200 v3/4th Gen Core Processor DRAM Controller
* 0c08: Xeon E3-1200 v3 Processor DRAM Controller * 0c08: Xeon E3-1200 v3 Processor DRAM Controller
* 1918: Xeon E3-1200 v5 Skylake Host Bridge/DRAM Registers * 1918: Xeon E3-1200 v5 Skylake Host Bridge/DRAM Registers
* 5918: Xeon E3-1200 Xeon E3-1200 v6/7th Gen Core Processor Host Bridge/DRAM Registers
* *
* Based on Intel specification: * Based on Intel specification:
* http://www.intel.com/content/dam/www/public/us/en/documents/datasheets/xeon-e3-1200v3-vol-2-datasheet.pdf * http://www.intel.com/content/dam/www/public/us/en/documents/datasheets/xeon-e3-1200v3-vol-2-datasheet.pdf
* http://www.intel.com/content/www/us/en/processors/xeon/xeon-e3-1200-family-vol-2-datasheet.html * http://www.intel.com/content/www/us/en/processors/xeon/xeon-e3-1200-family-vol-2-datasheet.html
* http://www.intel.com/content/www/us/en/processors/core/7th-gen-core-family-mobile-h-processor-lines-datasheet-vol-2.html
* *
* According to the above datasheet (p.16): * According to the above datasheet (p.16):
* " * "
...@@ -57,6 +59,7 @@ ...@@ -57,6 +59,7 @@
#define PCI_DEVICE_ID_INTEL_IE31200_HB_6 0x0c04 #define PCI_DEVICE_ID_INTEL_IE31200_HB_6 0x0c04
#define PCI_DEVICE_ID_INTEL_IE31200_HB_7 0x0c08 #define PCI_DEVICE_ID_INTEL_IE31200_HB_7 0x0c08
#define PCI_DEVICE_ID_INTEL_IE31200_HB_8 0x1918 #define PCI_DEVICE_ID_INTEL_IE31200_HB_8 0x1918
#define PCI_DEVICE_ID_INTEL_IE31200_HB_9 0x5918
#define IE31200_DIMMS 4 #define IE31200_DIMMS 4
#define IE31200_RANKS 8 #define IE31200_RANKS 8
...@@ -376,7 +379,12 @@ static int ie31200_probe1(struct pci_dev *pdev, int dev_idx) ...@@ -376,7 +379,12 @@ static int ie31200_probe1(struct pci_dev *pdev, int dev_idx)
void __iomem *window; void __iomem *window;
struct ie31200_priv *priv; struct ie31200_priv *priv;
u32 addr_decode, mad_offset; u32 addr_decode, mad_offset;
bool skl = (pdev->device == PCI_DEVICE_ID_INTEL_IE31200_HB_8);
/*
* Kaby Lake seems to work like Skylake. Please re-visit this logic
* when adding new CPU support.
*/
bool skl = (pdev->device >= PCI_DEVICE_ID_INTEL_IE31200_HB_8);
edac_dbg(0, "MC:\n"); edac_dbg(0, "MC:\n");
...@@ -559,6 +567,9 @@ static const struct pci_device_id ie31200_pci_tbl[] = { ...@@ -559,6 +567,9 @@ static const struct pci_device_id ie31200_pci_tbl[] = {
{ {
PCI_VEND_DEV(INTEL, IE31200_HB_8), PCI_ANY_ID, PCI_ANY_ID, 0, 0, PCI_VEND_DEV(INTEL, IE31200_HB_8), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
IE31200}, IE31200},
{
PCI_VEND_DEV(INTEL, IE31200_HB_9), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
IE31200},
{ {
0, 0,
} /* 0 terminated list. */ } /* 0 terminated list. */
......
...@@ -161,7 +161,7 @@ static const char * const smca_ls_mce_desc[] = { ...@@ -161,7 +161,7 @@ static const char * const smca_ls_mce_desc[] = {
"Sys Read data error thread 0", "Sys Read data error thread 0",
"Sys read data error thread 1", "Sys read data error thread 1",
"DC tag error type 2", "DC tag error type 2",
"DC data error type 1 (poison comsumption)", "DC data error type 1 (poison consumption)",
"DC data error type 2", "DC data error type 2",
"DC data error type 3", "DC data error type 3",
"DC tag error type 4", "DC tag error type 4",
......
...@@ -32,21 +32,21 @@ static void mv64x60_pci_check(struct edac_pci_ctl_info *pci) ...@@ -32,21 +32,21 @@ static void mv64x60_pci_check(struct edac_pci_ctl_info *pci)
struct mv64x60_pci_pdata *pdata = pci->pvt_info; struct mv64x60_pci_pdata *pdata = pci->pvt_info;
u32 cause; u32 cause;
cause = in_le32(pdata->pci_vbase + MV64X60_PCI_ERROR_CAUSE); cause = readl(pdata->pci_vbase + MV64X60_PCI_ERROR_CAUSE);
if (!cause) if (!cause)
return; return;
printk(KERN_ERR "Error in PCI %d Interface\n", pdata->pci_hose); printk(KERN_ERR "Error in PCI %d Interface\n", pdata->pci_hose);
printk(KERN_ERR "Cause register: 0x%08x\n", cause); printk(KERN_ERR "Cause register: 0x%08x\n", cause);
printk(KERN_ERR "Address Low: 0x%08x\n", printk(KERN_ERR "Address Low: 0x%08x\n",
in_le32(pdata->pci_vbase + MV64X60_PCI_ERROR_ADDR_LO)); readl(pdata->pci_vbase + MV64X60_PCI_ERROR_ADDR_LO));
printk(KERN_ERR "Address High: 0x%08x\n", printk(KERN_ERR "Address High: 0x%08x\n",
in_le32(pdata->pci_vbase + MV64X60_PCI_ERROR_ADDR_HI)); readl(pdata->pci_vbase + MV64X60_PCI_ERROR_ADDR_HI));
printk(KERN_ERR "Attribute: 0x%08x\n", printk(KERN_ERR "Attribute: 0x%08x\n",
in_le32(pdata->pci_vbase + MV64X60_PCI_ERROR_ATTR)); readl(pdata->pci_vbase + MV64X60_PCI_ERROR_ATTR));
printk(KERN_ERR "Command: 0x%08x\n", printk(KERN_ERR "Command: 0x%08x\n",
in_le32(pdata->pci_vbase + MV64X60_PCI_ERROR_CMD)); readl(pdata->pci_vbase + MV64X60_PCI_ERROR_CMD));
out_le32(pdata->pci_vbase + MV64X60_PCI_ERROR_CAUSE, ~cause); writel(~cause, pdata->pci_vbase + MV64X60_PCI_ERROR_CAUSE);
if (cause & MV64X60_PCI_PE_MASK) if (cause & MV64X60_PCI_PE_MASK)
edac_pci_handle_pe(pci, pci->ctl_name); edac_pci_handle_pe(pci, pci->ctl_name);
...@@ -61,7 +61,7 @@ static irqreturn_t mv64x60_pci_isr(int irq, void *dev_id) ...@@ -61,7 +61,7 @@ static irqreturn_t mv64x60_pci_isr(int irq, void *dev_id)
struct mv64x60_pci_pdata *pdata = pci->pvt_info; struct mv64x60_pci_pdata *pdata = pci->pvt_info;
u32 val; u32 val;
val = in_le32(pdata->pci_vbase + MV64X60_PCI_ERROR_CAUSE); val = readl(pdata->pci_vbase + MV64X60_PCI_ERROR_CAUSE);
if (!val) if (!val)
return IRQ_NONE; return IRQ_NONE;
...@@ -93,7 +93,7 @@ static int __init mv64x60_pci_fixup(struct platform_device *pdev) ...@@ -93,7 +93,7 @@ static int __init mv64x60_pci_fixup(struct platform_device *pdev)
if (!pci_serr) if (!pci_serr)
return -ENOMEM; return -ENOMEM;
out_le32(pci_serr, in_le32(pci_serr) & ~0x1); writel(readl(pci_serr) & ~0x1, pci_serr);
iounmap(pci_serr); iounmap(pci_serr);
return 0; return 0;
...@@ -116,7 +116,7 @@ static int mv64x60_pci_err_probe(struct platform_device *pdev) ...@@ -116,7 +116,7 @@ static int mv64x60_pci_err_probe(struct platform_device *pdev)
pdata = pci->pvt_info; pdata = pci->pvt_info;
pdata->pci_hose = pdev->id; pdata->pci_hose = pdev->id;
pdata->name = "mpc85xx_pci_err"; pdata->name = "mv64x60_pci_err";
platform_set_drvdata(pdev, pci); platform_set_drvdata(pdev, pci);
pci->dev = &pdev->dev; pci->dev = &pdev->dev;
pci->dev_name = dev_name(&pdev->dev); pci->dev_name = dev_name(&pdev->dev);
...@@ -161,10 +161,10 @@ static int mv64x60_pci_err_probe(struct platform_device *pdev) ...@@ -161,10 +161,10 @@ static int mv64x60_pci_err_probe(struct platform_device *pdev)
goto err; goto err;
} }
out_le32(pdata->pci_vbase + MV64X60_PCI_ERROR_CAUSE, 0); writel(0, pdata->pci_vbase + MV64X60_PCI_ERROR_CAUSE);
out_le32(pdata->pci_vbase + MV64X60_PCI_ERROR_MASK, 0); writel(0, pdata->pci_vbase + MV64X60_PCI_ERROR_MASK);
out_le32(pdata->pci_vbase + MV64X60_PCI_ERROR_MASK, writel(MV64X60_PCIx_ERR_MASK_VAL,
MV64X60_PCIx_ERR_MASK_VAL); pdata->pci_vbase + MV64X60_PCI_ERROR_MASK);
if (edac_pci_add_device(pci, pdata->edac_idx) > 0) { if (edac_pci_add_device(pci, pdata->edac_idx) > 0) {
edac_dbg(3, "failed edac_pci_add_device()\n"); edac_dbg(3, "failed edac_pci_add_device()\n");
...@@ -233,23 +233,23 @@ static void mv64x60_sram_check(struct edac_device_ctl_info *edac_dev) ...@@ -233,23 +233,23 @@ static void mv64x60_sram_check(struct edac_device_ctl_info *edac_dev)
struct mv64x60_sram_pdata *pdata = edac_dev->pvt_info; struct mv64x60_sram_pdata *pdata = edac_dev->pvt_info;
u32 cause; u32 cause;
cause = in_le32(pdata->sram_vbase + MV64X60_SRAM_ERR_CAUSE); cause = readl(pdata->sram_vbase + MV64X60_SRAM_ERR_CAUSE);
if (!cause) if (!cause)
return; return;
printk(KERN_ERR "Error in internal SRAM\n"); printk(KERN_ERR "Error in internal SRAM\n");
printk(KERN_ERR "Cause register: 0x%08x\n", cause); printk(KERN_ERR "Cause register: 0x%08x\n", cause);
printk(KERN_ERR "Address Low: 0x%08x\n", printk(KERN_ERR "Address Low: 0x%08x\n",
in_le32(pdata->sram_vbase + MV64X60_SRAM_ERR_ADDR_LO)); readl(pdata->sram_vbase + MV64X60_SRAM_ERR_ADDR_LO));
printk(KERN_ERR "Address High: 0x%08x\n", printk(KERN_ERR "Address High: 0x%08x\n",
in_le32(pdata->sram_vbase + MV64X60_SRAM_ERR_ADDR_HI)); readl(pdata->sram_vbase + MV64X60_SRAM_ERR_ADDR_HI));
printk(KERN_ERR "Data Low: 0x%08x\n", printk(KERN_ERR "Data Low: 0x%08x\n",
in_le32(pdata->sram_vbase + MV64X60_SRAM_ERR_DATA_LO)); readl(pdata->sram_vbase + MV64X60_SRAM_ERR_DATA_LO));
printk(KERN_ERR "Data High: 0x%08x\n", printk(KERN_ERR "Data High: 0x%08x\n",
in_le32(pdata->sram_vbase + MV64X60_SRAM_ERR_DATA_HI)); readl(pdata->sram_vbase + MV64X60_SRAM_ERR_DATA_HI));
printk(KERN_ERR "Parity: 0x%08x\n", printk(KERN_ERR "Parity: 0x%08x\n",
in_le32(pdata->sram_vbase + MV64X60_SRAM_ERR_PARITY)); readl(pdata->sram_vbase + MV64X60_SRAM_ERR_PARITY));
out_le32(pdata->sram_vbase + MV64X60_SRAM_ERR_CAUSE, 0); writel(0, pdata->sram_vbase + MV64X60_SRAM_ERR_CAUSE);
edac_device_handle_ue(edac_dev, 0, 0, edac_dev->ctl_name); edac_device_handle_ue(edac_dev, 0, 0, edac_dev->ctl_name);
} }
...@@ -260,7 +260,7 @@ static irqreturn_t mv64x60_sram_isr(int irq, void *dev_id) ...@@ -260,7 +260,7 @@ static irqreturn_t mv64x60_sram_isr(int irq, void *dev_id)
struct mv64x60_sram_pdata *pdata = edac_dev->pvt_info; struct mv64x60_sram_pdata *pdata = edac_dev->pvt_info;
u32 cause; u32 cause;
cause = in_le32(pdata->sram_vbase + MV64X60_SRAM_ERR_CAUSE); cause = readl(pdata->sram_vbase + MV64X60_SRAM_ERR_CAUSE);
if (!cause) if (!cause)
return IRQ_NONE; return IRQ_NONE;
...@@ -322,7 +322,7 @@ static int mv64x60_sram_err_probe(struct platform_device *pdev) ...@@ -322,7 +322,7 @@ static int mv64x60_sram_err_probe(struct platform_device *pdev)
} }
/* setup SRAM err registers */ /* setup SRAM err registers */
out_le32(pdata->sram_vbase + MV64X60_SRAM_ERR_CAUSE, 0); writel(0, pdata->sram_vbase + MV64X60_SRAM_ERR_CAUSE);
edac_dev->mod_name = EDAC_MOD_STR; edac_dev->mod_name = EDAC_MOD_STR;
edac_dev->ctl_name = pdata->name; edac_dev->ctl_name = pdata->name;
...@@ -398,7 +398,7 @@ static void mv64x60_cpu_check(struct edac_device_ctl_info *edac_dev) ...@@ -398,7 +398,7 @@ static void mv64x60_cpu_check(struct edac_device_ctl_info *edac_dev)
struct mv64x60_cpu_pdata *pdata = edac_dev->pvt_info; struct mv64x60_cpu_pdata *pdata = edac_dev->pvt_info;
u32 cause; u32 cause;
cause = in_le32(pdata->cpu_vbase[1] + MV64x60_CPU_ERR_CAUSE) & cause = readl(pdata->cpu_vbase[1] + MV64x60_CPU_ERR_CAUSE) &
MV64x60_CPU_CAUSE_MASK; MV64x60_CPU_CAUSE_MASK;
if (!cause) if (!cause)
return; return;
...@@ -406,16 +406,16 @@ static void mv64x60_cpu_check(struct edac_device_ctl_info *edac_dev) ...@@ -406,16 +406,16 @@ static void mv64x60_cpu_check(struct edac_device_ctl_info *edac_dev)
printk(KERN_ERR "Error on CPU interface\n"); printk(KERN_ERR "Error on CPU interface\n");
printk(KERN_ERR "Cause register: 0x%08x\n", cause); printk(KERN_ERR "Cause register: 0x%08x\n", cause);
printk(KERN_ERR "Address Low: 0x%08x\n", printk(KERN_ERR "Address Low: 0x%08x\n",
in_le32(pdata->cpu_vbase[0] + MV64x60_CPU_ERR_ADDR_LO)); readl(pdata->cpu_vbase[0] + MV64x60_CPU_ERR_ADDR_LO));
printk(KERN_ERR "Address High: 0x%08x\n", printk(KERN_ERR "Address High: 0x%08x\n",
in_le32(pdata->cpu_vbase[0] + MV64x60_CPU_ERR_ADDR_HI)); readl(pdata->cpu_vbase[0] + MV64x60_CPU_ERR_ADDR_HI));
printk(KERN_ERR "Data Low: 0x%08x\n", printk(KERN_ERR "Data Low: 0x%08x\n",
in_le32(pdata->cpu_vbase[1] + MV64x60_CPU_ERR_DATA_LO)); readl(pdata->cpu_vbase[1] + MV64x60_CPU_ERR_DATA_LO));
printk(KERN_ERR "Data High: 0x%08x\n", printk(KERN_ERR "Data High: 0x%08x\n",
in_le32(pdata->cpu_vbase[1] + MV64x60_CPU_ERR_DATA_HI)); readl(pdata->cpu_vbase[1] + MV64x60_CPU_ERR_DATA_HI));
printk(KERN_ERR "Parity: 0x%08x\n", printk(KERN_ERR "Parity: 0x%08x\n",
in_le32(pdata->cpu_vbase[1] + MV64x60_CPU_ERR_PARITY)); readl(pdata->cpu_vbase[1] + MV64x60_CPU_ERR_PARITY));
out_le32(pdata->cpu_vbase[1] + MV64x60_CPU_ERR_CAUSE, 0); writel(0, pdata->cpu_vbase[1] + MV64x60_CPU_ERR_CAUSE);
edac_device_handle_ue(edac_dev, 0, 0, edac_dev->ctl_name); edac_device_handle_ue(edac_dev, 0, 0, edac_dev->ctl_name);
} }
...@@ -426,7 +426,7 @@ static irqreturn_t mv64x60_cpu_isr(int irq, void *dev_id) ...@@ -426,7 +426,7 @@ static irqreturn_t mv64x60_cpu_isr(int irq, void *dev_id)
struct mv64x60_cpu_pdata *pdata = edac_dev->pvt_info; struct mv64x60_cpu_pdata *pdata = edac_dev->pvt_info;
u32 cause; u32 cause;
cause = in_le32(pdata->cpu_vbase[1] + MV64x60_CPU_ERR_CAUSE) & cause = readl(pdata->cpu_vbase[1] + MV64x60_CPU_ERR_CAUSE) &
MV64x60_CPU_CAUSE_MASK; MV64x60_CPU_CAUSE_MASK;
if (!cause) if (!cause)
return IRQ_NONE; return IRQ_NONE;
...@@ -515,9 +515,9 @@ static int mv64x60_cpu_err_probe(struct platform_device *pdev) ...@@ -515,9 +515,9 @@ static int mv64x60_cpu_err_probe(struct platform_device *pdev)
} }
/* setup CPU err registers */ /* setup CPU err registers */
out_le32(pdata->cpu_vbase[1] + MV64x60_CPU_ERR_CAUSE, 0); writel(0, pdata->cpu_vbase[1] + MV64x60_CPU_ERR_CAUSE);
out_le32(pdata->cpu_vbase[1] + MV64x60_CPU_ERR_MASK, 0); writel(0, pdata->cpu_vbase[1] + MV64x60_CPU_ERR_MASK);
out_le32(pdata->cpu_vbase[1] + MV64x60_CPU_ERR_MASK, 0x000000ff); writel(0x000000ff, pdata->cpu_vbase[1] + MV64x60_CPU_ERR_MASK);
edac_dev->mod_name = EDAC_MOD_STR; edac_dev->mod_name = EDAC_MOD_STR;
edac_dev->ctl_name = pdata->name; edac_dev->ctl_name = pdata->name;
...@@ -596,13 +596,13 @@ static void mv64x60_mc_check(struct mem_ctl_info *mci) ...@@ -596,13 +596,13 @@ static void mv64x60_mc_check(struct mem_ctl_info *mci)
u32 comp_ecc; u32 comp_ecc;
u32 syndrome; u32 syndrome;
reg = in_le32(pdata->mc_vbase + MV64X60_SDRAM_ERR_ADDR); reg = readl(pdata->mc_vbase + MV64X60_SDRAM_ERR_ADDR);
if (!reg) if (!reg)
return; return;
err_addr = reg & ~0x3; err_addr = reg & ~0x3;
sdram_ecc = in_le32(pdata->mc_vbase + MV64X60_SDRAM_ERR_ECC_RCVD); sdram_ecc = readl(pdata->mc_vbase + MV64X60_SDRAM_ERR_ECC_RCVD);
comp_ecc = in_le32(pdata->mc_vbase + MV64X60_SDRAM_ERR_ECC_CALC); comp_ecc = readl(pdata->mc_vbase + MV64X60_SDRAM_ERR_ECC_CALC);
syndrome = sdram_ecc ^ comp_ecc; syndrome = sdram_ecc ^ comp_ecc;
/* first bit clear in ECC Err Reg, 1 bit error, correctable by HW */ /* first bit clear in ECC Err Reg, 1 bit error, correctable by HW */
...@@ -620,7 +620,7 @@ static void mv64x60_mc_check(struct mem_ctl_info *mci) ...@@ -620,7 +620,7 @@ static void mv64x60_mc_check(struct mem_ctl_info *mci)
mci->ctl_name, ""); mci->ctl_name, "");
/* clear the error */ /* clear the error */
out_le32(pdata->mc_vbase + MV64X60_SDRAM_ERR_ADDR, 0); writel(0, pdata->mc_vbase + MV64X60_SDRAM_ERR_ADDR);
} }
static irqreturn_t mv64x60_mc_isr(int irq, void *dev_id) static irqreturn_t mv64x60_mc_isr(int irq, void *dev_id)
...@@ -629,7 +629,7 @@ static irqreturn_t mv64x60_mc_isr(int irq, void *dev_id) ...@@ -629,7 +629,7 @@ static irqreturn_t mv64x60_mc_isr(int irq, void *dev_id)
struct mv64x60_mc_pdata *pdata = mci->pvt_info; struct mv64x60_mc_pdata *pdata = mci->pvt_info;
u32 reg; u32 reg;
reg = in_le32(pdata->mc_vbase + MV64X60_SDRAM_ERR_ADDR); reg = readl(pdata->mc_vbase + MV64X60_SDRAM_ERR_ADDR);
if (!reg) if (!reg)
return IRQ_NONE; return IRQ_NONE;
...@@ -664,7 +664,7 @@ static void mv64x60_init_csrows(struct mem_ctl_info *mci, ...@@ -664,7 +664,7 @@ static void mv64x60_init_csrows(struct mem_ctl_info *mci,
get_total_mem(pdata); get_total_mem(pdata);
ctl = in_le32(pdata->mc_vbase + MV64X60_SDRAM_CONFIG); ctl = readl(pdata->mc_vbase + MV64X60_SDRAM_CONFIG);
csrow = mci->csrows[0]; csrow = mci->csrows[0];
dimm = csrow->channels[0]->dimm; dimm = csrow->channels[0]->dimm;
...@@ -753,7 +753,7 @@ static int mv64x60_mc_err_probe(struct platform_device *pdev) ...@@ -753,7 +753,7 @@ static int mv64x60_mc_err_probe(struct platform_device *pdev)
goto err; goto err;
} }
ctl = in_le32(pdata->mc_vbase + MV64X60_SDRAM_CONFIG); ctl = readl(pdata->mc_vbase + MV64X60_SDRAM_CONFIG);
if (!(ctl & MV64X60_SDRAM_ECC)) { if (!(ctl & MV64X60_SDRAM_ECC)) {
/* Non-ECC RAM? */ /* Non-ECC RAM? */
printk(KERN_WARNING "%s: No ECC DIMMs discovered\n", __func__); printk(KERN_WARNING "%s: No ECC DIMMs discovered\n", __func__);
...@@ -779,10 +779,10 @@ static int mv64x60_mc_err_probe(struct platform_device *pdev) ...@@ -779,10 +779,10 @@ static int mv64x60_mc_err_probe(struct platform_device *pdev)
mv64x60_init_csrows(mci, pdata); mv64x60_init_csrows(mci, pdata);
/* setup MC registers */ /* setup MC registers */
out_le32(pdata->mc_vbase + MV64X60_SDRAM_ERR_ADDR, 0); writel(0, pdata->mc_vbase + MV64X60_SDRAM_ERR_ADDR);
ctl = in_le32(pdata->mc_vbase + MV64X60_SDRAM_ERR_ECC_CNTL); ctl = readl(pdata->mc_vbase + MV64X60_SDRAM_ERR_ECC_CNTL);
ctl = (ctl & 0xff00ffff) | 0x10000; ctl = (ctl & 0xff00ffff) | 0x10000;
out_le32(pdata->mc_vbase + MV64X60_SDRAM_ERR_ECC_CNTL, ctl); writel(ctl, pdata->mc_vbase + MV64X60_SDRAM_ERR_ECC_CNTL);
res = edac_mc_add_mc(mci); res = edac_mc_add_mc(mci);
if (res) { if (res) {
...@@ -853,10 +853,10 @@ static struct platform_driver * const drivers[] = { ...@@ -853,10 +853,10 @@ static struct platform_driver * const drivers[] = {
static int __init mv64x60_edac_init(void) static int __init mv64x60_edac_init(void)
{ {
int ret = 0;
printk(KERN_INFO "Marvell MV64x60 EDAC driver " MV64x60_REVISION "\n"); printk(KERN_INFO "Marvell MV64x60 EDAC driver " MV64x60_REVISION "\n");
printk(KERN_INFO "\t(C) 2006-2007 MontaVista Software\n"); printk(KERN_INFO "\t(C) 2006-2007 MontaVista Software\n");
/* make sure error reporting method is sane */ /* make sure error reporting method is sane */
switch (edac_op_state) { switch (edac_op_state) {
case EDAC_OPSTATE_POLL: case EDAC_OPSTATE_POLL:
......
...@@ -131,7 +131,7 @@ static struct mem_ctl_info *pnd2_mci; ...@@ -131,7 +131,7 @@ static struct mem_ctl_info *pnd2_mci;
#ifdef CONFIG_X86_INTEL_SBI_APL #ifdef CONFIG_X86_INTEL_SBI_APL
#include "linux/platform_data/sbi_apl.h" #include "linux/platform_data/sbi_apl.h"
int sbi_send(int port, int off, int op, u32 *data) static int sbi_send(int port, int off, int op, u32 *data)
{ {
struct sbi_apl_message sbi_arg; struct sbi_apl_message sbi_arg;
int ret, read = 0; int ret, read = 0;
...@@ -160,7 +160,7 @@ int sbi_send(int port, int off, int op, u32 *data) ...@@ -160,7 +160,7 @@ int sbi_send(int port, int off, int op, u32 *data)
return ret; return ret;
} }
#else #else
int sbi_send(int port, int off, int op, u32 *data) static int sbi_send(int port, int off, int op, u32 *data)
{ {
return -EUNATCH; return -EUNATCH;
} }
...@@ -174,8 +174,9 @@ static int apl_rd_reg(int port, int off, int op, void *data, size_t sz, char *na ...@@ -174,8 +174,9 @@ static int apl_rd_reg(int port, int off, int op, void *data, size_t sz, char *na
switch (sz) { switch (sz) {
case 8: case 8:
ret = sbi_send(port, off + 4, op, (u32 *)(data + 4)); ret = sbi_send(port, off + 4, op, (u32 *)(data + 4));
/* fall through */
case 4: case 4:
ret = sbi_send(port, off, op, (u32 *)data); ret |= sbi_send(port, off, op, (u32 *)data);
pnd2_printk(KERN_DEBUG, "%s=%x%08x ret=%d\n", name, pnd2_printk(KERN_DEBUG, "%s=%x%08x ret=%d\n", name,
sz == 8 ? *((u32 *)(data + 4)) : 0, *((u32 *)data), ret); sz == 8 ? *((u32 *)(data + 4)) : 0, *((u32 *)data), ret);
break; break;
...@@ -423,16 +424,21 @@ static void dnv_mk_region(char *name, struct region *rp, void *asym) ...@@ -423,16 +424,21 @@ static void dnv_mk_region(char *name, struct region *rp, void *asym)
static int apl_get_registers(void) static int apl_get_registers(void)
{ {
int ret = -ENODEV;
int i; int i;
if (RD_REG(&asym_2way, b_cr_asym_2way_mem_region_mchbar)) if (RD_REG(&asym_2way, b_cr_asym_2way_mem_region_mchbar))
return -ENODEV; return -ENODEV;
/*
* RD_REGP() will fail for unpopulated or non-existent
* DIMM slots. Return success if we find at least one DIMM.
*/
for (i = 0; i < APL_NUM_CHANNELS; i++) for (i = 0; i < APL_NUM_CHANNELS; i++)
if (RD_REGP(&drp0[i], d_cr_drp0, apl_dports[i])) if (!RD_REGP(&drp0[i], d_cr_drp0, apl_dports[i]))
return -ENODEV; ret = 0;
return 0; return ret;
} }
static int dnv_get_registers(void) static int dnv_get_registers(void)
......
...@@ -35,7 +35,7 @@ static LIST_HEAD(sbridge_edac_list); ...@@ -35,7 +35,7 @@ static LIST_HEAD(sbridge_edac_list);
/* /*
* Alter this version for the module when modifications are made * Alter this version for the module when modifications are made
*/ */
#define SBRIDGE_REVISION " Ver: 1.1.1 " #define SBRIDGE_REVISION " Ver: 1.1.2 "
#define EDAC_MOD_STR "sbridge_edac" #define EDAC_MOD_STR "sbridge_edac"
/* /*
...@@ -279,7 +279,7 @@ static const u32 correrrthrsld[] = { ...@@ -279,7 +279,7 @@ static const u32 correrrthrsld[] = {
* sbridge structs * sbridge structs
*/ */
#define NUM_CHANNELS 8 /* 2MC per socket, four chan per MC */ #define NUM_CHANNELS 4 /* Max channels per MC */
#define MAX_DIMMS 3 /* Max DIMMS per channel */ #define MAX_DIMMS 3 /* Max DIMMS per channel */
#define KNL_MAX_CHAS 38 /* KNL max num. of Cache Home Agents */ #define KNL_MAX_CHAS 38 /* KNL max num. of Cache Home Agents */
#define KNL_MAX_CHANNELS 6 /* KNL max num. of PCI channels */ #define KNL_MAX_CHANNELS 6 /* KNL max num. of PCI channels */
...@@ -294,6 +294,12 @@ enum type { ...@@ -294,6 +294,12 @@ enum type {
KNIGHTS_LANDING, KNIGHTS_LANDING,
}; };
enum domain {
IMC0 = 0,
IMC1,
SOCK,
};
struct sbridge_pvt; struct sbridge_pvt;
struct sbridge_info { struct sbridge_info {
enum type type; enum type type;
...@@ -324,11 +330,14 @@ struct sbridge_channel { ...@@ -324,11 +330,14 @@ struct sbridge_channel {
struct pci_id_descr { struct pci_id_descr {
int dev_id; int dev_id;
int optional; int optional;
enum domain dom;
}; };
struct pci_id_table { struct pci_id_table {
const struct pci_id_descr *descr; const struct pci_id_descr *descr;
int n_devs; int n_devs_per_imc;
int n_devs_per_sock;
int n_imcs_per_sock;
enum type type; enum type type;
}; };
...@@ -337,7 +346,9 @@ struct sbridge_dev { ...@@ -337,7 +346,9 @@ struct sbridge_dev {
u8 bus, mc; u8 bus, mc;
u8 node_id, source_id; u8 node_id, source_id;
struct pci_dev **pdev; struct pci_dev **pdev;
enum domain dom;
int n_devs; int n_devs;
int i_devs;
struct mem_ctl_info *mci; struct mem_ctl_info *mci;
}; };
...@@ -352,11 +363,12 @@ struct knl_pvt { ...@@ -352,11 +363,12 @@ struct knl_pvt {
}; };
struct sbridge_pvt { struct sbridge_pvt {
struct pci_dev *pci_ta, *pci_ddrio, *pci_ras; /* Devices per socket */
struct pci_dev *pci_ddrio;
struct pci_dev *pci_sad0, *pci_sad1; struct pci_dev *pci_sad0, *pci_sad1;
struct pci_dev *pci_ha0, *pci_ha1;
struct pci_dev *pci_br0, *pci_br1; struct pci_dev *pci_br0, *pci_br1;
struct pci_dev *pci_ha1_ta; /* Devices per memory controller */
struct pci_dev *pci_ha, *pci_ta, *pci_ras;
struct pci_dev *pci_tad[NUM_CHANNELS]; struct pci_dev *pci_tad[NUM_CHANNELS];
struct sbridge_dev *sbridge_dev; struct sbridge_dev *sbridge_dev;
...@@ -373,39 +385,42 @@ struct sbridge_pvt { ...@@ -373,39 +385,42 @@ struct sbridge_pvt {
struct knl_pvt knl; struct knl_pvt knl;
}; };
#define PCI_DESCR(device_id, opt) \ #define PCI_DESCR(device_id, opt, domain) \
.dev_id = (device_id), \ .dev_id = (device_id), \
.optional = opt .optional = opt, \
.dom = domain
static const struct pci_id_descr pci_dev_descr_sbridge[] = { static const struct pci_id_descr pci_dev_descr_sbridge[] = {
/* Processor Home Agent */ /* Processor Home Agent */
{ PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_HA0, 0) }, { PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_HA0, 0, IMC0) },
/* Memory controller */ /* Memory controller */
{ PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TA, 0) }, { PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TA, 0, IMC0) },
{ PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_RAS, 0) }, { PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_RAS, 0, IMC0) },
{ PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD0, 0) }, { PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD0, 0, IMC0) },
{ PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD1, 0) }, { PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD1, 0, IMC0) },
{ PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD2, 0) }, { PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD2, 0, IMC0) },
{ PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD3, 0) }, { PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD3, 0, IMC0) },
{ PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_DDRIO, 1) }, { PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_DDRIO, 1, SOCK) },
/* System Address Decoder */ /* System Address Decoder */
{ PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_SAD0, 0) }, { PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_SAD0, 0, SOCK) },
{ PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_SAD1, 0) }, { PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_SAD1, 0, SOCK) },
/* Broadcast Registers */ /* Broadcast Registers */
{ PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_BR, 0) }, { PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_BR, 0, SOCK) },
}; };
#define PCI_ID_TABLE_ENTRY(A, T) { \ #define PCI_ID_TABLE_ENTRY(A, N, M, T) { \
.descr = A, \ .descr = A, \
.n_devs = ARRAY_SIZE(A), \ .n_devs_per_imc = N, \
.n_devs_per_sock = ARRAY_SIZE(A), \
.n_imcs_per_sock = M, \
.type = T \ .type = T \
} }
static const struct pci_id_table pci_dev_descr_sbridge_table[] = { static const struct pci_id_table pci_dev_descr_sbridge_table[] = {
PCI_ID_TABLE_ENTRY(pci_dev_descr_sbridge, SANDY_BRIDGE), PCI_ID_TABLE_ENTRY(pci_dev_descr_sbridge, ARRAY_SIZE(pci_dev_descr_sbridge), 1, SANDY_BRIDGE),
{0,} /* 0 terminated list. */ {0,} /* 0 terminated list. */
}; };
...@@ -439,40 +454,39 @@ static const struct pci_id_table pci_dev_descr_sbridge_table[] = { ...@@ -439,40 +454,39 @@ static const struct pci_id_table pci_dev_descr_sbridge_table[] = {
static const struct pci_id_descr pci_dev_descr_ibridge[] = { static const struct pci_id_descr pci_dev_descr_ibridge[] = {
/* Processor Home Agent */ /* Processor Home Agent */
{ PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0, 0) }, { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0, 0, IMC0) },
/* Memory controller */ /* Memory controller */
{ PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TA, 0) }, { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TA, 0, IMC0) },
{ PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_RAS, 0) }, { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_RAS, 0, IMC0) },
{ PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD0, 0) }, { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD0, 0, IMC0) },
{ PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD1, 0) }, { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD1, 0, IMC0) },
{ PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD2, 0) }, { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD2, 0, IMC0) },
{ PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD3, 0) }, { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD3, 0, IMC0) },
/* Optional, mode 2HA */
{ PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1, 1, IMC1) },
{ PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TA, 1, IMC1) },
{ PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_RAS, 1, IMC1) },
{ PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD0, 1, IMC1) },
{ PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD1, 1, IMC1) },
{ PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD2, 1, IMC1) },
{ PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD3, 1, IMC1) },
{ PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_1HA_DDRIO0, 1, SOCK) },
{ PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_2HA_DDRIO0, 1, SOCK) },
/* System Address Decoder */ /* System Address Decoder */
{ PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_SAD, 0) }, { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_SAD, 0, SOCK) },
/* Broadcast Registers */ /* Broadcast Registers */
{ PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_BR0, 1) }, { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_BR0, 1, SOCK) },
{ PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_BR1, 0) }, { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_BR1, 0, SOCK) },
/* Optional, mode 2HA */
{ PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1, 1) },
#if 0
{ PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TA, 1) },
{ PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_RAS, 1) },
#endif
{ PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD0, 1) },
{ PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD1, 1) },
{ PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD2, 1) },
{ PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD3, 1) },
{ PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_1HA_DDRIO0, 1) },
{ PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_2HA_DDRIO0, 1) },
}; };
static const struct pci_id_table pci_dev_descr_ibridge_table[] = { static const struct pci_id_table pci_dev_descr_ibridge_table[] = {
PCI_ID_TABLE_ENTRY(pci_dev_descr_ibridge, IVY_BRIDGE), PCI_ID_TABLE_ENTRY(pci_dev_descr_ibridge, 12, 2, IVY_BRIDGE),
{0,} /* 0 terminated list. */ {0,} /* 0 terminated list. */
}; };
...@@ -498,9 +512,9 @@ static const struct pci_id_table pci_dev_descr_ibridge_table[] = { ...@@ -498,9 +512,9 @@ static const struct pci_id_table pci_dev_descr_ibridge_table[] = {
#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0 0x2fa0 #define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0 0x2fa0
#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1 0x2f60 #define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1 0x2f60
#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TA 0x2fa8 #define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TA 0x2fa8
#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_THERMAL 0x2f71 #define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TM 0x2f71
#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TA 0x2f68 #define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TA 0x2f68
#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_THERMAL 0x2f79 #define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TM 0x2f79
#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_CBO_SAD0 0x2ffc #define PCI_DEVICE_ID_INTEL_HASWELL_IMC_CBO_SAD0 0x2ffc
#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_CBO_SAD1 0x2ffd #define PCI_DEVICE_ID_INTEL_HASWELL_IMC_CBO_SAD1 0x2ffd
#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD0 0x2faa #define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD0 0x2faa
...@@ -517,35 +531,33 @@ static const struct pci_id_table pci_dev_descr_ibridge_table[] = { ...@@ -517,35 +531,33 @@ static const struct pci_id_table pci_dev_descr_ibridge_table[] = {
#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_DDRIO3 0x2fbb #define PCI_DEVICE_ID_INTEL_HASWELL_IMC_DDRIO3 0x2fbb
static const struct pci_id_descr pci_dev_descr_haswell[] = { static const struct pci_id_descr pci_dev_descr_haswell[] = {
/* first item must be the HA */ /* first item must be the HA */
{ PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0, 0) }, { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0, 0, IMC0) },
{ PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1, 1, IMC1) },
{ PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_CBO_SAD0, 0) },
{ PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_CBO_SAD1, 0) }, { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TA, 0, IMC0) },
{ PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TM, 0, IMC0) },
{ PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1, 1) }, { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD0, 0, IMC0) },
{ PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD1, 0, IMC0) },
{ PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TA, 0) }, { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD2, 1, IMC0) },
{ PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_THERMAL, 0) }, { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD3, 1, IMC0) },
{ PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD0, 0) },
{ PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD1, 0) }, { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TA, 1, IMC1) },
{ PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD2, 1) }, { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TM, 1, IMC1) },
{ PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD3, 1) }, { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD0, 1, IMC1) },
{ PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD1, 1, IMC1) },
{ PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_DDRIO0, 1) }, { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD2, 1, IMC1) },
{ PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_DDRIO1, 1) }, { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD3, 1, IMC1) },
{ PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_DDRIO2, 1) },
{ PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_DDRIO3, 1) }, { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_CBO_SAD0, 0, SOCK) },
{ PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_CBO_SAD1, 0, SOCK) },
{ PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TA, 1) }, { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_DDRIO0, 1, SOCK) },
{ PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_THERMAL, 1) }, { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_DDRIO1, 1, SOCK) },
{ PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD0, 1) }, { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_DDRIO2, 1, SOCK) },
{ PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD1, 1) }, { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_DDRIO3, 1, SOCK) },
{ PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD2, 1) },
{ PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD3, 1) },
}; };
static const struct pci_id_table pci_dev_descr_haswell_table[] = { static const struct pci_id_table pci_dev_descr_haswell_table[] = {
PCI_ID_TABLE_ENTRY(pci_dev_descr_haswell, HASWELL), PCI_ID_TABLE_ENTRY(pci_dev_descr_haswell, 13, 2, HASWELL),
{0,} /* 0 terminated list. */ {0,} /* 0 terminated list. */
}; };
...@@ -559,7 +571,7 @@ static const struct pci_id_table pci_dev_descr_haswell_table[] = { ...@@ -559,7 +571,7 @@ static const struct pci_id_table pci_dev_descr_haswell_table[] = {
/* Memory controller, TAD tables, error injection - 2-8-0, 2-9-0 (2 of these) */ /* Memory controller, TAD tables, error injection - 2-8-0, 2-9-0 (2 of these) */
#define PCI_DEVICE_ID_INTEL_KNL_IMC_MC 0x7840 #define PCI_DEVICE_ID_INTEL_KNL_IMC_MC 0x7840
/* DRAM channel stuff; bank addrs, dimmmtr, etc.. 2-8-2 - 2-9-4 (6 of these) */ /* DRAM channel stuff; bank addrs, dimmmtr, etc.. 2-8-2 - 2-9-4 (6 of these) */
#define PCI_DEVICE_ID_INTEL_KNL_IMC_CHANNEL 0x7843 #define PCI_DEVICE_ID_INTEL_KNL_IMC_CHAN 0x7843
/* kdrwdbu TAD limits/offsets, MCMTR - 2-10-1, 2-11-1 (2 of these) */ /* kdrwdbu TAD limits/offsets, MCMTR - 2-10-1, 2-11-1 (2 of these) */
#define PCI_DEVICE_ID_INTEL_KNL_IMC_TA 0x7844 #define PCI_DEVICE_ID_INTEL_KNL_IMC_TA 0x7844
/* CHA broadcast registers, dram rules - 1-29-0 (1 of these) */ /* CHA broadcast registers, dram rules - 1-29-0 (1 of these) */
...@@ -579,17 +591,17 @@ static const struct pci_id_table pci_dev_descr_haswell_table[] = { ...@@ -579,17 +591,17 @@ static const struct pci_id_table pci_dev_descr_haswell_table[] = {
*/ */
static const struct pci_id_descr pci_dev_descr_knl[] = { static const struct pci_id_descr pci_dev_descr_knl[] = {
[0] = { PCI_DESCR(PCI_DEVICE_ID_INTEL_KNL_IMC_SAD0, 0) }, [0 ... 1] = { PCI_DESCR(PCI_DEVICE_ID_INTEL_KNL_IMC_MC, 0, IMC0)},
[1] = { PCI_DESCR(PCI_DEVICE_ID_INTEL_KNL_IMC_SAD1, 0) }, [2 ... 7] = { PCI_DESCR(PCI_DEVICE_ID_INTEL_KNL_IMC_CHAN, 0, IMC0) },
[2 ... 3] = { PCI_DESCR(PCI_DEVICE_ID_INTEL_KNL_IMC_MC, 0)}, [8] = { PCI_DESCR(PCI_DEVICE_ID_INTEL_KNL_IMC_TA, 0, IMC0) },
[4 ... 41] = { PCI_DESCR(PCI_DEVICE_ID_INTEL_KNL_IMC_CHA, 0) }, [9] = { PCI_DESCR(PCI_DEVICE_ID_INTEL_KNL_IMC_TOLHM, 0, IMC0) },
[42 ... 47] = { PCI_DESCR(PCI_DEVICE_ID_INTEL_KNL_IMC_CHANNEL, 0) }, [10] = { PCI_DESCR(PCI_DEVICE_ID_INTEL_KNL_IMC_SAD0, 0, SOCK) },
[48] = { PCI_DESCR(PCI_DEVICE_ID_INTEL_KNL_IMC_TA, 0) }, [11] = { PCI_DESCR(PCI_DEVICE_ID_INTEL_KNL_IMC_SAD1, 0, SOCK) },
[49] = { PCI_DESCR(PCI_DEVICE_ID_INTEL_KNL_IMC_TOLHM, 0) }, [12 ... 49] = { PCI_DESCR(PCI_DEVICE_ID_INTEL_KNL_IMC_CHA, 0, SOCK) },
}; };
static const struct pci_id_table pci_dev_descr_knl_table[] = { static const struct pci_id_table pci_dev_descr_knl_table[] = {
PCI_ID_TABLE_ENTRY(pci_dev_descr_knl, KNIGHTS_LANDING), PCI_ID_TABLE_ENTRY(pci_dev_descr_knl, ARRAY_SIZE(pci_dev_descr_knl), 1, KNIGHTS_LANDING),
{0,} {0,}
}; };
...@@ -615,9 +627,9 @@ static const struct pci_id_table pci_dev_descr_knl_table[] = { ...@@ -615,9 +627,9 @@ static const struct pci_id_table pci_dev_descr_knl_table[] = {
#define PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0 0x6fa0 #define PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0 0x6fa0
#define PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1 0x6f60 #define PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1 0x6f60
#define PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TA 0x6fa8 #define PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TA 0x6fa8
#define PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_THERMAL 0x6f71 #define PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TM 0x6f71
#define PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_TA 0x6f68 #define PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_TA 0x6f68
#define PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_THERMAL 0x6f79 #define PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_TM 0x6f79
#define PCI_DEVICE_ID_INTEL_BROADWELL_IMC_CBO_SAD0 0x6ffc #define PCI_DEVICE_ID_INTEL_BROADWELL_IMC_CBO_SAD0 0x6ffc
#define PCI_DEVICE_ID_INTEL_BROADWELL_IMC_CBO_SAD1 0x6ffd #define PCI_DEVICE_ID_INTEL_BROADWELL_IMC_CBO_SAD1 0x6ffd
#define PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TAD0 0x6faa #define PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TAD0 0x6faa
...@@ -632,32 +644,30 @@ static const struct pci_id_table pci_dev_descr_knl_table[] = { ...@@ -632,32 +644,30 @@ static const struct pci_id_table pci_dev_descr_knl_table[] = {
static const struct pci_id_descr pci_dev_descr_broadwell[] = { static const struct pci_id_descr pci_dev_descr_broadwell[] = {
/* first item must be the HA */ /* first item must be the HA */
{ PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0, 0) }, { PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0, 0, IMC0) },
{ PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1, 1, IMC1) },
{ PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_CBO_SAD0, 0) },
{ PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_CBO_SAD1, 0) }, { PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TA, 0, IMC0) },
{ PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TM, 0, IMC0) },
{ PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1, 1) }, { PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TAD0, 0, IMC0) },
{ PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TAD1, 0, IMC0) },
{ PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TA, 0) }, { PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TAD2, 1, IMC0) },
{ PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_THERMAL, 0) }, { PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TAD3, 1, IMC0) },
{ PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TAD0, 0) },
{ PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TAD1, 0) }, { PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_TA, 1, IMC1) },
{ PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TAD2, 1) }, { PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_TM, 1, IMC1) },
{ PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TAD3, 1) }, { PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_TAD0, 1, IMC1) },
{ PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_TAD1, 1, IMC1) },
{ PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_DDRIO0, 1) }, { PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_TAD2, 1, IMC1) },
{ PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_TAD3, 1, IMC1) },
{ PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_TA, 1) },
{ PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_THERMAL, 1) }, { PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_CBO_SAD0, 0, SOCK) },
{ PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_TAD0, 1) }, { PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_CBO_SAD1, 0, SOCK) },
{ PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_TAD1, 1) }, { PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_DDRIO0, 1, SOCK) },
{ PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_TAD2, 1) },
{ PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_TAD3, 1) },
}; };
static const struct pci_id_table pci_dev_descr_broadwell_table[] = { static const struct pci_id_table pci_dev_descr_broadwell_table[] = {
PCI_ID_TABLE_ENTRY(pci_dev_descr_broadwell, BROADWELL), PCI_ID_TABLE_ENTRY(pci_dev_descr_broadwell, 10, 2, BROADWELL),
{0,} /* 0 terminated list. */ {0,} /* 0 terminated list. */
}; };
...@@ -709,7 +719,8 @@ static inline int numcol(u32 mtr) ...@@ -709,7 +719,8 @@ static inline int numcol(u32 mtr)
return 1 << cols; return 1 << cols;
} }
static struct sbridge_dev *get_sbridge_dev(u8 bus, int multi_bus) static struct sbridge_dev *get_sbridge_dev(u8 bus, enum domain dom, int multi_bus,
struct sbridge_dev *prev)
{ {
struct sbridge_dev *sbridge_dev; struct sbridge_dev *sbridge_dev;
...@@ -722,15 +733,18 @@ static struct sbridge_dev *get_sbridge_dev(u8 bus, int multi_bus) ...@@ -722,15 +733,18 @@ static struct sbridge_dev *get_sbridge_dev(u8 bus, int multi_bus)
struct sbridge_dev, list); struct sbridge_dev, list);
} }
list_for_each_entry(sbridge_dev, &sbridge_edac_list, list) { sbridge_dev = list_entry(prev ? prev->list.next
if (sbridge_dev->bus == bus) : sbridge_edac_list.next, struct sbridge_dev, list);
list_for_each_entry_from(sbridge_dev, &sbridge_edac_list, list) {
if (sbridge_dev->bus == bus && (dom == SOCK || dom == sbridge_dev->dom))
return sbridge_dev; return sbridge_dev;
} }
return NULL; return NULL;
} }
static struct sbridge_dev *alloc_sbridge_dev(u8 bus, static struct sbridge_dev *alloc_sbridge_dev(u8 bus, enum domain dom,
const struct pci_id_table *table) const struct pci_id_table *table)
{ {
struct sbridge_dev *sbridge_dev; struct sbridge_dev *sbridge_dev;
...@@ -739,7 +753,8 @@ static struct sbridge_dev *alloc_sbridge_dev(u8 bus, ...@@ -739,7 +753,8 @@ static struct sbridge_dev *alloc_sbridge_dev(u8 bus,
if (!sbridge_dev) if (!sbridge_dev)
return NULL; return NULL;
sbridge_dev->pdev = kzalloc(sizeof(*sbridge_dev->pdev) * table->n_devs, sbridge_dev->pdev = kcalloc(table->n_devs_per_imc,
sizeof(*sbridge_dev->pdev),
GFP_KERNEL); GFP_KERNEL);
if (!sbridge_dev->pdev) { if (!sbridge_dev->pdev) {
kfree(sbridge_dev); kfree(sbridge_dev);
...@@ -747,7 +762,8 @@ static struct sbridge_dev *alloc_sbridge_dev(u8 bus, ...@@ -747,7 +762,8 @@ static struct sbridge_dev *alloc_sbridge_dev(u8 bus,
} }
sbridge_dev->bus = bus; sbridge_dev->bus = bus;
sbridge_dev->n_devs = table->n_devs; sbridge_dev->dom = dom;
sbridge_dev->n_devs = table->n_devs_per_imc;
list_add_tail(&sbridge_dev->list, &sbridge_edac_list); list_add_tail(&sbridge_dev->list, &sbridge_edac_list);
return sbridge_dev; return sbridge_dev;
...@@ -1044,79 +1060,6 @@ static int haswell_chan_hash(int idx, u64 addr) ...@@ -1044,79 +1060,6 @@ static int haswell_chan_hash(int idx, u64 addr)
return idx; return idx;
} }
/****************************************************************************
Memory check routines
****************************************************************************/
static struct pci_dev *get_pdev_same_bus(u8 bus, u32 id)
{
struct pci_dev *pdev = NULL;
do {
pdev = pci_get_device(PCI_VENDOR_ID_INTEL, id, pdev);
if (pdev && pdev->bus->number == bus)
break;
} while (pdev);
return pdev;
}
/**
* check_if_ecc_is_active() - Checks if ECC is active
* @bus: Device bus
* @type: Memory controller type
* returns: 0 in case ECC is active, -ENODEV if it can't be determined or
* disabled
*/
static int check_if_ecc_is_active(const u8 bus, enum type type)
{
struct pci_dev *pdev = NULL;
u32 mcmtr, id;
switch (type) {
case IVY_BRIDGE:
id = PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TA;
break;
case HASWELL:
id = PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TA;
break;
case SANDY_BRIDGE:
id = PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TA;
break;
case BROADWELL:
id = PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TA;
break;
case KNIGHTS_LANDING:
/*
* KNL doesn't group things by bus the same way
* SB/IB/Haswell does.
*/
id = PCI_DEVICE_ID_INTEL_KNL_IMC_TA;
break;
default:
return -ENODEV;
}
if (type != KNIGHTS_LANDING)
pdev = get_pdev_same_bus(bus, id);
else
pdev = pci_get_device(PCI_VENDOR_ID_INTEL, id, 0);
if (!pdev) {
sbridge_printk(KERN_ERR, "Couldn't find PCI device "
"%04x:%04x! on bus %02d\n",
PCI_VENDOR_ID_INTEL, id, bus);
return -ENODEV;
}
pci_read_config_dword(pdev,
type == KNIGHTS_LANDING ? KNL_MCMTR : MCMTR, &mcmtr);
if (!IS_ECC_ENABLED(mcmtr)) {
sbridge_printk(KERN_ERR, "ECC is disabled. Aborting\n");
return -ENODEV;
}
return 0;
}
/* Low bits of TAD limit, and some metadata. */ /* Low bits of TAD limit, and some metadata. */
static const u32 knl_tad_dram_limit_lo[] = { static const u32 knl_tad_dram_limit_lo[] = {
0x400, 0x500, 0x600, 0x700, 0x400, 0x500, 0x600, 0x700,
...@@ -1587,23 +1530,11 @@ static int knl_get_dimm_capacity(struct sbridge_pvt *pvt, u64 *mc_sizes) ...@@ -1587,23 +1530,11 @@ static int knl_get_dimm_capacity(struct sbridge_pvt *pvt, u64 *mc_sizes)
return 0; return 0;
} }
static int get_dimm_config(struct mem_ctl_info *mci) static void get_source_id(struct mem_ctl_info *mci)
{ {
struct sbridge_pvt *pvt = mci->pvt_info; struct sbridge_pvt *pvt = mci->pvt_info;
struct dimm_info *dimm;
unsigned i, j, banks, ranks, rows, cols, npages;
u64 size;
u32 reg; u32 reg;
enum edac_type mode;
enum mem_type mtype;
int channels = pvt->info.type == KNIGHTS_LANDING ?
KNL_MAX_CHANNELS : NUM_CHANNELS;
u64 knl_mc_sizes[KNL_MAX_CHANNELS];
if (pvt->info.type == HASWELL || pvt->info.type == BROADWELL) {
pci_read_config_dword(pvt->pci_ha0, HASWELL_HASYSDEFEATURE2, &reg);
pvt->is_chan_hash = GET_BITFIELD(reg, 21, 21);
}
if (pvt->info.type == HASWELL || pvt->info.type == BROADWELL || if (pvt->info.type == HASWELL || pvt->info.type == BROADWELL ||
pvt->info.type == KNIGHTS_LANDING) pvt->info.type == KNIGHTS_LANDING)
pci_read_config_dword(pvt->pci_sad1, SAD_TARGET, &reg); pci_read_config_dword(pvt->pci_sad1, SAD_TARGET, &reg);
...@@ -1614,50 +1545,19 @@ static int get_dimm_config(struct mem_ctl_info *mci) ...@@ -1614,50 +1545,19 @@ static int get_dimm_config(struct mem_ctl_info *mci)
pvt->sbridge_dev->source_id = SOURCE_ID_KNL(reg); pvt->sbridge_dev->source_id = SOURCE_ID_KNL(reg);
else else
pvt->sbridge_dev->source_id = SOURCE_ID(reg); pvt->sbridge_dev->source_id = SOURCE_ID(reg);
}
pvt->sbridge_dev->node_id = pvt->info.get_node_id(pvt); static int __populate_dimms(struct mem_ctl_info *mci,
edac_dbg(0, "mc#%d: Node ID: %d, source ID: %d\n", u64 knl_mc_sizes[KNL_MAX_CHANNELS],
pvt->sbridge_dev->mc, enum edac_type mode)
pvt->sbridge_dev->node_id, {
pvt->sbridge_dev->source_id); struct sbridge_pvt *pvt = mci->pvt_info;
int channels = pvt->info.type == KNIGHTS_LANDING ? KNL_MAX_CHANNELS
/* KNL doesn't support mirroring or lockstep, : NUM_CHANNELS;
* and is always closed page unsigned int i, j, banks, ranks, rows, cols, npages;
*/ struct dimm_info *dimm;
if (pvt->info.type == KNIGHTS_LANDING) { enum mem_type mtype;
mode = EDAC_S4ECD4ED; u64 size;
pvt->is_mirrored = false;
if (knl_get_dimm_capacity(pvt, knl_mc_sizes) != 0)
return -1;
} else {
pci_read_config_dword(pvt->pci_ras, RASENABLES, &reg);
if (IS_MIRROR_ENABLED(reg)) {
edac_dbg(0, "Memory mirror is enabled\n");
pvt->is_mirrored = true;
} else {
edac_dbg(0, "Memory mirror is disabled\n");
pvt->is_mirrored = false;
}
pci_read_config_dword(pvt->pci_ta, MCMTR, &pvt->info.mcmtr);
if (IS_LOCKSTEP_ENABLED(pvt->info.mcmtr)) {
edac_dbg(0, "Lockstep is enabled\n");
mode = EDAC_S8ECD8ED;
pvt->is_lockstep = true;
} else {
edac_dbg(0, "Lockstep is disabled\n");
mode = EDAC_S4ECD4ED;
pvt->is_lockstep = false;
}
if (IS_CLOSE_PG(pvt->info.mcmtr)) {
edac_dbg(0, "address map is on closed page mode\n");
pvt->is_close_pg = true;
} else {
edac_dbg(0, "address map is on open page mode\n");
pvt->is_close_pg = false;
}
}
mtype = pvt->info.get_memory_type(pvt); mtype = pvt->info.get_memory_type(pvt);
if (mtype == MEM_RDDR3 || mtype == MEM_RDDR4) if (mtype == MEM_RDDR3 || mtype == MEM_RDDR4)
...@@ -1688,8 +1588,7 @@ static int get_dimm_config(struct mem_ctl_info *mci) ...@@ -1688,8 +1588,7 @@ static int get_dimm_config(struct mem_ctl_info *mci)
} }
for (j = 0; j < max_dimms_per_channel; j++) { for (j = 0; j < max_dimms_per_channel; j++) {
dimm = EDAC_DIMM_PTR(mci->layers, mci->dimms, mci->n_layers, dimm = EDAC_DIMM_PTR(mci->layers, mci->dimms, mci->n_layers, i, j, 0);
i, j, 0);
if (pvt->info.type == KNIGHTS_LANDING) { if (pvt->info.type == KNIGHTS_LANDING) {
pci_read_config_dword(pvt->knl.pci_channel[i], pci_read_config_dword(pvt->knl.pci_channel[i],
knl_mtr_reg, &mtr); knl_mtr_reg, &mtr);
...@@ -1699,6 +1598,12 @@ static int get_dimm_config(struct mem_ctl_info *mci) ...@@ -1699,6 +1598,12 @@ static int get_dimm_config(struct mem_ctl_info *mci)
} }
edac_dbg(4, "Channel #%d MTR%d = %x\n", i, j, mtr); edac_dbg(4, "Channel #%d MTR%d = %x\n", i, j, mtr);
if (IS_DIMM_PRESENT(mtr)) { if (IS_DIMM_PRESENT(mtr)) {
if (!IS_ECC_ENABLED(pvt->info.mcmtr)) {
sbridge_printk(KERN_ERR, "CPU SrcID #%d, Ha #%d, Channel #%d has DIMMs, but ECC is disabled\n",
pvt->sbridge_dev->source_id,
pvt->sbridge_dev->dom, i);
return -ENODEV;
}
pvt->channel[i].dimms++; pvt->channel[i].dimms++;
ranks = numrank(pvt->info.type, mtr); ranks = numrank(pvt->info.type, mtr);
...@@ -1717,7 +1622,7 @@ static int get_dimm_config(struct mem_ctl_info *mci) ...@@ -1717,7 +1622,7 @@ static int get_dimm_config(struct mem_ctl_info *mci)
npages = MiB_TO_PAGES(size); npages = MiB_TO_PAGES(size);
edac_dbg(0, "mc#%d: ha %d channel %d, dimm %d, %lld Mb (%d pages) bank: %d, rank: %d, row: %#x, col: %#x\n", edac_dbg(0, "mc#%d: ha %d channel %d, dimm %d, %lld Mb (%d pages) bank: %d, rank: %d, row: %#x, col: %#x\n",
pvt->sbridge_dev->mc, i/4, i%4, j, pvt->sbridge_dev->mc, pvt->sbridge_dev->dom, i, j,
size, npages, size, npages,
banks, ranks, rows, cols); banks, ranks, rows, cols);
...@@ -1728,7 +1633,7 @@ static int get_dimm_config(struct mem_ctl_info *mci) ...@@ -1728,7 +1633,7 @@ static int get_dimm_config(struct mem_ctl_info *mci)
dimm->edac_mode = mode; dimm->edac_mode = mode;
snprintf(dimm->label, sizeof(dimm->label), snprintf(dimm->label, sizeof(dimm->label),
"CPU_SrcID#%u_Ha#%u_Chan#%u_DIMM#%u", "CPU_SrcID#%u_Ha#%u_Chan#%u_DIMM#%u",
pvt->sbridge_dev->source_id, i/4, i%4, j); pvt->sbridge_dev->source_id, pvt->sbridge_dev->dom, i, j);
} }
} }
} }
...@@ -1736,6 +1641,65 @@ static int get_dimm_config(struct mem_ctl_info *mci) ...@@ -1736,6 +1641,65 @@ static int get_dimm_config(struct mem_ctl_info *mci)
return 0; return 0;
} }
static int get_dimm_config(struct mem_ctl_info *mci)
{
struct sbridge_pvt *pvt = mci->pvt_info;
u64 knl_mc_sizes[KNL_MAX_CHANNELS];
enum edac_type mode;
u32 reg;
if (pvt->info.type == HASWELL || pvt->info.type == BROADWELL) {
pci_read_config_dword(pvt->pci_ha, HASWELL_HASYSDEFEATURE2, &reg);
pvt->is_chan_hash = GET_BITFIELD(reg, 21, 21);
}
pvt->sbridge_dev->node_id = pvt->info.get_node_id(pvt);
edac_dbg(0, "mc#%d: Node ID: %d, source ID: %d\n",
pvt->sbridge_dev->mc,
pvt->sbridge_dev->node_id,
pvt->sbridge_dev->source_id);
/* KNL doesn't support mirroring or lockstep,
* and is always closed page
*/
if (pvt->info.type == KNIGHTS_LANDING) {
mode = EDAC_S4ECD4ED;
pvt->is_mirrored = false;
if (knl_get_dimm_capacity(pvt, knl_mc_sizes) != 0)
return -1;
pci_read_config_dword(pvt->pci_ta, KNL_MCMTR, &pvt->info.mcmtr);
} else {
pci_read_config_dword(pvt->pci_ras, RASENABLES, &reg);
if (IS_MIRROR_ENABLED(reg)) {
edac_dbg(0, "Memory mirror is enabled\n");
pvt->is_mirrored = true;
} else {
edac_dbg(0, "Memory mirror is disabled\n");
pvt->is_mirrored = false;
}
pci_read_config_dword(pvt->pci_ta, MCMTR, &pvt->info.mcmtr);
if (IS_LOCKSTEP_ENABLED(pvt->info.mcmtr)) {
edac_dbg(0, "Lockstep is enabled\n");
mode = EDAC_S8ECD8ED;
pvt->is_lockstep = true;
} else {
edac_dbg(0, "Lockstep is disabled\n");
mode = EDAC_S4ECD4ED;
pvt->is_lockstep = false;
}
if (IS_CLOSE_PG(pvt->info.mcmtr)) {
edac_dbg(0, "address map is on closed page mode\n");
pvt->is_close_pg = true;
} else {
edac_dbg(0, "address map is on open page mode\n");
pvt->is_close_pg = false;
}
}
return __populate_dimms(mci, knl_mc_sizes, mode);
}
static void get_memory_layout(const struct mem_ctl_info *mci) static void get_memory_layout(const struct mem_ctl_info *mci)
{ {
struct sbridge_pvt *pvt = mci->pvt_info; struct sbridge_pvt *pvt = mci->pvt_info;
...@@ -1816,8 +1780,7 @@ static void get_memory_layout(const struct mem_ctl_info *mci) ...@@ -1816,8 +1780,7 @@ static void get_memory_layout(const struct mem_ctl_info *mci)
*/ */
prv = 0; prv = 0;
for (n_tads = 0; n_tads < MAX_TAD; n_tads++) { for (n_tads = 0; n_tads < MAX_TAD; n_tads++) {
pci_read_config_dword(pvt->pci_ha0, tad_dram_rule[n_tads], pci_read_config_dword(pvt->pci_ha, tad_dram_rule[n_tads], &reg);
&reg);
limit = TAD_LIMIT(reg); limit = TAD_LIMIT(reg);
if (limit <= prv) if (limit <= prv)
break; break;
...@@ -1899,12 +1862,12 @@ static void get_memory_layout(const struct mem_ctl_info *mci) ...@@ -1899,12 +1862,12 @@ static void get_memory_layout(const struct mem_ctl_info *mci)
} }
} }
static struct mem_ctl_info *get_mci_for_node_id(u8 node_id) static struct mem_ctl_info *get_mci_for_node_id(u8 node_id, u8 ha)
{ {
struct sbridge_dev *sbridge_dev; struct sbridge_dev *sbridge_dev;
list_for_each_entry(sbridge_dev, &sbridge_edac_list, list) { list_for_each_entry(sbridge_dev, &sbridge_edac_list, list) {
if (sbridge_dev->node_id == node_id) if (sbridge_dev->node_id == node_id && sbridge_dev->dom == ha)
return sbridge_dev->mci; return sbridge_dev->mci;
} }
return NULL; return NULL;
...@@ -1925,7 +1888,7 @@ static int get_memory_error_data(struct mem_ctl_info *mci, ...@@ -1925,7 +1888,7 @@ static int get_memory_error_data(struct mem_ctl_info *mci,
int interleave_mode, shiftup = 0; int interleave_mode, shiftup = 0;
unsigned sad_interleave[pvt->info.max_interleave]; unsigned sad_interleave[pvt->info.max_interleave];
u32 reg, dram_rule; u32 reg, dram_rule;
u8 ch_way, sck_way, pkg, sad_ha = 0, ch_add = 0; u8 ch_way, sck_way, pkg, sad_ha = 0;
u32 tad_offset; u32 tad_offset;
u32 rir_way; u32 rir_way;
u32 mb, gb; u32 mb, gb;
...@@ -2038,13 +2001,10 @@ static int get_memory_error_data(struct mem_ctl_info *mci, ...@@ -2038,13 +2001,10 @@ static int get_memory_error_data(struct mem_ctl_info *mci,
pkg = sad_pkg(pvt->info.interleave_pkg, reg, idx); pkg = sad_pkg(pvt->info.interleave_pkg, reg, idx);
*socket = sad_pkg_socket(pkg); *socket = sad_pkg_socket(pkg);
sad_ha = sad_pkg_ha(pkg); sad_ha = sad_pkg_ha(pkg);
if (sad_ha)
ch_add = 4;
if (a7mode) { if (a7mode) {
/* MCChanShiftUpEnable */ /* MCChanShiftUpEnable */
pci_read_config_dword(pvt->pci_ha0, pci_read_config_dword(pvt->pci_ha, HASWELL_HASYSDEFEATURE2, &reg);
HASWELL_HASYSDEFEATURE2, &reg);
shiftup = GET_BITFIELD(reg, 22, 22); shiftup = GET_BITFIELD(reg, 22, 22);
} }
...@@ -2056,8 +2016,6 @@ static int get_memory_error_data(struct mem_ctl_info *mci, ...@@ -2056,8 +2016,6 @@ static int get_memory_error_data(struct mem_ctl_info *mci,
pkg = sad_pkg(pvt->info.interleave_pkg, reg, idx); pkg = sad_pkg(pvt->info.interleave_pkg, reg, idx);
*socket = sad_pkg_socket(pkg); *socket = sad_pkg_socket(pkg);
sad_ha = sad_pkg_ha(pkg); sad_ha = sad_pkg_ha(pkg);
if (sad_ha)
ch_add = 4;
edac_dbg(0, "SAD interleave package: %d = CPU socket %d, HA %d\n", edac_dbg(0, "SAD interleave package: %d = CPU socket %d, HA %d\n",
idx, *socket, sad_ha); idx, *socket, sad_ha);
} }
...@@ -2068,7 +2026,7 @@ static int get_memory_error_data(struct mem_ctl_info *mci, ...@@ -2068,7 +2026,7 @@ static int get_memory_error_data(struct mem_ctl_info *mci,
* Move to the proper node structure, in order to access the * Move to the proper node structure, in order to access the
* right PCI registers * right PCI registers
*/ */
new_mci = get_mci_for_node_id(*socket); new_mci = get_mci_for_node_id(*socket, sad_ha);
if (!new_mci) { if (!new_mci) {
sprintf(msg, "Struct for socket #%u wasn't initialized", sprintf(msg, "Struct for socket #%u wasn't initialized",
*socket); *socket);
...@@ -2081,14 +2039,7 @@ static int get_memory_error_data(struct mem_ctl_info *mci, ...@@ -2081,14 +2039,7 @@ static int get_memory_error_data(struct mem_ctl_info *mci,
* Step 2) Get memory channel * Step 2) Get memory channel
*/ */
prv = 0; prv = 0;
if (pvt->info.type == SANDY_BRIDGE) pci_ha = pvt->pci_ha;
pci_ha = pvt->pci_ha0;
else {
if (sad_ha)
pci_ha = pvt->pci_ha1;
else
pci_ha = pvt->pci_ha0;
}
for (n_tads = 0; n_tads < MAX_TAD; n_tads++) { for (n_tads = 0; n_tads < MAX_TAD; n_tads++) {
pci_read_config_dword(pci_ha, tad_dram_rule[n_tads], &reg); pci_read_config_dword(pci_ha, tad_dram_rule[n_tads], &reg);
limit = TAD_LIMIT(reg); limit = TAD_LIMIT(reg);
...@@ -2139,9 +2090,7 @@ static int get_memory_error_data(struct mem_ctl_info *mci, ...@@ -2139,9 +2090,7 @@ static int get_memory_error_data(struct mem_ctl_info *mci,
} }
*channel_mask = 1 << base_ch; *channel_mask = 1 << base_ch;
pci_read_config_dword(pvt->pci_tad[ch_add + base_ch], pci_read_config_dword(pvt->pci_tad[base_ch], tad_ch_nilv_offset[n_tads], &tad_offset);
tad_ch_nilv_offset[n_tads],
&tad_offset);
if (pvt->is_mirrored) { if (pvt->is_mirrored) {
*channel_mask |= 1 << ((base_ch + 2) % 4); *channel_mask |= 1 << ((base_ch + 2) % 4);
...@@ -2192,9 +2141,7 @@ static int get_memory_error_data(struct mem_ctl_info *mci, ...@@ -2192,9 +2141,7 @@ static int get_memory_error_data(struct mem_ctl_info *mci,
* Step 3) Decode rank * Step 3) Decode rank
*/ */
for (n_rir = 0; n_rir < MAX_RIR_RANGES; n_rir++) { for (n_rir = 0; n_rir < MAX_RIR_RANGES; n_rir++) {
pci_read_config_dword(pvt->pci_tad[ch_add + base_ch], pci_read_config_dword(pvt->pci_tad[base_ch], rir_way_limit[n_rir], &reg);
rir_way_limit[n_rir],
&reg);
if (!IS_RIR_VALID(reg)) if (!IS_RIR_VALID(reg))
continue; continue;
...@@ -2222,9 +2169,7 @@ static int get_memory_error_data(struct mem_ctl_info *mci, ...@@ -2222,9 +2169,7 @@ static int get_memory_error_data(struct mem_ctl_info *mci,
idx = (ch_addr >> 13); /* FIXME: Datasheet says to shift by 15 */ idx = (ch_addr >> 13); /* FIXME: Datasheet says to shift by 15 */
idx %= 1 << rir_way; idx %= 1 << rir_way;
pci_read_config_dword(pvt->pci_tad[ch_add + base_ch], pci_read_config_dword(pvt->pci_tad[base_ch], rir_offset[n_rir][idx], &reg);
rir_offset[n_rir][idx],
&reg);
*rank = RIR_RNK_TGT(pvt->info.type, reg); *rank = RIR_RNK_TGT(pvt->info.type, reg);
edac_dbg(0, "RIR#%d: channel address 0x%08Lx < 0x%08Lx, RIR interleave %d, index %d\n", edac_dbg(0, "RIR#%d: channel address 0x%08Lx < 0x%08Lx, RIR interleave %d, index %d\n",
...@@ -2277,10 +2222,11 @@ static int sbridge_get_onedevice(struct pci_dev **prev, ...@@ -2277,10 +2222,11 @@ static int sbridge_get_onedevice(struct pci_dev **prev,
const unsigned devno, const unsigned devno,
const int multi_bus) const int multi_bus)
{ {
struct sbridge_dev *sbridge_dev; struct sbridge_dev *sbridge_dev = NULL;
const struct pci_id_descr *dev_descr = &table->descr[devno]; const struct pci_id_descr *dev_descr = &table->descr[devno];
struct pci_dev *pdev = NULL; struct pci_dev *pdev = NULL;
u8 bus = 0; u8 bus = 0;
int i = 0;
sbridge_printk(KERN_DEBUG, sbridge_printk(KERN_DEBUG,
"Seeking for: PCI ID %04x:%04x\n", "Seeking for: PCI ID %04x:%04x\n",
...@@ -2311,9 +2257,14 @@ static int sbridge_get_onedevice(struct pci_dev **prev, ...@@ -2311,9 +2257,14 @@ static int sbridge_get_onedevice(struct pci_dev **prev,
} }
bus = pdev->bus->number; bus = pdev->bus->number;
sbridge_dev = get_sbridge_dev(bus, multi_bus); next_imc:
sbridge_dev = get_sbridge_dev(bus, dev_descr->dom, multi_bus, sbridge_dev);
if (!sbridge_dev) { if (!sbridge_dev) {
sbridge_dev = alloc_sbridge_dev(bus, table);
if (dev_descr->dom == SOCK)
goto out_imc;
sbridge_dev = alloc_sbridge_dev(bus, dev_descr->dom, table);
if (!sbridge_dev) { if (!sbridge_dev) {
pci_dev_put(pdev); pci_dev_put(pdev);
return -ENOMEM; return -ENOMEM;
...@@ -2321,7 +2272,7 @@ static int sbridge_get_onedevice(struct pci_dev **prev, ...@@ -2321,7 +2272,7 @@ static int sbridge_get_onedevice(struct pci_dev **prev,
(*num_mc)++; (*num_mc)++;
} }
if (sbridge_dev->pdev[devno]) { if (sbridge_dev->pdev[sbridge_dev->i_devs]) {
sbridge_printk(KERN_ERR, sbridge_printk(KERN_ERR,
"Duplicated device for %04x:%04x\n", "Duplicated device for %04x:%04x\n",
PCI_VENDOR_ID_INTEL, dev_descr->dev_id); PCI_VENDOR_ID_INTEL, dev_descr->dev_id);
...@@ -2329,8 +2280,16 @@ static int sbridge_get_onedevice(struct pci_dev **prev, ...@@ -2329,8 +2280,16 @@ static int sbridge_get_onedevice(struct pci_dev **prev,
return -ENODEV; return -ENODEV;
} }
sbridge_dev->pdev[devno] = pdev; sbridge_dev->pdev[sbridge_dev->i_devs++] = pdev;
/* pdev belongs to more than one IMC, do extra gets */
if (++i > 1)
pci_dev_get(pdev);
if (dev_descr->dom == SOCK && i < table->n_imcs_per_sock)
goto next_imc;
out_imc:
/* Be sure that the device is enabled */ /* Be sure that the device is enabled */
if (unlikely(pci_enable_device(pdev) < 0)) { if (unlikely(pci_enable_device(pdev) < 0)) {
sbridge_printk(KERN_ERR, sbridge_printk(KERN_ERR,
...@@ -2374,7 +2333,7 @@ static int sbridge_get_all_devices(u8 *num_mc, ...@@ -2374,7 +2333,7 @@ static int sbridge_get_all_devices(u8 *num_mc,
if (table->type == KNIGHTS_LANDING) if (table->type == KNIGHTS_LANDING)
allow_dups = multi_bus = 1; allow_dups = multi_bus = 1;
while (table && table->descr) { while (table && table->descr) {
for (i = 0; i < table->n_devs; i++) { for (i = 0; i < table->n_devs_per_sock; i++) {
if (!allow_dups || i == 0 || if (!allow_dups || i == 0 ||
table->descr[i].dev_id != table->descr[i].dev_id !=
table->descr[i-1].dev_id) { table->descr[i-1].dev_id) {
...@@ -2385,7 +2344,7 @@ static int sbridge_get_all_devices(u8 *num_mc, ...@@ -2385,7 +2344,7 @@ static int sbridge_get_all_devices(u8 *num_mc,
table, i, multi_bus); table, i, multi_bus);
if (rc < 0) { if (rc < 0) {
if (i == 0) { if (i == 0) {
i = table->n_devs; i = table->n_devs_per_sock;
break; break;
} }
sbridge_put_all_devices(); sbridge_put_all_devices();
...@@ -2399,6 +2358,13 @@ static int sbridge_get_all_devices(u8 *num_mc, ...@@ -2399,6 +2358,13 @@ static int sbridge_get_all_devices(u8 *num_mc,
return 0; return 0;
} }
/*
* Device IDs for {SBRIDGE,IBRIDGE,HASWELL,BROADWELL}_IMC_HA0_TAD0 are in
* the format: XXXa. So we can convert from a device to the corresponding
* channel like this
*/
#define TAD_DEV_TO_CHAN(dev) (((dev) & 0xf) - 0xa)
static int sbridge_mci_bind_devs(struct mem_ctl_info *mci, static int sbridge_mci_bind_devs(struct mem_ctl_info *mci,
struct sbridge_dev *sbridge_dev) struct sbridge_dev *sbridge_dev)
{ {
...@@ -2423,7 +2389,7 @@ static int sbridge_mci_bind_devs(struct mem_ctl_info *mci, ...@@ -2423,7 +2389,7 @@ static int sbridge_mci_bind_devs(struct mem_ctl_info *mci,
pvt->pci_br0 = pdev; pvt->pci_br0 = pdev;
break; break;
case PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_HA0: case PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_HA0:
pvt->pci_ha0 = pdev; pvt->pci_ha = pdev;
break; break;
case PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TA: case PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TA:
pvt->pci_ta = pdev; pvt->pci_ta = pdev;
...@@ -2436,7 +2402,7 @@ static int sbridge_mci_bind_devs(struct mem_ctl_info *mci, ...@@ -2436,7 +2402,7 @@ static int sbridge_mci_bind_devs(struct mem_ctl_info *mci,
case PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD2: case PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD2:
case PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD3: case PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD3:
{ {
int id = pdev->device - PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD0; int id = TAD_DEV_TO_CHAN(pdev->device);
pvt->pci_tad[id] = pdev; pvt->pci_tad[id] = pdev;
saw_chan_mask |= 1 << id; saw_chan_mask |= 1 << id;
} }
...@@ -2455,7 +2421,7 @@ static int sbridge_mci_bind_devs(struct mem_ctl_info *mci, ...@@ -2455,7 +2421,7 @@ static int sbridge_mci_bind_devs(struct mem_ctl_info *mci,
} }
/* Check if everything were registered */ /* Check if everything were registered */
if (!pvt->pci_sad0 || !pvt->pci_sad1 || !pvt->pci_ha0 || if (!pvt->pci_sad0 || !pvt->pci_sad1 || !pvt->pci_ha ||
!pvt->pci_ras || !pvt->pci_ta) !pvt->pci_ras || !pvt->pci_ta)
goto enodev; goto enodev;
...@@ -2488,19 +2454,26 @@ static int ibridge_mci_bind_devs(struct mem_ctl_info *mci, ...@@ -2488,19 +2454,26 @@ static int ibridge_mci_bind_devs(struct mem_ctl_info *mci,
switch (pdev->device) { switch (pdev->device) {
case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0: case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0:
pvt->pci_ha0 = pdev; case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1:
pvt->pci_ha = pdev;
break; break;
case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TA: case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TA:
case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TA:
pvt->pci_ta = pdev; pvt->pci_ta = pdev;
case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_RAS: case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_RAS:
case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_RAS:
pvt->pci_ras = pdev; pvt->pci_ras = pdev;
break; break;
case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD0: case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD0:
case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD1: case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD1:
case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD2: case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD2:
case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD3: case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD3:
case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD0:
case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD1:
case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD2:
case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD3:
{ {
int id = pdev->device - PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD0; int id = TAD_DEV_TO_CHAN(pdev->device);
pvt->pci_tad[id] = pdev; pvt->pci_tad[id] = pdev;
saw_chan_mask |= 1 << id; saw_chan_mask |= 1 << id;
} }
...@@ -2520,19 +2493,6 @@ static int ibridge_mci_bind_devs(struct mem_ctl_info *mci, ...@@ -2520,19 +2493,6 @@ static int ibridge_mci_bind_devs(struct mem_ctl_info *mci,
case PCI_DEVICE_ID_INTEL_IBRIDGE_BR1: case PCI_DEVICE_ID_INTEL_IBRIDGE_BR1:
pvt->pci_br1 = pdev; pvt->pci_br1 = pdev;
break; break;
case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1:
pvt->pci_ha1 = pdev;
break;
case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD0:
case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD1:
case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD2:
case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD3:
{
int id = pdev->device - PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD0 + 4;
pvt->pci_tad[id] = pdev;
saw_chan_mask |= 1 << id;
}
break;
default: default:
goto error; goto error;
} }
...@@ -2544,13 +2504,12 @@ static int ibridge_mci_bind_devs(struct mem_ctl_info *mci, ...@@ -2544,13 +2504,12 @@ static int ibridge_mci_bind_devs(struct mem_ctl_info *mci,
} }
/* Check if everything were registered */ /* Check if everything were registered */
if (!pvt->pci_sad0 || !pvt->pci_ha0 || !pvt->pci_br0 || if (!pvt->pci_sad0 || !pvt->pci_ha || !pvt->pci_br0 ||
!pvt->pci_br1 || !pvt->pci_ras || !pvt->pci_ta) !pvt->pci_br1 || !pvt->pci_ras || !pvt->pci_ta)
goto enodev; goto enodev;
if (saw_chan_mask != 0x0f && /* -EN */ if (saw_chan_mask != 0x0f && /* -EN/-EX */
saw_chan_mask != 0x33 && /* -EP */ saw_chan_mask != 0x03) /* -EP */
saw_chan_mask != 0xff) /* -EX */
goto enodev; goto enodev;
return 0; return 0;
...@@ -2593,32 +2552,27 @@ static int haswell_mci_bind_devs(struct mem_ctl_info *mci, ...@@ -2593,32 +2552,27 @@ static int haswell_mci_bind_devs(struct mem_ctl_info *mci,
pvt->pci_sad1 = pdev; pvt->pci_sad1 = pdev;
break; break;
case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0: case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0:
pvt->pci_ha0 = pdev; case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1:
pvt->pci_ha = pdev;
break; break;
case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TA: case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TA:
case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TA:
pvt->pci_ta = pdev; pvt->pci_ta = pdev;
break; break;
case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_THERMAL: case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TM:
case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TM:
pvt->pci_ras = pdev; pvt->pci_ras = pdev;
break; break;
case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD0: case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD0:
case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD1: case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD1:
case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD2: case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD2:
case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD3: case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD3:
{
int id = pdev->device - PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD0;
pvt->pci_tad[id] = pdev;
saw_chan_mask |= 1 << id;
}
break;
case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD0: case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD0:
case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD1: case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD1:
case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD2: case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD2:
case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD3: case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD3:
{ {
int id = pdev->device - PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD0 + 4; int id = TAD_DEV_TO_CHAN(pdev->device);
pvt->pci_tad[id] = pdev; pvt->pci_tad[id] = pdev;
saw_chan_mask |= 1 << id; saw_chan_mask |= 1 << id;
} }
...@@ -2630,12 +2584,6 @@ static int haswell_mci_bind_devs(struct mem_ctl_info *mci, ...@@ -2630,12 +2584,6 @@ static int haswell_mci_bind_devs(struct mem_ctl_info *mci,
if (!pvt->pci_ddrio) if (!pvt->pci_ddrio)
pvt->pci_ddrio = pdev; pvt->pci_ddrio = pdev;
break; break;
case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1:
pvt->pci_ha1 = pdev;
break;
case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TA:
pvt->pci_ha1_ta = pdev;
break;
default: default:
break; break;
} }
...@@ -2647,13 +2595,12 @@ static int haswell_mci_bind_devs(struct mem_ctl_info *mci, ...@@ -2647,13 +2595,12 @@ static int haswell_mci_bind_devs(struct mem_ctl_info *mci,
} }
/* Check if everything were registered */ /* Check if everything were registered */
if (!pvt->pci_sad0 || !pvt->pci_ha0 || !pvt->pci_sad1 || if (!pvt->pci_sad0 || !pvt->pci_ha || !pvt->pci_sad1 ||
!pvt->pci_ras || !pvt->pci_ta || !pvt->info.pci_vtd) !pvt->pci_ras || !pvt->pci_ta || !pvt->info.pci_vtd)
goto enodev; goto enodev;
if (saw_chan_mask != 0x0f && /* -EN */ if (saw_chan_mask != 0x0f && /* -EN/-EX */
saw_chan_mask != 0x33 && /* -EP */ saw_chan_mask != 0x03) /* -EP */
saw_chan_mask != 0xff) /* -EX */
goto enodev; goto enodev;
return 0; return 0;
...@@ -2690,30 +2637,27 @@ static int broadwell_mci_bind_devs(struct mem_ctl_info *mci, ...@@ -2690,30 +2637,27 @@ static int broadwell_mci_bind_devs(struct mem_ctl_info *mci,
pvt->pci_sad1 = pdev; pvt->pci_sad1 = pdev;
break; break;
case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0: case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0:
pvt->pci_ha0 = pdev; case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1:
pvt->pci_ha = pdev;
break; break;
case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TA: case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TA:
case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_TA:
pvt->pci_ta = pdev; pvt->pci_ta = pdev;
break; break;
case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_THERMAL: case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TM:
case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_TM:
pvt->pci_ras = pdev; pvt->pci_ras = pdev;
break; break;
case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TAD0: case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TAD0:
case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TAD1: case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TAD1:
case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TAD2: case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TAD2:
case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TAD3: case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TAD3:
{
int id = pdev->device - PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TAD0;
pvt->pci_tad[id] = pdev;
saw_chan_mask |= 1 << id;
}
break;
case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_TAD0: case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_TAD0:
case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_TAD1: case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_TAD1:
case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_TAD2: case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_TAD2:
case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_TAD3: case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_TAD3:
{ {
int id = pdev->device - PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_TAD0 + 4; int id = TAD_DEV_TO_CHAN(pdev->device);
pvt->pci_tad[id] = pdev; pvt->pci_tad[id] = pdev;
saw_chan_mask |= 1 << id; saw_chan_mask |= 1 << id;
} }
...@@ -2721,12 +2665,6 @@ static int broadwell_mci_bind_devs(struct mem_ctl_info *mci, ...@@ -2721,12 +2665,6 @@ static int broadwell_mci_bind_devs(struct mem_ctl_info *mci,
case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_DDRIO0: case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_DDRIO0:
pvt->pci_ddrio = pdev; pvt->pci_ddrio = pdev;
break; break;
case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1:
pvt->pci_ha1 = pdev;
break;
case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_TA:
pvt->pci_ha1_ta = pdev;
break;
default: default:
break; break;
} }
...@@ -2738,13 +2676,12 @@ static int broadwell_mci_bind_devs(struct mem_ctl_info *mci, ...@@ -2738,13 +2676,12 @@ static int broadwell_mci_bind_devs(struct mem_ctl_info *mci,
} }
/* Check if everything were registered */ /* Check if everything were registered */
if (!pvt->pci_sad0 || !pvt->pci_ha0 || !pvt->pci_sad1 || if (!pvt->pci_sad0 || !pvt->pci_ha || !pvt->pci_sad1 ||
!pvt->pci_ras || !pvt->pci_ta || !pvt->info.pci_vtd) !pvt->pci_ras || !pvt->pci_ta || !pvt->info.pci_vtd)
goto enodev; goto enodev;
if (saw_chan_mask != 0x0f && /* -EN */ if (saw_chan_mask != 0x0f && /* -EN/-EX */
saw_chan_mask != 0x33 && /* -EP */ saw_chan_mask != 0x03) /* -EP */
saw_chan_mask != 0xff) /* -EX */
goto enodev; goto enodev;
return 0; return 0;
...@@ -2812,7 +2749,7 @@ static int knl_mci_bind_devs(struct mem_ctl_info *mci, ...@@ -2812,7 +2749,7 @@ static int knl_mci_bind_devs(struct mem_ctl_info *mci,
pvt->knl.pci_cha[devidx] = pdev; pvt->knl.pci_cha[devidx] = pdev;
break; break;
case PCI_DEVICE_ID_INTEL_KNL_IMC_CHANNEL: case PCI_DEVICE_ID_INTEL_KNL_IMC_CHAN:
devidx = -1; devidx = -1;
/* /*
...@@ -3006,7 +2943,7 @@ static void sbridge_mce_output_error(struct mem_ctl_info *mci, ...@@ -3006,7 +2943,7 @@ static void sbridge_mce_output_error(struct mem_ctl_info *mci,
if (rc < 0) if (rc < 0)
goto err_parsing; goto err_parsing;
new_mci = get_mci_for_node_id(socket); new_mci = get_mci_for_node_id(socket, ha);
if (!new_mci) { if (!new_mci) {
strcpy(msg, "Error: socket got corrupted!"); strcpy(msg, "Error: socket got corrupted!");
goto err_parsing; goto err_parsing;
...@@ -3053,7 +2990,7 @@ static void sbridge_mce_output_error(struct mem_ctl_info *mci, ...@@ -3053,7 +2990,7 @@ static void sbridge_mce_output_error(struct mem_ctl_info *mci,
/* Call the helper to output message */ /* Call the helper to output message */
edac_mc_handle_error(tp_event, mci, core_err_cnt, edac_mc_handle_error(tp_event, mci, core_err_cnt,
m->addr >> PAGE_SHIFT, m->addr & ~PAGE_MASK, 0, m->addr >> PAGE_SHIFT, m->addr & ~PAGE_MASK, 0,
4*ha+channel, dimm, -1, channel, dimm, -1,
optype, msg); optype, msg);
return; return;
err_parsing: err_parsing:
...@@ -3078,7 +3015,7 @@ static int sbridge_mce_check_error(struct notifier_block *nb, unsigned long val, ...@@ -3078,7 +3015,7 @@ static int sbridge_mce_check_error(struct notifier_block *nb, unsigned long val,
if (edac_get_report_status() == EDAC_REPORTING_DISABLED) if (edac_get_report_status() == EDAC_REPORTING_DISABLED)
return NOTIFY_DONE; return NOTIFY_DONE;
mci = get_mci_for_node_id(mce->socketid); mci = get_mci_for_node_id(mce->socketid, IMC0);
if (!mci) if (!mci)
return NOTIFY_DONE; return NOTIFY_DONE;
pvt = mci->pvt_info; pvt = mci->pvt_info;
...@@ -3159,11 +3096,6 @@ static int sbridge_register_mci(struct sbridge_dev *sbridge_dev, enum type type) ...@@ -3159,11 +3096,6 @@ static int sbridge_register_mci(struct sbridge_dev *sbridge_dev, enum type type)
struct pci_dev *pdev = sbridge_dev->pdev[0]; struct pci_dev *pdev = sbridge_dev->pdev[0];
int rc; int rc;
/* Check the number of active and not disabled channels */
rc = check_if_ecc_is_active(sbridge_dev->bus, type);
if (unlikely(rc < 0))
return rc;
/* allocate a new MC control structure */ /* allocate a new MC control structure */
layers[0].type = EDAC_MC_LAYER_CHANNEL; layers[0].type = EDAC_MC_LAYER_CHANNEL;
layers[0].size = type == KNIGHTS_LANDING ? layers[0].size = type == KNIGHTS_LANDING ?
...@@ -3192,7 +3124,7 @@ static int sbridge_register_mci(struct sbridge_dev *sbridge_dev, enum type type) ...@@ -3192,7 +3124,7 @@ static int sbridge_register_mci(struct sbridge_dev *sbridge_dev, enum type type)
MEM_FLAG_DDR4 : MEM_FLAG_DDR3; MEM_FLAG_DDR4 : MEM_FLAG_DDR3;
mci->edac_ctl_cap = EDAC_FLAG_NONE; mci->edac_ctl_cap = EDAC_FLAG_NONE;
mci->edac_cap = EDAC_FLAG_NONE; mci->edac_cap = EDAC_FLAG_NONE;
mci->mod_name = "sbridge_edac.c"; mci->mod_name = "sb_edac.c";
mci->mod_ver = SBRIDGE_REVISION; mci->mod_ver = SBRIDGE_REVISION;
mci->dev_name = pci_name(pdev); mci->dev_name = pci_name(pdev);
mci->ctl_page_to_phys = NULL; mci->ctl_page_to_phys = NULL;
...@@ -3215,12 +3147,14 @@ static int sbridge_register_mci(struct sbridge_dev *sbridge_dev, enum type type) ...@@ -3215,12 +3147,14 @@ static int sbridge_register_mci(struct sbridge_dev *sbridge_dev, enum type type)
pvt->info.max_interleave = ARRAY_SIZE(ibridge_interleave_list); pvt->info.max_interleave = ARRAY_SIZE(ibridge_interleave_list);
pvt->info.interleave_pkg = ibridge_interleave_pkg; pvt->info.interleave_pkg = ibridge_interleave_pkg;
pvt->info.get_width = ibridge_get_width; pvt->info.get_width = ibridge_get_width;
mci->ctl_name = kasprintf(GFP_KERNEL, "Ivy Bridge Socket#%d", mci->mc_idx);
/* Store pci devices at mci for faster access */ /* Store pci devices at mci for faster access */
rc = ibridge_mci_bind_devs(mci, sbridge_dev); rc = ibridge_mci_bind_devs(mci, sbridge_dev);
if (unlikely(rc < 0)) if (unlikely(rc < 0))
goto fail0; goto fail0;
get_source_id(mci);
mci->ctl_name = kasprintf(GFP_KERNEL, "Ivy Bridge SrcID#%d_Ha#%d",
pvt->sbridge_dev->source_id, pvt->sbridge_dev->dom);
break; break;
case SANDY_BRIDGE: case SANDY_BRIDGE:
pvt->info.rankcfgr = SB_RANK_CFG_A; pvt->info.rankcfgr = SB_RANK_CFG_A;
...@@ -3238,12 +3172,14 @@ static int sbridge_register_mci(struct sbridge_dev *sbridge_dev, enum type type) ...@@ -3238,12 +3172,14 @@ static int sbridge_register_mci(struct sbridge_dev *sbridge_dev, enum type type)
pvt->info.max_interleave = ARRAY_SIZE(sbridge_interleave_list); pvt->info.max_interleave = ARRAY_SIZE(sbridge_interleave_list);
pvt->info.interleave_pkg = sbridge_interleave_pkg; pvt->info.interleave_pkg = sbridge_interleave_pkg;
pvt->info.get_width = sbridge_get_width; pvt->info.get_width = sbridge_get_width;
mci->ctl_name = kasprintf(GFP_KERNEL, "Sandy Bridge Socket#%d", mci->mc_idx);
/* Store pci devices at mci for faster access */ /* Store pci devices at mci for faster access */
rc = sbridge_mci_bind_devs(mci, sbridge_dev); rc = sbridge_mci_bind_devs(mci, sbridge_dev);
if (unlikely(rc < 0)) if (unlikely(rc < 0))
goto fail0; goto fail0;
get_source_id(mci);
mci->ctl_name = kasprintf(GFP_KERNEL, "Sandy Bridge SrcID#%d_Ha#%d",
pvt->sbridge_dev->source_id, pvt->sbridge_dev->dom);
break; break;
case HASWELL: case HASWELL:
/* rankcfgr isn't used */ /* rankcfgr isn't used */
...@@ -3261,12 +3197,14 @@ static int sbridge_register_mci(struct sbridge_dev *sbridge_dev, enum type type) ...@@ -3261,12 +3197,14 @@ static int sbridge_register_mci(struct sbridge_dev *sbridge_dev, enum type type)
pvt->info.max_interleave = ARRAY_SIZE(ibridge_interleave_list); pvt->info.max_interleave = ARRAY_SIZE(ibridge_interleave_list);
pvt->info.interleave_pkg = ibridge_interleave_pkg; pvt->info.interleave_pkg = ibridge_interleave_pkg;
pvt->info.get_width = ibridge_get_width; pvt->info.get_width = ibridge_get_width;
mci->ctl_name = kasprintf(GFP_KERNEL, "Haswell Socket#%d", mci->mc_idx);
/* Store pci devices at mci for faster access */ /* Store pci devices at mci for faster access */
rc = haswell_mci_bind_devs(mci, sbridge_dev); rc = haswell_mci_bind_devs(mci, sbridge_dev);
if (unlikely(rc < 0)) if (unlikely(rc < 0))
goto fail0; goto fail0;
get_source_id(mci);
mci->ctl_name = kasprintf(GFP_KERNEL, "Haswell SrcID#%d_Ha#%d",
pvt->sbridge_dev->source_id, pvt->sbridge_dev->dom);
break; break;
case BROADWELL: case BROADWELL:
/* rankcfgr isn't used */ /* rankcfgr isn't used */
...@@ -3284,12 +3222,14 @@ static int sbridge_register_mci(struct sbridge_dev *sbridge_dev, enum type type) ...@@ -3284,12 +3222,14 @@ static int sbridge_register_mci(struct sbridge_dev *sbridge_dev, enum type type)
pvt->info.max_interleave = ARRAY_SIZE(ibridge_interleave_list); pvt->info.max_interleave = ARRAY_SIZE(ibridge_interleave_list);
pvt->info.interleave_pkg = ibridge_interleave_pkg; pvt->info.interleave_pkg = ibridge_interleave_pkg;
pvt->info.get_width = broadwell_get_width; pvt->info.get_width = broadwell_get_width;
mci->ctl_name = kasprintf(GFP_KERNEL, "Broadwell Socket#%d", mci->mc_idx);
/* Store pci devices at mci for faster access */ /* Store pci devices at mci for faster access */
rc = broadwell_mci_bind_devs(mci, sbridge_dev); rc = broadwell_mci_bind_devs(mci, sbridge_dev);
if (unlikely(rc < 0)) if (unlikely(rc < 0))
goto fail0; goto fail0;
get_source_id(mci);
mci->ctl_name = kasprintf(GFP_KERNEL, "Broadwell SrcID#%d_Ha#%d",
pvt->sbridge_dev->source_id, pvt->sbridge_dev->dom);
break; break;
case KNIGHTS_LANDING: case KNIGHTS_LANDING:
/* pvt->info.rankcfgr == ??? */ /* pvt->info.rankcfgr == ??? */
...@@ -3307,17 +3247,22 @@ static int sbridge_register_mci(struct sbridge_dev *sbridge_dev, enum type type) ...@@ -3307,17 +3247,22 @@ static int sbridge_register_mci(struct sbridge_dev *sbridge_dev, enum type type)
pvt->info.max_interleave = ARRAY_SIZE(knl_interleave_list); pvt->info.max_interleave = ARRAY_SIZE(knl_interleave_list);
pvt->info.interleave_pkg = ibridge_interleave_pkg; pvt->info.interleave_pkg = ibridge_interleave_pkg;
pvt->info.get_width = knl_get_width; pvt->info.get_width = knl_get_width;
mci->ctl_name = kasprintf(GFP_KERNEL,
"Knights Landing Socket#%d", mci->mc_idx);
rc = knl_mci_bind_devs(mci, sbridge_dev); rc = knl_mci_bind_devs(mci, sbridge_dev);
if (unlikely(rc < 0)) if (unlikely(rc < 0))
goto fail0; goto fail0;
get_source_id(mci);
mci->ctl_name = kasprintf(GFP_KERNEL, "Knights Landing SrcID#%d_Ha#%d",
pvt->sbridge_dev->source_id, pvt->sbridge_dev->dom);
break; break;
} }
/* Get dimm basic config and the memory layout */ /* Get dimm basic config and the memory layout */
get_dimm_config(mci); rc = get_dimm_config(mci);
if (rc < 0) {
edac_dbg(0, "MC: failed to get_dimm_config()\n");
goto fail;
}
get_memory_layout(mci); get_memory_layout(mci);
/* record ptr to the generic device */ /* record ptr to the generic device */
...@@ -3327,13 +3272,14 @@ static int sbridge_register_mci(struct sbridge_dev *sbridge_dev, enum type type) ...@@ -3327,13 +3272,14 @@ static int sbridge_register_mci(struct sbridge_dev *sbridge_dev, enum type type)
if (unlikely(edac_mc_add_mc(mci))) { if (unlikely(edac_mc_add_mc(mci))) {
edac_dbg(0, "MC: failed edac_mc_add_mc()\n"); edac_dbg(0, "MC: failed edac_mc_add_mc()\n");
rc = -EINVAL; rc = -EINVAL;
goto fail0; goto fail;
} }
return 0; return 0;
fail0: fail:
kfree(mci->ctl_name); kfree(mci->ctl_name);
fail0:
edac_mc_free(mci); edac_mc_free(mci);
sbridge_dev->mci = NULL; sbridge_dev->mci = NULL;
return rc; return rc;
......
...@@ -2080,7 +2080,7 @@ static int thunderx_l2c_probe(struct pci_dev *pdev, ...@@ -2080,7 +2080,7 @@ static int thunderx_l2c_probe(struct pci_dev *pdev,
if (IS_ENABLED(CONFIG_EDAC_DEBUG)) { if (IS_ENABLED(CONFIG_EDAC_DEBUG)) {
l2c->debugfs = edac_debugfs_create_dir(pdev->dev.kobj.name); l2c->debugfs = edac_debugfs_create_dir(pdev->dev.kobj.name);
thunderx_create_debugfs_nodes(l2c->debugfs, l2c_devattr, ret = thunderx_create_debugfs_nodes(l2c->debugfs, l2c_devattr,
l2c, dfs_entries); l2c, dfs_entries);
if (ret != dfs_entries) { if (ret != dfs_entries) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment