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

Commit 3f37a36b authored by Borislav Petkov's avatar Borislav Petkov
Browse files

EDAC, amd64_edac: Drop pci_register_driver() use



- remove homegrown instances counting.
- take F3 PCI device from amd_nb caching instead of F2 which was used with the
PCI core.

With those changes, the driver doesn't need to register a PCI driver and
relies on the northbridges caching which we do anyway on AMD.

Signed-off-by: default avatarBorislav Petkov <bp@suse.de>
Cc: Yazen Ghannam <yazen.ghannam@amd.com>
parent 953dee9b
Loading
Loading
Loading
Loading
+43 −82
Original line number Diff line number Diff line
@@ -15,11 +15,6 @@ module_param(ecc_enable_override, int, 0644);

static struct msr __percpu *msrs;

/*
 * count successfully initialized driver instances for setup_pci_device()
 */
static atomic_t drv_instances = ATOMIC_INIT(0);

/* Per-node stuff */
static struct ecc_settings **ecc_stngs;

@@ -1918,7 +1913,7 @@ static struct amd64_family_type family_types[] = {
	[K8_CPUS] = {
		.ctl_name = "K8",
		.f1_id = PCI_DEVICE_ID_AMD_K8_NB_ADDRMAP,
		.f3_id = PCI_DEVICE_ID_AMD_K8_NB_MISC,
		.f2_id = PCI_DEVICE_ID_AMD_K8_NB_MEMCTL,
		.ops = {
			.early_channel_count	= k8_early_channel_count,
			.map_sysaddr_to_csrow	= k8_map_sysaddr_to_csrow,
@@ -1928,7 +1923,7 @@ static struct amd64_family_type family_types[] = {
	[F10_CPUS] = {
		.ctl_name = "F10h",
		.f1_id = PCI_DEVICE_ID_AMD_10H_NB_MAP,
		.f3_id = PCI_DEVICE_ID_AMD_10H_NB_MISC,
		.f2_id = PCI_DEVICE_ID_AMD_10H_NB_DRAM,
		.ops = {
			.early_channel_count	= f1x_early_channel_count,
			.map_sysaddr_to_csrow	= f1x_map_sysaddr_to_csrow,
@@ -1938,7 +1933,7 @@ static struct amd64_family_type family_types[] = {
	[F15_CPUS] = {
		.ctl_name = "F15h",
		.f1_id = PCI_DEVICE_ID_AMD_15H_NB_F1,
		.f3_id = PCI_DEVICE_ID_AMD_15H_NB_F3,
		.f2_id = PCI_DEVICE_ID_AMD_15H_NB_F2,
		.ops = {
			.early_channel_count	= f1x_early_channel_count,
			.map_sysaddr_to_csrow	= f1x_map_sysaddr_to_csrow,
@@ -1948,7 +1943,7 @@ static struct amd64_family_type family_types[] = {
	[F15_M30H_CPUS] = {
		.ctl_name = "F15h_M30h",
		.f1_id = PCI_DEVICE_ID_AMD_15H_M30H_NB_F1,
		.f3_id = PCI_DEVICE_ID_AMD_15H_M30H_NB_F3,
		.f2_id = PCI_DEVICE_ID_AMD_15H_M30H_NB_F2,
		.ops = {
			.early_channel_count	= f1x_early_channel_count,
			.map_sysaddr_to_csrow	= f1x_map_sysaddr_to_csrow,
@@ -1958,7 +1953,7 @@ static struct amd64_family_type family_types[] = {
	[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,
		.f2_id = PCI_DEVICE_ID_AMD_15H_M60H_NB_F2,
		.ops = {
			.early_channel_count	= f1x_early_channel_count,
			.map_sysaddr_to_csrow	= f1x_map_sysaddr_to_csrow,
@@ -1968,7 +1963,7 @@ static struct amd64_family_type family_types[] = {
	[F16_CPUS] = {
		.ctl_name = "F16h",
		.f1_id = PCI_DEVICE_ID_AMD_16H_NB_F1,
		.f3_id = PCI_DEVICE_ID_AMD_16H_NB_F3,
		.f2_id = PCI_DEVICE_ID_AMD_16H_NB_F2,
		.ops = {
			.early_channel_count	= f1x_early_channel_count,
			.map_sysaddr_to_csrow	= f1x_map_sysaddr_to_csrow,
@@ -1978,7 +1973,7 @@ static struct amd64_family_type family_types[] = {
	[F16_M30H_CPUS] = {
		.ctl_name = "F16h_M30h",
		.f1_id = PCI_DEVICE_ID_AMD_16H_M30H_NB_F1,
		.f3_id = PCI_DEVICE_ID_AMD_16H_M30H_NB_F3,
		.f2_id = PCI_DEVICE_ID_AMD_16H_M30H_NB_F2,
		.ops = {
			.early_channel_count	= f1x_early_channel_count,
			.map_sysaddr_to_csrow	= f1x_map_sysaddr_to_csrow,
@@ -2227,13 +2222,13 @@ static inline void decode_bus_error(int node_id, struct mce *m)
}

/*
 * Use pvt->F2 which contains the F2 CPU PCI device to get the related
 * F1 (AddrMap) and F3 (Misc) devices. Return negative value on error.
 * Use pvt->F3 which contains the F3 CPU PCI device to get the related
 * F1 (AddrMap) and F2 (Dct) devices. Return negative value on error.
 */
static int reserve_mc_sibling_devs(struct amd64_pvt *pvt, u16 f1_id, u16 f3_id)
static int reserve_mc_sibling_devs(struct amd64_pvt *pvt, u16 f1_id, u16 f2_id)
{
	/* Reserve the ADDRESS MAP Device */
	pvt->F1 = pci_get_related_function(pvt->F2->vendor, f1_id, pvt->F2);
	pvt->F1 = pci_get_related_function(pvt->F3->vendor, f1_id, pvt->F3);
	if (!pvt->F1) {
		amd64_err("error address map device not found: "
			  "vendor %x device 0x%x (broken BIOS?)\n",
@@ -2241,15 +2236,15 @@ static int reserve_mc_sibling_devs(struct amd64_pvt *pvt, u16 f1_id, u16 f3_id)
		return -ENODEV;
	}

	/* Reserve the MISC Device */
	pvt->F3 = pci_get_related_function(pvt->F2->vendor, f3_id, pvt->F2);
	if (!pvt->F3) {
	/* Reserve the DCT Device */
	pvt->F2 = pci_get_related_function(pvt->F3->vendor, f2_id, pvt->F3);
	if (!pvt->F2) {
		pci_dev_put(pvt->F1);
		pvt->F1 = NULL;

		amd64_err("error F3 device not found: "
		amd64_err("error F2 device not found: "
			  "vendor %x device 0x%x (broken BIOS?)\n",
			  PCI_VENDOR_ID_AMD, f3_id);
			  PCI_VENDOR_ID_AMD, f2_id);

		return -ENODEV;
	}
@@ -2263,7 +2258,7 @@ static int reserve_mc_sibling_devs(struct amd64_pvt *pvt, u16 f1_id, u16 f3_id)
static void free_mc_sibling_devs(struct amd64_pvt *pvt)
{
	pci_dev_put(pvt->F1);
	pci_dev_put(pvt->F3);
	pci_dev_put(pvt->F2);
}

/*
@@ -2778,14 +2773,14 @@ static const struct attribute_group *amd64_edac_attr_groups[] = {
	NULL
};

static int init_one_instance(struct pci_dev *F2)
static int init_one_instance(unsigned int nid)
{
	struct amd64_pvt *pvt = NULL;
	struct pci_dev *F3 = node_to_amd_nb(nid)->misc;
	struct amd64_family_type *fam_type = NULL;
	struct mem_ctl_info *mci = NULL;
	struct edac_mc_layer layers[2];
	struct amd64_pvt *pvt = NULL;
	int err = 0, ret;
	u16 nid = amd_pci_dev_to_node_id(F2);

	ret = -ENOMEM;
	pvt = kzalloc(sizeof(struct amd64_pvt), GFP_KERNEL);
@@ -2793,7 +2788,7 @@ static int init_one_instance(struct pci_dev *F2)
		goto err_ret;

	pvt->mc_node_id	= nid;
	pvt->F2 = F2;
	pvt->F3 = F3;

	ret = -EINVAL;
	fam_type = per_family_init(pvt);
@@ -2801,7 +2796,7 @@ static int init_one_instance(struct pci_dev *F2)
		goto err_free;

	ret = -ENODEV;
	err = reserve_mc_sibling_devs(pvt, fam_type->f1_id, fam_type->f3_id);
	err = reserve_mc_sibling_devs(pvt, fam_type->f1_id, fam_type->f2_id);
	if (err)
		goto err_free;

@@ -2836,7 +2831,7 @@ static int init_one_instance(struct pci_dev *F2)
		goto err_siblings;

	mci->pvt_info = pvt;
	mci->pdev = &pvt->F2->dev;
	mci->pdev = &pvt->F3->dev;

	setup_mci_misc_attrs(mci, fam_type);

@@ -2855,8 +2850,6 @@ static int init_one_instance(struct pci_dev *F2)

	amd_register_ecc_decoder(decode_bus_error);

	atomic_inc(&drv_instances);

	return 0;

err_add_mc:
@@ -2872,19 +2865,11 @@ static int init_one_instance(struct pci_dev *F2)
	return ret;
}

static int probe_one_instance(struct pci_dev *pdev,
			      const struct pci_device_id *mc_type)
static int probe_one_instance(unsigned int nid)
{
	u16 nid = amd_pci_dev_to_node_id(pdev);
	struct pci_dev *F3 = node_to_amd_nb(nid)->misc;
	struct ecc_settings *s;
	int ret = 0;

	ret = pci_enable_device(pdev);
	if (ret < 0) {
		edac_dbg(0, "ret=%d\n", ret);
		return -EIO;
	}
	int ret;

	ret = -ENOMEM;
	s = kzalloc(sizeof(struct ecc_settings), GFP_KERNEL);
@@ -2905,7 +2890,7 @@ static int probe_one_instance(struct pci_dev *pdev,
			goto err_enable;
	}

	ret = init_one_instance(pdev);
	ret = init_one_instance(nid);
	if (ret < 0) {
		amd64_err("Error probing instance: %d\n", nid);
		restore_ecc_error_reporting(s, nid, F3);
@@ -2921,19 +2906,18 @@ static int probe_one_instance(struct pci_dev *pdev,
	return ret;
}

static void remove_one_instance(struct pci_dev *pdev)
static void remove_one_instance(unsigned int nid)
{
	struct mem_ctl_info *mci;
	struct amd64_pvt *pvt;
	u16 nid = amd_pci_dev_to_node_id(pdev);
	struct pci_dev *F3 = node_to_amd_nb(nid)->misc;
	struct ecc_settings *s = ecc_stngs[nid];
	struct mem_ctl_info *mci;
	struct amd64_pvt *pvt;

	mci = find_mci_by_dev(&pdev->dev);
	mci = find_mci_by_dev(&F3->dev);
	WARN_ON(!mci);

	/* Remove from EDAC CORE tracking list */
	mci = edac_mc_del_mc(&pdev->dev);
	mci = edac_mc_del_mc(&F3->dev);
	if (!mci)
		return;

@@ -2957,31 +2941,6 @@ static void remove_one_instance(struct pci_dev *pdev)
	edac_mc_free(mci);
}

/*
 * This table is part of the interface for loading drivers for PCI devices. The
 * PCI core identifies what devices are on a system during boot, and then
 * inquiry this table to see if this driver is for a given device found.
 */
static const struct pci_device_id amd64_pci_table[] = {
	{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_K8_NB_MEMCTL) },
	{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_10H_NB_DRAM) },
	{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_NB_F2) },
	{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_M30H_NB_F2) },
	{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_M60H_NB_F2) },
	{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_16H_NB_F2) },
	{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_16H_M30H_NB_F2) },
	{0, }
};
MODULE_DEVICE_TABLE(pci, amd64_pci_table);

static struct pci_driver amd64_pci_driver = {
	.name		= EDAC_MOD_STR,
	.probe		= probe_one_instance,
	.remove		= remove_one_instance,
	.id_table	= amd64_pci_table,
	.driver.probe_type = PROBE_FORCE_SYNCHRONOUS,
};

static void setup_pci_device(void)
{
	struct mem_ctl_info *mci;
@@ -3005,6 +2964,7 @@ static void setup_pci_device(void)
static int __init amd64_edac_init(void)
{
	int err = -ENODEV;
	int i;

	opstate_init();

@@ -3020,13 +2980,14 @@ static int __init amd64_edac_init(void)
	if (!msrs)
		goto err_free;

	err = pci_register_driver(&amd64_pci_driver);
	if (err)
		goto err_pci;
	for (i = 0; i < amd_nb_num(); i++)
		if (probe_one_instance(i)) {
			/* unwind properly */
			while (--i >= 0)
				remove_one_instance(i);

	err = -ENODEV;
	if (!atomic_read(&drv_instances))
		goto err_no_instances;
			goto err_pci;
		}

	setup_pci_device();

@@ -3038,9 +2999,6 @@ static int __init amd64_edac_init(void)

	return 0;

err_no_instances:
	pci_unregister_driver(&amd64_pci_driver);

err_pci:
	msrs_free(msrs);
	msrs = NULL;
@@ -3055,10 +3013,13 @@ static int __init amd64_edac_init(void)

static void __exit amd64_edac_exit(void)
{
	int i;

	if (pci_ctl)
		edac_pci_release_generic_ctl(pci_ctl);

	pci_unregister_driver(&amd64_pci_driver);
	for (i = 0; i < amd_nb_num(); i++)
		remove_one_instance(i);

	kfree(ecc_stngs);
	ecc_stngs = NULL;
+1 −1
Original line number Diff line number Diff line
@@ -422,7 +422,7 @@ struct low_ops {

struct amd64_family_type {
	const char *ctl_name;
	u16 f1_id, f3_id;
	u16 f1_id, f2_id;
	struct low_ops ops;
};