Merge tag 'rtc-5.19' of git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux
[linux-2.6-microblaze.git] / drivers / edac / edac_pci.c
1 /*
2  * EDAC PCI component
3  *
4  * Author: Dave Jiang <djiang@mvista.com>
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 <asm/page.h>
13 #include <linux/uaccess.h>
14 #include <linux/ctype.h>
15 #include <linux/highmem.h>
16 #include <linux/init.h>
17 #include <linux/module.h>
18 #include <linux/slab.h>
19 #include <linux/smp.h>
20 #include <linux/spinlock.h>
21 #include <linux/sysctl.h>
22 #include <linux/timer.h>
23
24 #include "edac_pci.h"
25 #include "edac_module.h"
26
27 static DEFINE_MUTEX(edac_pci_ctls_mutex);
28 static LIST_HEAD(edac_pci_list);
29 static atomic_t pci_indexes = ATOMIC_INIT(0);
30
31 struct edac_pci_ctl_info *edac_pci_alloc_ctl_info(unsigned int sz_pvt,
32                                                   const char *edac_pci_name)
33 {
34         struct edac_pci_ctl_info *pci;
35
36         edac_dbg(1, "\n");
37
38         pci = kzalloc(sizeof(struct edac_pci_ctl_info), GFP_KERNEL);
39         if (!pci)
40                 return NULL;
41
42         if (sz_pvt) {
43                 pci->pvt_info = kzalloc(sz_pvt, GFP_KERNEL);
44                 if (!pci->pvt_info)
45                         goto free;
46         }
47
48         pci->op_state = OP_ALLOC;
49
50         snprintf(pci->name, strlen(edac_pci_name) + 1, "%s", edac_pci_name);
51
52         return pci;
53
54 free:
55         kfree(pci);
56         return NULL;
57 }
58 EXPORT_SYMBOL_GPL(edac_pci_alloc_ctl_info);
59
60 void edac_pci_free_ctl_info(struct edac_pci_ctl_info *pci)
61 {
62         edac_dbg(1, "\n");
63
64         edac_pci_remove_sysfs(pci);
65 }
66 EXPORT_SYMBOL_GPL(edac_pci_free_ctl_info);
67
68 /*
69  * find_edac_pci_by_dev()
70  *      scans the edac_pci list for a specific 'struct device *'
71  *
72  *      return NULL if not found, or return control struct pointer
73  */
74 static struct edac_pci_ctl_info *find_edac_pci_by_dev(struct device *dev)
75 {
76         struct edac_pci_ctl_info *pci;
77         struct list_head *item;
78
79         edac_dbg(1, "\n");
80
81         list_for_each(item, &edac_pci_list) {
82                 pci = list_entry(item, struct edac_pci_ctl_info, link);
83
84                 if (pci->dev == dev)
85                         return pci;
86         }
87
88         return NULL;
89 }
90
91 /*
92  * add_edac_pci_to_global_list
93  *      Before calling this function, caller must assign a unique value to
94  *      edac_dev->pci_idx.
95  *      Return:
96  *              0 on success
97  *              1 on failure
98  */
99 static int add_edac_pci_to_global_list(struct edac_pci_ctl_info *pci)
100 {
101         struct list_head *item, *insert_before;
102         struct edac_pci_ctl_info *rover;
103
104         edac_dbg(1, "\n");
105
106         insert_before = &edac_pci_list;
107
108         /* Determine if already on the list */
109         rover = find_edac_pci_by_dev(pci->dev);
110         if (unlikely(rover != NULL))
111                 goto fail0;
112
113         /* Insert in ascending order by 'pci_idx', so find position */
114         list_for_each(item, &edac_pci_list) {
115                 rover = list_entry(item, struct edac_pci_ctl_info, link);
116
117                 if (rover->pci_idx >= pci->pci_idx) {
118                         if (unlikely(rover->pci_idx == pci->pci_idx))
119                                 goto fail1;
120
121                         insert_before = item;
122                         break;
123                 }
124         }
125
126         list_add_tail_rcu(&pci->link, insert_before);
127         return 0;
128
129 fail0:
130         edac_printk(KERN_WARNING, EDAC_PCI,
131                 "%s (%s) %s %s already assigned %d\n",
132                 dev_name(rover->dev), edac_dev_name(rover),
133                 rover->mod_name, rover->ctl_name, rover->pci_idx);
134         return 1;
135
136 fail1:
137         edac_printk(KERN_WARNING, EDAC_PCI,
138                 "but in low-level driver: attempt to assign\n"
139                 "\tduplicate pci_idx %d in %s()\n", rover->pci_idx,
140                 __func__);
141         return 1;
142 }
143
144 /*
145  * del_edac_pci_from_global_list
146  *
147  *      remove the PCI control struct from the global list
148  */
149 static void del_edac_pci_from_global_list(struct edac_pci_ctl_info *pci)
150 {
151         list_del_rcu(&pci->link);
152
153         /* these are for safe removal of devices from global list while
154          * NMI handlers may be traversing list
155          */
156         synchronize_rcu();
157         INIT_LIST_HEAD(&pci->link);
158 }
159
160 /*
161  * edac_pci_workq_function()
162  *
163  *      periodic function that performs the operation
164  *      scheduled by a workq request, for a given PCI control struct
165  */
166 static void edac_pci_workq_function(struct work_struct *work_req)
167 {
168         struct delayed_work *d_work = to_delayed_work(work_req);
169         struct edac_pci_ctl_info *pci = to_edac_pci_ctl_work(d_work);
170         int msec;
171         unsigned long delay;
172
173         edac_dbg(3, "checking\n");
174
175         mutex_lock(&edac_pci_ctls_mutex);
176
177         if (pci->op_state != OP_RUNNING_POLL) {
178                 mutex_unlock(&edac_pci_ctls_mutex);
179                 return;
180         }
181
182         if (edac_pci_get_check_errors())
183                 pci->edac_check(pci);
184
185         /* if we are on a one second period, then use round */
186         msec = edac_pci_get_poll_msec();
187         if (msec == 1000)
188                 delay = round_jiffies_relative(msecs_to_jiffies(msec));
189         else
190                 delay = msecs_to_jiffies(msec);
191
192         edac_queue_work(&pci->work, delay);
193
194         mutex_unlock(&edac_pci_ctls_mutex);
195 }
196
197 int edac_pci_alloc_index(void)
198 {
199         return atomic_inc_return(&pci_indexes) - 1;
200 }
201 EXPORT_SYMBOL_GPL(edac_pci_alloc_index);
202
203 int edac_pci_add_device(struct edac_pci_ctl_info *pci, int edac_idx)
204 {
205         edac_dbg(0, "\n");
206
207         pci->pci_idx = edac_idx;
208         pci->start_time = jiffies;
209
210         mutex_lock(&edac_pci_ctls_mutex);
211
212         if (add_edac_pci_to_global_list(pci))
213                 goto fail0;
214
215         if (edac_pci_create_sysfs(pci)) {
216                 edac_pci_printk(pci, KERN_WARNING,
217                                 "failed to create sysfs pci\n");
218                 goto fail1;
219         }
220
221         if (pci->edac_check) {
222                 pci->op_state = OP_RUNNING_POLL;
223
224                 INIT_DELAYED_WORK(&pci->work, edac_pci_workq_function);
225                 edac_queue_work(&pci->work, msecs_to_jiffies(edac_pci_get_poll_msec()));
226
227         } else {
228                 pci->op_state = OP_RUNNING_INTERRUPT;
229         }
230
231         edac_pci_printk(pci, KERN_INFO,
232                 "Giving out device to module %s controller %s: DEV %s (%s)\n",
233                 pci->mod_name, pci->ctl_name, pci->dev_name,
234                 edac_op_state_to_string(pci->op_state));
235
236         mutex_unlock(&edac_pci_ctls_mutex);
237         return 0;
238
239         /* error unwind stack */
240 fail1:
241         del_edac_pci_from_global_list(pci);
242 fail0:
243         mutex_unlock(&edac_pci_ctls_mutex);
244         return 1;
245 }
246 EXPORT_SYMBOL_GPL(edac_pci_add_device);
247
248 struct edac_pci_ctl_info *edac_pci_del_device(struct device *dev)
249 {
250         struct edac_pci_ctl_info *pci;
251
252         edac_dbg(0, "\n");
253
254         mutex_lock(&edac_pci_ctls_mutex);
255
256         /* ensure the control struct is on the global list
257          * if not, then leave
258          */
259         pci = find_edac_pci_by_dev(dev);
260         if (pci  == NULL) {
261                 mutex_unlock(&edac_pci_ctls_mutex);
262                 return NULL;
263         }
264
265         pci->op_state = OP_OFFLINE;
266
267         del_edac_pci_from_global_list(pci);
268
269         mutex_unlock(&edac_pci_ctls_mutex);
270
271         if (pci->edac_check)
272                 edac_stop_work(&pci->work);
273
274         edac_printk(KERN_INFO, EDAC_PCI,
275                 "Removed device %d for %s %s: DEV %s\n",
276                 pci->pci_idx, pci->mod_name, pci->ctl_name, edac_dev_name(pci));
277
278         return pci;
279 }
280 EXPORT_SYMBOL_GPL(edac_pci_del_device);
281
282 /*
283  * edac_pci_generic_check
284  *
285  *      a Generic parity check API
286  */
287 static void edac_pci_generic_check(struct edac_pci_ctl_info *pci)
288 {
289         edac_dbg(4, "\n");
290         edac_pci_do_parity_check();
291 }
292
293 /* free running instance index counter */
294 static int edac_pci_idx;
295 #define EDAC_PCI_GENCTL_NAME    "EDAC PCI controller"
296
297 struct edac_pci_gen_data {
298         int edac_idx;
299 };
300
301 struct edac_pci_ctl_info *edac_pci_create_generic_ctl(struct device *dev,
302                                                 const char *mod_name)
303 {
304         struct edac_pci_ctl_info *pci;
305         struct edac_pci_gen_data *pdata;
306
307         pci = edac_pci_alloc_ctl_info(sizeof(*pdata), EDAC_PCI_GENCTL_NAME);
308         if (!pci)
309                 return NULL;
310
311         pdata = pci->pvt_info;
312         pci->dev = dev;
313         dev_set_drvdata(pci->dev, pci);
314         pci->dev_name = pci_name(to_pci_dev(dev));
315
316         pci->mod_name = mod_name;
317         pci->ctl_name = EDAC_PCI_GENCTL_NAME;
318         if (edac_op_state == EDAC_OPSTATE_POLL)
319                 pci->edac_check = edac_pci_generic_check;
320
321         pdata->edac_idx = edac_pci_idx++;
322
323         if (edac_pci_add_device(pci, pdata->edac_idx) > 0) {
324                 edac_dbg(3, "failed edac_pci_add_device()\n");
325                 edac_pci_free_ctl_info(pci);
326                 return NULL;
327         }
328
329         return pci;
330 }
331 EXPORT_SYMBOL_GPL(edac_pci_create_generic_ctl);
332
333 void edac_pci_release_generic_ctl(struct edac_pci_ctl_info *pci)
334 {
335         edac_dbg(0, "pci mod=%s\n", pci->mod_name);
336
337         edac_pci_del_device(pci->dev);
338         edac_pci_free_ctl_info(pci);
339 }
340 EXPORT_SYMBOL_GPL(edac_pci_release_generic_ctl);