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

Commit 0160928e authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull EDAC updates from Borislav Petkov:
 "EDAC updates all over the place:

   - Enablement for AMD F15h models 0x60 CPUs.  Most notably DDR4 RAM
     support.  Out of tree stuff is adding the required PCI IDs.  From
     Aravind Gopalakrishnan.

   - Enable amd64_edac for 32-bit due to popular demand.  From Tomasz
     Pala.

   - Convert the AMD MCE injection module to debugfs, where it belongs.

   - Misc EDAC cleanups"

* tag 'edac_for_3.19' of git://git.kernel.org/pub/scm/linux/kernel/git/bp/bp:
  EDAC, MCE, AMD: Correct formatting of decoded text
  EDAC, mce_amd_inj: Add an injector function
  EDAC, mce_amd_inj: Add hw-injection attributes
  EDAC, mce_amd_inj: Enable direct writes to MCE MSRs
  EDAC, mce_amd_inj: Convert mce_amd_inj module to debugfs
  EDAC: Delete unnecessary check before calling pci_dev_put()
  EDAC, pci_sysfs: remove unneccessary ifdef around entire file
  ghes_edac: Use snprintf() to silence a static checker warning
  amd64_edac: Build module on x86-32
  EDAC, MCE, AMD: Add decoding table for MC6 xec
  amd64_edac: Add F15h M60h support
  {mv64x60,ppc4xx}_edac,: Remove deprecated IRQF_DISABLED
  EDAC: Sync memory types and names
  EDAC: Add DDR3 LRDIMM entries to edac_mem_types
  x86, amd_nb: Add device IDs to NB tables for F15h M60h
  pci_ids: Add PCI device IDs for F15h M60h
parents 3a7dbed7 50872ccd
Loading
Loading
Loading
Loading
+2 −0
Original line number Original line Diff line number Diff line
@@ -21,6 +21,7 @@ const struct pci_device_id amd_nb_misc_ids[] = {
	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_15H_NB_F3) },
	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_15H_NB_F3) },
	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_15H_M10H_F3) },
	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_15H_M10H_F3) },
	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_15H_M30H_NB_F3) },
	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_15H_M30H_NB_F3) },
	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_15H_M60H_NB_F3) },
	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_16H_NB_F3) },
	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_16H_NB_F3) },
	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_16H_M30H_NB_F3) },
	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_16H_M30H_NB_F3) },
	{}
	{}
@@ -30,6 +31,7 @@ EXPORT_SYMBOL(amd_nb_misc_ids);
static const struct pci_device_id amd_nb_link_ids[] = {
static const struct pci_device_id amd_nb_link_ids[] = {
	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_15H_NB_F4) },
	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_15H_NB_F4) },
	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_15H_M30H_NB_F4) },
	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_15H_M30H_NB_F4) },
	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_15H_M60H_NB_F4) },
	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_16H_NB_F4) },
	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_16H_NB_F4) },
	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_16H_M30H_NB_F4) },
	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_16H_M30H_NB_F4) },
	{}
	{}
+8 −8
Original line number Original line Diff line number Diff line
@@ -61,14 +61,14 @@ config EDAC_DECODE_MCE
	  has been initialized.
	  has been initialized.


config EDAC_MCE_INJ
config EDAC_MCE_INJ
	tristate "Simple MCE injection interface over /sysfs"
	tristate "Simple MCE injection interface"
	depends on EDAC_DECODE_MCE
	depends on EDAC_DECODE_MCE && DEBUG_FS
	default n
	default n
	help
	help
	  This is a simple interface to inject MCEs over /sysfs and test
	  This is a simple debugfs interface to inject MCEs and test different
	  the MCE decoding code in EDAC.
	  aspects of the MCE handling code.


	  This is currently AMD-only.
	  WARNING: Do not even assume this interface is staying stable!


config EDAC_MM_EDAC
config EDAC_MM_EDAC
	tristate "Main Memory EDAC (Error Detection And Correction) reporting"
	tristate "Main Memory EDAC (Error Detection And Correction) reporting"
@@ -105,11 +105,11 @@ config EDAC_GHES
	  In doubt, say 'Y'.
	  In doubt, say 'Y'.


config EDAC_AMD64
config EDAC_AMD64
	tristate "AMD64 (Opteron, Athlon64) K8, F10h"
	tristate "AMD64 (Opteron, Athlon64)"
	depends on EDAC_MM_EDAC && AMD_NB && X86_64 && EDAC_DECODE_MCE
	depends on EDAC_MM_EDAC && AMD_NB && EDAC_DECODE_MCE
	help
	help
	  Support for error detection and correction of DRAM ECC errors on
	  Support for error detection and correction of DRAM ECC errors on
	  the AMD64 families of memory controllers (K8 and F10h)
	  the AMD64 families (>= K8) of memory controllers.


config EDAC_AMD64_ERROR_INJECTION
config EDAC_AMD64_ERROR_INJECTION
	bool "Sysfs HW Error injection facilities"
	bool "Sysfs HW Error injection facilities"
+1 −1
Original line number Original line Diff line number Diff line
@@ -9,7 +9,7 @@
obj-$(CONFIG_EDAC)			:= edac_stub.o
obj-$(CONFIG_EDAC)			:= edac_stub.o
obj-$(CONFIG_EDAC_MM_EDAC)		+= edac_core.o
obj-$(CONFIG_EDAC_MM_EDAC)		+= edac_core.o


edac_core-y	:= edac_mc.o edac_device.o edac_mc_sysfs.o edac_pci_sysfs.o
edac_core-y	:= edac_mc.o edac_device.o edac_mc_sysfs.o
edac_core-y	+= edac_module.o edac_device_sysfs.o
edac_core-y	+= edac_module.o edac_device_sysfs.o


ifdef CONFIG_PCI
ifdef CONFIG_PCI
+181 −79
Original line number Original line Diff line number Diff line
@@ -692,10 +692,20 @@ static void debug_dump_dramcfg_low(struct amd64_pvt *pvt, u32 dclr, int chan)
{
{
	edac_dbg(1, "F2x%d90 (DRAM Cfg Low): 0x%08x\n", chan, dclr);
	edac_dbg(1, "F2x%d90 (DRAM Cfg Low): 0x%08x\n", chan, dclr);


	edac_dbg(1, "  DIMM type: %sbuffered; all DIMMs support ECC: %s\n",
	if (pvt->dram_type == MEM_LRDDR3) {
		 (dclr & BIT(16)) ?  "un" : "",
		u32 dcsm = pvt->csels[chan].csmasks[0];
		/*
		 * It's assumed all LRDIMMs in a DCT are going to be of
		 * same 'type' until proven otherwise. So, use a cs
		 * value of '0' here to get dcsm value.
		 */
		edac_dbg(1, " LRDIMM %dx rank multiply\n", (dcsm & 0x3));
	}

	edac_dbg(1, "All DIMMs support ECC:%s\n",
		    (dclr & BIT(19)) ? "yes" : "no");
		    (dclr & BIT(19)) ? "yes" : "no");



	edac_dbg(1, "  PAR/ERR parity: %s\n",
	edac_dbg(1, "  PAR/ERR parity: %s\n",
		 (dclr & BIT(8)) ?  "enabled" : "disabled");
		 (dclr & BIT(8)) ?  "enabled" : "disabled");


@@ -756,7 +766,7 @@ static void prep_chip_selects(struct amd64_pvt *pvt)
	if (pvt->fam == 0xf && pvt->ext_model < K8_REV_F) {
	if (pvt->fam == 0xf && pvt->ext_model < K8_REV_F) {
		pvt->csels[0].b_cnt = pvt->csels[1].b_cnt = 8;
		pvt->csels[0].b_cnt = pvt->csels[1].b_cnt = 8;
		pvt->csels[0].m_cnt = pvt->csels[1].m_cnt = 8;
		pvt->csels[0].m_cnt = pvt->csels[1].m_cnt = 8;
	} else if (pvt->fam == 0x15 && pvt->model >= 0x30) {
	} else if (pvt->fam == 0x15 && pvt->model == 0x30) {
		pvt->csels[0].b_cnt = pvt->csels[1].b_cnt = 4;
		pvt->csels[0].b_cnt = pvt->csels[1].b_cnt = 4;
		pvt->csels[0].m_cnt = pvt->csels[1].m_cnt = 2;
		pvt->csels[0].m_cnt = pvt->csels[1].m_cnt = 2;
	} else {
	} else {
@@ -813,25 +823,63 @@ static void read_dct_base_mask(struct amd64_pvt *pvt)
	}
	}
}
}


static enum mem_type determine_memory_type(struct amd64_pvt *pvt, int cs)
static void determine_memory_type(struct amd64_pvt *pvt)
{
{
	enum mem_type type;
	u32 dram_ctrl, dcsm;

	switch (pvt->fam) {
	case 0xf:
		if (pvt->ext_model >= K8_REV_F)
			goto ddr3;


	/* F15h supports only DDR3 */
		pvt->dram_type = (pvt->dclr0 & BIT(18)) ? MEM_DDR : MEM_RDDR;
	if (pvt->fam >= 0x15)
		return;
		type = (pvt->dclr0 & BIT(16)) ?	MEM_DDR3 : MEM_RDDR3;

	else if (pvt->fam == 0x10 || pvt->ext_model >= K8_REV_F) {
	case 0x10:
		if (pvt->dchr0 & DDR3_MODE)
		if (pvt->dchr0 & DDR3_MODE)
			type = (pvt->dclr0 & BIT(16)) ?	MEM_DDR3 : MEM_RDDR3;
			goto ddr3;

		pvt->dram_type = (pvt->dclr0 & BIT(16)) ? MEM_DDR2 : MEM_RDDR2;
		return;

	case 0x15:
		if (pvt->model < 0x60)
			goto ddr3;

		/*
		 * Model 0x60h needs special handling:
		 *
		 * We use a Chip Select value of '0' to obtain dcsm.
		 * Theoretically, it is possible to populate LRDIMMs of different
		 * 'Rank' value on a DCT. But this is not the common case. So,
		 * it's reasonable to assume all DIMMs are going to be of same
		 * 'type' until proven otherwise.
		 */
		amd64_read_dct_pci_cfg(pvt, 0, DRAM_CONTROL, &dram_ctrl);
		dcsm = pvt->csels[0].csmasks[0];

		if (((dram_ctrl >> 8) & 0x7) == 0x2)
			pvt->dram_type = MEM_DDR4;
		else if (pvt->dclr0 & BIT(16))
			pvt->dram_type = MEM_DDR3;
		else if (dcsm & 0x3)
			pvt->dram_type = MEM_LRDDR3;
		else
		else
			type = (pvt->dclr0 & BIT(16)) ? MEM_DDR2 : MEM_RDDR2;
			pvt->dram_type = MEM_RDDR3;
	} else {
		type = (pvt->dclr0 & BIT(18)) ? MEM_DDR : MEM_RDDR;
	}


	amd64_info("CS%d: %s\n", cs, edac_mem_types[type]);
		return;

	case 0x16:
		goto ddr3;


	return type;
	default:
		WARN(1, KERN_ERR "%s: Family??? 0x%x\n", __func__, pvt->fam);
		pvt->dram_type = MEM_EMPTY;
	}
	return;

ddr3:
	pvt->dram_type = (pvt->dclr0 & BIT(16)) ? MEM_DDR3 : MEM_RDDR3;
}
}


/* Get the number of DCT channels the memory controller is using. */
/* Get the number of DCT channels the memory controller is using. */
@@ -958,8 +1006,12 @@ static void read_dram_base_limit_regs(struct amd64_pvt *pvt, unsigned range)
	if (WARN_ON(!nb))
	if (WARN_ON(!nb))
		return;
		return;


	pci_func = (pvt->model == 0x30) ? PCI_DEVICE_ID_AMD_15H_M30H_NB_F1
	if (pvt->model == 0x60)
					: PCI_DEVICE_ID_AMD_15H_NB_F1;
		pci_func = PCI_DEVICE_ID_AMD_15H_M60H_NB_F1;
	else if (pvt->model == 0x30)
		pci_func = PCI_DEVICE_ID_AMD_15H_M30H_NB_F1;
	else
		pci_func = PCI_DEVICE_ID_AMD_15H_NB_F1;


	f1 = pci_get_related_function(nb->misc->vendor, pci_func, nb->misc);
	f1 = pci_get_related_function(nb->misc->vendor, pci_func, nb->misc);
	if (WARN_ON(!f1))
	if (WARN_ON(!f1))
@@ -1049,7 +1101,7 @@ static int ddr2_cs_size(unsigned i, bool dct_width)
}
}


static int k8_dbam_to_chip_select(struct amd64_pvt *pvt, u8 dct,
static int k8_dbam_to_chip_select(struct amd64_pvt *pvt, u8 dct,
				  unsigned cs_mode)
				  unsigned cs_mode, int cs_mask_nr)
{
{
	u32 dclr = dct ? pvt->dclr1 : pvt->dclr0;
	u32 dclr = dct ? pvt->dclr1 : pvt->dclr0;


@@ -1167,8 +1219,43 @@ static int ddr3_cs_size(unsigned i, bool dct_width)
	return cs_size;
	return cs_size;
}
}


static int ddr3_lrdimm_cs_size(unsigned i, unsigned rank_multiply)
{
	unsigned shift = 0;
	int cs_size = 0;

	if (i < 4 || i == 6)
		cs_size = -1;
	else if (i == 12)
		shift = 7;
	else if (!(i & 0x1))
		shift = i >> 1;
	else
		shift = (i + 1) >> 1;

	if (cs_size != -1)
		cs_size = rank_multiply * (128 << shift);

	return cs_size;
}

static int ddr4_cs_size(unsigned i)
{
	int cs_size = 0;

	if (i == 0)
		cs_size = -1;
	else if (i == 1)
		cs_size = 1024;
	else
		/* Min cs_size = 1G */
		cs_size = 1024 * (1 << (i >> 1));

	return cs_size;
}

static int f10_dbam_to_chip_select(struct amd64_pvt *pvt, u8 dct,
static int f10_dbam_to_chip_select(struct amd64_pvt *pvt, u8 dct,
				   unsigned cs_mode)
				   unsigned cs_mode, int cs_mask_nr)
{
{
	u32 dclr = dct ? pvt->dclr1 : pvt->dclr0;
	u32 dclr = dct ? pvt->dclr1 : pvt->dclr0;


@@ -1184,18 +1271,49 @@ static int f10_dbam_to_chip_select(struct amd64_pvt *pvt, u8 dct,
 * F15h supports only 64bit DCT interfaces
 * F15h supports only 64bit DCT interfaces
 */
 */
static int f15_dbam_to_chip_select(struct amd64_pvt *pvt, u8 dct,
static int f15_dbam_to_chip_select(struct amd64_pvt *pvt, u8 dct,
				   unsigned cs_mode)
				   unsigned cs_mode, int cs_mask_nr)
{
{
	WARN_ON(cs_mode > 12);
	WARN_ON(cs_mode > 12);


	return ddr3_cs_size(cs_mode, false);
	return ddr3_cs_size(cs_mode, false);
}
}


/* F15h M60h supports DDR4 mapping as well.. */
static int f15_m60h_dbam_to_chip_select(struct amd64_pvt *pvt, u8 dct,
					unsigned cs_mode, int cs_mask_nr)
{
	int cs_size;
	u32 dcsm = pvt->csels[dct].csmasks[cs_mask_nr];

	WARN_ON(cs_mode > 12);

	if (pvt->dram_type == MEM_DDR4) {
		if (cs_mode > 9)
			return -1;

		cs_size = ddr4_cs_size(cs_mode);
	} else if (pvt->dram_type == MEM_LRDDR3) {
		unsigned rank_multiply = dcsm & 0xf;

		if (rank_multiply == 3)
			rank_multiply = 4;
		cs_size = ddr3_lrdimm_cs_size(cs_mode, rank_multiply);
	} else {
		/* Minimum cs size is 512mb for F15hM60h*/
		if (cs_mode == 0x1)
			return -1;

		cs_size = ddr3_cs_size(cs_mode, false);
	}

	return cs_size;
}

/*
/*
 * F16h and F15h model 30h have only limited cs_modes.
 * F16h and F15h model 30h have only limited cs_modes.
 */
 */
static int f16_dbam_to_chip_select(struct amd64_pvt *pvt, u8 dct,
static int f16_dbam_to_chip_select(struct amd64_pvt *pvt, u8 dct,
				unsigned cs_mode)
				unsigned cs_mode, int cs_mask_nr)
{
{
	WARN_ON(cs_mode > 12);
	WARN_ON(cs_mode > 12);


@@ -1757,13 +1875,20 @@ static void debug_display_dimm_sizes(struct amd64_pvt *pvt, u8 ctrl)


		size0 = 0;
		size0 = 0;
		if (dcsb[dimm*2] & DCSB_CS_ENABLE)
		if (dcsb[dimm*2] & DCSB_CS_ENABLE)
			/* For f15m60h, need multiplier for LRDIMM cs_size
			 * calculation. We pass 'dimm' value to the dbam_to_cs
			 * mapper so we can find the multiplier from the
			 * corresponding DCSM.
			 */
			size0 = pvt->ops->dbam_to_cs(pvt, ctrl,
			size0 = pvt->ops->dbam_to_cs(pvt, ctrl,
						     DBAM_DIMM(dimm, dbam));
						     DBAM_DIMM(dimm, dbam),
						     dimm);


		size1 = 0;
		size1 = 0;
		if (dcsb[dimm*2 + 1] & DCSB_CS_ENABLE)
		if (dcsb[dimm*2 + 1] & DCSB_CS_ENABLE)
			size1 = pvt->ops->dbam_to_cs(pvt, ctrl,
			size1 = pvt->ops->dbam_to_cs(pvt, ctrl,
						     DBAM_DIMM(dimm, dbam));
						     DBAM_DIMM(dimm, dbam),
						     dimm);


		amd64_info(EDAC_MC ": %d: %5dMB %d: %5dMB\n",
		amd64_info(EDAC_MC ": %d: %5dMB %d: %5dMB\n",
				dimm * 2,     size0,
				dimm * 2,     size0,
@@ -1812,6 +1937,16 @@ static struct amd64_family_type family_types[] = {
			.dbam_to_cs		= f16_dbam_to_chip_select,
			.dbam_to_cs		= f16_dbam_to_chip_select,
		}
		}
	},
	},
	[F15_M60H_CPUS] = {
		.ctl_name = "F15h_M60h",
		.f1_id = PCI_DEVICE_ID_AMD_15H_M60H_NB_F1,
		.f3_id = PCI_DEVICE_ID_AMD_15H_M60H_NB_F3,
		.ops = {
			.early_channel_count	= f1x_early_channel_count,
			.map_sysaddr_to_csrow	= f1x_map_sysaddr_to_csrow,
			.dbam_to_cs		= f15_m60h_dbam_to_chip_select,
		}
	},
	[F16_CPUS] = {
	[F16_CPUS] = {
		.ctl_name = "F16h",
		.ctl_name = "F16h",
		.f1_id = PCI_DEVICE_ID_AMD_16H_NB_F1,
		.f1_id = PCI_DEVICE_ID_AMD_16H_NB_F1,
@@ -2175,6 +2310,8 @@ static void read_mc_regs(struct amd64_pvt *pvt)
	}
	}


	pvt->ecc_sym_sz = 4;
	pvt->ecc_sym_sz = 4;
	determine_memory_type(pvt);
	edac_dbg(1, "  DIMM type: %s\n", edac_mem_types[pvt->dram_type]);


	if (pvt->fam >= 0x10) {
	if (pvt->fam >= 0x10) {
		amd64_read_pci_cfg(pvt->F3, EXT_NB_MCA_CFG, &tmp);
		amd64_read_pci_cfg(pvt->F3, EXT_NB_MCA_CFG, &tmp);
@@ -2238,7 +2375,8 @@ static u32 get_csrow_nr_pages(struct amd64_pvt *pvt, u8 dct, int csrow_nr)
	 */
	 */
	cs_mode = DBAM_DIMM(csrow_nr / 2, dbam);
	cs_mode = DBAM_DIMM(csrow_nr / 2, dbam);


	nr_pages = pvt->ops->dbam_to_cs(pvt, dct, cs_mode) << (20 - PAGE_SHIFT);
	nr_pages = pvt->ops->dbam_to_cs(pvt, dct, cs_mode, (csrow_nr / 2))
							   << (20 - PAGE_SHIFT);


	edac_dbg(0, "csrow: %d, channel: %d, DBAM idx: %d\n",
	edac_dbg(0, "csrow: %d, channel: %d, DBAM idx: %d\n",
		    csrow_nr, dct,  cs_mode);
		    csrow_nr, dct,  cs_mode);
@@ -2257,7 +2395,6 @@ static int init_csrows(struct mem_ctl_info *mci)
	struct csrow_info *csrow;
	struct csrow_info *csrow;
	struct dimm_info *dimm;
	struct dimm_info *dimm;
	enum edac_type edac_mode;
	enum edac_type edac_mode;
	enum mem_type mtype;
	int i, j, empty = 1;
	int i, j, empty = 1;
	int nr_pages = 0;
	int nr_pages = 0;
	u32 val;
	u32 val;
@@ -2302,8 +2439,6 @@ static int init_csrows(struct mem_ctl_info *mci)
			nr_pages += row_dct1_pages;
			nr_pages += row_dct1_pages;
		}
		}


		mtype = determine_memory_type(pvt, i);

		edac_dbg(1, "Total csrow%d pages: %u\n", i, nr_pages);
		edac_dbg(1, "Total csrow%d pages: %u\n", i, nr_pages);


		/*
		/*
@@ -2317,7 +2452,7 @@ static int init_csrows(struct mem_ctl_info *mci)


		for (j = 0; j < pvt->channel_count; j++) {
		for (j = 0; j < pvt->channel_count; j++) {
			dimm = csrow->channels[j]->dimm;
			dimm = csrow->channels[j]->dimm;
			dimm->mtype = mtype;
			dimm->mtype = pvt->dram_type;
			dimm->edac_mode = edac_mode;
			dimm->edac_mode = edac_mode;
		}
		}
	}
	}
@@ -2604,6 +2739,10 @@ static struct amd64_family_type *per_family_init(struct amd64_pvt *pvt)
			fam_type = &family_types[F15_M30H_CPUS];
			fam_type = &family_types[F15_M30H_CPUS];
			pvt->ops = &family_types[F15_M30H_CPUS].ops;
			pvt->ops = &family_types[F15_M30H_CPUS].ops;
			break;
			break;
		} else if (pvt->model == 0x60) {
			fam_type = &family_types[F15_M60H_CPUS];
			pvt->ops = &family_types[F15_M60H_CPUS].ops;
			break;
		}
		}


		fam_type	= &family_types[F15_CPUS];
		fam_type	= &family_types[F15_CPUS];
@@ -2828,55 +2967,13 @@ static void remove_one_instance(struct pci_dev *pdev)
 * inquiry this table to see if this driver is for a given device found.
 * inquiry this table to see if this driver is for a given device found.
 */
 */
static const struct pci_device_id amd64_pci_table[] = {
static const struct pci_device_id amd64_pci_table[] = {
	{
	{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_K8_NB_MEMCTL) },
		.vendor		= PCI_VENDOR_ID_AMD,
	{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_10H_NB_DRAM) },
		.device		= PCI_DEVICE_ID_AMD_K8_NB_MEMCTL,
	{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_NB_F2) },
		.subvendor	= PCI_ANY_ID,
	{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_M30H_NB_F2) },
		.subdevice	= PCI_ANY_ID,
	{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_M60H_NB_F2) },
		.class		= 0,
	{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_16H_NB_F2) },
		.class_mask	= 0,
	{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_16H_M30H_NB_F2) },
	},
	{
		.vendor		= PCI_VENDOR_ID_AMD,
		.device		= PCI_DEVICE_ID_AMD_10H_NB_DRAM,
		.subvendor	= PCI_ANY_ID,
		.subdevice	= PCI_ANY_ID,
		.class		= 0,
		.class_mask	= 0,
	},
	{
		.vendor		= PCI_VENDOR_ID_AMD,
		.device		= PCI_DEVICE_ID_AMD_15H_NB_F2,
		.subvendor	= PCI_ANY_ID,
		.subdevice	= PCI_ANY_ID,
		.class		= 0,
		.class_mask	= 0,
	},
	{
		.vendor		= PCI_VENDOR_ID_AMD,
		.device		= PCI_DEVICE_ID_AMD_15H_M30H_NB_F2,
		.subvendor	= PCI_ANY_ID,
		.subdevice	= PCI_ANY_ID,
		.class		= 0,
		.class_mask	= 0,
	},
	{
		.vendor		= PCI_VENDOR_ID_AMD,
		.device		= PCI_DEVICE_ID_AMD_16H_NB_F2,
		.subvendor	= PCI_ANY_ID,
		.subdevice	= PCI_ANY_ID,
		.class		= 0,
		.class_mask	= 0,
	},
	{
		.vendor		= PCI_VENDOR_ID_AMD,
		.device		= PCI_DEVICE_ID_AMD_16H_M30H_NB_F2,
		.subvendor	= PCI_ANY_ID,
		.subdevice	= PCI_ANY_ID,
		.class		= 0,
		.class_mask	= 0,
	},

	{0, }
	{0, }
};
};
MODULE_DEVICE_TABLE(pci, amd64_pci_table);
MODULE_DEVICE_TABLE(pci, amd64_pci_table);
@@ -2938,6 +3035,11 @@ static int __init amd64_edac_init(void)
		goto err_no_instances;
		goto err_no_instances;


	setup_pci_device();
	setup_pci_device();

#ifdef CONFIG_X86_32
	amd64_err("%s on 32-bit is unsupported. USE AT YOUR OWN RISK!\n", EDAC_MOD_STR);
#endif

	return 0;
	return 0;


err_no_instances:
err_no_instances:
+12 −3
Original line number Original line Diff line number Diff line
@@ -162,10 +162,12 @@
/*
/*
 * PCI-defined configuration space registers
 * PCI-defined configuration space registers
 */
 */
#define PCI_DEVICE_ID_AMD_15H_M30H_NB_F1 0x141b
#define PCI_DEVICE_ID_AMD_15H_M30H_NB_F2 0x141c
#define PCI_DEVICE_ID_AMD_15H_NB_F1	0x1601
#define PCI_DEVICE_ID_AMD_15H_NB_F1	0x1601
#define PCI_DEVICE_ID_AMD_15H_NB_F2	0x1602
#define PCI_DEVICE_ID_AMD_15H_NB_F2	0x1602
#define PCI_DEVICE_ID_AMD_15H_M30H_NB_F1 0x141b
#define PCI_DEVICE_ID_AMD_15H_M30H_NB_F2 0x141c
#define PCI_DEVICE_ID_AMD_15H_M60H_NB_F1 0x1571
#define PCI_DEVICE_ID_AMD_15H_M60H_NB_F2 0x1572
#define PCI_DEVICE_ID_AMD_16H_NB_F1	0x1531
#define PCI_DEVICE_ID_AMD_16H_NB_F1	0x1531
#define PCI_DEVICE_ID_AMD_16H_NB_F2	0x1532
#define PCI_DEVICE_ID_AMD_16H_NB_F2	0x1532
#define PCI_DEVICE_ID_AMD_16H_M30H_NB_F1 0x1581
#define PCI_DEVICE_ID_AMD_16H_M30H_NB_F1 0x1581
@@ -221,6 +223,8 @@


#define csrow_enabled(i, dct, pvt)	((pvt)->csels[(dct)].csbases[(i)] & DCSB_CS_ENABLE)
#define csrow_enabled(i, dct, pvt)	((pvt)->csels[(dct)].csbases[(i)] & DCSB_CS_ENABLE)


#define DRAM_CONTROL			0x78

#define DBAM0				0x80
#define DBAM0				0x80
#define DBAM1				0x180
#define DBAM1				0x180


@@ -301,6 +305,7 @@ enum amd_families {
	F10_CPUS,
	F10_CPUS,
	F15_CPUS,
	F15_CPUS,
	F15_M30H_CPUS,
	F15_M30H_CPUS,
	F15_M60H_CPUS,
	F16_CPUS,
	F16_CPUS,
	F16_M30H_CPUS,
	F16_M30H_CPUS,
	NUM_FAMILIES,
	NUM_FAMILIES,
@@ -379,6 +384,9 @@ struct amd64_pvt {


	/* place to store error injection parameters prior to issue */
	/* place to store error injection parameters prior to issue */
	struct error_injection injection;
	struct error_injection injection;

	/* cache the dram_type */
	enum mem_type dram_type;
};
};


enum err_codes {
enum err_codes {
@@ -480,7 +488,8 @@ struct low_ops {
	int (*early_channel_count)	(struct amd64_pvt *pvt);
	int (*early_channel_count)	(struct amd64_pvt *pvt);
	void (*map_sysaddr_to_csrow)	(struct mem_ctl_info *mci, u64 sys_addr,
	void (*map_sysaddr_to_csrow)	(struct mem_ctl_info *mci, u64 sys_addr,
					 struct err_info *);
					 struct err_info *);
	int (*dbam_to_cs)		(struct amd64_pvt *pvt, u8 dct, unsigned cs_mode);
	int (*dbam_to_cs)		(struct amd64_pvt *pvt, u8 dct,
					 unsigned cs_mode, int cs_mask_nr);
};
};


struct amd64_family_type {
struct amd64_family_type {
Loading