i82975x_edac.c
来自「linux 内核源代码」· C语言 代码 · 共 667 行 · 第 1/2 页
C
667 行
/* * Intel 82975X Memory Controller kernel module * (C) 2007 aCarLab (India) Pvt. Ltd. (http://acarlab.com) * (C) 2007 jetzbroadband (http://jetzbroadband.com) * This file may be distributed under the terms of the * GNU General Public License. * * Written by Arvind R. * Copied from i82875p_edac.c source: */#include <linux/module.h>#include <linux/init.h>#include <linux/pci.h>#include <linux/pci_ids.h>#include <linux/slab.h>#include "edac_core.h"#define I82975X_REVISION " Ver: 1.0.0 " __DATE__#define EDAC_MOD_STR "i82975x_edac"#define i82975x_printk(level, fmt, arg...) \ edac_printk(level, "i82975x", fmt, ##arg)#define i82975x_mc_printk(mci, level, fmt, arg...) \ edac_mc_chipset_printk(mci, level, "i82975x", fmt, ##arg)#ifndef PCI_DEVICE_ID_INTEL_82975_0#define PCI_DEVICE_ID_INTEL_82975_0 0x277c#endif /* PCI_DEVICE_ID_INTEL_82975_0 */#define I82975X_NR_CSROWS(nr_chans) (8/(nr_chans))/* Intel 82975X register addresses - device 0 function 0 - DRAM Controller */#define I82975X_EAP 0x58 /* Dram Error Address Pointer (32b) * * 31:7 128 byte cache-line address * 6:1 reserved * 0 0: CH0; 1: CH1 */#define I82975X_DERRSYN 0x5c /* Dram Error SYNdrome (8b) * * 7:0 DRAM ECC Syndrome */#define I82975X_DES 0x5d /* Dram ERRor DeSTination (8b) * 0h: Processor Memory Reads * 1h:7h reserved * More - See Page 65 of Intel DocSheet. */#define I82975X_ERRSTS 0xc8 /* Error Status Register (16b) * * 15:12 reserved * 11 Thermal Sensor Event * 10 reserved * 9 non-DRAM lock error (ndlock) * 8 Refresh Timeout * 7:2 reserved * 1 ECC UE (multibit DRAM error) * 0 ECC CE (singlebit DRAM error) *//* Error Reporting is supported by 3 mechanisms: 1. DMI SERR generation ( ERRCMD ) 2. SMI DMI generation ( SMICMD ) 3. SCI DMI generation ( SCICMD )NOTE: Only ONE of the three must be enabled*/#define I82975X_ERRCMD 0xca /* Error Command (16b) * * 15:12 reserved * 11 Thermal Sensor Event * 10 reserved * 9 non-DRAM lock error (ndlock) * 8 Refresh Timeout * 7:2 reserved * 1 ECC UE (multibit DRAM error) * 0 ECC CE (singlebit DRAM error) */#define I82975X_SMICMD 0xcc /* Error Command (16b) * * 15:2 reserved * 1 ECC UE (multibit DRAM error) * 0 ECC CE (singlebit DRAM error) */#define I82975X_SCICMD 0xce /* Error Command (16b) * * 15:2 reserved * 1 ECC UE (multibit DRAM error) * 0 ECC CE (singlebit DRAM error) */#define I82975X_XEAP 0xfc /* Extended Dram Error Address Pointer (8b) * * 7:1 reserved * 0 Bit32 of the Dram Error Address */#define I82975X_MCHBAR 0x44 /* * * 31:14 Base Addr of 16K memory-mapped * configuration space * 13:1 reserverd * 0 mem-mapped config space enable *//* NOTE: Following addresses have to indexed using MCHBAR offset (44h, 32b) *//* Intel 82975x memory mapped register space */#define I82975X_DRB_SHIFT 25 /* fixed 32MiB grain */#define I82975X_DRB 0x100 /* DRAM Row Boundary (8b x 8) * * 7 set to 1 in highest DRB of * channel if 4GB in ch. * 6:2 upper boundary of rank in * 32MB grains * 1:0 set to 0 */#define I82975X_DRB_CH0R0 0x100#define I82975X_DRB_CH0R1 0x101#define I82975X_DRB_CH0R2 0x102#define I82975X_DRB_CH0R3 0x103#define I82975X_DRB_CH1R0 0x180#define I82975X_DRB_CH1R1 0x181#define I82975X_DRB_CH1R2 0x182#define I82975X_DRB_CH1R3 0x183#define I82975X_DRA 0x108 /* DRAM Row Attribute (4b x 8) * defines the PAGE SIZE to be used * for the rank * 7 reserved * 6:4 row attr of odd rank, i.e. 1 * 3 reserved * 2:0 row attr of even rank, i.e. 0 * * 000 = unpopulated * 001 = reserved * 010 = 4KiB * 011 = 8KiB * 100 = 16KiB * others = reserved */#define I82975X_DRA_CH0R01 0x108#define I82975X_DRA_CH0R23 0x109#define I82975X_DRA_CH1R01 0x188#define I82975X_DRA_CH1R23 0x189#define I82975X_BNKARC 0x10e /* Type of device in each rank - Bank Arch (16b) * * 15:8 reserved * 7:6 Rank 3 architecture * 5:4 Rank 2 architecture * 3:2 Rank 1 architecture * 1:0 Rank 0 architecture * * 00 => x16 devices; i.e 4 banks * 01 => x8 devices; i.e 8 banks */#define I82975X_C0BNKARC 0x10e#define I82975X_C1BNKARC 0x18e#define I82975X_DRC 0x120 /* DRAM Controller Mode0 (32b) * * 31:30 reserved * 29 init complete * 28:11 reserved, according to Intel * 22:21 number of channels * 00=1 01=2 in 82875 * seems to be ECC mode * bits in 82975 in Asus * P5W * 19:18 Data Integ Mode * 00=none 01=ECC in 82875 * 10:8 refresh mode * 7 reserved * 6:4 mode select * 3:2 reserved * 1:0 DRAM type 10=Second Revision * DDR2 SDRAM * 00, 01, 11 reserved */#define I82975X_DRC_CH0M0 0x120#define I82975X_DRC_CH1M0 0x1A0#define I82975X_DRC_M1 0x124 /* DRAM Controller Mode1 (32b) * 31 0=Standard Address Map * 1=Enhanced Address Map * 30:0 reserved */#define I82975X_DRC_CH0M1 0x124#define I82975X_DRC_CH1M1 0x1A4enum i82975x_chips { I82975X = 0,};struct i82975x_pvt { void __iomem *mch_window;};struct i82975x_dev_info { const char *ctl_name;};struct i82975x_error_info { u16 errsts; u32 eap; u8 des; u8 derrsyn; u16 errsts2; u8 chan; /* the channel is bit 0 of EAP */ u8 xeap; /* extended eap bit */};static const struct i82975x_dev_info i82975x_devs[] = { [I82975X] = { .ctl_name = "i82975x" },};static struct pci_dev *mci_pdev; /* init dev: in case that AGP code has * already registered driver */static int i82975x_registered = 1;static void i82975x_get_error_info(struct mem_ctl_info *mci, struct i82975x_error_info *info){ struct pci_dev *pdev; pdev = to_pci_dev(mci->dev); /* * This is a mess because there is no atomic way to read all the * registers at once and the registers can transition from CE being * overwritten by UE. */ pci_read_config_word(pdev, I82975X_ERRSTS, &info->errsts); pci_read_config_dword(pdev, I82975X_EAP, &info->eap); pci_read_config_byte(pdev, I82975X_XEAP, &info->xeap); pci_read_config_byte(pdev, I82975X_DES, &info->des); pci_read_config_byte(pdev, I82975X_DERRSYN, &info->derrsyn); pci_read_config_word(pdev, I82975X_ERRSTS, &info->errsts2); pci_write_bits16(pdev, I82975X_ERRSTS, 0x0003, 0x0003); /* * If the error is the same then we can for both reads then * the first set of reads is valid. If there is a change then * there is a CE no info and the second set of reads is valid * and should be UE info. */ if (!(info->errsts2 & 0x0003)) return; if ((info->errsts ^ info->errsts2) & 0x0003) { pci_read_config_dword(pdev, I82975X_EAP, &info->eap); pci_read_config_byte(pdev, I82975X_XEAP, &info->xeap); pci_read_config_byte(pdev, I82975X_DES, &info->des); pci_read_config_byte(pdev, I82975X_DERRSYN, &info->derrsyn); }}static int i82975x_process_error_info(struct mem_ctl_info *mci, struct i82975x_error_info *info, int handle_errors){ int row, multi_chan, chan; multi_chan = mci->csrows[0].nr_channels - 1; if (!(info->errsts2 & 0x0003)) return 0; if (!handle_errors) return 1; if ((info->errsts ^ info->errsts2) & 0x0003) { edac_mc_handle_ce_no_info(mci, "UE overwrote CE"); info->errsts = info->errsts2; } chan = info->eap & 1; info->eap >>= 1; if (info->xeap ) info->eap |= 0x80000000; info->eap >>= PAGE_SHIFT; row = edac_mc_find_csrow_by_page(mci, info->eap); if (info->errsts & 0x0002) edac_mc_handle_ue(mci, info->eap, 0, row, "i82975x UE"); else edac_mc_handle_ce(mci, info->eap, 0, info->derrsyn, row, multi_chan ? chan : 0, "i82975x CE"); return 1;}static void i82975x_check(struct mem_ctl_info *mci){ struct i82975x_error_info info; debugf1("MC%d: %s()\n", mci->mc_idx, __func__); i82975x_get_error_info(mci, &info); i82975x_process_error_info(mci, &info, 1);}/* Return 1 if dual channel mode is active. Else return 0. */static int dual_channel_active(void __iomem *mch_window){ /* * We treat interleaved-symmetric configuration as dual-channel - EAP's * bit-0 giving the channel of the error location. * * All other configurations are treated as single channel - the EAP's * bit-0 will resolve ok in symmetric area of mixed * (symmetric/asymmetric) configurations */ u8 drb[4][2]; int row;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?