1 // SPDX-License-Identifier: GPL-2.0-only
5 * Author: Dave Jiang <djiang@mvista.com>
7 * 2007 (c) MontaVista Software, Inc.
10 #include <linux/uaccess.h>
11 #include <linux/ctype.h>
12 #include <linux/highmem.h>
13 #include <linux/init.h>
14 #include <linux/module.h>
15 #include <linux/slab.h>
16 #include <linux/smp.h>
17 #include <linux/spinlock.h>
18 #include <linux/sysctl.h>
19 #include <linux/timer.h>
22 #include "edac_module.h"
24 static DEFINE_MUTEX(edac_pci_ctls_mutex
);
25 static LIST_HEAD(edac_pci_list
);
26 static atomic_t pci_indexes
= ATOMIC_INIT(0);
28 struct edac_pci_ctl_info
*edac_pci_alloc_ctl_info(unsigned int sz_pvt
,
29 const char *edac_pci_name
)
31 struct edac_pci_ctl_info
*pci
;
35 pci
= kzalloc(sizeof(struct edac_pci_ctl_info
), GFP_KERNEL
);
40 pci
->pvt_info
= kzalloc(sz_pvt
, GFP_KERNEL
);
45 pci
->op_state
= OP_ALLOC
;
47 snprintf(pci
->name
, strlen(edac_pci_name
) + 1, "%s", edac_pci_name
);
55 EXPORT_SYMBOL_GPL(edac_pci_alloc_ctl_info
);
57 void edac_pci_free_ctl_info(struct edac_pci_ctl_info
*pci
)
61 edac_pci_remove_sysfs(pci
);
63 EXPORT_SYMBOL_GPL(edac_pci_free_ctl_info
);
66 * find_edac_pci_by_dev()
67 * scans the edac_pci list for a specific 'struct device *'
69 * return NULL if not found, or return control struct pointer
71 static struct edac_pci_ctl_info
*find_edac_pci_by_dev(struct device
*dev
)
73 struct edac_pci_ctl_info
*pci
;
74 struct list_head
*item
;
78 list_for_each(item
, &edac_pci_list
) {
79 pci
= list_entry(item
, struct edac_pci_ctl_info
, link
);
89 * add_edac_pci_to_global_list
90 * Before calling this function, caller must assign a unique value to
96 static int add_edac_pci_to_global_list(struct edac_pci_ctl_info
*pci
)
98 struct list_head
*item
, *insert_before
;
99 struct edac_pci_ctl_info
*rover
;
103 insert_before
= &edac_pci_list
;
105 /* Determine if already on the list */
106 rover
= find_edac_pci_by_dev(pci
->dev
);
107 if (unlikely(rover
!= NULL
))
110 /* Insert in ascending order by 'pci_idx', so find position */
111 list_for_each(item
, &edac_pci_list
) {
112 rover
= list_entry(item
, struct edac_pci_ctl_info
, link
);
114 if (rover
->pci_idx
>= pci
->pci_idx
) {
115 if (unlikely(rover
->pci_idx
== pci
->pci_idx
))
118 insert_before
= item
;
123 list_add_tail_rcu(&pci
->link
, insert_before
);
127 edac_printk(KERN_WARNING
, EDAC_PCI
,
128 "%s (%s) %s %s already assigned %d\n",
129 dev_name(rover
->dev
), edac_dev_name(rover
),
130 rover
->mod_name
, rover
->ctl_name
, rover
->pci_idx
);
134 edac_printk(KERN_WARNING
, EDAC_PCI
,
135 "but in low-level driver: attempt to assign\n"
136 "\tduplicate pci_idx %d in %s()\n", rover
->pci_idx
,
142 * del_edac_pci_from_global_list
144 * remove the PCI control struct from the global list
146 static void del_edac_pci_from_global_list(struct edac_pci_ctl_info
*pci
)
148 list_del_rcu(&pci
->link
);
150 /* these are for safe removal of devices from global list while
151 * NMI handlers may be traversing list
154 INIT_LIST_HEAD(&pci
->link
);
158 * edac_pci_workq_function()
160 * periodic function that performs the operation
161 * scheduled by a workq request, for a given PCI control struct
163 static void edac_pci_workq_function(struct work_struct
*work_req
)
165 struct delayed_work
*d_work
= to_delayed_work(work_req
);
166 struct edac_pci_ctl_info
*pci
= to_edac_pci_ctl_work(d_work
);
170 edac_dbg(3, "checking\n");
172 mutex_lock(&edac_pci_ctls_mutex
);
174 if (pci
->op_state
!= OP_RUNNING_POLL
) {
175 mutex_unlock(&edac_pci_ctls_mutex
);
179 if (edac_pci_get_check_errors())
180 pci
->edac_check(pci
);
182 /* if we are on a one second period, then use round */
183 msec
= edac_pci_get_poll_msec();
185 delay
= round_jiffies_relative(msecs_to_jiffies(msec
));
187 delay
= msecs_to_jiffies(msec
);
189 edac_queue_work(&pci
->work
, delay
);
191 mutex_unlock(&edac_pci_ctls_mutex
);
194 int edac_pci_alloc_index(void)
196 return atomic_inc_return(&pci_indexes
) - 1;
198 EXPORT_SYMBOL_GPL(edac_pci_alloc_index
);
200 int edac_pci_add_device(struct edac_pci_ctl_info
*pci
, int edac_idx
)
204 pci
->pci_idx
= edac_idx
;
205 pci
->start_time
= jiffies
;
207 mutex_lock(&edac_pci_ctls_mutex
);
209 if (add_edac_pci_to_global_list(pci
))
212 if (edac_pci_create_sysfs(pci
)) {
213 edac_pci_printk(pci
, KERN_WARNING
,
214 "failed to create sysfs pci\n");
218 if (pci
->edac_check
) {
219 pci
->op_state
= OP_RUNNING_POLL
;
221 INIT_DELAYED_WORK(&pci
->work
, edac_pci_workq_function
);
222 edac_queue_work(&pci
->work
, msecs_to_jiffies(edac_pci_get_poll_msec()));
225 pci
->op_state
= OP_RUNNING_INTERRUPT
;
228 edac_pci_printk(pci
, KERN_INFO
,
229 "Giving out device to module %s controller %s: DEV %s (%s)\n",
230 pci
->mod_name
, pci
->ctl_name
, pci
->dev_name
,
231 edac_op_state_to_string(pci
->op_state
));
233 mutex_unlock(&edac_pci_ctls_mutex
);
236 /* error unwind stack */
238 del_edac_pci_from_global_list(pci
);
240 mutex_unlock(&edac_pci_ctls_mutex
);
243 EXPORT_SYMBOL_GPL(edac_pci_add_device
);
245 struct edac_pci_ctl_info
*edac_pci_del_device(struct device
*dev
)
247 struct edac_pci_ctl_info
*pci
;
251 mutex_lock(&edac_pci_ctls_mutex
);
253 /* ensure the control struct is on the global list
256 pci
= find_edac_pci_by_dev(dev
);
258 mutex_unlock(&edac_pci_ctls_mutex
);
262 pci
->op_state
= OP_OFFLINE
;
264 del_edac_pci_from_global_list(pci
);
266 mutex_unlock(&edac_pci_ctls_mutex
);
269 edac_stop_work(&pci
->work
);
271 edac_printk(KERN_INFO
, EDAC_PCI
,
272 "Removed device %d for %s %s: DEV %s\n",
273 pci
->pci_idx
, pci
->mod_name
, pci
->ctl_name
, edac_dev_name(pci
));
277 EXPORT_SYMBOL_GPL(edac_pci_del_device
);
280 * edac_pci_generic_check
282 * a Generic parity check API
284 static void edac_pci_generic_check(struct edac_pci_ctl_info
*pci
)
287 edac_pci_do_parity_check();
290 /* free running instance index counter */
291 static int edac_pci_idx
;
292 #define EDAC_PCI_GENCTL_NAME "EDAC PCI controller"
294 struct edac_pci_gen_data
{
298 struct edac_pci_ctl_info
*edac_pci_create_generic_ctl(struct device
*dev
,
299 const char *mod_name
)
301 struct edac_pci_ctl_info
*pci
;
302 struct edac_pci_gen_data
*pdata
;
304 pci
= edac_pci_alloc_ctl_info(sizeof(*pdata
), EDAC_PCI_GENCTL_NAME
);
308 pdata
= pci
->pvt_info
;
310 dev_set_drvdata(pci
->dev
, pci
);
311 pci
->dev_name
= pci_name(to_pci_dev(dev
));
313 pci
->mod_name
= mod_name
;
314 pci
->ctl_name
= EDAC_PCI_GENCTL_NAME
;
315 if (edac_op_state
== EDAC_OPSTATE_POLL
)
316 pci
->edac_check
= edac_pci_generic_check
;
318 pdata
->edac_idx
= edac_pci_idx
++;
320 if (edac_pci_add_device(pci
, pdata
->edac_idx
) > 0) {
321 edac_dbg(3, "failed edac_pci_add_device()\n");
322 edac_pci_free_ctl_info(pci
);
328 EXPORT_SYMBOL_GPL(edac_pci_create_generic_ctl
);
330 void edac_pci_release_generic_ctl(struct edac_pci_ctl_info
*pci
)
332 edac_dbg(0, "pci mod=%s\n", pci
->mod_name
);
334 edac_pci_del_device(pci
->dev
);
335 edac_pci_free_ctl_info(pci
);
337 EXPORT_SYMBOL_GPL(edac_pci_release_generic_ctl
);