/*1* Defines, structures, APIs for edac_device2*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_DEVICE_H_22#define _EDAC_DEVICE_H_2324#include <linux/device.h>25#include <linux/edac.h>26#include <linux/kobject.h>27#include <linux/list.h>28#include <linux/types.h>29#include <linux/sysfs.h>30#include <linux/workqueue.h>313233/*34* The following are the structures to provide for a generic35* or abstract 'edac_device'. This set of structures and the36* code that implements the APIs for the same, provide for37* registering EDAC type devices which are NOT standard memory.38*39* CPU caches (L1 and L2)40* DMA engines41* Core CPU switches42* Fabric switch units43* PCIe interface controllers44* other EDAC/ECC type devices that can be monitored for45* errors, etc.46*47* It allows for a 2 level set of hierarchy. For example:48*49* cache could be composed of L1, L2 and L3 levels of cache.50* Each CPU core would have its own L1 cache, while sharing51* L2 and maybe L3 caches.52*53* View them arranged, via the sysfs presentation:54* /sys/devices/system/edac/..55*56* mc/ <existing memory device directory>57* cpu/cpu0/.. <L1 and L2 block directory>58* /L1-cache/ce_count59* /ue_count60* /L2-cache/ce_count61* /ue_count62* cpu/cpu1/.. <L1 and L2 block directory>63* /L1-cache/ce_count64* /ue_count65* /L2-cache/ce_count66* /ue_count67* ...68*69* the L1 and L2 directories would be "edac_device_block's"70*/7172struct edac_device_counter {73u32 ue_count;74u32 ce_count;75};7677/* forward reference */78struct edac_device_ctl_info;79struct edac_device_block;8081/* edac_dev_sysfs_attribute structure82* used for driver sysfs attributes in mem_ctl_info83* for extra controls and attributes:84* like high level error Injection controls85*/86struct edac_dev_sysfs_attribute {87struct attribute attr;88ssize_t (*show)(struct edac_device_ctl_info *, char *);89ssize_t (*store)(struct edac_device_ctl_info *, const char *, size_t);90};9192/* edac_dev_sysfs_block_attribute structure93*94* used in leaf 'block' nodes for adding controls/attributes95*96* each block in each instance of the containing control structure can97* have an array of the following. The show function will be filled in98* with the show function in the low level driver.99*/100struct edac_dev_sysfs_block_attribute {101struct attribute attr;102ssize_t (*show)(struct kobject *, struct attribute *, char *);103};104105/* device block control structure */106struct edac_device_block {107struct edac_device_instance *instance; /* Up Pointer */108char name[EDAC_DEVICE_NAME_LEN + 1];109110struct edac_device_counter counters; /* basic UE and CE counters */111112int nr_attribs; /* how many attributes */113114/* this block's attributes, could be NULL */115struct edac_dev_sysfs_block_attribute *block_attributes;116117/* edac sysfs device control */118struct kobject kobj;119};120121/* device instance control structure */122struct edac_device_instance {123struct edac_device_ctl_info *ctl; /* Up pointer */124char name[EDAC_DEVICE_NAME_LEN + 4];125126struct edac_device_counter counters; /* instance counters */127128u32 nr_blocks; /* how many blocks */129struct edac_device_block *blocks; /* block array */130131/* edac sysfs device control */132struct kobject kobj;133};134135136/*137* Abstract edac_device control info structure138*139*/140struct edac_device_ctl_info {141/* for global list of edac_device_ctl_info structs */142struct list_head link;143144struct module *owner; /* Module owner of this control struct */145146int dev_idx;147148/* Per instance controls for this edac_device */149int log_ue; /* boolean for logging UEs */150int log_ce; /* boolean for logging CEs */151int panic_on_ue; /* boolean for panic'ing on an UE */152unsigned poll_msec; /* number of milliseconds to poll interval */153unsigned long delay; /* number of jiffies for poll_msec */154155/* Additional top controller level attributes, but specified156* by the low level driver.157*158* Set by the low level driver to provide attributes at the159* controller level, same level as 'ue_count' and 'ce_count' above.160* An array of structures, NULL terminated161*162* If attributes are desired, then set to array of attributes163* If no attributes are desired, leave NULL164*/165struct edac_dev_sysfs_attribute *sysfs_attributes;166167/* pointer to main 'edac' subsys in sysfs */168const struct bus_type *edac_subsys;169170/* the internal state of this controller instance */171int op_state;172/* work struct for this instance */173struct delayed_work work;174175/* pointer to edac polling checking routine:176* If NOT NULL: points to polling check routine177* If NULL: Then assumes INTERRUPT operation, where178* MC driver will receive events179*/180void (*edac_check) (struct edac_device_ctl_info * edac_dev);181182struct device *dev; /* pointer to device structure */183184const char *mod_name; /* module name */185const char *ctl_name; /* edac controller name */186const char *dev_name; /* pci/platform/etc... name */187188void *pvt_info; /* pointer to 'private driver' info */189190unsigned long start_time; /* edac_device load start time (jiffies) */191192/* sysfs top name under 'edac' directory193* and instance name:194* cpu/cpu0/...195* cpu/cpu1/...196* cpu/cpu2/...197* ...198*/199char name[EDAC_DEVICE_NAME_LEN + 1];200201/* Number of instances supported on this control structure202* and the array of those instances203*/204u32 nr_instances;205struct edac_device_instance *instances;206struct edac_device_block *blocks;207208/* Event counters for the this whole EDAC Device */209struct edac_device_counter counters;210211/* edac sysfs device control for the 'name'212* device this structure controls213*/214struct kobject kobj;215};216217/* To get from the instance's wq to the beginning of the ctl structure */218#define to_edac_mem_ctl_work(w) \219container_of(w, struct mem_ctl_info, work)220221#define to_edac_device_ctl_work(w) \222container_of(w,struct edac_device_ctl_info,work)223224/*225* The alloc() and free() functions for the 'edac_device' control info226* structure. A MC driver will allocate one of these for each edac_device227* it is going to control/register with the EDAC CORE.228*/229extern struct edac_device_ctl_info *edac_device_alloc_ctl_info(230unsigned sizeof_private,231char *edac_device_name, unsigned nr_instances,232char *edac_block_name, unsigned nr_blocks,233unsigned offset_value,234int device_index);235236/* The offset value can be:237* -1 indicating no offset value238* 0 for zero-based block numbers239* 1 for 1-based block number240* other for other-based block number241*/242#define BLOCK_OFFSET_VALUE_OFF ((unsigned) -1)243244extern void edac_device_free_ctl_info(struct edac_device_ctl_info *ctl_info);245246/**247* edac_device_add_device - Insert the 'edac_dev' structure into the248* edac_device global list and create sysfs entries associated with249* edac_device structure.250*251* @edac_dev: pointer to edac_device structure to be added to the list252* 'edac_device' structure.253*254* Returns:255* 0 on Success, or an error code on failure256*/257extern int edac_device_add_device(struct edac_device_ctl_info *edac_dev);258259/**260* edac_device_del_device - Remove sysfs entries for specified edac_device261* structure and then remove edac_device structure from global list262*263* @dev:264* Pointer to struct &device representing the edac device265* structure to remove.266*267* Returns:268* Pointer to removed edac_device structure,269* or %NULL if device not found.270*/271extern struct edac_device_ctl_info *edac_device_del_device(struct device *dev);272273/**274* edac_device_handle_ce_count - Log correctable errors.275*276* @edac_dev: pointer to struct &edac_device_ctl_info277* @inst_nr: number of the instance where the CE error happened278* @count: Number of errors to log.279* @block_nr: number of the block where the CE error happened280* @msg: message to be printed281*/282void edac_device_handle_ce_count(struct edac_device_ctl_info *edac_dev,283unsigned int count, int inst_nr, int block_nr,284const char *msg);285286/**287* edac_device_handle_ue_count - Log uncorrectable errors.288*289* @edac_dev: pointer to struct &edac_device_ctl_info290* @inst_nr: number of the instance where the CE error happened291* @count: Number of errors to log.292* @block_nr: number of the block where the CE error happened293* @msg: message to be printed294*/295void edac_device_handle_ue_count(struct edac_device_ctl_info *edac_dev,296unsigned int count, int inst_nr, int block_nr,297const char *msg);298299/**300* edac_device_handle_ce(): Log a single correctable error301*302* @edac_dev: pointer to struct &edac_device_ctl_info303* @inst_nr: number of the instance where the CE error happened304* @block_nr: number of the block where the CE error happened305* @msg: message to be printed306*/307static inline void308edac_device_handle_ce(struct edac_device_ctl_info *edac_dev, int inst_nr,309int block_nr, const char *msg)310{311edac_device_handle_ce_count(edac_dev, 1, inst_nr, block_nr, msg);312}313314/**315* edac_device_handle_ue(): Log a single uncorrectable error316*317* @edac_dev: pointer to struct &edac_device_ctl_info318* @inst_nr: number of the instance where the UE error happened319* @block_nr: number of the block where the UE error happened320* @msg: message to be printed321*/322static inline void323edac_device_handle_ue(struct edac_device_ctl_info *edac_dev, int inst_nr,324int block_nr, const char *msg)325{326edac_device_handle_ue_count(edac_dev, 1, inst_nr, block_nr, msg);327}328329/**330* edac_device_alloc_index: Allocate a unique device index number331*332* Returns:333* allocated index number334*/335extern int edac_device_alloc_index(void);336extern const char *edac_layer_name[];337338/* Free the actual struct */339static inline void __edac_device_free_ctl_info(struct edac_device_ctl_info *ci)340{341if (ci) {342kfree(ci->pvt_info);343kfree(ci->blocks);344kfree(ci->instances);345kfree(ci);346}347}348#endif349350351