aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/edac/edac_mc.c13
-rw-r--r--drivers/edac/edac_mc_sysfs.c1074
-rw-r--r--drivers/edac/edac_module.c13
-rw-r--r--drivers/edac/edac_module.h9
-rw-r--r--include/linux/edac.h47
5 files changed, 450 insertions, 706 deletions
diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c
index 811f09a38f3a..61ae34643b49 100644
--- a/drivers/edac/edac_mc.c
+++ b/drivers/edac/edac_mc.c
@@ -218,7 +218,7 @@ struct mem_ctl_info *edac_mc_alloc(unsigned mc_num,
218 unsigned size, tot_dimms = 1, count = 1; 218 unsigned size, tot_dimms = 1, count = 1;
219 unsigned tot_csrows = 1, tot_channels = 1, tot_errcount = 0; 219 unsigned tot_csrows = 1, tot_channels = 1, tot_errcount = 0;
220 void *pvt, *p, *ptr = NULL; 220 void *pvt, *p, *ptr = NULL;
221 int i, j, err, row, chn, n, len; 221 int i, j, row, chn, n, len;
222 bool per_rank = false; 222 bool per_rank = false;
223 223
224 BUG_ON(n_layers > EDAC_MAX_LAYERS || n_layers == 0); 224 BUG_ON(n_layers > EDAC_MAX_LAYERS || n_layers == 0);
@@ -374,15 +374,6 @@ struct mem_ctl_info *edac_mc_alloc(unsigned mc_num,
374 mci->op_state = OP_ALLOC; 374 mci->op_state = OP_ALLOC;
375 INIT_LIST_HEAD(&mci->grp_kobj_list); 375 INIT_LIST_HEAD(&mci->grp_kobj_list);
376 376
377 /*
378 * Initialize the 'root' kobj for the edac_mc controller
379 */
380 err = edac_mc_register_sysfs_main_kobj(mci);
381 if (err) {
382 kfree(mci);
383 return NULL;
384 }
385
386 /* at this point, the root kobj is valid, and in order to 377 /* at this point, the root kobj is valid, and in order to
387 * 'free' the object, then the function: 378 * 'free' the object, then the function:
388 * edac_mc_unregister_sysfs_main_kobj() must be called 379 * edac_mc_unregister_sysfs_main_kobj() must be called
@@ -403,7 +394,7 @@ void edac_mc_free(struct mem_ctl_info *mci)
403{ 394{
404 debugf1("%s()\n", __func__); 395 debugf1("%s()\n", __func__);
405 396
406 edac_mc_unregister_sysfs_main_kobj(mci); 397 edac_unregister_sysfs(mci);
407 398
408 /* free the mci instance memory here */ 399 /* free the mci instance memory here */
409 kfree(mci); 400 kfree(mci);
diff --git a/drivers/edac/edac_mc_sysfs.c b/drivers/edac/edac_mc_sysfs.c
index 595371941ef9..7002c9cab999 100644
--- a/drivers/edac/edac_mc_sysfs.c
+++ b/drivers/edac/edac_mc_sysfs.c
@@ -7,17 +7,20 @@
7 * 7 *
8 * Written Doug Thompson <norsk5@xmission.com> www.softwarebitmaker.com 8 * Written Doug Thompson <norsk5@xmission.com> www.softwarebitmaker.com
9 * 9 *
10 * (c) 2012 - Mauro Carvalho Chehab <mchehab@redhat.com>
11 * The entire API were re-written, and ported to use struct device
12 *
10 */ 13 */
11 14
12#include <linux/ctype.h> 15#include <linux/ctype.h>
13#include <linux/slab.h> 16#include <linux/slab.h>
14#include <linux/edac.h> 17#include <linux/edac.h>
15#include <linux/bug.h> 18#include <linux/bug.h>
19#include <linux/pm_runtime.h>
16 20
17#include "edac_core.h" 21#include "edac_core.h"
18#include "edac_module.h" 22#include "edac_module.h"
19 23
20
21/* MC EDAC Controls, setable by module parameter, and sysfs */ 24/* MC EDAC Controls, setable by module parameter, and sysfs */
22static int edac_mc_log_ue = 1; 25static int edac_mc_log_ue = 1;
23static int edac_mc_log_ce = 1; 26static int edac_mc_log_ce = 1;
@@ -78,6 +81,8 @@ module_param_call(edac_mc_poll_msec, edac_set_poll_msec, param_get_int,
78 &edac_mc_poll_msec, 0644); 81 &edac_mc_poll_msec, 0644);
79MODULE_PARM_DESC(edac_mc_poll_msec, "Polling period in milliseconds"); 82MODULE_PARM_DESC(edac_mc_poll_msec, "Polling period in milliseconds");
80 83
84static struct device mci_pdev;
85
81/* 86/*
82 * various constants for Memory Controllers 87 * various constants for Memory Controllers
83 */ 88 */
@@ -125,308 +130,336 @@ static const char *edac_caps[] = {
125 [EDAC_S16ECD16ED] = "S16ECD16ED" 130 [EDAC_S16ECD16ED] = "S16ECD16ED"
126}; 131};
127 132
128/* EDAC sysfs CSROW data structures and methods 133/*
134 * EDAC sysfs CSROW data structures and methods
135 */
136
137#define to_csrow(k) container_of(k, struct csrow_info, dev)
138
139/*
140 * We need it to avoid namespace conflicts between the legacy API
141 * and the per-dimm/per-rank one
129 */ 142 */
143#define DEVICE_ATTR_LEGACY(_name, _mode, _show, _store) \
144 struct device_attribute dev_attr_legacy_##_name = __ATTR(_name, _mode, _show, _store)
145
146struct dev_ch_attribute {
147 struct device_attribute attr;
148 int channel;
149};
150
151#define DEVICE_CHANNEL(_name, _mode, _show, _store, _var) \
152 struct dev_ch_attribute dev_attr_legacy_##_name = \
153 { __ATTR(_name, _mode, _show, _store), (_var) }
154
155#define to_channel(k) (container_of(k, struct dev_ch_attribute, attr)->channel)
130 156
131/* Set of more default csrow<id> attribute show/store functions */ 157/* Set of more default csrow<id> attribute show/store functions */
132static ssize_t csrow_ue_count_show(struct csrow_info *csrow, char *data, 158static ssize_t csrow_ue_count_show(struct device *dev,
133 int private) 159 struct device_attribute *mattr, char *data)
134{ 160{
161 struct csrow_info *csrow = to_csrow(dev);
162
135 return sprintf(data, "%u\n", csrow->ue_count); 163 return sprintf(data, "%u\n", csrow->ue_count);
136} 164}
137 165
138static ssize_t csrow_ce_count_show(struct csrow_info *csrow, char *data, 166static ssize_t csrow_ce_count_show(struct device *dev,
139 int private) 167 struct device_attribute *mattr, char *data)
140{ 168{
169 struct csrow_info *csrow = to_csrow(dev);
170
141 return sprintf(data, "%u\n", csrow->ce_count); 171 return sprintf(data, "%u\n", csrow->ce_count);
142} 172}
143 173
144static ssize_t csrow_size_show(struct csrow_info *csrow, char *data, 174static ssize_t csrow_size_show(struct device *dev,
145 int private) 175 struct device_attribute *mattr, char *data)
146{ 176{
177 struct csrow_info *csrow = to_csrow(dev);
147 int i; 178 int i;
148 u32 nr_pages = 0; 179 u32 nr_pages = 0;
149 180
150 for (i = 0; i < csrow->nr_channels; i++) 181 for (i = 0; i < csrow->nr_channels; i++)
151 nr_pages += csrow->channels[i].dimm->nr_pages; 182 nr_pages += csrow->channels[i].dimm->nr_pages;
152
153 return sprintf(data, "%u\n", PAGES_TO_MiB(nr_pages)); 183 return sprintf(data, "%u\n", PAGES_TO_MiB(nr_pages));
154} 184}
155 185
156static ssize_t csrow_mem_type_show(struct csrow_info *csrow, char *data, 186static ssize_t csrow_mem_type_show(struct device *dev,
157 int private) 187 struct device_attribute *mattr, char *data)
158{ 188{
189 struct csrow_info *csrow = to_csrow(dev);
190
159 return sprintf(data, "%s\n", mem_types[csrow->channels[0].dimm->mtype]); 191 return sprintf(data, "%s\n", mem_types[csrow->channels[0].dimm->mtype]);
160} 192}
161 193
162static ssize_t csrow_dev_type_show(struct csrow_info *csrow, char *data, 194static ssize_t csrow_dev_type_show(struct device *dev,
163 int private) 195 struct device_attribute *mattr, char *data)
164{ 196{
197 struct csrow_info *csrow = to_csrow(dev);
198
165 return sprintf(data, "%s\n", dev_types[csrow->channels[0].dimm->dtype]); 199 return sprintf(data, "%s\n", dev_types[csrow->channels[0].dimm->dtype]);
166} 200}
167 201
168static ssize_t csrow_edac_mode_show(struct csrow_info *csrow, char *data, 202static ssize_t csrow_edac_mode_show(struct device *dev,
169 int private) 203 struct device_attribute *mattr,
204 char *data)
170{ 205{
206 struct csrow_info *csrow = to_csrow(dev);
207
171 return sprintf(data, "%s\n", edac_caps[csrow->channels[0].dimm->edac_mode]); 208 return sprintf(data, "%s\n", edac_caps[csrow->channels[0].dimm->edac_mode]);
172} 209}
173 210
174/* show/store functions for DIMM Label attributes */ 211/* show/store functions for DIMM Label attributes */
175static ssize_t channel_dimm_label_show(struct csrow_info *csrow, 212static ssize_t channel_dimm_label_show(struct device *dev,
176 char *data, int channel) 213 struct device_attribute *mattr,
214 char *data)
177{ 215{
216 struct csrow_info *csrow = to_csrow(dev);
217 unsigned chan = to_channel(mattr);
218 struct rank_info *rank = &csrow->channels[chan];
219
178 /* if field has not been initialized, there is nothing to send */ 220 /* if field has not been initialized, there is nothing to send */
179 if (!csrow->channels[channel].dimm->label[0]) 221 if (!rank->dimm->label[0])
180 return 0; 222 return 0;
181 223
182 return snprintf(data, EDAC_MC_LABEL_LEN, "%s\n", 224 return snprintf(data, EDAC_MC_LABEL_LEN, "%s\n",
183 csrow->channels[channel].dimm->label); 225 rank->dimm->label);
184} 226}
185 227
186static ssize_t channel_dimm_label_store(struct csrow_info *csrow, 228static ssize_t channel_dimm_label_store(struct device *dev,
187 const char *data, 229 struct device_attribute *mattr,
188 size_t count, int channel) 230 const char *data, size_t count)
189{ 231{
232 struct csrow_info *csrow = to_csrow(dev);
233 unsigned chan = to_channel(mattr);
234 struct rank_info *rank = &csrow->channels[chan];
235
190 ssize_t max_size = 0; 236 ssize_t max_size = 0;
191 237
192 max_size = min((ssize_t) count, (ssize_t) EDAC_MC_LABEL_LEN - 1); 238 max_size = min((ssize_t) count, (ssize_t) EDAC_MC_LABEL_LEN - 1);
193 strncpy(csrow->channels[channel].dimm->label, data, max_size); 239 strncpy(rank->dimm->label, data, max_size);
194 csrow->channels[channel].dimm->label[max_size] = '\0'; 240 rank->dimm->label[max_size] = '\0';
195 241
196 return max_size; 242 return max_size;
197} 243}
198 244
199/* show function for dynamic chX_ce_count attribute */ 245/* show function for dynamic chX_ce_count attribute */
200static ssize_t channel_ce_count_show(struct csrow_info *csrow, 246static ssize_t channel_ce_count_show(struct device *dev,
201 char *data, int channel) 247 struct device_attribute *mattr, char *data)
202{ 248{
203 return sprintf(data, "%u\n", csrow->channels[channel].ce_count); 249 struct csrow_info *csrow = to_csrow(dev);
250 unsigned chan = to_channel(mattr);
251 struct rank_info *rank = &csrow->channels[chan];
252
253 return sprintf(data, "%u\n", rank->ce_count);
204} 254}
205 255
206/* csrow specific attribute structure */ 256/* cwrow<id>/attribute files */
207struct csrowdev_attribute { 257DEVICE_ATTR_LEGACY(size_mb, S_IRUGO, csrow_size_show, NULL);
208 struct attribute attr; 258DEVICE_ATTR_LEGACY(dev_type, S_IRUGO, csrow_dev_type_show, NULL);
209 ssize_t(*show) (struct csrow_info *, char *, int); 259DEVICE_ATTR_LEGACY(mem_type, S_IRUGO, csrow_mem_type_show, NULL);
210 ssize_t(*store) (struct csrow_info *, const char *, size_t, int); 260DEVICE_ATTR_LEGACY(edac_mode, S_IRUGO, csrow_edac_mode_show, NULL);
211 int private; 261DEVICE_ATTR_LEGACY(ue_count, S_IRUGO, csrow_ue_count_show, NULL);
212}; 262DEVICE_ATTR_LEGACY(ce_count, S_IRUGO, csrow_ce_count_show, NULL);
213 263
214#define to_csrow(k) container_of(k, struct csrow_info, kobj) 264/* default attributes of the CSROW<id> object */
215#define to_csrowdev_attr(a) container_of(a, struct csrowdev_attribute, attr) 265static struct attribute *csrow_attrs[] = {
266 &dev_attr_legacy_dev_type.attr,
267 &dev_attr_legacy_mem_type.attr,
268 &dev_attr_legacy_edac_mode.attr,
269 &dev_attr_legacy_size_mb.attr,
270 &dev_attr_legacy_ue_count.attr,
271 &dev_attr_legacy_ce_count.attr,
272 NULL,
273};
216 274
217/* Set of show/store higher level functions for default csrow attributes */ 275static struct attribute_group csrow_attr_grp = {
218static ssize_t csrowdev_show(struct kobject *kobj, 276 .attrs = csrow_attrs,
219 struct attribute *attr, char *buffer) 277};
220{
221 struct csrow_info *csrow = to_csrow(kobj);
222 struct csrowdev_attribute *csrowdev_attr = to_csrowdev_attr(attr);
223 278
224 if (csrowdev_attr->show) 279static const struct attribute_group *csrow_attr_groups[] = {
225 return csrowdev_attr->show(csrow, 280 &csrow_attr_grp,
226 buffer, csrowdev_attr->private); 281 NULL
227 return -EIO; 282};
228}
229 283
230static ssize_t csrowdev_store(struct kobject *kobj, struct attribute *attr, 284static void csrow_attr_release(struct device *device)
231 const char *buffer, size_t count)
232{ 285{
233 struct csrow_info *csrow = to_csrow(kobj); 286 debugf1("Releasing csrow device %s\n", dev_name(device));
234 struct csrowdev_attribute *csrowdev_attr = to_csrowdev_attr(attr);
235
236 if (csrowdev_attr->store)
237 return csrowdev_attr->store(csrow,
238 buffer,
239 count, csrowdev_attr->private);
240 return -EIO;
241} 287}
242 288
243static const struct sysfs_ops csrowfs_ops = { 289static struct device_type csrow_attr_type = {
244 .show = csrowdev_show, 290 .groups = csrow_attr_groups,
245 .store = csrowdev_store 291 .release = csrow_attr_release,
246}; 292};
247 293
248#define CSROWDEV_ATTR(_name,_mode,_show,_store,_private) \ 294/*
249static struct csrowdev_attribute attr_##_name = { \ 295 * possible dynamic channel DIMM Label attribute files
250 .attr = {.name = __stringify(_name), .mode = _mode }, \ 296 *
251 .show = _show, \ 297 */
252 .store = _store, \
253 .private = _private, \
254};
255
256/* default cwrow<id>/attribute files */
257CSROWDEV_ATTR(size_mb, S_IRUGO, csrow_size_show, NULL, 0);
258CSROWDEV_ATTR(dev_type, S_IRUGO, csrow_dev_type_show, NULL, 0);
259CSROWDEV_ATTR(mem_type, S_IRUGO, csrow_mem_type_show, NULL, 0);
260CSROWDEV_ATTR(edac_mode, S_IRUGO, csrow_edac_mode_show, NULL, 0);
261CSROWDEV_ATTR(ue_count, S_IRUGO, csrow_ue_count_show, NULL, 0);
262CSROWDEV_ATTR(ce_count, S_IRUGO, csrow_ce_count_show, NULL, 0);
263 298
264/* default attributes of the CSROW<id> object */ 299#define EDAC_NR_CHANNELS 6
265static struct csrowdev_attribute *default_csrow_attr[] = {
266 &attr_dev_type,
267 &attr_mem_type,
268 &attr_edac_mode,
269 &attr_size_mb,
270 &attr_ue_count,
271 &attr_ce_count,
272 NULL,
273};
274 300
275/* possible dynamic channel DIMM Label attribute files */ 301DEVICE_CHANNEL(ch0_dimm_label, S_IRUGO | S_IWUSR,
276CSROWDEV_ATTR(ch0_dimm_label, S_IRUGO | S_IWUSR,
277 channel_dimm_label_show, channel_dimm_label_store, 0); 302 channel_dimm_label_show, channel_dimm_label_store, 0);
278CSROWDEV_ATTR(ch1_dimm_label, S_IRUGO | S_IWUSR, 303DEVICE_CHANNEL(ch1_dimm_label, S_IRUGO | S_IWUSR,
279 channel_dimm_label_show, channel_dimm_label_store, 1); 304 channel_dimm_label_show, channel_dimm_label_store, 1);
280CSROWDEV_ATTR(ch2_dimm_label, S_IRUGO | S_IWUSR, 305DEVICE_CHANNEL(ch2_dimm_label, S_IRUGO | S_IWUSR,
281 channel_dimm_label_show, channel_dimm_label_store, 2); 306 channel_dimm_label_show, channel_dimm_label_store, 2);
282CSROWDEV_ATTR(ch3_dimm_label, S_IRUGO | S_IWUSR, 307DEVICE_CHANNEL(ch3_dimm_label, S_IRUGO | S_IWUSR,
283 channel_dimm_label_show, channel_dimm_label_store, 3); 308 channel_dimm_label_show, channel_dimm_label_store, 3);
284CSROWDEV_ATTR(ch4_dimm_label, S_IRUGO | S_IWUSR, 309DEVICE_CHANNEL(ch4_dimm_label, S_IRUGO | S_IWUSR,
285 channel_dimm_label_show, channel_dimm_label_store, 4); 310 channel_dimm_label_show, channel_dimm_label_store, 4);
286CSROWDEV_ATTR(ch5_dimm_label, S_IRUGO | S_IWUSR, 311DEVICE_CHANNEL(ch5_dimm_label, S_IRUGO | S_IWUSR,
287 channel_dimm_label_show, channel_dimm_label_store, 5); 312 channel_dimm_label_show, channel_dimm_label_store, 5);
288 313
289/* Total possible dynamic DIMM Label attribute file table */ 314/* Total possible dynamic DIMM Label attribute file table */
290static struct csrowdev_attribute *dynamic_csrow_dimm_attr[] = { 315static struct device_attribute *dynamic_csrow_dimm_attr[] = {
291 &attr_ch0_dimm_label, 316 &dev_attr_legacy_ch0_dimm_label.attr,
292 &attr_ch1_dimm_label, 317 &dev_attr_legacy_ch1_dimm_label.attr,
293 &attr_ch2_dimm_label, 318 &dev_attr_legacy_ch2_dimm_label.attr,
294 &attr_ch3_dimm_label, 319 &dev_attr_legacy_ch3_dimm_label.attr,
295 &attr_ch4_dimm_label, 320 &dev_attr_legacy_ch4_dimm_label.attr,
296 &attr_ch5_dimm_label 321 &dev_attr_legacy_ch5_dimm_label.attr
297}; 322};
298 323
299/* possible dynamic channel ce_count attribute files */ 324/* possible dynamic channel ce_count attribute files */
300CSROWDEV_ATTR(ch0_ce_count, S_IRUGO | S_IWUSR, channel_ce_count_show, NULL, 0); 325DEVICE_CHANNEL(ch0_ce_count, S_IRUGO | S_IWUSR,
301CSROWDEV_ATTR(ch1_ce_count, S_IRUGO | S_IWUSR, channel_ce_count_show, NULL, 1); 326 channel_ce_count_show, NULL, 0);
302CSROWDEV_ATTR(ch2_ce_count, S_IRUGO | S_IWUSR, channel_ce_count_show, NULL, 2); 327DEVICE_CHANNEL(ch1_ce_count, S_IRUGO | S_IWUSR,
303CSROWDEV_ATTR(ch3_ce_count, S_IRUGO | S_IWUSR, channel_ce_count_show, NULL, 3); 328 channel_ce_count_show, NULL, 1);
304CSROWDEV_ATTR(ch4_ce_count, S_IRUGO | S_IWUSR, channel_ce_count_show, NULL, 4); 329DEVICE_CHANNEL(ch2_ce_count, S_IRUGO | S_IWUSR,
305CSROWDEV_ATTR(ch5_ce_count, S_IRUGO | S_IWUSR, channel_ce_count_show, NULL, 5); 330 channel_ce_count_show, NULL, 2);
331DEVICE_CHANNEL(ch3_ce_count, S_IRUGO | S_IWUSR,
332 channel_ce_count_show, NULL, 3);
333DEVICE_CHANNEL(ch4_ce_count, S_IRUGO | S_IWUSR,
334 channel_ce_count_show, NULL, 4);
335DEVICE_CHANNEL(ch5_ce_count, S_IRUGO | S_IWUSR,
336 channel_ce_count_show, NULL, 5);
306 337
307/* Total possible dynamic ce_count attribute file table */ 338/* Total possible dynamic ce_count attribute file table */
308static struct csrowdev_attribute *dynamic_csrow_ce_count_attr[] = { 339static struct device_attribute *dynamic_csrow_ce_count_attr[] = {
309 &attr_ch0_ce_count, 340 &dev_attr_legacy_ch0_ce_count.attr,
310 &attr_ch1_ce_count, 341 &dev_attr_legacy_ch1_ce_count.attr,
311 &attr_ch2_ce_count, 342 &dev_attr_legacy_ch2_ce_count.attr,
312 &attr_ch3_ce_count, 343 &dev_attr_legacy_ch3_ce_count.attr,
313 &attr_ch4_ce_count, 344 &dev_attr_legacy_ch4_ce_count.attr,
314 &attr_ch5_ce_count 345 &dev_attr_legacy_ch5_ce_count.attr
315}; 346};
316 347
317#define EDAC_NR_CHANNELS 6 348/* Create a CSROW object under specifed edac_mc_device */
318 349static int edac_create_csrow_object(struct mem_ctl_info *mci,
319/* Create dynamic CHANNEL files, indexed by 'chan', under specifed CSROW */ 350 struct csrow_info *csrow, int index)
320static int edac_create_channel_files(struct kobject *kobj, int chan)
321{ 351{
322 int err = -ENODEV; 352 int err, chan;
323 353
324 if (chan >= EDAC_NR_CHANNELS) 354 if (csrow->nr_channels >= EDAC_NR_CHANNELS)
325 return err; 355 return -ENODEV;
326 356
327 /* create the DIMM label attribute file */ 357 csrow->dev.type = &csrow_attr_type;
328 err = sysfs_create_file(kobj, 358 csrow->dev.bus = &mci->bus;
329 (struct attribute *) 359 device_initialize(&csrow->dev);
330 dynamic_csrow_dimm_attr[chan]); 360 csrow->dev.parent = &mci->dev;
331 361 dev_set_name(&csrow->dev, "csrow%d", index);
332 if (!err) { 362 dev_set_drvdata(&csrow->dev, csrow);
333 /* create the CE Count attribute file */
334 err = sysfs_create_file(kobj,
335 (struct attribute *)
336 dynamic_csrow_ce_count_attr[chan]);
337 } else {
338 debugf1("%s() dimm labels and ce_count files created",
339 __func__);
340 }
341 363
342 return err; 364 debugf0("%s(): creating (virtual) csrow node %s\n", __func__,
343} 365 dev_name(&csrow->dev));
344 366
345/* No memory to release for this kobj */ 367 err = device_add(&csrow->dev);
346static void edac_csrow_instance_release(struct kobject *kobj) 368 if (err < 0)
347{ 369 return err;
348 struct mem_ctl_info *mci;
349 struct csrow_info *cs;
350 370
351 debugf1("%s()\n", __func__); 371 for (chan = 0; chan < csrow->nr_channels; chan++) {
372 err = device_create_file(&csrow->dev,
373 dynamic_csrow_dimm_attr[chan]);
374 if (err < 0)
375 goto error;
376 err = device_create_file(&csrow->dev,
377 dynamic_csrow_ce_count_attr[chan]);
378 if (err < 0) {
379 device_remove_file(&csrow->dev,
380 dynamic_csrow_dimm_attr[chan]);
381 goto error;
382 }
383 }
352 384
353 cs = container_of(kobj, struct csrow_info, kobj); 385 return 0;
354 mci = cs->mci;
355 386
356 kobject_put(&mci->edac_mci_kobj); 387error:
357} 388 for (--chan; chan >= 0; chan--) {
389 device_remove_file(&csrow->dev,
390 dynamic_csrow_dimm_attr[chan]);
391 device_remove_file(&csrow->dev,
392 dynamic_csrow_ce_count_attr[chan]);
393 }
394 put_device(&csrow->dev);
358 395
359/* the kobj_type instance for a CSROW */ 396 return err;
360static struct kobj_type ktype_csrow = { 397}
361 .release = edac_csrow_instance_release,
362 .sysfs_ops = &csrowfs_ops,
363 .default_attrs = (struct attribute **)default_csrow_attr,
364};
365 398
366/* Create a CSROW object under specifed edac_mc_device */ 399/* Create a CSROW object under specifed edac_mc_device */
367static int edac_create_csrow_object(struct mem_ctl_info *mci, 400static int edac_create_csrow_objects(struct mem_ctl_info *mci)
368 struct csrow_info *csrow, int index)
369{ 401{
370 struct kobject *kobj_mci = &mci->edac_mci_kobj; 402 int err, i, chan;
371 struct kobject *kobj; 403 struct csrow_info *csrow;
372 int chan;
373 int err;
374 404
375 /* generate ..../edac/mc/mc<id>/csrow<index> */ 405 for (i = 0; i < mci->nr_csrows; i++) {
376 memset(&csrow->kobj, 0, sizeof(csrow->kobj)); 406 err = edac_create_csrow_object(mci, &mci->csrows[i], i);
377 csrow->mci = mci; /* include container up link */ 407 if (err < 0)
408 goto error;
409 }
410 return 0;
378 411
379 /* bump the mci instance's kobject's ref count */ 412error:
380 kobj = kobject_get(&mci->edac_mci_kobj); 413 for (--i; i >= 0; i--) {
381 if (!kobj) { 414 csrow = &mci->csrows[i];
382 err = -ENODEV; 415 for (chan = csrow->nr_channels - 1; chan >= 0; chan--) {
383 goto err_out; 416 device_remove_file(&csrow->dev,
417 dynamic_csrow_dimm_attr[chan]);
418 device_remove_file(&csrow->dev,
419 dynamic_csrow_ce_count_attr[chan]);
420 }
421 put_device(&mci->csrows[i].dev);
384 } 422 }
385 423
386 /* Instanstiate the csrow object */ 424 return err;
387 err = kobject_init_and_add(&csrow->kobj, &ktype_csrow, kobj_mci, 425}
388 "csrow%d", index);
389 if (err)
390 goto err_release_top_kobj;
391 426
392 /* At this point, to release a csrow kobj, one must 427static void edac_delete_csrow_objects(struct mem_ctl_info *mci)
393 * call the kobject_put and allow that tear down 428{
394 * to work the releasing 429 int i, chan;
395 */ 430 struct csrow_info *csrow;
396 431
397 /* Create the dyanmic attribute files on this csrow, 432 for (i = mci->nr_csrows - 1; i >= 0; i--) {
398 * namely, the DIMM labels and the channel ce_count 433 csrow = &mci->csrows[i];
399 */ 434 for (chan = csrow->nr_channels - 1; chan >= 0; chan--) {
400 for (chan = 0; chan < csrow->nr_channels; chan++) { 435 debugf1("Removing csrow %d channel %d sysfs nodes\n",
401 err = edac_create_channel_files(&csrow->kobj, chan); 436 i, chan);
402 if (err) { 437 device_remove_file(&csrow->dev,
403 /* special case the unregister here */ 438 dynamic_csrow_dimm_attr[chan]);
404 kobject_put(&csrow->kobj); 439 device_remove_file(&csrow->dev,
405 goto err_out; 440 dynamic_csrow_ce_count_attr[chan]);
406 } 441 }
442 put_device(&mci->csrows[i].dev);
443 device_del(&mci->csrows[i].dev);
407 } 444 }
408 kobject_uevent(&csrow->kobj, KOBJ_ADD);
409 return 0;
410
411 /* error unwind stack */
412err_release_top_kobj:
413 kobject_put(&mci->edac_mci_kobj);
414
415err_out:
416 return err;
417} 445}
418 446
419/* default sysfs methods and data structures for the main MCI kobject */ 447/*
448 * Memory controller device
449 */
450
451#define to_mci(k) container_of(k, struct mem_ctl_info, dev)
420 452
421static ssize_t mci_reset_counters_store(struct mem_ctl_info *mci, 453static ssize_t mci_reset_counters_store(struct device *dev,
454 struct device_attribute *mattr,
422 const char *data, size_t count) 455 const char *data, size_t count)
423{ 456{
424 int row, chan; 457 struct mem_ctl_info *mci = to_mci(dev);
425 458 int cnt, row, chan, i;
426 mci->ue_noinfo_count = 0;
427 mci->ce_noinfo_count = 0;
428 mci->ue_mc = 0; 459 mci->ue_mc = 0;
429 mci->ce_mc = 0; 460 mci->ce_mc = 0;
461 mci->ue_noinfo_count = 0;
462 mci->ce_noinfo_count = 0;
430 463
431 for (row = 0; row < mci->nr_csrows; row++) { 464 for (row = 0; row < mci->nr_csrows; row++) {
432 struct csrow_info *ri = &mci->csrows[row]; 465 struct csrow_info *ri = &mci->csrows[row];
@@ -438,6 +471,13 @@ static ssize_t mci_reset_counters_store(struct mem_ctl_info *mci,
438 ri->channels[chan].ce_count = 0; 471 ri->channels[chan].ce_count = 0;
439 } 472 }
440 473
474 cnt = 1;
475 for (i = 0; i < mci->n_layers; i++) {
476 cnt *= mci->layers[i].size;
477 memset(mci->ce_per_layer[i], 0, cnt * sizeof(u32));
478 memset(mci->ue_per_layer[i], 0, cnt * sizeof(u32));
479 }
480
441 mci->start_time = jiffies; 481 mci->start_time = jiffies;
442 return count; 482 return count;
443} 483}
@@ -451,9 +491,11 @@ static ssize_t mci_reset_counters_store(struct mem_ctl_info *mci,
451 * Negative value still means that an error has occurred while setting 491 * Negative value still means that an error has occurred while setting
452 * the scrub rate. 492 * the scrub rate.
453 */ 493 */
454static ssize_t mci_sdram_scrub_rate_store(struct mem_ctl_info *mci, 494static ssize_t mci_sdram_scrub_rate_store(struct device *dev,
495 struct device_attribute *mattr,
455 const char *data, size_t count) 496 const char *data, size_t count)
456{ 497{
498 struct mem_ctl_info *mci = to_mci(dev);
457 unsigned long bandwidth = 0; 499 unsigned long bandwidth = 0;
458 int new_bw = 0; 500 int new_bw = 0;
459 501
@@ -476,8 +518,11 @@ static ssize_t mci_sdram_scrub_rate_store(struct mem_ctl_info *mci,
476/* 518/*
477 * ->get_sdram_scrub_rate() return value semantics same as above. 519 * ->get_sdram_scrub_rate() return value semantics same as above.
478 */ 520 */
479static ssize_t mci_sdram_scrub_rate_show(struct mem_ctl_info *mci, char *data) 521static ssize_t mci_sdram_scrub_rate_show(struct device *dev,
522 struct device_attribute *mattr,
523 char *data)
480{ 524{
525 struct mem_ctl_info *mci = to_mci(dev);
481 int bandwidth = 0; 526 int bandwidth = 0;
482 527
483 if (!mci->get_sdram_scrub_rate) 528 if (!mci->get_sdram_scrub_rate)
@@ -493,38 +538,65 @@ static ssize_t mci_sdram_scrub_rate_show(struct mem_ctl_info *mci, char *data)
493} 538}
494 539
495/* default attribute files for the MCI object */ 540/* default attribute files for the MCI object */
496static ssize_t mci_ue_count_show(struct mem_ctl_info *mci, char *data) 541static ssize_t mci_ue_count_show(struct device *dev,
542 struct device_attribute *mattr,
543 char *data)
497{ 544{
545 struct mem_ctl_info *mci = to_mci(dev);
546
498 return sprintf(data, "%d\n", mci->ue_mc); 547 return sprintf(data, "%d\n", mci->ue_mc);
499} 548}
500 549
501static ssize_t mci_ce_count_show(struct mem_ctl_info *mci, char *data) 550static ssize_t mci_ce_count_show(struct device *dev,
551 struct device_attribute *mattr,
552 char *data)
502{ 553{
554 struct mem_ctl_info *mci = to_mci(dev);
555
503 return sprintf(data, "%d\n", mci->ce_mc); 556 return sprintf(data, "%d\n", mci->ce_mc);
504} 557}
505 558
506static ssize_t mci_ce_noinfo_show(struct mem_ctl_info *mci, char *data) 559static ssize_t mci_ce_noinfo_show(struct device *dev,
560 struct device_attribute *mattr,
561 char *data)
507{ 562{
563 struct mem_ctl_info *mci = to_mci(dev);
564
508 return sprintf(data, "%d\n", mci->ce_noinfo_count); 565 return sprintf(data, "%d\n", mci->ce_noinfo_count);
509} 566}
510 567
511static ssize_t mci_ue_noinfo_show(struct mem_ctl_info *mci, char *data) 568static ssize_t mci_ue_noinfo_show(struct device *dev,
569 struct device_attribute *mattr,
570 char *data)
512{ 571{
572 struct mem_ctl_info *mci = to_mci(dev);
573
513 return sprintf(data, "%d\n", mci->ue_noinfo_count); 574 return sprintf(data, "%d\n", mci->ue_noinfo_count);
514} 575}
515 576
516static ssize_t mci_seconds_show(struct mem_ctl_info *mci, char *data) 577static ssize_t mci_seconds_show(struct device *dev,
578 struct device_attribute *mattr,
579 char *data)
517{ 580{
581 struct mem_ctl_info *mci = to_mci(dev);
582
518 return sprintf(data, "%ld\n", (jiffies - mci->start_time) / HZ); 583 return sprintf(data, "%ld\n", (jiffies - mci->start_time) / HZ);
519} 584}
520 585
521static ssize_t mci_ctl_name_show(struct mem_ctl_info *mci, char *data) 586static ssize_t mci_ctl_name_show(struct device *dev,
587 struct device_attribute *mattr,
588 char *data)
522{ 589{
590 struct mem_ctl_info *mci = to_mci(dev);
591
523 return sprintf(data, "%s\n", mci->ctl_name); 592 return sprintf(data, "%s\n", mci->ctl_name);
524} 593}
525 594
526static ssize_t mci_size_mb_show(struct mem_ctl_info *mci, char *data) 595static ssize_t mci_size_mb_show(struct device *dev,
596 struct device_attribute *mattr,
597 char *data)
527{ 598{
599 struct mem_ctl_info *mci = to_mci(dev);
528 int total_pages = 0, csrow_idx, j; 600 int total_pages = 0, csrow_idx, j;
529 601
530 for (csrow_idx = 0; csrow_idx < mci->nr_csrows; csrow_idx++) { 602 for (csrow_idx = 0; csrow_idx < mci->nr_csrows; csrow_idx++) {
@@ -540,360 +612,53 @@ static ssize_t mci_size_mb_show(struct mem_ctl_info *mci, char *data)
540 return sprintf(data, "%u\n", PAGES_TO_MiB(total_pages)); 612 return sprintf(data, "%u\n", PAGES_TO_MiB(total_pages));
541} 613}
542 614
543#define to_mci(k) container_of(k, struct mem_ctl_info, edac_mci_kobj)
544#define to_mcidev_attr(a) container_of(a,struct mcidev_sysfs_attribute,attr)
545
546/* MCI show/store functions for top most object */
547static ssize_t mcidev_show(struct kobject *kobj, struct attribute *attr,
548 char *buffer)
549{
550 struct mem_ctl_info *mem_ctl_info = to_mci(kobj);
551 struct mcidev_sysfs_attribute *mcidev_attr = to_mcidev_attr(attr);
552
553 debugf1("%s() mem_ctl_info %p\n", __func__, mem_ctl_info);
554
555 if (mcidev_attr->show)
556 return mcidev_attr->show(mem_ctl_info, buffer);
557
558 return -EIO;
559}
560
561static ssize_t mcidev_store(struct kobject *kobj, struct attribute *attr,
562 const char *buffer, size_t count)
563{
564 struct mem_ctl_info *mem_ctl_info = to_mci(kobj);
565 struct mcidev_sysfs_attribute *mcidev_attr = to_mcidev_attr(attr);
566
567 debugf1("%s() mem_ctl_info %p\n", __func__, mem_ctl_info);
568
569 if (mcidev_attr->store)
570 return mcidev_attr->store(mem_ctl_info, buffer, count);
571
572 return -EIO;
573}
574
575/* Intermediate show/store table */
576static const struct sysfs_ops mci_ops = {
577 .show = mcidev_show,
578 .store = mcidev_store
579};
580
581#define MCIDEV_ATTR(_name,_mode,_show,_store) \
582static struct mcidev_sysfs_attribute mci_attr_##_name = { \
583 .attr = {.name = __stringify(_name), .mode = _mode }, \
584 .show = _show, \
585 .store = _store, \
586};
587
588/* default Control file */ 615/* default Control file */
589MCIDEV_ATTR(reset_counters, S_IWUSR, NULL, mci_reset_counters_store); 616DEVICE_ATTR(reset_counters, S_IWUSR, NULL, mci_reset_counters_store);
590 617
591/* default Attribute files */ 618/* default Attribute files */
592MCIDEV_ATTR(mc_name, S_IRUGO, mci_ctl_name_show, NULL); 619DEVICE_ATTR(mc_name, S_IRUGO, mci_ctl_name_show, NULL);
593MCIDEV_ATTR(size_mb, S_IRUGO, mci_size_mb_show, NULL); 620DEVICE_ATTR(size_mb, S_IRUGO, mci_size_mb_show, NULL);
594MCIDEV_ATTR(seconds_since_reset, S_IRUGO, mci_seconds_show, NULL); 621DEVICE_ATTR(seconds_since_reset, S_IRUGO, mci_seconds_show, NULL);
595MCIDEV_ATTR(ue_noinfo_count, S_IRUGO, mci_ue_noinfo_show, NULL); 622DEVICE_ATTR(ue_noinfo_count, S_IRUGO, mci_ue_noinfo_show, NULL);
596MCIDEV_ATTR(ce_noinfo_count, S_IRUGO, mci_ce_noinfo_show, NULL); 623DEVICE_ATTR(ce_noinfo_count, S_IRUGO, mci_ce_noinfo_show, NULL);
597MCIDEV_ATTR(ue_count, S_IRUGO, mci_ue_count_show, NULL); 624DEVICE_ATTR(ue_count, S_IRUGO, mci_ue_count_show, NULL);
598MCIDEV_ATTR(ce_count, S_IRUGO, mci_ce_count_show, NULL); 625DEVICE_ATTR(ce_count, S_IRUGO, mci_ce_count_show, NULL);
599 626
600/* memory scrubber attribute file */ 627/* memory scrubber attribute file */
601MCIDEV_ATTR(sdram_scrub_rate, S_IRUGO | S_IWUSR, mci_sdram_scrub_rate_show, 628DEVICE_ATTR(sdram_scrub_rate, S_IRUGO | S_IWUSR, mci_sdram_scrub_rate_show,
602 mci_sdram_scrub_rate_store); 629 mci_sdram_scrub_rate_store);
603 630
604static struct mcidev_sysfs_attribute *mci_attr[] = { 631static struct attribute *mci_attrs[] = {
605 &mci_attr_reset_counters, 632 &dev_attr_reset_counters.attr,
606 &mci_attr_mc_name, 633 &dev_attr_mc_name.attr,
607 &mci_attr_size_mb, 634 &dev_attr_size_mb.attr,
608 &mci_attr_seconds_since_reset, 635 &dev_attr_seconds_since_reset.attr,
609 &mci_attr_ue_noinfo_count, 636 &dev_attr_ue_noinfo_count.attr,
610 &mci_attr_ce_noinfo_count, 637 &dev_attr_ce_noinfo_count.attr,
611 &mci_attr_ue_count, 638 &dev_attr_ue_count.attr,
612 &mci_attr_ce_count, 639 &dev_attr_ce_count.attr,
613 &mci_attr_sdram_scrub_rate, 640 &dev_attr_sdram_scrub_rate.attr,
614 NULL 641 NULL
615}; 642};
616 643
617 644static struct attribute_group mci_attr_grp = {
618/* 645 .attrs = mci_attrs,
619 * Release of a MC controlling instance
620 *
621 * each MC control instance has the following resources upon entry:
622 * a) a ref count on the top memctl kobj
623 * b) a ref count on this module
624 *
625 * this function must decrement those ref counts and then
626 * issue a free on the instance's memory
627 */
628static void edac_mci_control_release(struct kobject *kobj)
629{
630 struct mem_ctl_info *mci;
631
632 mci = to_mci(kobj);
633
634 debugf0("%s() mci instance idx=%d releasing\n", __func__, mci->mc_idx);
635
636 /* decrement the module ref count */
637 module_put(mci->owner);
638}
639
640static struct kobj_type ktype_mci = {
641 .release = edac_mci_control_release,
642 .sysfs_ops = &mci_ops,
643 .default_attrs = (struct attribute **)mci_attr,
644};
645
646/* EDAC memory controller sysfs kset:
647 * /sys/devices/system/edac/mc
648 */
649static struct kset *mc_kset;
650
651/*
652 * edac_mc_register_sysfs_main_kobj
653 *
654 * setups and registers the main kobject for each mci
655 */
656int edac_mc_register_sysfs_main_kobj(struct mem_ctl_info *mci)
657{
658 struct kobject *kobj_mci;
659 int err;
660
661 debugf1("%s()\n", __func__);
662
663 kobj_mci = &mci->edac_mci_kobj;
664
665 /* Init the mci's kobject */
666 memset(kobj_mci, 0, sizeof(*kobj_mci));
667
668 /* Record which module 'owns' this control structure
669 * and bump the ref count of the module
670 */
671 mci->owner = THIS_MODULE;
672
673 /* bump ref count on this module */
674 if (!try_module_get(mci->owner)) {
675 err = -ENODEV;
676 goto fail_out;
677 }
678
679 /* this instance become part of the mc_kset */
680 kobj_mci->kset = mc_kset;
681
682 /* register the mc<id> kobject to the mc_kset */
683 err = kobject_init_and_add(kobj_mci, &ktype_mci, NULL,
684 "mc%d", mci->mc_idx);
685 if (err) {
686 debugf1("%s()Failed to register '.../edac/mc%d'\n",
687 __func__, mci->mc_idx);
688 goto kobj_reg_fail;
689 }
690 kobject_uevent(kobj_mci, KOBJ_ADD);
691
692 /* At this point, to 'free' the control struct,
693 * edac_mc_unregister_sysfs_main_kobj() must be used
694 */
695
696 debugf1("%s() Registered '.../edac/mc%d' kobject\n",
697 __func__, mci->mc_idx);
698
699 return 0;
700
701 /* Error exit stack */
702
703kobj_reg_fail:
704 module_put(mci->owner);
705
706fail_out:
707 return err;
708}
709
710/*
711 * edac_mc_register_sysfs_main_kobj
712 *
713 * tears down and the main mci kobject from the mc_kset
714 */
715void edac_mc_unregister_sysfs_main_kobj(struct mem_ctl_info *mci)
716{
717 debugf1("%s()\n", __func__);
718
719 /* delete the kobj from the mc_kset */
720 kobject_put(&mci->edac_mci_kobj);
721}
722
723#define EDAC_DEVICE_SYMLINK "device"
724
725#define grp_to_mci(k) (container_of(k, struct mcidev_sysfs_group_kobj, kobj)->mci)
726
727/* MCI show/store functions for top most object */
728static ssize_t inst_grp_show(struct kobject *kobj, struct attribute *attr,
729 char *buffer)
730{
731 struct mem_ctl_info *mem_ctl_info = grp_to_mci(kobj);
732 struct mcidev_sysfs_attribute *mcidev_attr = to_mcidev_attr(attr);
733
734 debugf1("%s() mem_ctl_info %p\n", __func__, mem_ctl_info);
735
736 if (mcidev_attr->show)
737 return mcidev_attr->show(mem_ctl_info, buffer);
738
739 return -EIO;
740}
741
742static ssize_t inst_grp_store(struct kobject *kobj, struct attribute *attr,
743 const char *buffer, size_t count)
744{
745 struct mem_ctl_info *mem_ctl_info = grp_to_mci(kobj);
746 struct mcidev_sysfs_attribute *mcidev_attr = to_mcidev_attr(attr);
747
748 debugf1("%s() mem_ctl_info %p\n", __func__, mem_ctl_info);
749
750 if (mcidev_attr->store)
751 return mcidev_attr->store(mem_ctl_info, buffer, count);
752
753 return -EIO;
754}
755
756/* No memory to release for this kobj */
757static void edac_inst_grp_release(struct kobject *kobj)
758{
759 struct mcidev_sysfs_group_kobj *grp;
760 struct mem_ctl_info *mci;
761
762 debugf1("%s()\n", __func__);
763
764 grp = container_of(kobj, struct mcidev_sysfs_group_kobj, kobj);
765 mci = grp->mci;
766}
767
768/* Intermediate show/store table */
769static struct sysfs_ops inst_grp_ops = {
770 .show = inst_grp_show,
771 .store = inst_grp_store
772}; 646};
773 647
774/* the kobj_type instance for a instance group */ 648static const struct attribute_group *mci_attr_groups[] = {
775static struct kobj_type ktype_inst_grp = { 649 &mci_attr_grp,
776 .release = edac_inst_grp_release, 650 NULL
777 .sysfs_ops = &inst_grp_ops,
778}; 651};
779 652
780 653static void mci_attr_release(struct device *device)
781/*
782 * edac_create_mci_instance_attributes
783 * create MC driver specific attributes bellow an specified kobj
784 * This routine calls itself recursively, in order to create an entire
785 * object tree.
786 */
787static int edac_create_mci_instance_attributes(struct mem_ctl_info *mci,
788 const struct mcidev_sysfs_attribute *sysfs_attrib,
789 struct kobject *kobj)
790{ 654{
791 int err; 655 debugf1("Releasing mci device %s\n", dev_name(device));
792
793 debugf4("%s()\n", __func__);
794
795 while (sysfs_attrib) {
796 debugf4("%s() sysfs_attrib = %p\n",__func__, sysfs_attrib);
797 if (sysfs_attrib->grp) {
798 struct mcidev_sysfs_group_kobj *grp_kobj;
799
800 grp_kobj = kzalloc(sizeof(*grp_kobj), GFP_KERNEL);
801 if (!grp_kobj)
802 return -ENOMEM;
803
804 grp_kobj->grp = sysfs_attrib->grp;
805 grp_kobj->mci = mci;
806 list_add_tail(&grp_kobj->list, &mci->grp_kobj_list);
807
808 debugf0("%s() grp %s, mci %p\n", __func__,
809 sysfs_attrib->grp->name, mci);
810
811 err = kobject_init_and_add(&grp_kobj->kobj,
812 &ktype_inst_grp,
813 &mci->edac_mci_kobj,
814 sysfs_attrib->grp->name);
815 if (err < 0) {
816 printk(KERN_ERR "kobject_init_and_add failed: %d\n", err);
817 return err;
818 }
819 err = edac_create_mci_instance_attributes(mci,
820 grp_kobj->grp->mcidev_attr,
821 &grp_kobj->kobj);
822
823 if (err < 0)
824 return err;
825 } else if (sysfs_attrib->attr.name) {
826 debugf4("%s() file %s\n", __func__,
827 sysfs_attrib->attr.name);
828
829 err = sysfs_create_file(kobj, &sysfs_attrib->attr);
830 if (err < 0) {
831 printk(KERN_ERR "sysfs_create_file failed: %d\n", err);
832 return err;
833 }
834 } else
835 break;
836
837 sysfs_attrib++;
838 }
839
840 return 0;
841} 656}
842 657
843/* 658static struct device_type mci_attr_type = {
844 * edac_remove_mci_instance_attributes 659 .groups = mci_attr_groups,
845 * remove MC driver specific attributes at the topmost level 660 .release = mci_attr_release,
846 * directory of this mci instance. 661};
847 */
848static void edac_remove_mci_instance_attributes(struct mem_ctl_info *mci,
849 const struct mcidev_sysfs_attribute *sysfs_attrib,
850 struct kobject *kobj, int count)
851{
852 struct mcidev_sysfs_group_kobj *grp_kobj, *tmp;
853
854 debugf1("%s()\n", __func__);
855
856 /*
857 * loop if there are attributes and until we hit a NULL entry
858 * Remove first all the attributes
859 */
860 while (sysfs_attrib) {
861 debugf4("%s() sysfs_attrib = %p\n",__func__, sysfs_attrib);
862 if (sysfs_attrib->grp) {
863 debugf4("%s() seeking for group %s\n",
864 __func__, sysfs_attrib->grp->name);
865 list_for_each_entry(grp_kobj,
866 &mci->grp_kobj_list, list) {
867 debugf4("%s() grp_kobj->grp = %p\n",__func__, grp_kobj->grp);
868 if (grp_kobj->grp == sysfs_attrib->grp) {
869 edac_remove_mci_instance_attributes(mci,
870 grp_kobj->grp->mcidev_attr,
871 &grp_kobj->kobj, count + 1);
872 debugf4("%s() group %s\n", __func__,
873 sysfs_attrib->grp->name);
874 kobject_put(&grp_kobj->kobj);
875 }
876 }
877 debugf4("%s() end of seeking for group %s\n",
878 __func__, sysfs_attrib->grp->name);
879 } else if (sysfs_attrib->attr.name) {
880 debugf4("%s() file %s\n", __func__,
881 sysfs_attrib->attr.name);
882 sysfs_remove_file(kobj, &sysfs_attrib->attr);
883 } else
884 break;
885 sysfs_attrib++;
886 }
887
888 /* Remove the group objects */
889 if (count)
890 return;
891 list_for_each_entry_safe(grp_kobj, tmp,
892 &mci->grp_kobj_list, list) {
893 list_del(&grp_kobj->list);
894 kfree(grp_kobj);
895 }
896}
897 662
898 663
899/* 664/*
@@ -906,77 +671,80 @@ static void edac_remove_mci_instance_attributes(struct mem_ctl_info *mci,
906 */ 671 */
907int edac_create_sysfs_mci_device(struct mem_ctl_info *mci) 672int edac_create_sysfs_mci_device(struct mem_ctl_info *mci)
908{ 673{
909 int i, j; 674 int i, err;
910 int err;
911 struct csrow_info *csrow;
912 struct kobject *kobj_mci = &mci->edac_mci_kobj;
913 675
914 debugf0("%s() idx=%d\n", __func__, mci->mc_idx); 676 debugf0("%s() idx=%d\n", __func__, mci->mc_idx);
915 677
916 INIT_LIST_HEAD(&mci->grp_kobj_list); 678 /* get the /sys/devices/system/edac subsys reference */
917 679
918 /* create a symlink for the device */ 680 mci->dev.type = &mci_attr_type;
919 err = sysfs_create_link(kobj_mci, &mci->pdev->kobj, 681 device_initialize(&mci->dev);
920 EDAC_DEVICE_SYMLINK);
921 if (err) {
922 debugf1("%s() failure to create symlink\n", __func__);
923 goto fail0;
924 }
925 682
926 /* If the low level driver desires some attributes, 683 mci->dev.parent = &mci_pdev;
927 * then create them now for the driver. 684 mci->dev.bus = &mci->bus;
685 dev_set_name(&mci->dev, "mc%d", mci->mc_idx);
686 dev_set_drvdata(&mci->dev, mci);
687 pm_runtime_forbid(&mci->dev);
688
689 /*
690 * The memory controller needs its own bus, in order to avoid
691 * namespace conflicts at /sys/bus/edac.
928 */ 692 */
929 if (mci->mc_driver_sysfs_attributes) { 693 debugf0("creating bus %s\n",mci->bus.name);
930 err = edac_create_mci_instance_attributes(mci, 694 mci->bus.name = kstrdup(dev_name(&mci->dev), GFP_KERNEL);
931 mci->mc_driver_sysfs_attributes, 695 err = bus_register(&mci->bus);
932 &mci->edac_mci_kobj); 696 if (err < 0)
933 if (err) { 697 return err;
934 debugf1("%s() failure to create mci attributes\n", 698
935 __func__); 699 debugf0("%s(): creating device %s\n", __func__,
936 goto fail0; 700 dev_name(&mci->dev));
937 } 701 err = device_add(&mci->dev);
702 if (err < 0) {
703 bus_unregister(&mci->bus);
704 kfree(mci->bus.name);
705 return err;
938 } 706 }
939 707
940 /* Make directories for each CSROW object under the mc<id> kobject 708 /*
709 * Create the dimm/rank devices
941 */ 710 */
942 for (i = 0; i < mci->nr_csrows; i++) { 711 for (i = 0; i < mci->tot_dimms; i++) {
943 int nr_pages = 0; 712 struct dimm_info *dimm = &mci->dimms[i];
944 713 /* Only expose populated DIMMs */
945 csrow = &mci->csrows[i]; 714 if (dimm->nr_pages == 0)
946 for (j = 0; j < csrow->nr_channels; j++) 715 continue;
947 nr_pages += csrow->channels[j].dimm->nr_pages; 716#ifdef CONFIG_EDAC_DEBUG
948 717 debugf1("%s creating dimm%d, located at ",
949 if (nr_pages > 0) { 718 __func__, i);
950 err = edac_create_csrow_object(mci, csrow, i); 719 if (edac_debug_level >= 1) {
951 if (err) { 720 int lay;
952 debugf1("%s() failure: create csrow %d obj\n", 721 for (lay = 0; lay < mci->n_layers; lay++)
953 __func__, i); 722 printk(KERN_CONT "%s %d ",
954 goto fail1; 723 edac_layer_name[mci->layers[lay].type],
955 } 724 dimm->location[lay]);
725 printk(KERN_CONT "\n");
956 } 726 }
727#endif
957 } 728 }
958 729
730 err = edac_create_csrow_objects(mci);
731 if (err < 0)
732 goto fail;
733
959 return 0; 734 return 0;
960 735
961fail1: 736fail:
962 for (i--; i >= 0; i--) { 737 for (i--; i >= 0; i--) {
963 int nr_pages = 0; 738 struct dimm_info *dimm = &mci->dimms[i];
964 739 if (dimm->nr_pages == 0)
965 csrow = &mci->csrows[i]; 740 continue;
966 for (j = 0; j < csrow->nr_channels; j++) 741 put_device(&dimm->dev);
967 nr_pages += csrow->channels[j].dimm->nr_pages; 742 device_del(&dimm->dev);
968 if (nr_pages > 0)
969 kobject_put(&mci->csrows[i].kobj);
970 } 743 }
971 744 put_device(&mci->dev);
972 /* remove the mci instance's attributes, if any */ 745 device_del(&mci->dev);
973 edac_remove_mci_instance_attributes(mci, 746 bus_unregister(&mci->bus);
974 mci->mc_driver_sysfs_attributes, &mci->edac_mci_kobj, 0); 747 kfree(mci->bus.name);
975
976 /* remove the symlink */
977 sysfs_remove_link(kobj_mci, EDAC_DEVICE_SYMLINK);
978
979fail0:
980 return err; 748 return err;
981} 749}
982 750
@@ -985,98 +753,70 @@ fail0:
985 */ 753 */
986void edac_remove_sysfs_mci_device(struct mem_ctl_info *mci) 754void edac_remove_sysfs_mci_device(struct mem_ctl_info *mci)
987{ 755{
988 struct csrow_info *csrow; 756 int i;
989 int i, j;
990 757
991 debugf0("%s()\n", __func__); 758 debugf0("%s()\n", __func__);
992 759
993 /* remove all csrow kobjects */ 760 edac_delete_csrow_objects(mci);
994 debugf4("%s() unregister this mci kobj\n", __func__);
995 for (i = 0; i < mci->nr_csrows; i++) {
996 int nr_pages = 0;
997
998 csrow = &mci->csrows[i];
999 for (j = 0; j < csrow->nr_channels; j++)
1000 nr_pages += csrow->channels[j].dimm->nr_pages;
1001 if (nr_pages > 0) {
1002 debugf0("%s() unreg csrow-%d\n", __func__, i);
1003 kobject_put(&mci->csrows[i].kobj);
1004 }
1005 }
1006 761
1007 /* remove this mci instance's attribtes */ 762 for (i = 0; i < mci->tot_dimms; i++) {
1008 if (mci->mc_driver_sysfs_attributes) { 763 struct dimm_info *dimm = &mci->dimms[i];
1009 debugf4("%s() unregister mci private attributes\n", __func__); 764 if (dimm->nr_pages == 0)
1010 edac_remove_mci_instance_attributes(mci, 765 continue;
1011 mci->mc_driver_sysfs_attributes, 766 debugf0("%s(): removing device %s\n", __func__,
1012 &mci->edac_mci_kobj, 0); 767 dev_name(&dimm->dev));
768 put_device(&dimm->dev);
769 device_del(&dimm->dev);
1013 } 770 }
1014
1015 /* remove the symlink */
1016 debugf4("%s() remove_link\n", __func__);
1017 sysfs_remove_link(&mci->edac_mci_kobj, EDAC_DEVICE_SYMLINK);
1018
1019 /* unregister this instance's kobject */
1020 debugf4("%s() remove_mci_instance\n", __func__);
1021 kobject_put(&mci->edac_mci_kobj);
1022} 771}
1023 772
773void edac_unregister_sysfs(struct mem_ctl_info *mci)
774{
775 debugf1("Unregistering device %s\n", dev_name(&mci->dev));
776 put_device(&mci->dev);
777 device_del(&mci->dev);
778 bus_unregister(&mci->bus);
779 kfree(mci->bus.name);
780}
1024 781
782static void mc_attr_release(struct device *device)
783{
784 debugf1("Releasing device %s\n", dev_name(device));
785}
1025 786
1026 787static struct device_type mc_attr_type = {
788 .release = mc_attr_release,
789};
1027/* 790/*
1028 * edac_setup_sysfs_mc_kset(void) 791 * Init/exit code for the module. Basically, creates/removes /sys/class/rc
1029 *
1030 * Initialize the mc_kset for the 'mc' entry
1031 * This requires creating the top 'mc' directory with a kset
1032 * and its controls/attributes.
1033 *
1034 * To this 'mc' kset, instance 'mci' will be grouped as children.
1035 *
1036 * Return: 0 SUCCESS
1037 * !0 FAILURE error code
1038 */ 792 */
1039int edac_sysfs_setup_mc_kset(void) 793int __init edac_mc_sysfs_init(void)
1040{ 794{
1041 int err = -EINVAL;
1042 struct bus_type *edac_subsys; 795 struct bus_type *edac_subsys;
1043 796 int err;
1044 debugf1("%s()\n", __func__);
1045 797
1046 /* get the /sys/devices/system/edac subsys reference */ 798 /* get the /sys/devices/system/edac subsys reference */
1047 edac_subsys = edac_get_sysfs_subsys(); 799 edac_subsys = edac_get_sysfs_subsys();
1048 if (edac_subsys == NULL) { 800 if (edac_subsys == NULL) {
1049 debugf1("%s() no edac_subsys error=%d\n", __func__, err); 801 debugf1("%s() no edac_subsys\n", __func__);
1050 goto fail_out; 802 return -EINVAL;
1051 } 803 }
1052 804
1053 /* Init the MC's kobject */ 805 mci_pdev.bus = edac_subsys;
1054 mc_kset = kset_create_and_add("mc", NULL, &edac_subsys->dev_root->kobj); 806 mci_pdev.type = &mc_attr_type;
1055 if (!mc_kset) { 807 device_initialize(&mci_pdev);
1056 err = -ENOMEM; 808 dev_set_name(&mci_pdev, "mc");
1057 debugf1("%s() Failed to register '.../edac/mc'\n", __func__);
1058 goto fail_kset;
1059 }
1060 809
1061 debugf1("%s() Registered '.../edac/mc' kobject\n", __func__); 810 err = device_add(&mci_pdev);
811 if (err < 0)
812 return err;
1062 813
1063 return 0; 814 return 0;
1064
1065fail_kset:
1066 edac_put_sysfs_subsys();
1067
1068fail_out:
1069 return err;
1070} 815}
1071 816
1072/* 817void __exit edac_mc_sysfs_exit(void)
1073 * edac_sysfs_teardown_mc_kset
1074 *
1075 * deconstruct the mc_ket for memory controllers
1076 */
1077void edac_sysfs_teardown_mc_kset(void)
1078{ 818{
1079 kset_unregister(mc_kset); 819 put_device(&mci_pdev);
820 device_del(&mci_pdev);
1080 edac_put_sysfs_subsys(); 821 edac_put_sysfs_subsys();
1081} 822}
1082
diff --git a/drivers/edac/edac_module.c b/drivers/edac/edac_module.c
index 5ddaa86d6a6e..8735a0d3ed0c 100644
--- a/drivers/edac/edac_module.c
+++ b/drivers/edac/edac_module.c
@@ -90,10 +90,7 @@ static int __init edac_init(void)
90 */ 90 */
91 edac_pci_clear_parity_errors(); 91 edac_pci_clear_parity_errors();
92 92
93 /* 93 err = edac_mc_sysfs_init();
94 * now set up the mc_kset under the edac class object
95 */
96 err = edac_sysfs_setup_mc_kset();
97 if (err) 94 if (err)
98 goto error; 95 goto error;
99 96
@@ -101,15 +98,11 @@ static int __init edac_init(void)
101 err = edac_workqueue_setup(); 98 err = edac_workqueue_setup();
102 if (err) { 99 if (err) {
103 edac_printk(KERN_ERR, EDAC_MC, "init WorkQueue failure\n"); 100 edac_printk(KERN_ERR, EDAC_MC, "init WorkQueue failure\n");
104 goto workq_fail; 101 goto error;
105 } 102 }
106 103
107 return 0; 104 return 0;
108 105
109 /* Error teardown stack */
110workq_fail:
111 edac_sysfs_teardown_mc_kset();
112
113error: 106error:
114 return err; 107 return err;
115} 108}
@@ -124,7 +117,7 @@ static void __exit edac_exit(void)
124 117
125 /* tear down the various subsystems */ 118 /* tear down the various subsystems */
126 edac_workqueue_teardown(); 119 edac_workqueue_teardown();
127 edac_sysfs_teardown_mc_kset(); 120 edac_mc_sysfs_exit();
128} 121}
129 122
130/* 123/*
diff --git a/drivers/edac/edac_module.h b/drivers/edac/edac_module.h
index 0ea7d14cb930..1af13676e857 100644
--- a/drivers/edac/edac_module.h
+++ b/drivers/edac/edac_module.h
@@ -19,12 +19,12 @@
19 * 19 *
20 * edac_mc objects 20 * edac_mc objects
21 */ 21 */
22extern int edac_sysfs_setup_mc_kset(void); 22 /* on edac_mc_sysfs.c */
23extern void edac_sysfs_teardown_mc_kset(void); 23int edac_mc_sysfs_init(void);
24extern int edac_mc_register_sysfs_main_kobj(struct mem_ctl_info *mci); 24void edac_mc_sysfs_exit(void);
25extern void edac_mc_unregister_sysfs_main_kobj(struct mem_ctl_info *mci);
26extern int edac_create_sysfs_mci_device(struct mem_ctl_info *mci); 25extern int edac_create_sysfs_mci_device(struct mem_ctl_info *mci);
27extern void edac_remove_sysfs_mci_device(struct mem_ctl_info *mci); 26extern void edac_remove_sysfs_mci_device(struct mem_ctl_info *mci);
27void edac_unregister_sysfs(struct mem_ctl_info *mci);
28extern int edac_get_log_ue(void); 28extern int edac_get_log_ue(void);
29extern int edac_get_log_ce(void); 29extern int edac_get_log_ce(void);
30extern int edac_get_panic_on_ue(void); 30extern int edac_get_panic_on_ue(void);
@@ -34,6 +34,7 @@ extern int edac_mc_get_panic_on_ue(void);
34extern int edac_get_poll_msec(void); 34extern int edac_get_poll_msec(void);
35extern int edac_mc_get_poll_msec(void); 35extern int edac_mc_get_poll_msec(void);
36 36
37 /* on edac_device.c */
37extern int edac_device_register_sysfs_main_kobj( 38extern int edac_device_register_sysfs_main_kobj(
38 struct edac_device_ctl_info *edac_dev); 39 struct edac_device_ctl_info *edac_dev);
39extern void edac_device_unregister_sysfs_main_kobj( 40extern void edac_device_unregister_sysfs_main_kobj(
diff --git a/include/linux/edac.h b/include/linux/edac.h
index 4e32e8d31e0a..a2b0b6fc002c 100644
--- a/include/linux/edac.h
+++ b/include/linux/edac.h
@@ -13,6 +13,7 @@
13#define _LINUX_EDAC_H_ 13#define _LINUX_EDAC_H_
14 14
15#include <linux/atomic.h> 15#include <linux/atomic.h>
16#include <linux/device.h>
16#include <linux/kobject.h> 17#include <linux/kobject.h>
17#include <linux/completion.h> 18#include <linux/completion.h>
18#include <linux/workqueue.h> 19#include <linux/workqueue.h>
@@ -448,14 +449,15 @@ struct edac_mc_layer {
448 __p; \ 449 __p; \
449}) 450})
450 451
451
452/* FIXME: add the proper per-location error counts */
453struct dimm_info { 452struct dimm_info {
453 struct device dev;
454
454 char label[EDAC_MC_LABEL_LEN + 1]; /* DIMM label on motherboard */ 455 char label[EDAC_MC_LABEL_LEN + 1]; /* DIMM label on motherboard */
455 456
456 /* Memory location data */ 457 /* Memory location data */
457 unsigned location[EDAC_MAX_LAYERS]; 458 unsigned location[EDAC_MAX_LAYERS];
458 459
460 struct kobject kobj; /* sysfs kobject for this csrow */
459 struct mem_ctl_info *mci; /* the parent */ 461 struct mem_ctl_info *mci; /* the parent */
460 462
461 u32 grain; /* granularity of reported error in bytes */ 463 u32 grain; /* granularity of reported error in bytes */
@@ -484,6 +486,8 @@ struct dimm_info {
484 * patches in this series will fix this issue. 486 * patches in this series will fix this issue.
485 */ 487 */
486struct rank_info { 488struct rank_info {
489 struct device dev;
490
487 int chan_idx; 491 int chan_idx;
488 struct csrow_info *csrow; 492 struct csrow_info *csrow;
489 struct dimm_info *dimm; 493 struct dimm_info *dimm;
@@ -492,6 +496,8 @@ struct rank_info {
492}; 496};
493 497
494struct csrow_info { 498struct csrow_info {
499 struct device dev;
500
495 /* Used only by edac_mc_find_csrow_by_page() */ 501 /* Used only by edac_mc_find_csrow_by_page() */
496 unsigned long first_page; /* first page number in csrow */ 502 unsigned long first_page; /* first page number in csrow */
497 unsigned long last_page; /* last page number in csrow */ 503 unsigned long last_page; /* last page number in csrow */
@@ -517,15 +523,6 @@ struct mcidev_sysfs_group {
517 const struct mcidev_sysfs_attribute *mcidev_attr; /* group attributes */ 523 const struct mcidev_sysfs_attribute *mcidev_attr; /* group attributes */
518}; 524};
519 525
520struct mcidev_sysfs_group_kobj {
521 struct list_head list; /* list for all instances within a mc */
522
523 struct kobject kobj; /* kobj for the group */
524
525 const struct mcidev_sysfs_group *grp; /* group description table */
526 struct mem_ctl_info *mci; /* the parent */
527};
528
529/* mcidev_sysfs_attribute structure 526/* mcidev_sysfs_attribute structure
530 * used for driver sysfs attributes and in mem_ctl_info 527 * used for driver sysfs attributes and in mem_ctl_info
531 * sysfs top level entries 528 * sysfs top level entries
@@ -536,13 +533,27 @@ struct mcidev_sysfs_attribute {
536 const struct mcidev_sysfs_group *grp; /* Points to a group of attributes */ 533 const struct mcidev_sysfs_group *grp; /* Points to a group of attributes */
537 534
538 /* Ops for show/store values at the attribute - not used on group */ 535 /* Ops for show/store values at the attribute - not used on group */
539 ssize_t (*show)(struct mem_ctl_info *,char *); 536 ssize_t (*show)(struct mem_ctl_info *, char *);
540 ssize_t (*store)(struct mem_ctl_info *, const char *,size_t); 537 ssize_t (*store)(struct mem_ctl_info *, const char *, size_t);
538
539 void *priv;
540};
541
542/*
543 * struct errcount_attribute - used to store the several error counts
544 */
545struct errcount_attribute_data {
546 int n_layers;
547 int pos[EDAC_MAX_LAYERS];
548 int layer0, layer1, layer2;
541}; 549};
542 550
543/* MEMORY controller information structure 551/* MEMORY controller information structure
544 */ 552 */
545struct mem_ctl_info { 553struct mem_ctl_info {
554 struct device dev;
555 struct bus_type bus;
556
546 struct list_head link; /* for global list of mem_ctl_info structs */ 557 struct list_head link; /* for global list of mem_ctl_info structs */
547 558
548 struct module *owner; /* Module owner of this control struct */ 559 struct module *owner; /* Module owner of this control struct */
@@ -587,7 +598,15 @@ struct mem_ctl_info {
587 struct csrow_info *csrows; 598 struct csrow_info *csrows;
588 unsigned nr_csrows, num_cschannel; 599 unsigned nr_csrows, num_cschannel;
589 600
590 /* Memory Controller hierarchy */ 601 /*
602 * Memory Controller hierarchy
603 *
604 * There are basically two types of memory controller: the ones that
605 * sees memory sticks ("dimms"), and the ones that sees memory ranks.
606 * All old memory controllers enumerate memories per rank, but most
607 * of the recent drivers enumerate memories per DIMM, instead.
608 * When the memory controller is per rank, mem_is_per_rank is true.
609 */
591 unsigned n_layers; 610 unsigned n_layers;
592 struct edac_mc_layer *layers; 611 struct edac_mc_layer *layers;
593 bool mem_is_per_rank; 612 bool mem_is_per_rank;