aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/edac/edac_mc.c
diff options
context:
space:
mode:
authorGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
committerGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
commitc71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch)
treeecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /drivers/edac/edac_mc.c
parentea53c912f8a86a8567697115b6a0d8152beee5c8 (diff)
parent6a00f206debf8a5c8899055726ad127dbeeed098 (diff)
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts: litmus/sched_cedf.c
Diffstat (limited to 'drivers/edac/edac_mc.c')
-rw-r--r--drivers/edac/edac_mc.c44
1 files changed, 25 insertions, 19 deletions
diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c
index 6b21e25f7a84..d69144a09043 100644
--- a/drivers/edac/edac_mc.c
+++ b/drivers/edac/edac_mc.c
@@ -76,6 +76,8 @@ static void edac_mc_dump_mci(struct mem_ctl_info *mci)
76 debugf3("\tpvt_info = %p\n\n", mci->pvt_info); 76 debugf3("\tpvt_info = %p\n\n", mci->pvt_info);
77} 77}
78 78
79#endif /* CONFIG_EDAC_DEBUG */
80
79/* 81/*
80 * keep those in sync with the enum mem_type 82 * keep those in sync with the enum mem_type
81 */ 83 */
@@ -100,8 +102,6 @@ const char *edac_mem_types[] = {
100}; 102};
101EXPORT_SYMBOL_GPL(edac_mem_types); 103EXPORT_SYMBOL_GPL(edac_mem_types);
102 104
103#endif /* CONFIG_EDAC_DEBUG */
104
105/* 'ptr' points to a possibly unaligned item X such that sizeof(X) is 'size'. 105/* 'ptr' points to a possibly unaligned item X such that sizeof(X) is 'size'.
106 * Adjust 'ptr' so that its alignment is at least as stringent as what the 106 * Adjust 'ptr' so that its alignment is at least as stringent as what the
107 * compiler would provide for X and return the aligned result. 107 * compiler would provide for X and return the aligned result.
@@ -207,6 +207,7 @@ struct mem_ctl_info *edac_mc_alloc(unsigned sz_pvt, unsigned nr_csrows,
207 } 207 }
208 208
209 mci->op_state = OP_ALLOC; 209 mci->op_state = OP_ALLOC;
210 INIT_LIST_HEAD(&mci->grp_kobj_list);
210 211
211 /* 212 /*
212 * Initialize the 'root' kobj for the edac_mc controller 213 * Initialize the 'root' kobj for the edac_mc controller
@@ -234,18 +235,24 @@ EXPORT_SYMBOL_GPL(edac_mc_alloc);
234 */ 235 */
235void edac_mc_free(struct mem_ctl_info *mci) 236void edac_mc_free(struct mem_ctl_info *mci)
236{ 237{
238 debugf1("%s()\n", __func__);
239
237 edac_mc_unregister_sysfs_main_kobj(mci); 240 edac_mc_unregister_sysfs_main_kobj(mci);
241
242 /* free the mci instance memory here */
243 kfree(mci);
238} 244}
239EXPORT_SYMBOL_GPL(edac_mc_free); 245EXPORT_SYMBOL_GPL(edac_mc_free);
240 246
241 247
242/* 248/**
243 * find_mci_by_dev 249 * find_mci_by_dev
244 * 250 *
245 * scan list of controllers looking for the one that manages 251 * scan list of controllers looking for the one that manages
246 * the 'dev' device 252 * the 'dev' device
253 * @dev: pointer to a struct device related with the MCI
247 */ 254 */
248static struct mem_ctl_info *find_mci_by_dev(struct device *dev) 255struct mem_ctl_info *find_mci_by_dev(struct device *dev)
249{ 256{
250 struct mem_ctl_info *mci; 257 struct mem_ctl_info *mci;
251 struct list_head *item; 258 struct list_head *item;
@@ -261,6 +268,7 @@ static struct mem_ctl_info *find_mci_by_dev(struct device *dev)
261 268
262 return NULL; 269 return NULL;
263} 270}
271EXPORT_SYMBOL_GPL(find_mci_by_dev);
264 272
265/* 273/*
266 * handler for EDAC to check if NMI type handler has asserted interrupt 274 * handler for EDAC to check if NMI type handler has asserted interrupt
@@ -439,20 +447,16 @@ fail1:
439 return 1; 447 return 1;
440} 448}
441 449
442static void complete_mc_list_del(struct rcu_head *head)
443{
444 struct mem_ctl_info *mci;
445
446 mci = container_of(head, struct mem_ctl_info, rcu);
447 INIT_LIST_HEAD(&mci->link);
448}
449
450static void del_mc_from_global_list(struct mem_ctl_info *mci) 450static void del_mc_from_global_list(struct mem_ctl_info *mci)
451{ 451{
452 atomic_dec(&edac_handlers); 452 atomic_dec(&edac_handlers);
453 list_del_rcu(&mci->link); 453 list_del_rcu(&mci->link);
454 call_rcu(&mci->rcu, complete_mc_list_del); 454
455 rcu_barrier(); 455 /* these are for safe removal of devices from global list while
456 * NMI handlers may be traversing list
457 */
458 synchronize_rcu();
459 INIT_LIST_HEAD(&mci->link);
456} 460}
457 461
458/** 462/**
@@ -578,14 +582,16 @@ struct mem_ctl_info *edac_mc_del_mc(struct device *dev)
578 return NULL; 582 return NULL;
579 } 583 }
580 584
581 /* marking MCI offline */
582 mci->op_state = OP_OFFLINE;
583
584 del_mc_from_global_list(mci); 585 del_mc_from_global_list(mci);
585 mutex_unlock(&mem_ctls_mutex); 586 mutex_unlock(&mem_ctls_mutex);
586 587
587 /* flush workq processes and remove sysfs */ 588 /* flush workq processes */
588 edac_mc_workq_teardown(mci); 589 edac_mc_workq_teardown(mci);
590
591 /* marking MCI offline */
592 mci->op_state = OP_OFFLINE;
593
594 /* remove from sysfs */
589 edac_remove_sysfs_mci_device(mci); 595 edac_remove_sysfs_mci_device(mci);
590 596
591 edac_printk(KERN_INFO, EDAC_MC, 597 edac_printk(KERN_INFO, EDAC_MC,
@@ -714,7 +720,7 @@ void edac_mc_handle_ce(struct mem_ctl_info *mci,
714 * Some MC's can remap memory so that it is still available 720 * Some MC's can remap memory so that it is still available
715 * at a different address when PCI devices map into memory. 721 * at a different address when PCI devices map into memory.
716 * MC's that can't do this lose the memory where PCI devices 722 * MC's that can't do this lose the memory where PCI devices
717 * are mapped. This mapping is MC dependant and so we call 723 * are mapped. This mapping is MC dependent and so we call
718 * back into the MC driver for it to map the MC page to 724 * back into the MC driver for it to map the MC page to
719 * a physical (CPU) page which can then be mapped to a virtual 725 * a physical (CPU) page which can then be mapped to a virtual
720 * page - which can then be scrubbed. 726 * page - which can then be scrubbed.