10d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox/* 20d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox * Intel D82875P Memory Controller kernel module 30d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox * (C) 2003 Linux Networx (http://lnxi.com) 40d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox * This file may be distributed under the terms of the 50d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox * GNU General Public License. 60d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox * 70d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox * Written by Thayne Harbaugh 80d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox * Contributors: 90d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox * Wang Zhenyu at intel.com 100d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox * 110d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox * $Id: edac_i82875p.c,v 1.5.2.11 2005/10/05 00:43:44 dsp_llnl Exp $ 120d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox * 130d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox * Note: E7210 appears same as D82875P - zhenyu.z.wang at intel.com 140d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox */ 150d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox 160d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox#include <linux/module.h> 170d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox#include <linux/init.h> 180d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox#include <linux/pci.h> 190d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox#include <linux/pci_ids.h> 20c3c52bce6993c6d37af2c2de9b482a7013d646a7Hitoshi Mitake#include <linux/edac.h> 2120bcb7a81dee21bfa3408f03f46b2891c9b5c84bDouglas Thompson#include "edac_core.h" 220d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox 23152ba3942276c2a240703669ae4a3099e0a79451Michal Marek#define I82875P_REVISION " Ver: 2.0.2" 24929a40ec324e947d4ad14cc1ced785c104c560e2Doug Thompson#define EDAC_MOD_STR "i82875p_edac" 2537f04581abac20444e5b7106c1e1f28bec5b989cDoug Thompson 26537fba28928c01b7db1580627450691a4bb0b9b3Dave Peterson#define i82875p_printk(level, fmt, arg...) \ 27e7ecd8910293564d357dbaf18eb179e06fa35fd0Dave Peterson edac_printk(level, "i82875p", fmt, ##arg) 28537fba28928c01b7db1580627450691a4bb0b9b3Dave Peterson 29537fba28928c01b7db1580627450691a4bb0b9b3Dave Peterson#define i82875p_mc_printk(mci, level, fmt, arg...) \ 30e7ecd8910293564d357dbaf18eb179e06fa35fd0Dave Peterson edac_mc_chipset_printk(mci, level, "i82875p", fmt, ##arg) 31537fba28928c01b7db1580627450691a4bb0b9b3Dave Peterson 320d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox#ifndef PCI_DEVICE_ID_INTEL_82875_0 330d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox#define PCI_DEVICE_ID_INTEL_82875_0 0x2578 340d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox#endif /* PCI_DEVICE_ID_INTEL_82875_0 */ 350d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox 360d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox#ifndef PCI_DEVICE_ID_INTEL_82875_6 370d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox#define PCI_DEVICE_ID_INTEL_82875_6 0x257e 380d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox#endif /* PCI_DEVICE_ID_INTEL_82875_6 */ 390d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox 400d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox/* four csrows in dual channel, eight in single channel */ 410d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox#define I82875P_NR_CSROWS(nr_chans) (8/(nr_chans)) 420d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox 430d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox/* Intel 82875p register addresses - device 0 function 0 - DRAM Controller */ 440d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox#define I82875P_EAP 0x58 /* Error Address Pointer (32b) 450d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox * 460d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox * 31:12 block address 470d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox * 11:0 reserved 480d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox */ 490d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox 500d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox#define I82875P_DERRSYN 0x5c /* DRAM Error Syndrome (8b) 510d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox * 520d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox * 7:0 DRAM ECC Syndrome 530d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox */ 540d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox 550d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox#define I82875P_DES 0x5d /* DRAM Error Status (8b) 560d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox * 570d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox * 7:1 reserved 580d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox * 0 Error channel 0/1 590d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox */ 600d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox 610d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox#define I82875P_ERRSTS 0xc8 /* Error Status Register (16b) 620d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox * 630d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox * 15:10 reserved 640d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox * 9 non-DRAM lock error (ndlock) 650d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox * 8 Sftwr Generated SMI 660d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox * 7 ECC UE 670d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox * 6 reserved 680d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox * 5 MCH detects unimplemented cycle 690d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox * 4 AGP access outside GA 700d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox * 3 Invalid AGP access 710d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox * 2 Invalid GA translation table 720d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox * 1 Unsupported AGP command 730d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox * 0 ECC CE 740d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox */ 750d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox 760d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox#define I82875P_ERRCMD 0xca /* Error Command (16b) 770d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox * 780d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox * 15:10 reserved 790d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox * 9 SERR on non-DRAM lock 800d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox * 8 SERR on ECC UE 810d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox * 7 SERR on ECC CE 820d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox * 6 target abort on high exception 830d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox * 5 detect unimplemented cyc 840d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox * 4 AGP access outside of GA 850d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox * 3 SERR on invalid AGP access 860d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox * 2 invalid translation table 870d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox * 1 SERR on unsupported AGP command 880d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox * 0 reserved 890d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox */ 900d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox 910d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox/* Intel 82875p register addresses - device 6 function 0 - DRAM Controller */ 920d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox#define I82875P_PCICMD6 0x04 /* PCI Command Register (16b) 930d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox * 940d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox * 15:10 reserved 950d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox * 9 fast back-to-back - ro 0 960d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox * 8 SERR enable - ro 0 970d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox * 7 addr/data stepping - ro 0 980d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox * 6 parity err enable - ro 0 990d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox * 5 VGA palette snoop - ro 0 1000d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox * 4 mem wr & invalidate - ro 0 1010d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox * 3 special cycle - ro 0 1020d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox * 2 bus master - ro 0 1030d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox * 1 mem access dev6 - 0(dis),1(en) 1040d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox * 0 IO access dev3 - 0(dis),1(en) 1050d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox */ 1060d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox 1070d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox#define I82875P_BAR6 0x10 /* Mem Delays Base ADDR Reg (32b) 1080d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox * 1090d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox * 31:12 mem base addr [31:12] 1100d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox * 11:4 address mask - ro 0 1110d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox * 3 prefetchable - ro 0(non),1(pre) 1120d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox * 2:1 mem type - ro 0 1130d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox * 0 mem space - ro 0 1140d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox */ 1150d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox 1160d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox/* Intel 82875p MMIO register space - device 0 function 0 - MMR space */ 1170d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox 1180d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox#define I82875P_DRB_SHIFT 26 /* 64MiB grain */ 1190d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox#define I82875P_DRB 0x00 /* DRAM Row Boundary (8b x 8) 1200d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox * 1210d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox * 7 reserved 1220d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox * 6:0 64MiB row boundary addr 1230d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox */ 1240d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox 1250d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox#define I82875P_DRA 0x10 /* DRAM Row Attribute (4b x 8) 1260d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox * 1270d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox * 7 reserved 1280d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox * 6:4 row attr row 1 1290d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox * 3 reserved 1300d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox * 2:0 row attr row 0 1310d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox * 1320d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox * 000 = 4KiB 1330d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox * 001 = 8KiB 1340d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox * 010 = 16KiB 1350d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox * 011 = 32KiB 1360d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox */ 1370d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox 1380d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox#define I82875P_DRC 0x68 /* DRAM Controller Mode (32b) 1390d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox * 1400d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox * 31:30 reserved 1410d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox * 29 init complete 1420d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox * 28:23 reserved 1430d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox * 22:21 nr chan 00=1,01=2 1440d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox * 20 reserved 1450d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox * 19:18 Data Integ Mode 00=none,01=ecc 1460d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox * 17:11 reserved 1470d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox * 10:8 refresh mode 1480d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox * 7 reserved 1490d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox * 6:4 mode select 1500d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox * 3:2 reserved 1510d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox * 1:0 DRAM type 01=DDR 1520d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox */ 1530d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox 1540d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Coxenum i82875p_chips { 1550d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox I82875P = 0, 1560d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox}; 1570d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox 1580d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Coxstruct i82875p_pvt { 1590d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox struct pci_dev *ovrfl_pdev; 1606d57348d7d65ba6f2f42a24b0c7527e0f7470a84Al Viro void __iomem *ovrfl_window; 1610d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox}; 1620d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox 1630d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Coxstruct i82875p_dev_info { 1640d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox const char *ctl_name; 1650d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox}; 1660d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox 1670d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Coxstruct i82875p_error_info { 1680d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox u16 errsts; 1690d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox u32 eap; 1700d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox u8 des; 1710d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox u8 derrsyn; 1720d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox u16 errsts2; 1730d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox}; 1740d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox 1750d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Coxstatic const struct i82875p_dev_info i82875p_devs[] = { 1760d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox [I82875P] = { 177052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson .ctl_name = "i82875p"}, 1780d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox}; 1790d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox 180f044091ca4c0b05be8f83748d76d4fbba4fc74cfDouglas Thompsonstatic struct pci_dev *mci_pdev; /* init dev: in case that AGP code has 181e7ecd8910293564d357dbaf18eb179e06fa35fd0Dave Peterson * already registered driver 182e7ecd8910293564d357dbaf18eb179e06fa35fd0Dave Peterson */ 183e7ecd8910293564d357dbaf18eb179e06fa35fd0Dave Peterson 184456a2f9552e7849475f4aea1a9aa4c0e54b3dddaDave Jiangstatic struct edac_pci_ctl_info *i82875p_pci; 185456a2f9552e7849475f4aea1a9aa4c0e54b3dddaDave Jiang 186e7ecd8910293564d357dbaf18eb179e06fa35fd0Dave Petersonstatic void i82875p_get_error_info(struct mem_ctl_info *mci, 187052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson struct i82875p_error_info *info) 1880d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox{ 18937f04581abac20444e5b7106c1e1f28bec5b989cDoug Thompson struct pci_dev *pdev; 19037f04581abac20444e5b7106c1e1f28bec5b989cDoug Thompson 19137f04581abac20444e5b7106c1e1f28bec5b989cDoug Thompson pdev = to_pci_dev(mci->dev); 19237f04581abac20444e5b7106c1e1f28bec5b989cDoug Thompson 1930d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox /* 1940d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox * This is a mess because there is no atomic way to read all the 1950d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox * registers at once and the registers can transition from CE being 1960d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox * overwritten by UE. 1970d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox */ 19837f04581abac20444e5b7106c1e1f28bec5b989cDoug Thompson pci_read_config_word(pdev, I82875P_ERRSTS, &info->errsts); 199654ede200fe028373852bbca387ab4834ddb7228Jason Uhlenkott 200654ede200fe028373852bbca387ab4834ddb7228Jason Uhlenkott if (!(info->errsts & 0x0081)) 201654ede200fe028373852bbca387ab4834ddb7228Jason Uhlenkott return; 202654ede200fe028373852bbca387ab4834ddb7228Jason Uhlenkott 20337f04581abac20444e5b7106c1e1f28bec5b989cDoug Thompson pci_read_config_dword(pdev, I82875P_EAP, &info->eap); 20437f04581abac20444e5b7106c1e1f28bec5b989cDoug Thompson pci_read_config_byte(pdev, I82875P_DES, &info->des); 20537f04581abac20444e5b7106c1e1f28bec5b989cDoug Thompson pci_read_config_byte(pdev, I82875P_DERRSYN, &info->derrsyn); 20637f04581abac20444e5b7106c1e1f28bec5b989cDoug Thompson pci_read_config_word(pdev, I82875P_ERRSTS, &info->errsts2); 2070d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox 2080d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox /* 2090d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox * If the error is the same then we can for both reads then 2100d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox * the first set of reads is valid. If there is a change then 2110d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox * there is a CE no info and the second set of reads is valid 2120d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox * and should be UE info. 2130d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox */ 2140d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox if ((info->errsts ^ info->errsts2) & 0x0081) { 21537f04581abac20444e5b7106c1e1f28bec5b989cDoug Thompson pci_read_config_dword(pdev, I82875P_EAP, &info->eap); 21637f04581abac20444e5b7106c1e1f28bec5b989cDoug Thompson pci_read_config_byte(pdev, I82875P_DES, &info->des); 217466b71d58413a515a8029b4eccf98c08b8bb5acaDave Jiang pci_read_config_byte(pdev, I82875P_DERRSYN, &info->derrsyn); 2180d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox } 219654ede200fe028373852bbca387ab4834ddb7228Jason Uhlenkott 220654ede200fe028373852bbca387ab4834ddb7228Jason Uhlenkott pci_write_bits16(pdev, I82875P_ERRSTS, 0x0081, 0x0081); 2210d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox} 2220d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox 223e7ecd8910293564d357dbaf18eb179e06fa35fd0Dave Petersonstatic int i82875p_process_error_info(struct mem_ctl_info *mci, 224052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson struct i82875p_error_info *info, 225052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson int handle_errors) 2260d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox{ 2270d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox int row, multi_chan; 2280d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox 2290d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox multi_chan = mci->csrows[0].nr_channels - 1; 2300d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox 231654ede200fe028373852bbca387ab4834ddb7228Jason Uhlenkott if (!(info->errsts & 0x0081)) 2320d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox return 0; 2330d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox 2340d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox if (!handle_errors) 2350d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox return 1; 2360d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox 2370d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox if ((info->errsts ^ info->errsts2) & 0x0081) { 2380d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox edac_mc_handle_ce_no_info(mci, "UE overwrote CE"); 2390d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox info->errsts = info->errsts2; 2400d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox } 2410d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox 2420d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox info->eap >>= PAGE_SHIFT; 2430d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox row = edac_mc_find_csrow_by_page(mci, info->eap); 2440d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox 2450d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox if (info->errsts & 0x0080) 2460d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox edac_mc_handle_ue(mci, info->eap, 0, row, "i82875p UE"); 2470d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox else 2480d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox edac_mc_handle_ce(mci, info->eap, 0, info->derrsyn, row, 249052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson multi_chan ? (info->des & 0x1) : 0, 250052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson "i82875p CE"); 2510d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox 2520d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox return 1; 2530d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox} 2540d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox 2550d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Coxstatic void i82875p_check(struct mem_ctl_info *mci) 2560d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox{ 2570d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox struct i82875p_error_info info; 2580d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox 259537fba28928c01b7db1580627450691a4bb0b9b3Dave Peterson debugf1("MC%d: %s()\n", mci->mc_idx, __func__); 2600d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox i82875p_get_error_info(mci, &info); 2610d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox i82875p_process_error_info(mci, &info, 1); 2620d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox} 2630d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox 2641318952514d5651c453d89989595a9df3b37267bDoug Thompson/* Return 0 on success or 1 on failure. */ 2651318952514d5651c453d89989595a9df3b37267bDoug Thompsonstatic int i82875p_setup_overfl_dev(struct pci_dev *pdev, 266052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson struct pci_dev **ovrfl_pdev, 267052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson void __iomem **ovrfl_window) 2680d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox{ 2691318952514d5651c453d89989595a9df3b37267bDoug Thompson struct pci_dev *dev; 2701318952514d5651c453d89989595a9df3b37267bDoug Thompson void __iomem *window; 2711c52152b3008b7bdcc3b94d0be4d0b814dce1530Douglas Thompson int err; 2720d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox 2731318952514d5651c453d89989595a9df3b37267bDoug Thompson *ovrfl_pdev = NULL; 2741318952514d5651c453d89989595a9df3b37267bDoug Thompson *ovrfl_window = NULL; 2751318952514d5651c453d89989595a9df3b37267bDoug Thompson dev = pci_get_device(PCI_VEND_DEV(INTEL, 82875_6), NULL); 2760d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox 2771318952514d5651c453d89989595a9df3b37267bDoug Thompson if (dev == NULL) { 2781318952514d5651c453d89989595a9df3b37267bDoug Thompson /* Intel tells BIOS developers to hide device 6 which 2790d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox * configures the overflow device access containing 2800d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox * the DRBs - this is where we expose device 6. 2810d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox * http://www.x86-secret.com/articles/tweak/pat/patsecrets-2.htm 2820d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox */ 2830d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox pci_write_bits8(pdev, 0xf4, 0x2, 0x2); 2841318952514d5651c453d89989595a9df3b37267bDoug Thompson dev = pci_scan_single_device(pdev->bus, PCI_DEVFN(6, 0)); 285e7ecd8910293564d357dbaf18eb179e06fa35fd0Dave Peterson 2861318952514d5651c453d89989595a9df3b37267bDoug Thompson if (dev == NULL) 2871318952514d5651c453d89989595a9df3b37267bDoug Thompson return 1; 28862456726d715042e1976b830c59fd73f41c4aaa6John Feeney 2891c52152b3008b7bdcc3b94d0be4d0b814dce1530Douglas Thompson err = pci_bus_add_device(dev); 2901c52152b3008b7bdcc3b94d0be4d0b814dce1530Douglas Thompson if (err) { 2911c52152b3008b7bdcc3b94d0be4d0b814dce1530Douglas Thompson i82875p_printk(KERN_ERR, 2921c52152b3008b7bdcc3b94d0be4d0b814dce1530Douglas Thompson "%s(): pci_bus_add_device() Failed\n", 2931c52152b3008b7bdcc3b94d0be4d0b814dce1530Douglas Thompson __func__); 2941c52152b3008b7bdcc3b94d0be4d0b814dce1530Douglas Thompson } 295307d114441f905e4576871ff28d06408a1af1a7eJarkko Lavinen pci_bus_assign_resources(dev->bus); 2960d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox } 297e7ecd8910293564d357dbaf18eb179e06fa35fd0Dave Peterson 2981318952514d5651c453d89989595a9df3b37267bDoug Thompson *ovrfl_pdev = dev; 2991318952514d5651c453d89989595a9df3b37267bDoug Thompson 3001318952514d5651c453d89989595a9df3b37267bDoug Thompson if (pci_enable_device(dev)) { 3011318952514d5651c453d89989595a9df3b37267bDoug Thompson i82875p_printk(KERN_ERR, "%s(): Failed to enable overflow " 302052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson "device\n", __func__); 3031318952514d5651c453d89989595a9df3b37267bDoug Thompson return 1; 3040d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox } 3050d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox 3061318952514d5651c453d89989595a9df3b37267bDoug Thompson if (pci_request_regions(dev, pci_name(dev))) { 3070d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox#ifdef CORRECT_BIOS 308637beb697b8dc7b9d7a35c2b6488332e77963dedDave Peterson goto fail0; 3090d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox#endif 3100d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox } 311e7ecd8910293564d357dbaf18eb179e06fa35fd0Dave Peterson 3120d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox /* cache is irrelevant for PCI bus reads/writes */ 3131dca00bd028e96d39992f501e9251e0cda499562Arjan van de Ven window = pci_ioremap_bar(dev, 0); 3141318952514d5651c453d89989595a9df3b37267bDoug Thompson if (window == NULL) { 315537fba28928c01b7db1580627450691a4bb0b9b3Dave Peterson i82875p_printk(KERN_ERR, "%s(): Failed to ioremap bar6\n", 316052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson __func__); 317637beb697b8dc7b9d7a35c2b6488332e77963dedDave Peterson goto fail1; 3180d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox } 3190d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox 3201318952514d5651c453d89989595a9df3b37267bDoug Thompson *ovrfl_window = window; 3211318952514d5651c453d89989595a9df3b37267bDoug Thompson return 0; 3220d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox 323052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompsonfail1: 3241318952514d5651c453d89989595a9df3b37267bDoug Thompson pci_release_regions(dev); 3250d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox 3261318952514d5651c453d89989595a9df3b37267bDoug Thompson#ifdef CORRECT_BIOS 327052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompsonfail0: 3281318952514d5651c453d89989595a9df3b37267bDoug Thompson pci_disable_device(dev); 3291318952514d5651c453d89989595a9df3b37267bDoug Thompson#endif 3301318952514d5651c453d89989595a9df3b37267bDoug Thompson /* NOTE: the ovrfl proc entry and pci_dev are intentionally left */ 3311318952514d5651c453d89989595a9df3b37267bDoug Thompson return 1; 3321318952514d5651c453d89989595a9df3b37267bDoug Thompson} 3330d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox 3341318952514d5651c453d89989595a9df3b37267bDoug Thompson/* Return 1 if dual channel mode is active. Else return 0. */ 3351318952514d5651c453d89989595a9df3b37267bDoug Thompsonstatic inline int dual_channel_active(u32 drc) 3361318952514d5651c453d89989595a9df3b37267bDoug Thompson{ 3371318952514d5651c453d89989595a9df3b37267bDoug Thompson return (drc >> 21) & 0x1; 3381318952514d5651c453d89989595a9df3b37267bDoug Thompson} 3390d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox 3401318952514d5651c453d89989595a9df3b37267bDoug Thompsonstatic void i82875p_init_csrows(struct mem_ctl_info *mci, 341466b71d58413a515a8029b4eccf98c08b8bb5acaDave Jiang struct pci_dev *pdev, 342466b71d58413a515a8029b4eccf98c08b8bb5acaDave Jiang void __iomem * ovrfl_window, u32 drc) 3431318952514d5651c453d89989595a9df3b37267bDoug Thompson{ 3441318952514d5651c453d89989595a9df3b37267bDoug Thompson struct csrow_info *csrow; 3451318952514d5651c453d89989595a9df3b37267bDoug Thompson unsigned long last_cumul_size; 3461318952514d5651c453d89989595a9df3b37267bDoug Thompson u8 value; 347466b71d58413a515a8029b4eccf98c08b8bb5acaDave Jiang u32 drc_ddim; /* DRAM Data Integrity Mode 0=none,2=edac */ 3481318952514d5651c453d89989595a9df3b37267bDoug Thompson u32 cumul_size; 3491318952514d5651c453d89989595a9df3b37267bDoug Thompson int index; 3501318952514d5651c453d89989595a9df3b37267bDoug Thompson 3511318952514d5651c453d89989595a9df3b37267bDoug Thompson drc_ddim = (drc >> 18) & 0x1; 3521318952514d5651c453d89989595a9df3b37267bDoug Thompson last_cumul_size = 0; 3531318952514d5651c453d89989595a9df3b37267bDoug Thompson 3541318952514d5651c453d89989595a9df3b37267bDoug Thompson /* The dram row boundary (DRB) reg values are boundary address 3550d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox * for each DRAM row with a granularity of 32 or 64MB (single/dual 3560d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox * channel operation). DRB regs are cumulative; therefore DRB7 will 3570d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox * contain the total memory contained in all eight rows. 3580d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox */ 3591318952514d5651c453d89989595a9df3b37267bDoug Thompson 3601318952514d5651c453d89989595a9df3b37267bDoug Thompson for (index = 0; index < mci->nr_csrows; index++) { 3611318952514d5651c453d89989595a9df3b37267bDoug Thompson csrow = &mci->csrows[index]; 3620d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox 3630d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox value = readb(ovrfl_window + I82875P_DRB + index); 3640d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox cumul_size = value << (I82875P_DRB_SHIFT - PAGE_SHIFT); 365537fba28928c01b7db1580627450691a4bb0b9b3Dave Peterson debugf3("%s(): (%d) cumul_size 0x%x\n", __func__, index, 366537fba28928c01b7db1580627450691a4bb0b9b3Dave Peterson cumul_size); 3670d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox if (cumul_size == last_cumul_size) 3680d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox continue; /* not populated */ 3690d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox 3700d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox csrow->first_page = last_cumul_size; 3710d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox csrow->last_page = cumul_size - 1; 3720d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox csrow->nr_pages = cumul_size - last_cumul_size; 3730d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox last_cumul_size = cumul_size; 3741318952514d5651c453d89989595a9df3b37267bDoug Thompson csrow->grain = 1 << 12; /* I82875P_EAP has 4KiB reolution */ 3750d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox csrow->mtype = MEM_DDR; 3760d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox csrow->dtype = DEV_UNKNOWN; 3770d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox csrow->edac_mode = drc_ddim ? EDAC_SECDED : EDAC_NONE; 3780d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox } 3791318952514d5651c453d89989595a9df3b37267bDoug Thompson} 3801318952514d5651c453d89989595a9df3b37267bDoug Thompson 3811318952514d5651c453d89989595a9df3b37267bDoug Thompsonstatic int i82875p_probe1(struct pci_dev *pdev, int dev_idx) 3821318952514d5651c453d89989595a9df3b37267bDoug Thompson{ 3831318952514d5651c453d89989595a9df3b37267bDoug Thompson int rc = -ENODEV; 3841318952514d5651c453d89989595a9df3b37267bDoug Thompson struct mem_ctl_info *mci; 3851318952514d5651c453d89989595a9df3b37267bDoug Thompson struct i82875p_pvt *pvt; 3861318952514d5651c453d89989595a9df3b37267bDoug Thompson struct pci_dev *ovrfl_pdev; 3871318952514d5651c453d89989595a9df3b37267bDoug Thompson void __iomem *ovrfl_window; 3881318952514d5651c453d89989595a9df3b37267bDoug Thompson u32 drc; 3891318952514d5651c453d89989595a9df3b37267bDoug Thompson u32 nr_chans; 3901318952514d5651c453d89989595a9df3b37267bDoug Thompson struct i82875p_error_info discard; 3910d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox 3921318952514d5651c453d89989595a9df3b37267bDoug Thompson debugf0("%s()\n", __func__); 393c3c52bce6993c6d37af2c2de9b482a7013d646a7Hitoshi Mitake 3941318952514d5651c453d89989595a9df3b37267bDoug Thompson ovrfl_pdev = pci_get_device(PCI_VEND_DEV(INTEL, 82875_6), NULL); 3951318952514d5651c453d89989595a9df3b37267bDoug Thompson 3961318952514d5651c453d89989595a9df3b37267bDoug Thompson if (i82875p_setup_overfl_dev(pdev, &ovrfl_pdev, &ovrfl_window)) 3971318952514d5651c453d89989595a9df3b37267bDoug Thompson return -ENODEV; 3981318952514d5651c453d89989595a9df3b37267bDoug Thompson drc = readl(ovrfl_window + I82875P_DRC); 3991318952514d5651c453d89989595a9df3b37267bDoug Thompson nr_chans = dual_channel_active(drc) + 1; 4001318952514d5651c453d89989595a9df3b37267bDoug Thompson mci = edac_mc_alloc(sizeof(*pvt), I82875P_NR_CSROWS(nr_chans), 401b8f6f9755248026f21282e25cac49a1af698056cDoug Thompson nr_chans, 0); 4021318952514d5651c453d89989595a9df3b37267bDoug Thompson 4031318952514d5651c453d89989595a9df3b37267bDoug Thompson if (!mci) { 4041318952514d5651c453d89989595a9df3b37267bDoug Thompson rc = -ENOMEM; 4051318952514d5651c453d89989595a9df3b37267bDoug Thompson goto fail0; 4061318952514d5651c453d89989595a9df3b37267bDoug Thompson } 4071318952514d5651c453d89989595a9df3b37267bDoug Thompson 40809a81269c7aadaec3375a7ebd9647acbb72f5a67Jarkko Lavinen /* Keeps mci available after edac_mc_del_mc() till edac_mc_free() */ 40909a81269c7aadaec3375a7ebd9647acbb72f5a67Jarkko Lavinen kobject_get(&mci->edac_mci_kobj); 41009a81269c7aadaec3375a7ebd9647acbb72f5a67Jarkko Lavinen 4111318952514d5651c453d89989595a9df3b37267bDoug Thompson debugf3("%s(): init mci\n", __func__); 4121318952514d5651c453d89989595a9df3b37267bDoug Thompson mci->dev = &pdev->dev; 4131318952514d5651c453d89989595a9df3b37267bDoug Thompson mci->mtype_cap = MEM_FLAG_DDR; 4141318952514d5651c453d89989595a9df3b37267bDoug Thompson mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED; 4151318952514d5651c453d89989595a9df3b37267bDoug Thompson mci->edac_cap = EDAC_FLAG_UNKNOWN; 4161318952514d5651c453d89989595a9df3b37267bDoug Thompson mci->mod_name = EDAC_MOD_STR; 4171318952514d5651c453d89989595a9df3b37267bDoug Thompson mci->mod_ver = I82875P_REVISION; 4181318952514d5651c453d89989595a9df3b37267bDoug Thompson mci->ctl_name = i82875p_devs[dev_idx].ctl_name; 419c4192705fec85219086231a1c0fa61e8776e2c3bDave Jiang mci->dev_name = pci_name(pdev); 4201318952514d5651c453d89989595a9df3b37267bDoug Thompson mci->edac_check = i82875p_check; 4211318952514d5651c453d89989595a9df3b37267bDoug Thompson mci->ctl_page_to_phys = NULL; 4221318952514d5651c453d89989595a9df3b37267bDoug Thompson debugf3("%s(): init pvt\n", __func__); 423466b71d58413a515a8029b4eccf98c08b8bb5acaDave Jiang pvt = (struct i82875p_pvt *)mci->pvt_info; 4241318952514d5651c453d89989595a9df3b37267bDoug Thompson pvt->ovrfl_pdev = ovrfl_pdev; 4251318952514d5651c453d89989595a9df3b37267bDoug Thompson pvt->ovrfl_window = ovrfl_window; 4261318952514d5651c453d89989595a9df3b37267bDoug Thompson i82875p_init_csrows(mci, pdev, ovrfl_window, drc); 427466b71d58413a515a8029b4eccf98c08b8bb5acaDave Jiang i82875p_get_error_info(mci, &discard); /* clear counters */ 4280d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox 4292d7bbb91c8df26c60d223205a087507430024177Doug Thompson /* Here we assume that we will never see multiple instances of this 4302d7bbb91c8df26c60d223205a087507430024177Doug Thompson * type of memory controller. The ID is therefore hardcoded to 0. 4312d7bbb91c8df26c60d223205a087507430024177Doug Thompson */ 432b8f6f9755248026f21282e25cac49a1af698056cDoug Thompson if (edac_mc_add_mc(mci)) { 433537fba28928c01b7db1580627450691a4bb0b9b3Dave Peterson debugf3("%s(): failed edac_mc_add_mc()\n", __func__); 4341318952514d5651c453d89989595a9df3b37267bDoug Thompson goto fail1; 4350d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox } 4360d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox 437456a2f9552e7849475f4aea1a9aa4c0e54b3dddaDave Jiang /* allocating generic PCI control info */ 438456a2f9552e7849475f4aea1a9aa4c0e54b3dddaDave Jiang i82875p_pci = edac_pci_create_generic_ctl(&pdev->dev, EDAC_MOD_STR); 439456a2f9552e7849475f4aea1a9aa4c0e54b3dddaDave Jiang if (!i82875p_pci) { 440456a2f9552e7849475f4aea1a9aa4c0e54b3dddaDave Jiang printk(KERN_WARNING 441456a2f9552e7849475f4aea1a9aa4c0e54b3dddaDave Jiang "%s(): Unable to create PCI control\n", 442456a2f9552e7849475f4aea1a9aa4c0e54b3dddaDave Jiang __func__); 443456a2f9552e7849475f4aea1a9aa4c0e54b3dddaDave Jiang printk(KERN_WARNING 444456a2f9552e7849475f4aea1a9aa4c0e54b3dddaDave Jiang "%s(): PCI error report via EDAC not setup\n", 445456a2f9552e7849475f4aea1a9aa4c0e54b3dddaDave Jiang __func__); 446456a2f9552e7849475f4aea1a9aa4c0e54b3dddaDave Jiang } 447456a2f9552e7849475f4aea1a9aa4c0e54b3dddaDave Jiang 4480d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox /* get this far and it's successful */ 449537fba28928c01b7db1580627450691a4bb0b9b3Dave Peterson debugf3("%s(): success\n", __func__); 4500d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox return 0; 4510d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox 452052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompsonfail1: 45309a81269c7aadaec3375a7ebd9647acbb72f5a67Jarkko Lavinen kobject_put(&mci->edac_mci_kobj); 454637beb697b8dc7b9d7a35c2b6488332e77963dedDave Peterson edac_mc_free(mci); 4550d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox 456052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompsonfail0: 457637beb697b8dc7b9d7a35c2b6488332e77963dedDave Peterson iounmap(ovrfl_window); 458637beb697b8dc7b9d7a35c2b6488332e77963dedDave Peterson pci_release_regions(ovrfl_pdev); 4590d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox 460637beb697b8dc7b9d7a35c2b6488332e77963dedDave Peterson pci_disable_device(ovrfl_pdev); 4610d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox /* NOTE: the ovrfl proc entry and pci_dev are intentionally left */ 4620d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox return rc; 4630d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox} 4640d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox 4650d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox/* returns count (>= 0), or negative on error */ 4660d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Coxstatic int __devinit i82875p_init_one(struct pci_dev *pdev, 467052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson const struct pci_device_id *ent) 4680d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox{ 4690d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox int rc; 4700d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox 471537fba28928c01b7db1580627450691a4bb0b9b3Dave Peterson debugf0("%s()\n", __func__); 472537fba28928c01b7db1580627450691a4bb0b9b3Dave Peterson i82875p_printk(KERN_INFO, "i82875p init one\n"); 473e7ecd8910293564d357dbaf18eb179e06fa35fd0Dave Peterson 474e7ecd8910293564d357dbaf18eb179e06fa35fd0Dave Peterson if (pci_enable_device(pdev) < 0) 4750d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox return -EIO; 476e7ecd8910293564d357dbaf18eb179e06fa35fd0Dave Peterson 4770d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox rc = i82875p_probe1(pdev, ent->driver_data); 478e7ecd8910293564d357dbaf18eb179e06fa35fd0Dave Peterson 4790d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox if (mci_pdev == NULL) 4800d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox mci_pdev = pci_dev_get(pdev); 481e7ecd8910293564d357dbaf18eb179e06fa35fd0Dave Peterson 4820d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox return rc; 4830d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox} 4840d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox 4850d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Coxstatic void __devexit i82875p_remove_one(struct pci_dev *pdev) 4860d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox{ 4870d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox struct mem_ctl_info *mci; 4880d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox struct i82875p_pvt *pvt = NULL; 4890d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox 490537fba28928c01b7db1580627450691a4bb0b9b3Dave Peterson debugf0("%s()\n", __func__); 4910d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox 492456a2f9552e7849475f4aea1a9aa4c0e54b3dddaDave Jiang if (i82875p_pci) 493456a2f9552e7849475f4aea1a9aa4c0e54b3dddaDave Jiang edac_pci_release_generic_ctl(i82875p_pci); 494456a2f9552e7849475f4aea1a9aa4c0e54b3dddaDave Jiang 49537f04581abac20444e5b7106c1e1f28bec5b989cDoug Thompson if ((mci = edac_mc_del_mc(&pdev->dev)) == NULL) 4960d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox return; 4970d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox 498466b71d58413a515a8029b4eccf98c08b8bb5acaDave Jiang pvt = (struct i82875p_pvt *)mci->pvt_info; 499e7ecd8910293564d357dbaf18eb179e06fa35fd0Dave Peterson 5000d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox if (pvt->ovrfl_window) 5010d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox iounmap(pvt->ovrfl_window); 5020d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox 5030d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox if (pvt->ovrfl_pdev) { 5040d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox#ifdef CORRECT_BIOS 5050d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox pci_release_regions(pvt->ovrfl_pdev); 5060d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox#endif /*CORRECT_BIOS */ 5070d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox pci_disable_device(pvt->ovrfl_pdev); 5080d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox pci_dev_put(pvt->ovrfl_pdev); 5090d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox } 5100d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox 5110d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox edac_mc_free(mci); 5120d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox} 5130d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox 5140d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Coxstatic const struct pci_device_id i82875p_pci_tbl[] __devinitdata = { 515e7ecd8910293564d357dbaf18eb179e06fa35fd0Dave Peterson { 516466b71d58413a515a8029b4eccf98c08b8bb5acaDave Jiang PCI_VEND_DEV(INTEL, 82875_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0, 517466b71d58413a515a8029b4eccf98c08b8bb5acaDave Jiang I82875P}, 518e7ecd8910293564d357dbaf18eb179e06fa35fd0Dave Peterson { 519466b71d58413a515a8029b4eccf98c08b8bb5acaDave Jiang 0, 520466b71d58413a515a8029b4eccf98c08b8bb5acaDave Jiang } /* 0 terminated list. */ 5210d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox}; 5220d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox 5230d88a10e566d46bffc214c974e5cf5abe38d8da8Alan CoxMODULE_DEVICE_TABLE(pci, i82875p_pci_tbl); 5240d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox 5250d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Coxstatic struct pci_driver i82875p_driver = { 526680cbbbb0e336b04b74be48b8ddd870537f1e226Dave Peterson .name = EDAC_MOD_STR, 5270d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox .probe = i82875p_init_one, 5280d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox .remove = __devexit_p(i82875p_remove_one), 5290d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox .id_table = i82875p_pci_tbl, 5300d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox}; 5310d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox 532da9bb1d27b21cb24cbb6a2efb5d3c464d357a01eAlan Coxstatic int __init i82875p_init(void) 5330d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox{ 5340d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox int pci_rc; 5350d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox 536537fba28928c01b7db1580627450691a4bb0b9b3Dave Peterson debugf3("%s()\n", __func__); 537c3c52bce6993c6d37af2c2de9b482a7013d646a7Hitoshi Mitake 538c3c52bce6993c6d37af2c2de9b482a7013d646a7Hitoshi Mitake /* Ensure that the OPSTATE is set correctly for POLL or NMI */ 539c3c52bce6993c6d37af2c2de9b482a7013d646a7Hitoshi Mitake opstate_init(); 540c3c52bce6993c6d37af2c2de9b482a7013d646a7Hitoshi Mitake 5410d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox pci_rc = pci_register_driver(&i82875p_driver); 542e7ecd8910293564d357dbaf18eb179e06fa35fd0Dave Peterson 5430d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox if (pci_rc < 0) 544637beb697b8dc7b9d7a35c2b6488332e77963dedDave Peterson goto fail0; 545e7ecd8910293564d357dbaf18eb179e06fa35fd0Dave Peterson 5460d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox if (mci_pdev == NULL) { 547e7ecd8910293564d357dbaf18eb179e06fa35fd0Dave Peterson mci_pdev = pci_get_device(PCI_VENDOR_ID_INTEL, 548052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompson PCI_DEVICE_ID_INTEL_82875_0, NULL); 549e7ecd8910293564d357dbaf18eb179e06fa35fd0Dave Peterson 5500d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox if (!mci_pdev) { 5510d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox debugf0("875p pci_get_device fail\n"); 552637beb697b8dc7b9d7a35c2b6488332e77963dedDave Peterson pci_rc = -ENODEV; 553637beb697b8dc7b9d7a35c2b6488332e77963dedDave Peterson goto fail1; 5540d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox } 555e7ecd8910293564d357dbaf18eb179e06fa35fd0Dave Peterson 5560d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox pci_rc = i82875p_init_one(mci_pdev, i82875p_pci_tbl); 557e7ecd8910293564d357dbaf18eb179e06fa35fd0Dave Peterson 5580d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox if (pci_rc < 0) { 5590d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox debugf0("875p init fail\n"); 560637beb697b8dc7b9d7a35c2b6488332e77963dedDave Peterson pci_rc = -ENODEV; 561637beb697b8dc7b9d7a35c2b6488332e77963dedDave Peterson goto fail1; 5620d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox } 5630d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox } 564e7ecd8910293564d357dbaf18eb179e06fa35fd0Dave Peterson 5650d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox return 0; 566637beb697b8dc7b9d7a35c2b6488332e77963dedDave Peterson 567052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompsonfail1: 568637beb697b8dc7b9d7a35c2b6488332e77963dedDave Peterson pci_unregister_driver(&i82875p_driver); 569637beb697b8dc7b9d7a35c2b6488332e77963dedDave Peterson 570052dfb45ccb5ea354a426b52556bcfee75b9d2f5Douglas Thompsonfail0: 571637beb697b8dc7b9d7a35c2b6488332e77963dedDave Peterson if (mci_pdev != NULL) 572637beb697b8dc7b9d7a35c2b6488332e77963dedDave Peterson pci_dev_put(mci_pdev); 573637beb697b8dc7b9d7a35c2b6488332e77963dedDave Peterson 574637beb697b8dc7b9d7a35c2b6488332e77963dedDave Peterson return pci_rc; 5750d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox} 5760d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox 5770d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Coxstatic void __exit i82875p_exit(void) 5780d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox{ 579537fba28928c01b7db1580627450691a4bb0b9b3Dave Peterson debugf3("%s()\n", __func__); 5800d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox 58109a81269c7aadaec3375a7ebd9647acbb72f5a67Jarkko Lavinen i82875p_remove_one(mci_pdev); 58209a81269c7aadaec3375a7ebd9647acbb72f5a67Jarkko Lavinen pci_dev_put(mci_pdev); 58309a81269c7aadaec3375a7ebd9647acbb72f5a67Jarkko Lavinen 5840d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox pci_unregister_driver(&i82875p_driver); 585e7ecd8910293564d357dbaf18eb179e06fa35fd0Dave Peterson 5860d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox} 5870d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox 5880d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Coxmodule_init(i82875p_init); 5890d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Coxmodule_exit(i82875p_exit); 5900d88a10e566d46bffc214c974e5cf5abe38d8da8Alan Cox 5910d88a10e566d46bffc214c974e5cf5abe38d8da8Alan CoxMODULE_LICENSE("GPL"); 5920d88a10e566d46bffc214c974e5cf5abe38d8da8Alan CoxMODULE_AUTHOR("Linux Networx (http://lnxi.com) Thayne Harbaugh"); 5930d88a10e566d46bffc214c974e5cf5abe38d8da8Alan CoxMODULE_DESCRIPTION("MC support for Intel 82875 memory hub controllers"); 594c3c52bce6993c6d37af2c2de9b482a7013d646a7Hitoshi Mitake 595c3c52bce6993c6d37af2c2de9b482a7013d646a7Hitoshi Mitakemodule_param(edac_op_state, int, 0444); 596c3c52bce6993c6d37af2c2de9b482a7013d646a7Hitoshi MitakeMODULE_PARM_DESC(edac_op_state, "EDAC Error Reporting state: 0=Poll,1=NMI"); 597