diff options
author | Doug Thompson <dougthompson@xmission.com> | 2007-07-19 04:50:33 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-07-19 13:04:57 -0400 |
commit | b2a4ac0c2860b27670bce99e8c9c281bf431c272 (patch) | |
tree | 33a779777dda27f7660fc67db8444ad51aae8155 /drivers/edac/edac_device.c | |
parent | ba9a5918c86762fa7fae353c635bb6ed5221dfb8 (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.c')
-rw-r--r-- | drivers/edac/edac_device.c | 44 |
1 files changed, 30 insertions, 14 deletions
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 | ||