/*1* Defines, structures, APIs for edac_mc module2*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_MC_H_22#define _EDAC_MC_H_2324#include <linux/kernel.h>25#include <linux/types.h>26#include <linux/module.h>27#include <linux/spinlock.h>28#include <linux/smp.h>29#include <linux/pci.h>30#include <linux/time.h>31#include <linux/nmi.h>32#include <linux/rcupdate.h>33#include <linux/completion.h>34#include <linux/kobject.h>35#include <linux/platform_device.h>36#include <linux/workqueue.h>37#include <linux/edac.h>3839#if PAGE_SHIFT < 2040#define PAGES_TO_MiB(pages) ((pages) >> (20 - PAGE_SHIFT))41#define MiB_TO_PAGES(mb) ((mb) << (20 - PAGE_SHIFT))42#else /* PAGE_SHIFT > 20 */43#define PAGES_TO_MiB(pages) ((pages) << (PAGE_SHIFT - 20))44#define MiB_TO_PAGES(mb) ((mb) >> (PAGE_SHIFT - 20))45#endif4647#define edac_printk(level, prefix, fmt, arg...) \48printk(level "EDAC " prefix ": " fmt, ##arg)4950#define edac_mc_printk(mci, level, fmt, arg...) \51printk(level "EDAC MC%d: " fmt, mci->mc_idx, ##arg)5253#define edac_mc_chipset_printk(mci, level, prefix, fmt, arg...) \54printk(level "EDAC " prefix " MC%d: " fmt, mci->mc_idx, ##arg)5556#define edac_device_printk(ctl, level, fmt, arg...) \57printk(level "EDAC DEVICE%d: " fmt, ctl->dev_idx, ##arg)5859#define edac_pci_printk(ctl, level, fmt, arg...) \60printk(level "EDAC PCI%d: " fmt, ctl->pci_idx, ##arg)6162/* prefixes for edac_printk() and edac_mc_printk() */63#define EDAC_MC "MC"64#define EDAC_PCI "PCI"65#define EDAC_DEBUG "DEBUG"6667extern const char * const edac_mem_types[];6869#ifdef CONFIG_EDAC_DEBUG70extern int edac_debug_level;7172#define edac_dbg(level, fmt, ...) \73do { \74if (level <= edac_debug_level) \75edac_printk(KERN_DEBUG, EDAC_DEBUG, \76"%s: " fmt, __func__, ##__VA_ARGS__); \77} while (0)7879#else /* !CONFIG_EDAC_DEBUG */8081#define edac_dbg(level, fmt, ...) \82do { \83if (0) \84edac_printk(KERN_DEBUG, EDAC_DEBUG, \85"%s: " fmt, __func__, ##__VA_ARGS__); \86} while (0)8788#endif /* !CONFIG_EDAC_DEBUG */8990#define PCI_VEND_DEV(vend, dev) PCI_VENDOR_ID_ ## vend, \91PCI_DEVICE_ID_ ## vend ## _ ## dev9293#define edac_dev_name(dev) (dev)->dev_name9495#define to_mci(k) container_of(k, struct mem_ctl_info, dev)9697/**98* edac_mc_alloc() - Allocate and partially fill a struct &mem_ctl_info.99*100* @mc_num: Memory controller number101* @n_layers: Number of MC hierarchy layers102* @layers: Describes each layer as seen by the Memory Controller103* @sz_pvt: size of private storage needed104*105*106* Everything is kmalloc'ed as one big chunk - more efficient.107* Only can be used if all structures have the same lifetime - otherwise108* you have to allocate and initialize your own structures.109*110* Use edac_mc_free() to free mc structures allocated by this function.111*112* .. note::113*114* drivers handle multi-rank memories in different ways: in some115* drivers, one multi-rank memory stick is mapped as one entry, while, in116* others, a single multi-rank memory stick would be mapped into several117* entries. Currently, this function will allocate multiple struct dimm_info118* on such scenarios, as grouping the multiple ranks require drivers change.119*120* Returns:121* On success, return a pointer to struct mem_ctl_info pointer;122* %NULL otherwise123*/124struct mem_ctl_info *edac_mc_alloc(unsigned int mc_num,125unsigned int n_layers,126struct edac_mc_layer *layers,127unsigned int sz_pvt);128129/**130* edac_get_owner - Return the owner's mod_name of EDAC MC131*132* Returns:133* Pointer to mod_name string when EDAC MC is owned. NULL otherwise.134*/135extern const char *edac_get_owner(void);136137/*138* edac_mc_add_mc_with_groups() - Insert the @mci structure into the mci139* global list and create sysfs entries associated with @mci structure.140*141* @mci: pointer to the mci structure to be added to the list142* @groups: optional attribute groups for the driver-specific sysfs entries143*144* Returns:145* 0 on Success, or an error code on failure146*/147extern int edac_mc_add_mc_with_groups(struct mem_ctl_info *mci,148const struct attribute_group **groups);149#define edac_mc_add_mc(mci) edac_mc_add_mc_with_groups(mci, NULL)150151/**152* edac_mc_free() - Frees a previously allocated @mci structure153*154* @mci: pointer to a struct mem_ctl_info structure155*/156extern void edac_mc_free(struct mem_ctl_info *mci);157158/**159* edac_has_mcs() - Check if any MCs have been allocated.160*161* Returns:162* True if MC instances have been registered successfully.163* False otherwise.164*/165extern bool edac_has_mcs(void);166167/**168* edac_mc_find() - Search for a mem_ctl_info structure whose index is @idx.169*170* @idx: index to be seek171*172* If found, return a pointer to the structure.173* Else return NULL.174*/175extern struct mem_ctl_info *edac_mc_find(int idx);176177/**178* find_mci_by_dev() - Scan list of controllers looking for the one that179* manages the @dev device.180*181* @dev: pointer to a struct device related with the MCI182*183* Returns: on success, returns a pointer to struct &mem_ctl_info;184* %NULL otherwise.185*/186extern struct mem_ctl_info *find_mci_by_dev(struct device *dev);187188/**189* edac_mc_del_mc() - Remove sysfs entries for mci structure associated with190* @dev and remove mci structure from global list.191*192* @dev: Pointer to struct &device representing mci structure to remove.193*194* Returns: pointer to removed mci structure, or %NULL if device not found.195*/196extern struct mem_ctl_info *edac_mc_del_mc(struct device *dev);197198/**199* edac_mc_find_csrow_by_page() - Ancillary routine to identify what csrow200* contains a memory page.201*202* @mci: pointer to a struct mem_ctl_info structure203* @page: memory page to find204*205* Returns: on success, returns the csrow. -1 if not found.206*/207extern int edac_mc_find_csrow_by_page(struct mem_ctl_info *mci,208unsigned long page);209210/**211* edac_raw_mc_handle_error() - Reports a memory event to userspace without212* doing anything to discover the error location.213*214* @e: error description215*216* This raw function is used internally by edac_mc_handle_error(). It should217* only be called directly when the hardware error come directly from BIOS,218* like in the case of APEI GHES driver.219*/220void edac_raw_mc_handle_error(struct edac_raw_error_desc *e);221222/**223* edac_mc_handle_error() - Reports a memory event to userspace.224*225* @type: severity of the error (CE/UE/Fatal)226* @mci: a struct mem_ctl_info pointer227* @error_count: Number of errors of the same type228* @page_frame_number: mem page where the error occurred229* @offset_in_page: offset of the error inside the page230* @syndrome: ECC syndrome231* @top_layer: Memory layer[0] position232* @mid_layer: Memory layer[1] position233* @low_layer: Memory layer[2] position234* @msg: Message meaningful to the end users that235* explains the event236* @other_detail: Technical details about the event that237* may help hardware manufacturers and238* EDAC developers to analyse the event239*/240void edac_mc_handle_error(const enum hw_event_mc_err_type type,241struct mem_ctl_info *mci,242const u16 error_count,243const unsigned long page_frame_number,244const unsigned long offset_in_page,245const unsigned long syndrome,246const int top_layer,247const int mid_layer,248const int low_layer,249const char *msg,250const char *other_detail);251252/*253* edac misc APIs254*/255extern char *edac_op_state_to_string(int op_state);256257#endif /* _EDAC_MC_H_ */258259260