aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/edac/edac_device_sysfs.c
diff options
context:
space:
mode:
authorDoug Thompson <dougthompson@xmission.com>2007-07-19 04:50:33 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-07-19 13:04:57 -0400
commitb2a4ac0c2860b27670bce99e8c9c281bf431c272 (patch)
tree33a779777dda27f7660fc67db8444ad51aae8155 /drivers/edac/edac_device_sysfs.c
parentba9a5918c86762fa7fae353c635bb6ed5221dfb8 (diff)
drivers/edac: fix edac_device sysfs corner case bug
Some simple fixes to properly reference counter values from the block attribute level of edac_device objects. Properly sequencing the array pointer was added, resulting in correct identification of block level attributes from their base class functions. Added more verbose debug statement for event tracking. Also during some corner testing, found a bug in the store/show sequence of operations for the block attribute/controls management. An old intermediate structure for 'blocks' was still in the processing pipeline. This patch removes that old structure and correctly utilizes the new struct edac_dev_sysfs_block_attribute for passing control from the sysfs to the low level store/show function of the edac driver. Now the proper kobj pointer to passed downward to the store/show functions. Signed-off-by: Doug Thompson <dougthompson@xmission.com> Cc: Greg KH <greg@kroah.com> Cc: Alan Cox <alan@lxorguk.ukuu.org.uk> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/edac/edac_device_sysfs.c')
-rw-r--r--drivers/edac/edac_device_sysfs.c81
1 files changed, 46 insertions, 35 deletions
diff --git a/drivers/edac/edac_device_sysfs.c b/drivers/edac/edac_device_sysfs.c
index 52769ae69bd2..70b837f23c43 100644
--- a/drivers/edac/edac_device_sysfs.c
+++ b/drivers/edac/edac_device_sysfs.c
@@ -200,7 +200,7 @@ static void edac_device_ctrl_master_release(struct kobject *kobj)
200{ 200{
201 struct edac_device_ctl_info *edac_dev = to_edacdev(kobj); 201 struct edac_device_ctl_info *edac_dev = to_edacdev(kobj);
202 202
203 debugf1("%s() control index=%d\n", __func__, edac_dev->dev_idx); 203 debugf4("%s() control index=%d\n", __func__, edac_dev->dev_idx);
204 204
205 /* decrement the EDAC CORE module ref count */ 205 /* decrement the EDAC CORE module ref count */
206 module_put(edac_dev->owner); 206 module_put(edac_dev->owner);
@@ -252,7 +252,7 @@ int edac_device_register_sysfs_main_kobj(struct edac_device_ctl_info *edac_dev)
252 edac_dev->kobj.parent = &edac_class->kset.kobj; 252 edac_dev->kobj.parent = &edac_class->kset.kobj;
253 253
254 /* generate sysfs "..../edac/<name>" */ 254 /* generate sysfs "..../edac/<name>" */
255 debugf1("%s() set name of kobject to: %s\n", __func__, edac_dev->name); 255 debugf4("%s() set name of kobject to: %s\n", __func__, edac_dev->name);
256 err = kobject_set_name(&edac_dev->kobj, "%s", edac_dev->name); 256 err = kobject_set_name(&edac_dev->kobj, "%s", edac_dev->name);
257 if (err) 257 if (err)
258 goto err_out; 258 goto err_out;
@@ -279,7 +279,7 @@ int edac_device_register_sysfs_main_kobj(struct edac_device_ctl_info *edac_dev)
279 * edac_device_unregister_sysfs_main_kobj() must be used 279 * edac_device_unregister_sysfs_main_kobj() must be used
280 */ 280 */
281 281
282 debugf1("%s() Registered '.../edac/%s' kobject\n", 282 debugf4("%s() Registered '.../edac/%s' kobject\n",
283 __func__, edac_dev->name); 283 __func__, edac_dev->name);
284 284
285 return 0; 285 return 0;
@@ -300,7 +300,7 @@ void edac_device_unregister_sysfs_main_kobj(
300 struct edac_device_ctl_info *edac_dev) 300 struct edac_device_ctl_info *edac_dev)
301{ 301{
302 debugf0("%s()\n", __func__); 302 debugf0("%s()\n", __func__);
303 debugf1("%s() name of kobject is: %s\n", 303 debugf4("%s() name of kobject is: %s\n",
304 __func__, kobject_name(&edac_dev->kobj)); 304 __func__, kobject_name(&edac_dev->kobj));
305 305
306 /* 306 /*
@@ -416,22 +416,29 @@ static struct kobj_type ktype_instance_ctrl = {
416 416
417/* edac_dev -> instance -> block information */ 417/* edac_dev -> instance -> block information */
418 418
419#define to_block(k) container_of(k, struct edac_device_block, kobj)
420#define to_block_attr(a) \
421 container_of(a, struct edac_dev_sysfs_block_attribute, attr)
422
419/* 423/*
420 * Set of low-level block attribute show functions 424 * Set of low-level block attribute show functions
421 */ 425 */
422static ssize_t block_ue_count_show(struct edac_device_block *block, char *data) 426static ssize_t block_ue_count_show(struct kobject *kobj,
427 struct attribute *attr, char *data)
423{ 428{
429 struct edac_device_block *block = to_block(kobj);
430
424 return sprintf(data, "%u\n", block->counters.ue_count); 431 return sprintf(data, "%u\n", block->counters.ue_count);
425} 432}
426 433
427static ssize_t block_ce_count_show(struct edac_device_block *block, char *data) 434static ssize_t block_ce_count_show(struct kobject *kobj,
435 struct attribute *attr, char *data)
428{ 436{
437 struct edac_device_block *block = to_block(kobj);
438
429 return sprintf(data, "%u\n", block->counters.ce_count); 439 return sprintf(data, "%u\n", block->counters.ce_count);
430} 440}
431 441
432#define to_block(k) container_of(k, struct edac_device_block, kobj)
433#define to_block_attr(a) container_of(a,struct block_attribute,attr)
434
435/* DEVICE block kobject release() function */ 442/* DEVICE block kobject release() function */
436static void edac_device_ctrl_block_release(struct kobject *kobj) 443static void edac_device_ctrl_block_release(struct kobject *kobj)
437{ 444{
@@ -448,22 +455,16 @@ static void edac_device_ctrl_block_release(struct kobject *kobj)
448 kobject_put(&block->instance->ctl->kobj); 455 kobject_put(&block->instance->ctl->kobj);
449} 456}
450 457
451/* block specific attribute structure */
452struct block_attribute {
453 struct attribute attr;
454 ssize_t(*show) (struct edac_device_block *, char *);
455 ssize_t(*store) (struct edac_device_block *, const char *, size_t);
456};
457 458
458/* Function to 'show' fields from the edac_dev 'block' structure */ 459/* Function to 'show' fields from the edac_dev 'block' structure */
459static ssize_t edac_dev_block_show(struct kobject *kobj, 460static ssize_t edac_dev_block_show(struct kobject *kobj,
460 struct attribute *attr, char *buffer) 461 struct attribute *attr, char *buffer)
461{ 462{
462 struct edac_device_block *block = to_block(kobj); 463 struct edac_dev_sysfs_block_attribute *block_attr =
463 struct block_attribute *block_attr = to_block_attr(attr); 464 to_block_attr(attr);
464 465
465 if (block_attr->show) 466 if (block_attr->show)
466 return block_attr->show(block, buffer); 467 return block_attr->show(kobj, attr, buffer);
467 return -EIO; 468 return -EIO;
468} 469}
469 470
@@ -472,11 +473,12 @@ static ssize_t edac_dev_block_store(struct kobject *kobj,
472 struct attribute *attr, 473 struct attribute *attr,
473 const char *buffer, size_t count) 474 const char *buffer, size_t count)
474{ 475{
475 struct edac_device_block *block = to_block(kobj); 476 struct edac_dev_sysfs_block_attribute *block_attr;
476 struct block_attribute *block_attr = to_block_attr(attr); 477
478 block_attr = to_block_attr(attr);
477 479
478 if (block_attr->store) 480 if (block_attr->store)
479 return block_attr->store(block, buffer, count); 481 return block_attr->store(kobj, attr, buffer, count);
480 return -EIO; 482 return -EIO;
481} 483}
482 484
@@ -487,7 +489,7 @@ static struct sysfs_ops device_block_ops = {
487}; 489};
488 490
489#define BLOCK_ATTR(_name,_mode,_show,_store) \ 491#define BLOCK_ATTR(_name,_mode,_show,_store) \
490static struct block_attribute attr_block_##_name = { \ 492static struct edac_dev_sysfs_block_attribute attr_block_##_name = { \
491 .attr = {.name = __stringify(_name), .mode = _mode }, \ 493 .attr = {.name = __stringify(_name), .mode = _mode }, \
492 .show = _show, \ 494 .show = _show, \
493 .store = _store, \ 495 .store = _store, \
@@ -497,7 +499,7 @@ BLOCK_ATTR(ce_count, S_IRUGO, block_ce_count_show, NULL);
497BLOCK_ATTR(ue_count, S_IRUGO, block_ue_count_show, NULL); 499BLOCK_ATTR(ue_count, S_IRUGO, block_ue_count_show, NULL);
498 500
499/* list of edac_dev 'block' attributes */ 501/* list of edac_dev 'block' attributes */
500static struct block_attribute *device_block_attr[] = { 502static struct edac_dev_sysfs_block_attribute *device_block_attr[] = {
501 &attr_block_ce_count, 503 &attr_block_ce_count,
502 &attr_block_ue_count, 504 &attr_block_ue_count,
503 NULL, 505 NULL,
@@ -524,14 +526,15 @@ static int edac_device_create_block(struct edac_device_ctl_info *edac_dev,
524 struct edac_dev_sysfs_block_attribute *sysfs_attrib; 526 struct edac_dev_sysfs_block_attribute *sysfs_attrib;
525 struct kobject *main_kobj; 527 struct kobject *main_kobj;
526 528
527 debugf1("%s() Instance '%s' block '%s'\n", 529 debugf4("%s() Instance '%s' inst_p=%p block '%s' block_p=%p\n",
528 __func__, instance->name, block->name); 530 __func__, instance->name, instance, block->name, block);
531 debugf4("%s() block kobj=%p block kobj->parent=%p\n",
532 __func__, &block->kobj, &block->kobj.parent);
529 533
530 /* init this block's kobject */ 534 /* init this block's kobject */
531 memset(&block->kobj, 0, sizeof(struct kobject)); 535 memset(&block->kobj, 0, sizeof(struct kobject));
532 block->kobj.parent = &instance->kobj; 536 block->kobj.parent = &instance->kobj;
533 block->kobj.ktype = &ktype_block_ctrl; 537 block->kobj.ktype = &ktype_block_ctrl;
534 block->instance = instance;
535 538
536 err = kobject_set_name(&block->kobj, "%s", block->name); 539 err = kobject_set_name(&block->kobj, "%s", block->name);
537 if (err) 540 if (err)
@@ -560,14 +563,20 @@ static int edac_device_create_block(struct edac_device_ctl_info *edac_dev,
560 * to the block kobject 563 * to the block kobject
561 */ 564 */
562 sysfs_attrib = block->block_attributes; 565 sysfs_attrib = block->block_attributes;
563 if (sysfs_attrib) { 566 if (sysfs_attrib && block->nr_attribs) {
564 for (i = 0; i < block->nr_attribs; i++) { 567 for (i = 0; i < block->nr_attribs; i++, sysfs_attrib++) {
568
569 debugf4("%s() creating block attrib='%s' "
570 "attrib->%p to kobj=%p\n",
571 __func__,
572 sysfs_attrib->attr.name,
573 sysfs_attrib, &block->kobj);
574
575 /* Create each block_attribute file */
565 err = sysfs_create_file(&block->kobj, 576 err = sysfs_create_file(&block->kobj,
566 (struct attribute *) sysfs_attrib); 577 &sysfs_attrib->attr);
567 if (err) 578 if (err)
568 goto err_on_attrib; 579 goto err_on_attrib;
569
570 sysfs_attrib++;
571 } 580 }
572 } 581 }
573 582
@@ -595,7 +604,9 @@ static void edac_device_delete_block(struct edac_device_ctl_info *edac_dev,
595 */ 604 */
596 sysfs_attrib = block->block_attributes; 605 sysfs_attrib = block->block_attributes;
597 if (sysfs_attrib && block->nr_attribs) { 606 if (sysfs_attrib && block->nr_attribs) {
598 for (i = 0; i < block->nr_attribs; i++) { 607 for (i = 0; i < block->nr_attribs; i++, sysfs_attrib++) {
608
609 /* remove each block_attrib file */
599 sysfs_remove_file(&block->kobj, 610 sysfs_remove_file(&block->kobj,
600 (struct attribute *) sysfs_attrib); 611 (struct attribute *) sysfs_attrib);
601 } 612 }
@@ -653,7 +664,7 @@ static int edac_device_create_instance(struct edac_device_ctl_info *edac_dev,
653 goto err_out; 664 goto err_out;
654 } 665 }
655 666
656 debugf1("%s() now register '%d' blocks for instance %d\n", 667 debugf4("%s() now register '%d' blocks for instance %d\n",
657 __func__, instance->nr_blocks, idx); 668 __func__, instance->nr_blocks, idx);
658 669
659 /* register all blocks of this instance */ 670 /* register all blocks of this instance */
@@ -669,7 +680,7 @@ static int edac_device_create_instance(struct edac_device_ctl_info *edac_dev,
669 } 680 }
670 } 681 }
671 682
672 debugf1("%s() Registered instance %d '%s' kobject\n", 683 debugf4("%s() Registered instance %d '%s' kobject\n",
673 __func__, idx, instance->name); 684 __func__, idx, instance->name);
674 685
675 return 0; 686 return 0;
@@ -848,7 +859,7 @@ int edac_device_create_sysfs(struct edac_device_ctl_info *edac_dev)
848 } 859 }
849 860
850 861
851 debugf0("%s() calling create-instances, idx=%d\n", 862 debugf4("%s() create-instances done, idx=%d\n",
852 __func__, edac_dev->dev_idx); 863 __func__, edac_dev->dev_idx);
853 864
854 return 0; 865 return 0;