aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/edac/edac_mc.c76
-rw-r--r--drivers/edac/edac_mc.h9
2 files changed, 42 insertions, 43 deletions
diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c
index e6ecc7da38a5..7ee9419234aa 100644
--- a/drivers/edac/edac_mc.c
+++ b/drivers/edac/edac_mc.c
@@ -139,6 +139,12 @@ static struct sysdev_class edac_class = {
139static struct kobject edac_memctrl_kobj; 139static struct kobject edac_memctrl_kobj;
140static struct kobject edac_pci_kobj; 140static struct kobject edac_pci_kobj;
141 141
142/* We use these to wait for the reference counts on edac_memctrl_kobj and
143 * edac_pci_kobj to reach 0.
144 */
145static struct completion edac_memctrl_kobj_complete;
146static struct completion edac_pci_kobj_complete;
147
142/* 148/*
143 * /sys/devices/system/edac/mc; 149 * /sys/devices/system/edac/mc;
144 * data structures and methods 150 * data structures and methods
@@ -244,6 +250,7 @@ static struct memctrl_dev_attribute *memctrl_attr[] = {
244static void edac_memctrl_master_release(struct kobject *kobj) 250static void edac_memctrl_master_release(struct kobject *kobj)
245{ 251{
246 debugf1("%s()\n", __func__); 252 debugf1("%s()\n", __func__);
253 complete(&edac_memctrl_kobj_complete);
247} 254}
248 255
249static struct kobj_type ktype_memctrl = { 256static struct kobj_type ktype_memctrl = {
@@ -309,8 +316,12 @@ static void edac_sysfs_memctrl_teardown(void)
309#ifndef DISABLE_EDAC_SYSFS 316#ifndef DISABLE_EDAC_SYSFS
310 debugf0("MC: " __FILE__ ": %s()\n", __func__); 317 debugf0("MC: " __FILE__ ": %s()\n", __func__);
311 318
312 /* Unregister the MC's kobject */ 319 /* Unregister the MC's kobject and wait for reference count to reach
320 * 0.
321 */
322 init_completion(&edac_memctrl_kobj_complete);
313 kobject_unregister(&edac_memctrl_kobj); 323 kobject_unregister(&edac_memctrl_kobj);
324 wait_for_completion(&edac_memctrl_kobj_complete);
314 325
315 /* Unregister the 'edac' object */ 326 /* Unregister the 'edac' object */
316 sysdev_class_unregister(&edac_class); 327 sysdev_class_unregister(&edac_class);
@@ -563,6 +574,7 @@ static struct edac_pci_dev_attribute *edac_pci_attr[] = {
563static void edac_pci_release(struct kobject *kobj) 574static void edac_pci_release(struct kobject *kobj)
564{ 575{
565 debugf1("%s()\n", __func__); 576 debugf1("%s()\n", __func__);
577 complete(&edac_pci_kobj_complete);
566} 578}
567 579
568static struct kobj_type ktype_edac_pci = { 580static struct kobj_type ktype_edac_pci = {
@@ -610,8 +622,9 @@ static void edac_sysfs_pci_teardown(void)
610{ 622{
611#ifndef DISABLE_EDAC_SYSFS 623#ifndef DISABLE_EDAC_SYSFS
612 debugf0("%s()\n", __func__); 624 debugf0("%s()\n", __func__);
613 625 init_completion(&edac_pci_kobj_complete);
614 kobject_unregister(&edac_pci_kobj); 626 kobject_unregister(&edac_pci_kobj);
627 wait_for_completion(&edac_pci_kobj_complete);
615#endif 628#endif
616} 629}
617 630
@@ -800,7 +813,11 @@ static struct csrowdev_attribute *csrow_attr[] = {
800/* No memory to release */ 813/* No memory to release */
801static void edac_csrow_instance_release(struct kobject *kobj) 814static void edac_csrow_instance_release(struct kobject *kobj)
802{ 815{
816 struct csrow_info *cs;
817
803 debugf1("%s()\n", __func__); 818 debugf1("%s()\n", __func__);
819 cs = container_of(kobj, struct csrow_info, kobj);
820 complete(&cs->kobj_complete);
804} 821}
805 822
806static struct kobj_type ktype_csrow = { 823static struct kobj_type ktype_csrow = {
@@ -1055,11 +1072,10 @@ static struct mcidev_attribute *mci_attr[] = {
1055static void edac_mci_instance_release(struct kobject *kobj) 1072static void edac_mci_instance_release(struct kobject *kobj)
1056{ 1073{
1057 struct mem_ctl_info *mci; 1074 struct mem_ctl_info *mci;
1058 mci = container_of(kobj,struct mem_ctl_info,edac_mci_kobj);
1059 1075
1060 debugf0("%s() idx=%d calling kfree\n", __func__, mci->mc_idx); 1076 mci = to_mci(kobj);
1061 1077 debugf0("%s() idx=%d\n", __func__, mci->mc_idx);
1062 kfree(mci); 1078 complete(&mci->kobj_complete);
1063} 1079}
1064 1080
1065static struct kobj_type ktype_mci = { 1081static struct kobj_type ktype_mci = {
@@ -1131,21 +1147,23 @@ static int edac_create_sysfs_mci_device(struct mem_ctl_info *mci)
1131 } 1147 }
1132 } 1148 }
1133 1149
1134 /* Mark this MCI instance as having sysfs entries */
1135 mci->sysfs_active = MCI_SYSFS_ACTIVE;
1136
1137 return 0; 1150 return 0;
1138 1151
1139 1152
1140 /* CSROW error: backout what has already been registered, */ 1153 /* CSROW error: backout what has already been registered, */
1141fail1: 1154fail1:
1142 for ( i--; i >= 0; i--) { 1155 for ( i--; i >= 0; i--) {
1143 if (csrow->nr_pages > 0) 1156 if (csrow->nr_pages > 0) {
1157 init_completion(&csrow->kobj_complete);
1144 kobject_unregister(&mci->csrows[i].kobj); 1158 kobject_unregister(&mci->csrows[i].kobj);
1159 wait_for_completion(&csrow->kobj_complete);
1160 }
1145 } 1161 }
1146 1162
1147fail0: 1163fail0:
1164 init_completion(&mci->kobj_complete);
1148 kobject_unregister(edac_mci_kobj); 1165 kobject_unregister(edac_mci_kobj);
1166 wait_for_completion(&mci->kobj_complete);
1149 1167
1150 return err; 1168 return err;
1151} 1169}
@@ -1163,13 +1181,17 @@ static void edac_remove_sysfs_mci_device(struct mem_ctl_info *mci)
1163 1181
1164 /* remove all csrow kobjects */ 1182 /* remove all csrow kobjects */
1165 for (i = 0; i < mci->nr_csrows; i++) { 1183 for (i = 0; i < mci->nr_csrows; i++) {
1166 if (mci->csrows[i].nr_pages > 0) 1184 if (mci->csrows[i].nr_pages > 0) {
1185 init_completion(&mci->csrows[i].kobj_complete);
1167 kobject_unregister(&mci->csrows[i].kobj); 1186 kobject_unregister(&mci->csrows[i].kobj);
1187 wait_for_completion(&mci->csrows[i].kobj_complete);
1188 }
1168 } 1189 }
1169 1190
1170 sysfs_remove_link(&mci->edac_mci_kobj, EDAC_DEVICE_SYMLINK); 1191 sysfs_remove_link(&mci->edac_mci_kobj, EDAC_DEVICE_SYMLINK);
1171 1192 init_completion(&mci->kobj_complete);
1172 kobject_unregister(&mci->edac_mci_kobj); 1193 kobject_unregister(&mci->edac_mci_kobj);
1194 wait_for_completion(&mci->kobj_complete);
1173#endif /* DISABLE_EDAC_SYSFS */ 1195#endif /* DISABLE_EDAC_SYSFS */
1174} 1196}
1175 1197
@@ -1342,31 +1364,10 @@ EXPORT_SYMBOL(edac_mc_free);
1342/** 1364/**
1343 * edac_mc_free: Free a previously allocated 'mci' structure 1365 * edac_mc_free: Free a previously allocated 'mci' structure
1344 * @mci: pointer to a struct mem_ctl_info structure 1366 * @mci: pointer to a struct mem_ctl_info structure
1345 *
1346 * Free up a previously allocated mci structure
1347 * A MCI structure can be in 2 states after being allocated
1348 * by edac_mc_alloc().
1349 * 1) Allocated in a MC driver's probe, but not yet committed
1350 * 2) Allocated and committed, by a call to edac_mc_add_mc()
1351 * edac_mc_add_mc() is the function that adds the sysfs entries
1352 * thus, this free function must determine which state the 'mci'
1353 * structure is in, then either free it directly or
1354 * perform kobject cleanup by calling edac_remove_sysfs_mci_device().
1355 *
1356 * VOID Return
1357 */ 1367 */
1358void edac_mc_free(struct mem_ctl_info *mci) 1368void edac_mc_free(struct mem_ctl_info *mci)
1359{ 1369{
1360 /* only if sysfs entries for this mci instance exist 1370 kfree(mci);
1361 * do we remove them and defer the actual kfree via
1362 * the kobject 'release()' callback.
1363 *
1364 * Otherwise, do a straight kfree now.
1365 */
1366 if (mci->sysfs_active == MCI_SYSFS_ACTIVE)
1367 edac_remove_sysfs_mci_device(mci);
1368 else
1369 kfree(mci);
1370} 1371}
1371 1372
1372 1373
@@ -1456,7 +1457,8 @@ static void del_mc_from_global_list (struct mem_ctl_info *mci)
1456EXPORT_SYMBOL(edac_mc_add_mc); 1457EXPORT_SYMBOL(edac_mc_add_mc);
1457 1458
1458/** 1459/**
1459 * edac_mc_add_mc: Insert the 'mci' structure into the mci global list 1460 * edac_mc_add_mc: Insert the 'mci' structure into the mci global list and
1461 * create sysfs entries associated with mci structure
1460 * @mci: pointer to the mci structure to be added to the list 1462 * @mci: pointer to the mci structure to be added to the list
1461 * 1463 *
1462 * Return: 1464 * Return:
@@ -1516,7 +1518,8 @@ fail0:
1516EXPORT_SYMBOL(edac_mc_del_mc); 1518EXPORT_SYMBOL(edac_mc_del_mc);
1517 1519
1518/** 1520/**
1519 * edac_mc_del_mc: Remove the specified mci structure from global list 1521 * edac_mc_del_mc: Remove sysfs entries for specified mci structure and
1522 * remove mci structure from global list
1520 * @mci: Pointer to struct mem_ctl_info structure 1523 * @mci: Pointer to struct mem_ctl_info structure
1521 * 1524 *
1522 * Returns: 1525 * Returns:
@@ -1528,6 +1531,7 @@ int edac_mc_del_mc(struct mem_ctl_info *mci)
1528 int rc = 1; 1531 int rc = 1;
1529 1532
1530 debugf0("MC%d: %s()\n", mci->mc_idx, __func__); 1533 debugf0("MC%d: %s()\n", mci->mc_idx, __func__);
1534 edac_remove_sysfs_mci_device(mci);
1531 down(&mem_ctls_mutex); 1535 down(&mem_ctls_mutex);
1532 del_mc_from_global_list(mci); 1536 del_mc_from_global_list(mci);
1533 edac_printk(KERN_INFO, EDAC_MC, 1537 edac_printk(KERN_INFO, EDAC_MC,
diff --git a/drivers/edac/edac_mc.h b/drivers/edac/edac_mc.h
index 0bcc3797c753..c9c1590db721 100644
--- a/drivers/edac/edac_mc.h
+++ b/drivers/edac/edac_mc.h
@@ -185,11 +185,6 @@ enum scrub_type {
185#define SCRUB_FLAG_HW_PROG_SRC BIT(SCRUB_HW_PROG_SRC_CORR) 185#define SCRUB_FLAG_HW_PROG_SRC BIT(SCRUB_HW_PROG_SRC_CORR)
186#define SCRUB_FLAG_HW_TUN BIT(SCRUB_HW_TUNABLE) 186#define SCRUB_FLAG_HW_TUN BIT(SCRUB_HW_TUNABLE)
187 187
188enum mci_sysfs_status {
189 MCI_SYSFS_INACTIVE = 0, /* sysfs entries NOT registered */
190 MCI_SYSFS_ACTIVE /* sysfs entries ARE registered */
191};
192
193/* FIXME - should have notify capabilities: NMI, LOG, PROC, etc */ 188/* FIXME - should have notify capabilities: NMI, LOG, PROC, etc */
194 189
195/* 190/*
@@ -299,6 +294,7 @@ struct csrow_info {
299 struct mem_ctl_info *mci; /* the parent */ 294 struct mem_ctl_info *mci; /* the parent */
300 295
301 struct kobject kobj; /* sysfs kobject for this csrow */ 296 struct kobject kobj; /* sysfs kobject for this csrow */
297 struct completion kobj_complete;
302 298
303 /* FIXME the number of CHANNELs might need to become dynamic */ 299 /* FIXME the number of CHANNELs might need to become dynamic */
304 u32 nr_channels; 300 u32 nr_channels;
@@ -320,8 +316,6 @@ struct mem_ctl_info {
320 unsigned long scrub_cap; /* chipset scrub capabilities */ 316 unsigned long scrub_cap; /* chipset scrub capabilities */
321 enum scrub_type scrub_mode; /* current scrub mode */ 317 enum scrub_type scrub_mode; /* current scrub mode */
322 318
323 enum mci_sysfs_status sysfs_active; /* status of sysfs */
324
325 /* pointer to edac checking routine */ 319 /* pointer to edac checking routine */
326 void (*edac_check) (struct mem_ctl_info * mci); 320 void (*edac_check) (struct mem_ctl_info * mci);
327 /* 321 /*
@@ -359,6 +353,7 @@ struct mem_ctl_info {
359 353
360 /* edac sysfs device control */ 354 /* edac sysfs device control */
361 struct kobject edac_mci_kobj; 355 struct kobject edac_mci_kobj;
356 struct completion kobj_complete;
362}; 357};
363 358
364 359