xref: /OK3568_Linux_fs/kernel/drivers/edac/edac_pci.h (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * Defines, structures, APIs for edac_pci and edac_pci_sysfs
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  * (C) 2007 Linux Networx (http://lnxi.com)
5*4882a593Smuzhiyun  * This file may be distributed under the terms of the
6*4882a593Smuzhiyun  * GNU General Public License.
7*4882a593Smuzhiyun  *
8*4882a593Smuzhiyun  * Written by Thayne Harbaugh
9*4882a593Smuzhiyun  * Based on work by Dan Hollis <goemon at anime dot net> and others.
10*4882a593Smuzhiyun  *	http://www.anime.net/~goemon/linux-ecc/
11*4882a593Smuzhiyun  *
12*4882a593Smuzhiyun  * NMI handling support added by
13*4882a593Smuzhiyun  *     Dave Peterson <dsp@llnl.gov> <dave_peterson@pobox.com>
14*4882a593Smuzhiyun  *
15*4882a593Smuzhiyun  * Refactored for multi-source files:
16*4882a593Smuzhiyun  *	Doug Thompson <norsk5@xmission.com>
17*4882a593Smuzhiyun  *
18*4882a593Smuzhiyun  * Please look at Documentation/driver-api/edac.rst for more info about
19*4882a593Smuzhiyun  * EDAC core structs and functions.
20*4882a593Smuzhiyun  */
21*4882a593Smuzhiyun 
22*4882a593Smuzhiyun #ifndef _EDAC_PCI_H_
23*4882a593Smuzhiyun #define _EDAC_PCI_H_
24*4882a593Smuzhiyun 
25*4882a593Smuzhiyun #include <linux/completion.h>
26*4882a593Smuzhiyun #include <linux/device.h>
27*4882a593Smuzhiyun #include <linux/edac.h>
28*4882a593Smuzhiyun #include <linux/kobject.h>
29*4882a593Smuzhiyun #include <linux/list.h>
30*4882a593Smuzhiyun #include <linux/pci.h>
31*4882a593Smuzhiyun #include <linux/types.h>
32*4882a593Smuzhiyun #include <linux/workqueue.h>
33*4882a593Smuzhiyun 
34*4882a593Smuzhiyun #ifdef CONFIG_PCI
35*4882a593Smuzhiyun 
36*4882a593Smuzhiyun struct edac_pci_counter {
37*4882a593Smuzhiyun 	atomic_t pe_count;
38*4882a593Smuzhiyun 	atomic_t npe_count;
39*4882a593Smuzhiyun };
40*4882a593Smuzhiyun 
41*4882a593Smuzhiyun /*
42*4882a593Smuzhiyun  * Abstract edac_pci control info structure
43*4882a593Smuzhiyun  *
44*4882a593Smuzhiyun  */
45*4882a593Smuzhiyun struct edac_pci_ctl_info {
46*4882a593Smuzhiyun 	/* for global list of edac_pci_ctl_info structs */
47*4882a593Smuzhiyun 	struct list_head link;
48*4882a593Smuzhiyun 
49*4882a593Smuzhiyun 	int pci_idx;
50*4882a593Smuzhiyun 
51*4882a593Smuzhiyun 	struct bus_type *edac_subsys;	/* pointer to subsystem */
52*4882a593Smuzhiyun 
53*4882a593Smuzhiyun 	/* the internal state of this controller instance */
54*4882a593Smuzhiyun 	int op_state;
55*4882a593Smuzhiyun 	/* work struct for this instance */
56*4882a593Smuzhiyun 	struct delayed_work work;
57*4882a593Smuzhiyun 
58*4882a593Smuzhiyun 	/* pointer to edac polling checking routine:
59*4882a593Smuzhiyun 	 *      If NOT NULL: points to polling check routine
60*4882a593Smuzhiyun 	 *      If NULL: Then assumes INTERRUPT operation, where
61*4882a593Smuzhiyun 	 *              MC driver will receive events
62*4882a593Smuzhiyun 	 */
63*4882a593Smuzhiyun 	void (*edac_check) (struct edac_pci_ctl_info * edac_dev);
64*4882a593Smuzhiyun 
65*4882a593Smuzhiyun 	struct device *dev;	/* pointer to device structure */
66*4882a593Smuzhiyun 
67*4882a593Smuzhiyun 	const char *mod_name;	/* module name */
68*4882a593Smuzhiyun 	const char *ctl_name;	/* edac controller  name */
69*4882a593Smuzhiyun 	const char *dev_name;	/* pci/platform/etc... name */
70*4882a593Smuzhiyun 
71*4882a593Smuzhiyun 	void *pvt_info;		/* pointer to 'private driver' info */
72*4882a593Smuzhiyun 
73*4882a593Smuzhiyun 	unsigned long start_time;	/* edac_pci load start time (jiffies) */
74*4882a593Smuzhiyun 
75*4882a593Smuzhiyun 	struct completion complete;
76*4882a593Smuzhiyun 
77*4882a593Smuzhiyun 	/* sysfs top name under 'edac' directory
78*4882a593Smuzhiyun 	 * and instance name:
79*4882a593Smuzhiyun 	 *      cpu/cpu0/...
80*4882a593Smuzhiyun 	 *      cpu/cpu1/...
81*4882a593Smuzhiyun 	 *      cpu/cpu2/...
82*4882a593Smuzhiyun 	 *      ...
83*4882a593Smuzhiyun 	 */
84*4882a593Smuzhiyun 	char name[EDAC_DEVICE_NAME_LEN + 1];
85*4882a593Smuzhiyun 
86*4882a593Smuzhiyun 	/* Event counters for the this whole EDAC Device */
87*4882a593Smuzhiyun 	struct edac_pci_counter counters;
88*4882a593Smuzhiyun 
89*4882a593Smuzhiyun 	/* edac sysfs device control for the 'name'
90*4882a593Smuzhiyun 	 * device this structure controls
91*4882a593Smuzhiyun 	 */
92*4882a593Smuzhiyun 	struct kobject kobj;
93*4882a593Smuzhiyun };
94*4882a593Smuzhiyun 
95*4882a593Smuzhiyun #define to_edac_pci_ctl_work(w) \
96*4882a593Smuzhiyun 		container_of(w, struct edac_pci_ctl_info,work)
97*4882a593Smuzhiyun 
98*4882a593Smuzhiyun /* write all or some bits in a byte-register*/
pci_write_bits8(struct pci_dev * pdev,int offset,u8 value,u8 mask)99*4882a593Smuzhiyun static inline void pci_write_bits8(struct pci_dev *pdev, int offset, u8 value,
100*4882a593Smuzhiyun 				   u8 mask)
101*4882a593Smuzhiyun {
102*4882a593Smuzhiyun 	if (mask != 0xff) {
103*4882a593Smuzhiyun 		u8 buf;
104*4882a593Smuzhiyun 
105*4882a593Smuzhiyun 		pci_read_config_byte(pdev, offset, &buf);
106*4882a593Smuzhiyun 		value &= mask;
107*4882a593Smuzhiyun 		buf &= ~mask;
108*4882a593Smuzhiyun 		value |= buf;
109*4882a593Smuzhiyun 	}
110*4882a593Smuzhiyun 
111*4882a593Smuzhiyun 	pci_write_config_byte(pdev, offset, value);
112*4882a593Smuzhiyun }
113*4882a593Smuzhiyun 
114*4882a593Smuzhiyun /* write all or some bits in a word-register*/
pci_write_bits16(struct pci_dev * pdev,int offset,u16 value,u16 mask)115*4882a593Smuzhiyun static inline void pci_write_bits16(struct pci_dev *pdev, int offset,
116*4882a593Smuzhiyun 				    u16 value, u16 mask)
117*4882a593Smuzhiyun {
118*4882a593Smuzhiyun 	if (mask != 0xffff) {
119*4882a593Smuzhiyun 		u16 buf;
120*4882a593Smuzhiyun 
121*4882a593Smuzhiyun 		pci_read_config_word(pdev, offset, &buf);
122*4882a593Smuzhiyun 		value &= mask;
123*4882a593Smuzhiyun 		buf &= ~mask;
124*4882a593Smuzhiyun 		value |= buf;
125*4882a593Smuzhiyun 	}
126*4882a593Smuzhiyun 
127*4882a593Smuzhiyun 	pci_write_config_word(pdev, offset, value);
128*4882a593Smuzhiyun }
129*4882a593Smuzhiyun 
130*4882a593Smuzhiyun /*
131*4882a593Smuzhiyun  * pci_write_bits32
132*4882a593Smuzhiyun  *
133*4882a593Smuzhiyun  * edac local routine to do pci_write_config_dword, but adds
134*4882a593Smuzhiyun  * a mask parameter. If mask is all ones, ignore the mask.
135*4882a593Smuzhiyun  * Otherwise utilize the mask to isolate specified bits
136*4882a593Smuzhiyun  *
137*4882a593Smuzhiyun  * write all or some bits in a dword-register
138*4882a593Smuzhiyun  */
pci_write_bits32(struct pci_dev * pdev,int offset,u32 value,u32 mask)139*4882a593Smuzhiyun static inline void pci_write_bits32(struct pci_dev *pdev, int offset,
140*4882a593Smuzhiyun 				    u32 value, u32 mask)
141*4882a593Smuzhiyun {
142*4882a593Smuzhiyun 	if (mask != 0xffffffff) {
143*4882a593Smuzhiyun 		u32 buf;
144*4882a593Smuzhiyun 
145*4882a593Smuzhiyun 		pci_read_config_dword(pdev, offset, &buf);
146*4882a593Smuzhiyun 		value &= mask;
147*4882a593Smuzhiyun 		buf &= ~mask;
148*4882a593Smuzhiyun 		value |= buf;
149*4882a593Smuzhiyun 	}
150*4882a593Smuzhiyun 
151*4882a593Smuzhiyun 	pci_write_config_dword(pdev, offset, value);
152*4882a593Smuzhiyun }
153*4882a593Smuzhiyun 
154*4882a593Smuzhiyun #endif				/* CONFIG_PCI */
155*4882a593Smuzhiyun 
156*4882a593Smuzhiyun /*
157*4882a593Smuzhiyun  * edac_pci APIs
158*4882a593Smuzhiyun  */
159*4882a593Smuzhiyun 
160*4882a593Smuzhiyun /**
161*4882a593Smuzhiyun  * edac_pci_alloc_ctl_info:
162*4882a593Smuzhiyun  *	The alloc() function for the 'edac_pci' control info
163*4882a593Smuzhiyun  *	structure.
164*4882a593Smuzhiyun  *
165*4882a593Smuzhiyun  * @sz_pvt: size of the private info at struct &edac_pci_ctl_info
166*4882a593Smuzhiyun  * @edac_pci_name: name of the PCI device
167*4882a593Smuzhiyun  *
168*4882a593Smuzhiyun  * The chip driver will allocate one of these for each
169*4882a593Smuzhiyun  * edac_pci it is going to control/register with the EDAC CORE.
170*4882a593Smuzhiyun  *
171*4882a593Smuzhiyun  * Returns: a pointer to struct &edac_pci_ctl_info on success; %NULL otherwise.
172*4882a593Smuzhiyun  */
173*4882a593Smuzhiyun extern struct edac_pci_ctl_info *edac_pci_alloc_ctl_info(unsigned int sz_pvt,
174*4882a593Smuzhiyun 				const char *edac_pci_name);
175*4882a593Smuzhiyun 
176*4882a593Smuzhiyun /**
177*4882a593Smuzhiyun  * edac_pci_free_ctl_info():
178*4882a593Smuzhiyun  *	Last action on the pci control structure.
179*4882a593Smuzhiyun  *
180*4882a593Smuzhiyun  * @pci: pointer to struct &edac_pci_ctl_info
181*4882a593Smuzhiyun  *
182*4882a593Smuzhiyun  * Calls the remove sysfs information, which will unregister
183*4882a593Smuzhiyun  * this control struct's kobj. When that kobj's ref count
184*4882a593Smuzhiyun  * goes to zero, its release function will be call and then
185*4882a593Smuzhiyun  * kfree() the memory.
186*4882a593Smuzhiyun  */
187*4882a593Smuzhiyun extern void edac_pci_free_ctl_info(struct edac_pci_ctl_info *pci);
188*4882a593Smuzhiyun 
189*4882a593Smuzhiyun /**
190*4882a593Smuzhiyun  * edac_pci_alloc_index: Allocate a unique PCI index number
191*4882a593Smuzhiyun  *
192*4882a593Smuzhiyun  * Returns:
193*4882a593Smuzhiyun  *      allocated index number
194*4882a593Smuzhiyun  *
195*4882a593Smuzhiyun  */
196*4882a593Smuzhiyun extern int edac_pci_alloc_index(void);
197*4882a593Smuzhiyun 
198*4882a593Smuzhiyun /**
199*4882a593Smuzhiyun  * edac_pci_add_device(): Insert the 'edac_dev' structure into the
200*4882a593Smuzhiyun  *	edac_pci global list and create sysfs entries associated with
201*4882a593Smuzhiyun  *	edac_pci structure.
202*4882a593Smuzhiyun  *
203*4882a593Smuzhiyun  * @pci: pointer to the edac_device structure to be added to the list
204*4882a593Smuzhiyun  * @edac_idx: A unique numeric identifier to be assigned to the
205*4882a593Smuzhiyun  *	'edac_pci' structure.
206*4882a593Smuzhiyun  *
207*4882a593Smuzhiyun  * Returns:
208*4882a593Smuzhiyun  *	0 on Success, or an error code on failure
209*4882a593Smuzhiyun  */
210*4882a593Smuzhiyun extern int edac_pci_add_device(struct edac_pci_ctl_info *pci, int edac_idx);
211*4882a593Smuzhiyun 
212*4882a593Smuzhiyun /**
213*4882a593Smuzhiyun  * edac_pci_del_device()
214*4882a593Smuzhiyun  *	Remove sysfs entries for specified edac_pci structure and
215*4882a593Smuzhiyun  *	then remove edac_pci structure from global list
216*4882a593Smuzhiyun  *
217*4882a593Smuzhiyun  * @dev:
218*4882a593Smuzhiyun  *	Pointer to 'struct device' representing edac_pci structure
219*4882a593Smuzhiyun  *	to remove
220*4882a593Smuzhiyun  *
221*4882a593Smuzhiyun  * Returns:
222*4882a593Smuzhiyun  *	Pointer to removed edac_pci structure,
223*4882a593Smuzhiyun  *	or %NULL if device not found
224*4882a593Smuzhiyun  */
225*4882a593Smuzhiyun extern struct edac_pci_ctl_info *edac_pci_del_device(struct device *dev);
226*4882a593Smuzhiyun 
227*4882a593Smuzhiyun /**
228*4882a593Smuzhiyun  * edac_pci_create_generic_ctl()
229*4882a593Smuzhiyun  *	A generic constructor for a PCI parity polling device
230*4882a593Smuzhiyun  *	Some systems have more than one domain of PCI busses.
231*4882a593Smuzhiyun  *	For systems with one domain, then this API will
232*4882a593Smuzhiyun  *	provide for a generic poller.
233*4882a593Smuzhiyun  *
234*4882a593Smuzhiyun  * @dev: pointer to struct &device;
235*4882a593Smuzhiyun  * @mod_name: name of the PCI device
236*4882a593Smuzhiyun  *
237*4882a593Smuzhiyun  * This routine calls the edac_pci_alloc_ctl_info() for
238*4882a593Smuzhiyun  * the generic device, with default values
239*4882a593Smuzhiyun  *
240*4882a593Smuzhiyun  * Returns: Pointer to struct &edac_pci_ctl_info on success, %NULL on
241*4882a593Smuzhiyun  *	failure.
242*4882a593Smuzhiyun  */
243*4882a593Smuzhiyun extern struct edac_pci_ctl_info *edac_pci_create_generic_ctl(
244*4882a593Smuzhiyun 				struct device *dev,
245*4882a593Smuzhiyun 				const char *mod_name);
246*4882a593Smuzhiyun 
247*4882a593Smuzhiyun /**
248*4882a593Smuzhiyun  * edac_pci_release_generic_ctl
249*4882a593Smuzhiyun  *	The release function of a generic EDAC PCI polling device
250*4882a593Smuzhiyun  *
251*4882a593Smuzhiyun  * @pci: pointer to struct &edac_pci_ctl_info
252*4882a593Smuzhiyun  */
253*4882a593Smuzhiyun extern void edac_pci_release_generic_ctl(struct edac_pci_ctl_info *pci);
254*4882a593Smuzhiyun 
255*4882a593Smuzhiyun /**
256*4882a593Smuzhiyun  * edac_pci_create_sysfs
257*4882a593Smuzhiyun  *	Create the controls/attributes for the specified EDAC PCI device
258*4882a593Smuzhiyun  *
259*4882a593Smuzhiyun  * @pci: pointer to struct &edac_pci_ctl_info
260*4882a593Smuzhiyun  */
261*4882a593Smuzhiyun extern int edac_pci_create_sysfs(struct edac_pci_ctl_info *pci);
262*4882a593Smuzhiyun 
263*4882a593Smuzhiyun /**
264*4882a593Smuzhiyun  * edac_pci_remove_sysfs()
265*4882a593Smuzhiyun  *	remove the controls and attributes for this EDAC PCI device
266*4882a593Smuzhiyun  *
267*4882a593Smuzhiyun  * @pci: pointer to struct &edac_pci_ctl_info
268*4882a593Smuzhiyun  */
269*4882a593Smuzhiyun extern void edac_pci_remove_sysfs(struct edac_pci_ctl_info *pci);
270*4882a593Smuzhiyun 
271*4882a593Smuzhiyun #endif
272