diff options
author | Doug Thompson <dougthompson@xmission.com> | 2007-07-26 13:41:15 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-07-26 14:35:18 -0400 |
commit | d4c1465b7de9686c4c5aa533b15c09ab014aab3a (patch) | |
tree | 695434e881a3b395db782fe82e95eee2631b8a2e /drivers/edac | |
parent | bce19683c17485b584b62b984d6dcf5332181588 (diff) |
drivers/edac: fix edac_pci sysfs
This patch fixes sysfs exit code for the EDAC PCI device in a similiar manner
and the previous fixes for EDAC_MC and EDAC_DEVICE.
It removes the old (and incorrect) completion model and uses reference counts
on per instance kobjects and on the edac core module.
This pattern was applied to the edac_mc and edac_device code, but the EDAC PCI
code was missed. In addition, this fixes a system hang after a low level
driver was unloaded. (A cleanup function was called twice, which really
screwed things up)
Cc: Greg KH <greg@kroah.com>
Cc: Alan Cox <alan@lxorguk.ukuu.org.uk>
Signed-off-by: Doug Thompson <dougthompson@xmission.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/edac')
-rw-r--r-- | drivers/edac/edac_module.h | 6 | ||||
-rw-r--r-- | drivers/edac/edac_pci.c | 162 | ||||
-rw-r--r-- | drivers/edac/edac_pci_sysfs.c | 297 |
3 files changed, 337 insertions, 128 deletions
diff --git a/drivers/edac/edac_module.h b/drivers/edac/edac_module.h index 3664ae9ccd63..cbc419c8ebc1 100644 --- a/drivers/edac/edac_module.h +++ b/drivers/edac/edac_module.h | |||
@@ -66,6 +66,10 @@ extern int edac_sysfs_pci_setup(void); | |||
66 | extern void edac_sysfs_pci_teardown(void); | 66 | extern void edac_sysfs_pci_teardown(void); |
67 | extern int edac_pci_get_check_errors(void); | 67 | extern int edac_pci_get_check_errors(void); |
68 | extern int edac_pci_get_poll_msec(void); | 68 | extern int edac_pci_get_poll_msec(void); |
69 | extern void edac_pci_remove_sysfs(struct edac_pci_ctl_info *pci); | ||
70 | extern void edac_pci_handle_pe(struct edac_pci_ctl_info *pci, const char *msg); | ||
71 | extern void edac_pci_handle_npe(struct edac_pci_ctl_info *pci, | ||
72 | const char *msg); | ||
69 | #else /* CONFIG_PCI */ | 73 | #else /* CONFIG_PCI */ |
70 | /* pre-process these away */ | 74 | /* pre-process these away */ |
71 | #define edac_pci_do_parity_check() | 75 | #define edac_pci_do_parity_check() |
@@ -74,6 +78,8 @@ extern int edac_pci_get_poll_msec(void); | |||
74 | #define edac_sysfs_pci_teardown() | 78 | #define edac_sysfs_pci_teardown() |
75 | #define edac_pci_get_check_errors() | 79 | #define edac_pci_get_check_errors() |
76 | #define edac_pci_get_poll_msec() | 80 | #define edac_pci_get_poll_msec() |
81 | #define edac_pci_handle_pe() | ||
82 | #define edac_pci_handle_npe() | ||
77 | #endif /* CONFIG_PCI */ | 83 | #endif /* CONFIG_PCI */ |
78 | 84 | ||
79 | #endif /* __EDAC_MODULE_H__ */ | 85 | #endif /* __EDAC_MODULE_H__ */ |
diff --git a/drivers/edac/edac_pci.c b/drivers/edac/edac_pci.c index d9cd5e048cee..5dee9f50414b 100644 --- a/drivers/edac/edac_pci.c +++ b/drivers/edac/edac_pci.c | |||
@@ -31,20 +31,12 @@ | |||
31 | static DEFINE_MUTEX(edac_pci_ctls_mutex); | 31 | static DEFINE_MUTEX(edac_pci_ctls_mutex); |
32 | static struct list_head edac_pci_list = LIST_HEAD_INIT(edac_pci_list); | 32 | static struct list_head edac_pci_list = LIST_HEAD_INIT(edac_pci_list); |
33 | 33 | ||
34 | static inline void edac_lock_pci_list(void) | ||
35 | { | ||
36 | mutex_lock(&edac_pci_ctls_mutex); | ||
37 | } | ||
38 | |||
39 | static inline void edac_unlock_pci_list(void) | ||
40 | { | ||
41 | mutex_unlock(&edac_pci_ctls_mutex); | ||
42 | } | ||
43 | |||
44 | /* | 34 | /* |
45 | * The alloc() and free() functions for the 'edac_pci' control info | 35 | * edac_pci_alloc_ctl_info |
46 | * structure. The chip driver will allocate one of these for each | 36 | * |
47 | * edac_pci it is going to control/register with the EDAC CORE. | 37 | * The alloc() function for the 'edac_pci' control info |
38 | * structure. The chip driver will allocate one of these for each | ||
39 | * edac_pci it is going to control/register with the EDAC CORE. | ||
48 | */ | 40 | */ |
49 | struct edac_pci_ctl_info *edac_pci_alloc_ctl_info(unsigned int sz_pvt, | 41 | struct edac_pci_ctl_info *edac_pci_alloc_ctl_info(unsigned int sz_pvt, |
50 | const char *edac_pci_name) | 42 | const char *edac_pci_name) |
@@ -53,47 +45,59 @@ struct edac_pci_ctl_info *edac_pci_alloc_ctl_info(unsigned int sz_pvt, | |||
53 | void *pvt; | 45 | void *pvt; |
54 | unsigned int size; | 46 | unsigned int size; |
55 | 47 | ||
48 | debugf1("%s()\n", __func__); | ||
49 | |||
56 | pci = (struct edac_pci_ctl_info *)0; | 50 | pci = (struct edac_pci_ctl_info *)0; |
57 | pvt = edac_align_ptr(&pci[1], sz_pvt); | 51 | pvt = edac_align_ptr(&pci[1], sz_pvt); |
58 | size = ((unsigned long)pvt) + sz_pvt; | 52 | size = ((unsigned long)pvt) + sz_pvt; |
59 | 53 | ||
60 | if ((pci = kzalloc(size, GFP_KERNEL)) == NULL) | 54 | /* Alloc the needed control struct memory */ |
55 | pci = kzalloc(size, GFP_KERNEL); | ||
56 | if (pci == NULL) | ||
61 | return NULL; | 57 | return NULL; |
62 | 58 | ||
59 | /* Now much private space */ | ||
63 | pvt = sz_pvt ? ((char *)pci) + ((unsigned long)pvt) : NULL; | 60 | pvt = sz_pvt ? ((char *)pci) + ((unsigned long)pvt) : NULL; |
64 | 61 | ||
65 | pci->pvt_info = pvt; | 62 | pci->pvt_info = pvt; |
66 | |||
67 | pci->op_state = OP_ALLOC; | 63 | pci->op_state = OP_ALLOC; |
68 | 64 | ||
69 | snprintf(pci->name, strlen(edac_pci_name) + 1, "%s", edac_pci_name); | 65 | snprintf(pci->name, strlen(edac_pci_name) + 1, "%s", edac_pci_name); |
70 | 66 | ||
71 | return pci; | 67 | return pci; |
72 | } | 68 | } |
73 | |||
74 | EXPORT_SYMBOL_GPL(edac_pci_alloc_ctl_info); | 69 | EXPORT_SYMBOL_GPL(edac_pci_alloc_ctl_info); |
75 | 70 | ||
76 | /* | 71 | /* |
77 | * edac_pci_free_ctl_info() | 72 | * edac_pci_free_ctl_info() |
78 | * frees the memory allocated by edac_pci_alloc_ctl_info() function | 73 | * |
74 | * Last action on the pci control structure. | ||
75 | * | ||
76 | * call the remove sysfs informaton, which will unregister | ||
77 | * this control struct's kobj. When that kobj's ref count | ||
78 | * goes to zero, its release function will be call and then | ||
79 | * kfree() the memory. | ||
79 | */ | 80 | */ |
80 | void edac_pci_free_ctl_info(struct edac_pci_ctl_info *pci) | 81 | void edac_pci_free_ctl_info(struct edac_pci_ctl_info *pci) |
81 | { | 82 | { |
82 | kfree(pci); | 83 | debugf1("%s()\n", __func__); |
83 | } | ||
84 | 84 | ||
85 | edac_pci_remove_sysfs(pci); | ||
86 | } | ||
85 | EXPORT_SYMBOL_GPL(edac_pci_free_ctl_info); | 87 | EXPORT_SYMBOL_GPL(edac_pci_free_ctl_info); |
86 | 88 | ||
87 | /* | 89 | /* |
88 | * find_edac_pci_by_dev() | 90 | * find_edac_pci_by_dev() |
89 | * scans the edac_pci list for a specific 'struct device *' | 91 | * scans the edac_pci list for a specific 'struct device *' |
92 | * | ||
93 | * return NULL if not found, or return control struct pointer | ||
90 | */ | 94 | */ |
91 | static struct edac_pci_ctl_info *find_edac_pci_by_dev(struct device *dev) | 95 | static struct edac_pci_ctl_info *find_edac_pci_by_dev(struct device *dev) |
92 | { | 96 | { |
93 | struct edac_pci_ctl_info *pci; | 97 | struct edac_pci_ctl_info *pci; |
94 | struct list_head *item; | 98 | struct list_head *item; |
95 | 99 | ||
96 | debugf3("%s()\n", __func__); | 100 | debugf1("%s()\n", __func__); |
97 | 101 | ||
98 | list_for_each(item, &edac_pci_list) { | 102 | list_for_each(item, &edac_pci_list) { |
99 | pci = list_entry(item, struct edac_pci_ctl_info, link); | 103 | pci = list_entry(item, struct edac_pci_ctl_info, link); |
@@ -118,10 +122,13 @@ static int add_edac_pci_to_global_list(struct edac_pci_ctl_info *pci) | |||
118 | struct list_head *item, *insert_before; | 122 | struct list_head *item, *insert_before; |
119 | struct edac_pci_ctl_info *rover; | 123 | struct edac_pci_ctl_info *rover; |
120 | 124 | ||
125 | debugf1("%s()\n", __func__); | ||
126 | |||
121 | insert_before = &edac_pci_list; | 127 | insert_before = &edac_pci_list; |
122 | 128 | ||
123 | /* Determine if already on the list */ | 129 | /* Determine if already on the list */ |
124 | if (unlikely((rover = find_edac_pci_by_dev(pci->dev)) != NULL)) | 130 | rover = find_edac_pci_by_dev(pci->dev); |
131 | if (unlikely(rover != NULL)) | ||
125 | goto fail0; | 132 | goto fail0; |
126 | 133 | ||
127 | /* Insert in ascending order by 'pci_idx', so find position */ | 134 | /* Insert in ascending order by 'pci_idx', so find position */ |
@@ -157,6 +164,8 @@ fail1: | |||
157 | 164 | ||
158 | /* | 165 | /* |
159 | * complete_edac_pci_list_del | 166 | * complete_edac_pci_list_del |
167 | * | ||
168 | * RCU completion callback to indicate item is deleted | ||
160 | */ | 169 | */ |
161 | static void complete_edac_pci_list_del(struct rcu_head *head) | 170 | static void complete_edac_pci_list_del(struct rcu_head *head) |
162 | { | 171 | { |
@@ -169,6 +178,8 @@ static void complete_edac_pci_list_del(struct rcu_head *head) | |||
169 | 178 | ||
170 | /* | 179 | /* |
171 | * del_edac_pci_from_global_list | 180 | * del_edac_pci_from_global_list |
181 | * | ||
182 | * remove the PCI control struct from the global list | ||
172 | */ | 183 | */ |
173 | static void del_edac_pci_from_global_list(struct edac_pci_ctl_info *pci) | 184 | static void del_edac_pci_from_global_list(struct edac_pci_ctl_info *pci) |
174 | { | 185 | { |
@@ -207,35 +218,52 @@ struct edac_pci_ctl_info *edac_pci_find(int idx) | |||
207 | 218 | ||
208 | return NULL; | 219 | return NULL; |
209 | } | 220 | } |
210 | |||
211 | EXPORT_SYMBOL_GPL(edac_pci_find); | 221 | EXPORT_SYMBOL_GPL(edac_pci_find); |
212 | 222 | ||
213 | /* | 223 | /* |
214 | * edac_pci_workq_function() | 224 | * edac_pci_workq_function() |
215 | * performs the operation scheduled by a workq request | 225 | * |
226 | * periodic function that performs the operation | ||
227 | * scheduled by a workq request, for a given PCI control struct | ||
216 | */ | 228 | */ |
217 | static void edac_pci_workq_function(struct work_struct *work_req) | 229 | static void edac_pci_workq_function(struct work_struct *work_req) |
218 | { | 230 | { |
219 | struct delayed_work *d_work = (struct delayed_work *)work_req; | 231 | struct delayed_work *d_work = (struct delayed_work *)work_req; |
220 | struct edac_pci_ctl_info *pci = to_edac_pci_ctl_work(d_work); | 232 | struct edac_pci_ctl_info *pci = to_edac_pci_ctl_work(d_work); |
233 | int msec; | ||
234 | unsigned long delay; | ||
221 | 235 | ||
222 | edac_lock_pci_list(); | 236 | debugf3("%s() checking\n", __func__); |
223 | 237 | ||
224 | if ((pci->op_state == OP_RUNNING_POLL) && | 238 | mutex_lock(&edac_pci_ctls_mutex); |
225 | (pci->edac_check != NULL) && (edac_pci_get_check_errors())) | ||
226 | pci->edac_check(pci); | ||
227 | 239 | ||
228 | edac_unlock_pci_list(); | 240 | if (pci->op_state == OP_RUNNING_POLL) { |
241 | /* we might be in POLL mode, but there may NOT be a poll func | ||
242 | */ | ||
243 | if ((pci->edac_check != NULL) && edac_pci_get_check_errors()) | ||
244 | pci->edac_check(pci); | ||
245 | |||
246 | /* if we are on a one second period, then use round */ | ||
247 | msec = edac_pci_get_poll_msec(); | ||
248 | if (msec == 1000) | ||
249 | delay = round_jiffies(msecs_to_jiffies(msec)); | ||
250 | else | ||
251 | delay = msecs_to_jiffies(msec); | ||
252 | |||
253 | /* Reschedule only if we are in POLL mode */ | ||
254 | queue_delayed_work(edac_workqueue, &pci->work, delay); | ||
255 | } | ||
229 | 256 | ||
230 | /* Reschedule */ | 257 | mutex_unlock(&edac_pci_ctls_mutex); |
231 | queue_delayed_work(edac_workqueue, &pci->work, | ||
232 | msecs_to_jiffies(edac_pci_get_poll_msec())); | ||
233 | } | 258 | } |
234 | 259 | ||
235 | /* | 260 | /* |
236 | * edac_pci_workq_setup() | 261 | * edac_pci_workq_setup() |
237 | * initialize a workq item for this edac_pci instance | 262 | * initialize a workq item for this edac_pci instance |
238 | * passing in the new delay period in msec | 263 | * passing in the new delay period in msec |
264 | * | ||
265 | * locking model: | ||
266 | * called when 'edac_pci_ctls_mutex' is locked | ||
239 | */ | 267 | */ |
240 | static void edac_pci_workq_setup(struct edac_pci_ctl_info *pci, | 268 | static void edac_pci_workq_setup(struct edac_pci_ctl_info *pci, |
241 | unsigned int msec) | 269 | unsigned int msec) |
@@ -255,6 +283,8 @@ static void edac_pci_workq_teardown(struct edac_pci_ctl_info *pci) | |||
255 | { | 283 | { |
256 | int status; | 284 | int status; |
257 | 285 | ||
286 | debugf0("%s()\n", __func__); | ||
287 | |||
258 | status = cancel_delayed_work(&pci->work); | 288 | status = cancel_delayed_work(&pci->work); |
259 | if (status == 0) | 289 | if (status == 0) |
260 | flush_workqueue(edac_workqueue); | 290 | flush_workqueue(edac_workqueue); |
@@ -262,19 +292,25 @@ static void edac_pci_workq_teardown(struct edac_pci_ctl_info *pci) | |||
262 | 292 | ||
263 | /* | 293 | /* |
264 | * edac_pci_reset_delay_period | 294 | * edac_pci_reset_delay_period |
295 | * | ||
296 | * called with a new period value for the workq period | ||
297 | * a) stop current workq timer | ||
298 | * b) restart workq timer with new value | ||
265 | */ | 299 | */ |
266 | void edac_pci_reset_delay_period(struct edac_pci_ctl_info *pci, | 300 | void edac_pci_reset_delay_period(struct edac_pci_ctl_info *pci, |
267 | unsigned long value) | 301 | unsigned long value) |
268 | { | 302 | { |
269 | edac_lock_pci_list(); | 303 | debugf0("%s()\n", __func__); |
270 | 304 | ||
271 | edac_pci_workq_teardown(pci); | 305 | edac_pci_workq_teardown(pci); |
272 | 306 | ||
307 | /* need to lock for the setup */ | ||
308 | mutex_lock(&edac_pci_ctls_mutex); | ||
309 | |||
273 | edac_pci_workq_setup(pci, value); | 310 | edac_pci_workq_setup(pci, value); |
274 | 311 | ||
275 | edac_unlock_pci_list(); | 312 | mutex_unlock(&edac_pci_ctls_mutex); |
276 | } | 313 | } |
277 | |||
278 | EXPORT_SYMBOL_GPL(edac_pci_reset_delay_period); | 314 | EXPORT_SYMBOL_GPL(edac_pci_reset_delay_period); |
279 | 315 | ||
280 | /* | 316 | /* |
@@ -294,14 +330,13 @@ int edac_pci_add_device(struct edac_pci_ctl_info *pci, int edac_idx) | |||
294 | debugf0("%s()\n", __func__); | 330 | debugf0("%s()\n", __func__); |
295 | 331 | ||
296 | pci->pci_idx = edac_idx; | 332 | pci->pci_idx = edac_idx; |
333 | pci->start_time = jiffies; | ||
297 | 334 | ||
298 | edac_lock_pci_list(); | 335 | mutex_lock(&edac_pci_ctls_mutex); |
299 | 336 | ||
300 | if (add_edac_pci_to_global_list(pci)) | 337 | if (add_edac_pci_to_global_list(pci)) |
301 | goto fail0; | 338 | goto fail0; |
302 | 339 | ||
303 | pci->start_time = jiffies; | ||
304 | |||
305 | if (edac_pci_create_sysfs(pci)) { | 340 | if (edac_pci_create_sysfs(pci)) { |
306 | edac_pci_printk(pci, KERN_WARNING, | 341 | edac_pci_printk(pci, KERN_WARNING, |
307 | "failed to create sysfs pci\n"); | 342 | "failed to create sysfs pci\n"); |
@@ -323,16 +358,16 @@ int edac_pci_add_device(struct edac_pci_ctl_info *pci, int edac_idx) | |||
323 | pci->ctl_name, | 358 | pci->ctl_name, |
324 | dev_name(pci), edac_op_state_to_string(pci->op_state)); | 359 | dev_name(pci), edac_op_state_to_string(pci->op_state)); |
325 | 360 | ||
326 | edac_unlock_pci_list(); | 361 | mutex_unlock(&edac_pci_ctls_mutex); |
327 | return 0; | 362 | return 0; |
328 | 363 | ||
364 | /* error unwind stack */ | ||
329 | fail1: | 365 | fail1: |
330 | del_edac_pci_from_global_list(pci); | 366 | del_edac_pci_from_global_list(pci); |
331 | fail0: | 367 | fail0: |
332 | edac_unlock_pci_list(); | 368 | mutex_unlock(&edac_pci_ctls_mutex); |
333 | return 1; | 369 | return 1; |
334 | } | 370 | } |
335 | |||
336 | EXPORT_SYMBOL_GPL(edac_pci_add_device); | 371 | EXPORT_SYMBOL_GPL(edac_pci_add_device); |
337 | 372 | ||
338 | /* | 373 | /* |
@@ -354,22 +389,25 @@ struct edac_pci_ctl_info *edac_pci_del_device(struct device *dev) | |||
354 | 389 | ||
355 | debugf0("%s()\n", __func__); | 390 | debugf0("%s()\n", __func__); |
356 | 391 | ||
357 | edac_lock_pci_list(); | 392 | mutex_lock(&edac_pci_ctls_mutex); |
358 | 393 | ||
359 | if ((pci = find_edac_pci_by_dev(dev)) == NULL) { | 394 | /* ensure the control struct is on the global list |
360 | edac_unlock_pci_list(); | 395 | * if not, then leave |
396 | */ | ||
397 | pci = find_edac_pci_by_dev(dev); | ||
398 | if (pci == NULL) { | ||
399 | mutex_unlock(&edac_pci_ctls_mutex); | ||
361 | return NULL; | 400 | return NULL; |
362 | } | 401 | } |
363 | 402 | ||
364 | pci->op_state = OP_OFFLINE; | 403 | pci->op_state = OP_OFFLINE; |
365 | 404 | ||
366 | edac_pci_workq_teardown(pci); | ||
367 | |||
368 | edac_pci_remove_sysfs(pci); | ||
369 | |||
370 | del_edac_pci_from_global_list(pci); | 405 | del_edac_pci_from_global_list(pci); |
371 | 406 | ||
372 | edac_unlock_pci_list(); | 407 | mutex_unlock(&edac_pci_ctls_mutex); |
408 | |||
409 | /* stop the workq timer */ | ||
410 | edac_pci_workq_teardown(pci); | ||
373 | 411 | ||
374 | edac_printk(KERN_INFO, EDAC_PCI, | 412 | edac_printk(KERN_INFO, EDAC_PCI, |
375 | "Removed device %d for %s %s: DEV %s\n", | 413 | "Removed device %d for %s %s: DEV %s\n", |
@@ -377,14 +415,20 @@ struct edac_pci_ctl_info *edac_pci_del_device(struct device *dev) | |||
377 | 415 | ||
378 | return pci; | 416 | return pci; |
379 | } | 417 | } |
380 | |||
381 | EXPORT_SYMBOL_GPL(edac_pci_del_device); | 418 | EXPORT_SYMBOL_GPL(edac_pci_del_device); |
382 | 419 | ||
420 | /* | ||
421 | * edac_pci_generic_check | ||
422 | * | ||
423 | * a Generic parity check API | ||
424 | */ | ||
383 | void edac_pci_generic_check(struct edac_pci_ctl_info *pci) | 425 | void edac_pci_generic_check(struct edac_pci_ctl_info *pci) |
384 | { | 426 | { |
427 | debugf4("%s()\n", __func__); | ||
385 | edac_pci_do_parity_check(); | 428 | edac_pci_do_parity_check(); |
386 | } | 429 | } |
387 | 430 | ||
431 | /* free running instance index counter */ | ||
388 | static int edac_pci_idx; | 432 | static int edac_pci_idx; |
389 | #define EDAC_PCI_GENCTL_NAME "EDAC PCI controller" | 433 | #define EDAC_PCI_GENCTL_NAME "EDAC PCI controller" |
390 | 434 | ||
@@ -392,6 +436,17 @@ struct edac_pci_gen_data { | |||
392 | int edac_idx; | 436 | int edac_idx; |
393 | }; | 437 | }; |
394 | 438 | ||
439 | /* | ||
440 | * edac_pci_create_generic_ctl | ||
441 | * | ||
442 | * A generic constructor for a PCI parity polling device | ||
443 | * Some systems have more than one domain of PCI busses. | ||
444 | * For systems with one domain, then this API will | ||
445 | * provide for a generic poller. | ||
446 | * | ||
447 | * This routine calls the edac_pci_alloc_ctl_info() for | ||
448 | * the generic device, with default values | ||
449 | */ | ||
395 | struct edac_pci_ctl_info *edac_pci_create_generic_ctl(struct device *dev, | 450 | struct edac_pci_ctl_info *edac_pci_create_generic_ctl(struct device *dev, |
396 | const char *mod_name) | 451 | const char *mod_name) |
397 | { | 452 | { |
@@ -421,13 +476,18 @@ struct edac_pci_ctl_info *edac_pci_create_generic_ctl(struct device *dev, | |||
421 | 476 | ||
422 | return pci; | 477 | return pci; |
423 | } | 478 | } |
424 | |||
425 | EXPORT_SYMBOL_GPL(edac_pci_create_generic_ctl); | 479 | EXPORT_SYMBOL_GPL(edac_pci_create_generic_ctl); |
426 | 480 | ||
481 | /* | ||
482 | * edac_pci_release_generic_ctl | ||
483 | * | ||
484 | * The release function of a generic EDAC PCI polling device | ||
485 | */ | ||
427 | void edac_pci_release_generic_ctl(struct edac_pci_ctl_info *pci) | 486 | void edac_pci_release_generic_ctl(struct edac_pci_ctl_info *pci) |
428 | { | 487 | { |
488 | debugf0("%s() pci mod=%s\n", __func__, pci->mod_name); | ||
489 | |||
429 | edac_pci_del_device(pci->dev); | 490 | edac_pci_del_device(pci->dev); |
430 | edac_pci_free_ctl_info(pci); | 491 | edac_pci_free_ctl_info(pci); |
431 | } | 492 | } |
432 | |||
433 | EXPORT_SYMBOL_GPL(edac_pci_release_generic_ctl); | 493 | EXPORT_SYMBOL_GPL(edac_pci_release_generic_ctl); |
diff --git a/drivers/edac/edac_pci_sysfs.c b/drivers/edac/edac_pci_sysfs.c index fac94cae2c3d..69f5dddabddf 100644 --- a/drivers/edac/edac_pci_sysfs.c +++ b/drivers/edac/edac_pci_sysfs.c | |||
@@ -13,22 +13,25 @@ | |||
13 | #include "edac_core.h" | 13 | #include "edac_core.h" |
14 | #include "edac_module.h" | 14 | #include "edac_module.h" |
15 | 15 | ||
16 | /* Turn off this whole feature if PCI is not configured */ | ||
16 | #ifdef CONFIG_PCI | 17 | #ifdef CONFIG_PCI |
17 | 18 | ||
18 | #define EDAC_PCI_SYMLINK "device" | 19 | #define EDAC_PCI_SYMLINK "device" |
19 | 20 | ||
20 | static int check_pci_errors; /* default YES check PCI parity */ | 21 | /* data variables exported via sysfs */ |
21 | static int edac_pci_panic_on_pe; /* default no panic on PCI Parity */ | 22 | static int check_pci_errors; /* default NO check PCI parity */ |
22 | static int edac_pci_log_pe = 1; /* log PCI parity errors */ | 23 | static int edac_pci_panic_on_pe; /* default NO panic on PCI Parity */ |
24 | static int edac_pci_log_pe = 1; /* log PCI parity errors */ | ||
23 | static int edac_pci_log_npe = 1; /* log PCI non-parity error errors */ | 25 | static int edac_pci_log_npe = 1; /* log PCI non-parity error errors */ |
26 | static int edac_pci_poll_msec = 1000; /* one second workq period */ | ||
27 | |||
24 | static atomic_t pci_parity_count = ATOMIC_INIT(0); | 28 | static atomic_t pci_parity_count = ATOMIC_INIT(0); |
25 | static atomic_t pci_nonparity_count = ATOMIC_INIT(0); | 29 | static atomic_t pci_nonparity_count = ATOMIC_INIT(0); |
26 | static int edac_pci_poll_msec = 1000; | ||
27 | 30 | ||
28 | static struct kobject edac_pci_kobj; /* /sys/devices/system/edac/pci */ | 31 | static struct kobject edac_pci_top_main_kobj; |
29 | static struct completion edac_pci_kobj_complete; | ||
30 | static atomic_t edac_pci_sysfs_refcount = ATOMIC_INIT(0); | 32 | static atomic_t edac_pci_sysfs_refcount = ATOMIC_INIT(0); |
31 | 33 | ||
34 | /* getter functions for the data variables */ | ||
32 | int edac_pci_get_check_errors(void) | 35 | int edac_pci_get_check_errors(void) |
33 | { | 36 | { |
34 | return check_pci_errors; | 37 | return check_pci_errors; |
@@ -74,17 +77,22 @@ static void edac_pci_instance_release(struct kobject *kobj) | |||
74 | { | 77 | { |
75 | struct edac_pci_ctl_info *pci; | 78 | struct edac_pci_ctl_info *pci; |
76 | 79 | ||
77 | debugf1("%s()\n", __func__); | 80 | debugf0("%s()\n", __func__); |
78 | 81 | ||
82 | /* Form pointer to containing struct, the pci control struct */ | ||
79 | pci = to_instance(kobj); | 83 | pci = to_instance(kobj); |
80 | complete(&pci->kobj_complete); | 84 | |
85 | /* decrement reference count on top main kobj */ | ||
86 | kobject_put(&edac_pci_top_main_kobj); | ||
87 | |||
88 | kfree(pci); /* Free the control struct */ | ||
81 | } | 89 | } |
82 | 90 | ||
83 | /* instance specific attribute structure */ | 91 | /* instance specific attribute structure */ |
84 | struct instance_attribute { | 92 | struct instance_attribute { |
85 | struct attribute attr; | 93 | struct attribute attr; |
86 | ssize_t(*show) (struct edac_pci_ctl_info *, char *); | 94 | ssize_t(*show) (struct edac_pci_ctl_info *, char *); |
87 | ssize_t(*store) (struct edac_pci_ctl_info *, const char *, size_t); | 95 | ssize_t(*store) (struct edac_pci_ctl_info *, const char *, size_t); |
88 | }; | 96 | }; |
89 | 97 | ||
90 | /* Function to 'show' fields from the edac_pci 'instance' structure */ | 98 | /* Function to 'show' fields from the edac_pci 'instance' structure */ |
@@ -112,6 +120,7 @@ static ssize_t edac_pci_instance_store(struct kobject *kobj, | |||
112 | return -EIO; | 120 | return -EIO; |
113 | } | 121 | } |
114 | 122 | ||
123 | /* fs_ops table */ | ||
115 | static struct sysfs_ops pci_instance_ops = { | 124 | static struct sysfs_ops pci_instance_ops = { |
116 | .show = edac_pci_instance_show, | 125 | .show = edac_pci_instance_show, |
117 | .store = edac_pci_instance_store | 126 | .store = edac_pci_instance_store |
@@ -134,48 +143,82 @@ static struct instance_attribute *pci_instance_attr[] = { | |||
134 | NULL | 143 | NULL |
135 | }; | 144 | }; |
136 | 145 | ||
137 | /* the ktype for pci instance */ | 146 | /* the ktype for a pci instance */ |
138 | static struct kobj_type ktype_pci_instance = { | 147 | static struct kobj_type ktype_pci_instance = { |
139 | .release = edac_pci_instance_release, | 148 | .release = edac_pci_instance_release, |
140 | .sysfs_ops = &pci_instance_ops, | 149 | .sysfs_ops = &pci_instance_ops, |
141 | .default_attrs = (struct attribute **)pci_instance_attr, | 150 | .default_attrs = (struct attribute **)pci_instance_attr, |
142 | }; | 151 | }; |
143 | 152 | ||
153 | /* | ||
154 | * edac_pci_create_instance_kobj | ||
155 | * | ||
156 | * construct one EDAC PCI instance's kobject for use | ||
157 | */ | ||
144 | static int edac_pci_create_instance_kobj(struct edac_pci_ctl_info *pci, int idx) | 158 | static int edac_pci_create_instance_kobj(struct edac_pci_ctl_info *pci, int idx) |
145 | { | 159 | { |
160 | struct kobject *main_kobj; | ||
146 | int err; | 161 | int err; |
147 | 162 | ||
148 | pci->kobj.parent = &edac_pci_kobj; | 163 | debugf0("%s()\n", __func__); |
164 | |||
165 | /* Set the parent and the instance's ktype */ | ||
166 | pci->kobj.parent = &edac_pci_top_main_kobj; | ||
149 | pci->kobj.ktype = &ktype_pci_instance; | 167 | pci->kobj.ktype = &ktype_pci_instance; |
150 | 168 | ||
151 | err = kobject_set_name(&pci->kobj, "pci%d", idx); | 169 | err = kobject_set_name(&pci->kobj, "pci%d", idx); |
152 | if (err) | 170 | if (err) |
153 | return err; | 171 | return err; |
154 | 172 | ||
173 | /* First bump the ref count on the top main kobj, which will | ||
174 | * track the number of PCI instances we have, and thus nest | ||
175 | * properly on keeping the module loaded | ||
176 | */ | ||
177 | main_kobj = kobject_get(&edac_pci_top_main_kobj); | ||
178 | if (!main_kobj) { | ||
179 | err = -ENODEV; | ||
180 | goto error_out; | ||
181 | } | ||
182 | |||
183 | /* And now register this new kobject under the main kobj */ | ||
155 | err = kobject_register(&pci->kobj); | 184 | err = kobject_register(&pci->kobj); |
156 | if (err != 0) { | 185 | if (err != 0) { |
157 | debugf2("%s() failed to register instance pci%d\n", | 186 | debugf2("%s() failed to register instance pci%d\n", |
158 | __func__, idx); | 187 | __func__, idx); |
159 | return err; | 188 | kobject_put(&edac_pci_top_main_kobj); |
189 | goto error_out; | ||
160 | } | 190 | } |
161 | 191 | ||
162 | debugf1("%s() Register instance 'pci%d' kobject\n", __func__, idx); | 192 | debugf1("%s() Register instance 'pci%d' kobject\n", __func__, idx); |
163 | 193 | ||
164 | return 0; | 194 | return 0; |
195 | |||
196 | /* Error unwind statck */ | ||
197 | error_out: | ||
198 | return err; | ||
165 | } | 199 | } |
166 | 200 | ||
167 | static void | 201 | /* |
168 | edac_pci_delete_instance_kobj(struct edac_pci_ctl_info *pci, int idx) | 202 | * edac_pci_unregister_sysfs_instance_kobj |
203 | * | ||
204 | * unregister the kobj for the EDAC PCI instance | ||
205 | */ | ||
206 | void edac_pci_unregister_sysfs_instance_kobj(struct edac_pci_ctl_info *pci) | ||
169 | { | 207 | { |
170 | init_completion(&pci->kobj_complete); | 208 | debugf0("%s()\n", __func__); |
209 | |||
210 | /* Unregister the instance kobject and allow its release | ||
211 | * function release the main reference count and then | ||
212 | * kfree the memory | ||
213 | */ | ||
171 | kobject_unregister(&pci->kobj); | 214 | kobject_unregister(&pci->kobj); |
172 | wait_for_completion(&pci->kobj_complete); | ||
173 | } | 215 | } |
174 | 216 | ||
175 | /***************************** EDAC PCI sysfs root **********************/ | 217 | /***************************** EDAC PCI sysfs root **********************/ |
176 | #define to_edacpci(k) container_of(k, struct edac_pci_ctl_info, kobj) | 218 | #define to_edacpci(k) container_of(k, struct edac_pci_ctl_info, kobj) |
177 | #define to_edacpci_attr(a) container_of(a, struct edac_pci_attr, attr) | 219 | #define to_edacpci_attr(a) container_of(a, struct edac_pci_attr, attr) |
178 | 220 | ||
221 | /* simple show/store functions for attributes */ | ||
179 | static ssize_t edac_pci_int_show(void *ptr, char *buffer) | 222 | static ssize_t edac_pci_int_show(void *ptr, char *buffer) |
180 | { | 223 | { |
181 | int *value = ptr; | 224 | int *value = ptr; |
@@ -267,118 +310,189 @@ static struct edac_pci_dev_attribute *edac_pci_attr[] = { | |||
267 | NULL, | 310 | NULL, |
268 | }; | 311 | }; |
269 | 312 | ||
270 | /* No memory to release */ | 313 | /* |
271 | static void edac_pci_release(struct kobject *kobj) | 314 | * edac_pci_release_main_kobj |
315 | * | ||
316 | * This release function is called when the reference count to the | ||
317 | * passed kobj goes to zero. | ||
318 | * | ||
319 | * This kobj is the 'main' kobject that EDAC PCI instances | ||
320 | * link to, and thus provide for proper nesting counts | ||
321 | */ | ||
322 | static void edac_pci_release_main_kobj(struct kobject *kobj) | ||
272 | { | 323 | { |
273 | struct edac_pci_ctl_info *pci; | ||
274 | 324 | ||
275 | pci = to_edacpci(kobj); | 325 | debugf0("%s() here to module_put(THIS_MODULE)\n", __func__); |
276 | 326 | ||
277 | debugf1("%s()\n", __func__); | 327 | /* last reference to top EDAC PCI kobject has been removed, |
278 | complete(&pci->kobj_complete); | 328 | * NOW release our ref count on the core module |
329 | */ | ||
330 | module_put(THIS_MODULE); | ||
279 | } | 331 | } |
280 | 332 | ||
281 | static struct kobj_type ktype_edac_pci = { | 333 | /* ktype struct for the EDAC PCI main kobj */ |
282 | .release = edac_pci_release, | 334 | static struct kobj_type ktype_edac_pci_main_kobj = { |
335 | .release = edac_pci_release_main_kobj, | ||
283 | .sysfs_ops = &edac_pci_sysfs_ops, | 336 | .sysfs_ops = &edac_pci_sysfs_ops, |
284 | .default_attrs = (struct attribute **)edac_pci_attr, | 337 | .default_attrs = (struct attribute **)edac_pci_attr, |
285 | }; | 338 | }; |
286 | 339 | ||
287 | /** | 340 | /** |
288 | * edac_sysfs_pci_setup() | 341 | * edac_pci_main_kobj_setup() |
289 | * | 342 | * |
290 | * setup the sysfs for EDAC PCI attributes | 343 | * setup the sysfs for EDAC PCI attributes |
291 | * assumes edac_class has already been initialized | 344 | * assumes edac_class has already been initialized |
292 | */ | 345 | */ |
293 | int edac_pci_register_main_kobj(void) | 346 | int edac_pci_main_kobj_setup(void) |
294 | { | 347 | { |
295 | int err; | 348 | int err; |
296 | struct sysdev_class *edac_class; | 349 | struct sysdev_class *edac_class; |
297 | 350 | ||
298 | debugf1("%s()\n", __func__); | 351 | debugf0("%s()\n", __func__); |
352 | |||
353 | /* check and count if we have already created the main kobject */ | ||
354 | if (atomic_inc_return(&edac_pci_sysfs_refcount) != 1) | ||
355 | return 0; | ||
299 | 356 | ||
357 | /* First time, so create the main kobject and its | ||
358 | * controls and atributes | ||
359 | */ | ||
300 | edac_class = edac_get_edac_class(); | 360 | edac_class = edac_get_edac_class(); |
301 | if (edac_class == NULL) { | 361 | if (edac_class == NULL) { |
302 | debugf1("%s() no edac_class\n", __func__); | 362 | debugf1("%s() no edac_class\n", __func__); |
303 | return -ENODEV; | 363 | err = -ENODEV; |
364 | goto decrement_count_fail; | ||
304 | } | 365 | } |
305 | 366 | ||
306 | edac_pci_kobj.ktype = &ktype_edac_pci; | 367 | /* Need the kobject hook ups, and name setting */ |
368 | edac_pci_top_main_kobj.ktype = &ktype_edac_pci_main_kobj; | ||
369 | edac_pci_top_main_kobj.parent = &edac_class->kset.kobj; | ||
307 | 370 | ||
308 | edac_pci_kobj.parent = &edac_class->kset.kobj; | 371 | err = kobject_set_name(&edac_pci_top_main_kobj, "pci"); |
309 | |||
310 | err = kobject_set_name(&edac_pci_kobj, "pci"); | ||
311 | if (err) | 372 | if (err) |
312 | return err; | 373 | goto decrement_count_fail; |
374 | |||
375 | /* Bump the reference count on this module to ensure the | ||
376 | * modules isn't unloaded until we deconstruct the top | ||
377 | * level main kobj for EDAC PCI | ||
378 | */ | ||
379 | if (!try_module_get(THIS_MODULE)) { | ||
380 | debugf1("%s() try_module_get() failed\n", __func__); | ||
381 | err = -ENODEV; | ||
382 | goto decrement_count_fail; | ||
383 | } | ||
313 | 384 | ||
314 | /* Instanstiate the pci object */ | 385 | /* Instanstiate the pci object */ |
315 | /* FIXME: maybe new sysdev_create_subdir() */ | 386 | /* FIXME: maybe new sysdev_create_subdir() */ |
316 | err = kobject_register(&edac_pci_kobj); | 387 | err = kobject_register(&edac_pci_top_main_kobj); |
317 | |||
318 | if (err) { | 388 | if (err) { |
319 | debugf1("Failed to register '.../edac/pci'\n"); | 389 | debugf1("Failed to register '.../edac/pci'\n"); |
320 | return err; | 390 | goto kobject_register_fail; |
321 | } | 391 | } |
322 | 392 | ||
393 | /* At this point, to 'release' the top level kobject | ||
394 | * for EDAC PCI, then edac_pci_main_kobj_teardown() | ||
395 | * must be used, for resources to be cleaned up properly | ||
396 | */ | ||
323 | debugf1("Registered '.../edac/pci' kobject\n"); | 397 | debugf1("Registered '.../edac/pci' kobject\n"); |
324 | 398 | ||
325 | return 0; | 399 | return 0; |
400 | |||
401 | /* Error unwind statck */ | ||
402 | kobject_register_fail: | ||
403 | module_put(THIS_MODULE); | ||
404 | |||
405 | decrement_count_fail: | ||
406 | /* if are on this error exit, nothing to tear down */ | ||
407 | atomic_dec(&edac_pci_sysfs_refcount); | ||
408 | |||
409 | return err; | ||
326 | } | 410 | } |
327 | 411 | ||
328 | /* | 412 | /* |
329 | * edac_pci_unregister_main_kobj() | 413 | * edac_pci_main_kobj_teardown() |
330 | * | 414 | * |
331 | * perform the sysfs teardown for the PCI attributes | 415 | * if no longer linked (needed) remove the top level EDAC PCI |
416 | * kobject with its controls and attributes | ||
332 | */ | 417 | */ |
333 | void edac_pci_unregister_main_kobj(void) | 418 | static void edac_pci_main_kobj_teardown(void) |
334 | { | 419 | { |
335 | debugf0("%s()\n", __func__); | 420 | debugf0("%s()\n", __func__); |
336 | init_completion(&edac_pci_kobj_complete); | 421 | |
337 | kobject_unregister(&edac_pci_kobj); | 422 | /* Decrement the count and only if no more controller instances |
338 | wait_for_completion(&edac_pci_kobj_complete); | 423 | * are connected perform the unregisteration of the top level |
424 | * main kobj | ||
425 | */ | ||
426 | if (atomic_dec_return(&edac_pci_sysfs_refcount) == 0) { | ||
427 | debugf0("%s() called kobject_unregister on main kobj\n", | ||
428 | __func__); | ||
429 | kobject_unregister(&edac_pci_top_main_kobj); | ||
430 | } | ||
339 | } | 431 | } |
340 | 432 | ||
433 | /* | ||
434 | * | ||
435 | * edac_pci_create_sysfs | ||
436 | * | ||
437 | * Create the controls/attributes for the specified EDAC PCI device | ||
438 | */ | ||
341 | int edac_pci_create_sysfs(struct edac_pci_ctl_info *pci) | 439 | int edac_pci_create_sysfs(struct edac_pci_ctl_info *pci) |
342 | { | 440 | { |
343 | int err; | 441 | int err; |
344 | struct kobject *edac_kobj = &pci->kobj; | 442 | struct kobject *edac_kobj = &pci->kobj; |
345 | 443 | ||
346 | if (atomic_inc_return(&edac_pci_sysfs_refcount) == 1) { | 444 | debugf0("%s() idx=%d\n", __func__, pci->pci_idx); |
347 | err = edac_pci_register_main_kobj(); | ||
348 | if (err) { | ||
349 | atomic_dec(&edac_pci_sysfs_refcount); | ||
350 | return err; | ||
351 | } | ||
352 | } | ||
353 | 445 | ||
354 | err = edac_pci_create_instance_kobj(pci, pci->pci_idx); | 446 | /* create the top main EDAC PCI kobject, IF needed */ |
355 | if (err) { | 447 | err = edac_pci_main_kobj_setup(); |
356 | if (atomic_dec_return(&edac_pci_sysfs_refcount) == 0) | 448 | if (err) |
357 | edac_pci_unregister_main_kobj(); | 449 | return err; |
358 | } | ||
359 | 450 | ||
360 | debugf0("%s() idx=%d\n", __func__, pci->pci_idx); | 451 | /* Create this instance's kobject under the MAIN kobject */ |
452 | err = edac_pci_create_instance_kobj(pci, pci->pci_idx); | ||
453 | if (err) | ||
454 | goto unregister_cleanup; | ||
361 | 455 | ||
362 | err = sysfs_create_link(edac_kobj, &pci->dev->kobj, EDAC_PCI_SYMLINK); | 456 | err = sysfs_create_link(edac_kobj, &pci->dev->kobj, EDAC_PCI_SYMLINK); |
363 | if (err) { | 457 | if (err) { |
364 | debugf0("%s() sysfs_create_link() returned err= %d\n", | 458 | debugf0("%s() sysfs_create_link() returned err= %d\n", |
365 | __func__, err); | 459 | __func__, err); |
366 | return err; | 460 | goto symlink_fail; |
367 | } | 461 | } |
368 | 462 | ||
369 | return 0; | 463 | return 0; |
464 | |||
465 | /* Error unwind stack */ | ||
466 | symlink_fail: | ||
467 | edac_pci_unregister_sysfs_instance_kobj(pci); | ||
468 | |||
469 | unregister_cleanup: | ||
470 | edac_pci_main_kobj_teardown(); | ||
471 | |||
472 | return err; | ||
370 | } | 473 | } |
371 | 474 | ||
475 | /* | ||
476 | * edac_pci_remove_sysfs | ||
477 | * | ||
478 | * remove the controls and attributes for this EDAC PCI device | ||
479 | */ | ||
372 | void edac_pci_remove_sysfs(struct edac_pci_ctl_info *pci) | 480 | void edac_pci_remove_sysfs(struct edac_pci_ctl_info *pci) |
373 | { | 481 | { |
374 | debugf0("%s()\n", __func__); | 482 | debugf0("%s() index=%d\n", __func__, pci->pci_idx); |
375 | |||
376 | edac_pci_delete_instance_kobj(pci, pci->pci_idx); | ||
377 | 483 | ||
484 | /* Remove the symlink */ | ||
378 | sysfs_remove_link(&pci->kobj, EDAC_PCI_SYMLINK); | 485 | sysfs_remove_link(&pci->kobj, EDAC_PCI_SYMLINK); |
379 | 486 | ||
380 | if (atomic_dec_return(&edac_pci_sysfs_refcount) == 0) | 487 | /* remove this PCI instance's sysfs entries */ |
381 | edac_pci_unregister_main_kobj(); | 488 | edac_pci_unregister_sysfs_instance_kobj(pci); |
489 | |||
490 | /* Call the main unregister function, which will determine | ||
491 | * if this 'pci' is the last instance. | ||
492 | * If it is, the main kobject will be unregistered as a result | ||
493 | */ | ||
494 | debugf0("%s() calling edac_pci_main_kobj_teardown()\n", __func__); | ||
495 | edac_pci_main_kobj_teardown(); | ||
382 | } | 496 | } |
383 | 497 | ||
384 | /************************ PCI error handling *************************/ | 498 | /************************ PCI error handling *************************/ |
@@ -414,13 +528,14 @@ static u16 get_pci_parity_status(struct pci_dev *dev, int secondary) | |||
414 | return status; | 528 | return status; |
415 | } | 529 | } |
416 | 530 | ||
417 | typedef void (*pci_parity_check_fn_t) (struct pci_dev * dev); | ||
418 | 531 | ||
419 | /* Clear any PCI parity errors logged by this device. */ | 532 | /* Clear any PCI parity errors logged by this device. */ |
420 | static void edac_pci_dev_parity_clear(struct pci_dev *dev) | 533 | static void edac_pci_dev_parity_clear(struct pci_dev *dev) |
421 | { | 534 | { |
422 | u8 header_type; | 535 | u8 header_type; |
423 | 536 | ||
537 | debugf0("%s()\n", __func__); | ||
538 | |||
424 | get_pci_parity_status(dev, 0); | 539 | get_pci_parity_status(dev, 0); |
425 | 540 | ||
426 | /* read the device TYPE, looking for bridges */ | 541 | /* read the device TYPE, looking for bridges */ |
@@ -433,17 +548,28 @@ static void edac_pci_dev_parity_clear(struct pci_dev *dev) | |||
433 | /* | 548 | /* |
434 | * PCI Parity polling | 549 | * PCI Parity polling |
435 | * | 550 | * |
551 | * Fucntion to retrieve the current parity status | ||
552 | * and decode it | ||
553 | * | ||
436 | */ | 554 | */ |
437 | static void edac_pci_dev_parity_test(struct pci_dev *dev) | 555 | static void edac_pci_dev_parity_test(struct pci_dev *dev) |
438 | { | 556 | { |
557 | unsigned long flags; | ||
439 | u16 status; | 558 | u16 status; |
440 | u8 header_type; | 559 | u8 header_type; |
441 | 560 | ||
442 | /* read the STATUS register on this device | 561 | /* stop any interrupts until we can acquire the status */ |
443 | */ | 562 | local_irq_save(flags); |
563 | |||
564 | /* read the STATUS register on this device */ | ||
444 | status = get_pci_parity_status(dev, 0); | 565 | status = get_pci_parity_status(dev, 0); |
445 | 566 | ||
446 | debugf2("PCI STATUS= 0x%04x %s\n", status, dev->dev.bus_id); | 567 | /* read the device TYPE, looking for bridges */ |
568 | pci_read_config_byte(dev, PCI_HEADER_TYPE, &header_type); | ||
569 | |||
570 | local_irq_restore(flags); | ||
571 | |||
572 | debugf4("PCI STATUS= 0x%04x %s\n", status, dev->dev.bus_id); | ||
447 | 573 | ||
448 | /* check the status reg for errors */ | 574 | /* check the status reg for errors */ |
449 | if (status) { | 575 | if (status) { |
@@ -471,16 +597,14 @@ static void edac_pci_dev_parity_test(struct pci_dev *dev) | |||
471 | } | 597 | } |
472 | } | 598 | } |
473 | 599 | ||
474 | /* read the device TYPE, looking for bridges */ | ||
475 | pci_read_config_byte(dev, PCI_HEADER_TYPE, &header_type); | ||
476 | 600 | ||
477 | debugf2("PCI HEADER TYPE= 0x%02x %s\n", header_type, dev->dev.bus_id); | 601 | debugf4("PCI HEADER TYPE= 0x%02x %s\n", header_type, dev->dev.bus_id); |
478 | 602 | ||
479 | if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { | 603 | if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { |
480 | /* On bridges, need to examine secondary status register */ | 604 | /* On bridges, need to examine secondary status register */ |
481 | status = get_pci_parity_status(dev, 1); | 605 | status = get_pci_parity_status(dev, 1); |
482 | 606 | ||
483 | debugf2("PCI SEC_STATUS= 0x%04x %s\n", status, dev->dev.bus_id); | 607 | debugf4("PCI SEC_STATUS= 0x%04x %s\n", status, dev->dev.bus_id); |
484 | 608 | ||
485 | /* check the secondary status reg for errors */ | 609 | /* check the secondary status reg for errors */ |
486 | if (status) { | 610 | if (status) { |
@@ -510,9 +634,12 @@ static void edac_pci_dev_parity_test(struct pci_dev *dev) | |||
510 | } | 634 | } |
511 | } | 635 | } |
512 | 636 | ||
637 | /* reduce some complexity in definition of the iterator */ | ||
638 | typedef void (*pci_parity_check_fn_t) (struct pci_dev *dev); | ||
639 | |||
513 | /* | 640 | /* |
514 | * pci_dev parity list iterator | 641 | * pci_dev parity list iterator |
515 | * Scan the PCI device list for one iteration, looking for SERRORs | 642 | * Scan the PCI device list for one pass, looking for SERRORs |
516 | * Master Parity ERRORS or Parity ERRORs on primary or secondary devices | 643 | * Master Parity ERRORS or Parity ERRORs on primary or secondary devices |
517 | */ | 644 | */ |
518 | static inline void edac_pci_dev_parity_iterator(pci_parity_check_fn_t fn) | 645 | static inline void edac_pci_dev_parity_iterator(pci_parity_check_fn_t fn) |
@@ -535,22 +662,22 @@ static inline void edac_pci_dev_parity_iterator(pci_parity_check_fn_t fn) | |||
535 | */ | 662 | */ |
536 | void edac_pci_do_parity_check(void) | 663 | void edac_pci_do_parity_check(void) |
537 | { | 664 | { |
538 | unsigned long flags; | ||
539 | int before_count; | 665 | int before_count; |
540 | 666 | ||
541 | debugf3("%s()\n", __func__); | 667 | debugf3("%s()\n", __func__); |
542 | 668 | ||
669 | /* if policy has PCI check off, leave now */ | ||
543 | if (!check_pci_errors) | 670 | if (!check_pci_errors) |
544 | return; | 671 | return; |
545 | 672 | ||
546 | before_count = atomic_read(&pci_parity_count); | 673 | before_count = atomic_read(&pci_parity_count); |
547 | 674 | ||
548 | /* scan all PCI devices looking for a Parity Error on devices and | 675 | /* scan all PCI devices looking for a Parity Error on devices and |
549 | * bridges | 676 | * bridges. |
677 | * The iterator calls pci_get_device() which might sleep, thus | ||
678 | * we cannot disable interrupts in this scan. | ||
550 | */ | 679 | */ |
551 | local_irq_save(flags); | ||
552 | edac_pci_dev_parity_iterator(edac_pci_dev_parity_test); | 680 | edac_pci_dev_parity_iterator(edac_pci_dev_parity_test); |
553 | local_irq_restore(flags); | ||
554 | 681 | ||
555 | /* Only if operator has selected panic on PCI Error */ | 682 | /* Only if operator has selected panic on PCI Error */ |
556 | if (edac_pci_get_panic_on_pe()) { | 683 | if (edac_pci_get_panic_on_pe()) { |
@@ -560,6 +687,12 @@ void edac_pci_do_parity_check(void) | |||
560 | } | 687 | } |
561 | } | 688 | } |
562 | 689 | ||
690 | /* | ||
691 | * edac_pci_clear_parity_errors | ||
692 | * | ||
693 | * function to perform an iteration over the PCI devices | ||
694 | * and clearn their current status | ||
695 | */ | ||
563 | void edac_pci_clear_parity_errors(void) | 696 | void edac_pci_clear_parity_errors(void) |
564 | { | 697 | { |
565 | /* Clear any PCI bus parity errors that devices initially have logged | 698 | /* Clear any PCI bus parity errors that devices initially have logged |
@@ -567,6 +700,12 @@ void edac_pci_clear_parity_errors(void) | |||
567 | */ | 700 | */ |
568 | edac_pci_dev_parity_iterator(edac_pci_dev_parity_clear); | 701 | edac_pci_dev_parity_iterator(edac_pci_dev_parity_clear); |
569 | } | 702 | } |
703 | |||
704 | /* | ||
705 | * edac_pci_handle_pe | ||
706 | * | ||
707 | * Called to handle a PARITY ERROR event | ||
708 | */ | ||
570 | void edac_pci_handle_pe(struct edac_pci_ctl_info *pci, const char *msg) | 709 | void edac_pci_handle_pe(struct edac_pci_ctl_info *pci, const char *msg) |
571 | { | 710 | { |
572 | 711 | ||
@@ -584,9 +723,14 @@ void edac_pci_handle_pe(struct edac_pci_ctl_info *pci, const char *msg) | |||
584 | */ | 723 | */ |
585 | edac_pci_do_parity_check(); | 724 | edac_pci_do_parity_check(); |
586 | } | 725 | } |
587 | |||
588 | EXPORT_SYMBOL_GPL(edac_pci_handle_pe); | 726 | EXPORT_SYMBOL_GPL(edac_pci_handle_pe); |
589 | 727 | ||
728 | |||
729 | /* | ||
730 | * edac_pci_handle_npe | ||
731 | * | ||
732 | * Called to handle a NON-PARITY ERROR event | ||
733 | */ | ||
590 | void edac_pci_handle_npe(struct edac_pci_ctl_info *pci, const char *msg) | 734 | void edac_pci_handle_npe(struct edac_pci_ctl_info *pci, const char *msg) |
591 | { | 735 | { |
592 | 736 | ||
@@ -604,7 +748,6 @@ void edac_pci_handle_npe(struct edac_pci_ctl_info *pci, const char *msg) | |||
604 | */ | 748 | */ |
605 | edac_pci_do_parity_check(); | 749 | edac_pci_do_parity_check(); |
606 | } | 750 | } |
607 | |||
608 | EXPORT_SYMBOL_GPL(edac_pci_handle_npe); | 751 | EXPORT_SYMBOL_GPL(edac_pci_handle_npe); |
609 | 752 | ||
610 | /* | 753 | /* |