aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/edac/edac_mc.c
diff options
context:
space:
mode:
authorDave Peterson <dsp@llnl.gov>2006-03-26 04:38:50 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-03-26 11:57:07 -0500
commit18dbc337af5d6efd30cb9291e74722c8ad134fd3 (patch)
tree10163d19960173d29deb7a9d931dfcdfe2188975 /drivers/edac/edac_mc.c
parent472678ebd30d87cbe8d97562dcc0e46d1076040f (diff)
[PATCH] EDAC: protect memory controller list
- Fix code so we always hold mem_ctls_mutex while we are stepping through the list of mem_ctl_info structures. Otherwise bad things may happen if one task is stepping through the list while another task is modifying it. We may eventually want to use reference counting to manage the mem_ctl_info structures. In the meantime we may as well fix this bug. - Don't disable interrupts while we are walking the list of mem_ctl_info structures in check_mc_devices(). This is unnecessary. Signed-off-by: David S. Peterson <dsp@llnl.gov> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers/edac/edac_mc.c')
-rw-r--r--drivers/edac/edac_mc.c40
1 files changed, 18 insertions, 22 deletions
diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c
index 7ee9419234aa..ad812a4f8c99 100644
--- a/drivers/edac/edac_mc.c
+++ b/drivers/edac/edac_mc.c
@@ -1370,11 +1370,7 @@ void edac_mc_free(struct mem_ctl_info *mci)
1370 kfree(mci); 1370 kfree(mci);
1371} 1371}
1372 1372
1373 1373static struct mem_ctl_info *find_mci_by_pdev(struct pci_dev *pdev)
1374
1375EXPORT_SYMBOL(edac_mc_find_mci_by_pdev);
1376
1377struct mem_ctl_info *edac_mc_find_mci_by_pdev(struct pci_dev *pdev)
1378{ 1374{
1379 struct mem_ctl_info *mci; 1375 struct mem_ctl_info *mci;
1380 struct list_head *item; 1376 struct list_head *item;
@@ -1401,7 +1397,7 @@ static int add_mc_to_global_list (struct mem_ctl_info *mci)
1401 mci->mc_idx = 0; 1397 mci->mc_idx = 0;
1402 insert_before = &mc_devices; 1398 insert_before = &mc_devices;
1403 } else { 1399 } else {
1404 if (edac_mc_find_mci_by_pdev(mci->pdev)) { 1400 if (find_mci_by_pdev(mci->pdev)) {
1405 edac_printk(KERN_WARNING, EDAC_MC, 1401 edac_printk(KERN_WARNING, EDAC_MC,
1406 "%s (%s) %s %s already assigned %d\n", 1402 "%s (%s) %s %s already assigned %d\n",
1407 mci->pdev->dev.bus_id, 1403 mci->pdev->dev.bus_id,
@@ -1520,27 +1516,29 @@ EXPORT_SYMBOL(edac_mc_del_mc);
1520/** 1516/**
1521 * edac_mc_del_mc: Remove sysfs entries for specified mci structure and 1517 * edac_mc_del_mc: Remove sysfs entries for specified mci structure and
1522 * remove mci structure from global list 1518 * remove mci structure from global list
1523 * @mci: Pointer to struct mem_ctl_info structure 1519 * @pdev: Pointer to 'struct pci_dev' representing mci structure to remove.
1524 * 1520 *
1525 * Returns: 1521 * Return pointer to removed mci structure, or NULL if device not found.
1526 * 0 Success
1527 * 1 Failure
1528 */ 1522 */
1529int edac_mc_del_mc(struct mem_ctl_info *mci) 1523struct mem_ctl_info * edac_mc_del_mc(struct pci_dev *pdev)
1530{ 1524{
1531 int rc = 1; 1525 struct mem_ctl_info *mci;
1532 1526
1533 debugf0("MC%d: %s()\n", mci->mc_idx, __func__); 1527 debugf0("MC: %s()\n", __func__);
1534 edac_remove_sysfs_mci_device(mci);
1535 down(&mem_ctls_mutex); 1528 down(&mem_ctls_mutex);
1529
1530 if ((mci = find_mci_by_pdev(pdev)) == NULL) {
1531 up(&mem_ctls_mutex);
1532 return NULL;
1533 }
1534
1535 edac_remove_sysfs_mci_device(mci);
1536 del_mc_from_global_list(mci); 1536 del_mc_from_global_list(mci);
1537 up(&mem_ctls_mutex);
1537 edac_printk(KERN_INFO, EDAC_MC, 1538 edac_printk(KERN_INFO, EDAC_MC,
1538 "Removed device %d for %s %s: PCI %s\n", mci->mc_idx, 1539 "Removed device %d for %s %s: PCI %s\n", mci->mc_idx,
1539 mci->mod_name, mci->ctl_name, pci_name(mci->pdev)); 1540 mci->mod_name, mci->ctl_name, pci_name(mci->pdev));
1540 rc = 0; 1541 return mci;
1541 up(&mem_ctls_mutex);
1542
1543 return rc;
1544} 1542}
1545 1543
1546 1544
@@ -2018,14 +2016,12 @@ static inline void clear_pci_parity_errors(void)
2018 */ 2016 */
2019static inline void check_mc_devices (void) 2017static inline void check_mc_devices (void)
2020{ 2018{
2021 unsigned long flags;
2022 struct list_head *item; 2019 struct list_head *item;
2023 struct mem_ctl_info *mci; 2020 struct mem_ctl_info *mci;
2024 2021
2025 debugf3("%s()\n", __func__); 2022 debugf3("%s()\n", __func__);
2026 2023
2027 /* during poll, have interrupts off */ 2024 down(&mem_ctls_mutex);
2028 local_irq_save(flags);
2029 2025
2030 list_for_each(item, &mc_devices) { 2026 list_for_each(item, &mc_devices) {
2031 mci = list_entry(item, struct mem_ctl_info, link); 2027 mci = list_entry(item, struct mem_ctl_info, link);
@@ -2034,7 +2030,7 @@ static inline void check_mc_devices (void)
2034 mci->edac_check(mci); 2030 mci->edac_check(mci);
2035 } 2031 }
2036 2032
2037 local_irq_restore(flags); 2033 up(&mem_ctls_mutex);
2038} 2034}
2039 2035
2040 2036