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 <bp@suse.de>
Cc: Yazen Ghannam <yazen.ghannam@amd.com>
This commit is contained in:
Borislav Petkov 2016-05-06 19:44:27 +02:00
parent 953dee9bbd
commit 3f37a36b62
2 changed files with 44 additions and 83 deletions

View File

@ -15,11 +15,6 @@ module_param(ecc_enable_override, int, 0644);
static struct msr __percpu *msrs; 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 */ /* Per-node stuff */
static struct ecc_settings **ecc_stngs; static struct ecc_settings **ecc_stngs;
@ -1918,7 +1913,7 @@ static struct amd64_family_type family_types[] = {
[K8_CPUS] = { [K8_CPUS] = {
.ctl_name = "K8", .ctl_name = "K8",
.f1_id = PCI_DEVICE_ID_AMD_K8_NB_ADDRMAP, .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 = { .ops = {
.early_channel_count = k8_early_channel_count, .early_channel_count = k8_early_channel_count,
.map_sysaddr_to_csrow = k8_map_sysaddr_to_csrow, .map_sysaddr_to_csrow = k8_map_sysaddr_to_csrow,
@ -1928,7 +1923,7 @@ static struct amd64_family_type family_types[] = {
[F10_CPUS] = { [F10_CPUS] = {
.ctl_name = "F10h", .ctl_name = "F10h",
.f1_id = PCI_DEVICE_ID_AMD_10H_NB_MAP, .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 = { .ops = {
.early_channel_count = f1x_early_channel_count, .early_channel_count = f1x_early_channel_count,
.map_sysaddr_to_csrow = f1x_map_sysaddr_to_csrow, .map_sysaddr_to_csrow = f1x_map_sysaddr_to_csrow,
@ -1938,7 +1933,7 @@ static struct amd64_family_type family_types[] = {
[F15_CPUS] = { [F15_CPUS] = {
.ctl_name = "F15h", .ctl_name = "F15h",
.f1_id = PCI_DEVICE_ID_AMD_15H_NB_F1, .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 = { .ops = {
.early_channel_count = f1x_early_channel_count, .early_channel_count = f1x_early_channel_count,
.map_sysaddr_to_csrow = f1x_map_sysaddr_to_csrow, .map_sysaddr_to_csrow = f1x_map_sysaddr_to_csrow,
@ -1948,7 +1943,7 @@ static struct amd64_family_type family_types[] = {
[F15_M30H_CPUS] = { [F15_M30H_CPUS] = {
.ctl_name = "F15h_M30h", .ctl_name = "F15h_M30h",
.f1_id = PCI_DEVICE_ID_AMD_15H_M30H_NB_F1, .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 = { .ops = {
.early_channel_count = f1x_early_channel_count, .early_channel_count = f1x_early_channel_count,
.map_sysaddr_to_csrow = f1x_map_sysaddr_to_csrow, .map_sysaddr_to_csrow = f1x_map_sysaddr_to_csrow,
@ -1958,7 +1953,7 @@ static struct amd64_family_type family_types[] = {
[F15_M60H_CPUS] = { [F15_M60H_CPUS] = {
.ctl_name = "F15h_M60h", .ctl_name = "F15h_M60h",
.f1_id = PCI_DEVICE_ID_AMD_15H_M60H_NB_F1, .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 = { .ops = {
.early_channel_count = f1x_early_channel_count, .early_channel_count = f1x_early_channel_count,
.map_sysaddr_to_csrow = f1x_map_sysaddr_to_csrow, .map_sysaddr_to_csrow = f1x_map_sysaddr_to_csrow,
@ -1968,7 +1963,7 @@ static struct amd64_family_type family_types[] = {
[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,
.f3_id = PCI_DEVICE_ID_AMD_16H_NB_F3, .f2_id = PCI_DEVICE_ID_AMD_16H_NB_F2,
.ops = { .ops = {
.early_channel_count = f1x_early_channel_count, .early_channel_count = f1x_early_channel_count,
.map_sysaddr_to_csrow = f1x_map_sysaddr_to_csrow, .map_sysaddr_to_csrow = f1x_map_sysaddr_to_csrow,
@ -1978,7 +1973,7 @@ static struct amd64_family_type family_types[] = {
[F16_M30H_CPUS] = { [F16_M30H_CPUS] = {
.ctl_name = "F16h_M30h", .ctl_name = "F16h_M30h",
.f1_id = PCI_DEVICE_ID_AMD_16H_M30H_NB_F1, .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 = { .ops = {
.early_channel_count = f1x_early_channel_count, .early_channel_count = f1x_early_channel_count,
.map_sysaddr_to_csrow = f1x_map_sysaddr_to_csrow, .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 * Use pvt->F3 which contains the F3 CPU PCI device to get the related
* F1 (AddrMap) and F3 (Misc) devices. Return negative value on error. * 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 */ /* 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) { if (!pvt->F1) {
amd64_err("error address map device not found: " amd64_err("error address map device not found: "
"vendor %x device 0x%x (broken BIOS?)\n", "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; return -ENODEV;
} }
/* Reserve the MISC Device */ /* Reserve the DCT Device */
pvt->F3 = pci_get_related_function(pvt->F2->vendor, f3_id, pvt->F2); pvt->F2 = pci_get_related_function(pvt->F3->vendor, f2_id, pvt->F3);
if (!pvt->F3) { if (!pvt->F2) {
pci_dev_put(pvt->F1); pci_dev_put(pvt->F1);
pvt->F1 = NULL; 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", "vendor %x device 0x%x (broken BIOS?)\n",
PCI_VENDOR_ID_AMD, f3_id); PCI_VENDOR_ID_AMD, f2_id);
return -ENODEV; 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) static void free_mc_sibling_devs(struct amd64_pvt *pvt)
{ {
pci_dev_put(pvt->F1); 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 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 amd64_family_type *fam_type = NULL;
struct mem_ctl_info *mci = NULL; struct mem_ctl_info *mci = NULL;
struct edac_mc_layer layers[2]; struct edac_mc_layer layers[2];
struct amd64_pvt *pvt = NULL;
int err = 0, ret; int err = 0, ret;
u16 nid = amd_pci_dev_to_node_id(F2);
ret = -ENOMEM; ret = -ENOMEM;
pvt = kzalloc(sizeof(struct amd64_pvt), GFP_KERNEL); pvt = kzalloc(sizeof(struct amd64_pvt), GFP_KERNEL);
@ -2793,7 +2788,7 @@ static int init_one_instance(struct pci_dev *F2)
goto err_ret; goto err_ret;
pvt->mc_node_id = nid; pvt->mc_node_id = nid;
pvt->F2 = F2; pvt->F3 = F3;
ret = -EINVAL; ret = -EINVAL;
fam_type = per_family_init(pvt); fam_type = per_family_init(pvt);
@ -2801,7 +2796,7 @@ static int init_one_instance(struct pci_dev *F2)
goto err_free; goto err_free;
ret = -ENODEV; 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) if (err)
goto err_free; goto err_free;
@ -2836,7 +2831,7 @@ static int init_one_instance(struct pci_dev *F2)
goto err_siblings; goto err_siblings;
mci->pvt_info = pvt; mci->pvt_info = pvt;
mci->pdev = &pvt->F2->dev; mci->pdev = &pvt->F3->dev;
setup_mci_misc_attrs(mci, fam_type); 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); amd_register_ecc_decoder(decode_bus_error);
atomic_inc(&drv_instances);
return 0; return 0;
err_add_mc: err_add_mc:
@ -2872,19 +2865,11 @@ err_ret:
return ret; return ret;
} }
static int probe_one_instance(struct pci_dev *pdev, static int probe_one_instance(unsigned int nid)
const struct pci_device_id *mc_type)
{ {
u16 nid = amd_pci_dev_to_node_id(pdev);
struct pci_dev *F3 = node_to_amd_nb(nid)->misc; struct pci_dev *F3 = node_to_amd_nb(nid)->misc;
struct ecc_settings *s; struct ecc_settings *s;
int ret = 0; int ret;
ret = pci_enable_device(pdev);
if (ret < 0) {
edac_dbg(0, "ret=%d\n", ret);
return -EIO;
}
ret = -ENOMEM; ret = -ENOMEM;
s = kzalloc(sizeof(struct ecc_settings), GFP_KERNEL); s = kzalloc(sizeof(struct ecc_settings), GFP_KERNEL);
@ -2905,7 +2890,7 @@ static int probe_one_instance(struct pci_dev *pdev,
goto err_enable; goto err_enable;
} }
ret = init_one_instance(pdev); ret = init_one_instance(nid);
if (ret < 0) { if (ret < 0) {
amd64_err("Error probing instance: %d\n", nid); amd64_err("Error probing instance: %d\n", nid);
restore_ecc_error_reporting(s, nid, F3); restore_ecc_error_reporting(s, nid, F3);
@ -2921,19 +2906,18 @@ err_out:
return ret; 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 pci_dev *F3 = node_to_amd_nb(nid)->misc;
struct ecc_settings *s = ecc_stngs[nid]; 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); WARN_ON(!mci);
/* Remove from EDAC CORE tracking list */ /* Remove from EDAC CORE tracking list */
mci = edac_mc_del_mc(&pdev->dev); mci = edac_mc_del_mc(&F3->dev);
if (!mci) if (!mci)
return; return;
@ -2957,31 +2941,6 @@ static void remove_one_instance(struct pci_dev *pdev)
edac_mc_free(mci); 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) static void setup_pci_device(void)
{ {
struct mem_ctl_info *mci; struct mem_ctl_info *mci;
@ -3005,6 +2964,7 @@ static void setup_pci_device(void)
static int __init amd64_edac_init(void) static int __init amd64_edac_init(void)
{ {
int err = -ENODEV; int err = -ENODEV;
int i;
opstate_init(); opstate_init();
@ -3020,13 +2980,14 @@ static int __init amd64_edac_init(void)
if (!msrs) if (!msrs)
goto err_free; goto err_free;
err = pci_register_driver(&amd64_pci_driver); for (i = 0; i < amd_nb_num(); i++)
if (err) if (probe_one_instance(i)) {
goto err_pci; /* unwind properly */
while (--i >= 0)
remove_one_instance(i);
err = -ENODEV; goto err_pci;
if (!atomic_read(&drv_instances)) }
goto err_no_instances;
setup_pci_device(); setup_pci_device();
@ -3038,9 +2999,6 @@ static int __init amd64_edac_init(void)
return 0; return 0;
err_no_instances:
pci_unregister_driver(&amd64_pci_driver);
err_pci: err_pci:
msrs_free(msrs); msrs_free(msrs);
msrs = NULL; msrs = NULL;
@ -3055,10 +3013,13 @@ err_ret:
static void __exit amd64_edac_exit(void) static void __exit amd64_edac_exit(void)
{ {
int i;
if (pci_ctl) if (pci_ctl)
edac_pci_release_generic_ctl(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); kfree(ecc_stngs);
ecc_stngs = NULL; ecc_stngs = NULL;

View File

@ -422,7 +422,7 @@ struct low_ops {
struct amd64_family_type { struct amd64_family_type {
const char *ctl_name; const char *ctl_name;
u16 f1_id, f3_id; u16 f1_id, f2_id;
struct low_ops ops; struct low_ops ops;
}; };