aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/edac/edac_device.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/edac/edac_device.c')
-rw-r--r--drivers/edac/edac_device.c94
1 files changed, 63 insertions, 31 deletions
diff --git a/drivers/edac/edac_device.c b/drivers/edac/edac_device.c
index b53e8d51d9a5..8264e3728c79 100644
--- a/drivers/edac/edac_device.c
+++ b/drivers/edac/edac_device.c
@@ -67,12 +67,12 @@ struct edac_device_ctl_info *edac_device_alloc_ctl_info(
67 char *edac_device_name, unsigned nr_instances, 67 char *edac_device_name, unsigned nr_instances,
68 char *edac_block_name, unsigned nr_blocks, 68 char *edac_block_name, unsigned nr_blocks,
69 unsigned offset_value, /* zero, 1, or other based offset */ 69 unsigned offset_value, /* zero, 1, or other based offset */
70 struct edac_attrib_spec *attrib_spec, unsigned nr_attribs) 70 struct edac_dev_sysfs_block_attribute *attrib_spec, unsigned nr_attrib)
71{ 71{
72 struct edac_device_ctl_info *dev_ctl; 72 struct edac_device_ctl_info *dev_ctl;
73 struct edac_device_instance *dev_inst, *inst; 73 struct edac_device_instance *dev_inst, *inst;
74 struct edac_device_block *dev_blk, *blk_p, *blk; 74 struct edac_device_block *dev_blk, *blk_p, *blk;
75 struct edac_attrib *dev_attrib, *attrib_p, *attrib; 75 struct edac_dev_sysfs_block_attribute *dev_attrib, *attrib_p, *attrib;
76 unsigned total_size; 76 unsigned total_size;
77 unsigned count; 77 unsigned count;
78 unsigned instance, block, attr; 78 unsigned instance, block, attr;
@@ -81,29 +81,47 @@ struct edac_device_ctl_info *edac_device_alloc_ctl_info(
81 debugf1("%s() instances=%d blocks=%d\n", 81 debugf1("%s() instances=%d blocks=%d\n",
82 __func__, nr_instances, nr_blocks); 82 __func__, nr_instances, nr_blocks);
83 83
84 /* Figure out the offsets of the various items from the start of an 84 /* Calculate the size of memory we need to allocate AND
85 * ctl_info structure. We want the alignment of each item 85 * determine the offsets of the various item arrays
86 * (instance,block,attrib) from the start of an allocated structure.
87 * We want the alignment of each item (instance,block,attrib)
86 * to be at least as stringent as what the compiler would 88 * to be at least as stringent as what the compiler would
87 * provide if we could simply hardcode everything into a single struct. 89 * provide if we could simply hardcode everything into a single struct.
88 */ 90 */
89 dev_ctl = (struct edac_device_ctl_info *)NULL; 91 dev_ctl = (struct edac_device_ctl_info *)NULL;
90 92
91 /* Calc the 'end' offset past the ctl_info structure */ 93 /* Calc the 'end' offset past end of ONE ctl_info structure
94 * which will become the start of the 'instance' array
95 */
92 dev_inst = edac_align_ptr(&dev_ctl[1], sizeof(*dev_inst)); 96 dev_inst = edac_align_ptr(&dev_ctl[1], sizeof(*dev_inst));
93 97
94 /* Calc the 'end' offset past the instance array */ 98 /* Calc the 'end' offset past the instance array within the ctl_info
99 * which will become the start of the block array
100 */
95 dev_blk = edac_align_ptr(&dev_inst[nr_instances], sizeof(*dev_blk)); 101 dev_blk = edac_align_ptr(&dev_inst[nr_instances], sizeof(*dev_blk));
96 102
97 /* Calc the 'end' offset past the dev_blk array */ 103 /* Calc the 'end' offset past the dev_blk array
104 * which will become the start of the attrib array, if any.
105 */
98 count = nr_instances * nr_blocks; 106 count = nr_instances * nr_blocks;
99 dev_attrib = edac_align_ptr(&dev_blk[count], sizeof(*dev_attrib)); 107 dev_attrib = edac_align_ptr(&dev_blk[count], sizeof(*dev_attrib));
100 108
101 /* Check for case of NO attributes specified */ 109 /* Check for case of when an attribute array is specified */
102 if (nr_attribs > 0) 110 if (nr_attrib > 0) {
103 count *= nr_attribs; 111 /* calc how many nr_attrib we need */
112 count *= nr_attrib;
104 113
105 /* Calc the 'end' offset past the attributes array */ 114 /* Calc the 'end' offset past the attributes array */
106 pvt = edac_align_ptr(&dev_attrib[count], sz_private); 115 pvt = edac_align_ptr(&dev_attrib[count], sz_private);
116 } else {
117 /* no attribute array specificed */
118 pvt = edac_align_ptr(dev_attrib, sz_private);
119 }
120
121 /* 'pvt' now points to where the private data area is.
122 * At this point 'pvt' (like dev_inst,dev_blk and dev_attrib)
123 * is baselined at ZERO
124 */
107 total_size = ((unsigned long)pvt) + sz_private; 125 total_size = ((unsigned long)pvt) + sz_private;
108 126
109 /* Allocate the amount of memory for the set of control structures */ 127 /* Allocate the amount of memory for the set of control structures */
@@ -111,17 +129,22 @@ struct edac_device_ctl_info *edac_device_alloc_ctl_info(
111 if (dev_ctl == NULL) 129 if (dev_ctl == NULL)
112 return NULL; 130 return NULL;
113 131
114 /* Adjust pointers so they point within the memory we just allocated 132 /* Adjust pointers so they point within the actual memory we
115 * rather than an imaginary chunk of memory located at address 0. 133 * just allocated rather than an imaginary chunk of memory
134 * located at address 0.
135 * 'dev_ctl' points to REAL memory, while the others are
136 * ZERO based and thus need to be adjusted to point within
137 * the allocated memory.
116 */ 138 */
117 dev_inst = (struct edac_device_instance *) 139 dev_inst = (struct edac_device_instance *)
118 (((char *)dev_ctl) + ((unsigned long)dev_inst)); 140 (((char *)dev_ctl) + ((unsigned long)dev_inst));
119 dev_blk = (struct edac_device_block *) 141 dev_blk = (struct edac_device_block *)
120 (((char *)dev_ctl) + ((unsigned long)dev_blk)); 142 (((char *)dev_ctl) + ((unsigned long)dev_blk));
121 dev_attrib = (struct edac_attrib *) 143 dev_attrib = (struct edac_dev_sysfs_block_attribute *)
122 (((char *)dev_ctl) + ((unsigned long)dev_attrib)); 144 (((char *)dev_ctl) + ((unsigned long)dev_attrib));
123 pvt = sz_private ? (((char *)dev_ctl) + ((unsigned long)pvt)) : NULL; 145 pvt = sz_private ? (((char *)dev_ctl) + ((unsigned long)pvt)) : NULL;
124 146
147 /* Begin storing the information into the control info structure */
125 dev_ctl->nr_instances = nr_instances; 148 dev_ctl->nr_instances = nr_instances;
126 dev_ctl->instances = dev_inst; 149 dev_ctl->instances = dev_inst;
127 dev_ctl->pvt_info = pvt; 150 dev_ctl->pvt_info = pvt;
@@ -145,28 +168,37 @@ struct edac_device_ctl_info *edac_device_alloc_ctl_info(
145 for (block = 0; block < nr_blocks; block++) { 168 for (block = 0; block < nr_blocks; block++) {
146 blk = &blk_p[block]; 169 blk = &blk_p[block];
147 blk->instance = inst; 170 blk->instance = inst;
148 blk->nr_attribs = nr_attribs;
149 attrib_p = &dev_attrib[block * nr_attribs];
150 blk->attribs = attrib_p;
151 snprintf(blk->name, sizeof(blk->name), 171 snprintf(blk->name, sizeof(blk->name),
152 "%s%d", edac_block_name, block+offset_value); 172 "%s%d", edac_block_name, block+offset_value);
153 173
154 debugf1("%s() instance=%d block=%d name=%s\n", 174 debugf1("%s() instance=%d block=%d name=%s\n",
155 __func__, instance, block, blk->name); 175 __func__, instance, block, blk->name);
156 176
157 if (attrib_spec != NULL) { 177 /* if there are NO attributes OR no attribute pointer
158 /* when there is an attrib_spec passed int then 178 * then continue on to next block iteration
159 * Initialize every attrib of each block 179 */
160 */ 180 if ((nr_attrib == 0) || (attrib_spec == NULL))
161 for (attr = 0; attr < nr_attribs; attr++) { 181 continue;
162 attrib = &attrib_p[attr]; 182
163 attrib->block = blk; 183 /* setup the attribute array for this block */
164 184 blk->nr_attribs = nr_attrib;
165 /* Link each attribute to the caller's 185 attrib_p = &dev_attrib[block*nr_instances*nr_attrib];
166 * spec entry, for name and type 186 blk->block_attributes = attrib_p;
167 */ 187
168 attrib->spec = &attrib_spec[attr]; 188 /* Initialize every user specified attribute in this
169 } 189 * block with the data the caller passed in
190 */
191 for (attr = 0; attr < nr_attrib; attr++) {
192 attrib = &attrib_p[attr];
193 attrib->attr = attrib_spec->attr;
194 attrib->show = attrib_spec->show;
195 attrib->store = attrib_spec->store;
196
197 /* up reference this block */
198 attrib->block = blk;
199
200 /* bump the attrib_spec */
201 attrib_spec++;
170 } 202 }
171 } 203 }
172 } 204 }