aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/edac/edac_mc.c
diff options
context:
space:
mode:
authorDoug Thompson <dougthompson@xmission.com>2007-07-19 04:50:27 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-07-19 13:04:57 -0400
commit8096cfafbb7ad3cb1a286ae7e8086167f4ebb4b6 (patch)
tree27b859beffef019095db810244f93e10473ea06f /drivers/edac/edac_mc.c
parentd45e7823baf655ced91c7987fb4ba9aae990ad6d (diff)
drivers/edac: fix edac_mc sysfs completion code
This patch refactors the 'releasing' of kobjects for the edac_mc type of device. The correct pattern of kobject release is followed. As internal kobjs are allocated they bump a ref count on the top level kobj. It in turn has a module ref count on the edac_core module. When internal kobjects are released, they dec the ref count on the top level kobj. When the top level kobj reaches zero, it decrements the ref count on the edac_core object, allow it to be unloaded, as all resources have all now been released. Cc: Alan Cox alan@lxorguk.ukuu.org.uk Signed-off-by: Doug Thompson <dougthompson@xmission.com> Acked-by: Greg KH <greg@kroah.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/edac/edac_mc.c')
-rw-r--r--drivers/edac/edac_mc.c36
1 files changed, 21 insertions, 15 deletions
diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c
index 6e4c94e9654a..2d53cb38868a 100644
--- a/drivers/edac/edac_mc.c
+++ b/drivers/edac/edac_mc.c
@@ -137,6 +137,7 @@ struct mem_ctl_info *edac_mc_alloc(unsigned sz_pvt, unsigned nr_csrows,
137 void *pvt; 137 void *pvt;
138 unsigned size; 138 unsigned size;
139 int row, chn; 139 int row, chn;
140 int err;
140 141
141 /* Figure out the offsets of the various items from the start of an mc 142 /* Figure out the offsets of the various items from the start of an mc
142 * structure. We want the alignment of each item to be at least as 143 * structure. We want the alignment of each item to be at least as
@@ -149,7 +150,8 @@ struct mem_ctl_info *edac_mc_alloc(unsigned sz_pvt, unsigned nr_csrows,
149 pvt = edac_align_ptr(&chi[nr_chans * nr_csrows], sz_pvt); 150 pvt = edac_align_ptr(&chi[nr_chans * nr_csrows], sz_pvt);
150 size = ((unsigned long)pvt) + sz_pvt; 151 size = ((unsigned long)pvt) + sz_pvt;
151 152
152 if ((mci = kmalloc(size, GFP_KERNEL)) == NULL) 153 mci = kzalloc(size, GFP_KERNEL);
154 if (mci == NULL)
153 return NULL; 155 return NULL;
154 156
155 /* Adjust pointers so they point within the memory we just allocated 157 /* Adjust pointers so they point within the memory we just allocated
@@ -182,20 +184,34 @@ struct mem_ctl_info *edac_mc_alloc(unsigned sz_pvt, unsigned nr_csrows,
182 184
183 mci->op_state = OP_ALLOC; 185 mci->op_state = OP_ALLOC;
184 186
187 /*
188 * Initialize the 'root' kobj for the edac_mc controller
189 */
190 err = edac_mc_register_sysfs_main_kobj(mci);
191 if (err) {
192 kfree(mci);
193 return NULL;
194 }
195
196 /* at this point, the root kobj is valid, and in order to
197 * 'free' the object, then the function:
198 * edac_mc_unregister_sysfs_main_kobj() must be called
199 * which will perform kobj unregistration and the actual free
200 * will occur during the kobject callback operation
201 */
185 return mci; 202 return mci;
186} 203}
187
188EXPORT_SYMBOL_GPL(edac_mc_alloc); 204EXPORT_SYMBOL_GPL(edac_mc_alloc);
189 205
190/** 206/**
191 * edac_mc_free: Free a previously allocated 'mci' structure 207 * edac_mc_free
208 * 'Free' a previously allocated 'mci' structure
192 * @mci: pointer to a struct mem_ctl_info structure 209 * @mci: pointer to a struct mem_ctl_info structure
193 */ 210 */
194void edac_mc_free(struct mem_ctl_info *mci) 211void edac_mc_free(struct mem_ctl_info *mci)
195{ 212{
196 kfree(mci); 213 edac_mc_unregister_sysfs_main_kobj(mci);
197} 214}
198
199EXPORT_SYMBOL_GPL(edac_mc_free); 215EXPORT_SYMBOL_GPL(edac_mc_free);
200 216
201static struct mem_ctl_info *find_mci_by_dev(struct device *dev) 217static struct mem_ctl_info *find_mci_by_dev(struct device *dev)
@@ -391,7 +407,6 @@ struct mem_ctl_info *edac_mc_find(int idx)
391 407
392 return NULL; 408 return NULL;
393} 409}
394
395EXPORT_SYMBOL(edac_mc_find); 410EXPORT_SYMBOL(edac_mc_find);
396 411
397/** 412/**
@@ -465,7 +480,6 @@ fail0:
465 mutex_unlock(&mem_ctls_mutex); 480 mutex_unlock(&mem_ctls_mutex);
466 return 1; 481 return 1;
467} 482}
468
469EXPORT_SYMBOL_GPL(edac_mc_add_mc); 483EXPORT_SYMBOL_GPL(edac_mc_add_mc);
470 484
471/** 485/**
@@ -501,7 +515,6 @@ struct mem_ctl_info *edac_mc_del_mc(struct device *dev)
501 mci->mod_name, mci->ctl_name, dev_name(mci)); 515 mci->mod_name, mci->ctl_name, dev_name(mci));
502 return mci; 516 return mci;
503} 517}
504
505EXPORT_SYMBOL_GPL(edac_mc_del_mc); 518EXPORT_SYMBOL_GPL(edac_mc_del_mc);
506 519
507static void edac_mc_scrub_block(unsigned long page, unsigned long offset, 520static void edac_mc_scrub_block(unsigned long page, unsigned long offset,
@@ -571,7 +584,6 @@ int edac_mc_find_csrow_by_page(struct mem_ctl_info *mci, unsigned long page)
571 584
572 return row; 585 return row;
573} 586}
574
575EXPORT_SYMBOL_GPL(edac_mc_find_csrow_by_page); 587EXPORT_SYMBOL_GPL(edac_mc_find_csrow_by_page);
576 588
577/* FIXME - setable log (warning/emerg) levels */ 589/* FIXME - setable log (warning/emerg) levels */
@@ -636,7 +648,6 @@ void edac_mc_handle_ce(struct mem_ctl_info *mci,
636 mci->csrows[row].grain); 648 mci->csrows[row].grain);
637 } 649 }
638} 650}
639
640EXPORT_SYMBOL_GPL(edac_mc_handle_ce); 651EXPORT_SYMBOL_GPL(edac_mc_handle_ce);
641 652
642void edac_mc_handle_ce_no_info(struct mem_ctl_info *mci, const char *msg) 653void edac_mc_handle_ce_no_info(struct mem_ctl_info *mci, const char *msg)
@@ -648,7 +659,6 @@ void edac_mc_handle_ce_no_info(struct mem_ctl_info *mci, const char *msg)
648 mci->ce_noinfo_count++; 659 mci->ce_noinfo_count++;
649 mci->ce_count++; 660 mci->ce_count++;
650} 661}
651
652EXPORT_SYMBOL_GPL(edac_mc_handle_ce_no_info); 662EXPORT_SYMBOL_GPL(edac_mc_handle_ce_no_info);
653 663
654void edac_mc_handle_ue(struct mem_ctl_info *mci, 664void edac_mc_handle_ue(struct mem_ctl_info *mci,
@@ -702,7 +712,6 @@ void edac_mc_handle_ue(struct mem_ctl_info *mci,
702 mci->ue_count++; 712 mci->ue_count++;
703 mci->csrows[row].ue_count++; 713 mci->csrows[row].ue_count++;
704} 714}
705
706EXPORT_SYMBOL_GPL(edac_mc_handle_ue); 715EXPORT_SYMBOL_GPL(edac_mc_handle_ue);
707 716
708void edac_mc_handle_ue_no_info(struct mem_ctl_info *mci, const char *msg) 717void edac_mc_handle_ue_no_info(struct mem_ctl_info *mci, const char *msg)
@@ -716,7 +725,6 @@ void edac_mc_handle_ue_no_info(struct mem_ctl_info *mci, const char *msg)
716 mci->ue_noinfo_count++; 725 mci->ue_noinfo_count++;
717 mci->ue_count++; 726 mci->ue_count++;
718} 727}
719
720EXPORT_SYMBOL_GPL(edac_mc_handle_ue_no_info); 728EXPORT_SYMBOL_GPL(edac_mc_handle_ue_no_info);
721 729
722/************************************************************* 730/*************************************************************
@@ -784,7 +792,6 @@ void edac_mc_handle_fbd_ue(struct mem_ctl_info *mci,
784 "labels \"%s\": %s\n", csrow, channela, 792 "labels \"%s\": %s\n", csrow, channela,
785 channelb, labels, msg); 793 channelb, labels, msg);
786} 794}
787
788EXPORT_SYMBOL(edac_mc_handle_fbd_ue); 795EXPORT_SYMBOL(edac_mc_handle_fbd_ue);
789 796
790/************************************************************* 797/*************************************************************
@@ -824,7 +831,6 @@ void edac_mc_handle_fbd_ce(struct mem_ctl_info *mci,
824 mci->csrows[csrow].ce_count++; 831 mci->csrows[csrow].ce_count++;
825 mci->csrows[csrow].channels[channel].ce_count++; 832 mci->csrows[csrow].channels[channel].ce_count++;
826} 833}
827
828EXPORT_SYMBOL(edac_mc_handle_fbd_ce); 834EXPORT_SYMBOL(edac_mc_handle_fbd_ce);
829 835
830/* 836/*