Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/drivers/edac/edac_pci.c
15109 views
1
/*
2
* EDAC PCI component
3
*
4
* Author: Dave Jiang <[email protected]>
5
*
6
* 2007 (c) MontaVista Software, Inc. This file is licensed under
7
* the terms of the GNU General Public License version 2. This program
8
* is licensed "as is" without any warranty of any kind, whether express
9
* or implied.
10
*
11
*/
12
#include <linux/module.h>
13
#include <linux/types.h>
14
#include <linux/smp.h>
15
#include <linux/init.h>
16
#include <linux/sysctl.h>
17
#include <linux/highmem.h>
18
#include <linux/timer.h>
19
#include <linux/slab.h>
20
#include <linux/spinlock.h>
21
#include <linux/list.h>
22
#include <linux/sysdev.h>
23
#include <linux/ctype.h>
24
#include <linux/workqueue.h>
25
#include <asm/uaccess.h>
26
#include <asm/page.h>
27
28
#include "edac_core.h"
29
#include "edac_module.h"
30
31
static DEFINE_MUTEX(edac_pci_ctls_mutex);
32
static LIST_HEAD(edac_pci_list);
33
static atomic_t pci_indexes = ATOMIC_INIT(0);
34
35
/*
36
* edac_pci_alloc_ctl_info
37
*
38
* The alloc() function for the 'edac_pci' control info
39
* structure. The chip driver will allocate one of these for each
40
* edac_pci it is going to control/register with the EDAC CORE.
41
*/
42
struct edac_pci_ctl_info *edac_pci_alloc_ctl_info(unsigned int sz_pvt,
43
const char *edac_pci_name)
44
{
45
struct edac_pci_ctl_info *pci;
46
void *pvt;
47
unsigned int size;
48
49
debugf1("%s()\n", __func__);
50
51
pci = (struct edac_pci_ctl_info *)0;
52
pvt = edac_align_ptr(&pci[1], sz_pvt);
53
size = ((unsigned long)pvt) + sz_pvt;
54
55
/* Alloc the needed control struct memory */
56
pci = kzalloc(size, GFP_KERNEL);
57
if (pci == NULL)
58
return NULL;
59
60
/* Now much private space */
61
pvt = sz_pvt ? ((char *)pci) + ((unsigned long)pvt) : NULL;
62
63
pci->pvt_info = pvt;
64
pci->op_state = OP_ALLOC;
65
66
snprintf(pci->name, strlen(edac_pci_name) + 1, "%s", edac_pci_name);
67
68
return pci;
69
}
70
EXPORT_SYMBOL_GPL(edac_pci_alloc_ctl_info);
71
72
/*
73
* edac_pci_free_ctl_info()
74
*
75
* Last action on the pci control structure.
76
*
77
* call the remove sysfs information, which will unregister
78
* this control struct's kobj. When that kobj's ref count
79
* goes to zero, its release function will be call and then
80
* kfree() the memory.
81
*/
82
void edac_pci_free_ctl_info(struct edac_pci_ctl_info *pci)
83
{
84
debugf1("%s()\n", __func__);
85
86
edac_pci_remove_sysfs(pci);
87
}
88
EXPORT_SYMBOL_GPL(edac_pci_free_ctl_info);
89
90
/*
91
* find_edac_pci_by_dev()
92
* scans the edac_pci list for a specific 'struct device *'
93
*
94
* return NULL if not found, or return control struct pointer
95
*/
96
static struct edac_pci_ctl_info *find_edac_pci_by_dev(struct device *dev)
97
{
98
struct edac_pci_ctl_info *pci;
99
struct list_head *item;
100
101
debugf1("%s()\n", __func__);
102
103
list_for_each(item, &edac_pci_list) {
104
pci = list_entry(item, struct edac_pci_ctl_info, link);
105
106
if (pci->dev == dev)
107
return pci;
108
}
109
110
return NULL;
111
}
112
113
/*
114
* add_edac_pci_to_global_list
115
* Before calling this function, caller must assign a unique value to
116
* edac_dev->pci_idx.
117
* Return:
118
* 0 on success
119
* 1 on failure
120
*/
121
static int add_edac_pci_to_global_list(struct edac_pci_ctl_info *pci)
122
{
123
struct list_head *item, *insert_before;
124
struct edac_pci_ctl_info *rover;
125
126
debugf1("%s()\n", __func__);
127
128
insert_before = &edac_pci_list;
129
130
/* Determine if already on the list */
131
rover = find_edac_pci_by_dev(pci->dev);
132
if (unlikely(rover != NULL))
133
goto fail0;
134
135
/* Insert in ascending order by 'pci_idx', so find position */
136
list_for_each(item, &edac_pci_list) {
137
rover = list_entry(item, struct edac_pci_ctl_info, link);
138
139
if (rover->pci_idx >= pci->pci_idx) {
140
if (unlikely(rover->pci_idx == pci->pci_idx))
141
goto fail1;
142
143
insert_before = item;
144
break;
145
}
146
}
147
148
list_add_tail_rcu(&pci->link, insert_before);
149
return 0;
150
151
fail0:
152
edac_printk(KERN_WARNING, EDAC_PCI,
153
"%s (%s) %s %s already assigned %d\n",
154
dev_name(rover->dev), edac_dev_name(rover),
155
rover->mod_name, rover->ctl_name, rover->pci_idx);
156
return 1;
157
158
fail1:
159
edac_printk(KERN_WARNING, EDAC_PCI,
160
"but in low-level driver: attempt to assign\n"
161
"\tduplicate pci_idx %d in %s()\n", rover->pci_idx,
162
__func__);
163
return 1;
164
}
165
166
/*
167
* del_edac_pci_from_global_list
168
*
169
* remove the PCI control struct from the global list
170
*/
171
static void del_edac_pci_from_global_list(struct edac_pci_ctl_info *pci)
172
{
173
list_del_rcu(&pci->link);
174
175
/* these are for safe removal of devices from global list while
176
* NMI handlers may be traversing list
177
*/
178
synchronize_rcu();
179
INIT_LIST_HEAD(&pci->link);
180
}
181
182
#if 0
183
/* Older code, but might use in the future */
184
185
/*
186
* edac_pci_find()
187
* Search for an edac_pci_ctl_info structure whose index is 'idx'
188
*
189
* If found, return a pointer to the structure
190
* Else return NULL.
191
*
192
* Caller must hold pci_ctls_mutex.
193
*/
194
struct edac_pci_ctl_info *edac_pci_find(int idx)
195
{
196
struct list_head *item;
197
struct edac_pci_ctl_info *pci;
198
199
/* Iterage over list, looking for exact match of ID */
200
list_for_each(item, &edac_pci_list) {
201
pci = list_entry(item, struct edac_pci_ctl_info, link);
202
203
if (pci->pci_idx >= idx) {
204
if (pci->pci_idx == idx)
205
return pci;
206
207
/* not on list, so terminate early */
208
break;
209
}
210
}
211
212
return NULL;
213
}
214
EXPORT_SYMBOL_GPL(edac_pci_find);
215
#endif
216
217
/*
218
* edac_pci_workq_function()
219
*
220
* periodic function that performs the operation
221
* scheduled by a workq request, for a given PCI control struct
222
*/
223
static void edac_pci_workq_function(struct work_struct *work_req)
224
{
225
struct delayed_work *d_work = to_delayed_work(work_req);
226
struct edac_pci_ctl_info *pci = to_edac_pci_ctl_work(d_work);
227
int msec;
228
unsigned long delay;
229
230
debugf3("%s() checking\n", __func__);
231
232
mutex_lock(&edac_pci_ctls_mutex);
233
234
if (pci->op_state == OP_RUNNING_POLL) {
235
/* we might be in POLL mode, but there may NOT be a poll func
236
*/
237
if ((pci->edac_check != NULL) && edac_pci_get_check_errors())
238
pci->edac_check(pci);
239
240
/* if we are on a one second period, then use round */
241
msec = edac_pci_get_poll_msec();
242
if (msec == 1000)
243
delay = round_jiffies_relative(msecs_to_jiffies(msec));
244
else
245
delay = msecs_to_jiffies(msec);
246
247
/* Reschedule only if we are in POLL mode */
248
queue_delayed_work(edac_workqueue, &pci->work, delay);
249
}
250
251
mutex_unlock(&edac_pci_ctls_mutex);
252
}
253
254
/*
255
* edac_pci_workq_setup()
256
* initialize a workq item for this edac_pci instance
257
* passing in the new delay period in msec
258
*
259
* locking model:
260
* called when 'edac_pci_ctls_mutex' is locked
261
*/
262
static void edac_pci_workq_setup(struct edac_pci_ctl_info *pci,
263
unsigned int msec)
264
{
265
debugf0("%s()\n", __func__);
266
267
INIT_DELAYED_WORK(&pci->work, edac_pci_workq_function);
268
queue_delayed_work(edac_workqueue, &pci->work,
269
msecs_to_jiffies(edac_pci_get_poll_msec()));
270
}
271
272
/*
273
* edac_pci_workq_teardown()
274
* stop the workq processing on this edac_pci instance
275
*/
276
static void edac_pci_workq_teardown(struct edac_pci_ctl_info *pci)
277
{
278
int status;
279
280
debugf0("%s()\n", __func__);
281
282
status = cancel_delayed_work(&pci->work);
283
if (status == 0)
284
flush_workqueue(edac_workqueue);
285
}
286
287
/*
288
* edac_pci_reset_delay_period
289
*
290
* called with a new period value for the workq period
291
* a) stop current workq timer
292
* b) restart workq timer with new value
293
*/
294
void edac_pci_reset_delay_period(struct edac_pci_ctl_info *pci,
295
unsigned long value)
296
{
297
debugf0("%s()\n", __func__);
298
299
edac_pci_workq_teardown(pci);
300
301
/* need to lock for the setup */
302
mutex_lock(&edac_pci_ctls_mutex);
303
304
edac_pci_workq_setup(pci, value);
305
306
mutex_unlock(&edac_pci_ctls_mutex);
307
}
308
EXPORT_SYMBOL_GPL(edac_pci_reset_delay_period);
309
310
/*
311
* edac_pci_alloc_index: Allocate a unique PCI index number
312
*
313
* Return:
314
* allocated index number
315
*
316
*/
317
int edac_pci_alloc_index(void)
318
{
319
return atomic_inc_return(&pci_indexes) - 1;
320
}
321
EXPORT_SYMBOL_GPL(edac_pci_alloc_index);
322
323
/*
324
* edac_pci_add_device: Insert the 'edac_dev' structure into the
325
* edac_pci global list and create sysfs entries associated with
326
* edac_pci structure.
327
* @pci: pointer to the edac_device structure to be added to the list
328
* @edac_idx: A unique numeric identifier to be assigned to the
329
* 'edac_pci' structure.
330
*
331
* Return:
332
* 0 Success
333
* !0 Failure
334
*/
335
int edac_pci_add_device(struct edac_pci_ctl_info *pci, int edac_idx)
336
{
337
debugf0("%s()\n", __func__);
338
339
pci->pci_idx = edac_idx;
340
pci->start_time = jiffies;
341
342
mutex_lock(&edac_pci_ctls_mutex);
343
344
if (add_edac_pci_to_global_list(pci))
345
goto fail0;
346
347
if (edac_pci_create_sysfs(pci)) {
348
edac_pci_printk(pci, KERN_WARNING,
349
"failed to create sysfs pci\n");
350
goto fail1;
351
}
352
353
if (pci->edac_check != NULL) {
354
pci->op_state = OP_RUNNING_POLL;
355
356
edac_pci_workq_setup(pci, 1000);
357
} else {
358
pci->op_state = OP_RUNNING_INTERRUPT;
359
}
360
361
edac_pci_printk(pci, KERN_INFO,
362
"Giving out device to module '%s' controller '%s':"
363
" DEV '%s' (%s)\n",
364
pci->mod_name,
365
pci->ctl_name,
366
edac_dev_name(pci), edac_op_state_to_string(pci->op_state));
367
368
mutex_unlock(&edac_pci_ctls_mutex);
369
return 0;
370
371
/* error unwind stack */
372
fail1:
373
del_edac_pci_from_global_list(pci);
374
fail0:
375
mutex_unlock(&edac_pci_ctls_mutex);
376
return 1;
377
}
378
EXPORT_SYMBOL_GPL(edac_pci_add_device);
379
380
/*
381
* edac_pci_del_device()
382
* Remove sysfs entries for specified edac_pci structure and
383
* then remove edac_pci structure from global list
384
*
385
* @dev:
386
* Pointer to 'struct device' representing edac_pci structure
387
* to remove
388
*
389
* Return:
390
* Pointer to removed edac_pci structure,
391
* or NULL if device not found
392
*/
393
struct edac_pci_ctl_info *edac_pci_del_device(struct device *dev)
394
{
395
struct edac_pci_ctl_info *pci;
396
397
debugf0("%s()\n", __func__);
398
399
mutex_lock(&edac_pci_ctls_mutex);
400
401
/* ensure the control struct is on the global list
402
* if not, then leave
403
*/
404
pci = find_edac_pci_by_dev(dev);
405
if (pci == NULL) {
406
mutex_unlock(&edac_pci_ctls_mutex);
407
return NULL;
408
}
409
410
pci->op_state = OP_OFFLINE;
411
412
del_edac_pci_from_global_list(pci);
413
414
mutex_unlock(&edac_pci_ctls_mutex);
415
416
/* stop the workq timer */
417
edac_pci_workq_teardown(pci);
418
419
edac_printk(KERN_INFO, EDAC_PCI,
420
"Removed device %d for %s %s: DEV %s\n",
421
pci->pci_idx, pci->mod_name, pci->ctl_name, edac_dev_name(pci));
422
423
return pci;
424
}
425
EXPORT_SYMBOL_GPL(edac_pci_del_device);
426
427
/*
428
* edac_pci_generic_check
429
*
430
* a Generic parity check API
431
*/
432
static void edac_pci_generic_check(struct edac_pci_ctl_info *pci)
433
{
434
debugf4("%s()\n", __func__);
435
edac_pci_do_parity_check();
436
}
437
438
/* free running instance index counter */
439
static int edac_pci_idx;
440
#define EDAC_PCI_GENCTL_NAME "EDAC PCI controller"
441
442
struct edac_pci_gen_data {
443
int edac_idx;
444
};
445
446
/*
447
* edac_pci_create_generic_ctl
448
*
449
* A generic constructor for a PCI parity polling device
450
* Some systems have more than one domain of PCI busses.
451
* For systems with one domain, then this API will
452
* provide for a generic poller.
453
*
454
* This routine calls the edac_pci_alloc_ctl_info() for
455
* the generic device, with default values
456
*/
457
struct edac_pci_ctl_info *edac_pci_create_generic_ctl(struct device *dev,
458
const char *mod_name)
459
{
460
struct edac_pci_ctl_info *pci;
461
struct edac_pci_gen_data *pdata;
462
463
pci = edac_pci_alloc_ctl_info(sizeof(*pdata), EDAC_PCI_GENCTL_NAME);
464
if (!pci)
465
return NULL;
466
467
pdata = pci->pvt_info;
468
pci->dev = dev;
469
dev_set_drvdata(pci->dev, pci);
470
pci->dev_name = pci_name(to_pci_dev(dev));
471
472
pci->mod_name = mod_name;
473
pci->ctl_name = EDAC_PCI_GENCTL_NAME;
474
pci->edac_check = edac_pci_generic_check;
475
476
pdata->edac_idx = edac_pci_idx++;
477
478
if (edac_pci_add_device(pci, pdata->edac_idx) > 0) {
479
debugf3("%s(): failed edac_pci_add_device()\n", __func__);
480
edac_pci_free_ctl_info(pci);
481
return NULL;
482
}
483
484
return pci;
485
}
486
EXPORT_SYMBOL_GPL(edac_pci_create_generic_ctl);
487
488
/*
489
* edac_pci_release_generic_ctl
490
*
491
* The release function of a generic EDAC PCI polling device
492
*/
493
void edac_pci_release_generic_ctl(struct edac_pci_ctl_info *pci)
494
{
495
debugf0("%s() pci mod=%s\n", __func__, pci->mod_name);
496
497
edac_pci_del_device(pci->dev);
498
edac_pci_free_ctl_info(pci);
499
}
500
EXPORT_SYMBOL_GPL(edac_pci_release_generic_ctl);
501
502