EDAC, sb_edac: Check if ECC enabled when at least one DIMM is present
This is based on previous work by Patrick Geary, see Link. Additional cleanups ontop: - Remove the code to read MCMTR from pci_ha1_ta and CHN_TO_HA macro, now that TA0 and TA1 are unified. - Remove get_pdev_same_bus(), since in get_dimm_config() the variable "pvt->pci_ta" for KNL is also ready, we can simply use pci_read_config_dword(pvt->pci_ta, KNL_MCMTR, &pvt->info.mcmtr) to read MCMTR. Signed-off-by: Qiuxu Zhuo <qiuxu.zhuo@intel.com> Cc: linux-edac <linux-edac@vger.kernel.org> Link: https://lkml.kernel.org/r/57884350.1030401@supermicro.com Link: http://lkml.kernel.org/r/20170523000910.87925-1-qiuxu.zhuo@intel.com [ Make __populate_dimms() return int. ] Signed-off-by: Borislav Petkov <bp@suse.de>
This commit is contained in:
parent
3286d3eb90
commit
4d475dde79
1 changed files with 18 additions and 85 deletions
|
@ -1060,79 +1060,6 @@ static int haswell_chan_hash(int idx, u64 addr)
|
|||
return idx;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
Memory check routines
|
||||
****************************************************************************/
|
||||
static struct pci_dev *get_pdev_same_bus(u8 bus, u32 id)
|
||||
{
|
||||
struct pci_dev *pdev = NULL;
|
||||
|
||||
do {
|
||||
pdev = pci_get_device(PCI_VENDOR_ID_INTEL, id, pdev);
|
||||
if (pdev && pdev->bus->number == bus)
|
||||
break;
|
||||
} while (pdev);
|
||||
|
||||
return pdev;
|
||||
}
|
||||
|
||||
/**
|
||||
* check_if_ecc_is_active() - Checks if ECC is active
|
||||
* @bus: Device bus
|
||||
* @type: Memory controller type
|
||||
* returns: 0 in case ECC is active, -ENODEV if it can't be determined or
|
||||
* disabled
|
||||
*/
|
||||
static int check_if_ecc_is_active(const u8 bus, enum type type)
|
||||
{
|
||||
struct pci_dev *pdev = NULL;
|
||||
u32 mcmtr, id;
|
||||
|
||||
switch (type) {
|
||||
case IVY_BRIDGE:
|
||||
id = PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TA;
|
||||
break;
|
||||
case HASWELL:
|
||||
id = PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TA;
|
||||
break;
|
||||
case SANDY_BRIDGE:
|
||||
id = PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TA;
|
||||
break;
|
||||
case BROADWELL:
|
||||
id = PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TA;
|
||||
break;
|
||||
case KNIGHTS_LANDING:
|
||||
/*
|
||||
* KNL doesn't group things by bus the same way
|
||||
* SB/IB/Haswell does.
|
||||
*/
|
||||
id = PCI_DEVICE_ID_INTEL_KNL_IMC_TA;
|
||||
break;
|
||||
default:
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (type != KNIGHTS_LANDING)
|
||||
pdev = get_pdev_same_bus(bus, id);
|
||||
else
|
||||
pdev = pci_get_device(PCI_VENDOR_ID_INTEL, id, 0);
|
||||
|
||||
if (!pdev) {
|
||||
sbridge_printk(KERN_ERR, "Couldn't find PCI device "
|
||||
"%04x:%04x! on bus %02d\n",
|
||||
PCI_VENDOR_ID_INTEL, id, bus);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
pci_read_config_dword(pdev,
|
||||
type == KNIGHTS_LANDING ? KNL_MCMTR : MCMTR, &mcmtr);
|
||||
if (!IS_ECC_ENABLED(mcmtr)) {
|
||||
sbridge_printk(KERN_ERR, "ECC is disabled. Aborting\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Low bits of TAD limit, and some metadata. */
|
||||
static const u32 knl_tad_dram_limit_lo[] = {
|
||||
0x400, 0x500, 0x600, 0x700,
|
||||
|
@ -1620,9 +1547,9 @@ static void get_source_id(struct mem_ctl_info *mci)
|
|||
pvt->sbridge_dev->source_id = SOURCE_ID(reg);
|
||||
}
|
||||
|
||||
static void __populate_dimms(struct mem_ctl_info *mci,
|
||||
u64 knl_mc_sizes[KNL_MAX_CHANNELS],
|
||||
enum edac_type mode)
|
||||
static int __populate_dimms(struct mem_ctl_info *mci,
|
||||
u64 knl_mc_sizes[KNL_MAX_CHANNELS],
|
||||
enum edac_type mode)
|
||||
{
|
||||
struct sbridge_pvt *pvt = mci->pvt_info;
|
||||
int channels = pvt->info.type == KNIGHTS_LANDING ? KNL_MAX_CHANNELS
|
||||
|
@ -1671,6 +1598,12 @@ static void __populate_dimms(struct mem_ctl_info *mci,
|
|||
}
|
||||
edac_dbg(4, "Channel #%d MTR%d = %x\n", i, j, mtr);
|
||||
if (IS_DIMM_PRESENT(mtr)) {
|
||||
if (!IS_ECC_ENABLED(pvt->info.mcmtr)) {
|
||||
sbridge_printk(KERN_ERR, "CPU SrcID #%d, Ha #%d, Channel #%d has DIMMs, but ECC is disabled\n",
|
||||
pvt->sbridge_dev->source_id,
|
||||
pvt->sbridge_dev->dom, i);
|
||||
return -ENODEV;
|
||||
}
|
||||
pvt->channel[i].dimms++;
|
||||
|
||||
ranks = numrank(pvt->info.type, mtr);
|
||||
|
@ -1704,6 +1637,8 @@ static void __populate_dimms(struct mem_ctl_info *mci,
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_dimm_config(struct mem_ctl_info *mci)
|
||||
|
@ -1732,6 +1667,7 @@ static int get_dimm_config(struct mem_ctl_info *mci)
|
|||
|
||||
if (knl_get_dimm_capacity(pvt, knl_mc_sizes) != 0)
|
||||
return -1;
|
||||
pci_read_config_dword(pvt->pci_ta, KNL_MCMTR, &pvt->info.mcmtr);
|
||||
} else {
|
||||
pci_read_config_dword(pvt->pci_ras, RASENABLES, ®);
|
||||
if (IS_MIRROR_ENABLED(reg)) {
|
||||
|
@ -1761,9 +1697,7 @@ static int get_dimm_config(struct mem_ctl_info *mci)
|
|||
}
|
||||
}
|
||||
|
||||
__populate_dimms(mci, knl_mc_sizes, mode);
|
||||
|
||||
return 0;
|
||||
return __populate_dimms(mci, knl_mc_sizes, mode);
|
||||
}
|
||||
|
||||
static void get_memory_layout(const struct mem_ctl_info *mci)
|
||||
|
@ -3180,11 +3114,6 @@ static int sbridge_register_mci(struct sbridge_dev *sbridge_dev, enum type type)
|
|||
struct pci_dev *pdev = sbridge_dev->pdev[0];
|
||||
int rc;
|
||||
|
||||
/* Check the number of active and not disabled channels */
|
||||
rc = check_if_ecc_is_active(sbridge_dev->bus, type);
|
||||
if (unlikely(rc < 0))
|
||||
return rc;
|
||||
|
||||
/* allocate a new MC control structure */
|
||||
layers[0].type = EDAC_MC_LAYER_CHANNEL;
|
||||
layers[0].size = type == KNIGHTS_LANDING ?
|
||||
|
@ -3347,7 +3276,11 @@ static int sbridge_register_mci(struct sbridge_dev *sbridge_dev, enum type type)
|
|||
}
|
||||
|
||||
/* Get dimm basic config and the memory layout */
|
||||
get_dimm_config(mci);
|
||||
rc = get_dimm_config(mci);
|
||||
if (rc < 0) {
|
||||
edac_dbg(0, "MC: failed to get_dimm_config()\n");
|
||||
goto fail;
|
||||
}
|
||||
get_memory_layout(mci);
|
||||
|
||||
/* record ptr to the generic device */
|
||||
|
|
Loading…
Reference in a new issue