diff options
Diffstat (limited to 'drivers/edac/edac_device.c')
-rw-r--r-- | drivers/edac/edac_device.c | 94 |
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 | } |