diff options
author | Mauro Carvalho Chehab <mchehab@redhat.com> | 2010-08-10 10:22:01 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2010-10-24 09:20:12 -0400 |
commit | 939747bd680eb09bb98792b17a5bfd2f525afe9d (patch) | |
tree | 694fc4a5bd213b7723217123a60c4361375667d4 | |
parent | f6f94e2ab1b33f0082ac22d71f66385a60d8157f (diff) |
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.h | 1 | ||||
-rw-r--r-- | drivers/edac/edac_mc.c | 6 | ||||
-rw-r--r-- | drivers/edac/i7core_edac.c | 38 |
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, | |||
810 | extern int edac_mc_add_mc(struct mem_ctl_info *mci); | 810 | extern int edac_mc_add_mc(struct mem_ctl_info *mci); |
811 | extern void edac_mc_free(struct mem_ctl_info *mci); | 811 | extern void edac_mc_free(struct mem_ctl_info *mci); |
812 | extern struct mem_ctl_info *edac_mc_find(int idx); | 812 | extern struct mem_ctl_info *edac_mc_find(int idx); |
813 | extern struct mem_ctl_info *find_mci_by_dev(struct device *dev); | ||
813 | extern struct mem_ctl_info *edac_mc_del_mc(struct device *dev); | 814 | extern struct mem_ctl_info *edac_mc_del_mc(struct device *dev); |
814 | extern int edac_mc_find_csrow_by_page(struct mem_ctl_info *mci, | 815 | extern int edac_mc_find_csrow_by_page(struct mem_ctl_info *mci, |
815 | unsigned long page); | 816 | 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) | |||
239 | EXPORT_SYMBOL_GPL(edac_mc_free); | 239 | EXPORT_SYMBOL_GPL(edac_mc_free); |
240 | 240 | ||
241 | 241 | ||
242 | /* | 242 | /** |
243 | * find_mci_by_dev | 243 | * find_mci_by_dev |
244 | * | 244 | * |
245 | * scan list of controllers looking for the one that manages | 245 | * scan list of controllers looking for the one that manages |
246 | * the 'dev' device | 246 | * the 'dev' device |
247 | * @dev: pointer to a struct device related with the MCI | ||
247 | */ | 248 | */ |
248 | static struct mem_ctl_info *find_mci_by_dev(struct device *dev) | 249 | struct mem_ctl_info *find_mci_by_dev(struct device *dev) |
249 | { | 250 | { |
250 | struct mem_ctl_info *mci; | 251 | struct mem_ctl_info *mci; |
251 | struct list_head *item; | 252 | struct list_head *item; |
@@ -261,6 +262,7 @@ static struct mem_ctl_info *find_mci_by_dev(struct device *dev) | |||
261 | 262 | ||
262 | return NULL; | 263 | return NULL; |
263 | } | 264 | } |
265 | EXPORT_SYMBOL_GPL(find_mci_by_dev); | ||
264 | 266 | ||
265 | /* | 267 | /* |
266 | * handler for EDAC to check if NMI type handler has asserted interrupt | 268 | * 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 { | |||
261 | 261 | ||
262 | /* Count indicator to show errors not got */ | 262 | /* Count indicator to show errors not got */ |
263 | unsigned mce_overrun; | 263 | unsigned mce_overrun; |
264 | |||
265 | /* Struct to control EDAC polling */ | ||
266 | struct edac_pci_ctl_info *i7core_pci; | ||
264 | }; | 267 | }; |
265 | 268 | ||
266 | /* Static vars */ | 269 | /* Static vars */ |
@@ -378,8 +381,6 @@ static const struct pci_device_id i7core_pci_tbl[] __devinitdata = { | |||
378 | {0,} /* 0 terminated list. */ | 381 | {0,} /* 0 terminated list. */ |
379 | }; | 382 | }; |
380 | 383 | ||
381 | static struct edac_pci_ctl_info *i7core_pci; | ||
382 | |||
383 | /**************************************************************************** | 384 | /**************************************************************************** |
384 | Anciliary status routines | 385 | Anciliary status routines |
385 | ****************************************************************************/ | 386 | ****************************************************************************/ |
@@ -1906,9 +1907,9 @@ static int i7core_register_mci(struct i7core_dev *i7core_dev, | |||
1906 | } | 1907 | } |
1907 | 1908 | ||
1908 | /* allocating generic PCI control info */ | 1909 | /* allocating generic PCI control info */ |
1909 | i7core_pci = edac_pci_create_generic_ctl(&i7core_dev->pdev[0]->dev, | 1910 | pvt->i7core_pci = edac_pci_create_generic_ctl(&i7core_dev->pdev[0]->dev, |
1910 | EDAC_MOD_STR); | 1911 | EDAC_MOD_STR); |
1911 | if (unlikely(!i7core_pci)) { | 1912 | if (unlikely(!pvt->i7core_pci)) { |
1912 | printk(KERN_WARNING | 1913 | printk(KERN_WARNING |
1913 | "%s(): Unable to create PCI control\n", | 1914 | "%s(): Unable to create PCI control\n", |
1914 | __func__); | 1915 | __func__); |
@@ -2008,12 +2009,10 @@ static void __devexit i7core_remove(struct pci_dev *pdev) | |||
2008 | { | 2009 | { |
2009 | struct mem_ctl_info *mci; | 2010 | struct mem_ctl_info *mci; |
2010 | struct i7core_dev *i7core_dev, *tmp; | 2011 | struct i7core_dev *i7core_dev, *tmp; |
2012 | struct i7core_pvt *pvt; | ||
2011 | 2013 | ||
2012 | debugf0(__FILE__ ": %s()\n", __func__); | 2014 | debugf0(__FILE__ ": %s()\n", __func__); |
2013 | 2015 | ||
2014 | if (i7core_pci) | ||
2015 | edac_pci_release_generic_ctl(i7core_pci); | ||
2016 | |||
2017 | /* | 2016 | /* |
2018 | * we have a trouble here: pdev value for removal will be wrong, since | 2017 | * we have a trouble here: pdev value for removal will be wrong, since |
2019 | * it will point to the X58 register used to detect that the machine | 2018 | * 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) | |||
2024 | 2023 | ||
2025 | mutex_lock(&i7core_edac_lock); | 2024 | mutex_lock(&i7core_edac_lock); |
2026 | list_for_each_entry_safe(i7core_dev, tmp, &i7core_edac_list, list) { | 2025 | list_for_each_entry_safe(i7core_dev, tmp, &i7core_edac_list, list) { |
2027 | mci = edac_mc_del_mc(&i7core_dev->pdev[0]->dev); | 2026 | mci = find_mci_by_dev(&i7core_dev->pdev[0]->dev); |
2028 | if (mci) { | 2027 | if (unlikely(!mci || !mci->pvt_info)) { |
2029 | struct i7core_pvt *pvt = mci->pvt_info; | 2028 | i7core_printk(KERN_ERR, |
2030 | 2029 | "Couldn't find mci hanler\n"); | |
2030 | } else { | ||
2031 | pvt = mci->pvt_info; | ||
2031 | i7core_dev = pvt->i7core_dev; | 2032 | i7core_dev = pvt->i7core_dev; |
2033 | |||
2034 | if (likely(pvt->i7core_pci)) | ||
2035 | edac_pci_release_generic_ctl(pvt->i7core_pci); | ||
2036 | else | ||
2037 | i7core_printk(KERN_ERR, | ||
2038 | "Couldn't find mem_ctl_info for socket %d\n", | ||
2039 | i7core_dev->socket); | ||
2040 | pvt->i7core_pci = NULL; | ||
2041 | |||
2042 | edac_mc_del_mc(&i7core_dev->pdev[0]->dev); | ||
2043 | |||
2032 | edac_mce_unregister(&pvt->edac_mce); | 2044 | edac_mce_unregister(&pvt->edac_mce); |
2033 | kfree(mci->ctl_name); | 2045 | kfree(mci->ctl_name); |
2034 | edac_mc_free(mci); | 2046 | edac_mc_free(mci); |
2035 | i7core_put_devices(i7core_dev); | 2047 | i7core_put_devices(i7core_dev); |
2036 | } else { | ||
2037 | i7core_printk(KERN_ERR, | ||
2038 | "Couldn't find mci for socket %d\n", | ||
2039 | i7core_dev->socket); | ||
2040 | } | 2048 | } |
2041 | } | 2049 | } |
2042 | probed--; | 2050 | probed--; |