summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab@redhat.com>2010-08-10 18:22:01 +0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2010-10-24 17:20:12 +0400
commit939747bd680eb09bb98792b17a5bfd2f525afe9d (patch)
tree694fc4a5bd213b7723217123a60c4361375667d4
parentf6f94e2ab1b33f0082ac22d71f66385a60d8157f (diff)
downloadlinux-939747bd680eb09bb98792b17a5bfd2f525afe9d.tar.xz
i7core_edac: Be sure that the edac pci handler will be properly released
With multi-sockets, more than one edac pci handler is enabled. Be sure to un-register all instances. Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r--drivers/edac/edac_core.h1
-rw-r--r--drivers/edac/edac_mc.c6
-rw-r--r--drivers/edac/i7core_edac.c38
3 files changed, 28 insertions, 17 deletions
diff --git a/drivers/edac/edac_core.h b/drivers/edac/edac_core.h
index ce7146677e9b..7450fd3bdf0b 100644
--- a/drivers/edac/edac_core.h
+++ b/drivers/edac/edac_core.h
@@ -810,6 +810,7 @@ extern struct mem_ctl_info *edac_mc_alloc(unsigned sz_pvt, unsigned nr_csrows,
extern int edac_mc_add_mc(struct mem_ctl_info *mci);
extern void edac_mc_free(struct mem_ctl_info *mci);
extern struct mem_ctl_info *edac_mc_find(int idx);
+extern struct mem_ctl_info *find_mci_by_dev(struct device *dev);
extern struct mem_ctl_info *edac_mc_del_mc(struct device *dev);
extern int edac_mc_find_csrow_by_page(struct mem_ctl_info *mci,
unsigned long page);
diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c
index 6b21e25f7a84..6b7e723e46be 100644
--- a/drivers/edac/edac_mc.c
+++ b/drivers/edac/edac_mc.c
@@ -239,13 +239,14 @@ void edac_mc_free(struct mem_ctl_info *mci)
EXPORT_SYMBOL_GPL(edac_mc_free);
-/*
+/**
* find_mci_by_dev
*
* scan list of controllers looking for the one that manages
* the 'dev' device
+ * @dev: pointer to a struct device related with the MCI
*/
-static struct mem_ctl_info *find_mci_by_dev(struct device *dev)
+struct mem_ctl_info *find_mci_by_dev(struct device *dev)
{
struct mem_ctl_info *mci;
struct list_head *item;
@@ -261,6 +262,7 @@ static struct mem_ctl_info *find_mci_by_dev(struct device *dev)
return NULL;
}
+EXPORT_SYMBOL_GPL(find_mci_by_dev);
/*
* handler for EDAC to check if NMI type handler has asserted interrupt
diff --git a/drivers/edac/i7core_edac.c b/drivers/edac/i7core_edac.c
index 0fd5b85a0f75..414182719640 100644
--- a/drivers/edac/i7core_edac.c
+++ b/drivers/edac/i7core_edac.c
@@ -261,6 +261,9 @@ struct i7core_pvt {
/* Count indicator to show errors not got */
unsigned mce_overrun;
+
+ /* Struct to control EDAC polling */
+ struct edac_pci_ctl_info *i7core_pci;
};
/* Static vars */
@@ -378,8 +381,6 @@ static const struct pci_device_id i7core_pci_tbl[] __devinitdata = {
{0,} /* 0 terminated list. */
};
-static struct edac_pci_ctl_info *i7core_pci;
-
/****************************************************************************
Anciliary status routines
****************************************************************************/
@@ -1906,9 +1907,9 @@ static int i7core_register_mci(struct i7core_dev *i7core_dev,
}
/* allocating generic PCI control info */
- i7core_pci = edac_pci_create_generic_ctl(&i7core_dev->pdev[0]->dev,
+ pvt->i7core_pci = edac_pci_create_generic_ctl(&i7core_dev->pdev[0]->dev,
EDAC_MOD_STR);
- if (unlikely(!i7core_pci)) {
+ if (unlikely(!pvt->i7core_pci)) {
printk(KERN_WARNING
"%s(): Unable to create PCI control\n",
__func__);
@@ -2008,12 +2009,10 @@ static void __devexit i7core_remove(struct pci_dev *pdev)
{
struct mem_ctl_info *mci;
struct i7core_dev *i7core_dev, *tmp;
+ struct i7core_pvt *pvt;
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
@@ -2024,19 +2023,28 @@ static void __devexit i7core_remove(struct pci_dev *pdev)
mutex_lock(&i7core_edac_lock);
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;
-
+ mci = find_mci_by_dev(&i7core_dev->pdev[0]->dev);
+ if (unlikely(!mci || !mci->pvt_info)) {
+ i7core_printk(KERN_ERR,
+ "Couldn't find mci hanler\n");
+ } else {
+ pvt = mci->pvt_info;
i7core_dev = pvt->i7core_dev;
+
+ if (likely(pvt->i7core_pci))
+ edac_pci_release_generic_ctl(pvt->i7core_pci);
+ else
+ i7core_printk(KERN_ERR,
+ "Couldn't find mem_ctl_info for socket %d\n",
+ i7core_dev->socket);
+ pvt->i7core_pci = NULL;
+
+ edac_mc_del_mc(&i7core_dev->pdev[0]->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);
}
}
probed--;