Merge branch 'linux_next' of git://git.kernel.org/pub/scm/linux/kernel/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
This commit is contained in:
Коммит
e2823299cd
|
@ -750,15 +750,23 @@ static int i7300_init_csrows(struct mem_ctl_info *mci)
|
||||||
struct i7300_dimm_info *dinfo;
|
struct i7300_dimm_info *dinfo;
|
||||||
int rc = -ENODEV;
|
int rc = -ENODEV;
|
||||||
int mtr;
|
int mtr;
|
||||||
int ch, branch, slot, channel;
|
int ch, branch, slot, channel, max_channel, max_branch;
|
||||||
struct dimm_info *dimm;
|
struct dimm_info *dimm;
|
||||||
|
|
||||||
pvt = mci->pvt_info;
|
pvt = mci->pvt_info;
|
||||||
|
|
||||||
edac_dbg(2, "Memory Technology Registers:\n");
|
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 */
|
/* 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 */
|
/* Read and dump branch 0's MTRs */
|
||||||
channel = to_channel(0, branch);
|
channel = to_channel(0, branch);
|
||||||
pci_read_config_word(pvt->pci_dev_2x_0_fbd_branch[branch],
|
pci_read_config_word(pvt->pci_dev_2x_0_fbd_branch[branch],
|
||||||
|
@ -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",
|
edac_dbg(2, "\t\tAMB-present CH%d = 0x%x:\n",
|
||||||
channel, pvt->ambpresent[channel]);
|
channel, pvt->ambpresent[channel]);
|
||||||
|
|
||||||
|
if (max_channel == 1)
|
||||||
|
continue;
|
||||||
|
|
||||||
channel = to_channel(1, branch);
|
channel = to_channel(1, branch);
|
||||||
pci_read_config_word(pvt->pci_dev_2x_0_fbd_branch[branch],
|
pci_read_config_word(pvt->pci_dev_2x_0_fbd_branch[branch],
|
||||||
AMBPRESENT_1,
|
AMBPRESENT_1,
|
||||||
|
@ -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 */
|
/* Get the set of MTR[0-7] regs by each branch */
|
||||||
for (slot = 0; slot < MAX_SLOTS; slot++) {
|
for (slot = 0; slot < MAX_SLOTS; slot++) {
|
||||||
int where = mtr_regs[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],
|
pci_read_config_word(pvt->pci_dev_2x_0_fbd_branch[branch],
|
||||||
where,
|
where,
|
||||||
&pvt->mtr[slot][branch]);
|
&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);
|
int channel = to_channel(ch, branch);
|
||||||
|
|
||||||
dimm = EDAC_DIMM_PTR(mci->layers, mci->dimms,
|
dimm = EDAC_DIMM_PTR(mci->layers, mci->dimms,
|
||||||
|
|
|
@ -331,30 +331,31 @@ struct sbridge_pvt {
|
||||||
u64 tolm, tohm;
|
u64 tolm, tohm;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define PCI_DESCR(device, function, device_id) \
|
#define PCI_DESCR(device, function, device_id, opt) \
|
||||||
.dev = (device), \
|
.dev = (device), \
|
||||||
.func = (function), \
|
.func = (function), \
|
||||||
.dev_id = (device_id)
|
.dev_id = (device_id), \
|
||||||
|
.optional = opt
|
||||||
|
|
||||||
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(14, 0, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_HA0) },
|
{ PCI_DESCR(14, 0, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_HA0, 0) },
|
||||||
|
|
||||||
/* Memory controller */
|
/* Memory controller */
|
||||||
{ PCI_DESCR(15, 0, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TA) },
|
{ PCI_DESCR(15, 0, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TA, 0) },
|
||||||
{ PCI_DESCR(15, 1, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_RAS) },
|
{ PCI_DESCR(15, 1, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_RAS, 0) },
|
||||||
{ PCI_DESCR(15, 2, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD0) },
|
{ PCI_DESCR(15, 2, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD0, 0) },
|
||||||
{ PCI_DESCR(15, 3, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD1) },
|
{ PCI_DESCR(15, 3, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD1, 0) },
|
||||||
{ PCI_DESCR(15, 4, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD2) },
|
{ PCI_DESCR(15, 4, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD2, 0) },
|
||||||
{ PCI_DESCR(15, 5, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD3) },
|
{ PCI_DESCR(15, 5, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD3, 0) },
|
||||||
{ PCI_DESCR(17, 0, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_DDRIO) },
|
{ PCI_DESCR(17, 0, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_DDRIO, 1) },
|
||||||
|
|
||||||
/* System Address Decoder */
|
/* System Address Decoder */
|
||||||
{ PCI_DESCR(12, 6, PCI_DEVICE_ID_INTEL_SBRIDGE_SAD0) },
|
{ PCI_DESCR(12, 6, PCI_DEVICE_ID_INTEL_SBRIDGE_SAD0, 0) },
|
||||||
{ PCI_DESCR(12, 7, PCI_DEVICE_ID_INTEL_SBRIDGE_SAD1) },
|
{ PCI_DESCR(12, 7, PCI_DEVICE_ID_INTEL_SBRIDGE_SAD1, 0) },
|
||||||
|
|
||||||
/* Broadcast Registers */
|
/* 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) }
|
#define PCI_ID_TABLE_ENTRY(A) { .descr=A, .n_devs = ARRAY_SIZE(A) }
|
||||||
|
@ -556,14 +557,19 @@ static int get_dimm_config(struct mem_ctl_info *mci)
|
||||||
pvt->is_close_pg = false;
|
pvt->is_close_pg = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
pci_read_config_dword(pvt->pci_ddrio, RANK_CFG_A, ®);
|
if (pvt->pci_ddrio) {
|
||||||
if (IS_RDIMM_ENABLED(reg)) {
|
pci_read_config_dword(pvt->pci_ddrio, RANK_CFG_A, ®);
|
||||||
/* FIXME: Can also be LRDIMM */
|
if (IS_RDIMM_ENABLED(reg)) {
|
||||||
edac_dbg(0, "Memory is registered\n");
|
/* FIXME: Can also be LRDIMM */
|
||||||
mtype = MEM_RDDR3;
|
edac_dbg(0, "Memory is registered\n");
|
||||||
|
mtype = MEM_RDDR3;
|
||||||
|
} else {
|
||||||
|
edac_dbg(0, "Memory is unregistered\n");
|
||||||
|
mtype = MEM_DDR3;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
edac_dbg(0, "Memory is unregistered\n");
|
edac_dbg(0, "Cannot determine memory type\n");
|
||||||
mtype = MEM_DDR3;
|
mtype = MEM_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* On all supported DDR3 DIMM types, there are 8 banks available */
|
/* On all supported DDR3 DIMM types, there are 8 banks available */
|
||||||
|
@ -1303,8 +1309,7 @@ static int 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_ha0 ||
|
||||||
!pvt-> pci_tad || !pvt->pci_ras || !pvt->pci_ta ||
|
!pvt-> pci_tad || !pvt->pci_ras || !pvt->pci_ta)
|
||||||
!pvt->pci_ddrio)
|
|
||||||
goto enodev;
|
goto enodev;
|
||||||
|
|
||||||
for (i = 0; i < NUM_CHANNELS; i++) {
|
for (i = 0; i < NUM_CHANNELS; i++) {
|
||||||
|
|
Загрузка…
Ссылка в новой задаче