xref: /linux-6.15/include/linux/edac.h (revision 81e42fc1)
1c0d12172SDave Jiang /*
2c0d12172SDave Jiang  * Generic EDAC defs
3c0d12172SDave Jiang  *
4c0d12172SDave Jiang  * Author: Dave Jiang <[email protected]>
5c0d12172SDave Jiang  *
6c3c52bceSHitoshi Mitake  * 2006-2008 (c) MontaVista Software, Inc. This file is licensed under
7c0d12172SDave Jiang  * the terms of the GNU General Public License version 2. This program
8c0d12172SDave Jiang  * is licensed "as is" without any warranty of any kind, whether express
9c0d12172SDave Jiang  * or implied.
10c0d12172SDave Jiang  *
11c0d12172SDave Jiang  */
12c0d12172SDave Jiang #ifndef _LINUX_EDAC_H_
13c0d12172SDave Jiang #define _LINUX_EDAC_H_
14c0d12172SDave Jiang 
1560063497SArun Sharma #include <linux/atomic.h>
167a623c03SMauro Carvalho Chehab #include <linux/device.h>
17313162d0SPaul Gortmaker #include <linux/completion.h>
18313162d0SPaul Gortmaker #include <linux/workqueue.h>
19452a6bf9SMauro Carvalho Chehab #include <linux/debugfs.h>
206b588594SJustin Ernst #include <linux/numa.h>
21313162d0SPaul Gortmaker 
220b892c71SMauro Carvalho Chehab #define EDAC_DEVICE_NAME_LEN	31
230b892c71SMauro Carvalho Chehab 
24313162d0SPaul Gortmaker struct device;
25c0d12172SDave Jiang 
26c0d12172SDave Jiang #define EDAC_OPSTATE_INVAL	-1
27c0d12172SDave Jiang #define EDAC_OPSTATE_POLL	0
28c0d12172SDave Jiang #define EDAC_OPSTATE_NMI	1
29c0d12172SDave Jiang #define EDAC_OPSTATE_INT	2
30c0d12172SDave Jiang 
31c0d12172SDave Jiang extern int edac_op_state;
32c0d12172SDave Jiang 
33f36be9ceSGreg Kroah-Hartman const struct bus_type *edac_get_sysfs_subsys(void);
34c700f013SChen, Gong 
opstate_init(void)35c3c52bceSHitoshi Mitake static inline void opstate_init(void)
36c3c52bceSHitoshi Mitake {
37c3c52bceSHitoshi Mitake 	switch (edac_op_state) {
38c3c52bceSHitoshi Mitake 	case EDAC_OPSTATE_POLL:
39c3c52bceSHitoshi Mitake 	case EDAC_OPSTATE_NMI:
40c3c52bceSHitoshi Mitake 		break;
41c3c52bceSHitoshi Mitake 	default:
42c3c52bceSHitoshi Mitake 		edac_op_state = EDAC_OPSTATE_POLL;
43c3c52bceSHitoshi Mitake 	}
44c3c52bceSHitoshi Mitake 	return;
45c3c52bceSHitoshi Mitake }
46c3c52bceSHitoshi Mitake 
47c7ef7645SMauro Carvalho Chehab /* Max length of a DIMM label*/
48ddeb3547SMauro Carvalho Chehab #define EDAC_MC_LABEL_LEN	31
49ddeb3547SMauro Carvalho Chehab 
50c7ef7645SMauro Carvalho Chehab /* Maximum size of the location string */
5156507694SChen, Gong #define LOCATION_SIZE 256
52c7ef7645SMauro Carvalho Chehab 
53c7ef7645SMauro Carvalho Chehab /* Defines the maximum number of labels that can be reported */
54c7ef7645SMauro Carvalho Chehab #define EDAC_MAX_LABELS		8
55c7ef7645SMauro Carvalho Chehab 
56c7ef7645SMauro Carvalho Chehab /* String used to join two or more labels */
57c7ef7645SMauro Carvalho Chehab #define OTHER_LABEL " or "
58c7ef7645SMauro Carvalho Chehab 
59b0610bb8SMauro Carvalho Chehab /**
60b0610bb8SMauro Carvalho Chehab  * enum dev_type - describe the type of memory DRAM chips used at the stick
61b0610bb8SMauro Carvalho Chehab  * @DEV_UNKNOWN:	Can't be determined, or MC doesn't support detect it
62b0610bb8SMauro Carvalho Chehab  * @DEV_X1:		1 bit for data
63b0610bb8SMauro Carvalho Chehab  * @DEV_X2:		2 bits for data
64b0610bb8SMauro Carvalho Chehab  * @DEV_X4:		4 bits for data
65b0610bb8SMauro Carvalho Chehab  * @DEV_X8:		8 bits for data
66b0610bb8SMauro Carvalho Chehab  * @DEV_X16:		16 bits for data
67b0610bb8SMauro Carvalho Chehab  * @DEV_X32:		32 bits for data
68b0610bb8SMauro Carvalho Chehab  * @DEV_X64:		64 bits for data
69b0610bb8SMauro Carvalho Chehab  *
70b0610bb8SMauro Carvalho Chehab  * Typical values are x4 and x8.
71b0610bb8SMauro Carvalho Chehab  */
72ddeb3547SMauro Carvalho Chehab enum dev_type {
73ddeb3547SMauro Carvalho Chehab 	DEV_UNKNOWN = 0,
74ddeb3547SMauro Carvalho Chehab 	DEV_X1,
75ddeb3547SMauro Carvalho Chehab 	DEV_X2,
76ddeb3547SMauro Carvalho Chehab 	DEV_X4,
77ddeb3547SMauro Carvalho Chehab 	DEV_X8,
78ddeb3547SMauro Carvalho Chehab 	DEV_X16,
79ddeb3547SMauro Carvalho Chehab 	DEV_X32,		/* Do these parts exist? */
80ddeb3547SMauro Carvalho Chehab 	DEV_X64			/* Do these parts exist? */
81ddeb3547SMauro Carvalho Chehab };
82ddeb3547SMauro Carvalho Chehab 
83ddeb3547SMauro Carvalho Chehab #define DEV_FLAG_UNKNOWN	BIT(DEV_UNKNOWN)
84ddeb3547SMauro Carvalho Chehab #define DEV_FLAG_X1		BIT(DEV_X1)
85ddeb3547SMauro Carvalho Chehab #define DEV_FLAG_X2		BIT(DEV_X2)
86ddeb3547SMauro Carvalho Chehab #define DEV_FLAG_X4		BIT(DEV_X4)
87ddeb3547SMauro Carvalho Chehab #define DEV_FLAG_X8		BIT(DEV_X8)
88ddeb3547SMauro Carvalho Chehab #define DEV_FLAG_X16		BIT(DEV_X16)
89ddeb3547SMauro Carvalho Chehab #define DEV_FLAG_X32		BIT(DEV_X32)
90ddeb3547SMauro Carvalho Chehab #define DEV_FLAG_X64		BIT(DEV_X64)
91ddeb3547SMauro Carvalho Chehab 
9201a6e28bSMauro Carvalho Chehab /**
93982216a4SMauro Carvalho Chehab  * enum hw_event_mc_err_type - type of the detected error
94982216a4SMauro Carvalho Chehab  *
95982216a4SMauro Carvalho Chehab  * @HW_EVENT_ERR_CORRECTED:	Corrected Error - Indicates that an ECC
96982216a4SMauro Carvalho Chehab  *				corrected error was detected
97982216a4SMauro Carvalho Chehab  * @HW_EVENT_ERR_UNCORRECTED:	Uncorrected Error - Indicates an error that
98982216a4SMauro Carvalho Chehab  *				can't be corrected by ECC, but it is not
99982216a4SMauro Carvalho Chehab  *				fatal (maybe it is on an unused memory area,
100982216a4SMauro Carvalho Chehab  *				or the memory controller could recover from
101982216a4SMauro Carvalho Chehab  *				it for example, by re-trying the operation).
1024838a0deSYazen Ghannam  * @HW_EVENT_ERR_DEFERRED:	Deferred Error - Indicates an uncorrectable
1034838a0deSYazen Ghannam  *				error whose handling is not urgent. This could
1044838a0deSYazen Ghannam  *				be due to hardware data poisoning where the
1054838a0deSYazen Ghannam  *				system can continue operation until the poisoned
1064838a0deSYazen Ghannam  *				data is consumed. Preemptive measures may also
1074838a0deSYazen Ghannam  *				be taken, e.g. offlining pages, etc.
108982216a4SMauro Carvalho Chehab  * @HW_EVENT_ERR_FATAL:		Fatal Error - Uncorrected error that could not
109982216a4SMauro Carvalho Chehab  *				be recovered.
110e0020758SMauro Carvalho Chehab  * @HW_EVENT_ERR_INFO:		Informational - The CPER spec defines a forth
111e0020758SMauro Carvalho Chehab  *				type of error: informational logs.
112982216a4SMauro Carvalho Chehab  */
113982216a4SMauro Carvalho Chehab enum hw_event_mc_err_type {
114982216a4SMauro Carvalho Chehab 	HW_EVENT_ERR_CORRECTED,
115982216a4SMauro Carvalho Chehab 	HW_EVENT_ERR_UNCORRECTED,
116d12a969eSYazen Ghannam 	HW_EVENT_ERR_DEFERRED,
117982216a4SMauro Carvalho Chehab 	HW_EVENT_ERR_FATAL,
1188dd93d45SMauro Carvalho Chehab 	HW_EVENT_ERR_INFO,
119982216a4SMauro Carvalho Chehab };
120982216a4SMauro Carvalho Chehab 
mc_event_error_type(const unsigned int err_type)1218dd93d45SMauro Carvalho Chehab static inline char *mc_event_error_type(const unsigned int err_type)
1228dd93d45SMauro Carvalho Chehab {
1238dd93d45SMauro Carvalho Chehab 	switch (err_type) {
1248dd93d45SMauro Carvalho Chehab 	case HW_EVENT_ERR_CORRECTED:
1258dd93d45SMauro Carvalho Chehab 		return "Corrected";
1268dd93d45SMauro Carvalho Chehab 	case HW_EVENT_ERR_UNCORRECTED:
1278dd93d45SMauro Carvalho Chehab 		return "Uncorrected";
128d12a969eSYazen Ghannam 	case HW_EVENT_ERR_DEFERRED:
129d12a969eSYazen Ghannam 		return "Deferred";
1308dd93d45SMauro Carvalho Chehab 	case HW_EVENT_ERR_FATAL:
1318dd93d45SMauro Carvalho Chehab 		return "Fatal";
1328dd93d45SMauro Carvalho Chehab 	default:
1338dd93d45SMauro Carvalho Chehab 	case HW_EVENT_ERR_INFO:
1348dd93d45SMauro Carvalho Chehab 		return "Info";
1358dd93d45SMauro Carvalho Chehab 	}
1368dd93d45SMauro Carvalho Chehab }
1378dd93d45SMauro Carvalho Chehab 
138982216a4SMauro Carvalho Chehab /**
13901a6e28bSMauro Carvalho Chehab  * enum mem_type - memory types. For a more detailed reference, please see
14001a6e28bSMauro Carvalho Chehab  *			http://en.wikipedia.org/wiki/DRAM
14101a6e28bSMauro Carvalho Chehab  *
142e0020758SMauro Carvalho Chehab  * @MEM_EMPTY:		Empty csrow
14301a6e28bSMauro Carvalho Chehab  * @MEM_RESERVED:	Reserved csrow type
14401a6e28bSMauro Carvalho Chehab  * @MEM_UNKNOWN:	Unknown csrow type
14501a6e28bSMauro Carvalho Chehab  * @MEM_FPM:		FPM - Fast Page Mode, used on systems up to 1995.
14601a6e28bSMauro Carvalho Chehab  * @MEM_EDO:		EDO - Extended data out, used on systems up to 1998.
14701a6e28bSMauro Carvalho Chehab  * @MEM_BEDO:		BEDO - Burst Extended data out, an EDO variant.
14801a6e28bSMauro Carvalho Chehab  * @MEM_SDR:		SDR - Single data rate SDRAM
14901a6e28bSMauro Carvalho Chehab  *			http://en.wikipedia.org/wiki/Synchronous_dynamic_random-access_memory
15001a6e28bSMauro Carvalho Chehab  *			They use 3 pins for chip select: Pins 0 and 2 are
15101a6e28bSMauro Carvalho Chehab  *			for rank 0; pins 1 and 3 are for rank 1, if the memory
15201a6e28bSMauro Carvalho Chehab  *			is dual-rank.
15301a6e28bSMauro Carvalho Chehab  * @MEM_RDR:		Registered SDR SDRAM
15401a6e28bSMauro Carvalho Chehab  * @MEM_DDR:		Double data rate SDRAM
15501a6e28bSMauro Carvalho Chehab  *			http://en.wikipedia.org/wiki/DDR_SDRAM
15601a6e28bSMauro Carvalho Chehab  * @MEM_RDDR:		Registered Double data rate SDRAM
15701a6e28bSMauro Carvalho Chehab  *			This is a variant of the DDR memories.
15801a6e28bSMauro Carvalho Chehab  *			A registered memory has a buffer inside it, hiding
15901a6e28bSMauro Carvalho Chehab  *			part of the memory details to the memory controller.
16001a6e28bSMauro Carvalho Chehab  * @MEM_RMBS:		Rambus DRAM, used on a few Pentium III/IV controllers.
16101a6e28bSMauro Carvalho Chehab  * @MEM_DDR2:		DDR2 RAM, as described at JEDEC JESD79-2F.
162eca90a3bSAlexander Alemayhu  *			Those memories are labeled as "PC2-" instead of "PC" to
163eca90a3bSAlexander Alemayhu  *			differentiate from DDR.
16401a6e28bSMauro Carvalho Chehab  * @MEM_FB_DDR2:	Fully-Buffered DDR2, as described at JEDEC Std No. 205
16501a6e28bSMauro Carvalho Chehab  *			and JESD206.
16601a6e28bSMauro Carvalho Chehab  *			Those memories are accessed per DIMM slot, and not by
16701a6e28bSMauro Carvalho Chehab  *			a chip select signal.
16801a6e28bSMauro Carvalho Chehab  * @MEM_RDDR2:		Registered DDR2 RAM
16901a6e28bSMauro Carvalho Chehab  *			This is a variant of the DDR2 memories.
17001a6e28bSMauro Carvalho Chehab  * @MEM_XDR:		Rambus XDR
17101a6e28bSMauro Carvalho Chehab  *			It is an evolution of the original RAMBUS memories,
17201a6e28bSMauro Carvalho Chehab  *			created to compete with DDR2. Weren't used on any
17301a6e28bSMauro Carvalho Chehab  *			x86 arch, but cell_edac PPC memory controller uses it.
17401a6e28bSMauro Carvalho Chehab  * @MEM_DDR3:		DDR3 RAM
17501a6e28bSMauro Carvalho Chehab  * @MEM_RDDR3:		Registered DDR3 RAM
17601a6e28bSMauro Carvalho Chehab  *			This is a variant of the DDR3 memories.
1771e8096bbSYazen Ghannam  * @MEM_LRDDR3:		Load-Reduced DDR3 memory.
1783b203693SQiuxu Zhuo  * @MEM_LPDDR3:		Low-Power DDR3 memory.
179348fec70SAravind Gopalakrishnan  * @MEM_DDR4:		Unbuffered DDR4 RAM
1807b827835SAristeu Rozanski  * @MEM_RDDR4:		Registered DDR4 RAM
1817b827835SAristeu Rozanski  *			This is a variant of the DDR4 memories.
1821e8096bbSYazen Ghannam  * @MEM_LRDDR4:		Load-Reduced DDR4 memory.
1833b203693SQiuxu Zhuo  * @MEM_LPDDR4:		Low-Power DDR4 memory.
184bc1c99a5SQiuxu Zhuo  * @MEM_DDR5:		Unbuffered DDR5 RAM
185f9571124SYazen Ghannam  * @MEM_RDDR5:		Registered DDR5 RAM
186f9571124SYazen Ghannam  * @MEM_LRDDR5:		Load-Reduced DDR5 memory.
187001f8613STony Luck  * @MEM_NVDIMM:		Non-volatile RAM
1883b203693SQiuxu Zhuo  * @MEM_WIO2:		Wide I/O 2.
189e1ca90b7SNaveen Krishna Chatradhi  * @MEM_HBM2:		High bandwidth Memory Gen 2.
1909a5f580cSMuralidhara M K  * @MEM_HBM3:		High bandwidth Memory Gen 3.
19101a6e28bSMauro Carvalho Chehab  */
192ddeb3547SMauro Carvalho Chehab enum mem_type {
19301a6e28bSMauro Carvalho Chehab 	MEM_EMPTY = 0,
19401a6e28bSMauro Carvalho Chehab 	MEM_RESERVED,
19501a6e28bSMauro Carvalho Chehab 	MEM_UNKNOWN,
19601a6e28bSMauro Carvalho Chehab 	MEM_FPM,
19701a6e28bSMauro Carvalho Chehab 	MEM_EDO,
19801a6e28bSMauro Carvalho Chehab 	MEM_BEDO,
19901a6e28bSMauro Carvalho Chehab 	MEM_SDR,
20001a6e28bSMauro Carvalho Chehab 	MEM_RDR,
20101a6e28bSMauro Carvalho Chehab 	MEM_DDR,
20201a6e28bSMauro Carvalho Chehab 	MEM_RDDR,
20301a6e28bSMauro Carvalho Chehab 	MEM_RMBS,
20401a6e28bSMauro Carvalho Chehab 	MEM_DDR2,
20501a6e28bSMauro Carvalho Chehab 	MEM_FB_DDR2,
20601a6e28bSMauro Carvalho Chehab 	MEM_RDDR2,
20701a6e28bSMauro Carvalho Chehab 	MEM_XDR,
20801a6e28bSMauro Carvalho Chehab 	MEM_DDR3,
20901a6e28bSMauro Carvalho Chehab 	MEM_RDDR3,
210348fec70SAravind Gopalakrishnan 	MEM_LRDDR3,
2113b203693SQiuxu Zhuo 	MEM_LPDDR3,
2127b827835SAristeu Rozanski 	MEM_DDR4,
2137b827835SAristeu Rozanski 	MEM_RDDR4,
2141e8096bbSYazen Ghannam 	MEM_LRDDR4,
2153b203693SQiuxu Zhuo 	MEM_LPDDR4,
216bc1c99a5SQiuxu Zhuo 	MEM_DDR5,
217f9571124SYazen Ghannam 	MEM_RDDR5,
218f9571124SYazen Ghannam 	MEM_LRDDR5,
219001f8613STony Luck 	MEM_NVDIMM,
2203b203693SQiuxu Zhuo 	MEM_WIO2,
221e1ca90b7SNaveen Krishna Chatradhi 	MEM_HBM2,
2229a5f580cSMuralidhara M K 	MEM_HBM3,
223ddeb3547SMauro Carvalho Chehab };
224ddeb3547SMauro Carvalho Chehab 
225ddeb3547SMauro Carvalho Chehab #define MEM_FLAG_EMPTY		BIT(MEM_EMPTY)
226ddeb3547SMauro Carvalho Chehab #define MEM_FLAG_RESERVED	BIT(MEM_RESERVED)
227ddeb3547SMauro Carvalho Chehab #define MEM_FLAG_UNKNOWN	BIT(MEM_UNKNOWN)
228ddeb3547SMauro Carvalho Chehab #define MEM_FLAG_FPM		BIT(MEM_FPM)
229ddeb3547SMauro Carvalho Chehab #define MEM_FLAG_EDO		BIT(MEM_EDO)
230ddeb3547SMauro Carvalho Chehab #define MEM_FLAG_BEDO		BIT(MEM_BEDO)
231ddeb3547SMauro Carvalho Chehab #define MEM_FLAG_SDR		BIT(MEM_SDR)
232ddeb3547SMauro Carvalho Chehab #define MEM_FLAG_RDR		BIT(MEM_RDR)
233ddeb3547SMauro Carvalho Chehab #define MEM_FLAG_DDR		BIT(MEM_DDR)
234ddeb3547SMauro Carvalho Chehab #define MEM_FLAG_RDDR		BIT(MEM_RDDR)
235ddeb3547SMauro Carvalho Chehab #define MEM_FLAG_RMBS		BIT(MEM_RMBS)
236ddeb3547SMauro Carvalho Chehab #define MEM_FLAG_DDR2		BIT(MEM_DDR2)
237ddeb3547SMauro Carvalho Chehab #define MEM_FLAG_FB_DDR2	BIT(MEM_FB_DDR2)
238ddeb3547SMauro Carvalho Chehab #define MEM_FLAG_RDDR2		BIT(MEM_RDDR2)
239ddeb3547SMauro Carvalho Chehab #define MEM_FLAG_XDR		BIT(MEM_XDR)
240ddeb3547SMauro Carvalho Chehab #define MEM_FLAG_DDR3		BIT(MEM_DDR3)
241ddeb3547SMauro Carvalho Chehab #define MEM_FLAG_RDDR3		BIT(MEM_RDDR3)
2423b203693SQiuxu Zhuo #define MEM_FLAG_LPDDR3		BIT(MEM_LPDDR3)
243255379aeSJim Snow #define MEM_FLAG_DDR4		BIT(MEM_DDR4)
244255379aeSJim Snow #define MEM_FLAG_RDDR4		BIT(MEM_RDDR4)
2451e8096bbSYazen Ghannam #define MEM_FLAG_LRDDR4		BIT(MEM_LRDDR4)
2463b203693SQiuxu Zhuo #define MEM_FLAG_LPDDR4		BIT(MEM_LPDDR4)
247bc1c99a5SQiuxu Zhuo #define MEM_FLAG_DDR5		BIT(MEM_DDR5)
248f9571124SYazen Ghannam #define MEM_FLAG_RDDR5		BIT(MEM_RDDR5)
249f9571124SYazen Ghannam #define MEM_FLAG_LRDDR5		BIT(MEM_LRDDR5)
250001f8613STony Luck #define MEM_FLAG_NVDIMM		BIT(MEM_NVDIMM)
2513b203693SQiuxu Zhuo #define MEM_FLAG_WIO2		BIT(MEM_WIO2)
252e1ca90b7SNaveen Krishna Chatradhi #define MEM_FLAG_HBM2		BIT(MEM_HBM2)
2539a5f580cSMuralidhara M K #define MEM_FLAG_HBM3		BIT(MEM_HBM3)
254ddeb3547SMauro Carvalho Chehab 
255b0610bb8SMauro Carvalho Chehab /**
25624269999SMauro Carvalho Chehab  * enum edac_type - Error Detection and Correction capabilities and mode
257b0610bb8SMauro Carvalho Chehab  * @EDAC_UNKNOWN:	Unknown if ECC is available
258b0610bb8SMauro Carvalho Chehab  * @EDAC_NONE:		Doesn't support ECC
259b0610bb8SMauro Carvalho Chehab  * @EDAC_RESERVED:	Reserved ECC type
260b0610bb8SMauro Carvalho Chehab  * @EDAC_PARITY:	Detects parity errors
261b0610bb8SMauro Carvalho Chehab  * @EDAC_EC:		Error Checking - no correction
262b0610bb8SMauro Carvalho Chehab  * @EDAC_SECDED:	Single bit error correction, Double detection
263b0610bb8SMauro Carvalho Chehab  * @EDAC_S2ECD2ED:	Chipkill x2 devices - do these exist?
264b0610bb8SMauro Carvalho Chehab  * @EDAC_S4ECD4ED:	Chipkill x4 devices
265b0610bb8SMauro Carvalho Chehab  * @EDAC_S8ECD8ED:	Chipkill x8 devices
266b0610bb8SMauro Carvalho Chehab  * @EDAC_S16ECD16ED:	Chipkill x16 devices
267b0610bb8SMauro Carvalho Chehab  */
268ddeb3547SMauro Carvalho Chehab enum edac_type {
269b0610bb8SMauro Carvalho Chehab 	EDAC_UNKNOWN =	0,
270b0610bb8SMauro Carvalho Chehab 	EDAC_NONE,
271b0610bb8SMauro Carvalho Chehab 	EDAC_RESERVED,
272b0610bb8SMauro Carvalho Chehab 	EDAC_PARITY,
273b0610bb8SMauro Carvalho Chehab 	EDAC_EC,
274b0610bb8SMauro Carvalho Chehab 	EDAC_SECDED,
275b0610bb8SMauro Carvalho Chehab 	EDAC_S2ECD2ED,
276b0610bb8SMauro Carvalho Chehab 	EDAC_S4ECD4ED,
277b0610bb8SMauro Carvalho Chehab 	EDAC_S8ECD8ED,
278b0610bb8SMauro Carvalho Chehab 	EDAC_S16ECD16ED,
279ddeb3547SMauro Carvalho Chehab };
280ddeb3547SMauro Carvalho Chehab 
281ddeb3547SMauro Carvalho Chehab #define EDAC_FLAG_UNKNOWN	BIT(EDAC_UNKNOWN)
282ddeb3547SMauro Carvalho Chehab #define EDAC_FLAG_NONE		BIT(EDAC_NONE)
283ddeb3547SMauro Carvalho Chehab #define EDAC_FLAG_PARITY	BIT(EDAC_PARITY)
284ddeb3547SMauro Carvalho Chehab #define EDAC_FLAG_EC		BIT(EDAC_EC)
285ddeb3547SMauro Carvalho Chehab #define EDAC_FLAG_SECDED	BIT(EDAC_SECDED)
286ddeb3547SMauro Carvalho Chehab #define EDAC_FLAG_S2ECD2ED	BIT(EDAC_S2ECD2ED)
287ddeb3547SMauro Carvalho Chehab #define EDAC_FLAG_S4ECD4ED	BIT(EDAC_S4ECD4ED)
288ddeb3547SMauro Carvalho Chehab #define EDAC_FLAG_S8ECD8ED	BIT(EDAC_S8ECD8ED)
289ddeb3547SMauro Carvalho Chehab #define EDAC_FLAG_S16ECD16ED	BIT(EDAC_S16ECD16ED)
290ddeb3547SMauro Carvalho Chehab 
291b0610bb8SMauro Carvalho Chehab /**
292b0610bb8SMauro Carvalho Chehab  * enum scrub_type - scrubbing capabilities
293e0020758SMauro Carvalho Chehab  * @SCRUB_UNKNOWN:		Unknown if scrubber is available
294b0610bb8SMauro Carvalho Chehab  * @SCRUB_NONE:			No scrubber
295b0610bb8SMauro Carvalho Chehab  * @SCRUB_SW_PROG:		SW progressive (sequential) scrubbing
296b0610bb8SMauro Carvalho Chehab  * @SCRUB_SW_SRC:		Software scrub only errors
297b0610bb8SMauro Carvalho Chehab  * @SCRUB_SW_PROG_SRC:		Progressive software scrub from an error
298b0610bb8SMauro Carvalho Chehab  * @SCRUB_SW_TUNABLE:		Software scrub frequency is tunable
299b0610bb8SMauro Carvalho Chehab  * @SCRUB_HW_PROG:		HW progressive (sequential) scrubbing
300b0610bb8SMauro Carvalho Chehab  * @SCRUB_HW_SRC:		Hardware scrub only errors
301b0610bb8SMauro Carvalho Chehab  * @SCRUB_HW_PROG_SRC:		Progressive hardware scrub from an error
302e0020758SMauro Carvalho Chehab  * @SCRUB_HW_TUNABLE:		Hardware scrub frequency is tunable
303b0610bb8SMauro Carvalho Chehab  */
304ddeb3547SMauro Carvalho Chehab enum scrub_type {
305b0610bb8SMauro Carvalho Chehab 	SCRUB_UNKNOWN =	0,
306b0610bb8SMauro Carvalho Chehab 	SCRUB_NONE,
307b0610bb8SMauro Carvalho Chehab 	SCRUB_SW_PROG,
308b0610bb8SMauro Carvalho Chehab 	SCRUB_SW_SRC,
309b0610bb8SMauro Carvalho Chehab 	SCRUB_SW_PROG_SRC,
310b0610bb8SMauro Carvalho Chehab 	SCRUB_SW_TUNABLE,
311b0610bb8SMauro Carvalho Chehab 	SCRUB_HW_PROG,
312b0610bb8SMauro Carvalho Chehab 	SCRUB_HW_SRC,
313b0610bb8SMauro Carvalho Chehab 	SCRUB_HW_PROG_SRC,
314b0610bb8SMauro Carvalho Chehab 	SCRUB_HW_TUNABLE
315ddeb3547SMauro Carvalho Chehab };
316ddeb3547SMauro Carvalho Chehab 
317ddeb3547SMauro Carvalho Chehab #define SCRUB_FLAG_SW_PROG	BIT(SCRUB_SW_PROG)
318ddeb3547SMauro Carvalho Chehab #define SCRUB_FLAG_SW_SRC	BIT(SCRUB_SW_SRC)
319ddeb3547SMauro Carvalho Chehab #define SCRUB_FLAG_SW_PROG_SRC	BIT(SCRUB_SW_PROG_SRC)
320ddeb3547SMauro Carvalho Chehab #define SCRUB_FLAG_SW_TUN	BIT(SCRUB_SW_SCRUB_TUNABLE)
321ddeb3547SMauro Carvalho Chehab #define SCRUB_FLAG_HW_PROG	BIT(SCRUB_HW_PROG)
322ddeb3547SMauro Carvalho Chehab #define SCRUB_FLAG_HW_SRC	BIT(SCRUB_HW_SRC)
323ddeb3547SMauro Carvalho Chehab #define SCRUB_FLAG_HW_PROG_SRC	BIT(SCRUB_HW_PROG_SRC)
324ddeb3547SMauro Carvalho Chehab #define SCRUB_FLAG_HW_TUN	BIT(SCRUB_HW_TUNABLE)
325ddeb3547SMauro Carvalho Chehab 
326ddeb3547SMauro Carvalho Chehab /* FIXME - should have notify capabilities: NMI, LOG, PROC, etc */
327ddeb3547SMauro Carvalho Chehab 
328ddeb3547SMauro Carvalho Chehab /* EDAC internal operation states */
329ddeb3547SMauro Carvalho Chehab #define	OP_ALLOC		0x100
330ddeb3547SMauro Carvalho Chehab #define OP_RUNNING_POLL		0x201
331ddeb3547SMauro Carvalho Chehab #define OP_RUNNING_INTERRUPT	0x202
332ddeb3547SMauro Carvalho Chehab #define OP_RUNNING_POLL_INTR	0x203
333ddeb3547SMauro Carvalho Chehab #define OP_OFFLINE		0x300
334ddeb3547SMauro Carvalho Chehab 
335982216a4SMauro Carvalho Chehab /**
33624269999SMauro Carvalho Chehab  * enum edac_mc_layer_type - memory controller hierarchy layer
337982216a4SMauro Carvalho Chehab  *
338982216a4SMauro Carvalho Chehab  * @EDAC_MC_LAYER_BRANCH:	memory layer is named "branch"
339982216a4SMauro Carvalho Chehab  * @EDAC_MC_LAYER_CHANNEL:	memory layer is named "channel"
340982216a4SMauro Carvalho Chehab  * @EDAC_MC_LAYER_SLOT:		memory layer is named "slot"
341982216a4SMauro Carvalho Chehab  * @EDAC_MC_LAYER_CHIP_SELECT:	memory layer is named "chip select"
342c66b5a79SMauro Carvalho Chehab  * @EDAC_MC_LAYER_ALL_MEM:	memory layout is unknown. All memory is mapped
343c66b5a79SMauro Carvalho Chehab  *				as a single memory area. This is used when
344c66b5a79SMauro Carvalho Chehab  *				retrieving errors from a firmware driven driver.
345982216a4SMauro Carvalho Chehab  *
346982216a4SMauro Carvalho Chehab  * This enum is used by the drivers to tell edac_mc_sysfs what name should
347982216a4SMauro Carvalho Chehab  * be used when describing a memory stick location.
348982216a4SMauro Carvalho Chehab  */
349982216a4SMauro Carvalho Chehab enum edac_mc_layer_type {
350982216a4SMauro Carvalho Chehab 	EDAC_MC_LAYER_BRANCH,
351982216a4SMauro Carvalho Chehab 	EDAC_MC_LAYER_CHANNEL,
352982216a4SMauro Carvalho Chehab 	EDAC_MC_LAYER_SLOT,
353982216a4SMauro Carvalho Chehab 	EDAC_MC_LAYER_CHIP_SELECT,
354c66b5a79SMauro Carvalho Chehab 	EDAC_MC_LAYER_ALL_MEM,
355982216a4SMauro Carvalho Chehab };
356982216a4SMauro Carvalho Chehab 
357982216a4SMauro Carvalho Chehab /**
358982216a4SMauro Carvalho Chehab  * struct edac_mc_layer - describes the memory controller hierarchy
359e0020758SMauro Carvalho Chehab  * @type:		layer type
360982216a4SMauro Carvalho Chehab  * @size:		number of components per layer. For example,
361982216a4SMauro Carvalho Chehab  *			if the channel layer has two channels, size = 2
362982216a4SMauro Carvalho Chehab  * @is_virt_csrow:	This layer is part of the "csrow" when old API
363982216a4SMauro Carvalho Chehab  *			compatibility mode is enabled. Otherwise, it is
364982216a4SMauro Carvalho Chehab  *			a channel
365982216a4SMauro Carvalho Chehab  */
366982216a4SMauro Carvalho Chehab struct edac_mc_layer {
367982216a4SMauro Carvalho Chehab 	enum edac_mc_layer_type	type;
368982216a4SMauro Carvalho Chehab 	unsigned		size;
369982216a4SMauro Carvalho Chehab 	bool			is_virt_csrow;
370982216a4SMauro Carvalho Chehab };
371982216a4SMauro Carvalho Chehab 
372982216a4SMauro Carvalho Chehab /*
373982216a4SMauro Carvalho Chehab  * Maximum number of layers used by the memory controller to uniquely
374982216a4SMauro Carvalho Chehab  * identify a single memory stick.
375982216a4SMauro Carvalho Chehab  * NOTE: Changing this constant requires not only to change the constant
376982216a4SMauro Carvalho Chehab  * below, but also to change the existing code at the core, as there are
377982216a4SMauro Carvalho Chehab  * some code there that are optimized for 3 layers.
378982216a4SMauro Carvalho Chehab  */
379982216a4SMauro Carvalho Chehab #define EDAC_MAX_LAYERS		3
380982216a4SMauro Carvalho Chehab 
381a7d7d2e1SMauro Carvalho Chehab struct dimm_info {
3827a623c03SMauro Carvalho Chehab 	struct device dev;
3837a623c03SMauro Carvalho Chehab 
384a7d7d2e1SMauro Carvalho Chehab 	char label[EDAC_MC_LABEL_LEN + 1];	/* DIMM label on motherboard */
3854275be63SMauro Carvalho Chehab 
3864275be63SMauro Carvalho Chehab 	/* Memory location data */
387d55c79acSRobert Richter 	unsigned int location[EDAC_MAX_LAYERS];
3884275be63SMauro Carvalho Chehab 
3894275be63SMauro Carvalho Chehab 	struct mem_ctl_info *mci;	/* the parent */
390977b1ce7SRobert Richter 	unsigned int idx;		/* index within the parent dimm array */
391084a4fccSMauro Carvalho Chehab 
392084a4fccSMauro Carvalho Chehab 	u32 grain;		/* granularity of reported error in bytes */
393084a4fccSMauro Carvalho Chehab 	enum dev_type dtype;	/* memory device type */
394084a4fccSMauro Carvalho Chehab 	enum mem_type mtype;	/* memory dimm type */
395084a4fccSMauro Carvalho Chehab 	enum edac_type edac_mode;	/* EDAC mode for this dimm */
396084a4fccSMauro Carvalho Chehab 
3974275be63SMauro Carvalho Chehab 	u32 nr_pages;			/* number of pages on this dimm */
398a895bf8bSMauro Carvalho Chehab 
399d55c79acSRobert Richter 	unsigned int csrow, cschannel;	/* Points to the old API data */
400c798c88fSFan Wu 
401c798c88fSFan Wu 	u16 smbios_handle;              /* Handle for SMBIOS type 17 */
4024aa92c86SRobert Richter 
4034aa92c86SRobert Richter 	u32 ce_count;
4044aa92c86SRobert Richter 	u32 ue_count;
405a7d7d2e1SMauro Carvalho Chehab };
406a7d7d2e1SMauro Carvalho Chehab 
407a4b4be3fSMauro Carvalho Chehab /**
408a4b4be3fSMauro Carvalho Chehab  * struct rank_info - contains the information for one DIMM rank
409a4b4be3fSMauro Carvalho Chehab  *
410a4b4be3fSMauro Carvalho Chehab  * @chan_idx:	channel number where the rank is (typically, 0 or 1)
411a4b4be3fSMauro Carvalho Chehab  * @ce_count:	number of correctable errors for this rank
412a4b4be3fSMauro Carvalho Chehab  * @csrow:	A pointer to the chip select row structure (the parent
413a4b4be3fSMauro Carvalho Chehab  *		structure). The location of the rank is given by
414a4b4be3fSMauro Carvalho Chehab  *		the (csrow->csrow_idx, chan_idx) vector.
415a7d7d2e1SMauro Carvalho Chehab  * @dimm:	A pointer to the DIMM structure, where the DIMM label
416a7d7d2e1SMauro Carvalho Chehab  *		information is stored.
417a7d7d2e1SMauro Carvalho Chehab  *
418a7d7d2e1SMauro Carvalho Chehab  * FIXME: Currently, the EDAC core model will assume one DIMM per rank.
419a7d7d2e1SMauro Carvalho Chehab  *	  This is a bad assumption, but it makes this patch easier. Later
420a7d7d2e1SMauro Carvalho Chehab  *	  patches in this series will fix this issue.
421a4b4be3fSMauro Carvalho Chehab  */
422a4b4be3fSMauro Carvalho Chehab struct rank_info {
423a4b4be3fSMauro Carvalho Chehab 	int chan_idx;
424a7d7d2e1SMauro Carvalho Chehab 	struct csrow_info *csrow;
425a7d7d2e1SMauro Carvalho Chehab 	struct dimm_info *dimm;
4264275be63SMauro Carvalho Chehab 
4274275be63SMauro Carvalho Chehab 	u32 ce_count;		/* Correctable Errors for this csrow */
428ddeb3547SMauro Carvalho Chehab };
429ddeb3547SMauro Carvalho Chehab 
430ddeb3547SMauro Carvalho Chehab struct csrow_info {
4317a623c03SMauro Carvalho Chehab 	struct device dev;
4327a623c03SMauro Carvalho Chehab 
433a895bf8bSMauro Carvalho Chehab 	/* Used only by edac_mc_find_csrow_by_page() */
434084a4fccSMauro Carvalho Chehab 	unsigned long first_page;	/* first page number in csrow */
435084a4fccSMauro Carvalho Chehab 	unsigned long last_page;	/* last page number in csrow */
436ddeb3547SMauro Carvalho Chehab 	unsigned long page_mask;	/* used for interleaving -
437a895bf8bSMauro Carvalho Chehab 					 * 0UL for non intlv */
438a895bf8bSMauro Carvalho Chehab 
439ddeb3547SMauro Carvalho Chehab 	int csrow_idx;			/* the chip-select row */
440084a4fccSMauro Carvalho Chehab 
441ddeb3547SMauro Carvalho Chehab 	u32 ue_count;		/* Uncorrectable Errors for this csrow */
442ddeb3547SMauro Carvalho Chehab 	u32 ce_count;		/* Correctable Errors for this csrow */
443084a4fccSMauro Carvalho Chehab 
444ddeb3547SMauro Carvalho Chehab 	struct mem_ctl_info *mci;	/* the parent */
445ddeb3547SMauro Carvalho Chehab 
446ddeb3547SMauro Carvalho Chehab 	/* channel information for this csrow */
447ddeb3547SMauro Carvalho Chehab 	u32 nr_channels;
448de3910ebSMauro Carvalho Chehab 	struct rank_info **channels;
449ddeb3547SMauro Carvalho Chehab };
450ddeb3547SMauro Carvalho Chehab 
4517a623c03SMauro Carvalho Chehab /*
4527a623c03SMauro Carvalho Chehab  * struct errcount_attribute - used to store the several error counts
4537a623c03SMauro Carvalho Chehab  */
4547a623c03SMauro Carvalho Chehab struct errcount_attribute_data {
4557a623c03SMauro Carvalho Chehab 	int n_layers;
4567a623c03SMauro Carvalho Chehab 	int pos[EDAC_MAX_LAYERS];
4577a623c03SMauro Carvalho Chehab 	int layer0, layer1, layer2;
458ddeb3547SMauro Carvalho Chehab };
459ddeb3547SMauro Carvalho Chehab 
460c7ef7645SMauro Carvalho Chehab /**
461e0020758SMauro Carvalho Chehab  * struct edac_raw_error_desc - Raw error report structure
462c7ef7645SMauro Carvalho Chehab  * @grain:			minimum granularity for an error report, in bytes
463c7ef7645SMauro Carvalho Chehab  * @error_count:		number of errors of the same type
464672ef0e5SRobert Richter  * @type:			severity of the error (CE/UE/Fatal)
465c7ef7645SMauro Carvalho Chehab  * @top_layer:			top layer of the error (layer[0])
466c7ef7645SMauro Carvalho Chehab  * @mid_layer:			middle layer of the error (layer[1])
467c7ef7645SMauro Carvalho Chehab  * @low_layer:			low layer of the error (layer[2])
468c7ef7645SMauro Carvalho Chehab  * @page_frame_number:		page where the error happened
469c7ef7645SMauro Carvalho Chehab  * @offset_in_page:		page offset
470c7ef7645SMauro Carvalho Chehab  * @syndrome:			syndrome of the error (or 0 if unknown or if
471c7ef7645SMauro Carvalho Chehab  * 				the syndrome is not applicable)
472c7ef7645SMauro Carvalho Chehab  * @msg:			error message
473c7ef7645SMauro Carvalho Chehab  * @location:			location of the error
474c7ef7645SMauro Carvalho Chehab  * @label:			label of the affected DIMM(s)
475c7ef7645SMauro Carvalho Chehab  * @other_detail:		other driver-specific detail about the error
476c7ef7645SMauro Carvalho Chehab  */
477c7ef7645SMauro Carvalho Chehab struct edac_raw_error_desc {
478c7ef7645SMauro Carvalho Chehab 	char location[LOCATION_SIZE];
479c7ef7645SMauro Carvalho Chehab 	char label[(EDAC_MC_LABEL_LEN + 1 + sizeof(OTHER_LABEL)) * EDAC_MAX_LABELS];
480c7ef7645SMauro Carvalho Chehab 	long grain;
481c7ef7645SMauro Carvalho Chehab 
482c7ef7645SMauro Carvalho Chehab 	u16 error_count;
483672ef0e5SRobert Richter 	enum hw_event_mc_err_type type;
484c7ef7645SMauro Carvalho Chehab 	int top_layer;
485c7ef7645SMauro Carvalho Chehab 	int mid_layer;
486c7ef7645SMauro Carvalho Chehab 	int low_layer;
487c7ef7645SMauro Carvalho Chehab 	unsigned long page_frame_number;
488c7ef7645SMauro Carvalho Chehab 	unsigned long offset_in_page;
489c7ef7645SMauro Carvalho Chehab 	unsigned long syndrome;
490c7ef7645SMauro Carvalho Chehab 	const char *msg;
491c7ef7645SMauro Carvalho Chehab 	const char *other_detail;
492c7ef7645SMauro Carvalho Chehab };
493c7ef7645SMauro Carvalho Chehab 
494ddeb3547SMauro Carvalho Chehab /* MEMORY controller information structure
495ddeb3547SMauro Carvalho Chehab  */
496ddeb3547SMauro Carvalho Chehab struct mem_ctl_info {
4977a623c03SMauro Carvalho Chehab 	struct device			dev;
498f36be9ceSGreg Kroah-Hartman 	const struct bus_type		*bus;
4997a623c03SMauro Carvalho Chehab 
500ddeb3547SMauro Carvalho Chehab 	struct list_head link;	/* for global list of mem_ctl_info structs */
501ddeb3547SMauro Carvalho Chehab 
502ddeb3547SMauro Carvalho Chehab 	struct module *owner;	/* Module owner of this control struct */
503ddeb3547SMauro Carvalho Chehab 
504ddeb3547SMauro Carvalho Chehab 	unsigned long mtype_cap;	/* memory types supported by mc */
505ddeb3547SMauro Carvalho Chehab 	unsigned long edac_ctl_cap;	/* Mem controller EDAC capabilities */
506ddeb3547SMauro Carvalho Chehab 	unsigned long edac_cap;	/* configuration capabilities - this is
507ddeb3547SMauro Carvalho Chehab 				 * closely related to edac_ctl_cap.  The
508ddeb3547SMauro Carvalho Chehab 				 * difference is that the controller may be
509ddeb3547SMauro Carvalho Chehab 				 * capable of s4ecd4ed which would be listed
510ddeb3547SMauro Carvalho Chehab 				 * in edac_ctl_cap, but if channels aren't
511ddeb3547SMauro Carvalho Chehab 				 * capable of s4ecd4ed then the edac_cap would
512ddeb3547SMauro Carvalho Chehab 				 * not have that capability.
513ddeb3547SMauro Carvalho Chehab 				 */
514ddeb3547SMauro Carvalho Chehab 	unsigned long scrub_cap;	/* chipset scrub capabilities */
515ddeb3547SMauro Carvalho Chehab 	enum scrub_type scrub_mode;	/* current scrub mode */
516ddeb3547SMauro Carvalho Chehab 
517ddeb3547SMauro Carvalho Chehab 	/* Translates sdram memory scrub rate given in bytes/sec to the
518ddeb3547SMauro Carvalho Chehab 	   internal representation and configures whatever else needs
519ddeb3547SMauro Carvalho Chehab 	   to be configured.
520ddeb3547SMauro Carvalho Chehab 	 */
521ddeb3547SMauro Carvalho Chehab 	int (*set_sdram_scrub_rate) (struct mem_ctl_info * mci, u32 bw);
522ddeb3547SMauro Carvalho Chehab 
523ddeb3547SMauro Carvalho Chehab 	/* Get the current sdram memory scrub rate from the internal
524ddeb3547SMauro Carvalho Chehab 	   representation and converts it to the closest matching
525ddeb3547SMauro Carvalho Chehab 	   bandwidth in bytes/sec.
526ddeb3547SMauro Carvalho Chehab 	 */
527ddeb3547SMauro Carvalho Chehab 	int (*get_sdram_scrub_rate) (struct mem_ctl_info * mci);
528ddeb3547SMauro Carvalho Chehab 
529ddeb3547SMauro Carvalho Chehab 
530ddeb3547SMauro Carvalho Chehab 	/* pointer to edac checking routine */
531ddeb3547SMauro Carvalho Chehab 	void (*edac_check) (struct mem_ctl_info * mci);
532ddeb3547SMauro Carvalho Chehab 
533ddeb3547SMauro Carvalho Chehab 	/*
534ddeb3547SMauro Carvalho Chehab 	 * Remaps memory pages: controller pages to physical pages.
535ddeb3547SMauro Carvalho Chehab 	 * For most MC's, this will be NULL.
536ddeb3547SMauro Carvalho Chehab 	 */
537ddeb3547SMauro Carvalho Chehab 	/* FIXME - why not send the phys page to begin with? */
538ddeb3547SMauro Carvalho Chehab 	unsigned long (*ctl_page_to_phys) (struct mem_ctl_info * mci,
539ddeb3547SMauro Carvalho Chehab 					   unsigned long page);
540ddeb3547SMauro Carvalho Chehab 	int mc_idx;
541de3910ebSMauro Carvalho Chehab 	struct csrow_info **csrows;
542d55c79acSRobert Richter 	unsigned int nr_csrows, num_cschannel;
5434275be63SMauro Carvalho Chehab 
5447a623c03SMauro Carvalho Chehab 	/*
5457a623c03SMauro Carvalho Chehab 	 * Memory Controller hierarchy
5467a623c03SMauro Carvalho Chehab 	 *
5477a623c03SMauro Carvalho Chehab 	 * There are basically two types of memory controller: the ones that
5487a623c03SMauro Carvalho Chehab 	 * sees memory sticks ("dimms"), and the ones that sees memory ranks.
5497a623c03SMauro Carvalho Chehab 	 * All old memory controllers enumerate memories per rank, but most
5507a623c03SMauro Carvalho Chehab 	 * of the recent drivers enumerate memories per DIMM, instead.
5519713faecSMauro Carvalho Chehab 	 * When the memory controller is per rank, csbased is true.
5527a623c03SMauro Carvalho Chehab 	 */
553d55c79acSRobert Richter 	unsigned int n_layers;
5544275be63SMauro Carvalho Chehab 	struct edac_mc_layer *layers;
5559713faecSMauro Carvalho Chehab 	bool csbased;
556a7d7d2e1SMauro Carvalho Chehab 
557a7d7d2e1SMauro Carvalho Chehab 	/*
558a7d7d2e1SMauro Carvalho Chehab 	 * DIMM info. Will eventually remove the entire csrows_info some day
559a7d7d2e1SMauro Carvalho Chehab 	 */
560d55c79acSRobert Richter 	unsigned int tot_dimms;
561de3910ebSMauro Carvalho Chehab 	struct dimm_info **dimms;
562a7d7d2e1SMauro Carvalho Chehab 
563ddeb3547SMauro Carvalho Chehab 	/*
564ddeb3547SMauro Carvalho Chehab 	 * FIXME - what about controllers on other busses? - IDs must be
565ddeb3547SMauro Carvalho Chehab 	 * unique.  dev pointer should be sufficiently unique, but
566ddeb3547SMauro Carvalho Chehab 	 * BUS:SLOT.FUNC numbers may not be unique.
567ddeb3547SMauro Carvalho Chehab 	 */
568fd687502SMauro Carvalho Chehab 	struct device *pdev;
569ddeb3547SMauro Carvalho Chehab 	const char *mod_name;
570ddeb3547SMauro Carvalho Chehab 	const char *ctl_name;
571ddeb3547SMauro Carvalho Chehab 	const char *dev_name;
572ddeb3547SMauro Carvalho Chehab 	void *pvt_info;
573ddeb3547SMauro Carvalho Chehab 	unsigned long start_time;	/* mci load start time (in jiffies) */
574ddeb3547SMauro Carvalho Chehab 
5754275be63SMauro Carvalho Chehab 	/*
5764275be63SMauro Carvalho Chehab 	 * drivers shouldn't access those fields directly, as the core
5774275be63SMauro Carvalho Chehab 	 * already handles that.
5784275be63SMauro Carvalho Chehab 	 */
5794275be63SMauro Carvalho Chehab 	u32 ce_noinfo_count, ue_noinfo_count;
5805926ff50SMauro Carvalho Chehab 	u32 ue_mc, ce_mc;
5814275be63SMauro Carvalho Chehab 
582ddeb3547SMauro Carvalho Chehab 	struct completion complete;
583ddeb3547SMauro Carvalho Chehab 
584ddeb3547SMauro Carvalho Chehab 	/* Additional top controller level attributes, but specified
585ddeb3547SMauro Carvalho Chehab 	 * by the low level driver.
586ddeb3547SMauro Carvalho Chehab 	 *
587ddeb3547SMauro Carvalho Chehab 	 * Set by the low level driver to provide attributes at the
5884275be63SMauro Carvalho Chehab 	 * controller level.
589ddeb3547SMauro Carvalho Chehab 	 * An array of structures, NULL terminated
590ddeb3547SMauro Carvalho Chehab 	 *
591ddeb3547SMauro Carvalho Chehab 	 * If attributes are desired, then set to array of attributes
592ddeb3547SMauro Carvalho Chehab 	 * If no attributes are desired, leave NULL
593ddeb3547SMauro Carvalho Chehab 	 */
594ddeb3547SMauro Carvalho Chehab 	const struct mcidev_sysfs_attribute *mc_driver_sysfs_attributes;
595ddeb3547SMauro Carvalho Chehab 
596ddeb3547SMauro Carvalho Chehab 	/* work struct for this MC */
597ddeb3547SMauro Carvalho Chehab 	struct delayed_work work;
598ddeb3547SMauro Carvalho Chehab 
599c7ef7645SMauro Carvalho Chehab 	/*
600c7ef7645SMauro Carvalho Chehab 	 * Used to report an error - by being at the global struct
601c7ef7645SMauro Carvalho Chehab 	 * makes the memory allocated by the EDAC core
602c7ef7645SMauro Carvalho Chehab 	 */
603c7ef7645SMauro Carvalho Chehab 	struct edac_raw_error_desc error_desc;
604c7ef7645SMauro Carvalho Chehab 
605ddeb3547SMauro Carvalho Chehab 	/* the internal state of this controller instance */
606ddeb3547SMauro Carvalho Chehab 	int op_state;
607452a6bf9SMauro Carvalho Chehab 
608452a6bf9SMauro Carvalho Chehab 	struct dentry *debugfs;
609452a6bf9SMauro Carvalho Chehab 	u8 fake_inject_layer[EDAC_MAX_LAYERS];
610621a5f7aSViresh Kumar 	bool fake_inject_ue;
61138ced28bSMauro Carvalho Chehab 	u16 fake_inject_count;
612ddeb3547SMauro Carvalho Chehab };
613bc9ad9e4SRobert Richter 
614c498afafSRobert Richter #define mci_for_each_dimm(mci, dimm)				\
615c498afafSRobert Richter 	for ((dimm) = (mci)->dimms[0];				\
616c498afafSRobert Richter 	     (dimm);						\
617c498afafSRobert Richter 	     (dimm) = (dimm)->idx + 1 < (mci)->tot_dimms	\
618c498afafSRobert Richter 		     ? (mci)->dimms[(dimm)->idx + 1]		\
619c498afafSRobert Richter 		     : NULL)
620c498afafSRobert Richter 
621bc9ad9e4SRobert Richter /**
622bc9ad9e4SRobert Richter  * edac_get_dimm - Get DIMM info from a memory controller given by
623bc9ad9e4SRobert Richter  *                 [layer0,layer1,layer2] position
624bc9ad9e4SRobert Richter  *
625bc9ad9e4SRobert Richter  * @mci:	MC descriptor struct mem_ctl_info
626bc9ad9e4SRobert Richter  * @layer0:	layer0 position
627bc9ad9e4SRobert Richter  * @layer1:	layer1 position. Unused if n_layers < 2
628bc9ad9e4SRobert Richter  * @layer2:	layer2 position. Unused if n_layers < 3
629bc9ad9e4SRobert Richter  *
630bc9ad9e4SRobert Richter  * For 1 layer, this function returns "dimms[layer0]";
631bc9ad9e4SRobert Richter  *
632bc9ad9e4SRobert Richter  * For 2 layers, this function is similar to allocating a two-dimensional
633bc9ad9e4SRobert Richter  * array and returning "dimms[layer0][layer1]";
634bc9ad9e4SRobert Richter  *
635bc9ad9e4SRobert Richter  * For 3 layers, this function is similar to allocating a tri-dimensional
636bc9ad9e4SRobert Richter  * array and returning "dimms[layer0][layer1][layer2]";
637bc9ad9e4SRobert Richter  */
edac_get_dimm(struct mem_ctl_info * mci,int layer0,int layer1,int layer2)638bc9ad9e4SRobert Richter static inline struct dimm_info *edac_get_dimm(struct mem_ctl_info *mci,
639bc9ad9e4SRobert Richter 	int layer0, int layer1, int layer2)
640bc9ad9e4SRobert Richter {
641bc9ad9e4SRobert Richter 	int index;
642bc9ad9e4SRobert Richter 
643bc9ad9e4SRobert Richter 	if (layer0 < 0
644bc9ad9e4SRobert Richter 	    || (mci->n_layers > 1 && layer1 < 0)
645bc9ad9e4SRobert Richter 	    || (mci->n_layers > 2 && layer2 < 0))
646bc9ad9e4SRobert Richter 		return NULL;
647bc9ad9e4SRobert Richter 
648bc9ad9e4SRobert Richter 	index = layer0;
649bc9ad9e4SRobert Richter 
650bc9ad9e4SRobert Richter 	if (mci->n_layers > 1)
651bc9ad9e4SRobert Richter 		index = index * mci->layers[1].size + layer1;
652bc9ad9e4SRobert Richter 
653bc9ad9e4SRobert Richter 	if (mci->n_layers > 2)
654bc9ad9e4SRobert Richter 		index = index * mci->layers[2].size + layer2;
655bc9ad9e4SRobert Richter 
656e370f886SBorislav Petkov 	if (index < 0 || index >= mci->tot_dimms)
657e370f886SBorislav Petkov 		return NULL;
658e370f886SBorislav Petkov 
659e370f886SBorislav Petkov 	if (WARN_ON_ONCE(mci->dimms[index]->idx != index))
660e370f886SBorislav Petkov 		return NULL;
661e370f886SBorislav Petkov 
662e370f886SBorislav Petkov 	return mci->dimms[index];
663bc9ad9e4SRobert Richter }
664db99ea5fSShiju Jose 
665f90b7381SShiju Jose #define EDAC_FEAT_NAME_LEN	128
666f90b7381SShiju Jose 
667db99ea5fSShiju Jose /* RAS feature type */
668db99ea5fSShiju Jose enum edac_dev_feat {
669f90b7381SShiju Jose 	RAS_FEAT_SCRUB,
670bcbd069bSShiju Jose 	RAS_FEAT_ECS,
671699ea521SShiju Jose 	RAS_FEAT_MEM_REPAIR,
672db99ea5fSShiju Jose 	RAS_FEAT_MAX
673db99ea5fSShiju Jose };
674db99ea5fSShiju Jose 
675f90b7381SShiju Jose /**
676f90b7381SShiju Jose  * struct edac_scrub_ops - scrub device operations (all elements optional)
677f90b7381SShiju Jose  * @read_addr: read base address of scrubbing range.
678f90b7381SShiju Jose  * @read_size: read offset of scrubbing range.
679f90b7381SShiju Jose  * @write_addr: set base address of the scrubbing range.
680f90b7381SShiju Jose  * @write_size: set offset of the scrubbing range.
681f90b7381SShiju Jose  * @get_enabled_bg: check if currently performing background scrub.
682f90b7381SShiju Jose  * @set_enabled_bg: start or stop a bg-scrub.
683f90b7381SShiju Jose  * @get_min_cycle: get minimum supported scrub cycle duration in seconds.
684f90b7381SShiju Jose  * @get_max_cycle: get maximum supported scrub cycle duration in seconds.
685f90b7381SShiju Jose  * @get_cycle_duration: get current scrub cycle duration in seconds.
686f90b7381SShiju Jose  * @set_cycle_duration: set current scrub cycle duration in seconds.
687f90b7381SShiju Jose  */
688f90b7381SShiju Jose struct edac_scrub_ops {
689f90b7381SShiju Jose 	int (*read_addr)(struct device *dev, void *drv_data, u64 *base);
690f90b7381SShiju Jose 	int (*read_size)(struct device *dev, void *drv_data, u64 *size);
691f90b7381SShiju Jose 	int (*write_addr)(struct device *dev, void *drv_data, u64 base);
692f90b7381SShiju Jose 	int (*write_size)(struct device *dev, void *drv_data, u64 size);
693f90b7381SShiju Jose 	int (*get_enabled_bg)(struct device *dev, void *drv_data, bool *enable);
694f90b7381SShiju Jose 	int (*set_enabled_bg)(struct device *dev, void *drv_data, bool enable);
695f90b7381SShiju Jose 	int (*get_min_cycle)(struct device *dev, void *drv_data,  u32 *min);
696f90b7381SShiju Jose 	int (*get_max_cycle)(struct device *dev, void *drv_data,  u32 *max);
697f90b7381SShiju Jose 	int (*get_cycle_duration)(struct device *dev, void *drv_data, u32 *cycle);
698f90b7381SShiju Jose 	int (*set_cycle_duration)(struct device *dev, void *drv_data, u32 cycle);
699f90b7381SShiju Jose };
700f90b7381SShiju Jose 
701f90b7381SShiju Jose #if IS_ENABLED(CONFIG_EDAC_SCRUB)
702f90b7381SShiju Jose int edac_scrub_get_desc(struct device *scrub_dev,
703f90b7381SShiju Jose 			const struct attribute_group **attr_groups,
704f90b7381SShiju Jose 			u8 instance);
705f90b7381SShiju Jose #else
edac_scrub_get_desc(struct device * scrub_dev,const struct attribute_group ** attr_groups,u8 instance)706f90b7381SShiju Jose static inline int edac_scrub_get_desc(struct device *scrub_dev,
707f90b7381SShiju Jose 				      const struct attribute_group **attr_groups,
708f90b7381SShiju Jose 				      u8 instance)
709f90b7381SShiju Jose { return -EOPNOTSUPP; }
710f90b7381SShiju Jose #endif /* CONFIG_EDAC_SCRUB */
711f90b7381SShiju Jose 
712bcbd069bSShiju Jose /**
713bcbd069bSShiju Jose  * struct edac_ecs_ops - ECS device operations (all elements optional)
714bcbd069bSShiju Jose  * @get_log_entry_type: read the log entry type value.
715bcbd069bSShiju Jose  * @set_log_entry_type: set the log entry type value.
716bcbd069bSShiju Jose  * @get_mode: read the mode value.
717bcbd069bSShiju Jose  * @set_mode: set the mode value.
718bcbd069bSShiju Jose  * @reset: reset the ECS counter.
719bcbd069bSShiju Jose  * @get_threshold: read the threshold count per gigabits of memory cells.
720bcbd069bSShiju Jose  * @set_threshold: set the threshold count per gigabits of memory cells.
721bcbd069bSShiju Jose  */
722bcbd069bSShiju Jose struct edac_ecs_ops {
723bcbd069bSShiju Jose 	int (*get_log_entry_type)(struct device *dev, void *drv_data, int fru_id, u32 *val);
724bcbd069bSShiju Jose 	int (*set_log_entry_type)(struct device *dev, void *drv_data, int fru_id, u32 val);
725bcbd069bSShiju Jose 	int (*get_mode)(struct device *dev, void *drv_data, int fru_id, u32 *val);
726bcbd069bSShiju Jose 	int (*set_mode)(struct device *dev, void *drv_data, int fru_id, u32 val);
727bcbd069bSShiju Jose 	int (*reset)(struct device *dev, void *drv_data, int fru_id, u32 val);
728bcbd069bSShiju Jose 	int (*get_threshold)(struct device *dev, void *drv_data, int fru_id, u32 *threshold);
729bcbd069bSShiju Jose 	int (*set_threshold)(struct device *dev, void *drv_data, int fru_id, u32 threshold);
730bcbd069bSShiju Jose };
731bcbd069bSShiju Jose 
732bcbd069bSShiju Jose struct edac_ecs_ex_info {
733bcbd069bSShiju Jose 	u16 num_media_frus;
734bcbd069bSShiju Jose };
735bcbd069bSShiju Jose 
736bcbd069bSShiju Jose #if IS_ENABLED(CONFIG_EDAC_ECS)
737bcbd069bSShiju Jose int edac_ecs_get_desc(struct device *ecs_dev,
738bcbd069bSShiju Jose 		      const struct attribute_group **attr_groups,
739bcbd069bSShiju Jose 		      u16 num_media_frus);
740bcbd069bSShiju Jose #else
edac_ecs_get_desc(struct device * ecs_dev,const struct attribute_group ** attr_groups,u16 num_media_frus)741bcbd069bSShiju Jose static inline int edac_ecs_get_desc(struct device *ecs_dev,
742bcbd069bSShiju Jose 				    const struct attribute_group **attr_groups,
743bcbd069bSShiju Jose 				    u16 num_media_frus)
744bcbd069bSShiju Jose { return -EOPNOTSUPP; }
745bcbd069bSShiju Jose #endif /* CONFIG_EDAC_ECS */
746bcbd069bSShiju Jose 
747699ea521SShiju Jose enum edac_mem_repair_type {
748699ea521SShiju Jose 	EDAC_REPAIR_MAX
749699ea521SShiju Jose };
750699ea521SShiju Jose 
751699ea521SShiju Jose enum edac_mem_repair_cmd {
752699ea521SShiju Jose 	EDAC_DO_MEM_REPAIR = 1,
753699ea521SShiju Jose };
754699ea521SShiju Jose 
755699ea521SShiju Jose /**
756699ea521SShiju Jose  * struct edac_mem_repair_ops - memory repair operations
757699ea521SShiju Jose  * (all elements are optional except do_repair, set_hpa/set_dpa)
758699ea521SShiju Jose  * @get_repair_type: get the memory repair type, listed in
759699ea521SShiju Jose  *			 enum edac_mem_repair_function.
760699ea521SShiju Jose  * @get_persist_mode: get the current persist mode.
761699ea521SShiju Jose  *		      false - Soft repair type (temporary repair).
762699ea521SShiju Jose  *		      true - Hard memory repair type (permanent repair).
763699ea521SShiju Jose  * @set_persist_mode: set the persist mode of the memory repair instance.
764699ea521SShiju Jose  * @get_repair_safe_when_in_use: get whether memory media is accessible and
765699ea521SShiju Jose  *				 data is retained during repair operation.
766699ea521SShiju Jose  * @get_hpa: get current host physical address (HPA) of memory to repair.
767699ea521SShiju Jose  * @set_hpa: set host physical address (HPA) of memory to repair.
768699ea521SShiju Jose  * @get_min_hpa: get the minimum supported host physical address (HPA).
769699ea521SShiju Jose  * @get_max_hpa: get the maximum supported host physical address (HPA).
770699ea521SShiju Jose  * @get_dpa: get current device physical address (DPA) of memory to repair.
771699ea521SShiju Jose  * @set_dpa: set device physical address (DPA) of memory to repair.
772699ea521SShiju Jose  *	     In some states of system configuration (e.g. before address decoders
773699ea521SShiju Jose  *	     have been configured), memory devices (e.g. CXL) may not have an active
774699ea521SShiju Jose  *	     mapping in the host physical address map. As such, the memory
775699ea521SShiju Jose  *	     to repair must be identified by a device specific physical addressing
776699ea521SShiju Jose  *	     scheme using a device physical address(DPA). The DPA and other control
777699ea521SShiju Jose  *	     attributes to use for the repair operations will be presented in related
778699ea521SShiju Jose  *	     error records.
779699ea521SShiju Jose  * @get_min_dpa: get the minimum supported device physical address (DPA).
780699ea521SShiju Jose  * @get_max_dpa: get the maximum supported device physical address (DPA).
781699ea521SShiju Jose  * @get_nibble_mask: get current nibble mask of memory to repair.
782699ea521SShiju Jose  * @set_nibble_mask: set nibble mask of memory to repair.
783*81e42fc1SShiju Jose  * @get_bank_group: get current bank group of memory to repair.
784*81e42fc1SShiju Jose  * @set_bank_group: set bank group of memory to repair.
785*81e42fc1SShiju Jose  * @get_bank: get current bank of memory to repair.
786*81e42fc1SShiju Jose  * @set_bank: set bank of memory to repair.
787*81e42fc1SShiju Jose  * @get_rank: get current rank of memory to repair.
788*81e42fc1SShiju Jose  * @set_rank: set rank of memory to repair.
789*81e42fc1SShiju Jose  * @get_row: get current row of memory to repair.
790*81e42fc1SShiju Jose  * @set_row: set row of memory to repair.
791*81e42fc1SShiju Jose  * @get_column: get current column of memory to repair.
792*81e42fc1SShiju Jose  * @set_column: set column of memory to repair.
793*81e42fc1SShiju Jose  * @get_channel: get current channel of memory to repair.
794*81e42fc1SShiju Jose  * @set_channel: set channel of memory to repair.
795*81e42fc1SShiju Jose  * @get_sub_channel: get current subchannel of memory to repair.
796*81e42fc1SShiju Jose  * @set_sub_channel: set subchannel of memory to repair.
797699ea521SShiju Jose  * @do_repair: Issue memory repair operation for the HPA/DPA and
798699ea521SShiju Jose  *	       other control attributes set for the memory to repair.
799699ea521SShiju Jose  *
800699ea521SShiju Jose  * All elements are optional except do_repair and at least one of set_hpa/set_dpa.
801699ea521SShiju Jose  */
802699ea521SShiju Jose struct edac_mem_repair_ops {
803699ea521SShiju Jose 	int (*get_repair_type)(struct device *dev, void *drv_data, const char **type);
804699ea521SShiju Jose 	int (*get_persist_mode)(struct device *dev, void *drv_data, bool *persist);
805699ea521SShiju Jose 	int (*set_persist_mode)(struct device *dev, void *drv_data, bool persist);
806699ea521SShiju Jose 	int (*get_repair_safe_when_in_use)(struct device *dev, void *drv_data, bool *safe);
807699ea521SShiju Jose 	int (*get_hpa)(struct device *dev, void *drv_data, u64 *hpa);
808699ea521SShiju Jose 	int (*set_hpa)(struct device *dev, void *drv_data, u64 hpa);
809699ea521SShiju Jose 	int (*get_min_hpa)(struct device *dev, void *drv_data, u64 *hpa);
810699ea521SShiju Jose 	int (*get_max_hpa)(struct device *dev, void *drv_data, u64 *hpa);
811699ea521SShiju Jose 	int (*get_dpa)(struct device *dev, void *drv_data, u64 *dpa);
812699ea521SShiju Jose 	int (*set_dpa)(struct device *dev, void *drv_data, u64 dpa);
813699ea521SShiju Jose 	int (*get_min_dpa)(struct device *dev, void *drv_data, u64 *dpa);
814699ea521SShiju Jose 	int (*get_max_dpa)(struct device *dev, void *drv_data, u64 *dpa);
815699ea521SShiju Jose 	int (*get_nibble_mask)(struct device *dev, void *drv_data, u32 *val);
816699ea521SShiju Jose 	int (*set_nibble_mask)(struct device *dev, void *drv_data, u32 val);
817*81e42fc1SShiju Jose 	int (*get_bank_group)(struct device *dev, void *drv_data, u32 *val);
818*81e42fc1SShiju Jose 	int (*set_bank_group)(struct device *dev, void *drv_data, u32 val);
819*81e42fc1SShiju Jose 	int (*get_bank)(struct device *dev, void *drv_data, u32 *val);
820*81e42fc1SShiju Jose 	int (*set_bank)(struct device *dev, void *drv_data, u32 val);
821*81e42fc1SShiju Jose 	int (*get_rank)(struct device *dev, void *drv_data, u32 *val);
822*81e42fc1SShiju Jose 	int (*set_rank)(struct device *dev, void *drv_data, u32 val);
823*81e42fc1SShiju Jose 	int (*get_row)(struct device *dev, void *drv_data, u32 *val);
824*81e42fc1SShiju Jose 	int (*set_row)(struct device *dev, void *drv_data, u32 val);
825*81e42fc1SShiju Jose 	int (*get_column)(struct device *dev, void *drv_data, u32 *val);
826*81e42fc1SShiju Jose 	int (*set_column)(struct device *dev, void *drv_data, u32 val);
827*81e42fc1SShiju Jose 	int (*get_channel)(struct device *dev, void *drv_data, u32 *val);
828*81e42fc1SShiju Jose 	int (*set_channel)(struct device *dev, void *drv_data, u32 val);
829*81e42fc1SShiju Jose 	int (*get_sub_channel)(struct device *dev, void *drv_data, u32 *val);
830*81e42fc1SShiju Jose 	int (*set_sub_channel)(struct device *dev, void *drv_data, u32 val);
831699ea521SShiju Jose 	int (*do_repair)(struct device *dev, void *drv_data, u32 val);
832699ea521SShiju Jose };
833699ea521SShiju Jose 
834699ea521SShiju Jose #if IS_ENABLED(CONFIG_EDAC_MEM_REPAIR)
835699ea521SShiju Jose int edac_mem_repair_get_desc(struct device *dev,
836699ea521SShiju Jose 			     const struct attribute_group **attr_groups,
837699ea521SShiju Jose 			     u8 instance);
838699ea521SShiju Jose #else
edac_mem_repair_get_desc(struct device * dev,const struct attribute_group ** attr_groups,u8 instance)839699ea521SShiju Jose static inline int edac_mem_repair_get_desc(struct device *dev,
840699ea521SShiju Jose 					   const struct attribute_group **attr_groups,
841699ea521SShiju Jose 					   u8 instance)
842699ea521SShiju Jose { return -EOPNOTSUPP; }
843699ea521SShiju Jose #endif /* CONFIG_EDAC_MEM_REPAIR */
844699ea521SShiju Jose 
845db99ea5fSShiju Jose /* EDAC device feature information structure */
846db99ea5fSShiju Jose struct edac_dev_data {
847bcbd069bSShiju Jose 	union {
848f90b7381SShiju Jose 		const struct edac_scrub_ops *scrub_ops;
849bcbd069bSShiju Jose 		const struct edac_ecs_ops *ecs_ops;
850699ea521SShiju Jose 		const struct edac_mem_repair_ops *mem_repair_ops;
851bcbd069bSShiju Jose 	};
852db99ea5fSShiju Jose 	u8 instance;
853db99ea5fSShiju Jose 	void *private;
854db99ea5fSShiju Jose };
855db99ea5fSShiju Jose 
856db99ea5fSShiju Jose struct edac_dev_feat_ctx {
857db99ea5fSShiju Jose 	struct device dev;
858db99ea5fSShiju Jose 	void *private;
859f90b7381SShiju Jose 	struct edac_dev_data *scrub;
860bcbd069bSShiju Jose 	struct edac_dev_data ecs;
861699ea521SShiju Jose 	struct edac_dev_data *mem_repair;
862db99ea5fSShiju Jose };
863db99ea5fSShiju Jose 
864db99ea5fSShiju Jose struct edac_dev_feature {
865db99ea5fSShiju Jose 	enum edac_dev_feat ft_type;
866db99ea5fSShiju Jose 	u8 instance;
867bcbd069bSShiju Jose 	union {
868f90b7381SShiju Jose 		const struct edac_scrub_ops *scrub_ops;
869bcbd069bSShiju Jose 		const struct edac_ecs_ops *ecs_ops;
870699ea521SShiju Jose 		const struct edac_mem_repair_ops *mem_repair_ops;
871bcbd069bSShiju Jose 	};
872db99ea5fSShiju Jose 	void *ctx;
873bcbd069bSShiju Jose 	struct edac_ecs_ex_info ecs_info;
874db99ea5fSShiju Jose };
875db99ea5fSShiju Jose 
876db99ea5fSShiju Jose int edac_dev_register(struct device *parent, char *dev_name,
877db99ea5fSShiju Jose 		      void *parent_pvt_data, int num_features,
878db99ea5fSShiju Jose 		      const struct edac_dev_feature *ras_features);
879bc9ad9e4SRobert Richter #endif /* _LINUX_EDAC_H_ */
880