aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
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
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')
-rw-r--r--drivers/edac/edac_core.h11
-rw-r--r--drivers/edac/edac_device.c44
-rw-r--r--drivers/edac/edac_device_sysfs.c81
3 files changed, 85 insertions, 51 deletions
diff --git a/drivers/edac/edac_core.h b/drivers/edac/edac_core.h
index 4e31ac438760..4e6bad15c4ba 100644
--- a/drivers/edac/edac_core.h
+++ b/drivers/edac/edac_core.h
@@ -485,7 +485,16 @@ struct edac_dev_sysfs_attribute {
485}; 485};
486 486
487/* edac_dev_sysfs_block_attribute structure 487/* edac_dev_sysfs_block_attribute structure
488 *
488 * used in leaf 'block' nodes for adding controls/attributes 489 * used in leaf 'block' nodes for adding controls/attributes
490 *
491 * each block in each instance of the containing control structure
492 * can have an array of the following. The show and store functions
493 * will be filled in with the show/store function in the
494 * low level driver.
495 *
496 * The 'value' field will be the actual value field used for
497 * counting
489 */ 498 */
490struct edac_dev_sysfs_block_attribute { 499struct edac_dev_sysfs_block_attribute {
491 struct attribute attr; 500 struct attribute attr;
@@ -494,8 +503,6 @@ struct edac_dev_sysfs_block_attribute {
494 const char *, size_t); 503 const char *, size_t);
495 struct edac_device_block *block; 504 struct edac_device_block *block;
496 505
497 /* low driver use */
498 void *arg;
499 unsigned int value; 506 unsigned int value;
500}; 507};
501 508
diff --git a/drivers/edac/edac_device.c b/drivers/edac/edac_device.c
index 7e3723768aca..f3690a697cf9 100644
--- a/drivers/edac/edac_device.c
+++ b/drivers/edac/edac_device.c
@@ -83,7 +83,7 @@ struct edac_device_ctl_info *edac_device_alloc_ctl_info(
83 void *pvt; 83 void *pvt;
84 int err; 84 int err;
85 85
86 debugf1("%s() instances=%d blocks=%d\n", 86 debugf4("%s() instances=%d blocks=%d\n",
87 __func__, nr_instances, nr_blocks); 87 __func__, nr_instances, nr_blocks);
88 88
89 /* Calculate the size of memory we need to allocate AND 89 /* Calculate the size of memory we need to allocate AND
@@ -158,6 +158,9 @@ struct edac_device_ctl_info *edac_device_alloc_ctl_info(
158 /* Name of this edac device */ 158 /* Name of this edac device */
159 snprintf(dev_ctl->name,sizeof(dev_ctl->name),"%s",edac_device_name); 159 snprintf(dev_ctl->name,sizeof(dev_ctl->name),"%s",edac_device_name);
160 160
161 debugf4("%s() edac_dev=%p next after end=%p\n",
162 __func__, dev_ctl, pvt + sz_private );
163
161 /* Initialize every Instance */ 164 /* Initialize every Instance */
162 for (instance = 0; instance < nr_instances; instance++) { 165 for (instance = 0; instance < nr_instances; instance++) {
163 inst = &dev_inst[instance]; 166 inst = &dev_inst[instance];
@@ -177,8 +180,10 @@ struct edac_device_ctl_info *edac_device_alloc_ctl_info(
177 snprintf(blk->name, sizeof(blk->name), 180 snprintf(blk->name, sizeof(blk->name),
178 "%s%d", edac_block_name, block+offset_value); 181 "%s%d", edac_block_name, block+offset_value);
179 182
180 debugf1("%s() instance=%d block=%d name=%s\n", 183 debugf4("%s() instance=%d inst_p=%p block=#%d "
181 __func__, instance, block, blk->name); 184 "block_p=%p name='%s'\n",
185 __func__, instance, inst, block,
186 blk, blk->name);
182 187
183 /* if there are NO attributes OR no attribute pointer 188 /* if there are NO attributes OR no attribute pointer
184 * then continue on to next block iteration 189 * then continue on to next block iteration
@@ -191,20 +196,32 @@ struct edac_device_ctl_info *edac_device_alloc_ctl_info(
191 attrib_p = &dev_attrib[block*nr_instances*nr_attrib]; 196 attrib_p = &dev_attrib[block*nr_instances*nr_attrib];
192 blk->block_attributes = attrib_p; 197 blk->block_attributes = attrib_p;
193 198
199 debugf4("%s() THIS BLOCK_ATTRIB=%p\n",
200 __func__, blk->block_attributes);
201
194 /* Initialize every user specified attribute in this 202 /* Initialize every user specified attribute in this
195 * block with the data the caller passed in 203 * block with the data the caller passed in
204 * Each block gets its own copy of pointers,
205 * and its unique 'value'
196 */ 206 */
197 for (attr = 0; attr < nr_attrib; attr++) { 207 for (attr = 0; attr < nr_attrib; attr++) {
198 attrib = &attrib_p[attr]; 208 attrib = &attrib_p[attr];
199 attrib->attr = attrib_spec->attr;
200 attrib->show = attrib_spec->show;
201 attrib->store = attrib_spec->store;
202
203 /* up reference this block */
204 attrib->block = blk;
205 209
206 /* bump the attrib_spec */ 210 /* populate the unique per attrib
207 attrib_spec++; 211 * with the code pointers and info
212 */
213 attrib->attr = attrib_spec[attr].attr;
214 attrib->show = attrib_spec[attr].show;
215 attrib->store = attrib_spec[attr].store;
216
217 attrib->block = blk; /* up link */
218
219 debugf4("%s() alloc-attrib=%p attrib_name='%s' "
220 "attrib-spec=%p spec-name=%s\n",
221 __func__, attrib, attrib->attr.name,
222 &attrib_spec[attr],
223 attrib_spec[attr].attr.name
224 );
208 } 225 }
209 } 226 }
210 } 227 }
@@ -258,7 +275,7 @@ static struct edac_device_ctl_info *find_edac_device_by_dev(struct device *dev)
258 struct edac_device_ctl_info *edac_dev; 275 struct edac_device_ctl_info *edac_dev;
259 struct list_head *item; 276 struct list_head *item;
260 277
261 debugf3("%s()\n", __func__); 278 debugf0("%s()\n", __func__);
262 279
263 list_for_each(item, &edac_device_list) { 280 list_for_each(item, &edac_device_list) {
264 edac_dev = list_entry(item, struct edac_device_ctl_info, link); 281 edac_dev = list_entry(item, struct edac_device_ctl_info, link);
@@ -402,7 +419,6 @@ static void edac_device_workq_function(struct work_struct *work_req)
402 struct delayed_work *d_work = (struct delayed_work *)work_req; 419 struct delayed_work *d_work = (struct delayed_work *)work_req;
403 struct edac_device_ctl_info *edac_dev = to_edac_device_ctl_work(d_work); 420 struct edac_device_ctl_info *edac_dev = to_edac_device_ctl_work(d_work);
404 421
405 //debugf0("%s() here and running\n", __func__);
406 mutex_lock(&device_ctls_mutex); 422 mutex_lock(&device_ctls_mutex);
407 423
408 /* Only poll controllers that are running polled and have a check */ 424 /* Only poll controllers that are running polled and have a check */
@@ -582,7 +598,7 @@ struct edac_device_ctl_info *edac_device_del_device(struct device *dev)
582{ 598{
583 struct edac_device_ctl_info *edac_dev; 599 struct edac_device_ctl_info *edac_dev;
584 600
585 debugf0("MC: %s()\n", __func__); 601 debugf0("%s()\n", __func__);
586 602
587 mutex_lock(&device_ctls_mutex); 603 mutex_lock(&device_ctls_mutex);
588 604
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;