aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/edac/edac_mc_sysfs.c
diff options
context:
space:
mode:
authorDouglas Thompson <dougthompson@xmission.com>2007-07-19 04:49:36 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-07-19 13:04:53 -0400
commite27e3dac651771fe3250f6305dee277bce29fc5d (patch)
tree9c0ac81a0948d8e52a72865ff9fbae4a12031a32 /drivers/edac/edac_mc_sysfs.c
parent7c9281d76c1c0b130f79d5fc021084e9749959d4 (diff)
drivers/edac: add edac_device class
This patch adds the new 'class' of object to be managed, named: 'edac_device'. As a peer of the 'edac_mc' class of object, it provides a non-memory centric view of an ERROR DETECTING device in hardware. It provides a sysfs interface and an abstraction for varioius EDAC type devices. Multiple 'instances' within the class are possible, with each 'instance' able to have multiple 'blocks', and each 'block' having 'attributes'. At the 'block' level there are the 'ce_count' and 'ue_count' fields which the device driver can update and/or call edac_device_handle_XX() functions. At each higher level are additional 'total' count fields, which are a summation of counts below that level. This 'edac_device' has been used to capture and present ECC errors which are found in a a L1 and L2 system on a per CORE/CPU basis. Signed-off-by: Douglas Thompson <dougthompson@xmission.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_sysfs.c')
-rw-r--r--drivers/edac/edac_mc_sysfs.c70
1 files changed, 31 insertions, 39 deletions
diff --git a/drivers/edac/edac_mc_sysfs.c b/drivers/edac/edac_mc_sysfs.c
index 4a5e335f61d3..35bcf926017f 100644
--- a/drivers/edac/edac_mc_sysfs.c
+++ b/drivers/edac/edac_mc_sysfs.c
@@ -94,14 +94,6 @@ static const char *edac_caps[] = {
94 [EDAC_S16ECD16ED] = "S16ECD16ED" 94 [EDAC_S16ECD16ED] = "S16ECD16ED"
95}; 95};
96 96
97/*
98 * sysfs object: /sys/devices/system/edac
99 * need to export to other files in this modules
100 */
101struct sysdev_class edac_class = {
102 set_kset_name("edac"),
103};
104
105/* sysfs object: 97/* sysfs object:
106 * /sys/devices/system/edac/mc 98 * /sys/devices/system/edac/mc
107 */ 99 */
@@ -224,43 +216,38 @@ static struct kobj_type ktype_memctrl = {
224int edac_sysfs_memctrl_setup(void) 216int edac_sysfs_memctrl_setup(void)
225{ 217{
226 int err = 0; 218 int err = 0;
219 struct sysdev_class *edac_class;
227 220
228 debugf1("%s()\n", __func__); 221 debugf1("%s()\n", __func__);
229 222
230 /* create the /sys/devices/system/edac directory */ 223 /* get the /sys/devices/system/edac class reference */
231 err = sysdev_class_register(&edac_class); 224 edac_class = edac_get_edac_class();
232 225 if (edac_class == NULL) {
233 if (err) { 226 debugf1("%s() no edac_class error=%d\n", __func__, err);
234 debugf1("%s() error=%d\n", __func__, err);
235 return err; 227 return err;
236 } 228 }
237 229
238 /* Init the MC's kobject */ 230 /* Init the MC's kobject */
239 memset(&edac_memctrl_kobj, 0, sizeof (edac_memctrl_kobj)); 231 memset(&edac_memctrl_kobj, 0, sizeof (edac_memctrl_kobj));
240 edac_memctrl_kobj.parent = &edac_class.kset.kobj; 232 edac_memctrl_kobj.parent = &edac_class->kset.kobj;
241 edac_memctrl_kobj.ktype = &ktype_memctrl; 233 edac_memctrl_kobj.ktype = &ktype_memctrl;
242 234
243 /* generate sysfs "..../edac/mc" */ 235 /* generate sysfs "..../edac/mc" */
244 err = kobject_set_name(&edac_memctrl_kobj,"mc"); 236 err = kobject_set_name(&edac_memctrl_kobj,"mc");
245 237 if (err) {
246 if (err) 238 debugf1("%s() Failed to set name '.../edac/mc'\n", __func__ );
247 goto fail; 239 return err;
240 }
248 241
249 /* FIXME: maybe new sysdev_create_subdir() */ 242 /* FIXME: maybe new sysdev_create_subdir() */
250 err = kobject_register(&edac_memctrl_kobj); 243 err = kobject_register(&edac_memctrl_kobj);
251
252 if (err) { 244 if (err) {
253 debugf1("Failed to register '.../edac/mc'\n"); 245 debugf1("%s() Failed to register '.../edac/mc'\n", __func__ );
254 goto fail; 246 return err;
255 } 247 }
256 248
257 debugf1("Registered '.../edac/mc' kobject\n"); 249 debugf1("%s() Registered '.../edac/mc' kobject\n",__func__);
258
259 return 0; 250 return 0;
260
261fail:
262 sysdev_class_unregister(&edac_class);
263 return err;
264} 251}
265 252
266/* 253/*
@@ -276,9 +263,6 @@ void edac_sysfs_memctrl_teardown(void)
276 init_completion(&edac_memctrl_kobj_complete); 263 init_completion(&edac_memctrl_kobj_complete);
277 kobject_unregister(&edac_memctrl_kobj); 264 kobject_unregister(&edac_memctrl_kobj);
278 wait_for_completion(&edac_memctrl_kobj_complete); 265 wait_for_completion(&edac_memctrl_kobj_complete);
279
280 /* Unregister the 'edac' object */
281 sysdev_class_unregister(&edac_class);
282} 266}
283 267
284 268
@@ -286,32 +270,38 @@ void edac_sysfs_memctrl_teardown(void)
286 */ 270 */
287 271
288/* Set of more default csrow<id> attribute show/store functions */ 272/* Set of more default csrow<id> attribute show/store functions */
289static ssize_t csrow_ue_count_show(struct csrow_info *csrow, char *data, int private) 273static ssize_t csrow_ue_count_show(struct csrow_info *csrow, char *data,
274 int private)
290{ 275{
291 return sprintf(data,"%u\n", csrow->ue_count); 276 return sprintf(data,"%u\n", csrow->ue_count);
292} 277}
293 278
294static ssize_t csrow_ce_count_show(struct csrow_info *csrow, char *data, int private) 279static ssize_t csrow_ce_count_show(struct csrow_info *csrow, char *data,
280 int private)
295{ 281{
296 return sprintf(data,"%u\n", csrow->ce_count); 282 return sprintf(data,"%u\n", csrow->ce_count);
297} 283}
298 284
299static ssize_t csrow_size_show(struct csrow_info *csrow, char *data, int private) 285static ssize_t csrow_size_show(struct csrow_info *csrow, char *data,
286 int private)
300{ 287{
301 return sprintf(data,"%u\n", PAGES_TO_MiB(csrow->nr_pages)); 288 return sprintf(data,"%u\n", PAGES_TO_MiB(csrow->nr_pages));
302} 289}
303 290
304static ssize_t csrow_mem_type_show(struct csrow_info *csrow, char *data, int private) 291static ssize_t csrow_mem_type_show(struct csrow_info *csrow, char *data,
292 int private)
305{ 293{
306 return sprintf(data,"%s\n", mem_types[csrow->mtype]); 294 return sprintf(data,"%s\n", mem_types[csrow->mtype]);
307} 295}
308 296
309static ssize_t csrow_dev_type_show(struct csrow_info *csrow, char *data, int private) 297static ssize_t csrow_dev_type_show(struct csrow_info *csrow, char *data,
298 int private)
310{ 299{
311 return sprintf(data,"%s\n", dev_types[csrow->dtype]); 300 return sprintf(data,"%s\n", dev_types[csrow->dtype]);
312} 301}
313 302
314static ssize_t csrow_edac_mode_show(struct csrow_info *csrow, char *data, int private) 303static ssize_t csrow_edac_mode_show(struct csrow_info *csrow, char *data,
304 int private)
315{ 305{
316 return sprintf(data,"%s\n", edac_caps[csrow->edac_mode]); 306 return sprintf(data,"%s\n", edac_caps[csrow->edac_mode]);
317} 307}
@@ -509,9 +499,10 @@ static int edac_create_channel_files(struct kobject *kobj, int chan)
509 if (!err) { 499 if (!err) {
510 /* create the CE Count attribute file */ 500 /* create the CE Count attribute file */
511 err = sysfs_create_file(kobj, 501 err = sysfs_create_file(kobj,
512 (struct attribute *) dynamic_csrow_ce_count_attr[chan]); 502 (struct attribute *)dynamic_csrow_ce_count_attr[chan]);
513 } else { 503 } else {
514 debugf1("%s() dimm labels and ce_count files created", __func__); 504 debugf1("%s() dimm labels and ce_count files created",
505 __func__);
515 } 506 }
516 507
517 return err; 508 return err;
@@ -643,7 +634,7 @@ static ssize_t mci_sdram_scrub_rate_show(struct mem_ctl_info *mci, char *data)
643 } else { 634 } else {
644 /* FIXME: produce "not implemented" ERROR for user-side. */ 635 /* FIXME: produce "not implemented" ERROR for user-side. */
645 edac_printk(KERN_WARNING, EDAC_MC, 636 edac_printk(KERN_WARNING, EDAC_MC,
646 "Memory scrubbing 'get' control is not implemented!\n"); 637 "Memory scrubbing 'get' control is not implemented\n");
647 } 638 }
648 return sprintf(data, "%d\n", bandwidth); 639 return sprintf(data, "%d\n", bandwidth);
649} 640}
@@ -755,7 +746,8 @@ MCIDEV_ATTR(ue_count,S_IRUGO,mci_ue_count_show,NULL);
755MCIDEV_ATTR(ce_count,S_IRUGO,mci_ce_count_show,NULL); 746MCIDEV_ATTR(ce_count,S_IRUGO,mci_ce_count_show,NULL);
756 747
757/* memory scrubber attribute file */ 748/* memory scrubber attribute file */
758MCIDEV_ATTR(sdram_scrub_rate,S_IRUGO|S_IWUSR,mci_sdram_scrub_rate_show,mci_sdram_scrub_rate_store); 749MCIDEV_ATTR(sdram_scrub_rate,S_IRUGO|S_IWUSR,mci_sdram_scrub_rate_show,\
750 mci_sdram_scrub_rate_store);
759 751
760static struct mcidev_attribute *mci_attr[] = { 752static struct mcidev_attribute *mci_attr[] = {
761 &mci_attr_reset_counters, 753 &mci_attr_reset_counters,