Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d9b44fe3 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull edac updates from Mauro Carvalho Chehab:
 "Two EDAC fixes for Intel systems (Haswell and Ivy Bridge)"

* tag 'edac/v4.3-1' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-edac:
  sb_edac: correctly fetch DIMM width on Ivy Bridge and Haswell
  sb_edac: look harder for DDRIO on Haswell systems
parents 9ebd051a 12f0721c
Loading
Loading
Loading
Loading
+60 −12
Original line number Original line Diff line number Diff line
@@ -280,6 +280,7 @@ struct sbridge_info {
	u8		max_interleave;
	u8		max_interleave;
	u8		(*get_node_id)(struct sbridge_pvt *pvt);
	u8		(*get_node_id)(struct sbridge_pvt *pvt);
	enum mem_type	(*get_memory_type)(struct sbridge_pvt *pvt);
	enum mem_type	(*get_memory_type)(struct sbridge_pvt *pvt);
	enum dev_type	(*get_width)(struct sbridge_pvt *pvt, u32 mtr);
	struct pci_dev	*pci_vtd;
	struct pci_dev	*pci_vtd;
};
};


@@ -471,6 +472,9 @@ static const struct pci_id_table pci_dev_descr_ibridge_table[] = {
#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD2 0x2f6c
#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD2 0x2f6c
#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD3 0x2f6d
#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD3 0x2f6d
#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_DDRIO0 0x2fbd
#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_DDRIO0 0x2fbd
#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_DDRIO1 0x2fbf
#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_DDRIO2 0x2fb9
#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_DDRIO3 0x2fbb
static const struct pci_id_descr pci_dev_descr_haswell[] = {
static const struct pci_id_descr pci_dev_descr_haswell[] = {
	/* first item must be the HA */
	/* first item must be the HA */
	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0, 0)		},
	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0, 0)		},
@@ -488,6 +492,9 @@ static const struct pci_id_descr pci_dev_descr_haswell[] = {
	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD3, 1)	},
	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD3, 1)	},


	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_DDRIO0, 1)		},
	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_DDRIO0, 1)		},
	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_DDRIO1, 1)		},
	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_DDRIO2, 1)		},
	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_DDRIO3, 1)		},


	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TA, 1)		},
	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TA, 1)		},
	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_THERMAL, 1)	},
	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_THERMAL, 1)	},
@@ -762,6 +769,49 @@ static enum mem_type haswell_get_memory_type(struct sbridge_pvt *pvt)
	return mtype;
	return mtype;
}
}


static enum dev_type sbridge_get_width(struct sbridge_pvt *pvt, u32 mtr)
{
	/* there's no way to figure out */
	return DEV_UNKNOWN;
}

static enum dev_type __ibridge_get_width(u32 mtr)
{
	enum dev_type type;

	switch (mtr) {
	case 3:
		type = DEV_UNKNOWN;
		break;
	case 2:
		type = DEV_X16;
		break;
	case 1:
		type = DEV_X8;
		break;
	case 0:
		type = DEV_X4;
		break;
	}

	return type;
}

static enum dev_type ibridge_get_width(struct sbridge_pvt *pvt, u32 mtr)
{
	/*
	 * ddr3_width on the documentation but also valid for DDR4 on
	 * Haswell
	 */
	return __ibridge_get_width(GET_BITFIELD(mtr, 7, 8));
}

static enum dev_type broadwell_get_width(struct sbridge_pvt *pvt, u32 mtr)
{
	/* ddr3_width on the documentation but also valid for DDR4 */
	return __ibridge_get_width(GET_BITFIELD(mtr, 8, 9));
}

static u8 get_node_id(struct sbridge_pvt *pvt)
static u8 get_node_id(struct sbridge_pvt *pvt)
{
{
	u32 reg;
	u32 reg;
@@ -966,17 +1016,7 @@ static int get_dimm_config(struct mem_ctl_info *mci)


				dimm->nr_pages = npages;
				dimm->nr_pages = npages;
				dimm->grain = 32;
				dimm->grain = 32;
				switch (banks) {
				dimm->dtype = pvt->info.get_width(pvt, mtr);
				case 16:
					dimm->dtype = DEV_X16;
					break;
				case 8:
					dimm->dtype = DEV_X8;
					break;
				case 4:
					dimm->dtype = DEV_X4;
					break;
				}
				dimm->mtype = mtype;
				dimm->mtype = mtype;
				dimm->edac_mode = mode;
				dimm->edac_mode = mode;
				snprintf(dimm->label, sizeof(dimm->label),
				snprintf(dimm->label, sizeof(dimm->label),
@@ -1869,6 +1909,10 @@ static int haswell_mci_bind_devs(struct mem_ctl_info *mci,
		}
		}
			break;
			break;
		case PCI_DEVICE_ID_INTEL_HASWELL_IMC_DDRIO0:
		case PCI_DEVICE_ID_INTEL_HASWELL_IMC_DDRIO0:
		case PCI_DEVICE_ID_INTEL_HASWELL_IMC_DDRIO1:
		case PCI_DEVICE_ID_INTEL_HASWELL_IMC_DDRIO2:
		case PCI_DEVICE_ID_INTEL_HASWELL_IMC_DDRIO3:
			if (!pvt->pci_ddrio)
				pvt->pci_ddrio = pdev;
				pvt->pci_ddrio = pdev;
			break;
			break;
		case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1:
		case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1:
@@ -2361,6 +2405,7 @@ static int sbridge_register_mci(struct sbridge_dev *sbridge_dev, enum type type)
		pvt->info.interleave_list = ibridge_interleave_list;
		pvt->info.interleave_list = ibridge_interleave_list;
		pvt->info.max_interleave = ARRAY_SIZE(ibridge_interleave_list);
		pvt->info.max_interleave = ARRAY_SIZE(ibridge_interleave_list);
		pvt->info.interleave_pkg = ibridge_interleave_pkg;
		pvt->info.interleave_pkg = ibridge_interleave_pkg;
		pvt->info.get_width = ibridge_get_width;
		mci->ctl_name = kasprintf(GFP_KERNEL, "Ivy Bridge Socket#%d", mci->mc_idx);
		mci->ctl_name = kasprintf(GFP_KERNEL, "Ivy Bridge Socket#%d", mci->mc_idx);


		/* Store pci devices at mci for faster access */
		/* Store pci devices at mci for faster access */
@@ -2380,6 +2425,7 @@ static int sbridge_register_mci(struct sbridge_dev *sbridge_dev, enum type type)
		pvt->info.interleave_list = sbridge_interleave_list;
		pvt->info.interleave_list = sbridge_interleave_list;
		pvt->info.max_interleave = ARRAY_SIZE(sbridge_interleave_list);
		pvt->info.max_interleave = ARRAY_SIZE(sbridge_interleave_list);
		pvt->info.interleave_pkg = sbridge_interleave_pkg;
		pvt->info.interleave_pkg = sbridge_interleave_pkg;
		pvt->info.get_width = sbridge_get_width;
		mci->ctl_name = kasprintf(GFP_KERNEL, "Sandy Bridge Socket#%d", mci->mc_idx);
		mci->ctl_name = kasprintf(GFP_KERNEL, "Sandy Bridge Socket#%d", mci->mc_idx);


		/* Store pci devices at mci for faster access */
		/* Store pci devices at mci for faster access */
@@ -2399,6 +2445,7 @@ static int sbridge_register_mci(struct sbridge_dev *sbridge_dev, enum type type)
		pvt->info.interleave_list = ibridge_interleave_list;
		pvt->info.interleave_list = ibridge_interleave_list;
		pvt->info.max_interleave = ARRAY_SIZE(ibridge_interleave_list);
		pvt->info.max_interleave = ARRAY_SIZE(ibridge_interleave_list);
		pvt->info.interleave_pkg = ibridge_interleave_pkg;
		pvt->info.interleave_pkg = ibridge_interleave_pkg;
		pvt->info.get_width = ibridge_get_width;
		mci->ctl_name = kasprintf(GFP_KERNEL, "Haswell Socket#%d", mci->mc_idx);
		mci->ctl_name = kasprintf(GFP_KERNEL, "Haswell Socket#%d", mci->mc_idx);


		/* Store pci devices at mci for faster access */
		/* Store pci devices at mci for faster access */
@@ -2418,6 +2465,7 @@ static int sbridge_register_mci(struct sbridge_dev *sbridge_dev, enum type type)
		pvt->info.interleave_list = ibridge_interleave_list;
		pvt->info.interleave_list = ibridge_interleave_list;
		pvt->info.max_interleave = ARRAY_SIZE(ibridge_interleave_list);
		pvt->info.max_interleave = ARRAY_SIZE(ibridge_interleave_list);
		pvt->info.interleave_pkg = ibridge_interleave_pkg;
		pvt->info.interleave_pkg = ibridge_interleave_pkg;
		pvt->info.get_width = broadwell_get_width;
		mci->ctl_name = kasprintf(GFP_KERNEL, "Broadwell Socket#%d", mci->mc_idx);
		mci->ctl_name = kasprintf(GFP_KERNEL, "Broadwell Socket#%d", mci->mc_idx);


		/* Store pci devices at mci for faster access */
		/* Store pci devices at mci for faster access */