From 3f37a36b6282621d7c5a99b6911275f989766996 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Fri, 6 May 2016 19:44:27 +0200 Subject: [PATCH] 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: Borislav Petkov Cc: Yazen Ghannam --- drivers/edac/amd64_edac.c | 125 +++++++++++++------------------------- drivers/edac/amd64_edac.h | 2 +- 2 files changed, 44 insertions(+), 83 deletions(-) diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c index 651d96c93f22..624e2f78339c 100644 --- a/drivers/edac/amd64_edac.c +++ b/drivers/edac/amd64_edac.c @@ -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 @@ err_ret: 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 @@ err_out: 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 @@ err_ret: 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; diff --git a/drivers/edac/amd64_edac.h b/drivers/edac/amd64_edac.h index c0f248f3aaf9..c08870479054 100644 --- a/drivers/edac/amd64_edac.h +++ b/drivers/edac/amd64_edac.h @@ -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; }; -- 2.20.1