summaryrefslogtreecommitdiff
path: root/drivers/edac
diff options
context:
space:
mode:
authorScott Wood <scottwood@freescale.com>2014-04-08 01:00:49 (GMT)
committerScott Wood <scottwood@freescale.com>2014-04-08 19:58:35 (GMT)
commit47d2261a3fa71cde24263559a4219a25e50d8c89 (patch)
tree28774d5b330ccf1b777a3af222d8356918328013 /drivers/edac
parentfb7f27080adc65cd5f341bdf56a1d0c14f316c1b (diff)
parent5fb9d37f27351e42f002e372074249f92cbdf815 (diff)
downloadlinux-fsl-qoriq-47d2261a3fa71cde24263559a4219a25e50d8c89.tar.xz
Merge branch 'merge' into sdk-v1.6.x
This reverts v3.13-rc3+ (78fd82238d0e5716) to v3.12, except for commits which I noticed which appear relevant to the SDK. Signed-off-by: Scott Wood <scottwood@freescale.com> Conflicts: arch/powerpc/include/asm/kvm_host.h arch/powerpc/kvm/book3s_hv_rmhandlers.S arch/powerpc/kvm/book3s_interrupts.S arch/powerpc/kvm/e500.c arch/powerpc/kvm/e500mc.c arch/powerpc/sysdev/fsl_soc.h drivers/Kconfig drivers/cpufreq/ppc-corenet-cpufreq.c drivers/dma/fsldma.c drivers/dma/s3c24xx-dma.c drivers/misc/Makefile drivers/mmc/host/sdhci-of-esdhc.c drivers/mtd/devices/m25p80.c drivers/net/ethernet/freescale/gianfar.h drivers/platform/Kconfig drivers/platform/Makefile drivers/spi/spi-fsl-espi.c include/crypto/algapi.h include/linux/netdev_features.h include/linux/skbuff.h include/net/ip.h net/core/ethtool.c
Diffstat (limited to 'drivers/edac')
-rw-r--r--drivers/edac/amd64_edac.c46
-rw-r--r--drivers/edac/amd64_edac.h8
-rw-r--r--drivers/edac/cell_edac.c2
-rw-r--r--drivers/edac/edac_device.c9
-rw-r--r--drivers/edac/edac_mc.c6
-rw-r--r--drivers/edac/edac_pci.c8
-rw-r--r--drivers/edac/ghes_edac.c16
-rw-r--r--drivers/edac/highbank_l2_edac.c33
-rw-r--r--drivers/edac/highbank_mc_edac.c175
-rw-r--r--drivers/edac/mpc85xx_edac.c22
-rw-r--r--drivers/edac/sb_edac.c595
11 files changed, 288 insertions, 632 deletions
diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c
index b53d0de..3c9e4e9 100644
--- a/drivers/edac/amd64_edac.c
+++ b/drivers/edac/amd64_edac.c
@@ -339,8 +339,8 @@ static void get_cs_base_and_mask(struct amd64_pvt *pvt, int csrow, u8 dct,
if (pvt->fam == 0xf && pvt->ext_model < K8_REV_F) {
csbase = pvt->csels[dct].csbases[csrow];
csmask = pvt->csels[dct].csmasks[csrow];
- base_bits = GENMASK_ULL(31, 21) | GENMASK_ULL(15, 9);
- mask_bits = GENMASK_ULL(29, 21) | GENMASK_ULL(15, 9);
+ base_bits = GENMASK(21, 31) | GENMASK(9, 15);
+ mask_bits = GENMASK(21, 29) | GENMASK(9, 15);
addr_shift = 4;
/*
@@ -352,16 +352,16 @@ static void get_cs_base_and_mask(struct amd64_pvt *pvt, int csrow, u8 dct,
csbase = pvt->csels[dct].csbases[csrow];
csmask = pvt->csels[dct].csmasks[csrow >> 1];
- *base = (csbase & GENMASK_ULL(15, 5)) << 6;
- *base |= (csbase & GENMASK_ULL(30, 19)) << 8;
+ *base = (csbase & GENMASK(5, 15)) << 6;
+ *base |= (csbase & GENMASK(19, 30)) << 8;
*mask = ~0ULL;
/* poke holes for the csmask */
- *mask &= ~((GENMASK_ULL(15, 5) << 6) |
- (GENMASK_ULL(30, 19) << 8));
+ *mask &= ~((GENMASK(5, 15) << 6) |
+ (GENMASK(19, 30) << 8));
- *mask |= (csmask & GENMASK_ULL(15, 5)) << 6;
- *mask |= (csmask & GENMASK_ULL(30, 19)) << 8;
+ *mask |= (csmask & GENMASK(5, 15)) << 6;
+ *mask |= (csmask & GENMASK(19, 30)) << 8;
return;
} else {
@@ -370,11 +370,9 @@ static void get_cs_base_and_mask(struct amd64_pvt *pvt, int csrow, u8 dct,
addr_shift = 8;
if (pvt->fam == 0x15)
- base_bits = mask_bits =
- GENMASK_ULL(30,19) | GENMASK_ULL(13,5);
+ base_bits = mask_bits = GENMASK(19,30) | GENMASK(5,13);
else
- base_bits = mask_bits =
- GENMASK_ULL(28,19) | GENMASK_ULL(13,5);
+ base_bits = mask_bits = GENMASK(19,28) | GENMASK(5,13);
}
*base = (csbase & base_bits) << addr_shift;
@@ -563,7 +561,7 @@ static u64 sys_addr_to_dram_addr(struct mem_ctl_info *mci, u64 sys_addr)
* section 3.4.2 of AMD publication 24592: AMD x86-64 Architecture
* Programmer's Manual Volume 1 Application Programming.
*/
- dram_addr = (sys_addr & GENMASK_ULL(39, 0)) - dram_base;
+ dram_addr = (sys_addr & GENMASK(0, 39)) - dram_base;
edac_dbg(2, "using DRAM Base register to translate SysAddr 0x%lx to DramAddr 0x%lx\n",
(unsigned long)sys_addr, (unsigned long)dram_addr);
@@ -599,7 +597,7 @@ static u64 dram_addr_to_input_addr(struct mem_ctl_info *mci, u64 dram_addr)
* concerning translating a DramAddr to an InputAddr.
*/
intlv_shift = num_node_interleave_bits(dram_intlv_en(pvt, 0));
- input_addr = ((dram_addr >> intlv_shift) & GENMASK_ULL(35, 12)) +
+ input_addr = ((dram_addr >> intlv_shift) & GENMASK(12, 35)) +
(dram_addr & 0xfff);
edac_dbg(2, " Intlv Shift=%d DramAddr=0x%lx maps to InputAddr=0x%lx\n",
@@ -851,7 +849,7 @@ static u64 get_error_address(struct amd64_pvt *pvt, struct mce *m)
end_bit = 39;
}
- addr = m->addr & GENMASK_ULL(end_bit, start_bit);
+ addr = m->addr & GENMASK(start_bit, end_bit);
/*
* Erratum 637 workaround
@@ -863,7 +861,7 @@ static u64 get_error_address(struct amd64_pvt *pvt, struct mce *m)
u16 mce_nid;
u8 intlv_en;
- if ((addr & GENMASK_ULL(47, 24)) >> 24 != 0x00fdf7)
+ if ((addr & GENMASK(24, 47)) >> 24 != 0x00fdf7)
return addr;
mce_nid = amd_get_nb_id(m->extcpu);
@@ -873,7 +871,7 @@ static u64 get_error_address(struct amd64_pvt *pvt, struct mce *m)
intlv_en = tmp >> 21 & 0x7;
/* add [47:27] + 3 trailing bits */
- cc6_base = (tmp & GENMASK_ULL(20, 0)) << 3;
+ cc6_base = (tmp & GENMASK(0, 20)) << 3;
/* reverse and add DramIntlvEn */
cc6_base |= intlv_en ^ 0x7;
@@ -882,18 +880,18 @@ static u64 get_error_address(struct amd64_pvt *pvt, struct mce *m)
cc6_base <<= 24;
if (!intlv_en)
- return cc6_base | (addr & GENMASK_ULL(23, 0));
+ return cc6_base | (addr & GENMASK(0, 23));
amd64_read_pci_cfg(pvt->F1, DRAM_LOCAL_NODE_BASE, &tmp);
/* faster log2 */
- tmp_addr = (addr & GENMASK_ULL(23, 12)) << __fls(intlv_en + 1);
+ tmp_addr = (addr & GENMASK(12, 23)) << __fls(intlv_en + 1);
/* OR DramIntlvSel into bits [14:12] */
- tmp_addr |= (tmp & GENMASK_ULL(23, 21)) >> 9;
+ tmp_addr |= (tmp & GENMASK(21, 23)) >> 9;
/* add remaining [11:0] bits from original MC4_ADDR */
- tmp_addr |= addr & GENMASK_ULL(11, 0);
+ tmp_addr |= addr & GENMASK(0, 11);
return cc6_base | tmp_addr;
}
@@ -954,12 +952,12 @@ static void read_dram_base_limit_regs(struct amd64_pvt *pvt, unsigned range)
amd64_read_pci_cfg(f1, DRAM_LOCAL_NODE_LIM, &llim);
- pvt->ranges[range].lim.lo &= GENMASK_ULL(15, 0);
+ pvt->ranges[range].lim.lo &= GENMASK(0, 15);
/* {[39:27],111b} */
pvt->ranges[range].lim.lo |= ((llim & 0x1fff) << 3 | 0x7) << 16;
- pvt->ranges[range].lim.hi &= GENMASK_ULL(7, 0);
+ pvt->ranges[range].lim.hi &= GENMASK(0, 7);
/* [47:40] */
pvt->ranges[range].lim.hi |= llim >> 13;
@@ -1332,7 +1330,7 @@ static u64 f1x_get_norm_dct_addr(struct amd64_pvt *pvt, u8 range,
chan_off = dram_base;
}
- return (sys_addr & GENMASK_ULL(47,6)) - (chan_off & GENMASK_ULL(47,23));
+ return (sys_addr & GENMASK(6,47)) - (chan_off & GENMASK(23,47));
}
/*
diff --git a/drivers/edac/amd64_edac.h b/drivers/edac/amd64_edac.h
index 6dc1fcc..d2443cf 100644
--- a/drivers/edac/amd64_edac.h
+++ b/drivers/edac/amd64_edac.h
@@ -160,6 +160,14 @@
#define OFF false
/*
+ * Create a contiguous bitmask starting at bit position @lo and ending at
+ * position @hi. For example
+ *
+ * GENMASK(21, 39) gives us the 64bit vector 0x000000ffffe00000.
+ */
+#define GENMASK(lo, hi) (((1ULL << ((hi) - (lo) + 1)) - 1) << (lo))
+
+/*
* PCI-defined configuration space registers
*/
#define PCI_DEVICE_ID_AMD_15H_M30H_NB_F1 0x141b
diff --git a/drivers/edac/cell_edac.c b/drivers/edac/cell_edac.c
index 374b57f..c2eaf33 100644
--- a/drivers/edac/cell_edac.c
+++ b/drivers/edac/cell_edac.c
@@ -15,7 +15,6 @@
#include <linux/platform_device.h>
#include <linux/stop_machine.h>
#include <linux/io.h>
-#include <linux/of_address.h>
#include <asm/machdep.h>
#include <asm/cell-regs.h>
@@ -163,7 +162,6 @@ static void cell_edac_init_csrows(struct mem_ctl_info *mci)
csrow->first_page, nr_pages);
break;
}
- of_node_put(np);
}
static int cell_edac_probe(struct platform_device *pdev)
diff --git a/drivers/edac/edac_device.c b/drivers/edac/edac_device.c
index 1026743..211021d 100644
--- a/drivers/edac/edac_device.c
+++ b/drivers/edac/edac_device.c
@@ -530,9 +530,12 @@ int edac_device_add_device(struct edac_device_ctl_info *edac_dev)
/* Report action taken */
edac_device_printk(edac_dev, KERN_INFO,
- "Giving out device to module %s controller %s: DEV %s (%s)\n",
- edac_dev->mod_name, edac_dev->ctl_name, edac_dev->dev_name,
- edac_op_state_to_string(edac_dev->op_state));
+ "Giving out device to module '%s' controller "
+ "'%s': DEV '%s' (%s)\n",
+ edac_dev->mod_name,
+ edac_dev->ctl_name,
+ edac_dev_name(edac_dev),
+ edac_op_state_to_string(edac_dev->op_state));
mutex_unlock(&device_ctls_mutex);
return 0;
diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c
index e8c9ef0..89e1090 100644
--- a/drivers/edac/edac_mc.c
+++ b/drivers/edac/edac_mc.c
@@ -788,10 +788,8 @@ int edac_mc_add_mc(struct mem_ctl_info *mci)
}
/* Report action taken */
- edac_mc_printk(mci, KERN_INFO,
- "Giving out device to module %s controller %s: DEV %s (%s)\n",
- mci->mod_name, mci->ctl_name, mci->dev_name,
- edac_op_state_to_string(mci->op_state));
+ edac_mc_printk(mci, KERN_INFO, "Giving out device to '%s' '%s':"
+ " DEV %s\n", mci->mod_name, mci->ctl_name, edac_dev_name(mci));
edac_mc_owner = mci->mod_name;
diff --git a/drivers/edac/edac_pci.c b/drivers/edac/edac_pci.c
index a3893e3..ce1e97f 100644
--- a/drivers/edac/edac_pci.c
+++ b/drivers/edac/edac_pci.c
@@ -358,9 +358,11 @@ int edac_pci_add_device(struct edac_pci_ctl_info *pci, int edac_idx)
}
edac_pci_printk(pci, KERN_INFO,
- "Giving out device to module %s controller %s: DEV %s (%s)\n",
- pci->mod_name, pci->ctl_name, pci->dev_name,
- edac_op_state_to_string(pci->op_state));
+ "Giving out device to module '%s' controller '%s':"
+ " DEV '%s' (%s)\n",
+ pci->mod_name,
+ pci->ctl_name,
+ edac_dev_name(pci), edac_op_state_to_string(pci->op_state));
mutex_unlock(&edac_pci_ctls_mutex);
return 0;
diff --git a/drivers/edac/ghes_edac.c b/drivers/edac/ghes_edac.c
index d5a98a4..bb53467 100644
--- a/drivers/edac/ghes_edac.c
+++ b/drivers/edac/ghes_edac.c
@@ -297,14 +297,15 @@ void ghes_edac_report_mem_error(struct ghes *ghes, int sev,
}
/* Error address */
- if (mem_err->validation_bits & CPER_MEM_VALID_PA) {
+ if (mem_err->validation_bits & CPER_MEM_VALID_PHYSICAL_ADDRESS) {
e->page_frame_number = mem_err->physical_addr >> PAGE_SHIFT;
e->offset_in_page = mem_err->physical_addr & ~PAGE_MASK;
}
/* Error grain */
- if (mem_err->validation_bits & CPER_MEM_VALID_PA_MASK)
+ if (mem_err->validation_bits & CPER_MEM_VALID_PHYSICAL_ADDRESS_MASK) {
e->grain = ~(mem_err->physical_addr_mask & ~PAGE_MASK);
+ }
/* Memory error location, mapped on e->location */
p = e->location;
@@ -314,8 +315,6 @@ void ghes_edac_report_mem_error(struct ghes *ghes, int sev,
p += sprintf(p, "card:%d ", mem_err->card);
if (mem_err->validation_bits & CPER_MEM_VALID_MODULE)
p += sprintf(p, "module:%d ", mem_err->module);
- if (mem_err->validation_bits & CPER_MEM_VALID_RANK_NUMBER)
- p += sprintf(p, "rank:%d ", mem_err->rank);
if (mem_err->validation_bits & CPER_MEM_VALID_BANK)
p += sprintf(p, "bank:%d ", mem_err->bank);
if (mem_err->validation_bits & CPER_MEM_VALID_ROW)
@@ -324,15 +323,6 @@ void ghes_edac_report_mem_error(struct ghes *ghes, int sev,
p += sprintf(p, "col:%d ", mem_err->column);
if (mem_err->validation_bits & CPER_MEM_VALID_BIT_POSITION)
p += sprintf(p, "bit_pos:%d ", mem_err->bit_pos);
- if (mem_err->validation_bits & CPER_MEM_VALID_MODULE_HANDLE) {
- const char *bank = NULL, *device = NULL;
- dmi_memdev_name(mem_err->mem_dev_handle, &bank, &device);
- if (bank != NULL && device != NULL)
- p += sprintf(p, "DIMM location:%s %s ", bank, device);
- else
- p += sprintf(p, "DIMM DMI handle: 0x%.4x ",
- mem_err->mem_dev_handle);
- }
if (p > e->location)
*(p - 1) = '\0';
diff --git a/drivers/edac/highbank_l2_edac.c b/drivers/edac/highbank_l2_edac.c
index 2f19366..c2bd8c6 100644
--- a/drivers/edac/highbank_l2_edac.c
+++ b/drivers/edac/highbank_l2_edac.c
@@ -50,15 +50,8 @@ static irqreturn_t highbank_l2_err_handler(int irq, void *dev_id)
return IRQ_HANDLED;
}
-static const struct of_device_id hb_l2_err_of_match[] = {
- { .compatible = "calxeda,hb-sregs-l2-ecc", },
- {},
-};
-MODULE_DEVICE_TABLE(of, hb_l2_err_of_match);
-
static int highbank_l2_err_probe(struct platform_device *pdev)
{
- const struct of_device_id *id;
struct edac_device_ctl_info *dci;
struct hb_l2_drvdata *drvdata;
struct resource *r;
@@ -97,32 +90,28 @@ static int highbank_l2_err_probe(struct platform_device *pdev)
goto err;
}
- id = of_match_device(hb_l2_err_of_match, &pdev->dev);
- dci->mod_name = pdev->dev.driver->name;
- dci->ctl_name = id ? id->compatible : "unknown";
- dci->dev_name = dev_name(&pdev->dev);
-
- if (edac_device_add_device(dci))
- goto err;
-
drvdata->db_irq = platform_get_irq(pdev, 0);
res = devm_request_irq(&pdev->dev, drvdata->db_irq,
highbank_l2_err_handler,
0, dev_name(&pdev->dev), dci);
if (res < 0)
- goto err2;
+ goto err;
drvdata->sb_irq = platform_get_irq(pdev, 1);
res = devm_request_irq(&pdev->dev, drvdata->sb_irq,
highbank_l2_err_handler,
0, dev_name(&pdev->dev), dci);
if (res < 0)
- goto err2;
+ goto err;
+
+ dci->mod_name = dev_name(&pdev->dev);
+ dci->dev_name = dev_name(&pdev->dev);
+
+ if (edac_device_add_device(dci))
+ goto err;
devres_close_group(&pdev->dev, NULL);
return 0;
-err2:
- edac_device_del_device(&pdev->dev);
err:
devres_release_group(&pdev->dev, NULL);
edac_device_free_ctl_info(dci);
@@ -138,6 +127,12 @@ static int highbank_l2_err_remove(struct platform_device *pdev)
return 0;
}
+static const struct of_device_id hb_l2_err_of_match[] = {
+ { .compatible = "calxeda,hb-sregs-l2-ecc", },
+ {},
+};
+MODULE_DEVICE_TABLE(of, hb_l2_err_of_match);
+
static struct platform_driver highbank_l2_edac_driver = {
.probe = highbank_l2_err_probe,
.remove = highbank_l2_err_remove,
diff --git a/drivers/edac/highbank_mc_edac.c b/drivers/edac/highbank_mc_edac.c
index f784de1..4695dd2 100644
--- a/drivers/edac/highbank_mc_edac.c
+++ b/drivers/edac/highbank_mc_edac.c
@@ -26,40 +26,31 @@
#include "edac_module.h"
/* DDR Ctrlr Error Registers */
-
-#define HB_DDR_ECC_ERR_BASE 0x128
-#define MW_DDR_ECC_ERR_BASE 0x1b4
-
-#define HB_DDR_ECC_OPT 0x00
-#define HB_DDR_ECC_U_ERR_ADDR 0x08
-#define HB_DDR_ECC_U_ERR_STAT 0x0c
-#define HB_DDR_ECC_U_ERR_DATAL 0x10
-#define HB_DDR_ECC_U_ERR_DATAH 0x14
-#define HB_DDR_ECC_C_ERR_ADDR 0x18
-#define HB_DDR_ECC_C_ERR_STAT 0x1c
-#define HB_DDR_ECC_C_ERR_DATAL 0x20
-#define HB_DDR_ECC_C_ERR_DATAH 0x24
-
-#define HB_DDR_ECC_OPT_MODE_MASK 0x3
-#define HB_DDR_ECC_OPT_FWC 0x100
-#define HB_DDR_ECC_OPT_XOR_SHIFT 16
-
-/* DDR Ctrlr Interrupt Registers */
-
-#define HB_DDR_ECC_INT_BASE 0x180
-#define MW_DDR_ECC_INT_BASE 0x218
-
-#define HB_DDR_ECC_INT_STATUS 0x00
-#define HB_DDR_ECC_INT_ACK 0x04
+#define HB_DDR_ECC_OPT 0x128
+#define HB_DDR_ECC_U_ERR_ADDR 0x130
+#define HB_DDR_ECC_U_ERR_STAT 0x134
+#define HB_DDR_ECC_U_ERR_DATAL 0x138
+#define HB_DDR_ECC_U_ERR_DATAH 0x13c
+#define HB_DDR_ECC_C_ERR_ADDR 0x140
+#define HB_DDR_ECC_C_ERR_STAT 0x144
+#define HB_DDR_ECC_C_ERR_DATAL 0x148
+#define HB_DDR_ECC_C_ERR_DATAH 0x14c
+#define HB_DDR_ECC_INT_STATUS 0x180
+#define HB_DDR_ECC_INT_ACK 0x184
+#define HB_DDR_ECC_U_ERR_ID 0x424
+#define HB_DDR_ECC_C_ERR_ID 0x428
#define HB_DDR_ECC_INT_STAT_CE 0x8
#define HB_DDR_ECC_INT_STAT_DOUBLE_CE 0x10
#define HB_DDR_ECC_INT_STAT_UE 0x20
#define HB_DDR_ECC_INT_STAT_DOUBLE_UE 0x40
+#define HB_DDR_ECC_OPT_MODE_MASK 0x3
+#define HB_DDR_ECC_OPT_FWC 0x100
+#define HB_DDR_ECC_OPT_XOR_SHIFT 16
+
struct hb_mc_drvdata {
- void __iomem *mc_err_base;
- void __iomem *mc_int_base;
+ void __iomem *mc_vbase;
};
static irqreturn_t highbank_mc_err_handler(int irq, void *dev_id)
@@ -69,10 +60,10 @@ static irqreturn_t highbank_mc_err_handler(int irq, void *dev_id)
u32 status, err_addr;
/* Read the interrupt status register */
- status = readl(drvdata->mc_int_base + HB_DDR_ECC_INT_STATUS);
+ status = readl(drvdata->mc_vbase + HB_DDR_ECC_INT_STATUS);
if (status & HB_DDR_ECC_INT_STAT_UE) {
- err_addr = readl(drvdata->mc_err_base + HB_DDR_ECC_U_ERR_ADDR);
+ err_addr = readl(drvdata->mc_vbase + HB_DDR_ECC_U_ERR_ADDR);
edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1,
err_addr >> PAGE_SHIFT,
err_addr & ~PAGE_MASK, 0,
@@ -80,9 +71,9 @@ static irqreturn_t highbank_mc_err_handler(int irq, void *dev_id)
mci->ctl_name, "");
}
if (status & HB_DDR_ECC_INT_STAT_CE) {
- u32 syndrome = readl(drvdata->mc_err_base + HB_DDR_ECC_C_ERR_STAT);
+ u32 syndrome = readl(drvdata->mc_vbase + HB_DDR_ECC_C_ERR_STAT);
syndrome = (syndrome >> 8) & 0xff;
- err_addr = readl(drvdata->mc_err_base + HB_DDR_ECC_C_ERR_ADDR);
+ err_addr = readl(drvdata->mc_vbase + HB_DDR_ECC_C_ERR_ADDR);
edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1,
err_addr >> PAGE_SHIFT,
err_addr & ~PAGE_MASK, syndrome,
@@ -91,79 +82,66 @@ static irqreturn_t highbank_mc_err_handler(int irq, void *dev_id)
}
/* clear the error, clears the interrupt */
- writel(status, drvdata->mc_int_base + HB_DDR_ECC_INT_ACK);
+ writel(status, drvdata->mc_vbase + HB_DDR_ECC_INT_ACK);
return IRQ_HANDLED;
}
-static void highbank_mc_err_inject(struct mem_ctl_info *mci, u8 synd)
+#ifdef CONFIG_EDAC_DEBUG
+static ssize_t highbank_mc_err_inject_write(struct file *file,
+ const char __user *data,
+ size_t count, loff_t *ppos)
{
+ struct mem_ctl_info *mci = file->private_data;
struct hb_mc_drvdata *pdata = mci->pvt_info;
+ char buf[32];
+ size_t buf_size;
u32 reg;
-
- reg = readl(pdata->mc_err_base + HB_DDR_ECC_OPT);
- reg &= HB_DDR_ECC_OPT_MODE_MASK;
- reg |= (synd << HB_DDR_ECC_OPT_XOR_SHIFT) | HB_DDR_ECC_OPT_FWC;
- writel(reg, pdata->mc_err_base + HB_DDR_ECC_OPT);
-}
-
-#define to_mci(k) container_of(k, struct mem_ctl_info, dev)
-
-static ssize_t highbank_mc_inject_ctrl(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count)
-{
- struct mem_ctl_info *mci = to_mci(dev);
u8 synd;
- if (kstrtou8(buf, 16, &synd))
- return -EINVAL;
+ buf_size = min(count, (sizeof(buf)-1));
+ if (copy_from_user(buf, data, buf_size))
+ return -EFAULT;
+ buf[buf_size] = 0;
- highbank_mc_err_inject(mci, synd);
+ if (!kstrtou8(buf, 16, &synd)) {
+ reg = readl(pdata->mc_vbase + HB_DDR_ECC_OPT);
+ reg &= HB_DDR_ECC_OPT_MODE_MASK;
+ reg |= (synd << HB_DDR_ECC_OPT_XOR_SHIFT) | HB_DDR_ECC_OPT_FWC;
+ writel(reg, pdata->mc_vbase + HB_DDR_ECC_OPT);
+ }
return count;
}
-static DEVICE_ATTR(inject_ctrl, S_IWUSR, NULL, highbank_mc_inject_ctrl);
-
-struct hb_mc_settings {
- int err_offset;
- int int_offset;
+static const struct file_operations highbank_mc_debug_inject_fops = {
+ .open = simple_open,
+ .write = highbank_mc_err_inject_write,
+ .llseek = generic_file_llseek,
};
-static struct hb_mc_settings hb_settings = {
- .err_offset = HB_DDR_ECC_ERR_BASE,
- .int_offset = HB_DDR_ECC_INT_BASE,
-};
-
-static struct hb_mc_settings mw_settings = {
- .err_offset = MW_DDR_ECC_ERR_BASE,
- .int_offset = MW_DDR_ECC_INT_BASE,
-};
-
-static struct of_device_id hb_ddr_ctrl_of_match[] = {
- { .compatible = "calxeda,hb-ddr-ctrl", .data = &hb_settings },
- { .compatible = "calxeda,ecx-2000-ddr-ctrl", .data = &mw_settings },
- {},
-};
-MODULE_DEVICE_TABLE(of, hb_ddr_ctrl_of_match);
+static void highbank_mc_create_debugfs_nodes(struct mem_ctl_info *mci)
+{
+ if (mci->debugfs)
+ debugfs_create_file("inject_ctrl", S_IWUSR, mci->debugfs, mci,
+ &highbank_mc_debug_inject_fops);
+;
+}
+#else
+static void highbank_mc_create_debugfs_nodes(struct mem_ctl_info *mci)
+{}
+#endif
static int highbank_mc_probe(struct platform_device *pdev)
{
- const struct of_device_id *id;
- const struct hb_mc_settings *settings;
struct edac_mc_layer layers[2];
struct mem_ctl_info *mci;
struct hb_mc_drvdata *drvdata;
struct dimm_info *dimm;
struct resource *r;
- void __iomem *base;
u32 control;
int irq;
int res = 0;
- id = of_match_device(hb_ddr_ctrl_of_match, &pdev->dev);
- if (!id)
- return -ENODEV;
-
layers[0].type = EDAC_MC_LAYER_CHIP_SELECT;
layers[0].size = 1;
layers[0].is_virt_csrow = true;
@@ -196,31 +174,35 @@ static int highbank_mc_probe(struct platform_device *pdev)
goto err;
}
- base = devm_ioremap(&pdev->dev, r->start, resource_size(r));
- if (!base) {
+ drvdata->mc_vbase = devm_ioremap(&pdev->dev,
+ r->start, resource_size(r));
+ if (!drvdata->mc_vbase) {
dev_err(&pdev->dev, "Unable to map regs\n");
res = -ENOMEM;
goto err;
}
- settings = id->data;
- drvdata->mc_err_base = base + settings->err_offset;
- drvdata->mc_int_base = base + settings->int_offset;
-
- control = readl(drvdata->mc_err_base + HB_DDR_ECC_OPT) & 0x3;
+ control = readl(drvdata->mc_vbase + HB_DDR_ECC_OPT) & 0x3;
if (!control || (control == 0x2)) {
dev_err(&pdev->dev, "No ECC present, or ECC disabled\n");
res = -ENODEV;
goto err;
}
+ irq = platform_get_irq(pdev, 0);
+ res = devm_request_irq(&pdev->dev, irq, highbank_mc_err_handler,
+ 0, dev_name(&pdev->dev), mci);
+ if (res < 0) {
+ dev_err(&pdev->dev, "Unable to request irq %d\n", irq);
+ goto err;
+ }
+
mci->mtype_cap = MEM_FLAG_DDR3;
mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED;
mci->edac_cap = EDAC_FLAG_SECDED;
- mci->mod_name = pdev->dev.driver->name;
+ mci->mod_name = dev_name(&pdev->dev);
mci->mod_ver = "1";
- mci->ctl_name = id->compatible;
- mci->dev_name = dev_name(&pdev->dev);
+ mci->ctl_name = dev_name(&pdev->dev);
mci->scrub_mode = SCRUB_SW_SRC;
/* Only a single 4GB DIMM is supported */
@@ -235,20 +217,10 @@ static int highbank_mc_probe(struct platform_device *pdev)
if (res < 0)
goto err;
- irq = platform_get_irq(pdev, 0);
- res = devm_request_irq(&pdev->dev, irq, highbank_mc_err_handler,
- 0, dev_name(&pdev->dev), mci);
- if (res < 0) {
- dev_err(&pdev->dev, "Unable to request irq %d\n", irq);
- goto err2;
- }
-
- device_create_file(&mci->dev, &dev_attr_inject_ctrl);
+ highbank_mc_create_debugfs_nodes(mci);
devres_close_group(&pdev->dev, NULL);
return 0;
-err2:
- edac_mc_del_mc(&pdev->dev);
err:
devres_release_group(&pdev->dev, NULL);
edac_mc_free(mci);
@@ -259,12 +231,17 @@ static int highbank_mc_remove(struct platform_device *pdev)
{
struct mem_ctl_info *mci = platform_get_drvdata(pdev);
- device_remove_file(&mci->dev, &dev_attr_inject_ctrl);
edac_mc_del_mc(&pdev->dev);
edac_mc_free(mci);
return 0;
}
+static const struct of_device_id hb_ddr_ctrl_of_match[] = {
+ { .compatible = "calxeda,hb-ddr-ctrl", },
+ {},
+};
+MODULE_DEVICE_TABLE(of, hb_ddr_ctrl_of_match);
+
static struct platform_driver highbank_mc_edac_driver = {
.probe = highbank_mc_probe,
.remove = highbank_mc_remove,
diff --git a/drivers/edac/mpc85xx_edac.c b/drivers/edac/mpc85xx_edac.c
index d7fa04e..939ea18 100644
--- a/drivers/edac/mpc85xx_edac.c
+++ b/drivers/edac/mpc85xx_edac.c
@@ -400,6 +400,28 @@ err:
}
EXPORT_SYMBOL(mpc85xx_pci_err_probe);
+static int mpc85xx_pci_err_remove(struct platform_device *op)
+{
+ struct edac_pci_ctl_info *pci = dev_get_drvdata(&op->dev);
+ struct mpc85xx_pci_pdata *pdata = pci->pvt_info;
+
+ edac_dbg(0, "\n");
+
+ out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_CAP_DR,
+ orig_pci_err_cap_dr);
+
+ out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_EN, orig_pci_err_en);
+
+ edac_pci_del_device(pci->dev);
+
+ if (edac_op_state == EDAC_OPSTATE_INT)
+ irq_dispose_mapping(pdata->irq);
+
+ edac_pci_free_ctl_info(pci);
+
+ return 0;
+}
+
#endif /* CONFIG_PCI */
/**************************** L2 Err device ***************************/
diff --git a/drivers/edac/sb_edac.c b/drivers/edac/sb_edac.c
index 8472405..e04462b 100644
--- a/drivers/edac/sb_edac.c
+++ b/drivers/edac/sb_edac.c
@@ -34,7 +34,7 @@ static int probed;
/*
* Alter this version for the module when modifications are made
*/
-#define SBRIDGE_REVISION " Ver: 1.1.0 "
+#define SBRIDGE_REVISION " Ver: 1.0.0 "
#define EDAC_MOD_STR "sbridge_edac"
/*
@@ -50,7 +50,7 @@ static int probed;
* Get a bit field at register value <v>, from bit <lo> to bit <hi>
*/
#define GET_BITFIELD(v, lo, hi) \
- (((v) & GENMASK_ULL(hi, lo)) >> (lo))
+ (((v) & ((1ULL << ((hi) - (lo) + 1)) - 1) << (lo)) >> (lo))
/*
* sbridge Memory Controller Registers
@@ -83,17 +83,11 @@ static int probed;
#define PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_ERR3 0x3c77 /* 16.7 */
/* Devices 12 Function 6, Offsets 0x80 to 0xcc */
-static const u32 sbridge_dram_rule[] = {
+static const u32 dram_rule[] = {
0x80, 0x88, 0x90, 0x98, 0xa0,
0xa8, 0xb0, 0xb8, 0xc0, 0xc8,
};
-
-static const u32 ibridge_dram_rule[] = {
- 0x60, 0x68, 0x70, 0x78, 0x80,
- 0x88, 0x90, 0x98, 0xa0, 0xa8,
- 0xb0, 0xb8, 0xc0, 0xc8, 0xd0,
- 0xd8, 0xe0, 0xe8, 0xf0, 0xf8,
-};
+#define MAX_SAD ARRAY_SIZE(dram_rule)
#define SAD_LIMIT(reg) ((GET_BITFIELD(reg, 6, 25) << 26) | 0x3ffffff)
#define DRAM_ATTR(reg) GET_BITFIELD(reg, 2, 3)
@@ -114,50 +108,43 @@ static char *get_dram_attr(u32 reg)
}
}
-static const u32 sbridge_interleave_list[] = {
+static const u32 interleave_list[] = {
0x84, 0x8c, 0x94, 0x9c, 0xa4,
0xac, 0xb4, 0xbc, 0xc4, 0xcc,
};
-
-static const u32 ibridge_interleave_list[] = {
- 0x64, 0x6c, 0x74, 0x7c, 0x84,
- 0x8c, 0x94, 0x9c, 0xa4, 0xac,
- 0xb4, 0xbc, 0xc4, 0xcc, 0xd4,
- 0xdc, 0xe4, 0xec, 0xf4, 0xfc,
-};
-
-struct interleave_pkg {
- unsigned char start;
- unsigned char end;
-};
-
-static const struct interleave_pkg sbridge_interleave_pkg[] = {
- { 0, 2 },
- { 3, 5 },
- { 8, 10 },
- { 11, 13 },
- { 16, 18 },
- { 19, 21 },
- { 24, 26 },
- { 27, 29 },
-};
-
-static const struct interleave_pkg ibridge_interleave_pkg[] = {
- { 0, 3 },
- { 4, 7 },
- { 8, 11 },
- { 12, 15 },
- { 16, 19 },
- { 20, 23 },
- { 24, 27 },
- { 28, 31 },
-};
-
-static inline int sad_pkg(const struct interleave_pkg *table, u32 reg,
- int interleave)
+#define MAX_INTERLEAVE ARRAY_SIZE(interleave_list)
+
+#define SAD_PKG0(reg) GET_BITFIELD(reg, 0, 2)
+#define SAD_PKG1(reg) GET_BITFIELD(reg, 3, 5)
+#define SAD_PKG2(reg) GET_BITFIELD(reg, 8, 10)
+#define SAD_PKG3(reg) GET_BITFIELD(reg, 11, 13)
+#define SAD_PKG4(reg) GET_BITFIELD(reg, 16, 18)
+#define SAD_PKG5(reg) GET_BITFIELD(reg, 19, 21)
+#define SAD_PKG6(reg) GET_BITFIELD(reg, 24, 26)
+#define SAD_PKG7(reg) GET_BITFIELD(reg, 27, 29)
+
+static inline int sad_pkg(u32 reg, int interleave)
{
- return GET_BITFIELD(reg, table[interleave].start,
- table[interleave].end);
+ switch (interleave) {
+ case 0:
+ return SAD_PKG0(reg);
+ case 1:
+ return SAD_PKG1(reg);
+ case 2:
+ return SAD_PKG2(reg);
+ case 3:
+ return SAD_PKG3(reg);
+ case 4:
+ return SAD_PKG4(reg);
+ case 5:
+ return SAD_PKG5(reg);
+ case 6:
+ return SAD_PKG6(reg);
+ case 7:
+ return SAD_PKG7(reg);
+ default:
+ return -EINVAL;
+ }
}
/* Devices 12 Function 7 */
@@ -275,9 +262,7 @@ static const u32 correrrthrsld[] = {
/* Device 17, function 0 */
-#define SB_RANK_CFG_A 0x0328
-
-#define IB_RANK_CFG_A 0x0320
+#define RANK_CFG_A 0x0328
#define IS_RDIMM_ENABLED(reg) GET_BITFIELD(reg, 11, 11)
@@ -288,23 +273,8 @@ static const u32 correrrthrsld[] = {
#define NUM_CHANNELS 4
#define MAX_DIMMS 3 /* Max DIMMS per channel */
-enum type {
- SANDY_BRIDGE,
- IVY_BRIDGE,
-};
-
-struct sbridge_pvt;
struct sbridge_info {
- enum type type;
- u32 mcmtr;
- u32 rankcfgr;
- u64 (*get_tolm)(struct sbridge_pvt *pvt);
- u64 (*get_tohm)(struct sbridge_pvt *pvt);
- const u32 *dram_rule;
- const u32 *interleave_list;
- const struct interleave_pkg *interleave_pkg;
- u8 max_sad;
- u8 max_interleave;
+ u32 mcmtr;
};
struct sbridge_channel {
@@ -335,9 +305,8 @@ struct sbridge_dev {
struct sbridge_pvt {
struct pci_dev *pci_ta, *pci_ddrio, *pci_ras;
- 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_sad0, *pci_sad1, *pci_ha0;
+ struct pci_dev *pci_br;
struct pci_dev *pci_tad[NUM_CHANNELS];
struct sbridge_dev *sbridge_dev;
@@ -395,75 +364,11 @@ static const struct pci_id_table pci_dev_descr_sbridge_table[] = {
{0,} /* 0 terminated list. */
};
-/* This changes depending if 1HA or 2HA:
- * 1HA:
- * 0x0eb8 (17.0) is DDRIO0
- * 2HA:
- * 0x0ebc (17.4) is DDRIO0
- */
-#define PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_1HA_DDRIO0 0x0eb8
-#define PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_2HA_DDRIO0 0x0ebc
-
-/* pci ids */
-#define PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0 0x0ea0
-#define PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TA 0x0ea8
-#define PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_RAS 0x0e71
-#define PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD0 0x0eaa
-#define PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD1 0x0eab
-#define PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD2 0x0eac
-#define PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD3 0x0ead
-#define PCI_DEVICE_ID_INTEL_IBRIDGE_SAD 0x0ec8
-#define PCI_DEVICE_ID_INTEL_IBRIDGE_BR0 0x0ec9
-#define PCI_DEVICE_ID_INTEL_IBRIDGE_BR1 0x0eca
-#define PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1 0x0e60
-#define PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TA 0x0e68
-#define PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_RAS 0x0e79
-#define PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD0 0x0e6a
-#define PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD1 0x0e6b
-
-static const struct pci_id_descr pci_dev_descr_ibridge[] = {
- /* Processor Home Agent */
- { PCI_DESCR(14, 0, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0, 0) },
-
- /* Memory controller */
- { PCI_DESCR(15, 0, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TA, 0) },
- { PCI_DESCR(15, 1, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_RAS, 0) },
- { PCI_DESCR(15, 2, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD0, 0) },
- { PCI_DESCR(15, 3, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD1, 0) },
- { PCI_DESCR(15, 4, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD2, 0) },
- { PCI_DESCR(15, 5, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD3, 0) },
-
- /* System Address Decoder */
- { PCI_DESCR(22, 0, PCI_DEVICE_ID_INTEL_IBRIDGE_SAD, 0) },
-
- /* Broadcast Registers */
- { PCI_DESCR(22, 1, PCI_DEVICE_ID_INTEL_IBRIDGE_BR0, 1) },
- { PCI_DESCR(22, 2, PCI_DEVICE_ID_INTEL_IBRIDGE_BR1, 0) },
-
- /* Optional, mode 2HA */
- { PCI_DESCR(28, 0, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1, 1) },
-#if 0
- { PCI_DESCR(29, 0, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TA, 1) },
- { PCI_DESCR(29, 1, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_RAS, 1) },
-#endif
- { PCI_DESCR(29, 2, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD0, 1) },
- { PCI_DESCR(29, 3, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD1, 1) },
-
- { PCI_DESCR(17, 0, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_1HA_DDRIO0, 1) },
- { PCI_DESCR(17, 4, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_2HA_DDRIO0, 1) },
-};
-
-static const struct pci_id_table pci_dev_descr_ibridge_table[] = {
- PCI_ID_TABLE_ENTRY(pci_dev_descr_ibridge),
- {0,} /* 0 terminated list. */
-};
-
/*
* pci_device_id table for which devices we are looking for
*/
static DEFINE_PCI_DEVICE_TABLE(sbridge_pci_tbl) = {
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TA)},
- {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TA)},
{0,} /* 0 terminated list. */
};
@@ -553,52 +458,6 @@ static void free_sbridge_dev(struct sbridge_dev *sbridge_dev)
kfree(sbridge_dev);
}
-static u64 sbridge_get_tolm(struct sbridge_pvt *pvt)
-{
- u32 reg;
-
- /* Address range is 32:28 */
- pci_read_config_dword(pvt->pci_sad1, TOLM, &reg);
- return GET_TOLM(reg);
-}
-
-static u64 sbridge_get_tohm(struct sbridge_pvt *pvt)
-{
- u32 reg;
-
- pci_read_config_dword(pvt->pci_sad1, TOHM, &reg);
- return GET_TOHM(reg);
-}
-
-static u64 ibridge_get_tolm(struct sbridge_pvt *pvt)
-{
- u32 reg;
-
- pci_read_config_dword(pvt->pci_br1, TOLM, &reg);
-
- return GET_TOLM(reg);
-}
-
-static u64 ibridge_get_tohm(struct sbridge_pvt *pvt)
-{
- u32 reg;
-
- pci_read_config_dword(pvt->pci_br1, TOHM, &reg);
-
- return GET_TOHM(reg);
-}
-
-static inline u8 sad_pkg_socket(u8 pkg)
-{
- /* on Ivy Bridge, nodeID is SASS, where A is HA and S is node id */
- return (pkg >> 3) | (pkg & 0x3);
-}
-
-static inline u8 sad_pkg_ha(u8 pkg)
-{
- return (pkg >> 2) & 0x1;
-}
-
/****************************************************************************
Memory check routines
****************************************************************************/
@@ -661,10 +520,10 @@ static int get_dimm_config(struct mem_ctl_info *mci)
enum edac_type mode;
enum mem_type mtype;
- pci_read_config_dword(pvt->pci_br0, SAD_TARGET, &reg);
+ pci_read_config_dword(pvt->pci_br, SAD_TARGET, &reg);
pvt->sbridge_dev->source_id = SOURCE_ID(reg);
- pci_read_config_dword(pvt->pci_br0, SAD_CONTROL, &reg);
+ pci_read_config_dword(pvt->pci_br, SAD_CONTROL, &reg);
pvt->sbridge_dev->node_id = NODE_ID(reg);
edac_dbg(0, "mc#%d: Node ID: %d, source ID: %d\n",
pvt->sbridge_dev->mc,
@@ -699,8 +558,7 @@ static int get_dimm_config(struct mem_ctl_info *mci)
}
if (pvt->pci_ddrio) {
- pci_read_config_dword(pvt->pci_ddrio, pvt->info.rankcfgr,
- &reg);
+ pci_read_config_dword(pvt->pci_ddrio, RANK_CFG_A, &reg);
if (IS_RDIMM_ENABLED(reg)) {
/* FIXME: Can also be LRDIMM */
edac_dbg(0, "Memory is registered\n");
@@ -771,14 +629,19 @@ static void get_memory_layout(const struct mem_ctl_info *mci)
* Step 1) Get TOLM/TOHM ranges
*/
- pvt->tolm = pvt->info.get_tolm(pvt);
+ /* Address range is 32:28 */
+ pci_read_config_dword(pvt->pci_sad1, TOLM,
+ &reg);
+ pvt->tolm = GET_TOLM(reg);
tmp_mb = (1 + pvt->tolm) >> 20;
mb = div_u64_rem(tmp_mb, 1000, &kb);
edac_dbg(0, "TOLM: %u.%03u GB (0x%016Lx)\n", mb, kb, (u64)pvt->tolm);
/* Address range is already 45:25 */
- pvt->tohm = pvt->info.get_tohm(pvt);
+ pci_read_config_dword(pvt->pci_sad1, TOHM,
+ &reg);
+ pvt->tohm = GET_TOHM(reg);
tmp_mb = (1 + pvt->tohm) >> 20;
mb = div_u64_rem(tmp_mb, 1000, &kb);
@@ -791,9 +654,9 @@ static void get_memory_layout(const struct mem_ctl_info *mci)
* algorithm bellow.
*/
prv = 0;
- for (n_sads = 0; n_sads < pvt->info.max_sad; n_sads++) {
+ for (n_sads = 0; n_sads < MAX_SAD; n_sads++) {
/* SAD_LIMIT Address range is 45:26 */
- pci_read_config_dword(pvt->pci_sad0, pvt->info.dram_rule[n_sads],
+ pci_read_config_dword(pvt->pci_sad0, dram_rule[n_sads],
&reg);
limit = SAD_LIMIT(reg);
@@ -814,16 +677,15 @@ static void get_memory_layout(const struct mem_ctl_info *mci)
reg);
prv = limit;
- pci_read_config_dword(pvt->pci_sad0, pvt->info.interleave_list[n_sads],
+ pci_read_config_dword(pvt->pci_sad0, interleave_list[n_sads],
&reg);
- sad_interl = sad_pkg(pvt->info.interleave_pkg, reg, 0);
+ sad_interl = sad_pkg(reg, 0);
for (j = 0; j < 8; j++) {
- u32 pkg = sad_pkg(pvt->info.interleave_pkg, reg, j);
- if (j > 0 && sad_interl == pkg)
+ if (j > 0 && sad_interl == sad_pkg(reg, j))
break;
edac_dbg(0, "SAD#%d, interleave #%d: %d\n",
- n_sads, j, pkg);
+ n_sads, j, sad_pkg(reg, j));
}
}
@@ -935,13 +797,12 @@ static int get_memory_error_data(struct mem_ctl_info *mci,
{
struct mem_ctl_info *new_mci;
struct sbridge_pvt *pvt = mci->pvt_info;
- struct pci_dev *pci_ha;
int n_rir, n_sads, n_tads, sad_way, sck_xch;
int sad_interl, idx, base_ch;
int interleave_mode;
- unsigned sad_interleave[pvt->info.max_interleave];
+ unsigned sad_interleave[MAX_INTERLEAVE];
u32 reg;
- u8 ch_way, sck_way, pkg, sad_ha = 0;
+ u8 ch_way,sck_way;
u32 tad_offset;
u32 rir_way;
u32 mb, kb;
@@ -967,8 +828,8 @@ static int get_memory_error_data(struct mem_ctl_info *mci,
/*
* Step 1) Get socket
*/
- for (n_sads = 0; n_sads < pvt->info.max_sad; n_sads++) {
- pci_read_config_dword(pvt->pci_sad0, pvt->info.dram_rule[n_sads],
+ for (n_sads = 0; n_sads < MAX_SAD; n_sads++) {
+ pci_read_config_dword(pvt->pci_sad0, dram_rule[n_sads],
&reg);
if (!DRAM_RULE_ENABLE(reg))
@@ -983,65 +844,53 @@ static int get_memory_error_data(struct mem_ctl_info *mci,
break;
prv = limit;
}
- if (n_sads == pvt->info.max_sad) {
+ if (n_sads == MAX_SAD) {
sprintf(msg, "Can't discover the memory socket");
return -EINVAL;
}
*area_type = get_dram_attr(reg);
interleave_mode = INTERLEAVE_MODE(reg);
- pci_read_config_dword(pvt->pci_sad0, pvt->info.interleave_list[n_sads],
+ pci_read_config_dword(pvt->pci_sad0, interleave_list[n_sads],
&reg);
-
- if (pvt->info.type == SANDY_BRIDGE) {
- sad_interl = sad_pkg(pvt->info.interleave_pkg, reg, 0);
- for (sad_way = 0; sad_way < 8; sad_way++) {
- u32 pkg = sad_pkg(pvt->info.interleave_pkg, reg, sad_way);
- if (sad_way > 0 && sad_interl == pkg)
- break;
- sad_interleave[sad_way] = pkg;
- edac_dbg(0, "SAD interleave #%d: %d\n",
- sad_way, sad_interleave[sad_way]);
- }
- edac_dbg(0, "mc#%d: Error detected on SAD#%d: address 0x%016Lx < 0x%016Lx, Interleave [%d:6]%s\n",
- pvt->sbridge_dev->mc,
- n_sads,
- addr,
- limit,
- sad_way + 7,
- !interleave_mode ? "" : "XOR[18:16]");
- if (interleave_mode)
- idx = ((addr >> 6) ^ (addr >> 16)) & 7;
- else
- idx = (addr >> 6) & 7;
- switch (sad_way) {
- case 1:
- idx = 0;
+ sad_interl = sad_pkg(reg, 0);
+ for (sad_way = 0; sad_way < 8; sad_way++) {
+ if (sad_way > 0 && sad_interl == sad_pkg(reg, sad_way))
break;
- case 2:
- idx = idx & 1;
- break;
- case 4:
- idx = idx & 3;
- break;
- case 8:
- break;
- default:
- sprintf(msg, "Can't discover socket interleave");
- return -EINVAL;
- }
- *socket = sad_interleave[idx];
- edac_dbg(0, "SAD interleave index: %d (wayness %d) = CPU socket %d\n",
- idx, sad_way, *socket);
- } else {
- /* Ivy Bridge's SAD mode doesn't support XOR interleave mode */
+ sad_interleave[sad_way] = sad_pkg(reg, sad_way);
+ edac_dbg(0, "SAD interleave #%d: %d\n",
+ sad_way, sad_interleave[sad_way]);
+ }
+ edac_dbg(0, "mc#%d: Error detected on SAD#%d: address 0x%016Lx < 0x%016Lx, Interleave [%d:6]%s\n",
+ pvt->sbridge_dev->mc,
+ n_sads,
+ addr,
+ limit,
+ sad_way + 7,
+ interleave_mode ? "" : "XOR[18:16]");
+ if (interleave_mode)
+ idx = ((addr >> 6) ^ (addr >> 16)) & 7;
+ else
idx = (addr >> 6) & 7;
- pkg = sad_pkg(pvt->info.interleave_pkg, reg, idx);
- *socket = sad_pkg_socket(pkg);
- sad_ha = sad_pkg_ha(pkg);
- edac_dbg(0, "SAD interleave package: %d = CPU socket %d, HA %d\n",
- idx, *socket, sad_ha);
+ switch (sad_way) {
+ case 1:
+ idx = 0;
+ break;
+ case 2:
+ idx = idx & 1;
+ break;
+ case 4:
+ idx = idx & 3;
+ break;
+ case 8:
+ break;
+ default:
+ sprintf(msg, "Can't discover socket interleave");
+ return -EINVAL;
}
+ *socket = sad_interleave[idx];
+ edac_dbg(0, "SAD interleave index: %d (wayness %d) = CPU socket %d\n",
+ idx, sad_way, *socket);
/*
* Move to the proper node structure, in order to access the
@@ -1060,16 +909,9 @@ static int get_memory_error_data(struct mem_ctl_info *mci,
* Step 2) Get memory channel
*/
prv = 0;
- if (pvt->info.type == SANDY_BRIDGE)
- 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++) {
- pci_read_config_dword(pci_ha, tad_dram_rule[n_tads], &reg);
+ pci_read_config_dword(pvt->pci_ha0, tad_dram_rule[n_tads],
+ &reg);
limit = TAD_LIMIT(reg);
if (limit <= prv) {
sprintf(msg, "Can't discover the memory channel");
@@ -1079,13 +921,14 @@ static int get_memory_error_data(struct mem_ctl_info *mci,
break;
prv = limit;
}
- if (n_tads == MAX_TAD) {
- sprintf(msg, "Can't discover the memory channel");
- return -EINVAL;
- }
-
ch_way = TAD_CH(reg) + 1;
sck_way = TAD_SOCK(reg) + 1;
+ /*
+ * FIXME: Is it right to always use channel 0 for offsets?
+ */
+ pci_read_config_dword(pvt->pci_tad[0],
+ tad_ch_nilv_offset[n_tads],
+ &tad_offset);
if (ch_way == 3)
idx = addr >> 6;
@@ -1115,10 +958,6 @@ static int get_memory_error_data(struct mem_ctl_info *mci,
}
*channel_mask = 1 << base_ch;
- pci_read_config_dword(pvt->pci_tad[base_ch],
- tad_ch_nilv_offset[n_tads],
- &tad_offset);
-
if (pvt->is_mirrored) {
*channel_mask |= 1 << ((base_ch + 2) % 4);
switch(ch_way) {
@@ -1252,6 +1091,12 @@ static void sbridge_put_all_devices(void)
}
}
+/*
+ * sbridge_get_all_devices Find and perform 'get' operation on the MCH's
+ * device/functions we want to reference for this driver
+ *
+ * Need to 'get' device 16 func 1 and func 2
+ */
static int sbridge_get_onedevice(struct pci_dev **prev,
u8 *num_mc,
const struct pci_id_table *table,
@@ -1353,21 +1198,11 @@ static int sbridge_get_onedevice(struct pci_dev **prev,
return 0;
}
-/*
- * sbridge_get_all_devices - Find and perform 'get' operation on the MCH's
- * device/functions we want to reference for this driver.
- * Need to 'get' device 16 func 1 and func 2.
- * @num_mc: pointer to the memory controllers count, to be incremented in case
- * of success.
- * @table: model specific table
- *
- * returns 0 in case of success or error code
- */
-static int sbridge_get_all_devices(u8 *num_mc,
- const struct pci_id_table *table)
+static int sbridge_get_all_devices(u8 *num_mc)
{
int i, rc;
struct pci_dev *pdev = NULL;
+ const struct pci_id_table *table = pci_dev_descr_sbridge_table;
while (table && table->descr) {
for (i = 0; i < table->n_devs; i++) {
@@ -1391,8 +1226,8 @@ static int sbridge_get_all_devices(u8 *num_mc,
return 0;
}
-static int sbridge_mci_bind_devs(struct mem_ctl_info *mci,
- struct sbridge_dev *sbridge_dev)
+static int mci_bind_devs(struct mem_ctl_info *mci,
+ struct sbridge_dev *sbridge_dev)
{
struct sbridge_pvt *pvt = mci->pvt_info;
struct pci_dev *pdev;
@@ -1420,7 +1255,7 @@ static int sbridge_mci_bind_devs(struct mem_ctl_info *mci,
case 13:
switch (func) {
case 6:
- pvt->pci_br0 = pdev;
+ pvt->pci_br = pdev;
break;
default:
goto error;
@@ -1494,131 +1329,6 @@ error:
return -EINVAL;
}
-static int ibridge_mci_bind_devs(struct mem_ctl_info *mci,
- struct sbridge_dev *sbridge_dev)
-{
- struct sbridge_pvt *pvt = mci->pvt_info;
- struct pci_dev *pdev, *tmp;
- int i, func, slot;
- bool mode_2ha = false;
-
- tmp = pci_get_device(PCI_VENDOR_ID_INTEL,
- PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1, NULL);
- if (tmp) {
- mode_2ha = true;
- pci_dev_put(tmp);
- }
-
- for (i = 0; i < sbridge_dev->n_devs; i++) {
- pdev = sbridge_dev->pdev[i];
- if (!pdev)
- continue;
- slot = PCI_SLOT(pdev->devfn);
- func = PCI_FUNC(pdev->devfn);
-
- switch (slot) {
- case 14:
- if (func == 0) {
- pvt->pci_ha0 = pdev;
- break;
- }
- goto error;
- case 15:
- switch (func) {
- case 0:
- pvt->pci_ta = pdev;
- break;
- case 1:
- pvt->pci_ras = pdev;
- break;
- case 4:
- case 5:
- /* if we have 2 HAs active, channels 2 and 3
- * are in other device */
- if (mode_2ha)
- break;
- /* fall through */
- case 2:
- case 3:
- pvt->pci_tad[func - 2] = pdev;
- break;
- default:
- goto error;
- }
- break;
- case 17:
- if (func == 4) {
- pvt->pci_ddrio = pdev;
- break;
- } else if (func == 0) {
- if (!mode_2ha)
- pvt->pci_ddrio = pdev;
- break;
- }
- goto error;
- case 22:
- switch (func) {
- case 0:
- pvt->pci_sad0 = pdev;
- break;
- case 1:
- pvt->pci_br0 = pdev;
- break;
- case 2:
- pvt->pci_br1 = pdev;
- break;
- default:
- goto error;
- }
- break;
- case 28:
- if (func == 0) {
- pvt->pci_ha1 = pdev;
- break;
- }
- goto error;
- case 29:
- /* we shouldn't have this device if we have just one
- * HA present */
- WARN_ON(!mode_2ha);
- if (func == 2 || func == 3) {
- pvt->pci_tad[func] = pdev;
- break;
- }
- goto error;
- default:
- goto error;
- }
-
- edac_dbg(0, "Associated PCI %02x.%02d.%d with dev = %p\n",
- sbridge_dev->bus,
- PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn),
- pdev);
- }
-
- /* Check if everything were registered */
- if (!pvt->pci_sad0 || !pvt->pci_ha0 || !pvt->pci_br0 ||
- !pvt->pci_br1 || !pvt->pci_tad || !pvt->pci_ras ||
- !pvt->pci_ta)
- goto enodev;
-
- for (i = 0; i < NUM_CHANNELS; i++) {
- if (!pvt->pci_tad[i])
- goto enodev;
- }
- return 0;
-
-enodev:
- sbridge_printk(KERN_ERR, "Some needed devices are missing\n");
- return -ENODEV;
-
-error:
- sbridge_printk(KERN_ERR,
- "Device %d, function %d is out of the expected range\n",
- slot, func);
- return -EINVAL;
-}
-
/****************************************************************************
Error check routines
****************************************************************************/
@@ -1639,7 +1349,7 @@ static void sbridge_mce_output_error(struct mem_ctl_info *mci,
bool ripv = GET_BITFIELD(m->mcgstatus, 0, 0);
bool overflow = GET_BITFIELD(m->status, 62, 62);
bool uncorrected_error = GET_BITFIELD(m->status, 61, 61);
- bool recoverable;
+ bool recoverable = GET_BITFIELD(m->status, 56, 56);
u32 core_err_cnt = GET_BITFIELD(m->status, 38, 52);
u32 mscod = GET_BITFIELD(m->status, 16, 31);
u32 errcode = GET_BITFIELD(m->status, 0, 15);
@@ -1650,11 +1360,6 @@ static void sbridge_mce_output_error(struct mem_ctl_info *mci,
int rc, dimm;
char *area_type = NULL;
- if (pvt->info.type == IVY_BRIDGE)
- recoverable = true;
- else
- recoverable = GET_BITFIELD(m->status, 56, 56);
-
if (uncorrected_error) {
if (ripv) {
type = "FATAL";
@@ -1704,10 +1409,6 @@ static void sbridge_mce_output_error(struct mem_ctl_info *mci,
}
}
- /* Only decode errors with an valid address (ADDRV) */
- if (!GET_BITFIELD(m->status, 58, 58))
- return;
-
rc = get_memory_error_data(mci, m->addr, &socket,
&channel_mask, &rank, &area_type, msg);
if (rc < 0)
@@ -1913,12 +1614,11 @@ static void sbridge_unregister_mci(struct sbridge_dev *sbridge_dev)
sbridge_dev->mci = NULL;
}
-static int sbridge_register_mci(struct sbridge_dev *sbridge_dev, enum type type)
+static int sbridge_register_mci(struct sbridge_dev *sbridge_dev)
{
struct mem_ctl_info *mci;
struct edac_mc_layer layers[2];
struct sbridge_pvt *pvt;
- struct pci_dev *pdev = sbridge_dev->pdev[0];
int rc;
/* Check the number of active and not disabled channels */
@@ -1940,7 +1640,7 @@ static int sbridge_register_mci(struct sbridge_dev *sbridge_dev, enum type type)
return -ENOMEM;
edac_dbg(0, "MC: mci = %p, dev = %p\n",
- mci, &pdev->dev);
+ mci, &sbridge_dev->pdev[0]->dev);
pvt = mci->pvt_info;
memset(pvt, 0, sizeof(*pvt));
@@ -1954,52 +1654,24 @@ static int sbridge_register_mci(struct sbridge_dev *sbridge_dev, enum type type)
mci->edac_cap = EDAC_FLAG_NONE;
mci->mod_name = "sbridge_edac.c";
mci->mod_ver = SBRIDGE_REVISION;
- mci->dev_name = pci_name(pdev);
+ mci->ctl_name = kasprintf(GFP_KERNEL, "Sandy Bridge Socket#%d", mci->mc_idx);
+ mci->dev_name = pci_name(sbridge_dev->pdev[0]);
mci->ctl_page_to_phys = NULL;
/* Set the function pointer to an actual operation function */
mci->edac_check = sbridge_check_error;
- pvt->info.type = type;
- if (type == IVY_BRIDGE) {
- pvt->info.rankcfgr = IB_RANK_CFG_A;
- pvt->info.get_tolm = ibridge_get_tolm;
- pvt->info.get_tohm = ibridge_get_tohm;
- pvt->info.dram_rule = ibridge_dram_rule;
- pvt->info.max_sad = ARRAY_SIZE(ibridge_dram_rule);
- pvt->info.interleave_list = ibridge_interleave_list;
- pvt->info.max_interleave = ARRAY_SIZE(ibridge_interleave_list);
- pvt->info.interleave_pkg = ibridge_interleave_pkg;
- mci->ctl_name = kasprintf(GFP_KERNEL, "Ivy Bridge Socket#%d", mci->mc_idx);
-
- /* Store pci devices at mci for faster access */
- rc = ibridge_mci_bind_devs(mci, sbridge_dev);
- if (unlikely(rc < 0))
- goto fail0;
- } else {
- pvt->info.rankcfgr = SB_RANK_CFG_A;
- pvt->info.get_tolm = sbridge_get_tolm;
- pvt->info.get_tohm = sbridge_get_tohm;
- pvt->info.dram_rule = sbridge_dram_rule;
- pvt->info.max_sad = ARRAY_SIZE(sbridge_dram_rule);
- pvt->info.interleave_list = sbridge_interleave_list;
- pvt->info.max_interleave = ARRAY_SIZE(sbridge_interleave_list);
- pvt->info.interleave_pkg = sbridge_interleave_pkg;
- mci->ctl_name = kasprintf(GFP_KERNEL, "Sandy Bridge Socket#%d", mci->mc_idx);
-
- /* Store pci devices at mci for faster access */
- rc = sbridge_mci_bind_devs(mci, sbridge_dev);
- if (unlikely(rc < 0))
- goto fail0;
- }
-
+ /* Store pci devices at mci for faster access */
+ rc = mci_bind_devs(mci, sbridge_dev);
+ if (unlikely(rc < 0))
+ goto fail0;
/* Get dimm basic config and the memory layout */
get_dimm_config(mci);
get_memory_layout(mci);
/* record ptr to the generic device */
- mci->pdev = &pdev->dev;
+ mci->pdev = &sbridge_dev->pdev[0]->dev;
/* add this new MC control structure to EDAC's list of MCs */
if (unlikely(edac_mc_add_mc(mci))) {
@@ -2030,7 +1702,6 @@ static int sbridge_probe(struct pci_dev *pdev, const struct pci_device_id *id)
int rc;
u8 mc, num_mc = 0;
struct sbridge_dev *sbridge_dev;
- enum type type;
/* get the pci devices we want to reserve for our use */
mutex_lock(&sbridge_edac_lock);
@@ -2044,13 +1715,7 @@ static int sbridge_probe(struct pci_dev *pdev, const struct pci_device_id *id)
}
probed++;
- if (pdev->device == PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TA) {
- rc = sbridge_get_all_devices(&num_mc, pci_dev_descr_ibridge_table);
- type = IVY_BRIDGE;
- } else {
- rc = sbridge_get_all_devices(&num_mc, pci_dev_descr_sbridge_table);
- type = SANDY_BRIDGE;
- }
+ rc = sbridge_get_all_devices(&num_mc);
if (unlikely(rc < 0))
goto fail0;
mc = 0;
@@ -2059,7 +1724,7 @@ static int sbridge_probe(struct pci_dev *pdev, const struct pci_device_id *id)
edac_dbg(0, "Registering MC#%d (%d of %d)\n",
mc, mc + 1, num_mc);
sbridge_dev->mc = mc++;
- rc = sbridge_register_mci(sbridge_dev, type);
+ rc = sbridge_register_mci(sbridge_dev);
if (unlikely(rc < 0))
goto fail1;
}
@@ -2174,5 +1839,5 @@ MODULE_PARM_DESC(edac_op_state, "EDAC Error Reporting state: 0=Poll,1=NMI");
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)");
-MODULE_DESCRIPTION("MC Driver for Intel Sandy Bridge and Ivy Bridge memory controllers - "
+MODULE_DESCRIPTION("MC Driver for Intel Sandy Bridge memory controllers - "
SBRIDGE_REVISION);