Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  * edac_device.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  * (C) 2007 www.douglaskthompson.com
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  * This file may be distributed under the terms of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7)  * GNU General Public License.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9)  * Written by Doug Thompson <norsk5@xmission.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11)  * edac_device API implementation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12)  * 19 Jan 2007
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) #include <asm/page.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) #include <linux/ctype.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) #include <linux/highmem.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) #include <linux/jiffies.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) #include <linux/smp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) #include <linux/spinlock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) #include <linux/sysctl.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) #include <linux/timer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) #include "edac_device.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) #include "edac_module.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) /* lock for the list: 'edac_device_list', manipulation of this list
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32)  * is protected by the 'device_ctls_mutex' lock
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) static DEFINE_MUTEX(device_ctls_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) static LIST_HEAD(edac_device_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) #ifdef CONFIG_EDAC_DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) static void edac_device_dump_device(struct edac_device_ctl_info *edac_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 	edac_dbg(3, "\tedac_dev = %p dev_idx=%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 		 edac_dev, edac_dev->dev_idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 	edac_dbg(4, "\tedac_dev->edac_check = %p\n", edac_dev->edac_check);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 	edac_dbg(3, "\tdev = %p\n", edac_dev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 	edac_dbg(3, "\tmod_name:ctl_name = %s:%s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 		 edac_dev->mod_name, edac_dev->ctl_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 	edac_dbg(3, "\tpvt_info = %p\n\n", edac_dev->pvt_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) #endif				/* CONFIG_EDAC_DEBUG */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) struct edac_device_ctl_info *edac_device_alloc_ctl_info(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 	unsigned sz_private,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 	char *edac_device_name, unsigned nr_instances,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 	char *edac_block_name, unsigned nr_blocks,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 	unsigned offset_value,		/* zero, 1, or other based offset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 	struct edac_dev_sysfs_block_attribute *attrib_spec, unsigned nr_attrib,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 	int device_index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 	struct edac_device_ctl_info *dev_ctl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 	struct edac_device_instance *dev_inst, *inst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 	struct edac_device_block *dev_blk, *blk_p, *blk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 	struct edac_dev_sysfs_block_attribute *dev_attrib, *attrib_p, *attrib;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 	unsigned total_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 	unsigned count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 	unsigned instance, block, attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 	void *pvt, *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 	int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 	edac_dbg(4, "instances=%d blocks=%d\n", nr_instances, nr_blocks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 	/* Calculate the size of memory we need to allocate AND
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 	 * determine the offsets of the various item arrays
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 	 * (instance,block,attrib) from the start of an  allocated structure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 	 * We want the alignment of each item  (instance,block,attrib)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 	 * to be at least as stringent as what the compiler would
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 	 * provide if we could simply hardcode everything into a single struct.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 	p = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 	dev_ctl = edac_align_ptr(&p, sizeof(*dev_ctl), 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 	/* Calc the 'end' offset past end of ONE ctl_info structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 	 * which will become the start of the 'instance' array
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 	dev_inst = edac_align_ptr(&p, sizeof(*dev_inst), nr_instances);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 	/* Calc the 'end' offset past the instance array within the ctl_info
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 	 * which will become the start of the block array
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 	count = nr_instances * nr_blocks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 	dev_blk = edac_align_ptr(&p, sizeof(*dev_blk), count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 	/* Calc the 'end' offset past the dev_blk array
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 	 * which will become the start of the attrib array, if any.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 	/* calc how many nr_attrib we need */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 	if (nr_attrib > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 		count *= nr_attrib;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 	dev_attrib = edac_align_ptr(&p, sizeof(*dev_attrib), count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 	/* Calc the 'end' offset past the attributes array */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 	pvt = edac_align_ptr(&p, sz_private, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 	/* 'pvt' now points to where the private data area is.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 	 * At this point 'pvt' (like dev_inst,dev_blk and dev_attrib)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 	 * is baselined at ZERO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 	total_size = ((unsigned long)pvt) + sz_private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 	/* Allocate the amount of memory for the set of control structures */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 	dev_ctl = kzalloc(total_size, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 	if (dev_ctl == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 		return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 	/* Adjust pointers so they point within the actual memory we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 	 * just allocated rather than an imaginary chunk of memory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 	 * located at address 0.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 	 * 'dev_ctl' points to REAL memory, while the others are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 	 * ZERO based and thus need to be adjusted to point within
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 	 * the allocated memory.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 	dev_inst = (struct edac_device_instance *)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 		(((char *)dev_ctl) + ((unsigned long)dev_inst));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 	dev_blk = (struct edac_device_block *)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 		(((char *)dev_ctl) + ((unsigned long)dev_blk));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 	dev_attrib = (struct edac_dev_sysfs_block_attribute *)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 		(((char *)dev_ctl) + ((unsigned long)dev_attrib));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 	pvt = sz_private ? (((char *)dev_ctl) + ((unsigned long)pvt)) : NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 	/* Begin storing the information into the control info structure */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 	dev_ctl->dev_idx = device_index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 	dev_ctl->nr_instances = nr_instances;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 	dev_ctl->instances = dev_inst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 	dev_ctl->pvt_info = pvt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 	/* Default logging of CEs and UEs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 	dev_ctl->log_ce = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 	dev_ctl->log_ue = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 	/* Name of this edac device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 	snprintf(dev_ctl->name,sizeof(dev_ctl->name),"%s",edac_device_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 	edac_dbg(4, "edac_dev=%p next after end=%p\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 		 dev_ctl, pvt + sz_private);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 	/* Initialize every Instance */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 	for (instance = 0; instance < nr_instances; instance++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 		inst = &dev_inst[instance];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 		inst->ctl = dev_ctl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 		inst->nr_blocks = nr_blocks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 		blk_p = &dev_blk[instance * nr_blocks];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 		inst->blocks = blk_p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 		/* name of this instance */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 		snprintf(inst->name, sizeof(inst->name),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 			 "%s%u", edac_device_name, instance);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 		/* Initialize every block in each instance */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 		for (block = 0; block < nr_blocks; block++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 			blk = &blk_p[block];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 			blk->instance = inst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 			snprintf(blk->name, sizeof(blk->name),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 				 "%s%d", edac_block_name, block+offset_value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 			edac_dbg(4, "instance=%d inst_p=%p block=#%d block_p=%p name='%s'\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 				 instance, inst, block, blk, blk->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 			/* if there are NO attributes OR no attribute pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 			 * then continue on to next block iteration
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 			 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 			if ((nr_attrib == 0) || (attrib_spec == NULL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 				continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 			/* setup the attribute array for this block */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 			blk->nr_attribs = nr_attrib;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 			attrib_p = &dev_attrib[block*nr_instances*nr_attrib];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 			blk->block_attributes = attrib_p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 			edac_dbg(4, "THIS BLOCK_ATTRIB=%p\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 				 blk->block_attributes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 			/* Initialize every user specified attribute in this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 			 * block with the data the caller passed in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 			 * Each block gets its own copy of pointers,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 			 * and its unique 'value'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 			 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 			for (attr = 0; attr < nr_attrib; attr++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 				attrib = &attrib_p[attr];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 				/* populate the unique per attrib
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 				 * with the code pointers and info
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 				 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 				attrib->attr = attrib_spec[attr].attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 				attrib->show = attrib_spec[attr].show;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 				attrib->store = attrib_spec[attr].store;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 				attrib->block = blk;	/* up link */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 				edac_dbg(4, "alloc-attrib=%p attrib_name='%s' attrib-spec=%p spec-name=%s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 					 attrib, attrib->attr.name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 					 &attrib_spec[attr],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 					 attrib_spec[attr].attr.name
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 					);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) 	/* Mark this instance as merely ALLOCATED */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 	dev_ctl->op_state = OP_ALLOC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 	 * Initialize the 'root' kobj for the edac_device controller
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 	err = edac_device_register_sysfs_main_kobj(dev_ctl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) 	if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) 		kfree(dev_ctl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 		return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) 	/* at this point, the root kobj is valid, and in order to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) 	 * 'free' the object, then the function:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 	 *	edac_device_unregister_sysfs_main_kobj() must be called
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 	 * which will perform kobj unregistration and the actual free
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 	 * will occur during the kobject callback operation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) 	return dev_ctl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) EXPORT_SYMBOL_GPL(edac_device_alloc_ctl_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) void edac_device_free_ctl_info(struct edac_device_ctl_info *ctl_info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 	edac_device_unregister_sysfs_main_kobj(ctl_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) EXPORT_SYMBOL_GPL(edac_device_free_ctl_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)  * find_edac_device_by_dev
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237)  *	scans the edac_device list for a specific 'struct device *'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239)  *	lock to be held prior to call:	device_ctls_mutex
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)  *	Return:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242)  *		pointer to control structure managing 'dev'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243)  *		NULL if not found on list
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) static struct edac_device_ctl_info *find_edac_device_by_dev(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) 	struct edac_device_ctl_info *edac_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) 	struct list_head *item;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) 	edac_dbg(0, "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 	list_for_each(item, &edac_device_list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 		edac_dev = list_entry(item, struct edac_device_ctl_info, link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 		if (edac_dev->dev == dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) 			return edac_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) 	return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263)  * add_edac_dev_to_global_list
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264)  *	Before calling this function, caller must
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265)  *	assign a unique value to edac_dev->dev_idx.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267)  *	lock to be held prior to call:	device_ctls_mutex
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269)  *	Return:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)  *		0 on success
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271)  *		1 on failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) static int add_edac_dev_to_global_list(struct edac_device_ctl_info *edac_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) 	struct list_head *item, *insert_before;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) 	struct edac_device_ctl_info *rover;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) 	insert_before = &edac_device_list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 	/* Determine if already on the list */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) 	rover = find_edac_device_by_dev(edac_dev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) 	if (unlikely(rover != NULL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 		goto fail0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 	/* Insert in ascending order by 'dev_idx', so find position */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 	list_for_each(item, &edac_device_list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) 		rover = list_entry(item, struct edac_device_ctl_info, link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) 		if (rover->dev_idx >= edac_dev->dev_idx) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) 			if (unlikely(rover->dev_idx == edac_dev->dev_idx))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) 				goto fail1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) 			insert_before = item;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) 	list_add_tail_rcu(&edac_dev->link, insert_before);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) fail0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) 	edac_printk(KERN_WARNING, EDAC_MC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) 			"%s (%s) %s %s already assigned %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) 			dev_name(rover->dev), edac_dev_name(rover),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) 			rover->mod_name, rover->ctl_name, rover->dev_idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) 	return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) fail1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) 	edac_printk(KERN_WARNING, EDAC_MC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) 			"bug in low-level driver: attempt to assign\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) 			"    duplicate dev_idx %d in %s()\n", rover->dev_idx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) 			__func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) 	return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317)  * del_edac_device_from_global_list
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) static void del_edac_device_from_global_list(struct edac_device_ctl_info
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) 						*edac_device)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) 	list_del_rcu(&edac_device->link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) 	/* these are for safe removal of devices from global list while
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) 	 * NMI handlers may be traversing list
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) 	synchronize_rcu();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) 	INIT_LIST_HEAD(&edac_device->link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332)  * edac_device_workq_function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333)  *	performs the operation scheduled by a workq request
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335)  *	this workq is embedded within an edac_device_ctl_info
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336)  *	structure, that needs to be polled for possible error events.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338)  *	This operation is to acquire the list mutex lock
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339)  *	(thus preventing insertation or deletion)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340)  *	and then call the device's poll function IFF this device is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341)  *	running polled and there is a poll function defined.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) static void edac_device_workq_function(struct work_struct *work_req)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) 	struct delayed_work *d_work = to_delayed_work(work_req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) 	struct edac_device_ctl_info *edac_dev = to_edac_device_ctl_work(d_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) 	mutex_lock(&device_ctls_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) 	/* If we are being removed, bail out immediately */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) 	if (edac_dev->op_state == OP_OFFLINE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) 		mutex_unlock(&device_ctls_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) 	/* Only poll controllers that are running polled and have a check */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) 	if ((edac_dev->op_state == OP_RUNNING_POLL) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) 		(edac_dev->edac_check != NULL)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) 			edac_dev->edac_check(edac_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) 	mutex_unlock(&device_ctls_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) 	/* Reschedule the workq for the next time period to start again
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) 	 * if the number of msec is for 1 sec, then adjust to the next
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) 	 * whole one second to save timers firing all over the period
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) 	 * between integral seconds
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) 	if (edac_dev->poll_msec == 1000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) 		edac_queue_work(&edac_dev->work, round_jiffies_relative(edac_dev->delay));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) 		edac_queue_work(&edac_dev->work, edac_dev->delay);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376)  * edac_device_workq_setup
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377)  *	initialize a workq item for this edac_device instance
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378)  *	passing in the new delay period in msec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) static void edac_device_workq_setup(struct edac_device_ctl_info *edac_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) 				    unsigned msec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) 	edac_dbg(0, "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) 	/* take the arg 'msec' and set it into the control structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) 	 * to used in the time period calculation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) 	 * then calc the number of jiffies that represents
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) 	edac_dev->poll_msec = msec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) 	edac_dev->delay = msecs_to_jiffies(msec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) 	INIT_DELAYED_WORK(&edac_dev->work, edac_device_workq_function);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) 	/* optimize here for the 1 second case, which will be normal value, to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) 	 * fire ON the 1 second time event. This helps reduce all sorts of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) 	 * timers firing on sub-second basis, while they are happy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) 	 * to fire together on the 1 second exactly
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) 	if (edac_dev->poll_msec == 1000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) 		edac_queue_work(&edac_dev->work, round_jiffies_relative(edac_dev->delay));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) 		edac_queue_work(&edac_dev->work, edac_dev->delay);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406)  * edac_device_workq_teardown
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407)  *	stop the workq processing on this edac_dev
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) static void edac_device_workq_teardown(struct edac_device_ctl_info *edac_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) 	if (!edac_dev->edac_check)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) 	edac_dev->op_state = OP_OFFLINE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) 	edac_stop_work(&edac_dev->work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420)  * edac_device_reset_delay_period
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422)  *	need to stop any outstanding workq queued up at this time
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423)  *	because we will be resetting the sleep time.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424)  *	Then restart the workq on the new delay
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) void edac_device_reset_delay_period(struct edac_device_ctl_info *edac_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) 					unsigned long value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) 	unsigned long jiffs = msecs_to_jiffies(value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) 	if (value == 1000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) 		jiffs = round_jiffies_relative(value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) 	edac_dev->poll_msec = value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) 	edac_dev->delay	    = jiffs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) 	edac_mod_work(&edac_dev->work, jiffs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) int edac_device_alloc_index(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) 	static atomic_t device_indexes = ATOMIC_INIT(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) 	return atomic_inc_return(&device_indexes) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) EXPORT_SYMBOL_GPL(edac_device_alloc_index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) int edac_device_add_device(struct edac_device_ctl_info *edac_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) 	edac_dbg(0, "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) #ifdef CONFIG_EDAC_DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) 	if (edac_debug_level >= 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) 		edac_device_dump_device(edac_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) 	mutex_lock(&device_ctls_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) 	if (add_edac_dev_to_global_list(edac_dev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) 		goto fail0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) 	/* set load time so that error rate can be tracked */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) 	edac_dev->start_time = jiffies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) 	/* create this instance's sysfs entries */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) 	if (edac_device_create_sysfs(edac_dev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) 		edac_device_printk(edac_dev, KERN_WARNING,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) 					"failed to create sysfs device\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) 		goto fail1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) 	/* If there IS a check routine, then we are running POLLED */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) 	if (edac_dev->edac_check != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) 		/* This instance is NOW RUNNING */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) 		edac_dev->op_state = OP_RUNNING_POLL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) 		 * enable workq processing on this instance,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) 		 * default = 1000 msec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) 		edac_device_workq_setup(edac_dev, 1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) 		edac_dev->op_state = OP_RUNNING_INTERRUPT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) 	/* Report action taken */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) 	edac_device_printk(edac_dev, KERN_INFO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) 		"Giving out device to module %s controller %s: DEV %s (%s)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) 		edac_dev->mod_name, edac_dev->ctl_name, edac_dev->dev_name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) 		edac_op_state_to_string(edac_dev->op_state));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) 	mutex_unlock(&device_ctls_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) fail1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) 	/* Some error, so remove the entry from the lsit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) 	del_edac_device_from_global_list(edac_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) fail0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) 	mutex_unlock(&device_ctls_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) 	return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) EXPORT_SYMBOL_GPL(edac_device_add_device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) struct edac_device_ctl_info *edac_device_del_device(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) 	struct edac_device_ctl_info *edac_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) 	edac_dbg(0, "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) 	mutex_lock(&device_ctls_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) 	/* Find the structure on the list, if not there, then leave */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) 	edac_dev = find_edac_device_by_dev(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) 	if (edac_dev == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) 		mutex_unlock(&device_ctls_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) 		return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) 	/* mark this instance as OFFLINE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) 	edac_dev->op_state = OP_OFFLINE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) 	/* deregister from global list */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) 	del_edac_device_from_global_list(edac_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) 	mutex_unlock(&device_ctls_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) 	/* clear workq processing on this instance */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) 	edac_device_workq_teardown(edac_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) 	/* Tear down the sysfs entries for this instance */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) 	edac_device_remove_sysfs(edac_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) 	edac_printk(KERN_INFO, EDAC_MC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) 		"Removed device %d for %s %s: DEV %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) 		edac_dev->dev_idx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) 		edac_dev->mod_name, edac_dev->ctl_name, edac_dev_name(edac_dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) 	return edac_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) EXPORT_SYMBOL_GPL(edac_device_del_device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) static inline int edac_device_get_log_ce(struct edac_device_ctl_info *edac_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) 	return edac_dev->log_ce;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) static inline int edac_device_get_log_ue(struct edac_device_ctl_info *edac_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) 	return edac_dev->log_ue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) static inline int edac_device_get_panic_on_ue(struct edac_device_ctl_info
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) 					*edac_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) 	return edac_dev->panic_on_ue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) void edac_device_handle_ce_count(struct edac_device_ctl_info *edac_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) 				 unsigned int count, int inst_nr, int block_nr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) 				 const char *msg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) 	struct edac_device_instance *instance;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) 	struct edac_device_block *block = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) 	if (!count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) 	if ((inst_nr >= edac_dev->nr_instances) || (inst_nr < 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) 		edac_device_printk(edac_dev, KERN_ERR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) 				"INTERNAL ERROR: 'instance' out of range "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) 				"(%d >= %d)\n", inst_nr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) 				edac_dev->nr_instances);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) 	instance = edac_dev->instances + inst_nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) 	if ((block_nr >= instance->nr_blocks) || (block_nr < 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) 		edac_device_printk(edac_dev, KERN_ERR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) 				"INTERNAL ERROR: instance %d 'block' "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) 				"out of range (%d >= %d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) 				inst_nr, block_nr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) 				instance->nr_blocks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) 	if (instance->nr_blocks > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) 		block = instance->blocks + block_nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) 		block->counters.ce_count += count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) 	/* Propagate the count up the 'totals' tree */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) 	instance->counters.ce_count += count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) 	edac_dev->counters.ce_count += count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) 	if (edac_device_get_log_ce(edac_dev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) 		edac_device_printk(edac_dev, KERN_WARNING,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) 				   "CE: %s instance: %s block: %s count: %d '%s'\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) 				   edac_dev->ctl_name, instance->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) 				   block ? block->name : "N/A", count, msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) EXPORT_SYMBOL_GPL(edac_device_handle_ce_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) void edac_device_handle_ue_count(struct edac_device_ctl_info *edac_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) 				 unsigned int count, int inst_nr, int block_nr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) 				 const char *msg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) 	struct edac_device_instance *instance;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) 	struct edac_device_block *block = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) 	if (!count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) 	if ((inst_nr >= edac_dev->nr_instances) || (inst_nr < 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) 		edac_device_printk(edac_dev, KERN_ERR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) 				"INTERNAL ERROR: 'instance' out of range "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) 				"(%d >= %d)\n", inst_nr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) 				edac_dev->nr_instances);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) 	instance = edac_dev->instances + inst_nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) 	if ((block_nr >= instance->nr_blocks) || (block_nr < 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) 		edac_device_printk(edac_dev, KERN_ERR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) 				"INTERNAL ERROR: instance %d 'block' "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) 				"out of range (%d >= %d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) 				inst_nr, block_nr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) 				instance->nr_blocks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) 	if (instance->nr_blocks > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) 		block = instance->blocks + block_nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) 		block->counters.ue_count += count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) 	/* Propagate the count up the 'totals' tree */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) 	instance->counters.ue_count += count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) 	edac_dev->counters.ue_count += count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) 	if (edac_device_get_log_ue(edac_dev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) 		edac_device_printk(edac_dev, KERN_EMERG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) 				   "UE: %s instance: %s block: %s count: %d '%s'\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) 				   edac_dev->ctl_name, instance->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) 				   block ? block->name : "N/A", count, msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) 	if (edac_device_get_panic_on_ue(edac_dev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) 		panic("EDAC %s: UE instance: %s block %s count: %d '%s'\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) 		      edac_dev->ctl_name, instance->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) 		      block ? block->name : "N/A", count, msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) EXPORT_SYMBOL_GPL(edac_device_handle_ue_count);