Skip to content

Commit

Permalink
Merge branch 'linux_next' of git://git.kernel.org/pub/scm/linux/kerne…
Browse files Browse the repository at this point in the history
…l/git/mchehab/linux-edac

Pull EDAC fixes from Mauro Carvalho Chehab:
 "A series of EDAC driver fixes.  It also has one core fix at the
  documentation, and a rename patch, fixing the name of the struct that
  contains the rank information."

* 'linux_next' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-edac:
  edac: rename channel_info to rank_info
  i5400_edac: Avoid calling pci_put_device() twice
  edac: i5100 ack error detection register after each read
  edac: i5100 fix erroneous define for M1Err
  edac: sb_edac: Fix a wrong value setting for the previous value
  edac: sb_edac: Fix a INTERLEAVE_MODE() misuse
  edac: sb_edac: Let the driver depend on PCI_MMCONFIG
  edac: Improve the comments to better describe the memory concepts
  edac/ppc4xx_edac: Fix compilation
  Fix sb_edac compilation with 32 bits kernels
  • Loading branch information
Linus Torvalds committed Mar 28, 2012
2 parents 61e5191 + a4b4be3 commit f0f3680
Show file tree
Hide file tree
Showing 7 changed files with 208 additions and 102 deletions.
2 changes: 1 addition & 1 deletion drivers/edac/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ config EDAC_I7300
config EDAC_SBRIDGE
tristate "Intel Sandy-Bridge Integrated MC"
depends on EDAC_MM_EDAC && PCI && X86_64 && X86_MCE_INTEL
depends on EXPERIMENTAL
depends on PCI_MMCONFIG && EXPERIMENTAL
help
Support for error detection and correction the Intel
Sandy Bridge Integrated Memory Controller.
Expand Down
6 changes: 3 additions & 3 deletions drivers/edac/edac_mc.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ static LIST_HEAD(mc_devices);

#ifdef CONFIG_EDAC_DEBUG

static void edac_mc_dump_channel(struct channel_info *chan)
static void edac_mc_dump_channel(struct rank_info *chan)
{
debugf4("\tchannel = %p\n", chan);
debugf4("\tchannel->chan_idx = %d\n", chan->chan_idx);
Expand Down Expand Up @@ -156,7 +156,7 @@ struct mem_ctl_info *edac_mc_alloc(unsigned sz_pvt, unsigned nr_csrows,
{
struct mem_ctl_info *mci;
struct csrow_info *csi, *csrow;
struct channel_info *chi, *chp, *chan;
struct rank_info *chi, *chp, *chan;
void *pvt;
unsigned size;
int row, chn;
Expand All @@ -181,7 +181,7 @@ struct mem_ctl_info *edac_mc_alloc(unsigned sz_pvt, unsigned nr_csrows,
* rather than an imaginary chunk of memory located at address 0.
*/
csi = (struct csrow_info *)(((char *)mci) + ((unsigned long)csi));
chi = (struct channel_info *)(((char *)mci) + ((unsigned long)chi));
chi = (struct rank_info *)(((char *)mci) + ((unsigned long)chi));
pvt = sz_pvt ? (((char *)mci) + ((unsigned long)pvt)) : NULL;

/* setup index and various internal pointers */
Expand Down
13 changes: 5 additions & 8 deletions drivers/edac/i5100_edac.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@
#define I5100_FERR_NF_MEM_M6ERR_MASK (1 << 6)
#define I5100_FERR_NF_MEM_M5ERR_MASK (1 << 5)
#define I5100_FERR_NF_MEM_M4ERR_MASK (1 << 4)
#define I5100_FERR_NF_MEM_M1ERR_MASK 1
#define I5100_FERR_NF_MEM_M1ERR_MASK (1 << 1)
#define I5100_FERR_NF_MEM_ANY_MASK \
(I5100_FERR_NF_MEM_M16ERR_MASK | \
I5100_FERR_NF_MEM_M15ERR_MASK | \
Expand Down Expand Up @@ -535,23 +535,20 @@ static void i5100_read_log(struct mem_ctl_info *mci, int chan,
static void i5100_check_error(struct mem_ctl_info *mci)
{
struct i5100_priv *priv = mci->pvt_info;
u32 dw;

u32 dw, dw2;

pci_read_config_dword(priv->mc, I5100_FERR_NF_MEM, &dw);
if (i5100_ferr_nf_mem_any(dw)) {
u32 dw2;

pci_read_config_dword(priv->mc, I5100_NERR_NF_MEM, &dw2);
if (dw2)
pci_write_config_dword(priv->mc, I5100_NERR_NF_MEM,
dw2);
pci_write_config_dword(priv->mc, I5100_FERR_NF_MEM, dw);

i5100_read_log(mci, i5100_ferr_nf_mem_chan_indx(dw),
i5100_ferr_nf_mem_any(dw),
i5100_nerr_nf_mem_any(dw2));

pci_write_config_dword(priv->mc, I5100_NERR_NF_MEM, dw2);
}
pci_write_config_dword(priv->mc, I5100_FERR_NF_MEM, dw);
}

/* The i5100 chipset will scrub the entire memory once, then
Expand Down
54 changes: 38 additions & 16 deletions drivers/edac/i5400_edac.c
Original file line number Diff line number Diff line change
Expand Up @@ -735,31 +735,50 @@ static int i5400_get_devices(struct mem_ctl_info *mci, int dev_idx)

/* Attempt to 'get' the MCH register we want */
pdev = NULL;
while (!pvt->branchmap_werrors || !pvt->fsb_error_regs) {
while (1) {
pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
PCI_DEVICE_ID_INTEL_5400_ERR, pdev);
if (!pdev) {
/* End of list, leave */
i5400_printk(KERN_ERR,
"'system address,Process Bus' "
"device not found:"
"vendor 0x%x device 0x%x ERR funcs "
"vendor 0x%x device 0x%x ERR func 1 "
"(broken BIOS?)\n",
PCI_VENDOR_ID_INTEL,
PCI_DEVICE_ID_INTEL_5400_ERR);
goto error;
return -ENODEV;
}

/* Store device 16 funcs 1 and 2 */
switch (PCI_FUNC(pdev->devfn)) {
case 1:
pvt->branchmap_werrors = pdev;
break;
case 2:
pvt->fsb_error_regs = pdev;
/* Store device 16 func 1 */
if (PCI_FUNC(pdev->devfn) == 1)
break;
}
pvt->branchmap_werrors = pdev;

pdev = NULL;
while (1) {
pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
PCI_DEVICE_ID_INTEL_5400_ERR, pdev);
if (!pdev) {
/* End of list, leave */
i5400_printk(KERN_ERR,
"'system address,Process Bus' "
"device not found:"
"vendor 0x%x device 0x%x ERR func 2 "
"(broken BIOS?)\n",
PCI_VENDOR_ID_INTEL,
PCI_DEVICE_ID_INTEL_5400_ERR);

pci_dev_put(pvt->branchmap_werrors);
return -ENODEV;
}

/* Store device 16 func 2 */
if (PCI_FUNC(pdev->devfn) == 2)
break;
}
pvt->fsb_error_regs = pdev;

debugf1("System Address, processor bus- PCI Bus ID: %s %x:%x\n",
pci_name(pvt->system_address),
Expand All @@ -778,7 +797,10 @@ static int i5400_get_devices(struct mem_ctl_info *mci, int dev_idx)
"MC: 'BRANCH 0' device not found:"
"vendor 0x%x device 0x%x Func 0 (broken BIOS?)\n",
PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_5400_FBD0);
goto error;

pci_dev_put(pvt->fsb_error_regs);
pci_dev_put(pvt->branchmap_werrors);
return -ENODEV;
}

/* If this device claims to have more than 2 channels then
Expand All @@ -796,14 +818,14 @@ static int i5400_get_devices(struct mem_ctl_info *mci, int dev_idx)
"(broken BIOS?)\n",
PCI_VENDOR_ID_INTEL,
PCI_DEVICE_ID_INTEL_5400_FBD1);
goto error;

pci_dev_put(pvt->branch_0);
pci_dev_put(pvt->fsb_error_regs);
pci_dev_put(pvt->branchmap_werrors);
return -ENODEV;
}

return 0;

error:
i5400_put_devices(mci);
return -ENODEV;
}

/*
Expand Down
4 changes: 2 additions & 2 deletions drivers/edac/ppc4xx_edac.c
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ struct ppc4xx_ecc_status {

/* Function Prototypes */

static int ppc4xx_edac_probe(struct platform_device *device)
static int ppc4xx_edac_probe(struct platform_device *device);
static int ppc4xx_edac_remove(struct platform_device *device);

/* Global Variables */
Expand Down Expand Up @@ -1068,7 +1068,7 @@ ppc4xx_edac_mc_init(struct mem_ctl_info *mci,

mci->mod_name = PPC4XX_EDAC_MODULE_NAME;
mci->mod_ver = PPC4XX_EDAC_MODULE_REVISION;
mci->ctl_name = match->compatible,
mci->ctl_name = ppc4xx_edac_match->compatible,
mci->dev_name = np->full_name;

/* Initialize callbacks */
Expand Down
52 changes: 31 additions & 21 deletions drivers/edac/sb_edac.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include <linux/mmzone.h>
#include <linux/smp.h>
#include <linux/bitmap.h>
#include <linux/math64.h>
#include <asm/processor.h>
#include <asm/mce.h>

Expand Down Expand Up @@ -670,6 +671,7 @@ static void get_memory_layout(const struct mem_ctl_info *mci)
u32 reg;
u64 limit, prv = 0;
u64 tmp_mb;
u32 mb, kb;
u32 rir_way;

/*
Expand All @@ -682,17 +684,19 @@ static void get_memory_layout(const struct mem_ctl_info *mci)
pvt->tolm = GET_TOLM(reg);
tmp_mb = (1 + pvt->tolm) >> 20;

debugf0("TOLM: %Lu.%03Lu GB (0x%016Lx)\n",
tmp_mb / 1000, tmp_mb % 1000, (u64)pvt->tolm);
mb = div_u64_rem(tmp_mb, 1000, &kb);
debugf0("TOLM: %u.%03u GB (0x%016Lx)\n",
mb, kb, (u64)pvt->tolm);

/* Address range is already 45:25 */
pci_read_config_dword(pvt->pci_sad1, TOHM,
&reg);
pvt->tohm = GET_TOHM(reg);
tmp_mb = (1 + pvt->tohm) >> 20;

debugf0("TOHM: %Lu.%03Lu GB (0x%016Lx)",
tmp_mb / 1000, tmp_mb % 1000, (u64)pvt->tohm);
mb = div_u64_rem(tmp_mb, 1000, &kb);
debugf0("TOHM: %u.%03u GB (0x%016Lx)",
mb, kb, (u64)pvt->tohm);

/*
* Step 2) Get SAD range and SAD Interleave list
Expand All @@ -714,10 +718,11 @@ static void get_memory_layout(const struct mem_ctl_info *mci)
break;

tmp_mb = (limit + 1) >> 20;
debugf0("SAD#%d %s up to %Lu.%03Lu GB (0x%016Lx) %s reg=0x%08x\n",
mb = div_u64_rem(tmp_mb, 1000, &kb);
debugf0("SAD#%d %s up to %u.%03u GB (0x%016Lx) %s reg=0x%08x\n",
n_sads,
get_dram_attr(reg),
tmp_mb / 1000, tmp_mb % 1000,
mb, kb,
((u64)tmp_mb) << 20L,
INTERLEAVE_MODE(reg) ? "Interleave: 8:6" : "Interleave: [8:6]XOR[18:16]",
reg);
Expand Down Expand Up @@ -747,8 +752,9 @@ static void get_memory_layout(const struct mem_ctl_info *mci)
break;
tmp_mb = (limit + 1) >> 20;

debugf0("TAD#%d: up to %Lu.%03Lu GB (0x%016Lx), socket interleave %d, memory interleave %d, TGT: %d, %d, %d, %d, reg=0x%08x\n",
n_tads, tmp_mb / 1000, tmp_mb % 1000,
mb = div_u64_rem(tmp_mb, 1000, &kb);
debugf0("TAD#%d: up to %u.%03u GB (0x%016Lx), socket interleave %d, memory interleave %d, TGT: %d, %d, %d, %d, reg=0x%08x\n",
n_tads, mb, kb,
((u64)tmp_mb) << 20L,
(u32)TAD_SOCK(reg),
(u32)TAD_CH(reg),
Expand All @@ -757,7 +763,7 @@ static void get_memory_layout(const struct mem_ctl_info *mci)
(u32)TAD_TGT2(reg),
(u32)TAD_TGT3(reg),
reg);
prv = tmp_mb;
prv = limit;
}

/*
Expand All @@ -771,9 +777,10 @@ static void get_memory_layout(const struct mem_ctl_info *mci)
tad_ch_nilv_offset[j],
&reg);
tmp_mb = TAD_OFFSET(reg) >> 20;
debugf0("TAD CH#%d, offset #%d: %Lu.%03Lu GB (0x%016Lx), reg=0x%08x\n",
mb = div_u64_rem(tmp_mb, 1000, &kb);
debugf0("TAD CH#%d, offset #%d: %u.%03u GB (0x%016Lx), reg=0x%08x\n",
i, j,
tmp_mb / 1000, tmp_mb % 1000,
mb, kb,
((u64)tmp_mb) << 20L,
reg);
}
Expand All @@ -795,9 +802,10 @@ static void get_memory_layout(const struct mem_ctl_info *mci)

tmp_mb = RIR_LIMIT(reg) >> 20;
rir_way = 1 << RIR_WAY(reg);
debugf0("CH#%d RIR#%d, limit: %Lu.%03Lu GB (0x%016Lx), way: %d, reg=0x%08x\n",
mb = div_u64_rem(tmp_mb, 1000, &kb);
debugf0("CH#%d RIR#%d, limit: %u.%03u GB (0x%016Lx), way: %d, reg=0x%08x\n",
i, j,
tmp_mb / 1000, tmp_mb % 1000,
mb, kb,
((u64)tmp_mb) << 20L,
rir_way,
reg);
Expand All @@ -808,9 +816,10 @@ static void get_memory_layout(const struct mem_ctl_info *mci)
&reg);
tmp_mb = RIR_OFFSET(reg) << 6;

debugf0("CH#%d RIR#%d INTL#%d, offset %Lu.%03Lu GB (0x%016Lx), tgt: %d, reg=0x%08x\n",
mb = div_u64_rem(tmp_mb, 1000, &kb);
debugf0("CH#%d RIR#%d INTL#%d, offset %u.%03u GB (0x%016Lx), tgt: %d, reg=0x%08x\n",
i, j, k,
tmp_mb / 1000, tmp_mb % 1000,
mb, kb,
((u64)tmp_mb) << 20L,
(u32)RIR_RNK_TGT(reg),
reg);
Expand Down Expand Up @@ -848,6 +857,7 @@ static int get_memory_error_data(struct mem_ctl_info *mci,
u8 ch_way,sck_way;
u32 tad_offset;
u32 rir_way;
u32 mb, kb;
u64 ch_addr, offset, limit, prv = 0;


Expand All @@ -858,7 +868,7 @@ static int get_memory_error_data(struct mem_ctl_info *mci,
* range (e. g. VGA addresses). It is unlikely, however, that the
* memory controller would generate an error on that range.
*/
if ((addr > (u64) pvt->tolm) && (addr < (1L << 32))) {
if ((addr > (u64) pvt->tolm) && (addr < (1LL << 32))) {
sprintf(msg, "Error at TOLM area, on addr 0x%08Lx", addr);
edac_mc_handle_ce_no_info(mci, msg);
return -EINVAL;
Expand Down Expand Up @@ -913,7 +923,7 @@ static int get_memory_error_data(struct mem_ctl_info *mci,
addr,
limit,
sad_way + 7,
INTERLEAVE_MODE(reg) ? "" : "XOR[18:16]");
interleave_mode ? "" : "XOR[18:16]");
if (interleave_mode)
idx = ((addr >> 6) ^ (addr >> 16)) & 7;
else
Expand Down Expand Up @@ -1053,7 +1063,7 @@ static int get_memory_error_data(struct mem_ctl_info *mci,
ch_addr = addr & 0x7f;
/* Remove socket wayness and remove 6 bits */
addr >>= 6;
addr /= sck_xch;
addr = div_u64(addr, sck_xch);
#if 0
/* Divide by channel way */
addr = addr / ch_way;
Expand All @@ -1073,10 +1083,10 @@ static int get_memory_error_data(struct mem_ctl_info *mci,
continue;

limit = RIR_LIMIT(reg);

debugf0("RIR#%d, limit: %Lu.%03Lu GB (0x%016Lx), way: %d\n",
mb = div_u64_rem(limit >> 20, 1000, &kb);
debugf0("RIR#%d, limit: %u.%03u GB (0x%016Lx), way: %d\n",
n_rir,
(limit >> 20) / 1000, (limit >> 20) % 1000,
mb, kb,
limit,
1 << RIR_WAY(reg));
if (ch_addr <= limit)
Expand Down
Loading

0 comments on commit f0f3680

Please sign in to comment.