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

Commit 94c1acf2 authored by Aravind Gopalakrishnan's avatar Aravind Gopalakrishnan Committed by Borislav Petkov
Browse files

amd64_edac: Add Family 16h support



Add code to handle DRAM ECC errors decoding for Fam16h.

Tested on Fam16h with ECC turned on using the mce_amd_inj facility and
works fine.

Signed-off-by: default avatarAravind Gopalakrishnan <Aravind.Gopalakrishnan@amd.com>
[ Boris: cleanups and clarifications ]
Signed-off-by: default avatarBorislav Petkov <bp@suse.de>
parent 41ef2d56
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -20,12 +20,14 @@ const struct pci_device_id amd_nb_misc_ids[] = {
	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_10H_NB_MISC) },
	{ 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_16H_NB_F3) },
	{}
};
EXPORT_SYMBOL(amd_nb_misc_ids);

static 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_16H_NB_F4) },
	{}
};

@@ -81,7 +83,6 @@ int amd_cache_northbridges(void)
			next_northbridge(link, amd_nb_link_ids);
        }

	/* some CPU families (e.g. family 0x11) do not support GART */
	if (boot_cpu_data.x86 == 0xf || boot_cpu_data.x86 == 0x10 ||
	    boot_cpu_data.x86 == 0x15)
		amd_northbridges.flags |= AMD_NB_GART;
+64 −1
Original line number Diff line number Diff line
@@ -98,6 +98,7 @@ int __amd64_write_pci_cfg_dword(struct pci_dev *pdev, int offset,
 *
 * F15h: we select which DCT we access using F1x10C[DctCfgSel]
 *
 * F16h: has only 1 DCT
 */
static int k8_read_dct_pci_cfg(struct amd64_pvt *pvt, int addr, u32 *val,
			       const char *func)
@@ -340,6 +341,27 @@ static void get_cs_base_and_mask(struct amd64_pvt *pvt, int csrow, u8 dct,
		base_bits	= GENMASK(21, 31) | GENMASK(9, 15);
		mask_bits	= GENMASK(21, 29) | GENMASK(9, 15);
		addr_shift	= 4;

	/*
	* F16h needs two addr_shift values: 8 for high and 6 for low
	* (cf. F16h BKDG).
	*/
	} else if (boot_cpu_data.x86 == 0x16) {
		csbase          = pvt->csels[dct].csbases[csrow];
		csmask          = pvt->csels[dct].csmasks[csrow >> 1];

		*base  = (csbase & GENMASK(5,  15)) << 6;
		*base |= (csbase & GENMASK(19, 30)) << 8;

		*mask = ~0ULL;
		/* poke holes for the csmask */
		*mask &= ~((GENMASK(5, 15)  << 6) |
			   (GENMASK(19, 30) << 8));

		*mask |= (csmask & GENMASK(5, 15))  << 6;
		*mask |= (csmask & GENMASK(19, 30)) << 8;

		return;
	} else {
		csbase		= pvt->csels[dct].csbases[csrow];
		csmask		= pvt->csels[dct].csmasks[csrow >> 1];
@@ -1150,6 +1172,21 @@ static int f15_dbam_to_chip_select(struct amd64_pvt *pvt, u8 dct,
	return ddr3_cs_size(cs_mode, false);
}

/*
 * F16h has only limited cs_modes
 */
static int f16_dbam_to_chip_select(struct amd64_pvt *pvt, u8 dct,
				unsigned cs_mode)
{
	WARN_ON(cs_mode > 12);

	if (cs_mode == 6 || cs_mode == 8 ||
	    cs_mode == 9 || cs_mode == 12)
		return -1;
	else
		return ddr3_cs_size(cs_mode, false);
}

static void read_dram_ctl_register(struct amd64_pvt *pvt)
{

@@ -1587,6 +1624,17 @@ static struct amd64_family_type amd64_family_types[] = {
			.read_dct_pci_cfg	= f15_read_dct_pci_cfg,
		}
	},
	[F16_CPUS] = {
		.ctl_name = "F16h",
		.f1_id = PCI_DEVICE_ID_AMD_16H_NB_F1,
		.f3_id = PCI_DEVICE_ID_AMD_16H_NB_F3,
		.ops = {
			.early_channel_count	= f1x_early_channel_count,
			.map_sysaddr_to_csrow	= f1x_map_sysaddr_to_csrow,
			.dbam_to_cs		= f16_dbam_to_chip_select,
			.read_dct_pci_cfg	= f10_read_dct_pci_cfg,
		}
	},
};

/*
@@ -1939,6 +1987,8 @@ static void read_mc_regs(struct amd64_pvt *pvt)

	if (c->x86 >= 0x10) {
		amd64_read_pci_cfg(pvt->F3, EXT_NB_MCA_CFG, &tmp);
		if (c->x86 != 0x16)
			/* F16h has only DCT0 */
			amd64_read_dct_pci_cfg(pvt, DBAM1, &pvt->dbam1);

		/* F10h, revD and later can do x8 ECC too */
@@ -2356,6 +2406,11 @@ static struct amd64_family_type *amd64_per_family_init(struct amd64_pvt *pvt)
		pvt->ops		= &amd64_family_types[F15_CPUS].ops;
		break;

	case 0x16:
		fam_type		= &amd64_family_types[F16_CPUS];
		pvt->ops		= &amd64_family_types[F16_CPUS].ops;
		break;

	default:
		amd64_err("Unsupported family!\n");
		return NULL;
@@ -2581,6 +2636,14 @@ static DEFINE_PCI_DEVICE_TABLE(amd64_pci_table) = {
		.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,
	},

	{0, }
};
+3 −1
Original line number Diff line number Diff line
@@ -172,7 +172,8 @@
 */
#define PCI_DEVICE_ID_AMD_15H_NB_F1	0x1601
#define PCI_DEVICE_ID_AMD_15H_NB_F2	0x1602

#define PCI_DEVICE_ID_AMD_16H_NB_F1	0x1531
#define PCI_DEVICE_ID_AMD_16H_NB_F2	0x1532

/*
 * Function 1 - Address Map
@@ -296,6 +297,7 @@ enum amd_families {
	K8_CPUS = 0,
	F10_CPUS,
	F15_CPUS,
	F16_CPUS,
	NUM_FAMILIES,
};

+2 −0
Original line number Diff line number Diff line
@@ -524,6 +524,8 @@
#define PCI_DEVICE_ID_AMD_15H_NB_F3	0x1603
#define PCI_DEVICE_ID_AMD_15H_NB_F4	0x1604
#define PCI_DEVICE_ID_AMD_15H_NB_F5	0x1605
#define PCI_DEVICE_ID_AMD_16H_NB_F3	0x1533
#define PCI_DEVICE_ID_AMD_16H_NB_F4	0x1534
#define PCI_DEVICE_ID_AMD_CNB17H_F3	0x1703
#define PCI_DEVICE_ID_AMD_LANCE		0x2000
#define PCI_DEVICE_ID_AMD_LANCE_HOME	0x2001