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