forked from Minki/linux
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:
parent
953dee9bbd
commit
3f37a36b62
@ -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;
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user