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