aboutsummaryrefslogtreecommitdiff
path: root/drivers/edac
diff options
context:
space:
mode:
authorMauro Carvalho Chehab2009-09-05 23:06:50 -0300
committerMauro Carvalho Chehab2010-05-10 11:45:00 -0300
commit22e6bcbdcf9279321dbe646c5a234b816db12881 (patch)
tree1488af672bbf9b4ffd5afd35c450c95b4fd8a32b /drivers/edac
parent0f062792b48dc8389fb18cbfb9318625886644c7 (diff)
i7core_edac: change remove module strategy
The old remove module stragegy didn't work on devices with multiple cores, since only one PCI device is used to open all mc's, due to Nehalem nature. Also, it were based at pdev value. However, this doesn't point to the pci device used at mci->dev. So, instead, it unregisters all devices at once, deleting them from the device list. Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/edac')
-rw-r--r--drivers/edac/i7core_edac.c55
1 files changed, 35 insertions, 20 deletions
diff --git a/drivers/edac/i7core_edac.c b/drivers/edac/i7core_edac.c
index 391348bf93d2..c3fec5de3e51 100644
--- a/drivers/edac/i7core_edac.c
+++ b/drivers/edac/i7core_edac.c
@@ -1138,11 +1138,18 @@ static void i7core_put_devices(struct i7core_dev *i7core_dev)
{
int i;
- for (i = 0; i < N_DEVS; i++)
- pci_dev_put(i7core_dev->pdev[i]);
-
- list_del(&i7core_dev->list);
+ debugf0(__FILE__ ": %s()\n", __func__);
+ for (i = 0; i < N_DEVS; i++) {
+ struct pci_dev *pdev = i7core_dev->pdev[i];
+ if (!pdev)
+ continue;
+ debugf0("Removing dev %02x:%02x.%d\n",
+ pdev->bus->number,
+ PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn));
+ pci_dev_put(pdev);
+ }
kfree(i7core_dev->pdev);
+ list_del(&i7core_dev->list);
kfree(i7core_dev);
}
@@ -1863,31 +1870,39 @@ fail0:
static void __devexit i7core_remove(struct pci_dev *pdev)
{
struct mem_ctl_info *mci;
- struct i7core_pvt *pvt;
- struct i7core_dev *i7core_dev;
+ struct i7core_dev *i7core_dev, *tmp;
debugf0(__FILE__ ": %s()\n", __func__);
if (i7core_pci)
edac_pci_release_generic_ctl(i7core_pci);
+ /*
+ * we have a trouble here: pdev value for removal will be wrong, since
+ * it will point to the X58 register used to detect that the machine
+ * is a Nehalem or upper design. However, due to the way several PCI
+ * devices are grouped together to provide MC functionality, we need
+ * to use a different method for releasing the devices
+ */
- mci = edac_mc_del_mc(&pdev->dev);
- if (!mci)
- return;
-
- /* Unregisters on edac_mce in order to receive memory errors */
- pvt = mci->pvt_info;
- i7core_dev = pvt->i7core_dev;
- edac_mce_unregister(&pvt->edac_mce);
-
- /* retrieve references to resources, and free those resources */
mutex_lock(&i7core_edac_lock);
- i7core_put_devices(i7core_dev);
+ list_for_each_entry_safe(i7core_dev, tmp, &i7core_edac_list, list) {
+ mci = edac_mc_del_mc(&i7core_dev->pdev[0]->dev);
+ if (mci) {
+ struct i7core_pvt *pvt = mci->pvt_info;
+
+ i7core_dev = pvt->i7core_dev;
+ edac_mce_unregister(&pvt->edac_mce);
+ kfree(mci->ctl_name);
+ edac_mc_free(mci);
+ i7core_put_devices(i7core_dev);
+ } else {
+ i7core_printk(KERN_ERR,
+ "Couldn't find mci for socket %d\n",
+ i7core_dev->socket);
+ }
+ }
mutex_unlock(&i7core_edac_lock);
-
- kfree(mci->ctl_name);
- edac_mc_free(mci);
}
MODULE_DEVICE_TABLE(pci, i7core_pci_tbl);