aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
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
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')
-rw-r--r--drivers/edac/amd76x_edac.c5
-rw-r--r--drivers/edac/e752x_edac.c5
-rw-r--r--drivers/edac/e7xxx_edac.c12
-rw-r--r--drivers/edac/edac_mc.c40
-rw-r--r--drivers/edac/edac_mc.h5
-rw-r--r--drivers/edac/i82860_edac.c7
-rw-r--r--drivers/edac/i82875p_edac.c5
-rw-r--r--drivers/edac/r82600_edac.c7
8 files changed, 37 insertions, 49 deletions
diff --git a/drivers/edac/amd76x_edac.c b/drivers/edac/amd76x_edac.c
index 821c252d414c..87bd8b4d561f 100644
--- a/drivers/edac/amd76x_edac.c
+++ b/drivers/edac/amd76x_edac.c
@@ -314,10 +314,9 @@ static void __devexit amd76x_remove_one(struct pci_dev *pdev)
314 314
315 debugf0("%s()\n", __func__); 315 debugf0("%s()\n", __func__);
316 316
317 if ((mci = edac_mc_find_mci_by_pdev(pdev)) == NULL) 317 if ((mci = edac_mc_del_mc(pdev)) == NULL)
318 return;
319 if (edac_mc_del_mc(mci))
320 return; 318 return;
319
321 edac_mc_free(mci); 320 edac_mc_free(mci);
322} 321}
323 322
diff --git a/drivers/edac/e752x_edac.c b/drivers/edac/e752x_edac.c
index 24446542d8d6..c86db23d3af3 100644
--- a/drivers/edac/e752x_edac.c
+++ b/drivers/edac/e752x_edac.c
@@ -976,10 +976,7 @@ static void __devexit e752x_remove_one(struct pci_dev *pdev)
976 976
977 debugf0("%s()\n", __func__); 977 debugf0("%s()\n", __func__);
978 978
979 if ((mci = edac_mc_find_mci_by_pdev(pdev)) == NULL) 979 if ((mci = edac_mc_del_mc(pdev)) == NULL)
980 return;
981
982 if (edac_mc_del_mc(mci))
983 return; 980 return;
984 981
985 pvt = (struct e752x_pvt *) mci->pvt_info; 982 pvt = (struct e752x_pvt *) mci->pvt_info;
diff --git a/drivers/edac/e7xxx_edac.c b/drivers/edac/e7xxx_edac.c
index 8b0da35ae47c..9b59c661f45e 100644
--- a/drivers/edac/e7xxx_edac.c
+++ b/drivers/edac/e7xxx_edac.c
@@ -510,12 +510,12 @@ static void __devexit e7xxx_remove_one(struct pci_dev *pdev)
510 510
511 debugf0("%s()\n", __func__); 511 debugf0("%s()\n", __func__);
512 512
513 if (((mci = edac_mc_find_mci_by_pdev(pdev)) != 0) && 513 if ((mci = edac_mc_del_mc(pdev)) == NULL)
514 !edac_mc_del_mc(mci)) { 514 return;
515 pvt = (struct e7xxx_pvt *) mci->pvt_info; 515
516 pci_dev_put(pvt->bridge_ck); 516 pvt = (struct e7xxx_pvt *) mci->pvt_info;
517 edac_mc_free(mci); 517 pci_dev_put(pvt->bridge_ck);
518 } 518 edac_mc_free(mci);
519} 519}
520 520
521 521
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
diff --git a/drivers/edac/edac_mc.h b/drivers/edac/edac_mc.h
index c9c1590db721..2cec157aaeba 100644
--- a/drivers/edac/edac_mc.h
+++ b/drivers/edac/edac_mc.h
@@ -410,14 +410,11 @@ void edac_mc_dump_csrow(struct csrow_info *csrow);
410#endif /* CONFIG_EDAC_DEBUG */ 410#endif /* CONFIG_EDAC_DEBUG */
411 411
412extern int edac_mc_add_mc(struct mem_ctl_info *mci); 412extern int edac_mc_add_mc(struct mem_ctl_info *mci);
413extern int edac_mc_del_mc(struct mem_ctl_info *mci); 413extern struct mem_ctl_info * edac_mc_del_mc(struct pci_dev *pdev);
414 414
415extern int edac_mc_find_csrow_by_page(struct mem_ctl_info *mci, 415extern int edac_mc_find_csrow_by_page(struct mem_ctl_info *mci,
416 unsigned long page); 416 unsigned long page);
417 417
418extern struct mem_ctl_info *edac_mc_find_mci_by_pdev(struct pci_dev
419 *pdev);
420
421extern void edac_mc_scrub_block(unsigned long page, 418extern void edac_mc_scrub_block(unsigned long page,
422 unsigned long offset, u32 size); 419 unsigned long offset, u32 size);
423 420
diff --git a/drivers/edac/i82860_edac.c b/drivers/edac/i82860_edac.c
index 942129df0212..688854260a0e 100644
--- a/drivers/edac/i82860_edac.c
+++ b/drivers/edac/i82860_edac.c
@@ -237,9 +237,10 @@ static void __devexit i82860_remove_one(struct pci_dev *pdev)
237 237
238 debugf0("%s()\n", __func__); 238 debugf0("%s()\n", __func__);
239 239
240 mci = edac_mc_find_mci_by_pdev(pdev); 240 if ((mci = edac_mc_del_mc(pdev)) == NULL)
241 if ((mci != NULL) && (edac_mc_del_mc(mci) == 0)) 241 return;
242 edac_mc_free(mci); 242
243 edac_mc_free(mci);
243} 244}
244 245
245static const struct pci_device_id i82860_pci_tbl[] __devinitdata = { 246static const struct pci_device_id i82860_pci_tbl[] __devinitdata = {
diff --git a/drivers/edac/i82875p_edac.c b/drivers/edac/i82875p_edac.c
index 40ba2be6169a..aad1900a4689 100644
--- a/drivers/edac/i82875p_edac.c
+++ b/drivers/edac/i82875p_edac.c
@@ -452,7 +452,7 @@ static void __devexit i82875p_remove_one(struct pci_dev *pdev)
452 452
453 debugf0("%s()\n", __func__); 453 debugf0("%s()\n", __func__);
454 454
455 if ((mci = edac_mc_find_mci_by_pdev(pdev)) == NULL) 455 if ((mci = edac_mc_del_mc(pdev)) == NULL)
456 return; 456 return;
457 457
458 pvt = (struct i82875p_pvt *) mci->pvt_info; 458 pvt = (struct i82875p_pvt *) mci->pvt_info;
@@ -467,9 +467,6 @@ static void __devexit i82875p_remove_one(struct pci_dev *pdev)
467 pci_dev_put(pvt->ovrfl_pdev); 467 pci_dev_put(pvt->ovrfl_pdev);
468 } 468 }
469 469
470 if (edac_mc_del_mc(mci))
471 return;
472
473 edac_mc_free(mci); 470 edac_mc_free(mci);
474} 471}
475 472
diff --git a/drivers/edac/r82600_edac.c b/drivers/edac/r82600_edac.c
index 787a7652c7ef..5966916d02bd 100644
--- a/drivers/edac/r82600_edac.c
+++ b/drivers/edac/r82600_edac.c
@@ -353,9 +353,10 @@ static void __devexit r82600_remove_one(struct pci_dev *pdev)
353 353
354 debugf0("%s()\n", __func__); 354 debugf0("%s()\n", __func__);
355 355
356 if (((mci = edac_mc_find_mci_by_pdev(pdev)) != NULL) && 356 if ((mci = edac_mc_del_mc(pdev)) == NULL)
357 !edac_mc_del_mc(mci)) 357 return;
358 edac_mc_free(mci); 358
359 edac_mc_free(mci);
359} 360}
360 361
361 362