Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Defines, structures, APIs for edac_pci and edac_pci_sysfs
0003  *
0004  * (C) 2007 Linux Networx (http://lnxi.com)
0005  * This file may be distributed under the terms of the
0006  * GNU General Public License.
0007  *
0008  * Written by Thayne Harbaugh
0009  * Based on work by Dan Hollis <goemon at anime dot net> and others.
0010  *  http://www.anime.net/~goemon/linux-ecc/
0011  *
0012  * NMI handling support added by
0013  *     Dave Peterson <dsp@llnl.gov> <dave_peterson@pobox.com>
0014  *
0015  * Refactored for multi-source files:
0016  *  Doug Thompson <norsk5@xmission.com>
0017  *
0018  * Please look at Documentation/driver-api/edac.rst for more info about
0019  * EDAC core structs and functions.
0020  */
0021 
0022 #ifndef _EDAC_PCI_H_
0023 #define _EDAC_PCI_H_
0024 
0025 #include <linux/completion.h>
0026 #include <linux/device.h>
0027 #include <linux/edac.h>
0028 #include <linux/kobject.h>
0029 #include <linux/list.h>
0030 #include <linux/pci.h>
0031 #include <linux/types.h>
0032 #include <linux/workqueue.h>
0033 
0034 #ifdef CONFIG_PCI
0035 
0036 struct edac_pci_counter {
0037     atomic_t pe_count;
0038     atomic_t npe_count;
0039 };
0040 
0041 /*
0042  * Abstract edac_pci control info structure
0043  *
0044  */
0045 struct edac_pci_ctl_info {
0046     /* for global list of edac_pci_ctl_info structs */
0047     struct list_head link;
0048 
0049     int pci_idx;
0050 
0051     struct bus_type *edac_subsys;   /* pointer to subsystem */
0052 
0053     /* the internal state of this controller instance */
0054     int op_state;
0055     /* work struct for this instance */
0056     struct delayed_work work;
0057 
0058     /* pointer to edac polling checking routine:
0059      *      If NOT NULL: points to polling check routine
0060      *      If NULL: Then assumes INTERRUPT operation, where
0061      *              MC driver will receive events
0062      */
0063     void (*edac_check) (struct edac_pci_ctl_info * edac_dev);
0064 
0065     struct device *dev; /* pointer to device structure */
0066 
0067     const char *mod_name;   /* module name */
0068     const char *ctl_name;   /* edac controller  name */
0069     const char *dev_name;   /* pci/platform/etc... name */
0070 
0071     void *pvt_info;     /* pointer to 'private driver' info */
0072 
0073     unsigned long start_time;   /* edac_pci load start time (jiffies) */
0074 
0075     struct completion complete;
0076 
0077     /* sysfs top name under 'edac' directory
0078      * and instance name:
0079      *      cpu/cpu0/...
0080      *      cpu/cpu1/...
0081      *      cpu/cpu2/...
0082      *      ...
0083      */
0084     char name[EDAC_DEVICE_NAME_LEN + 1];
0085 
0086     /* Event counters for the this whole EDAC Device */
0087     struct edac_pci_counter counters;
0088 
0089     /* edac sysfs device control for the 'name'
0090      * device this structure controls
0091      */
0092     struct kobject kobj;
0093 };
0094 
0095 #define to_edac_pci_ctl_work(w) \
0096         container_of(w, struct edac_pci_ctl_info,work)
0097 
0098 /* write all or some bits in a byte-register*/
0099 static inline void pci_write_bits8(struct pci_dev *pdev, int offset, u8 value,
0100                    u8 mask)
0101 {
0102     if (mask != 0xff) {
0103         u8 buf;
0104 
0105         pci_read_config_byte(pdev, offset, &buf);
0106         value &= mask;
0107         buf &= ~mask;
0108         value |= buf;
0109     }
0110 
0111     pci_write_config_byte(pdev, offset, value);
0112 }
0113 
0114 /* write all or some bits in a word-register*/
0115 static inline void pci_write_bits16(struct pci_dev *pdev, int offset,
0116                     u16 value, u16 mask)
0117 {
0118     if (mask != 0xffff) {
0119         u16 buf;
0120 
0121         pci_read_config_word(pdev, offset, &buf);
0122         value &= mask;
0123         buf &= ~mask;
0124         value |= buf;
0125     }
0126 
0127     pci_write_config_word(pdev, offset, value);
0128 }
0129 
0130 /*
0131  * pci_write_bits32
0132  *
0133  * edac local routine to do pci_write_config_dword, but adds
0134  * a mask parameter. If mask is all ones, ignore the mask.
0135  * Otherwise utilize the mask to isolate specified bits
0136  *
0137  * write all or some bits in a dword-register
0138  */
0139 static inline void pci_write_bits32(struct pci_dev *pdev, int offset,
0140                     u32 value, u32 mask)
0141 {
0142     if (mask != 0xffffffff) {
0143         u32 buf;
0144 
0145         pci_read_config_dword(pdev, offset, &buf);
0146         value &= mask;
0147         buf &= ~mask;
0148         value |= buf;
0149     }
0150 
0151     pci_write_config_dword(pdev, offset, value);
0152 }
0153 
0154 #endif              /* CONFIG_PCI */
0155 
0156 /*
0157  * edac_pci APIs
0158  */
0159 
0160 /**
0161  * edac_pci_alloc_ctl_info:
0162  *  The alloc() function for the 'edac_pci' control info
0163  *  structure.
0164  *
0165  * @sz_pvt: size of the private info at struct &edac_pci_ctl_info
0166  * @edac_pci_name: name of the PCI device
0167  *
0168  * The chip driver will allocate one of these for each
0169  * edac_pci it is going to control/register with the EDAC CORE.
0170  *
0171  * Returns: a pointer to struct &edac_pci_ctl_info on success; %NULL otherwise.
0172  */
0173 extern struct edac_pci_ctl_info *edac_pci_alloc_ctl_info(unsigned int sz_pvt,
0174                 const char *edac_pci_name);
0175 
0176 /**
0177  * edac_pci_free_ctl_info():
0178  *  Last action on the pci control structure.
0179  *
0180  * @pci: pointer to struct &edac_pci_ctl_info
0181  *
0182  * Calls the remove sysfs information, which will unregister
0183  * this control struct's kobj. When that kobj's ref count
0184  * goes to zero, its release function will be call and then
0185  * kfree() the memory.
0186  */
0187 extern void edac_pci_free_ctl_info(struct edac_pci_ctl_info *pci);
0188 
0189 /**
0190  * edac_pci_alloc_index: Allocate a unique PCI index number
0191  *
0192  * Returns:
0193  *      allocated index number
0194  *
0195  */
0196 extern int edac_pci_alloc_index(void);
0197 
0198 /**
0199  * edac_pci_add_device(): Insert the 'edac_dev' structure into the
0200  *  edac_pci global list and create sysfs entries associated with
0201  *  edac_pci structure.
0202  *
0203  * @pci: pointer to the edac_device structure to be added to the list
0204  * @edac_idx: A unique numeric identifier to be assigned to the
0205  *  'edac_pci' structure.
0206  *
0207  * Returns:
0208  *  0 on Success, or an error code on failure
0209  */
0210 extern int edac_pci_add_device(struct edac_pci_ctl_info *pci, int edac_idx);
0211 
0212 /**
0213  * edac_pci_del_device()
0214  *  Remove sysfs entries for specified edac_pci structure and
0215  *  then remove edac_pci structure from global list
0216  *
0217  * @dev:
0218  *  Pointer to 'struct device' representing edac_pci structure
0219  *  to remove
0220  *
0221  * Returns:
0222  *  Pointer to removed edac_pci structure,
0223  *  or %NULL if device not found
0224  */
0225 extern struct edac_pci_ctl_info *edac_pci_del_device(struct device *dev);
0226 
0227 /**
0228  * edac_pci_create_generic_ctl()
0229  *  A generic constructor for a PCI parity polling device
0230  *  Some systems have more than one domain of PCI busses.
0231  *  For systems with one domain, then this API will
0232  *  provide for a generic poller.
0233  *
0234  * @dev: pointer to struct &device;
0235  * @mod_name: name of the PCI device
0236  *
0237  * This routine calls the edac_pci_alloc_ctl_info() for
0238  * the generic device, with default values
0239  *
0240  * Returns: Pointer to struct &edac_pci_ctl_info on success, %NULL on
0241  *  failure.
0242  */
0243 extern struct edac_pci_ctl_info *edac_pci_create_generic_ctl(
0244                 struct device *dev,
0245                 const char *mod_name);
0246 
0247 /**
0248  * edac_pci_release_generic_ctl
0249  *  The release function of a generic EDAC PCI polling device
0250  *
0251  * @pci: pointer to struct &edac_pci_ctl_info
0252  */
0253 extern void edac_pci_release_generic_ctl(struct edac_pci_ctl_info *pci);
0254 
0255 /**
0256  * edac_pci_create_sysfs
0257  *  Create the controls/attributes for the specified EDAC PCI device
0258  *
0259  * @pci: pointer to struct &edac_pci_ctl_info
0260  */
0261 extern int edac_pci_create_sysfs(struct edac_pci_ctl_info *pci);
0262 
0263 /**
0264  * edac_pci_remove_sysfs()
0265  *  remove the controls and attributes for this EDAC PCI device
0266  *
0267  * @pci: pointer to struct &edac_pci_ctl_info
0268  */
0269 extern void edac_pci_remove_sysfs(struct edac_pci_ctl_info *pci);
0270 
0271 #endif