diff options
author | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-17 16:15:55 -0500 |
---|---|---|
committer | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-17 16:15:55 -0500 |
commit | 8dea78da5cee153b8af9c07a2745f6c55057fe12 (patch) | |
tree | a8f4d49d63b1ecc92f2fddceba0655b2472c5bd9 /drivers/edac/edac_device.c | |
parent | 406089d01562f1e2bf9f089fd7637009ebaad589 (diff) |
Patched in Tegra support.
Diffstat (limited to 'drivers/edac/edac_device.c')
-rw-r--r-- | drivers/edac/edac_device.c | 81 |
1 files changed, 45 insertions, 36 deletions
diff --git a/drivers/edac/edac_device.c b/drivers/edac/edac_device.c index 211021dfec7..c3f67437afb 100644 --- a/drivers/edac/edac_device.c +++ b/drivers/edac/edac_device.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/jiffies.h> | 23 | #include <linux/jiffies.h> |
24 | #include <linux/spinlock.h> | 24 | #include <linux/spinlock.h> |
25 | #include <linux/list.h> | 25 | #include <linux/list.h> |
26 | #include <linux/sysdev.h> | ||
26 | #include <linux/ctype.h> | 27 | #include <linux/ctype.h> |
27 | #include <linux/workqueue.h> | 28 | #include <linux/workqueue.h> |
28 | #include <asm/uaccess.h> | 29 | #include <asm/uaccess.h> |
@@ -40,13 +41,12 @@ static LIST_HEAD(edac_device_list); | |||
40 | #ifdef CONFIG_EDAC_DEBUG | 41 | #ifdef CONFIG_EDAC_DEBUG |
41 | static void edac_device_dump_device(struct edac_device_ctl_info *edac_dev) | 42 | static void edac_device_dump_device(struct edac_device_ctl_info *edac_dev) |
42 | { | 43 | { |
43 | edac_dbg(3, "\tedac_dev = %p dev_idx=%d\n", | 44 | debugf3("\tedac_dev = %p dev_idx=%d \n", edac_dev, edac_dev->dev_idx); |
44 | edac_dev, edac_dev->dev_idx); | 45 | debugf4("\tedac_dev->edac_check = %p\n", edac_dev->edac_check); |
45 | edac_dbg(4, "\tedac_dev->edac_check = %p\n", edac_dev->edac_check); | 46 | debugf3("\tdev = %p\n", edac_dev->dev); |
46 | edac_dbg(3, "\tdev = %p\n", edac_dev->dev); | 47 | debugf3("\tmod_name:ctl_name = %s:%s\n", |
47 | edac_dbg(3, "\tmod_name:ctl_name = %s:%s\n", | 48 | edac_dev->mod_name, edac_dev->ctl_name); |
48 | edac_dev->mod_name, edac_dev->ctl_name); | 49 | debugf3("\tpvt_info = %p\n\n", edac_dev->pvt_info); |
49 | edac_dbg(3, "\tpvt_info = %p\n\n", edac_dev->pvt_info); | ||
50 | } | 50 | } |
51 | #endif /* CONFIG_EDAC_DEBUG */ | 51 | #endif /* CONFIG_EDAC_DEBUG */ |
52 | 52 | ||
@@ -57,7 +57,7 @@ static void edac_device_dump_device(struct edac_device_ctl_info *edac_dev) | |||
57 | * | 57 | * |
58 | * The control structure is allocated in complete chunk | 58 | * The control structure is allocated in complete chunk |
59 | * from the OS. It is in turn sub allocated to the | 59 | * from the OS. It is in turn sub allocated to the |
60 | * various objects that compose the structure | 60 | * various objects that compose the struture |
61 | * | 61 | * |
62 | * The structure has a 'nr_instance' array within itself. | 62 | * The structure has a 'nr_instance' array within itself. |
63 | * Each instance represents a major component | 63 | * Each instance represents a major component |
@@ -80,10 +80,11 @@ struct edac_device_ctl_info *edac_device_alloc_ctl_info( | |||
80 | unsigned total_size; | 80 | unsigned total_size; |
81 | unsigned count; | 81 | unsigned count; |
82 | unsigned instance, block, attr; | 82 | unsigned instance, block, attr; |
83 | void *pvt, *p; | 83 | void *pvt; |
84 | int err; | 84 | int err; |
85 | 85 | ||
86 | edac_dbg(4, "instances=%d blocks=%d\n", nr_instances, nr_blocks); | 86 | debugf4("%s() instances=%d blocks=%d\n", |
87 | __func__, nr_instances, nr_blocks); | ||
87 | 88 | ||
88 | /* Calculate the size of memory we need to allocate AND | 89 | /* Calculate the size of memory we need to allocate AND |
89 | * determine the offsets of the various item arrays | 90 | * determine the offsets of the various item arrays |
@@ -92,30 +93,35 @@ struct edac_device_ctl_info *edac_device_alloc_ctl_info( | |||
92 | * to be at least as stringent as what the compiler would | 93 | * to be at least as stringent as what the compiler would |
93 | * provide if we could simply hardcode everything into a single struct. | 94 | * provide if we could simply hardcode everything into a single struct. |
94 | */ | 95 | */ |
95 | p = NULL; | 96 | dev_ctl = (struct edac_device_ctl_info *)NULL; |
96 | dev_ctl = edac_align_ptr(&p, sizeof(*dev_ctl), 1); | ||
97 | 97 | ||
98 | /* Calc the 'end' offset past end of ONE ctl_info structure | 98 | /* Calc the 'end' offset past end of ONE ctl_info structure |
99 | * which will become the start of the 'instance' array | 99 | * which will become the start of the 'instance' array |
100 | */ | 100 | */ |
101 | dev_inst = edac_align_ptr(&p, sizeof(*dev_inst), nr_instances); | 101 | dev_inst = edac_align_ptr(&dev_ctl[1], sizeof(*dev_inst)); |
102 | 102 | ||
103 | /* Calc the 'end' offset past the instance array within the ctl_info | 103 | /* Calc the 'end' offset past the instance array within the ctl_info |
104 | * which will become the start of the block array | 104 | * which will become the start of the block array |
105 | */ | 105 | */ |
106 | count = nr_instances * nr_blocks; | 106 | dev_blk = edac_align_ptr(&dev_inst[nr_instances], sizeof(*dev_blk)); |
107 | dev_blk = edac_align_ptr(&p, sizeof(*dev_blk), count); | ||
108 | 107 | ||
109 | /* Calc the 'end' offset past the dev_blk array | 108 | /* Calc the 'end' offset past the dev_blk array |
110 | * which will become the start of the attrib array, if any. | 109 | * which will become the start of the attrib array, if any. |
111 | */ | 110 | */ |
112 | /* calc how many nr_attrib we need */ | 111 | count = nr_instances * nr_blocks; |
113 | if (nr_attrib > 0) | 112 | dev_attrib = edac_align_ptr(&dev_blk[count], sizeof(*dev_attrib)); |
113 | |||
114 | /* Check for case of when an attribute array is specified */ | ||
115 | if (nr_attrib > 0) { | ||
116 | /* calc how many nr_attrib we need */ | ||
114 | count *= nr_attrib; | 117 | count *= nr_attrib; |
115 | dev_attrib = edac_align_ptr(&p, sizeof(*dev_attrib), count); | ||
116 | 118 | ||
117 | /* Calc the 'end' offset past the attributes array */ | 119 | /* Calc the 'end' offset past the attributes array */ |
118 | pvt = edac_align_ptr(&p, sz_private, 1); | 120 | pvt = edac_align_ptr(&dev_attrib[count], sz_private); |
121 | } else { | ||
122 | /* no attribute array specificed */ | ||
123 | pvt = edac_align_ptr(dev_attrib, sz_private); | ||
124 | } | ||
119 | 125 | ||
120 | /* 'pvt' now points to where the private data area is. | 126 | /* 'pvt' now points to where the private data area is. |
121 | * At this point 'pvt' (like dev_inst,dev_blk and dev_attrib) | 127 | * At this point 'pvt' (like dev_inst,dev_blk and dev_attrib) |
@@ -156,8 +162,8 @@ struct edac_device_ctl_info *edac_device_alloc_ctl_info( | |||
156 | /* Name of this edac device */ | 162 | /* Name of this edac device */ |
157 | snprintf(dev_ctl->name,sizeof(dev_ctl->name),"%s",edac_device_name); | 163 | snprintf(dev_ctl->name,sizeof(dev_ctl->name),"%s",edac_device_name); |
158 | 164 | ||
159 | edac_dbg(4, "edac_dev=%p next after end=%p\n", | 165 | debugf4("%s() edac_dev=%p next after end=%p\n", |
160 | dev_ctl, pvt + sz_private); | 166 | __func__, dev_ctl, pvt + sz_private ); |
161 | 167 | ||
162 | /* Initialize every Instance */ | 168 | /* Initialize every Instance */ |
163 | for (instance = 0; instance < nr_instances; instance++) { | 169 | for (instance = 0; instance < nr_instances; instance++) { |
@@ -178,8 +184,10 @@ struct edac_device_ctl_info *edac_device_alloc_ctl_info( | |||
178 | snprintf(blk->name, sizeof(blk->name), | 184 | snprintf(blk->name, sizeof(blk->name), |
179 | "%s%d", edac_block_name, block+offset_value); | 185 | "%s%d", edac_block_name, block+offset_value); |
180 | 186 | ||
181 | edac_dbg(4, "instance=%d inst_p=%p block=#%d block_p=%p name='%s'\n", | 187 | debugf4("%s() instance=%d inst_p=%p block=#%d " |
182 | instance, inst, block, blk, blk->name); | 188 | "block_p=%p name='%s'\n", |
189 | __func__, instance, inst, block, | ||
190 | blk, blk->name); | ||
183 | 191 | ||
184 | /* if there are NO attributes OR no attribute pointer | 192 | /* if there are NO attributes OR no attribute pointer |
185 | * then continue on to next block iteration | 193 | * then continue on to next block iteration |
@@ -192,8 +200,8 @@ struct edac_device_ctl_info *edac_device_alloc_ctl_info( | |||
192 | attrib_p = &dev_attrib[block*nr_instances*nr_attrib]; | 200 | attrib_p = &dev_attrib[block*nr_instances*nr_attrib]; |
193 | blk->block_attributes = attrib_p; | 201 | blk->block_attributes = attrib_p; |
194 | 202 | ||
195 | edac_dbg(4, "THIS BLOCK_ATTRIB=%p\n", | 203 | debugf4("%s() THIS BLOCK_ATTRIB=%p\n", |
196 | blk->block_attributes); | 204 | __func__, blk->block_attributes); |
197 | 205 | ||
198 | /* Initialize every user specified attribute in this | 206 | /* Initialize every user specified attribute in this |
199 | * block with the data the caller passed in | 207 | * block with the data the caller passed in |
@@ -212,10 +220,11 @@ struct edac_device_ctl_info *edac_device_alloc_ctl_info( | |||
212 | 220 | ||
213 | attrib->block = blk; /* up link */ | 221 | attrib->block = blk; /* up link */ |
214 | 222 | ||
215 | edac_dbg(4, "alloc-attrib=%p attrib_name='%s' attrib-spec=%p spec-name=%s\n", | 223 | debugf4("%s() alloc-attrib=%p attrib_name='%s' " |
216 | attrib, attrib->attr.name, | 224 | "attrib-spec=%p spec-name=%s\n", |
217 | &attrib_spec[attr], | 225 | __func__, attrib, attrib->attr.name, |
218 | attrib_spec[attr].attr.name | 226 | &attrib_spec[attr], |
227 | attrib_spec[attr].attr.name | ||
219 | ); | 228 | ); |
220 | } | 229 | } |
221 | } | 230 | } |
@@ -270,7 +279,7 @@ static struct edac_device_ctl_info *find_edac_device_by_dev(struct device *dev) | |||
270 | struct edac_device_ctl_info *edac_dev; | 279 | struct edac_device_ctl_info *edac_dev; |
271 | struct list_head *item; | 280 | struct list_head *item; |
272 | 281 | ||
273 | edac_dbg(0, "\n"); | 282 | debugf0("%s()\n", __func__); |
274 | 283 | ||
275 | list_for_each(item, &edac_device_list) { | 284 | list_for_each(item, &edac_device_list) { |
276 | edac_dev = list_entry(item, struct edac_device_ctl_info, link); | 285 | edac_dev = list_entry(item, struct edac_device_ctl_info, link); |
@@ -386,7 +395,7 @@ static void edac_device_workq_function(struct work_struct *work_req) | |||
386 | 395 | ||
387 | /* Reschedule the workq for the next time period to start again | 396 | /* Reschedule the workq for the next time period to start again |
388 | * if the number of msec is for 1 sec, then adjust to the next | 397 | * if the number of msec is for 1 sec, then adjust to the next |
389 | * whole one second to save timers firing all over the period | 398 | * whole one second to save timers fireing all over the period |
390 | * between integral seconds | 399 | * between integral seconds |
391 | */ | 400 | */ |
392 | if (edac_dev->poll_msec == 1000) | 401 | if (edac_dev->poll_msec == 1000) |
@@ -405,7 +414,7 @@ static void edac_device_workq_function(struct work_struct *work_req) | |||
405 | void edac_device_workq_setup(struct edac_device_ctl_info *edac_dev, | 414 | void edac_device_workq_setup(struct edac_device_ctl_info *edac_dev, |
406 | unsigned msec) | 415 | unsigned msec) |
407 | { | 416 | { |
408 | edac_dbg(0, "\n"); | 417 | debugf0("%s()\n", __func__); |
409 | 418 | ||
410 | /* take the arg 'msec' and set it into the control structure | 419 | /* take the arg 'msec' and set it into the control structure |
411 | * to used in the time period calculation | 420 | * to used in the time period calculation |
@@ -493,7 +502,7 @@ EXPORT_SYMBOL_GPL(edac_device_alloc_index); | |||
493 | */ | 502 | */ |
494 | int edac_device_add_device(struct edac_device_ctl_info *edac_dev) | 503 | int edac_device_add_device(struct edac_device_ctl_info *edac_dev) |
495 | { | 504 | { |
496 | edac_dbg(0, "\n"); | 505 | debugf0("%s()\n", __func__); |
497 | 506 | ||
498 | #ifdef CONFIG_EDAC_DEBUG | 507 | #ifdef CONFIG_EDAC_DEBUG |
499 | if (edac_debug_level >= 3) | 508 | if (edac_debug_level >= 3) |
@@ -555,7 +564,7 @@ EXPORT_SYMBOL_GPL(edac_device_add_device); | |||
555 | * Remove sysfs entries for specified edac_device structure and | 564 | * Remove sysfs entries for specified edac_device structure and |
556 | * then remove edac_device structure from global list | 565 | * then remove edac_device structure from global list |
557 | * | 566 | * |
558 | * @dev: | 567 | * @pdev: |
559 | * Pointer to 'struct device' representing edac_device | 568 | * Pointer to 'struct device' representing edac_device |
560 | * structure to remove. | 569 | * structure to remove. |
561 | * | 570 | * |
@@ -567,7 +576,7 @@ struct edac_device_ctl_info *edac_device_del_device(struct device *dev) | |||
567 | { | 576 | { |
568 | struct edac_device_ctl_info *edac_dev; | 577 | struct edac_device_ctl_info *edac_dev; |
569 | 578 | ||
570 | edac_dbg(0, "\n"); | 579 | debugf0("%s()\n", __func__); |
571 | 580 | ||
572 | mutex_lock(&device_ctls_mutex); | 581 | mutex_lock(&device_ctls_mutex); |
573 | 582 | ||