/*1* Defines, structures, APIs for edac_pci and edac_pci_sysfs2*3* (C) 2007 Linux Networx (http://lnxi.com)4* This file may be distributed under the terms of the5* GNU General Public License.6*7* Written by Thayne Harbaugh8* Based on work by Dan Hollis <goemon at anime dot net> and others.9* http://www.anime.net/~goemon/linux-ecc/10*11* NMI handling support added by12* Dave Peterson <[email protected]> <[email protected]>13*14* Refactored for multi-source files:15* Doug Thompson <[email protected]>16*17* Please look at Documentation/driver-api/edac.rst for more info about18* EDAC core structs and functions.19*/2021#ifndef _EDAC_PCI_H_22#define _EDAC_PCI_H_2324#include <linux/device.h>25#include <linux/edac.h>26#include <linux/kobject.h>27#include <linux/list.h>28#include <linux/pci.h>29#include <linux/types.h>30#include <linux/workqueue.h>3132#ifdef CONFIG_PCI3334struct edac_pci_counter {35atomic_t pe_count;36atomic_t npe_count;37};3839/*40* Abstract edac_pci control info structure41*42*/43struct edac_pci_ctl_info {44/* for global list of edac_pci_ctl_info structs */45struct list_head link;4647int pci_idx;4849/* the internal state of this controller instance */50int op_state;51/* work struct for this instance */52struct delayed_work work;5354/* pointer to edac polling checking routine:55* If NOT NULL: points to polling check routine56* If NULL: Then assumes INTERRUPT operation, where57* MC driver will receive events58*/59void (*edac_check) (struct edac_pci_ctl_info * edac_dev);6061struct device *dev; /* pointer to device structure */6263const char *mod_name; /* module name */64const char *ctl_name; /* edac controller name */65const char *dev_name; /* pci/platform/etc... name */6667void *pvt_info; /* pointer to 'private driver' info */6869unsigned long start_time; /* edac_pci load start time (jiffies) */7071/* sysfs top name under 'edac' directory72* and instance name:73* cpu/cpu0/...74* cpu/cpu1/...75* cpu/cpu2/...76* ...77*/78char name[EDAC_DEVICE_NAME_LEN + 1];7980/* Event counters for the this whole EDAC Device */81struct edac_pci_counter counters;8283/* edac sysfs device control for the 'name'84* device this structure controls85*/86struct kobject kobj;87};8889#define to_edac_pci_ctl_work(w) \90container_of(w, struct edac_pci_ctl_info,work)9192/* write all or some bits in a byte-register*/93static inline void pci_write_bits8(struct pci_dev *pdev, int offset, u8 value,94u8 mask)95{96if (mask != 0xff) {97u8 buf;9899pci_read_config_byte(pdev, offset, &buf);100value &= mask;101buf &= ~mask;102value |= buf;103}104105pci_write_config_byte(pdev, offset, value);106}107108/* write all or some bits in a word-register*/109static inline void pci_write_bits16(struct pci_dev *pdev, int offset,110u16 value, u16 mask)111{112if (mask != 0xffff) {113u16 buf;114115pci_read_config_word(pdev, offset, &buf);116value &= mask;117buf &= ~mask;118value |= buf;119}120121pci_write_config_word(pdev, offset, value);122}123124/*125* pci_write_bits32126*127* edac local routine to do pci_write_config_dword, but adds128* a mask parameter. If mask is all ones, ignore the mask.129* Otherwise utilize the mask to isolate specified bits130*131* write all or some bits in a dword-register132*/133static inline void pci_write_bits32(struct pci_dev *pdev, int offset,134u32 value, u32 mask)135{136if (mask != 0xffffffff) {137u32 buf;138139pci_read_config_dword(pdev, offset, &buf);140value &= mask;141buf &= ~mask;142value |= buf;143}144145pci_write_config_dword(pdev, offset, value);146}147148#endif /* CONFIG_PCI */149150/*151* edac_pci APIs152*/153154/**155* edac_pci_alloc_ctl_info:156* The alloc() function for the 'edac_pci' control info157* structure.158*159* @sz_pvt: size of the private info at struct &edac_pci_ctl_info160* @edac_pci_name: name of the PCI device161*162* The chip driver will allocate one of these for each163* edac_pci it is going to control/register with the EDAC CORE.164*165* Returns: a pointer to struct &edac_pci_ctl_info on success; %NULL otherwise.166*/167extern struct edac_pci_ctl_info *edac_pci_alloc_ctl_info(unsigned int sz_pvt,168const char *edac_pci_name);169170/**171* edac_pci_free_ctl_info():172* Last action on the pci control structure.173*174* @pci: pointer to struct &edac_pci_ctl_info175*176* Calls the remove sysfs information, which will unregister177* this control struct's kobj. When that kobj's ref count178* goes to zero, its release function will be call and then179* kfree() the memory.180*/181extern void edac_pci_free_ctl_info(struct edac_pci_ctl_info *pci);182183/**184* edac_pci_alloc_index: Allocate a unique PCI index number185*186* Returns:187* allocated index number188*189*/190extern int edac_pci_alloc_index(void);191192/**193* edac_pci_add_device(): Insert the 'edac_dev' structure into the194* edac_pci global list and create sysfs entries associated with195* edac_pci structure.196*197* @pci: pointer to the edac_device structure to be added to the list198* @edac_idx: A unique numeric identifier to be assigned to the199* 'edac_pci' structure.200*201* Returns:202* 0 on Success, or an error code on failure203*/204extern int edac_pci_add_device(struct edac_pci_ctl_info *pci, int edac_idx);205206/**207* edac_pci_del_device()208* Remove sysfs entries for specified edac_pci structure and209* then remove edac_pci structure from global list210*211* @dev:212* Pointer to 'struct device' representing edac_pci structure213* to remove214*215* Returns:216* Pointer to removed edac_pci structure,217* or %NULL if device not found218*/219extern struct edac_pci_ctl_info *edac_pci_del_device(struct device *dev);220221/**222* edac_pci_create_generic_ctl()223* A generic constructor for a PCI parity polling device224* Some systems have more than one domain of PCI busses.225* For systems with one domain, then this API will226* provide for a generic poller.227*228* @dev: pointer to struct &device;229* @mod_name: name of the PCI device230*231* This routine calls the edac_pci_alloc_ctl_info() for232* the generic device, with default values233*234* Returns: Pointer to struct &edac_pci_ctl_info on success, %NULL on235* failure.236*/237extern struct edac_pci_ctl_info *edac_pci_create_generic_ctl(238struct device *dev,239const char *mod_name);240241/**242* edac_pci_release_generic_ctl243* The release function of a generic EDAC PCI polling device244*245* @pci: pointer to struct &edac_pci_ctl_info246*/247extern void edac_pci_release_generic_ctl(struct edac_pci_ctl_info *pci);248249/**250* edac_pci_create_sysfs251* Create the controls/attributes for the specified EDAC PCI device252*253* @pci: pointer to struct &edac_pci_ctl_info254*/255extern int edac_pci_create_sysfs(struct edac_pci_ctl_info *pci);256257/**258* edac_pci_remove_sysfs()259* remove the controls and attributes for this EDAC PCI device260*261* @pci: pointer to struct &edac_pci_ctl_info262*/263extern void edac_pci_remove_sysfs(struct edac_pci_ctl_info *pci);264265#endif266267268