#include <linux/module.h>
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/pci_ids.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/edac.h>
#include <linux/mmzone.h>
#include <linux/smp.h>
#include <linux/bitmap.h>
#include <linux/math64.h>
#include <linux/mod_devicetable.h>
#include <asm/cpu_device_id.h>
#include <asm/intel-family.h>
#include <asm/processor.h>
#include <asm/mce.h>
#include "edac_module.h"
static LIST_HEAD(sbridge_edac_list);
#define SBRIDGE_REVISION …
#define EDAC_MOD_STR …
#define sbridge_printk(level, fmt, arg...) …
#define sbridge_mc_printk(mci, level, fmt, arg...) …
#define GET_BITFIELD(v, lo, hi) …
static const u32 sbridge_dram_rule[] = …;
static const u32 ibridge_dram_rule[] = …;
static const u32 knl_dram_rule[] = …;
#define DRAM_RULE_ENABLE(reg) …
#define A7MODE(reg) …
static char *show_dram_attr(u32 attr)
{ … }
static const u32 sbridge_interleave_list[] = …;
static const u32 ibridge_interleave_list[] = …;
static const u32 knl_interleave_list[] = …;
#define MAX_INTERLEAVE …
struct interleave_pkg { … };
static const struct interleave_pkg sbridge_interleave_pkg[] = …;
static const struct interleave_pkg ibridge_interleave_pkg[] = …;
static inline int sad_pkg(const struct interleave_pkg *table, u32 reg,
int interleave)
{ … }
#define TOLM …
#define TOHM …
#define HASWELL_TOLM …
#define HASWELL_TOHM_0 …
#define HASWELL_TOHM_1 …
#define KNL_TOLM …
#define KNL_TOHM_0 …
#define KNL_TOHM_1 …
#define GET_TOLM(reg) …
#define GET_TOHM(reg) …
#define SAD_TARGET …
#define SOURCE_ID(reg) …
#define SOURCE_ID_KNL(reg) …
#define SAD_CONTROL …
static const u32 tad_dram_rule[] = …;
#define MAX_TAD …
#define TAD_LIMIT(reg) …
#define TAD_SOCK(reg) …
#define TAD_CH(reg) …
#define TAD_TGT3(reg) …
#define TAD_TGT2(reg) …
#define TAD_TGT1(reg) …
#define TAD_TGT0(reg) …
#define MCMTR …
#define KNL_MCMTR …
#define IS_ECC_ENABLED(mcmtr) …
#define IS_LOCKSTEP_ENABLED(mcmtr) …
#define IS_CLOSE_PG(mcmtr) …
#define RASENABLES …
#define IS_MIRROR_ENABLED(reg) …
static const int mtr_regs[] = …;
static const int knl_mtr_reg = …;
#define RANK_DISABLE(mtr) …
#define IS_DIMM_PRESENT(mtr) …
#define RANK_CNT_BITS(mtr) …
#define RANK_WIDTH_BITS(mtr) …
#define COL_WIDTH_BITS(mtr) …
static const u32 tad_ch_nilv_offset[] = …;
#define CHN_IDX_OFFSET(reg) …
#define TAD_OFFSET(reg) …
static const u32 rir_way_limit[] = …;
#define MAX_RIR_RANGES …
#define IS_RIR_VALID(reg) …
#define RIR_WAY(reg) …
#define MAX_RIR_WAY …
static const u32 rir_offset[MAX_RIR_RANGES][MAX_RIR_WAY] = …;
#define RIR_RNK_TGT(type, reg) …
#define RIR_OFFSET(type, reg) …
#define RANK_ODD_OV(reg) …
#define RANK_ODD_ERR_CNT(reg) …
#define RANK_EVEN_OV(reg) …
#define RANK_EVEN_ERR_CNT(reg) …
#if 0
static const u32 correrrcnt[] = {
0x104, 0x108, 0x10c, 0x110,
};
static const u32 correrrthrsld[] = {
0x11c, 0x120, 0x124, 0x128,
};
#endif
#define RANK_ODD_ERR_THRSLD(reg) …
#define RANK_EVEN_ERR_THRSLD(reg) …
#define SB_RANK_CFG_A …
#define IB_RANK_CFG_A …
#define NUM_CHANNELS …
#define MAX_DIMMS …
#define KNL_MAX_CHAS …
#define KNL_MAX_CHANNELS …
#define KNL_MAX_EDCS …
#define CHANNEL_UNSPECIFIED …
enum type { … };
enum domain { … };
enum mirroring_mode { … };
struct sbridge_pvt;
struct sbridge_info { … };
struct sbridge_channel { … };
struct pci_id_descr { … };
struct pci_id_table { … };
struct sbridge_dev { … };
struct knl_pvt { … };
struct sbridge_pvt { … };
#define PCI_DESCR(device_id, opt, domain) …
static const struct pci_id_descr pci_dev_descr_sbridge[] = …;
#define PCI_ID_TABLE_ENTRY(A, N, M, T) …
static const struct pci_id_table pci_dev_descr_sbridge_table[] = …;
#define PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_1HA_DDRIO0 …
#define PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_2HA_DDRIO0 …
#define PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0 …
#define PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TA …
#define PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_RAS …
#define PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD0 …
#define PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD1 …
#define PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD2 …
#define PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD3 …
#define PCI_DEVICE_ID_INTEL_IBRIDGE_SAD …
#define PCI_DEVICE_ID_INTEL_IBRIDGE_BR0 …
#define PCI_DEVICE_ID_INTEL_IBRIDGE_BR1 …
#define PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1 …
#define PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TA …
#define PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_RAS …
#define PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD0 …
#define PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD1 …
#define PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD2 …
#define PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD3 …
static const struct pci_id_descr pci_dev_descr_ibridge[] = …;
static const struct pci_id_table pci_dev_descr_ibridge_table[] = …;
#define HASWELL_DDRCRCLKCONTROLS …
#define HASWELL_HASYSDEFEATURE2 …
#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_VTD_MISC …
#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0 …
#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1 …
#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TA …
#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TM …
#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TA …
#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TM …
#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_CBO_SAD0 …
#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_CBO_SAD1 …
#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD0 …
#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD1 …
#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD2 …
#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD3 …
#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD0 …
#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD1 …
#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD2 …
#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD3 …
#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_DDRIO0 …
#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_DDRIO1 …
#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_DDRIO2 …
#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_DDRIO3 …
static const struct pci_id_descr pci_dev_descr_haswell[] = …;
static const struct pci_id_table pci_dev_descr_haswell_table[] = …;
#define knl_channel_remap(mc, chan) …
#define PCI_DEVICE_ID_INTEL_KNL_IMC_MC …
#define PCI_DEVICE_ID_INTEL_KNL_IMC_CHAN …
#define PCI_DEVICE_ID_INTEL_KNL_IMC_TA …
#define PCI_DEVICE_ID_INTEL_KNL_IMC_SAD0 …
#define PCI_DEVICE_ID_INTEL_KNL_IMC_SAD1 …
#define PCI_DEVICE_ID_INTEL_KNL_IMC_CHA …
#define PCI_DEVICE_ID_INTEL_KNL_IMC_TOLHM …
static const struct pci_id_descr pci_dev_descr_knl[] = …;
static const struct pci_id_table pci_dev_descr_knl_table[] = …;
#define PCI_DEVICE_ID_INTEL_BROADWELL_IMC_VTD_MISC …
#define PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0 …
#define PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1 …
#define PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TA …
#define PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TM …
#define PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_TA …
#define PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_TM …
#define PCI_DEVICE_ID_INTEL_BROADWELL_IMC_CBO_SAD0 …
#define PCI_DEVICE_ID_INTEL_BROADWELL_IMC_CBO_SAD1 …
#define PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TAD0 …
#define PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TAD1 …
#define PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TAD2 …
#define PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TAD3 …
#define PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_TAD0 …
#define PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_TAD1 …
#define PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_TAD2 …
#define PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_TAD3 …
#define PCI_DEVICE_ID_INTEL_BROADWELL_IMC_DDRIO0 …
static const struct pci_id_descr pci_dev_descr_broadwell[] = …;
static const struct pci_id_table pci_dev_descr_broadwell_table[] = …;
static inline int numrank(enum type type, u32 mtr)
{ … }
static inline int numrow(u32 mtr)
{ … }
static inline int numcol(u32 mtr)
{ … }
static struct sbridge_dev *get_sbridge_dev(int seg, u8 bus, enum domain dom,
int multi_bus,
struct sbridge_dev *prev)
{ … }
static struct sbridge_dev *alloc_sbridge_dev(int seg, u8 bus, enum domain dom,
const struct pci_id_table *table)
{ … }
static void free_sbridge_dev(struct sbridge_dev *sbridge_dev)
{ … }
static u64 sbridge_get_tolm(struct sbridge_pvt *pvt)
{ … }
static u64 sbridge_get_tohm(struct sbridge_pvt *pvt)
{ … }
static u64 ibridge_get_tolm(struct sbridge_pvt *pvt)
{ … }
static u64 ibridge_get_tohm(struct sbridge_pvt *pvt)
{ … }
static u64 rir_limit(u32 reg)
{ … }
static u64 sad_limit(u32 reg)
{ … }
static u32 interleave_mode(u32 reg)
{ … }
static u32 dram_attr(u32 reg)
{ … }
static u64 knl_sad_limit(u32 reg)
{ … }
static u32 knl_interleave_mode(u32 reg)
{ … }
static const char * const knl_intlv_mode[] = …;
static const char *get_intlv_mode_str(u32 reg, enum type t)
{ … }
static u32 dram_attr_knl(u32 reg)
{ … }
static enum mem_type get_memory_type(struct sbridge_pvt *pvt)
{ … }
static enum mem_type haswell_get_memory_type(struct sbridge_pvt *pvt)
{ … }
static enum dev_type knl_get_width(struct sbridge_pvt *pvt, u32 mtr)
{ … }
static enum dev_type sbridge_get_width(struct sbridge_pvt *pvt, u32 mtr)
{ … }
static enum dev_type __ibridge_get_width(u32 mtr)
{ … }
static enum dev_type ibridge_get_width(struct sbridge_pvt *pvt, u32 mtr)
{ … }
static enum dev_type broadwell_get_width(struct sbridge_pvt *pvt, u32 mtr)
{ … }
static enum mem_type knl_get_memory_type(struct sbridge_pvt *pvt)
{ … }
static u8 get_node_id(struct sbridge_pvt *pvt)
{ … }
static u8 haswell_get_node_id(struct sbridge_pvt *pvt)
{ … }
static u8 knl_get_node_id(struct sbridge_pvt *pvt)
{ … }
static u8 sbridge_get_ha(u8 bank)
{ … }
static u8 ibridge_get_ha(u8 bank)
{ … }
static u8 knl_get_ha(u8 bank)
{ … }
static u64 haswell_get_tolm(struct sbridge_pvt *pvt)
{ … }
static u64 haswell_get_tohm(struct sbridge_pvt *pvt)
{ … }
static u64 knl_get_tolm(struct sbridge_pvt *pvt)
{ … }
static u64 knl_get_tohm(struct sbridge_pvt *pvt)
{ … }
static u64 haswell_rir_limit(u32 reg)
{ … }
static inline u8 sad_pkg_socket(u8 pkg)
{ … }
static inline u8 sad_pkg_ha(u8 pkg)
{ … }
static int haswell_chan_hash(int idx, u64 addr)
{ … }
static const u32 knl_tad_dram_limit_lo[] = …;
static const u32 knl_tad_dram_offset_lo[] = …;
static const u32 knl_tad_dram_hi[] = …;
static const u32 knl_tad_ways[] = …;
static int knl_get_tad(const struct sbridge_pvt *pvt,
const int entry,
const int mc,
u64 *offset,
u64 *limit,
int *ways)
{ … }
static int knl_channel_mc(int channel)
{ … }
static u32 knl_get_edc_route(int entry, u32 reg)
{ … }
static u32 knl_get_mc_route(int entry, u32 reg)
{ … }
static void knl_show_edc_route(u32 reg, char *s)
{ … }
static void knl_show_mc_route(u32 reg, char *s)
{ … }
#define KNL_EDC_ROUTE …
#define KNL_MC_ROUTE …
#define KNL_EDRAM(reg) …
#define KNL_CACHEABLE(reg) …
#define KNL_EDRAM_ONLY(reg) …
#define KNL_CACHEABLE(reg) …
#define KNL_MOD3(reg) …
static int knl_get_dimm_capacity(struct sbridge_pvt *pvt, u64 *mc_sizes)
{ … }
static void get_source_id(struct mem_ctl_info *mci)
{ … }
static int __populate_dimms(struct mem_ctl_info *mci,
u64 knl_mc_sizes[KNL_MAX_CHANNELS],
enum edac_type mode)
{ … }
static int get_dimm_config(struct mem_ctl_info *mci)
{ … }
static void get_memory_layout(const struct mem_ctl_info *mci)
{ … }
static struct mem_ctl_info *get_mci_for_node_id(u8 node_id, u8 ha)
{ … }
static u8 sb_close_row[] = …;
static u8 sb_close_column[] = …;
static u8 sb_open_row[] = …;
static u8 sb_open_column[] = …;
static u8 sb_open_fine_column[] = …;
static int sb_bits(u64 addr, int nbits, u8 *bits)
{ … }
static int sb_bank_bits(u64 addr, int b0, int b1, int do_xor, int x0, int x1)
{ … }
static bool sb_decode_ddr4(struct mem_ctl_info *mci, int ch, u8 rank,
u64 rank_addr, char *msg)
{ … }
static bool sb_decode_ddr3(struct mem_ctl_info *mci, int ch, u8 rank,
u64 rank_addr, char *msg)
{ … }
static int get_memory_error_data(struct mem_ctl_info *mci,
u64 addr,
u8 *socket, u8 *ha,
long *channel_mask,
u8 *rank,
char **area_type, char *msg)
{ … }
static int get_memory_error_data_from_mce(struct mem_ctl_info *mci,
const struct mce *m, u8 *socket,
u8 *ha, long *channel_mask,
char *msg)
{ … }
static void sbridge_put_devices(struct sbridge_dev *sbridge_dev)
{ … }
static void sbridge_put_all_devices(void)
{ … }
static int sbridge_get_onedevice(struct pci_dev **prev,
u8 *num_mc,
const struct pci_id_table *table,
const unsigned devno,
const int multi_bus)
{ … }
static int sbridge_get_all_devices(u8 *num_mc,
const struct pci_id_table *table)
{ … }
#define TAD_DEV_TO_CHAN(dev) …
static int sbridge_mci_bind_devs(struct mem_ctl_info *mci,
struct sbridge_dev *sbridge_dev)
{ … }
static int ibridge_mci_bind_devs(struct mem_ctl_info *mci,
struct sbridge_dev *sbridge_dev)
{ … }
static int haswell_mci_bind_devs(struct mem_ctl_info *mci,
struct sbridge_dev *sbridge_dev)
{ … }
static int broadwell_mci_bind_devs(struct mem_ctl_info *mci,
struct sbridge_dev *sbridge_dev)
{ … }
static int knl_mci_bind_devs(struct mem_ctl_info *mci,
struct sbridge_dev *sbridge_dev)
{ … }
static void sbridge_mce_output_error(struct mem_ctl_info *mci,
const struct mce *m)
{ … }
static int sbridge_mce_check_error(struct notifier_block *nb, unsigned long val,
void *data)
{ … }
static struct notifier_block sbridge_mce_dec = …;
static void sbridge_unregister_mci(struct sbridge_dev *sbridge_dev)
{ … }
static int sbridge_register_mci(struct sbridge_dev *sbridge_dev, enum type type)
{ … }
static const struct x86_cpu_id sbridge_cpuids[] = …;
MODULE_DEVICE_TABLE(x86cpu, sbridge_cpuids);
static int sbridge_probe(const struct x86_cpu_id *id)
{ … }
static void sbridge_remove(void)
{ … }
static int __init sbridge_init(void)
{ … }
static void __exit sbridge_exit(void)
{ … }
module_init(…) …;
module_exit(sbridge_exit);
module_param(edac_op_state, int, 0444);
MODULE_PARM_DESC(…) …;
MODULE_LICENSE(…) …;
MODULE_AUTHOR(…) …;
MODULE_AUTHOR(…) …;
MODULE_DESCRIPTION(…) …;