static DEFINE_MUTEX(i7core_edac_lock);
static int probed;
+static int use_pci_fixup;
+module_param(use_pci_fixup, int, 0444);
+MODULE_PARM_DESC(use_pci_fixup, "Enable PCI fixup to seek for hidden devices");
/*
* This is used for Nehalem-EP and Nehalem-EX devices, where the non-core
* registers start at bus 255, and are not reported by BIOS.
pci_dev_put(pdev);
}
kfree(i7core_dev->pdev);
- list_del(&i7core_dev->list);
- kfree(i7core_dev);
}
static void i7core_put_all_devices(void)
{
struct i7core_dev *i7core_dev, *tmp;
- list_for_each_entry_safe(i7core_dev, tmp, &i7core_edac_list, list)
+ list_for_each_entry_safe(i7core_dev, tmp, &i7core_edac_list, list) {
i7core_put_devices(i7core_dev);
+ list_del(&i7core_dev->list);
+ kfree(i7core_dev);
+ }
}
static void __init i7core_xeon_pci_fixup(const struct pci_id_table *table)
{
struct pci_dev *pdev = NULL;
int i;
+
/*
* On Xeon 55xx, the Intel Quckpath Arch Generic Non-core pci buses
* aren't announced by acpi. So, we need to use a legacy scan probing
}
return 0;
- return 0;
}
static int mci_bind_devs(struct mem_ctl_info *mci,
if (unlikely(!mci))
return -ENOMEM;
- debugf0("MC: " __FILE__ ": %s(): mci = %p\n", __func__, mci);
+ debugf0("MC: " __FILE__ ": %s(): mci = %p, dev = %p\n",
+ __func__, mci, &i7core_dev->pdev[0]->dev);
/* record ptr to the generic device */
mci->dev = &i7core_dev->pdev[0]->dev;
goto fail;
}
- /* allocating generic PCI control info */
- pvt->i7core_pci = edac_pci_create_generic_ctl(&i7core_dev->pdev[0]->dev,
- EDAC_MOD_STR);
- if (unlikely(!pvt->i7core_pci)) {
- printk(KERN_WARNING
- "%s(): Unable to create PCI control\n",
- __func__);
- printk(KERN_WARNING
- "%s(): PCI error report via EDAC not setup\n",
- __func__);
- }
-
/* Default error mask is any memory */
pvt->inject.channel = 0;
pvt->inject.dimm = -1;
pvt->edac_mce.priv = mci;
pvt->edac_mce.check_error = i7core_mce_check_error;
+ /* allocating generic PCI control info */
+ pvt->i7core_pci = edac_pci_create_generic_ctl(&i7core_dev->pdev[0]->dev,
+ EDAC_MOD_STR);
+ if (unlikely(!pvt->i7core_pci)) {
+ printk(KERN_WARNING
+ "%s(): Unable to create PCI control\n",
+ __func__);
+ printk(KERN_WARNING
+ "%s(): PCI error report via EDAC not setup\n",
+ __func__);
+ }
+
rc = edac_mce_register(&pvt->edac_mce);
if (unlikely(rc < 0)) {
debugf0("MC: " __FILE__
list_for_each_entry_safe(i7core_dev, tmp, &i7core_edac_list, list) {
mci = find_mci_by_dev(&i7core_dev->pdev[0]->dev);
if (unlikely(!mci || !mci->pvt_info)) {
- i7core_printk(KERN_ERR,
+ debugf0("MC: " __FILE__ ": %s(): dev = %p\n",
+ __func__, &i7core_dev->pdev[0]->dev);
+
+ i7core_printk(KERN_ERR,
"Couldn't find mci hanler\n");
} else {
pvt = mci->pvt_info;
i7core_dev = pvt->i7core_dev;
+ debugf0("MC: " __FILE__ ": %s(): mci = %p, dev = %p\n",
+ __func__, mci, &i7core_dev->pdev[0]->dev);
+
+ /* Disable MCE NMI handler */
+ edac_mce_unregister(&pvt->edac_mce);
+
+ /* Disable EDAC polling */
if (likely(pvt->i7core_pci))
edac_pci_release_generic_ctl(pvt->i7core_pci);
else
i7core_dev->socket);
pvt->i7core_pci = NULL;
+ /* Remove MC sysfs nodes */
edac_mc_del_mc(&i7core_dev->pdev[0]->dev);
- edac_mce_unregister(&pvt->edac_mce);
+ debugf1("%s: free mci struct\n", mci->ctl_name);
kfree(mci->ctl_name);
edac_mc_free(mci);
+
+ /* Release PCI resources */
i7core_put_devices(i7core_dev);
}
+ list_del(&i7core_dev->list);
+ kfree(i7core_dev);
}
probed--;
/* Ensure that the OPSTATE is set correctly for POLL or NMI */
opstate_init();
- i7core_xeon_pci_fixup(pci_dev_table);
+ if (use_pci_fixup)
+ i7core_xeon_pci_fixup(pci_dev_table);
pci_rc = pci_register_driver(&i7core_driver);