Unverified Commit b1dddf67 authored by openeuler-ci-bot's avatar openeuler-ci-bot Committed by Gitee
Browse files

!4639 Some fixes for Hygon model 4h~6h processors

Merge Pull Request from: @hygoner 
 
Some fixes of NB and EDAC for Hygon model 4h~6h processors.

Reference:
https://gitee.com/openeuler/kernel/pulls/1531
https://gitee.com/openeuler/kernel/pulls/4620 
 
Link:https://gitee.com/openeuler/kernel/pulls/4639

 

Reviewed-by: default avatarJason Zeng <jason.zeng@intel.com>
Signed-off-by: default avatarJialin Zhang <zhangjialin11@huawei.com>
parents a752e742 d0d1ed37
Loading
Loading
Loading
Loading
+46 −27
Original line number Diff line number Diff line
@@ -35,6 +35,7 @@
#define PCI_DEVICE_ID_HYGON_18H_M04H_DF_F1 0x1491
#define PCI_DEVICE_ID_HYGON_18H_M05H_DF_F1 0x14b1
#define PCI_DEVICE_ID_HYGON_18H_M05H_DF_F4 0x14b4
#define PCI_DEVICE_ID_HYGON_18H_M06H_DF_F5 0x14b5

/* Protect the PCI config register pairs used for SMN and DF indirect access. */
static DEFINE_MUTEX(smn_mutex);
@@ -267,12 +268,13 @@ u16 hygon_nb_num(void)
}
EXPORT_SYMBOL_GPL(hygon_nb_num);

static int get_df1_register(struct pci_dev *misc, int offset, u32 *value)
static int get_df_register(struct pci_dev *misc, u8 func, int offset, u32 *value)
{
	struct pci_dev *df_f1 = NULL;
	struct pci_dev *df_func = NULL;
	u32 device;
	int err;

	if (func == 1) {
		switch (boot_cpu_data.x86_model) {
		case 0x4:
			device = PCI_DEVICE_ID_HYGON_18H_M04H_DF_F1;
@@ -289,21 +291,32 @@ static int get_df1_register(struct pci_dev *misc, int offset, u32 *value)
		default:
			return -ENODEV;
		}
	} else if (func == 5) {
		switch (boot_cpu_data.x86_model) {
		case 0x6:
			device = PCI_DEVICE_ID_HYGON_18H_M06H_DF_F5;
			break;
		default:
			return -ENODEV;
		}
	} else {
		return -ENODEV;
	}

	while ((df_f1 = pci_get_device(misc->vendor, device, df_f1)))
		if (pci_domain_nr(df_f1->bus) == pci_domain_nr(misc->bus) &&
		    df_f1->bus->number == misc->bus->number &&
		    PCI_SLOT(df_f1->devfn) == PCI_SLOT(misc->devfn))
	while ((df_func = pci_get_device(misc->vendor, device, df_func)))
		if (pci_domain_nr(df_func->bus) == pci_domain_nr(misc->bus) &&
		    df_func->bus->number == misc->bus->number &&
		    PCI_SLOT(df_func->devfn) == PCI_SLOT(misc->devfn))
			break;

	if (!df_f1) {
		pr_warn("Error getting DF F1 device.\n");
	if (!df_func) {
		pr_warn("Error getting DF F%d device.\n", func);
		return -ENODEV;
	}

	err = pci_read_config_dword(df_f1, offset, value);
	err = pci_read_config_dword(df_func, offset, value);
	if (err)
		pr_warn("Error reading DF F1 register.\n");
		pr_warn("Error reading DF F%d register.\n", func);

	return err;
}
@@ -313,9 +326,15 @@ int get_df_id(struct pci_dev *misc, u8 *id)
	u32 value;
	int ret;

	if (boot_cpu_data.x86_model == 0x6) {
		/* F5x180[19:16]: DF ID */
		ret = get_df_register(misc, 5, 0x180, &value);
		*id = (value >> 16) & 0xf;
	} else {
		/* F1x200[23:20]: DF ID */
	ret = get_df1_register(misc, 0x200, &value);
		ret = get_df_register(misc, 1, 0x200, &value);
		*id = (value >> 20) & 0xf;
	}

	return ret;
}
@@ -327,7 +346,7 @@ static u8 get_socket_num(struct pci_dev *misc)
	int ret;

	/* F1x200[7:0]: Which socket is present. */
	ret = get_df1_register(misc, 0x200, &value);
	ret = get_df_register(misc, 1, 0x200, &value);

	return ret ? 0 : hweight8(value & 0xff);
}
+11 −11
Original line number Diff line number Diff line
@@ -760,12 +760,7 @@ static int umc_normaddr_to_sysaddr(u64 norm_addr, u16 nid, u8 umc, u64 *sys_addr

	/* Remove HiAddrOffset from normalized address, if enabled: */
	if (tmp & BIT(0)) {
		u64 hi_addr_offset;

		if (hygon_f18h_m4h())
			hi_addr_offset = (tmp & GENMASK_ULL(31, 18)) << 8;
		else
			hi_addr_offset = (tmp & GENMASK_ULL(31, 20)) << 8;
		u64 hi_addr_offset = (tmp & GENMASK_ULL(31, 20)) << 8;

		if (norm_addr >= hi_addr_offset) {
			ret_addr -= hi_addr_offset;
@@ -814,10 +809,6 @@ static int umc_normaddr_to_sysaddr(u64 norm_addr, u16 nid, u8 umc, u64 *sys_addr
	switch (intlv_num_chan) {
	case 0:	intlv_num_chan = 0; break;
	case 1: intlv_num_chan = 1; break;
	case 2:
		if (hygon_f18h_m4h())
			intlv_num_chan = 2;
		break;
	case 3: intlv_num_chan = 2; break;
	case 5:	intlv_num_chan = 3; break;
	case 7:	intlv_num_chan = 4; break;
@@ -826,6 +817,9 @@ static int umc_normaddr_to_sysaddr(u64 norm_addr, u16 nid, u8 umc, u64 *sys_addr
		hash_enabled = true;
		break;
	default:
		if (hygon_f18h_m4h() && boot_cpu_data.x86_model == 0x4 &&
		    intlv_num_chan == 2)
			break;
		pr_err("%s: Invalid number of interleaved channels %d.\n",
			__func__, intlv_num_chan);
		goto out_err;
@@ -2977,6 +2971,7 @@ static void decode_umc_error(int node_id, struct mce *m)
	struct amd64_pvt *pvt;
	struct err_info err;
	u64 sys_addr;
	u8 umc;

	mci = edac_mc_find(node_id);
	if (!mci)
@@ -3007,7 +3002,12 @@ static void decode_umc_error(int node_id, struct mce *m)

	err.csrow = m->synd & 0x7;

	if (umc_normaddr_to_sysaddr(m->addr, pvt->mc_node_id, err.channel, &sys_addr)) {
	if (hygon_f18h_m4h() && boot_cpu_data.x86_model == 0x6)
		umc = err.channel << 1;
	else
		umc = err.channel;

	if (umc_normaddr_to_sysaddr(m->addr, pvt->mc_node_id, umc, &sys_addr)) {
		err.err_code = ERR_NORM_ADDR;
		goto log_error;
	}