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:
 "Two edac fixes:

   - i7300_edac currently reports a wrong number of DIMMs when the
     memory controller is in single channel mode

   - on some Sandy Bridge machines, the EDAC driver bails out as one of
     the PCI IDs used by the driver is hidden by BIOS.  As the driver
     uses it only to detect the type of memory, make it optional at the
     driver"

* 'linux_next' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-edac:
  edac: sb_edac.c should not require prescence of IMC_DDRIO device
  i7300_edac: Fix memory detection in single mode
  • Loading branch information
Linus Torvalds committed Apr 30, 2013
2 parents 240c3c3 + de4772c commit e282329
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 28 deletions.
19 changes: 15 additions & 4 deletions drivers/edac/i7300_edac.c
Original file line number Diff line number Diff line change
Expand Up @@ -750,15 +750,23 @@ static int i7300_init_csrows(struct mem_ctl_info *mci)
struct i7300_dimm_info *dinfo;
int rc = -ENODEV;
int mtr;
int ch, branch, slot, channel;
int ch, branch, slot, channel, max_channel, max_branch;
struct dimm_info *dimm;

pvt = mci->pvt_info;

edac_dbg(2, "Memory Technology Registers:\n");

if (IS_SINGLE_MODE(pvt->mc_settings_a)) {
max_branch = 1;
max_channel = 1;
} else {
max_branch = MAX_BRANCHES;
max_channel = MAX_CH_PER_BRANCH;
}

/* Get the AMB present registers for the four channels */
for (branch = 0; branch < MAX_BRANCHES; branch++) {
for (branch = 0; branch < max_branch; branch++) {
/* Read and dump branch 0's MTRs */
channel = to_channel(0, branch);
pci_read_config_word(pvt->pci_dev_2x_0_fbd_branch[branch],
Expand All @@ -767,6 +775,9 @@ static int i7300_init_csrows(struct mem_ctl_info *mci)
edac_dbg(2, "\t\tAMB-present CH%d = 0x%x:\n",
channel, pvt->ambpresent[channel]);

if (max_channel == 1)
continue;

channel = to_channel(1, branch);
pci_read_config_word(pvt->pci_dev_2x_0_fbd_branch[branch],
AMBPRESENT_1,
Expand All @@ -778,11 +789,11 @@ static int i7300_init_csrows(struct mem_ctl_info *mci)
/* Get the set of MTR[0-7] regs by each branch */
for (slot = 0; slot < MAX_SLOTS; slot++) {
int where = mtr_regs[slot];
for (branch = 0; branch < MAX_BRANCHES; branch++) {
for (branch = 0; branch < max_branch; branch++) {
pci_read_config_word(pvt->pci_dev_2x_0_fbd_branch[branch],
where,
&pvt->mtr[slot][branch]);
for (ch = 0; ch < MAX_CH_PER_BRANCH; ch++) {
for (ch = 0; ch < max_channel; ch++) {
int channel = to_channel(ch, branch);

dimm = EDAC_DIMM_PTR(mci->layers, mci->dimms,
Expand Down
53 changes: 29 additions & 24 deletions drivers/edac/sb_edac.c
Original file line number Diff line number Diff line change
Expand Up @@ -331,30 +331,31 @@ struct sbridge_pvt {
u64 tolm, tohm;
};

#define PCI_DESCR(device, function, device_id) \
.dev = (device), \
.func = (function), \
.dev_id = (device_id)
#define PCI_DESCR(device, function, device_id, opt) \
.dev = (device), \
.func = (function), \
.dev_id = (device_id), \
.optional = opt

static const struct pci_id_descr pci_dev_descr_sbridge[] = {
/* Processor Home Agent */
{ PCI_DESCR(14, 0, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_HA0) },
{ PCI_DESCR(14, 0, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_HA0, 0) },

/* Memory controller */
{ PCI_DESCR(15, 0, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TA) },
{ PCI_DESCR(15, 1, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_RAS) },
{ PCI_DESCR(15, 2, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD0) },
{ PCI_DESCR(15, 3, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD1) },
{ PCI_DESCR(15, 4, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD2) },
{ PCI_DESCR(15, 5, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD3) },
{ PCI_DESCR(17, 0, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_DDRIO) },
{ PCI_DESCR(15, 0, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TA, 0) },
{ PCI_DESCR(15, 1, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_RAS, 0) },
{ PCI_DESCR(15, 2, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD0, 0) },
{ PCI_DESCR(15, 3, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD1, 0) },
{ PCI_DESCR(15, 4, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD2, 0) },
{ PCI_DESCR(15, 5, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD3, 0) },
{ PCI_DESCR(17, 0, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_DDRIO, 1) },

/* System Address Decoder */
{ PCI_DESCR(12, 6, PCI_DEVICE_ID_INTEL_SBRIDGE_SAD0) },
{ PCI_DESCR(12, 7, PCI_DEVICE_ID_INTEL_SBRIDGE_SAD1) },
{ PCI_DESCR(12, 6, PCI_DEVICE_ID_INTEL_SBRIDGE_SAD0, 0) },
{ PCI_DESCR(12, 7, PCI_DEVICE_ID_INTEL_SBRIDGE_SAD1, 0) },

/* Broadcast Registers */
{ PCI_DESCR(13, 6, PCI_DEVICE_ID_INTEL_SBRIDGE_BR) },
{ PCI_DESCR(13, 6, PCI_DEVICE_ID_INTEL_SBRIDGE_BR, 0) },
};

#define PCI_ID_TABLE_ENTRY(A) { .descr=A, .n_devs = ARRAY_SIZE(A) }
Expand Down Expand Up @@ -556,14 +557,19 @@ static int get_dimm_config(struct mem_ctl_info *mci)
pvt->is_close_pg = false;
}

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");
mtype = MEM_RDDR3;
if (pvt->pci_ddrio) {
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");
mtype = MEM_RDDR3;
} else {
edac_dbg(0, "Memory is unregistered\n");
mtype = MEM_DDR3;
}
} else {
edac_dbg(0, "Memory is unregistered\n");
mtype = MEM_DDR3;
edac_dbg(0, "Cannot determine memory type\n");
mtype = MEM_UNKNOWN;
}

/* On all supported DDR3 DIMM types, there are 8 banks available */
Expand Down Expand Up @@ -1303,8 +1309,7 @@ static int mci_bind_devs(struct mem_ctl_info *mci,

/* Check if everything were registered */
if (!pvt->pci_sad0 || !pvt->pci_sad1 || !pvt->pci_ha0 ||
!pvt-> pci_tad || !pvt->pci_ras || !pvt->pci_ta ||
!pvt->pci_ddrio)
!pvt-> pci_tad || !pvt->pci_ras || !pvt->pci_ta)
goto enodev;

for (i = 0; i < NUM_CHANNELS; i++) {
Expand Down

0 comments on commit e282329

Please sign in to comment.