Blame view

drivers/edac/edac_pci_sysfs.c 18.9 KB
20bcb7a81   Douglas Thompson   drivers/edac: mod...
1
  /*
7c9281d76   Douglas Thompson   drivers/edac: spl...
2
3
4
5
6
7
8
9
   * (C) 2005, 2006 Linux Networx (http://lnxi.com)
   * This file may be distributed under the terms of the
   * GNU General Public License.
   *
   * Written Doug Thompson <norsk5@xmission.com>
   *
   */
  #include <linux/module.h>
30e1f7a81   Borislav Petkov   EDAC: Export edac...
10
  #include <linux/edac.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
11
  #include <linux/slab.h>
7c9281d76   Douglas Thompson   drivers/edac: spl...
12
  #include <linux/ctype.h>
0b892c717   Mauro Carvalho Chehab   edac: move EDAC P...
13
  #include "edac_pci.h"
7c9281d76   Douglas Thompson   drivers/edac: spl...
14
  #include "edac_module.h"
91b99041c   Dave Jiang   drivers/edac: upd...
15
  #define EDAC_PCI_SYMLINK	"device"
d4c1465b7   Doug Thompson   drivers/edac: fix...
16
17
18
19
  /* data variables exported via sysfs */
  static int check_pci_errors;		/* default NO check PCI parity */
  static int edac_pci_panic_on_pe;	/* default NO panic on PCI Parity */
  static int edac_pci_log_pe = 1;		/* log PCI parity errors */
4de78c687   Dave Jiang   drivers/edac: mod...
20
  static int edac_pci_log_npe = 1;	/* log PCI non-parity error errors */
d4c1465b7   Doug Thompson   drivers/edac: fix...
21
  static int edac_pci_poll_msec = 1000;	/* one second workq period */
7c9281d76   Douglas Thompson   drivers/edac: spl...
22
  static atomic_t pci_parity_count = ATOMIC_INIT(0);
91b99041c   Dave Jiang   drivers/edac: upd...
23
  static atomic_t pci_nonparity_count = ATOMIC_INIT(0);
7c9281d76   Douglas Thompson   drivers/edac: spl...
24

14cc571bb   Arthur Jones   edac: core fix to...
25
  static struct kobject *edac_pci_top_main_kobj;
91b99041c   Dave Jiang   drivers/edac: upd...
26
  static atomic_t edac_pci_sysfs_refcount = ATOMIC_INIT(0);
d4c1465b7   Doug Thompson   drivers/edac: fix...
27
  /* getter functions for the data variables */
4de78c687   Dave Jiang   drivers/edac: mod...
28
29
30
31
  int edac_pci_get_check_errors(void)
  {
  	return check_pci_errors;
  }
1a45027d1   Adrian Bunk   edac: remove unne...
32
  static int edac_pci_get_log_pe(void)
4de78c687   Dave Jiang   drivers/edac: mod...
33
34
35
  {
  	return edac_pci_log_pe;
  }
1a45027d1   Adrian Bunk   edac: remove unne...
36
  static int edac_pci_get_log_npe(void)
4de78c687   Dave Jiang   drivers/edac: mod...
37
38
39
  {
  	return edac_pci_log_npe;
  }
1a45027d1   Adrian Bunk   edac: remove unne...
40
  static int edac_pci_get_panic_on_pe(void)
4de78c687   Dave Jiang   drivers/edac: mod...
41
42
43
44
45
46
47
48
  {
  	return edac_pci_panic_on_pe;
  }
  
  int edac_pci_get_poll_msec(void)
  {
  	return edac_pci_poll_msec;
  }
91b99041c   Dave Jiang   drivers/edac: upd...
49
50
51
  /**************************** EDAC PCI sysfs instance *******************/
  static ssize_t instance_pe_count_show(struct edac_pci_ctl_info *pci, char *data)
  {
079708b91   Douglas Thompson   drivers/edac: cor...
52
53
  	return sprintf(data, "%u
  ", atomic_read(&pci->counters.pe_count));
91b99041c   Dave Jiang   drivers/edac: upd...
54
55
56
  }
  
  static ssize_t instance_npe_count_show(struct edac_pci_ctl_info *pci,
052dfb45c   Douglas Thompson   drivers/edac: cle...
57
  				char *data)
91b99041c   Dave Jiang   drivers/edac: upd...
58
  {
079708b91   Douglas Thompson   drivers/edac: cor...
59
60
  	return sprintf(data, "%u
  ", atomic_read(&pci->counters.npe_count));
91b99041c   Dave Jiang   drivers/edac: upd...
61
62
63
64
65
66
67
68
69
  }
  
  #define to_instance(k) container_of(k, struct edac_pci_ctl_info, kobj)
  #define to_instance_attr(a) container_of(a, struct instance_attribute, attr)
  
  /* DEVICE instance kobject release() function */
  static void edac_pci_instance_release(struct kobject *kobj)
  {
  	struct edac_pci_ctl_info *pci;
956b9ba15   Joe Perches   edac: Convert deb...
70
71
  	edac_dbg(0, "
  ");
91b99041c   Dave Jiang   drivers/edac: upd...
72

d4c1465b7   Doug Thompson   drivers/edac: fix...
73
  	/* Form pointer to containing struct, the pci control struct */
91b99041c   Dave Jiang   drivers/edac: upd...
74
  	pci = to_instance(kobj);
d4c1465b7   Doug Thompson   drivers/edac: fix...
75
76
  
  	/* decrement reference count on top main kobj */
14cc571bb   Arthur Jones   edac: core fix to...
77
  	kobject_put(edac_pci_top_main_kobj);
d4c1465b7   Doug Thompson   drivers/edac: fix...
78
79
  
  	kfree(pci);	/* Free the control struct */
91b99041c   Dave Jiang   drivers/edac: upd...
80
81
82
83
  }
  
  /* instance specific attribute structure */
  struct instance_attribute {
079708b91   Douglas Thompson   drivers/edac: cor...
84
  	struct attribute attr;
d4c1465b7   Doug Thompson   drivers/edac: fix...
85
86
  	ssize_t(*show) (struct edac_pci_ctl_info *, char *);
  	ssize_t(*store) (struct edac_pci_ctl_info *, const char *, size_t);
91b99041c   Dave Jiang   drivers/edac: upd...
87
88
89
90
  };
  
  /* Function to 'show' fields from the edac_pci 'instance' structure */
  static ssize_t edac_pci_instance_show(struct kobject *kobj,
052dfb45c   Douglas Thompson   drivers/edac: cle...
91
  				struct attribute *attr, char *buffer)
91b99041c   Dave Jiang   drivers/edac: upd...
92
  {
079708b91   Douglas Thompson   drivers/edac: cor...
93
94
  	struct edac_pci_ctl_info *pci = to_instance(kobj);
  	struct instance_attribute *instance_attr = to_instance_attr(attr);
91b99041c   Dave Jiang   drivers/edac: upd...
95

079708b91   Douglas Thompson   drivers/edac: cor...
96
97
98
  	if (instance_attr->show)
  		return instance_attr->show(pci, buffer);
  	return -EIO;
91b99041c   Dave Jiang   drivers/edac: upd...
99
  }
91b99041c   Dave Jiang   drivers/edac: upd...
100
101
  /* Function to 'store' fields into the edac_pci 'instance' structure */
  static ssize_t edac_pci_instance_store(struct kobject *kobj,
052dfb45c   Douglas Thompson   drivers/edac: cle...
102
103
  				struct attribute *attr,
  				const char *buffer, size_t count)
91b99041c   Dave Jiang   drivers/edac: upd...
104
  {
079708b91   Douglas Thompson   drivers/edac: cor...
105
106
  	struct edac_pci_ctl_info *pci = to_instance(kobj);
  	struct instance_attribute *instance_attr = to_instance_attr(attr);
91b99041c   Dave Jiang   drivers/edac: upd...
107

079708b91   Douglas Thompson   drivers/edac: cor...
108
109
110
  	if (instance_attr->store)
  		return instance_attr->store(pci, buffer, count);
  	return -EIO;
91b99041c   Dave Jiang   drivers/edac: upd...
111
  }
d4c1465b7   Doug Thompson   drivers/edac: fix...
112
  /* fs_ops table */
52cf25d0a   Emese Revfy   Driver core: Cons...
113
  static const struct sysfs_ops pci_instance_ops = {
91b99041c   Dave Jiang   drivers/edac: upd...
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
  	.show = edac_pci_instance_show,
  	.store = edac_pci_instance_store
  };
  
  #define INSTANCE_ATTR(_name, _mode, _show, _store)	\
  static struct instance_attribute attr_instance_##_name = {	\
  	.attr	= {.name = __stringify(_name), .mode = _mode },	\
  	.show	= _show,					\
  	.store	= _store,					\
  };
  
  INSTANCE_ATTR(pe_count, S_IRUGO, instance_pe_count_show, NULL);
  INSTANCE_ATTR(npe_count, S_IRUGO, instance_npe_count_show, NULL);
  
  /* pci instance attributes */
  static struct instance_attribute *pci_instance_attr[] = {
  	&attr_instance_pe_count,
  	&attr_instance_npe_count,
  	NULL
  };
7c9281d76   Douglas Thompson   drivers/edac: spl...
134

d4c1465b7   Doug Thompson   drivers/edac: fix...
135
  /* the ktype for a pci instance */
91b99041c   Dave Jiang   drivers/edac: upd...
136
137
138
139
140
  static struct kobj_type ktype_pci_instance = {
  	.release = edac_pci_instance_release,
  	.sysfs_ops = &pci_instance_ops,
  	.default_attrs = (struct attribute **)pci_instance_attr,
  };
d4c1465b7   Doug Thompson   drivers/edac: fix...
141
142
143
144
145
  /*
   * edac_pci_create_instance_kobj
   *
   *	construct one EDAC PCI instance's kobject for use
   */
91b99041c   Dave Jiang   drivers/edac: upd...
146
147
  static int edac_pci_create_instance_kobj(struct edac_pci_ctl_info *pci, int idx)
  {
d4c1465b7   Doug Thompson   drivers/edac: fix...
148
  	struct kobject *main_kobj;
91b99041c   Dave Jiang   drivers/edac: upd...
149
  	int err;
956b9ba15   Joe Perches   edac: Convert deb...
150
151
  	edac_dbg(0, "
  ");
d4c1465b7   Doug Thompson   drivers/edac: fix...
152

d4c1465b7   Doug Thompson   drivers/edac: fix...
153
154
155
156
  	/* First bump the ref count on the top main kobj, which will
  	 * track the number of PCI instances we have, and thus nest
  	 * properly on keeping the module loaded
  	 */
14cc571bb   Arthur Jones   edac: core fix to...
157
  	main_kobj = kobject_get(edac_pci_top_main_kobj);
d4c1465b7   Doug Thompson   drivers/edac: fix...
158
159
160
161
162
163
  	if (!main_kobj) {
  		err = -ENODEV;
  		goto error_out;
  	}
  
  	/* And now register this new kobject under the main kobj */
b2ed215a3   Greg Kroah-Hartman   Kobject: change d...
164
  	err = kobject_init_and_add(&pci->kobj, &ktype_pci_instance,
14cc571bb   Arthur Jones   edac: core fix to...
165
  				   edac_pci_top_main_kobj, "pci%d", idx);
91b99041c   Dave Jiang   drivers/edac: upd...
166
  	if (err != 0) {
956b9ba15   Joe Perches   edac: Convert deb...
167
168
  		edac_dbg(2, "failed to register instance pci%d
  ", idx);
14cc571bb   Arthur Jones   edac: core fix to...
169
  		kobject_put(edac_pci_top_main_kobj);
d4c1465b7   Doug Thompson   drivers/edac: fix...
170
  		goto error_out;
91b99041c   Dave Jiang   drivers/edac: upd...
171
  	}
b2ed215a3   Greg Kroah-Hartman   Kobject: change d...
172
  	kobject_uevent(&pci->kobj, KOBJ_ADD);
956b9ba15   Joe Perches   edac: Convert deb...
173
174
  	edac_dbg(1, "Register instance 'pci%d' kobject
  ", idx);
91b99041c   Dave Jiang   drivers/edac: upd...
175
176
  
  	return 0;
d4c1465b7   Doug Thompson   drivers/edac: fix...
177
178
179
180
  
  	/* Error unwind statck */
  error_out:
  	return err;
91b99041c   Dave Jiang   drivers/edac: upd...
181
  }
d4c1465b7   Doug Thompson   drivers/edac: fix...
182
183
184
185
186
  /*
   * edac_pci_unregister_sysfs_instance_kobj
   *
   *	unregister the kobj for the EDAC PCI instance
   */
1a45027d1   Adrian Bunk   edac: remove unne...
187
188
  static void edac_pci_unregister_sysfs_instance_kobj(
  			struct edac_pci_ctl_info *pci)
91b99041c   Dave Jiang   drivers/edac: upd...
189
  {
956b9ba15   Joe Perches   edac: Convert deb...
190
191
  	edac_dbg(0, "
  ");
d4c1465b7   Doug Thompson   drivers/edac: fix...
192
193
194
195
196
  
  	/* Unregister the instance kobject and allow its release
  	 * function release the main reference count and then
  	 * kfree the memory
  	 */
c10997f65   Greg Kroah-Hartman   Kobject: convert ...
197
  	kobject_put(&pci->kobj);
91b99041c   Dave Jiang   drivers/edac: upd...
198
199
200
201
202
  }
  
  /***************************** EDAC PCI sysfs root **********************/
  #define to_edacpci(k) container_of(k, struct edac_pci_ctl_info, kobj)
  #define to_edacpci_attr(a) container_of(a, struct edac_pci_attr, attr)
7c9281d76   Douglas Thompson   drivers/edac: spl...
203

d4c1465b7   Doug Thompson   drivers/edac: fix...
204
  /* simple show/store functions for attributes */
7c9281d76   Douglas Thompson   drivers/edac: spl...
205
206
207
  static ssize_t edac_pci_int_show(void *ptr, char *buffer)
  {
  	int *value = ptr;
079708b91   Douglas Thompson   drivers/edac: cor...
208
209
  	return sprintf(buffer, "%d
  ", *value);
7c9281d76   Douglas Thompson   drivers/edac: spl...
210
211
212
213
214
215
216
  }
  
  static ssize_t edac_pci_int_store(void *ptr, const char *buffer, size_t count)
  {
  	int *value = ptr;
  
  	if (isdigit(*buffer))
079708b91   Douglas Thompson   drivers/edac: cor...
217
  		*value = simple_strtoul(buffer, NULL, 0);
7c9281d76   Douglas Thompson   drivers/edac: spl...
218
219
220
221
222
223
224
  
  	return count;
  }
  
  struct edac_pci_dev_attribute {
  	struct attribute attr;
  	void *value;
079708b91   Douglas Thompson   drivers/edac: cor...
225
226
  	 ssize_t(*show) (void *, char *);
  	 ssize_t(*store) (void *, const char *, size_t);
7c9281d76   Douglas Thompson   drivers/edac: spl...
227
228
229
230
  };
  
  /* Set of show/store abstract level functions for PCI Parity object */
  static ssize_t edac_pci_dev_show(struct kobject *kobj, struct attribute *attr,
079708b91   Douglas Thompson   drivers/edac: cor...
231
  				 char *buffer)
7c9281d76   Douglas Thompson   drivers/edac: spl...
232
233
  {
  	struct edac_pci_dev_attribute *edac_pci_dev;
079708b91   Douglas Thompson   drivers/edac: cor...
234
  	edac_pci_dev = (struct edac_pci_dev_attribute *)attr;
7c9281d76   Douglas Thompson   drivers/edac: spl...
235
236
237
238
239
240
241
  
  	if (edac_pci_dev->show)
  		return edac_pci_dev->show(edac_pci_dev->value, buffer);
  	return -EIO;
  }
  
  static ssize_t edac_pci_dev_store(struct kobject *kobj,
052dfb45c   Douglas Thompson   drivers/edac: cle...
242
243
  				struct attribute *attr, const char *buffer,
  				size_t count)
7c9281d76   Douglas Thompson   drivers/edac: spl...
244
245
  {
  	struct edac_pci_dev_attribute *edac_pci_dev;
079708b91   Douglas Thompson   drivers/edac: cor...
246
  	edac_pci_dev = (struct edac_pci_dev_attribute *)attr;
7c9281d76   Douglas Thompson   drivers/edac: spl...
247

8024c4c0b   Dan Carpenter   EDAC: Test correc...
248
  	if (edac_pci_dev->store)
7c9281d76   Douglas Thompson   drivers/edac: spl...
249
250
251
  		return edac_pci_dev->store(edac_pci_dev->value, buffer, count);
  	return -EIO;
  }
52cf25d0a   Emese Revfy   Driver core: Cons...
252
  static const struct sysfs_ops edac_pci_sysfs_ops = {
079708b91   Douglas Thompson   drivers/edac: cor...
253
254
  	.show = edac_pci_dev_show,
  	.store = edac_pci_dev_store
7c9281d76   Douglas Thompson   drivers/edac: spl...
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
  };
  
  #define EDAC_PCI_ATTR(_name,_mode,_show,_store)			\
  static struct edac_pci_dev_attribute edac_pci_attr_##_name = {		\
  	.attr = {.name = __stringify(_name), .mode = _mode },	\
  	.value  = &_name,					\
  	.show   = _show,					\
  	.store  = _store,					\
  };
  
  #define EDAC_PCI_STRING_ATTR(_name,_data,_mode,_show,_store)	\
  static struct edac_pci_dev_attribute edac_pci_attr_##_name = {		\
  	.attr = {.name = __stringify(_name), .mode = _mode },	\
  	.value  = _data,					\
  	.show   = _show,					\
  	.store  = _store,					\
  };
  
  /* PCI Parity control files */
079708b91   Douglas Thompson   drivers/edac: cor...
274
  EDAC_PCI_ATTR(check_pci_errors, S_IRUGO | S_IWUSR, edac_pci_int_show,
052dfb45c   Douglas Thompson   drivers/edac: cle...
275
  	edac_pci_int_store);
079708b91   Douglas Thompson   drivers/edac: cor...
276
  EDAC_PCI_ATTR(edac_pci_log_pe, S_IRUGO | S_IWUSR, edac_pci_int_show,
052dfb45c   Douglas Thompson   drivers/edac: cle...
277
  	edac_pci_int_store);
079708b91   Douglas Thompson   drivers/edac: cor...
278
  EDAC_PCI_ATTR(edac_pci_log_npe, S_IRUGO | S_IWUSR, edac_pci_int_show,
052dfb45c   Douglas Thompson   drivers/edac: cle...
279
  	edac_pci_int_store);
079708b91   Douglas Thompson   drivers/edac: cor...
280
  EDAC_PCI_ATTR(edac_pci_panic_on_pe, S_IRUGO | S_IWUSR, edac_pci_int_show,
052dfb45c   Douglas Thompson   drivers/edac: cle...
281
  	edac_pci_int_store);
7c9281d76   Douglas Thompson   drivers/edac: spl...
282
  EDAC_PCI_ATTR(pci_parity_count, S_IRUGO, edac_pci_int_show, NULL);
91b99041c   Dave Jiang   drivers/edac: upd...
283
  EDAC_PCI_ATTR(pci_nonparity_count, S_IRUGO, edac_pci_int_show, NULL);
7c9281d76   Douglas Thompson   drivers/edac: spl...
284
285
286
  
  /* Base Attributes of the memory ECC object */
  static struct edac_pci_dev_attribute *edac_pci_attr[] = {
91b99041c   Dave Jiang   drivers/edac: upd...
287
  	&edac_pci_attr_check_pci_errors,
4de78c687   Dave Jiang   drivers/edac: mod...
288
289
290
  	&edac_pci_attr_edac_pci_log_pe,
  	&edac_pci_attr_edac_pci_log_npe,
  	&edac_pci_attr_edac_pci_panic_on_pe,
7c9281d76   Douglas Thompson   drivers/edac: spl...
291
  	&edac_pci_attr_pci_parity_count,
91b99041c   Dave Jiang   drivers/edac: upd...
292
  	&edac_pci_attr_pci_nonparity_count,
7c9281d76   Douglas Thompson   drivers/edac: spl...
293
294
  	NULL,
  };
d4c1465b7   Doug Thompson   drivers/edac: fix...
295
296
297
298
299
300
301
302
303
304
  /*
   * edac_pci_release_main_kobj
   *
   *	This release function is called when the reference count to the
   *	passed kobj goes to zero.
   *
   *	This kobj is the 'main' kobject that EDAC PCI instances
   *	link to, and thus provide for proper nesting counts
   */
  static void edac_pci_release_main_kobj(struct kobject *kobj)
7c9281d76   Douglas Thompson   drivers/edac: spl...
305
  {
956b9ba15   Joe Perches   edac: Convert deb...
306
307
  	edac_dbg(0, "here to module_put(THIS_MODULE)
  ");
91b99041c   Dave Jiang   drivers/edac: upd...
308

14cc571bb   Arthur Jones   edac: core fix to...
309
  	kfree(kobj);
d4c1465b7   Doug Thompson   drivers/edac: fix...
310
311
312
313
  	/* last reference to top EDAC PCI kobject has been removed,
  	 * NOW release our ref count on the core module
  	 */
  	module_put(THIS_MODULE);
7c9281d76   Douglas Thompson   drivers/edac: spl...
314
  }
d4c1465b7   Doug Thompson   drivers/edac: fix...
315
316
317
  /* ktype struct for the EDAC PCI main kobj */
  static struct kobj_type ktype_edac_pci_main_kobj = {
  	.release = edac_pci_release_main_kobj,
7c9281d76   Douglas Thompson   drivers/edac: spl...
318
  	.sysfs_ops = &edac_pci_sysfs_ops,
079708b91   Douglas Thompson   drivers/edac: cor...
319
  	.default_attrs = (struct attribute **)edac_pci_attr,
7c9281d76   Douglas Thompson   drivers/edac: spl...
320
321
322
  };
  
  /**
d4538000c   Borislav Petkov   EDAC: Remove edac...
323
   * edac_pci_main_kobj_setup: Setup the sysfs for EDAC PCI attributes.
7c9281d76   Douglas Thompson   drivers/edac: spl...
324
   */
1a45027d1   Adrian Bunk   edac: remove unne...
325
  static int edac_pci_main_kobj_setup(void)
7c9281d76   Douglas Thompson   drivers/edac: spl...
326
327
  {
  	int err;
fe5ff8b84   Kay Sievers   edac: convert sys...
328
  	struct bus_type *edac_subsys;
7c9281d76   Douglas Thompson   drivers/edac: spl...
329

956b9ba15   Joe Perches   edac: Convert deb...
330
331
  	edac_dbg(0, "
  ");
d4c1465b7   Doug Thompson   drivers/edac: fix...
332
333
334
335
  
  	/* check and count if we have already created the main kobject */
  	if (atomic_inc_return(&edac_pci_sysfs_refcount) != 1)
  		return 0;
7c9281d76   Douglas Thompson   drivers/edac: spl...
336

d4c1465b7   Doug Thompson   drivers/edac: fix...
337
  	/* First time, so create the main kobject and its
25985edce   Lucas De Marchi   Fix common misspe...
338
  	 * controls and attributes
d4c1465b7   Doug Thompson   drivers/edac: fix...
339
  	 */
fe5ff8b84   Kay Sievers   edac: convert sys...
340
  	edac_subsys = edac_get_sysfs_subsys();
7c9281d76   Douglas Thompson   drivers/edac: spl...
341

d4c1465b7   Doug Thompson   drivers/edac: fix...
342
343
344
345
346
  	/* Bump the reference count on this module to ensure the
  	 * modules isn't unloaded until we deconstruct the top
  	 * level main kobj for EDAC PCI
  	 */
  	if (!try_module_get(THIS_MODULE)) {
956b9ba15   Joe Perches   edac: Convert deb...
347
348
  		edac_dbg(1, "try_module_get() failed
  ");
d4c1465b7   Doug Thompson   drivers/edac: fix...
349
  		err = -ENODEV;
733476cf2   Borislav Petkov   EDAC: Rip out the...
350
  		goto decrement_count_fail;
d4c1465b7   Doug Thompson   drivers/edac: fix...
351
  	}
7c9281d76   Douglas Thompson   drivers/edac: spl...
352

14cc571bb   Arthur Jones   edac: core fix to...
353
354
  	edac_pci_top_main_kobj = kzalloc(sizeof(struct kobject), GFP_KERNEL);
  	if (!edac_pci_top_main_kobj) {
956b9ba15   Joe Perches   edac: Convert deb...
355
356
  		edac_dbg(1, "Failed to allocate
  ");
14cc571bb   Arthur Jones   edac: core fix to...
357
358
359
  		err = -ENOMEM;
  		goto kzalloc_fail;
  	}
91b99041c   Dave Jiang   drivers/edac: upd...
360
  	/* Instanstiate the pci object */
14cc571bb   Arthur Jones   edac: core fix to...
361
362
  	err = kobject_init_and_add(edac_pci_top_main_kobj,
  				   &ktype_edac_pci_main_kobj,
fe5ff8b84   Kay Sievers   edac: convert sys...
363
  				   &edac_subsys->dev_root->kobj, "pci");
91b99041c   Dave Jiang   drivers/edac: upd...
364
  	if (err) {
956b9ba15   Joe Perches   edac: Convert deb...
365
366
  		edac_dbg(1, "Failed to register '.../edac/pci'
  ");
b2ed215a3   Greg Kroah-Hartman   Kobject: change d...
367
  		goto kobject_init_and_add_fail;
7c9281d76   Douglas Thompson   drivers/edac: spl...
368
  	}
d4c1465b7   Doug Thompson   drivers/edac: fix...
369
370
371
372
  	/* At this point, to 'release' the top level kobject
  	 * for EDAC PCI, then edac_pci_main_kobj_teardown()
  	 * must be used, for resources to be cleaned up properly
  	 */
14cc571bb   Arthur Jones   edac: core fix to...
373
  	kobject_uevent(edac_pci_top_main_kobj, KOBJ_ADD);
956b9ba15   Joe Perches   edac: Convert deb...
374
375
  	edac_dbg(1, "Registered '.../edac/pci' kobject
  ");
91b99041c   Dave Jiang   drivers/edac: upd...
376
377
  
  	return 0;
d4c1465b7   Doug Thompson   drivers/edac: fix...
378
379
  
  	/* Error unwind statck */
b2ed215a3   Greg Kroah-Hartman   Kobject: change d...
380
  kobject_init_and_add_fail:
14cc571bb   Arthur Jones   edac: core fix to...
381
382
383
  	kfree(edac_pci_top_main_kobj);
  
  kzalloc_fail:
d4c1465b7   Doug Thompson   drivers/edac: fix...
384
385
386
387
388
389
390
  	module_put(THIS_MODULE);
  
  decrement_count_fail:
  	/* if are on this error exit, nothing to tear down */
  	atomic_dec(&edac_pci_sysfs_refcount);
  
  	return err;
7c9281d76   Douglas Thompson   drivers/edac: spl...
391
392
393
  }
  
  /*
d4c1465b7   Doug Thompson   drivers/edac: fix...
394
   * edac_pci_main_kobj_teardown()
7c9281d76   Douglas Thompson   drivers/edac: spl...
395
   *
d4c1465b7   Doug Thompson   drivers/edac: fix...
396
397
   *	if no longer linked (needed) remove the top level EDAC PCI
   *	kobject with its controls and attributes
7c9281d76   Douglas Thompson   drivers/edac: spl...
398
   */
d4c1465b7   Doug Thompson   drivers/edac: fix...
399
  static void edac_pci_main_kobj_teardown(void)
7c9281d76   Douglas Thompson   drivers/edac: spl...
400
  {
956b9ba15   Joe Perches   edac: Convert deb...
401
402
  	edac_dbg(0, "
  ");
d4c1465b7   Doug Thompson   drivers/edac: fix...
403
404
405
406
407
408
  
  	/* Decrement the count and only if no more controller instances
  	 * are connected perform the unregisteration of the top level
  	 * main kobj
  	 */
  	if (atomic_dec_return(&edac_pci_sysfs_refcount) == 0) {
956b9ba15   Joe Perches   edac: Convert deb...
409
410
  		edac_dbg(0, "called kobject_put on main kobj
  ");
14cc571bb   Arthur Jones   edac: core fix to...
411
  		kobject_put(edac_pci_top_main_kobj);
d4c1465b7   Doug Thompson   drivers/edac: fix...
412
  	}
7c9281d76   Douglas Thompson   drivers/edac: spl...
413
  }
91b99041c   Dave Jiang   drivers/edac: upd...
414
415
416
417
  int edac_pci_create_sysfs(struct edac_pci_ctl_info *pci)
  {
  	int err;
  	struct kobject *edac_kobj = &pci->kobj;
956b9ba15   Joe Perches   edac: Convert deb...
418
419
  	edac_dbg(0, "idx=%d
  ", pci->pci_idx);
91b99041c   Dave Jiang   drivers/edac: upd...
420

d4c1465b7   Doug Thompson   drivers/edac: fix...
421
422
423
424
  	/* create the top main EDAC PCI kobject, IF needed */
  	err = edac_pci_main_kobj_setup();
  	if (err)
  		return err;
7c9281d76   Douglas Thompson   drivers/edac: spl...
425

d4c1465b7   Doug Thompson   drivers/edac: fix...
426
427
428
429
  	/* Create this instance's kobject under the MAIN kobject */
  	err = edac_pci_create_instance_kobj(pci, pci->pci_idx);
  	if (err)
  		goto unregister_cleanup;
91b99041c   Dave Jiang   drivers/edac: upd...
430

079708b91   Douglas Thompson   drivers/edac: cor...
431
  	err = sysfs_create_link(edac_kobj, &pci->dev->kobj, EDAC_PCI_SYMLINK);
91b99041c   Dave Jiang   drivers/edac: upd...
432
  	if (err) {
956b9ba15   Joe Perches   edac: Convert deb...
433
434
  		edac_dbg(0, "sysfs_create_link() returned err= %d
  ", err);
d4c1465b7   Doug Thompson   drivers/edac: fix...
435
  		goto symlink_fail;
91b99041c   Dave Jiang   drivers/edac: upd...
436
437
438
  	}
  
  	return 0;
d4c1465b7   Doug Thompson   drivers/edac: fix...
439
440
441
442
443
444
445
446
447
  
  	/* Error unwind stack */
  symlink_fail:
  	edac_pci_unregister_sysfs_instance_kobj(pci);
  
  unregister_cleanup:
  	edac_pci_main_kobj_teardown();
  
  	return err;
91b99041c   Dave Jiang   drivers/edac: upd...
448
449
450
451
  }
  
  void edac_pci_remove_sysfs(struct edac_pci_ctl_info *pci)
  {
956b9ba15   Joe Perches   edac: Convert deb...
452
453
  	edac_dbg(0, "index=%d
  ", pci->pci_idx);
91b99041c   Dave Jiang   drivers/edac: upd...
454

d4c1465b7   Doug Thompson   drivers/edac: fix...
455
  	/* Remove the symlink */
91b99041c   Dave Jiang   drivers/edac: upd...
456
  	sysfs_remove_link(&pci->kobj, EDAC_PCI_SYMLINK);
d4c1465b7   Doug Thompson   drivers/edac: fix...
457
458
459
460
461
462
463
  	/* remove this PCI instance's sysfs entries */
  	edac_pci_unregister_sysfs_instance_kobj(pci);
  
  	/* Call the main unregister function, which will determine
  	 * if this 'pci' is the last instance.
  	 * If it is, the main kobject will be unregistered as a result
  	 */
956b9ba15   Joe Perches   edac: Convert deb...
464
465
  	edac_dbg(0, "calling edac_pci_main_kobj_teardown()
  ");
d4c1465b7   Doug Thompson   drivers/edac: fix...
466
  	edac_pci_main_kobj_teardown();
91b99041c   Dave Jiang   drivers/edac: upd...
467
468
469
  }
  
  /************************ PCI error handling *************************/
7c9281d76   Douglas Thompson   drivers/edac: spl...
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
  static u16 get_pci_parity_status(struct pci_dev *dev, int secondary)
  {
  	int where;
  	u16 status;
  
  	where = secondary ? PCI_SEC_STATUS : PCI_STATUS;
  	pci_read_config_word(dev, where, &status);
  
  	/* If we get back 0xFFFF then we must suspect that the card has been
  	 * pulled but the Linux PCI layer has not yet finished cleaning up.
  	 * We don't want to report on such devices
  	 */
  
  	if (status == 0xFFFF) {
  		u32 sanity;
  
  		pci_read_config_dword(dev, 0, &sanity);
  
  		if (sanity == 0xFFFFFFFF)
  			return 0;
  	}
  
  	status &= PCI_STATUS_DETECTED_PARITY | PCI_STATUS_SIG_SYSTEM_ERROR |
052dfb45c   Douglas Thompson   drivers/edac: cle...
493
  		PCI_STATUS_PARITY;
7c9281d76   Douglas Thompson   drivers/edac: spl...
494
495
496
497
498
499
500
  
  	if (status)
  		/* reset only the bits we are interested in */
  		pci_write_config_word(dev, where, status);
  
  	return status;
  }
7c9281d76   Douglas Thompson   drivers/edac: spl...
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
  
  /* Clear any PCI parity errors logged by this device. */
  static void edac_pci_dev_parity_clear(struct pci_dev *dev)
  {
  	u8 header_type;
  
  	get_pci_parity_status(dev, 0);
  
  	/* read the device TYPE, looking for bridges */
  	pci_read_config_byte(dev, PCI_HEADER_TYPE, &header_type);
  
  	if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE)
  		get_pci_parity_status(dev, 1);
  }
  
  /*
   *  PCI Parity polling
   *
25985edce   Lucas De Marchi   Fix common misspe...
519
   *	Function to retrieve the current parity status
d4c1465b7   Doug Thompson   drivers/edac: fix...
520
521
   *	and decode it
   *
7c9281d76   Douglas Thompson   drivers/edac: spl...
522
523
524
   */
  static void edac_pci_dev_parity_test(struct pci_dev *dev)
  {
d4c1465b7   Doug Thompson   drivers/edac: fix...
525
  	unsigned long flags;
7c9281d76   Douglas Thompson   drivers/edac: spl...
526
  	u16 status;
079708b91   Douglas Thompson   drivers/edac: cor...
527
  	u8 header_type;
7c9281d76   Douglas Thompson   drivers/edac: spl...
528

d4c1465b7   Doug Thompson   drivers/edac: fix...
529
530
531
532
  	/* stop any interrupts until we can acquire the status */
  	local_irq_save(flags);
  
  	/* read the STATUS register on this device */
7c9281d76   Douglas Thompson   drivers/edac: spl...
533
  	status = get_pci_parity_status(dev, 0);
d4c1465b7   Doug Thompson   drivers/edac: fix...
534
535
536
537
  	/* read the device TYPE, looking for bridges */
  	pci_read_config_byte(dev, PCI_HEADER_TYPE, &header_type);
  
  	local_irq_restore(flags);
956b9ba15   Joe Perches   edac: Convert deb...
538
539
  	edac_dbg(4, "PCI STATUS= 0x%04x %s
  ", status, dev_name(&dev->dev));
7c9281d76   Douglas Thompson   drivers/edac: spl...
540

6b09ff9d7   Bryan Boatright   drivers/edac: pci...
541
542
543
544
  	/* check the status reg for errors on boards NOT marked as broken
  	 * if broken, we cannot trust any of the status bits
  	 */
  	if (status && !dev->broken_parity_status) {
91b99041c   Dave Jiang   drivers/edac: upd...
545
  		if (status & (PCI_STATUS_SIG_SYSTEM_ERROR)) {
7c9281d76   Douglas Thompson   drivers/edac: spl...
546
  			edac_printk(KERN_CRIT, EDAC_PCI,
052dfb45c   Douglas Thompson   drivers/edac: cle...
547
548
549
  				"Signaled System Error on %s
  ",
  				pci_name(dev));
91b99041c   Dave Jiang   drivers/edac: upd...
550
551
  			atomic_inc(&pci_nonparity_count);
  		}
7c9281d76   Douglas Thompson   drivers/edac: spl...
552
553
554
  
  		if (status & (PCI_STATUS_PARITY)) {
  			edac_printk(KERN_CRIT, EDAC_PCI,
052dfb45c   Douglas Thompson   drivers/edac: cle...
555
556
557
  				"Master Data Parity Error on %s
  ",
  				pci_name(dev));
7c9281d76   Douglas Thompson   drivers/edac: spl...
558
559
560
561
562
563
  
  			atomic_inc(&pci_parity_count);
  		}
  
  		if (status & (PCI_STATUS_DETECTED_PARITY)) {
  			edac_printk(KERN_CRIT, EDAC_PCI,
052dfb45c   Douglas Thompson   drivers/edac: cle...
564
565
566
  				"Detected Parity Error on %s
  ",
  				pci_name(dev));
7c9281d76   Douglas Thompson   drivers/edac: spl...
567
568
569
570
  
  			atomic_inc(&pci_parity_count);
  		}
  	}
7c9281d76   Douglas Thompson   drivers/edac: spl...
571

956b9ba15   Joe Perches   edac: Convert deb...
572
573
574
  	edac_dbg(4, "PCI HEADER TYPE= 0x%02x %s
  ",
  		 header_type, dev_name(&dev->dev));
7c9281d76   Douglas Thompson   drivers/edac: spl...
575
576
577
578
  
  	if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) {
  		/* On bridges, need to examine secondary status register  */
  		status = get_pci_parity_status(dev, 1);
956b9ba15   Joe Perches   edac: Convert deb...
579
580
581
  		edac_dbg(4, "PCI SEC_STATUS= 0x%04x %s
  ",
  			 status, dev_name(&dev->dev));
7c9281d76   Douglas Thompson   drivers/edac: spl...
582

6b09ff9d7   Bryan Boatright   drivers/edac: pci...
583
584
585
586
  		/* check the secondary status reg for errors,
  		 * on NOT broken boards
  		 */
  		if (status && !dev->broken_parity_status) {
91b99041c   Dave Jiang   drivers/edac: upd...
587
  			if (status & (PCI_STATUS_SIG_SYSTEM_ERROR)) {
7c9281d76   Douglas Thompson   drivers/edac: spl...
588
  				edac_printk(KERN_CRIT, EDAC_PCI, "Bridge "
052dfb45c   Douglas Thompson   drivers/edac: cle...
589
590
591
  					"Signaled System Error on %s
  ",
  					pci_name(dev));
91b99041c   Dave Jiang   drivers/edac: upd...
592
593
  				atomic_inc(&pci_nonparity_count);
  			}
7c9281d76   Douglas Thompson   drivers/edac: spl...
594
595
596
  
  			if (status & (PCI_STATUS_PARITY)) {
  				edac_printk(KERN_CRIT, EDAC_PCI, "Bridge "
052dfb45c   Douglas Thompson   drivers/edac: cle...
597
598
599
  					"Master Data Parity Error on "
  					"%s
  ", pci_name(dev));
7c9281d76   Douglas Thompson   drivers/edac: spl...
600
601
602
603
604
605
  
  				atomic_inc(&pci_parity_count);
  			}
  
  			if (status & (PCI_STATUS_DETECTED_PARITY)) {
  				edac_printk(KERN_CRIT, EDAC_PCI, "Bridge "
052dfb45c   Douglas Thompson   drivers/edac: cle...
606
607
608
  					"Detected Parity Error on %s
  ",
  					pci_name(dev));
7c9281d76   Douglas Thompson   drivers/edac: spl...
609
610
611
612
613
614
  
  				atomic_inc(&pci_parity_count);
  			}
  		}
  	}
  }
d4c1465b7   Doug Thompson   drivers/edac: fix...
615
616
  /* reduce some complexity in definition of the iterator */
  typedef void (*pci_parity_check_fn_t) (struct pci_dev *dev);
7c9281d76   Douglas Thompson   drivers/edac: spl...
617
618
  /*
   * pci_dev parity list iterator
3bfe5aae8   Wei Yongjun   EDAC, pci_sysfs: ...
619
620
621
   *
   *	Scan the PCI device list looking for SERRORs, Master Parity ERRORS or
   *	Parity ERRORs on primary or secondary devices.
7c9281d76   Douglas Thompson   drivers/edac: spl...
622
623
624
625
   */
  static inline void edac_pci_dev_parity_iterator(pci_parity_check_fn_t fn)
  {
  	struct pci_dev *dev = NULL;
3bfe5aae8   Wei Yongjun   EDAC, pci_sysfs: ...
626
  	for_each_pci_dev(dev)
7c9281d76   Douglas Thompson   drivers/edac: spl...
627
  		fn(dev);
7c9281d76   Douglas Thompson   drivers/edac: spl...
628
629
630
631
632
633
634
635
636
  }
  
  /*
   * edac_pci_do_parity_check
   *
   *	performs the actual PCI parity check operation
   */
  void edac_pci_do_parity_check(void)
  {
7c9281d76   Douglas Thompson   drivers/edac: spl...
637
  	int before_count;
956b9ba15   Joe Perches   edac: Convert deb...
638
639
  	edac_dbg(3, "
  ");
7c9281d76   Douglas Thompson   drivers/edac: spl...
640

d4c1465b7   Doug Thompson   drivers/edac: fix...
641
  	/* if policy has PCI check off, leave now */
91b99041c   Dave Jiang   drivers/edac: upd...
642
  	if (!check_pci_errors)
7c9281d76   Douglas Thompson   drivers/edac: spl...
643
644
645
646
647
  		return;
  
  	before_count = atomic_read(&pci_parity_count);
  
  	/* scan all PCI devices looking for a Parity Error on devices and
d4c1465b7   Doug Thompson   drivers/edac: fix...
648
649
650
  	 * bridges.
  	 * The iterator calls pci_get_device() which might sleep, thus
  	 * we cannot disable interrupts in this scan.
7c9281d76   Douglas Thompson   drivers/edac: spl...
651
  	 */
7c9281d76   Douglas Thompson   drivers/edac: spl...
652
  	edac_pci_dev_parity_iterator(edac_pci_dev_parity_test);
7c9281d76   Douglas Thompson   drivers/edac: spl...
653
654
  
  	/* Only if operator has selected panic on PCI Error */
4de78c687   Dave Jiang   drivers/edac: mod...
655
  	if (edac_pci_get_panic_on_pe()) {
7c9281d76   Douglas Thompson   drivers/edac: spl...
656
657
658
659
660
  		/* If the count is different 'after' from 'before' */
  		if (before_count != atomic_read(&pci_parity_count))
  			panic("EDAC: PCI Parity Error");
  	}
  }
d4c1465b7   Doug Thompson   drivers/edac: fix...
661
662
663
664
665
666
  /*
   * edac_pci_clear_parity_errors
   *
   *	function to perform an iteration over the PCI devices
   *	and clearn their current status
   */
7c9281d76   Douglas Thompson   drivers/edac: spl...
667
668
669
670
671
672
673
  void edac_pci_clear_parity_errors(void)
  {
  	/* Clear any PCI bus parity errors that devices initially have logged
  	 * in their registers.
  	 */
  	edac_pci_dev_parity_iterator(edac_pci_dev_parity_clear);
  }
d4c1465b7   Doug Thompson   drivers/edac: fix...
674
675
676
677
678
679
  
  /*
   * edac_pci_handle_pe
   *
   *	Called to handle a PARITY ERROR event
   */
91b99041c   Dave Jiang   drivers/edac: upd...
680
681
682
683
684
  void edac_pci_handle_pe(struct edac_pci_ctl_info *pci, const char *msg)
  {
  
  	/* global PE counter incremented by edac_pci_do_parity_check() */
  	atomic_inc(&pci->counters.pe_count);
4de78c687   Dave Jiang   drivers/edac: mod...
685
  	if (edac_pci_get_log_pe())
91b99041c   Dave Jiang   drivers/edac: upd...
686
687
688
689
690
691
692
693
694
695
696
697
  		edac_pci_printk(pci, KERN_WARNING,
  				"Parity Error ctl: %s %d: %s
  ",
  				pci->ctl_name, pci->pci_idx, msg);
  
  	/*
  	 * poke all PCI devices and see which one is the troublemaker
  	 * panic() is called if set
  	 */
  	edac_pci_do_parity_check();
  }
  EXPORT_SYMBOL_GPL(edac_pci_handle_pe);
7c9281d76   Douglas Thompson   drivers/edac: spl...
698

d4c1465b7   Doug Thompson   drivers/edac: fix...
699
700
701
702
703
704
  
  /*
   * edac_pci_handle_npe
   *
   *	Called to handle a NON-PARITY ERROR event
   */
91b99041c   Dave Jiang   drivers/edac: upd...
705
706
707
708
709
  void edac_pci_handle_npe(struct edac_pci_ctl_info *pci, const char *msg)
  {
  
  	/* global NPE counter incremented by edac_pci_do_parity_check() */
  	atomic_inc(&pci->counters.npe_count);
4de78c687   Dave Jiang   drivers/edac: mod...
710
  	if (edac_pci_get_log_npe())
91b99041c   Dave Jiang   drivers/edac: upd...
711
712
713
714
715
716
717
718
719
720
721
722
  		edac_pci_printk(pci, KERN_WARNING,
  				"Non-Parity Error ctl: %s %d: %s
  ",
  				pci->ctl_name, pci->pci_idx, msg);
  
  	/*
  	 * poke all PCI devices and see which one is the troublemaker
  	 * panic() is called if set
  	 */
  	edac_pci_do_parity_check();
  }
  EXPORT_SYMBOL_GPL(edac_pci_handle_npe);
7c9281d76   Douglas Thompson   drivers/edac: spl...
723
724
725
726
  
  /*
   * Define the PCI parameter to the module
   */
91b99041c   Dave Jiang   drivers/edac: upd...
727
  module_param(check_pci_errors, int, 0644);
4de78c687   Dave Jiang   drivers/edac: mod...
728
  MODULE_PARM_DESC(check_pci_errors,
079708b91   Douglas Thompson   drivers/edac: cor...
729
  		 "Check for PCI bus parity errors: 0=off 1=on");
4de78c687   Dave Jiang   drivers/edac: mod...
730
731
  module_param(edac_pci_panic_on_pe, int, 0644);
  MODULE_PARM_DESC(edac_pci_panic_on_pe,
079708b91   Douglas Thompson   drivers/edac: cor...
732
  		 "Panic on PCI Bus Parity error: 0=off 1=on");