[PATCH 2.6.28 3/3] EDAC: Add support for i82865P/PE chipsets

From: Michał Mirosław
Date: Thu Jan 01 2009 - 14:06:40 EST


i82865P have the same registers as i82875P but without support for ECC
memory modules, so this change only allows to see some information from
/sys/devices/system/edac, but no memory errors will be detected.
Checked in chipset's datasheet and tested on HP nx9500 laptop.

This is a actually the same code as previous version. I resend it for
completeness, as it depends on previous patches in this series.

Signed-off-by: Michał Mirosław <mirq-linux@xxxxxxxxxxxx>

--- tmp/drivers/edac/i82875p_edac.c 2008-12-07 13:02:32.000000000 +0100
+++ rechot/drivers/edac/i82875p_edac.c 2008-12-07 13:01:37.000000000 +0100
@@ -30,6 +30,10 @@
#define i82875p_mc_printk(mci, level, fmt, arg...) \
edac_mc_chipset_printk(mci, level, "i82875p", fmt, ##arg)

+#ifndef PCI_DEVICE_ID_INTEL_82865_6
+#define PCI_DEVICE_ID_INTEL_82865_6 0x2576
+#endif /* PCI_DEVICE_ID_INTEL_82865_6 */
+
#ifndef PCI_DEVICE_ID_INTEL_82875_6
#define PCI_DEVICE_ID_INTEL_82875_6 0x257e
#endif /* PCI_DEVICE_ID_INTEL_82875_6 */
@@ -150,6 +154,7 @@

enum i82875p_chips {
I82875P = 0,
+ I82865P = 1, /* this one lacks support for ECC memory */
};

struct i82875p_pvt {
@@ -159,6 +164,9 @@

struct i82875p_dev_info {
const char *ctl_name;
+ unsigned long edac_ctl_cap;
+ void (*check)(struct mem_ctl_info *mci);
+ unsigned long drc_mask; /* valid DRC register bits according to datasheet */
};

struct i82875p_error_info {
@@ -169,11 +177,6 @@
u16 errsts2;
};

-static const struct i82875p_dev_info i82875p_devs[] = {
- [I82875P] = {
- .ctl_name = "i82875p"},
-};
-
static struct edac_pci_ctl_info *i82875p_pci;

static void i82875p_get_error_info(struct mem_ctl_info *mci,
@@ -253,6 +256,26 @@
i82875p_process_error_info(mci, &info, 1);
}

+static void i82865p_check(struct mem_ctl_info *mci)
+{
+}
+
+static const struct i82875p_dev_info i82875p_devs[] = {
+ [I82875P] = {
+ .ctl_name = "i82875p",
+ .edac_ctl_cap = EDAC_FLAG_NONE|EDAC_FLAG_SECDED,
+ .check = i82875p_check,
+ .drc_mask = 0x20660773,
+ },
+ [I82865P] = {
+ .ctl_name = "i82865p",
+ .edac_ctl_cap = EDAC_FLAG_NONE,
+ .check = i82865p_check,
+ .drc_mask = 0x20600773,
+ },
+};
+
+
/* Return 1 if dual channel mode is active. Else return 0. */
static inline int dual_channel_active(u32 drc)
{
@@ -318,7 +341,7 @@
if (!ovrfl_window)
return -EBUSY;

- drc = readl(ovrfl_window + I82875P_DRC);
+ drc = readl(ovrfl_window + I82875P_DRC) & i82875p_devs[dev_idx].drc_mask;
nr_chans = dual_channel_active(drc) + 1;
mci = edac_mc_alloc(sizeof(*pvt), I82875P_NR_CSROWS(nr_chans),
nr_chans, 0);
@@ -334,13 +357,13 @@
debugf3("%s(): init mci\n", __func__);
mci->dev = &ovrfl_pdev->dev;
mci->mtype_cap = MEM_FLAG_DDR;
- mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED;
+ mci->edac_ctl_cap = i82875p_devs[dev_idx].edac_ctl_cap;
mci->edac_cap = EDAC_FLAG_UNKNOWN;
mci->mod_name = EDAC_MOD_STR;
mci->mod_ver = I82875P_REVISION;
mci->ctl_name = i82875p_devs[dev_idx].ctl_name;
mci->dev_name = pci_name(mci_pdev);
- mci->edac_check = i82875p_check;
+ mci->edac_check = i82875p_devs[dev_idx].check;
mci->ctl_page_to_phys = NULL;

debugf3("%s(): init pvt\n", __func__);
@@ -429,8 +452,6 @@

static void __devexit i82875p_remove_one(struct pci_dev *pdev)
{
- int mci_devfn = PCI_DEVFN(PCI_SLOT(pdev->devfn), 0);
- struct pci_dev *mci_pdev;
struct mem_ctl_info *mci;
struct i82875p_pvt *pvt;

@@ -454,6 +475,7 @@

static DEFINE_PCI_DEVICE_TABLE(i82875p_pci_tbl) = {
{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82875_6), I82875P },
+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82865_6), I82865P },
{ 0, } /* 0 terminated list. */
};

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/