xref: /openbmc/linux/drivers/edac/edac_pci.h (revision 9095bf25ea08135a5b74875dd0e3eeaddc4218a0)
10b892c71SMauro Carvalho Chehab /*
20b892c71SMauro Carvalho Chehab  * Defines, structures, APIs for edac_pci and edac_pci_sysfs
30b892c71SMauro Carvalho Chehab  *
40b892c71SMauro Carvalho Chehab  * (C) 2007 Linux Networx (http://lnxi.com)
50b892c71SMauro Carvalho Chehab  * This file may be distributed under the terms of the
60b892c71SMauro Carvalho Chehab  * GNU General Public License.
70b892c71SMauro Carvalho Chehab  *
80b892c71SMauro Carvalho Chehab  * Written by Thayne Harbaugh
90b892c71SMauro Carvalho Chehab  * Based on work by Dan Hollis <goemon at anime dot net> and others.
100b892c71SMauro Carvalho Chehab  *	http://www.anime.net/~goemon/linux-ecc/
110b892c71SMauro Carvalho Chehab  *
120b892c71SMauro Carvalho Chehab  * NMI handling support added by
130b892c71SMauro Carvalho Chehab  *     Dave Peterson <dsp@llnl.gov> <dave_peterson@pobox.com>
140b892c71SMauro Carvalho Chehab  *
150b892c71SMauro Carvalho Chehab  * Refactored for multi-source files:
160b892c71SMauro Carvalho Chehab  *	Doug Thompson <norsk5@xmission.com>
170b892c71SMauro Carvalho Chehab  *
180b892c71SMauro Carvalho Chehab  * Please look at Documentation/driver-api/edac.rst for more info about
190b892c71SMauro Carvalho Chehab  * EDAC core structs and functions.
200b892c71SMauro Carvalho Chehab  */
210b892c71SMauro Carvalho Chehab 
220b892c71SMauro Carvalho Chehab #ifndef _EDAC_PCI_H_
230b892c71SMauro Carvalho Chehab #define _EDAC_PCI_H_
240b892c71SMauro Carvalho Chehab 
250b892c71SMauro Carvalho Chehab #include <linux/completion.h>
260b892c71SMauro Carvalho Chehab #include <linux/device.h>
270b892c71SMauro Carvalho Chehab #include <linux/edac.h>
280b892c71SMauro Carvalho Chehab #include <linux/kobject.h>
290b892c71SMauro Carvalho Chehab #include <linux/list.h>
300b892c71SMauro Carvalho Chehab #include <linux/pci.h>
310b892c71SMauro Carvalho Chehab #include <linux/types.h>
320b892c71SMauro Carvalho Chehab #include <linux/workqueue.h>
330b892c71SMauro Carvalho Chehab 
340b892c71SMauro Carvalho Chehab #ifdef CONFIG_PCI
350b892c71SMauro Carvalho Chehab 
360b892c71SMauro Carvalho Chehab struct edac_pci_counter {
370b892c71SMauro Carvalho Chehab 	atomic_t pe_count;
380b892c71SMauro Carvalho Chehab 	atomic_t npe_count;
390b892c71SMauro Carvalho Chehab };
400b892c71SMauro Carvalho Chehab 
410b892c71SMauro Carvalho Chehab /*
420b892c71SMauro Carvalho Chehab  * Abstract edac_pci control info structure
430b892c71SMauro Carvalho Chehab  *
440b892c71SMauro Carvalho Chehab  */
450b892c71SMauro Carvalho Chehab struct edac_pci_ctl_info {
460b892c71SMauro Carvalho Chehab 	/* for global list of edac_pci_ctl_info structs */
470b892c71SMauro Carvalho Chehab 	struct list_head link;
480b892c71SMauro Carvalho Chehab 
490b892c71SMauro Carvalho Chehab 	int pci_idx;
500b892c71SMauro Carvalho Chehab 
510b892c71SMauro Carvalho Chehab 	struct bus_type *edac_subsys;	/* pointer to subsystem */
520b892c71SMauro Carvalho Chehab 
530b892c71SMauro Carvalho Chehab 	/* the internal state of this controller instance */
540b892c71SMauro Carvalho Chehab 	int op_state;
550b892c71SMauro Carvalho Chehab 	/* work struct for this instance */
560b892c71SMauro Carvalho Chehab 	struct delayed_work work;
570b892c71SMauro Carvalho Chehab 
580b892c71SMauro Carvalho Chehab 	/* pointer to edac polling checking routine:
590b892c71SMauro Carvalho Chehab 	 *      If NOT NULL: points to polling check routine
600b892c71SMauro Carvalho Chehab 	 *      If NULL: Then assumes INTERRUPT operation, where
610b892c71SMauro Carvalho Chehab 	 *              MC driver will receive events
620b892c71SMauro Carvalho Chehab 	 */
630b892c71SMauro Carvalho Chehab 	void (*edac_check) (struct edac_pci_ctl_info * edac_dev);
640b892c71SMauro Carvalho Chehab 
650b892c71SMauro Carvalho Chehab 	struct device *dev;	/* pointer to device structure */
660b892c71SMauro Carvalho Chehab 
670b892c71SMauro Carvalho Chehab 	const char *mod_name;	/* module name */
680b892c71SMauro Carvalho Chehab 	const char *ctl_name;	/* edac controller  name */
690b892c71SMauro Carvalho Chehab 	const char *dev_name;	/* pci/platform/etc... name */
700b892c71SMauro Carvalho Chehab 
710b892c71SMauro Carvalho Chehab 	void *pvt_info;		/* pointer to 'private driver' info */
720b892c71SMauro Carvalho Chehab 
730b892c71SMauro Carvalho Chehab 	unsigned long start_time;	/* edac_pci load start time (jiffies) */
740b892c71SMauro Carvalho Chehab 
750b892c71SMauro Carvalho Chehab 	struct completion complete;
760b892c71SMauro Carvalho Chehab 
770b892c71SMauro Carvalho Chehab 	/* sysfs top name under 'edac' directory
780b892c71SMauro Carvalho Chehab 	 * and instance name:
790b892c71SMauro Carvalho Chehab 	 *      cpu/cpu0/...
800b892c71SMauro Carvalho Chehab 	 *      cpu/cpu1/...
810b892c71SMauro Carvalho Chehab 	 *      cpu/cpu2/...
820b892c71SMauro Carvalho Chehab 	 *      ...
830b892c71SMauro Carvalho Chehab 	 */
840b892c71SMauro Carvalho Chehab 	char name[EDAC_DEVICE_NAME_LEN + 1];
850b892c71SMauro Carvalho Chehab 
860b892c71SMauro Carvalho Chehab 	/* Event counters for the this whole EDAC Device */
870b892c71SMauro Carvalho Chehab 	struct edac_pci_counter counters;
880b892c71SMauro Carvalho Chehab 
890b892c71SMauro Carvalho Chehab 	/* edac sysfs device control for the 'name'
900b892c71SMauro Carvalho Chehab 	 * device this structure controls
910b892c71SMauro Carvalho Chehab 	 */
920b892c71SMauro Carvalho Chehab 	struct kobject kobj;
930b892c71SMauro Carvalho Chehab };
940b892c71SMauro Carvalho Chehab 
950b892c71SMauro Carvalho Chehab #define to_edac_pci_ctl_work(w) \
960b892c71SMauro Carvalho Chehab 		container_of(w, struct edac_pci_ctl_info,work)
970b892c71SMauro Carvalho Chehab 
980b892c71SMauro Carvalho Chehab /* write all or some bits in a byte-register*/
pci_write_bits8(struct pci_dev * pdev,int offset,u8 value,u8 mask)990b892c71SMauro Carvalho Chehab static inline void pci_write_bits8(struct pci_dev *pdev, int offset, u8 value,
1000b892c71SMauro Carvalho Chehab 				   u8 mask)
1010b892c71SMauro Carvalho Chehab {
1020b892c71SMauro Carvalho Chehab 	if (mask != 0xff) {
1030b892c71SMauro Carvalho Chehab 		u8 buf;
1040b892c71SMauro Carvalho Chehab 
1050b892c71SMauro Carvalho Chehab 		pci_read_config_byte(pdev, offset, &buf);
1060b892c71SMauro Carvalho Chehab 		value &= mask;
1070b892c71SMauro Carvalho Chehab 		buf &= ~mask;
1080b892c71SMauro Carvalho Chehab 		value |= buf;
1090b892c71SMauro Carvalho Chehab 	}
1100b892c71SMauro Carvalho Chehab 
1110b892c71SMauro Carvalho Chehab 	pci_write_config_byte(pdev, offset, value);
1120b892c71SMauro Carvalho Chehab }
1130b892c71SMauro Carvalho Chehab 
1140b892c71SMauro Carvalho Chehab /* write all or some bits in a word-register*/
pci_write_bits16(struct pci_dev * pdev,int offset,u16 value,u16 mask)1150b892c71SMauro Carvalho Chehab static inline void pci_write_bits16(struct pci_dev *pdev, int offset,
1160b892c71SMauro Carvalho Chehab 				    u16 value, u16 mask)
1170b892c71SMauro Carvalho Chehab {
1180b892c71SMauro Carvalho Chehab 	if (mask != 0xffff) {
1190b892c71SMauro Carvalho Chehab 		u16 buf;
1200b892c71SMauro Carvalho Chehab 
1210b892c71SMauro Carvalho Chehab 		pci_read_config_word(pdev, offset, &buf);
1220b892c71SMauro Carvalho Chehab 		value &= mask;
1230b892c71SMauro Carvalho Chehab 		buf &= ~mask;
1240b892c71SMauro Carvalho Chehab 		value |= buf;
1250b892c71SMauro Carvalho Chehab 	}
1260b892c71SMauro Carvalho Chehab 
1270b892c71SMauro Carvalho Chehab 	pci_write_config_word(pdev, offset, value);
1280b892c71SMauro Carvalho Chehab }
1290b892c71SMauro Carvalho Chehab 
1300b892c71SMauro Carvalho Chehab /*
1310b892c71SMauro Carvalho Chehab  * pci_write_bits32
1320b892c71SMauro Carvalho Chehab  *
1330b892c71SMauro Carvalho Chehab  * edac local routine to do pci_write_config_dword, but adds
1340b892c71SMauro Carvalho Chehab  * a mask parameter. If mask is all ones, ignore the mask.
1350b892c71SMauro Carvalho Chehab  * Otherwise utilize the mask to isolate specified bits
1360b892c71SMauro Carvalho Chehab  *
1370b892c71SMauro Carvalho Chehab  * write all or some bits in a dword-register
1380b892c71SMauro Carvalho Chehab  */
pci_write_bits32(struct pci_dev * pdev,int offset,u32 value,u32 mask)1390b892c71SMauro Carvalho Chehab static inline void pci_write_bits32(struct pci_dev *pdev, int offset,
1400b892c71SMauro Carvalho Chehab 				    u32 value, u32 mask)
1410b892c71SMauro Carvalho Chehab {
1420b892c71SMauro Carvalho Chehab 	if (mask != 0xffffffff) {
1430b892c71SMauro Carvalho Chehab 		u32 buf;
1440b892c71SMauro Carvalho Chehab 
1450b892c71SMauro Carvalho Chehab 		pci_read_config_dword(pdev, offset, &buf);
1460b892c71SMauro Carvalho Chehab 		value &= mask;
1470b892c71SMauro Carvalho Chehab 		buf &= ~mask;
1480b892c71SMauro Carvalho Chehab 		value |= buf;
1490b892c71SMauro Carvalho Chehab 	}
1500b892c71SMauro Carvalho Chehab 
1510b892c71SMauro Carvalho Chehab 	pci_write_config_dword(pdev, offset, value);
1520b892c71SMauro Carvalho Chehab }
1530b892c71SMauro Carvalho Chehab 
1540b892c71SMauro Carvalho Chehab #endif				/* CONFIG_PCI */
1550b892c71SMauro Carvalho Chehab 
156*fdaf0b35SMauro Carvalho Chehab /*
157*fdaf0b35SMauro Carvalho Chehab  * edac_pci APIs
158*fdaf0b35SMauro Carvalho Chehab  */
159*fdaf0b35SMauro Carvalho Chehab 
160*fdaf0b35SMauro Carvalho Chehab /**
161*fdaf0b35SMauro Carvalho Chehab  * edac_pci_alloc_ctl_info:
162*fdaf0b35SMauro Carvalho Chehab  *	The alloc() function for the 'edac_pci' control info
163*fdaf0b35SMauro Carvalho Chehab  *	structure.
164*fdaf0b35SMauro Carvalho Chehab  *
165*fdaf0b35SMauro Carvalho Chehab  * @sz_pvt: size of the private info at struct &edac_pci_ctl_info
166*fdaf0b35SMauro Carvalho Chehab  * @edac_pci_name: name of the PCI device
167*fdaf0b35SMauro Carvalho Chehab  *
168*fdaf0b35SMauro Carvalho Chehab  * The chip driver will allocate one of these for each
169*fdaf0b35SMauro Carvalho Chehab  * edac_pci it is going to control/register with the EDAC CORE.
170*fdaf0b35SMauro Carvalho Chehab  *
171*fdaf0b35SMauro Carvalho Chehab  * Returns: a pointer to struct &edac_pci_ctl_info on success; %NULL otherwise.
172*fdaf0b35SMauro Carvalho Chehab  */
1730b892c71SMauro Carvalho Chehab extern struct edac_pci_ctl_info *edac_pci_alloc_ctl_info(unsigned int sz_pvt,
1740b892c71SMauro Carvalho Chehab 				const char *edac_pci_name);
1750b892c71SMauro Carvalho Chehab 
176*fdaf0b35SMauro Carvalho Chehab /**
177*fdaf0b35SMauro Carvalho Chehab  * edac_pci_free_ctl_info():
178*fdaf0b35SMauro Carvalho Chehab  *	Last action on the pci control structure.
179*fdaf0b35SMauro Carvalho Chehab  *
180*fdaf0b35SMauro Carvalho Chehab  * @pci: pointer to struct &edac_pci_ctl_info
181*fdaf0b35SMauro Carvalho Chehab  *
182*fdaf0b35SMauro Carvalho Chehab  * Calls the remove sysfs information, which will unregister
183*fdaf0b35SMauro Carvalho Chehab  * this control struct's kobj. When that kobj's ref count
184*fdaf0b35SMauro Carvalho Chehab  * goes to zero, its release function will be call and then
185*fdaf0b35SMauro Carvalho Chehab  * kfree() the memory.
186*fdaf0b35SMauro Carvalho Chehab  */
1870b892c71SMauro Carvalho Chehab extern void edac_pci_free_ctl_info(struct edac_pci_ctl_info *pci);
1880b892c71SMauro Carvalho Chehab 
189*fdaf0b35SMauro Carvalho Chehab /**
190*fdaf0b35SMauro Carvalho Chehab  * edac_pci_alloc_index: Allocate a unique PCI index number
191*fdaf0b35SMauro Carvalho Chehab  *
192*fdaf0b35SMauro Carvalho Chehab  * Returns:
193*fdaf0b35SMauro Carvalho Chehab  *      allocated index number
194*fdaf0b35SMauro Carvalho Chehab  *
195*fdaf0b35SMauro Carvalho Chehab  */
1960b892c71SMauro Carvalho Chehab extern int edac_pci_alloc_index(void);
197*fdaf0b35SMauro Carvalho Chehab 
198*fdaf0b35SMauro Carvalho Chehab /**
199*fdaf0b35SMauro Carvalho Chehab  * edac_pci_add_device(): Insert the 'edac_dev' structure into the
200*fdaf0b35SMauro Carvalho Chehab  *	edac_pci global list and create sysfs entries associated with
201*fdaf0b35SMauro Carvalho Chehab  *	edac_pci structure.
202*fdaf0b35SMauro Carvalho Chehab  *
203*fdaf0b35SMauro Carvalho Chehab  * @pci: pointer to the edac_device structure to be added to the list
204*fdaf0b35SMauro Carvalho Chehab  * @edac_idx: A unique numeric identifier to be assigned to the
205*fdaf0b35SMauro Carvalho Chehab  *	'edac_pci' structure.
206*fdaf0b35SMauro Carvalho Chehab  *
207*fdaf0b35SMauro Carvalho Chehab  * Returns:
208*fdaf0b35SMauro Carvalho Chehab  *	0 on Success, or an error code on failure
209*fdaf0b35SMauro Carvalho Chehab  */
2100b892c71SMauro Carvalho Chehab extern int edac_pci_add_device(struct edac_pci_ctl_info *pci, int edac_idx);
211*fdaf0b35SMauro Carvalho Chehab 
212*fdaf0b35SMauro Carvalho Chehab /**
213*fdaf0b35SMauro Carvalho Chehab  * edac_pci_del_device()
214*fdaf0b35SMauro Carvalho Chehab  *	Remove sysfs entries for specified edac_pci structure and
215*fdaf0b35SMauro Carvalho Chehab  *	then remove edac_pci structure from global list
216*fdaf0b35SMauro Carvalho Chehab  *
217*fdaf0b35SMauro Carvalho Chehab  * @dev:
218*fdaf0b35SMauro Carvalho Chehab  *	Pointer to 'struct device' representing edac_pci structure
219*fdaf0b35SMauro Carvalho Chehab  *	to remove
220*fdaf0b35SMauro Carvalho Chehab  *
221*fdaf0b35SMauro Carvalho Chehab  * Returns:
222*fdaf0b35SMauro Carvalho Chehab  *	Pointer to removed edac_pci structure,
223*fdaf0b35SMauro Carvalho Chehab  *	or %NULL if device not found
224*fdaf0b35SMauro Carvalho Chehab  */
2250b892c71SMauro Carvalho Chehab extern struct edac_pci_ctl_info *edac_pci_del_device(struct device *dev);
2260b892c71SMauro Carvalho Chehab 
227*fdaf0b35SMauro Carvalho Chehab /**
228*fdaf0b35SMauro Carvalho Chehab  * edac_pci_create_generic_ctl()
229*fdaf0b35SMauro Carvalho Chehab  *	A generic constructor for a PCI parity polling device
230*fdaf0b35SMauro Carvalho Chehab  *	Some systems have more than one domain of PCI busses.
231*fdaf0b35SMauro Carvalho Chehab  *	For systems with one domain, then this API will
232*fdaf0b35SMauro Carvalho Chehab  *	provide for a generic poller.
233*fdaf0b35SMauro Carvalho Chehab  *
234*fdaf0b35SMauro Carvalho Chehab  * @dev: pointer to struct &device;
235*fdaf0b35SMauro Carvalho Chehab  * @mod_name: name of the PCI device
236*fdaf0b35SMauro Carvalho Chehab  *
237*fdaf0b35SMauro Carvalho Chehab  * This routine calls the edac_pci_alloc_ctl_info() for
238*fdaf0b35SMauro Carvalho Chehab  * the generic device, with default values
239*fdaf0b35SMauro Carvalho Chehab  *
240*fdaf0b35SMauro Carvalho Chehab  * Returns: Pointer to struct &edac_pci_ctl_info on success, %NULL on
241*fdaf0b35SMauro Carvalho Chehab  *	failure.
242*fdaf0b35SMauro Carvalho Chehab  */
2430b892c71SMauro Carvalho Chehab extern struct edac_pci_ctl_info *edac_pci_create_generic_ctl(
2440b892c71SMauro Carvalho Chehab 				struct device *dev,
2450b892c71SMauro Carvalho Chehab 				const char *mod_name);
2460b892c71SMauro Carvalho Chehab 
247*fdaf0b35SMauro Carvalho Chehab /**
248*fdaf0b35SMauro Carvalho Chehab  * edac_pci_release_generic_ctl
249*fdaf0b35SMauro Carvalho Chehab  *	The release function of a generic EDAC PCI polling device
250*fdaf0b35SMauro Carvalho Chehab  *
251*fdaf0b35SMauro Carvalho Chehab  * @pci: pointer to struct &edac_pci_ctl_info
252*fdaf0b35SMauro Carvalho Chehab  */
2530b892c71SMauro Carvalho Chehab extern void edac_pci_release_generic_ctl(struct edac_pci_ctl_info *pci);
254*fdaf0b35SMauro Carvalho Chehab 
255*fdaf0b35SMauro Carvalho Chehab /**
256*fdaf0b35SMauro Carvalho Chehab  * edac_pci_create_sysfs
257*fdaf0b35SMauro Carvalho Chehab  *	Create the controls/attributes for the specified EDAC PCI device
258*fdaf0b35SMauro Carvalho Chehab  *
259*fdaf0b35SMauro Carvalho Chehab  * @pci: pointer to struct &edac_pci_ctl_info
260*fdaf0b35SMauro Carvalho Chehab  */
2610b892c71SMauro Carvalho Chehab extern int edac_pci_create_sysfs(struct edac_pci_ctl_info *pci);
262*fdaf0b35SMauro Carvalho Chehab 
263*fdaf0b35SMauro Carvalho Chehab /**
264*fdaf0b35SMauro Carvalho Chehab  * edac_pci_remove_sysfs()
265*fdaf0b35SMauro Carvalho Chehab  *	remove the controls and attributes for this EDAC PCI device
266*fdaf0b35SMauro Carvalho Chehab  *
267*fdaf0b35SMauro Carvalho Chehab  * @pci: pointer to struct &edac_pci_ctl_info
268*fdaf0b35SMauro Carvalho Chehab  */
2690b892c71SMauro Carvalho Chehab extern void edac_pci_remove_sysfs(struct edac_pci_ctl_info *pci);
2700b892c71SMauro Carvalho Chehab 
2710b892c71SMauro Carvalho Chehab #endif
272