15 #include <linux/module.h>
16 #include <linux/types.h>
19 #include <linux/sysctl.h>
22 #include <linux/slab.h>
25 #include <linux/list.h>
26 #include <linux/ctype.h>
28 #include <asm/uaccess.h>
40 #ifdef CONFIG_EDAC_DEBUG
43 edac_dbg(3,
"\tedac_dev = %p dev_idx=%d\n",
47 edac_dbg(3,
"\tmod_name:ctl_name = %s:%s\n",
71 char *edac_block_name,
unsigned nr_blocks,
72 unsigned offset_value,
86 edac_dbg(4,
"instances=%d blocks=%d\n", nr_instances, nr_blocks);
106 count = nr_instances * nr_blocks;
124 total_size = ((
unsigned long)pvt) + sz_private;
139 (((
char *)dev_ctl) + ((
unsigned long)dev_inst));
141 (((
char *)dev_ctl) + ((
unsigned long)dev_blk));
143 (((
char *)dev_ctl) + ((
unsigned long)dev_attrib));
144 pvt = sz_private ? (((
char *)dev_ctl) + ((
unsigned long)pvt)) :
NULL;
147 dev_ctl->dev_idx = device_index;
148 dev_ctl->nr_instances = nr_instances;
149 dev_ctl->instances = dev_inst;
150 dev_ctl->pvt_info = pvt;
157 snprintf(dev_ctl->name,
sizeof(dev_ctl->name),
"%s",edac_device_name);
159 edac_dbg(4,
"edac_dev=%p next after end=%p\n",
160 dev_ctl, pvt + sz_private);
163 for (instance = 0; instance < nr_instances; instance++) {
164 inst = &dev_inst[instance];
167 blk_p = &dev_blk[instance * nr_blocks];
172 "%s%u", edac_device_name, instance);
175 for (block = 0; block < nr_blocks; block++) {
179 "%s%d", edac_block_name, block+offset_value);
181 edac_dbg(4,
"instance=%d inst_p=%p block=#%d block_p=%p name='%s'\n",
182 instance, inst, block, blk, blk->
name);
187 if ((nr_attrib == 0) || (attrib_spec ==
NULL))
192 attrib_p = &dev_attrib[block*nr_instances*nr_attrib];
195 edac_dbg(4,
"THIS BLOCK_ATTRIB=%p\n",
203 for (attr = 0; attr < nr_attrib; attr++) {
204 attrib = &attrib_p[
attr];
215 edac_dbg(4,
"alloc-attrib=%p attrib_name='%s' attrib-spec=%p spec-name=%s\n",
216 attrib, attrib->
attr.name,
218 attrib_spec[attr].
attr.name
278 if (edac_dev->
dev == dev)
301 insert_before = &edac_device_list;
304 rover = find_edac_device_by_dev(edac_dev->
dev);
316 insert_before =
item;
321 list_add_tail_rcu(&edac_dev->
link, insert_before);
326 "%s (%s) %s %s already assigned %d\n",
333 "bug in low-level driver: attempt to assign\n"
334 " duplicate dev_idx %d in %s()\n", rover->
dev_idx,
345 list_del_rcu(&edac_device->
link);
351 INIT_LIST_HEAD(&edac_device->
link);
366 static void edac_device_workq_function(
struct work_struct *work_req)
368 struct delayed_work *d_work = to_delayed_work(work_req);
498 #ifdef CONFIG_EDAC_DEBUG
499 if (edac_debug_level >= 3)
500 edac_device_dump_device(edac_dev);
504 if (add_edac_dev_to_global_list(edac_dev))
513 "failed to create sysfs device\n");
533 "Giving out device to module '%s' controller "
534 "'%s': DEV '%s' (%s)\n",
545 del_edac_device_from_global_list(edac_dev);
575 edac_dev = find_edac_device_by_dev(dev);
576 if (edac_dev ==
NULL) {
585 del_edac_device_from_global_list(edac_dev);
596 "Removed device %d for %s %s: DEV %s\n",
625 int inst_nr,
int block_nr,
const char *
msg)
630 if ((inst_nr >= edac_dev->
nr_instances) || (inst_nr < 0)) {
632 "INTERNAL ERROR: 'instance' out of range "
633 "(%d >= %d)\n", inst_nr,
638 instance = edac_dev->
instances + inst_nr;
640 if ((block_nr >= instance->
nr_blocks) || (block_nr < 0)) {
642 "INTERNAL ERROR: instance %d 'block' "
643 "out of range (%d >= %d)\n",
650 block = instance->
blocks + block_nr;
658 if (edac_device_get_log_ce(edac_dev))
660 "CE: %s instance: %s block: %s '%s'\n",
662 block ? block->
name :
"N/A", msg);
671 int inst_nr,
int block_nr,
const char *
msg)
676 if ((inst_nr >= edac_dev->
nr_instances) || (inst_nr < 0)) {
678 "INTERNAL ERROR: 'instance' out of range "
679 "(%d >= %d)\n", inst_nr,
684 instance = edac_dev->
instances + inst_nr;
686 if ((block_nr >= instance->
nr_blocks) || (block_nr < 0)) {
688 "INTERNAL ERROR: instance %d 'block' "
689 "out of range (%d >= %d)\n",
696 block = instance->
blocks + block_nr;
704 if (edac_device_get_log_ue(edac_dev))
706 "UE: %s instance: %s block: %s '%s'\n",
708 block ? block->
name :
"N/A", msg);
710 if (edac_device_get_panic_on_ue(edac_dev))
711 panic(
"EDAC %s: UE instance: %s block %s '%s'\n",
713 block ? block->
name :
"N/A", msg);