xref: /openbmc/linux/drivers/edac/edac_pci.c (revision 2cc39179)
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);
341