^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) * Intel 5000(P/V/X) class Memory Controllers kernel module
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * This file may be distributed under the terms of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * GNU General Public License.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Written by Douglas Thompson Linux Networx (http://lnxi.com)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * norsk5@xmission.com
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * This module is based on the following document:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * Intel 5000X Chipset Memory Controller Hub (MCH) - Datasheet
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * http://developer.intel.com/design/chipsets/datashts/313070.htm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/pci.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/pci_ids.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/edac.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <asm/mmzone.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include "edac_module.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) * Alter this version for the I5000 module when modifications are made
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #define I5000_REVISION " Ver: 2.0.12"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #define EDAC_MOD_STR "i5000_edac"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #define i5000_printk(level, fmt, arg...) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) edac_printk(level, "i5000", fmt, ##arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #define i5000_mc_printk(mci, level, fmt, arg...) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) edac_mc_chipset_printk(mci, level, "i5000", fmt, ##arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #ifndef PCI_DEVICE_ID_INTEL_FBD_0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #define PCI_DEVICE_ID_INTEL_FBD_0 0x25F5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #ifndef PCI_DEVICE_ID_INTEL_FBD_1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #define PCI_DEVICE_ID_INTEL_FBD_1 0x25F6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) /* Device 16,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) * Function 0: System Address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) * Function 1: Memory Branch Map, Control, Errors Register
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) * Function 2: FSB Error Registers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) * All 3 functions of Device 16 (0,1,2) share the SAME DID
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #define PCI_DEVICE_ID_INTEL_I5000_DEV16 0x25F0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) /* OFFSETS for Function 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) /* OFFSETS for Function 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #define AMBASE 0x48
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) #define MAXCH 0x56
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) #define MAXDIMMPERCH 0x57
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) #define TOLM 0x6C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) #define REDMEMB 0x7C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) #define RED_ECC_LOCATOR(x) ((x) & 0x3FFFF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) #define REC_ECC_LOCATOR_EVEN(x) ((x) & 0x001FF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) #define REC_ECC_LOCATOR_ODD(x) ((x) & 0x3FE00)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) #define MIR0 0x80
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) #define MIR1 0x84
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) #define MIR2 0x88
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) #define AMIR0 0x8C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) #define AMIR1 0x90
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) #define AMIR2 0x94
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) #define FERR_FAT_FBD 0x98
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) #define NERR_FAT_FBD 0x9C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) #define EXTRACT_FBDCHAN_INDX(x) (((x)>>28) & 0x3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) #define FERR_FAT_FBDCHAN 0x30000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) #define FERR_FAT_M3ERR 0x00000004
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) #define FERR_FAT_M2ERR 0x00000002
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) #define FERR_FAT_M1ERR 0x00000001
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) #define FERR_FAT_MASK (FERR_FAT_M1ERR | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) FERR_FAT_M2ERR | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) FERR_FAT_M3ERR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) #define FERR_NF_FBD 0xA0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) /* Thermal and SPD or BFD errors */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) #define FERR_NF_M28ERR 0x01000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) #define FERR_NF_M27ERR 0x00800000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) #define FERR_NF_M26ERR 0x00400000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) #define FERR_NF_M25ERR 0x00200000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) #define FERR_NF_M24ERR 0x00100000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) #define FERR_NF_M23ERR 0x00080000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) #define FERR_NF_M22ERR 0x00040000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) #define FERR_NF_M21ERR 0x00020000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) /* Correctable errors */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) #define FERR_NF_M20ERR 0x00010000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) #define FERR_NF_M19ERR 0x00008000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) #define FERR_NF_M18ERR 0x00004000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) #define FERR_NF_M17ERR 0x00002000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) /* Non-Retry or redundant Retry errors */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) #define FERR_NF_M16ERR 0x00001000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) #define FERR_NF_M15ERR 0x00000800
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) #define FERR_NF_M14ERR 0x00000400
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) #define FERR_NF_M13ERR 0x00000200
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) /* Uncorrectable errors */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) #define FERR_NF_M12ERR 0x00000100
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) #define FERR_NF_M11ERR 0x00000080
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) #define FERR_NF_M10ERR 0x00000040
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) #define FERR_NF_M9ERR 0x00000020
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) #define FERR_NF_M8ERR 0x00000010
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) #define FERR_NF_M7ERR 0x00000008
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) #define FERR_NF_M6ERR 0x00000004
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) #define FERR_NF_M5ERR 0x00000002
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) #define FERR_NF_M4ERR 0x00000001
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) #define FERR_NF_UNCORRECTABLE (FERR_NF_M12ERR | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) FERR_NF_M11ERR | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) FERR_NF_M10ERR | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) FERR_NF_M9ERR | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) FERR_NF_M8ERR | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) FERR_NF_M7ERR | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) FERR_NF_M6ERR | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) FERR_NF_M5ERR | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) FERR_NF_M4ERR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) #define FERR_NF_CORRECTABLE (FERR_NF_M20ERR | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) FERR_NF_M19ERR | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) FERR_NF_M18ERR | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) FERR_NF_M17ERR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) #define FERR_NF_DIMM_SPARE (FERR_NF_M27ERR | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) FERR_NF_M28ERR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) #define FERR_NF_THERMAL (FERR_NF_M26ERR | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) FERR_NF_M25ERR | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) FERR_NF_M24ERR | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) FERR_NF_M23ERR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) #define FERR_NF_SPD_PROTOCOL (FERR_NF_M22ERR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) #define FERR_NF_NORTH_CRC (FERR_NF_M21ERR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) #define FERR_NF_NON_RETRY (FERR_NF_M13ERR | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) FERR_NF_M14ERR | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) FERR_NF_M15ERR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) #define NERR_NF_FBD 0xA4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) #define FERR_NF_MASK (FERR_NF_UNCORRECTABLE | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) FERR_NF_CORRECTABLE | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) FERR_NF_DIMM_SPARE | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) FERR_NF_THERMAL | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) FERR_NF_SPD_PROTOCOL | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) FERR_NF_NORTH_CRC | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) FERR_NF_NON_RETRY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) #define EMASK_FBD 0xA8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) #define EMASK_FBD_M28ERR 0x08000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) #define EMASK_FBD_M27ERR 0x04000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) #define EMASK_FBD_M26ERR 0x02000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) #define EMASK_FBD_M25ERR 0x01000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) #define EMASK_FBD_M24ERR 0x00800000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) #define EMASK_FBD_M23ERR 0x00400000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) #define EMASK_FBD_M22ERR 0x00200000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) #define EMASK_FBD_M21ERR 0x00100000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) #define EMASK_FBD_M20ERR 0x00080000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) #define EMASK_FBD_M19ERR 0x00040000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) #define EMASK_FBD_M18ERR 0x00020000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) #define EMASK_FBD_M17ERR 0x00010000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) #define EMASK_FBD_M15ERR 0x00004000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) #define EMASK_FBD_M14ERR 0x00002000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) #define EMASK_FBD_M13ERR 0x00001000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) #define EMASK_FBD_M12ERR 0x00000800
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) #define EMASK_FBD_M11ERR 0x00000400
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) #define EMASK_FBD_M10ERR 0x00000200
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) #define EMASK_FBD_M9ERR 0x00000100
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) #define EMASK_FBD_M8ERR 0x00000080
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) #define EMASK_FBD_M7ERR 0x00000040
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) #define EMASK_FBD_M6ERR 0x00000020
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) #define EMASK_FBD_M5ERR 0x00000010
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) #define EMASK_FBD_M4ERR 0x00000008
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) #define EMASK_FBD_M3ERR 0x00000004
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) #define EMASK_FBD_M2ERR 0x00000002
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) #define EMASK_FBD_M1ERR 0x00000001
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) #define ENABLE_EMASK_FBD_FATAL_ERRORS (EMASK_FBD_M1ERR | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) EMASK_FBD_M2ERR | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) EMASK_FBD_M3ERR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) #define ENABLE_EMASK_FBD_UNCORRECTABLE (EMASK_FBD_M4ERR | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) EMASK_FBD_M5ERR | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) EMASK_FBD_M6ERR | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) EMASK_FBD_M7ERR | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) EMASK_FBD_M8ERR | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) EMASK_FBD_M9ERR | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) EMASK_FBD_M10ERR | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) EMASK_FBD_M11ERR | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) EMASK_FBD_M12ERR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) #define ENABLE_EMASK_FBD_CORRECTABLE (EMASK_FBD_M17ERR | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) EMASK_FBD_M18ERR | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) EMASK_FBD_M19ERR | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) EMASK_FBD_M20ERR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) #define ENABLE_EMASK_FBD_DIMM_SPARE (EMASK_FBD_M27ERR | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) EMASK_FBD_M28ERR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) #define ENABLE_EMASK_FBD_THERMALS (EMASK_FBD_M26ERR | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) EMASK_FBD_M25ERR | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) EMASK_FBD_M24ERR | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) EMASK_FBD_M23ERR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) #define ENABLE_EMASK_FBD_SPD_PROTOCOL (EMASK_FBD_M22ERR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) #define ENABLE_EMASK_FBD_NORTH_CRC (EMASK_FBD_M21ERR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) #define ENABLE_EMASK_FBD_NON_RETRY (EMASK_FBD_M15ERR | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) EMASK_FBD_M14ERR | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) EMASK_FBD_M13ERR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) #define ENABLE_EMASK_ALL (ENABLE_EMASK_FBD_NON_RETRY | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) ENABLE_EMASK_FBD_NORTH_CRC | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) ENABLE_EMASK_FBD_SPD_PROTOCOL | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) ENABLE_EMASK_FBD_THERMALS | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) ENABLE_EMASK_FBD_DIMM_SPARE | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) ENABLE_EMASK_FBD_FATAL_ERRORS | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) ENABLE_EMASK_FBD_CORRECTABLE | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) ENABLE_EMASK_FBD_UNCORRECTABLE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) #define ERR0_FBD 0xAC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) #define ERR1_FBD 0xB0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) #define ERR2_FBD 0xB4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) #define MCERR_FBD 0xB8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) #define NRECMEMA 0xBE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) #define NREC_BANK(x) (((x)>>12) & 0x7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) #define NREC_RDWR(x) (((x)>>11) & 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) #define NREC_RANK(x) (((x)>>8) & 0x7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) #define NRECMEMB 0xC0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) #define NREC_CAS(x) (((x)>>16) & 0xFFF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) #define NREC_RAS(x) ((x) & 0x7FFF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) #define NRECFGLOG 0xC4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) #define NREEECFBDA 0xC8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) #define NREEECFBDB 0xCC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) #define NREEECFBDC 0xD0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) #define NREEECFBDD 0xD4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) #define NREEECFBDE 0xD8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) #define REDMEMA 0xDC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) #define RECMEMA 0xE2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) #define REC_BANK(x) (((x)>>12) & 0x7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) #define REC_RDWR(x) (((x)>>11) & 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) #define REC_RANK(x) (((x)>>8) & 0x7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) #define RECMEMB 0xE4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) #define REC_CAS(x) (((x)>>16) & 0xFFFFFF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) #define REC_RAS(x) ((x) & 0x7FFF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) #define RECFGLOG 0xE8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) #define RECFBDA 0xEC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) #define RECFBDB 0xF0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) #define RECFBDC 0xF4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) #define RECFBDD 0xF8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) #define RECFBDE 0xFC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) /* OFFSETS for Function 2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) * Device 21,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) * Function 0: Memory Map Branch 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) * Device 22,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) * Function 0: Memory Map Branch 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) #define PCI_DEVICE_ID_I5000_BRANCH_0 0x25F5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) #define PCI_DEVICE_ID_I5000_BRANCH_1 0x25F6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) #define AMB_PRESENT_0 0x64
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) #define AMB_PRESENT_1 0x66
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) #define MTR0 0x80
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) #define MTR1 0x84
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) #define MTR2 0x88
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) #define MTR3 0x8C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) #define NUM_MTRS 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) #define CHANNELS_PER_BRANCH 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) #define MAX_BRANCHES 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) /* Defines to extract the various fields from the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) * MTRx - Memory Technology Registers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) #define MTR_DIMMS_PRESENT(mtr) ((mtr) & (0x1 << 8))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) #define MTR_DRAM_WIDTH(mtr) ((((mtr) >> 6) & 0x1) ? 8 : 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) #define MTR_DRAM_BANKS(mtr) ((((mtr) >> 5) & 0x1) ? 8 : 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) #define MTR_DRAM_BANKS_ADDR_BITS(mtr) ((MTR_DRAM_BANKS(mtr) == 8) ? 3 : 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) #define MTR_DIMM_RANK(mtr) (((mtr) >> 4) & 0x1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) #define MTR_DIMM_RANK_ADDR_BITS(mtr) (MTR_DIMM_RANK(mtr) ? 2 : 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) #define MTR_DIMM_ROWS(mtr) (((mtr) >> 2) & 0x3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) #define MTR_DIMM_ROWS_ADDR_BITS(mtr) (MTR_DIMM_ROWS(mtr) + 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) #define MTR_DIMM_COLS(mtr) ((mtr) & 0x3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) #define MTR_DIMM_COLS_ADDR_BITS(mtr) (MTR_DIMM_COLS(mtr) + 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) /* enables the report of miscellaneous messages as CE errors - default off */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) static int misc_messages;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) /* Enumeration of supported devices */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) enum i5000_chips {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) I5000P = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) I5000V = 1, /* future */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) I5000X = 2 /* future */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) /* Device name and register DID (Device ID) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) struct i5000_dev_info {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) const char *ctl_name; /* name for this device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) u16 fsb_mapping_errors; /* DID for the branchmap,control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) /* Table of devices attributes supported by this driver */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) static const struct i5000_dev_info i5000_devs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) [I5000P] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) .ctl_name = "I5000",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) .fsb_mapping_errors = PCI_DEVICE_ID_INTEL_I5000_DEV16,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) struct i5000_dimm_info {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) int megabytes; /* size, 0 means not present */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) int dual_rank;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) #define MAX_CHANNELS 6 /* max possible channels */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) #define MAX_CSROWS (8*2) /* max possible csrows per channel */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) /* driver private data structure */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) struct i5000_pvt {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) struct pci_dev *system_address; /* 16.0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) struct pci_dev *branchmap_werrors; /* 16.1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) struct pci_dev *fsb_error_regs; /* 16.2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) struct pci_dev *branch_0; /* 21.0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) struct pci_dev *branch_1; /* 22.0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) u16 tolm; /* top of low memory */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) union {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) u64 ambase; /* AMB BAR */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) u32 ambase_bottom;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) u32 ambase_top;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) } u __packed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) u16 mir0, mir1, mir2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) u16 b0_mtr[NUM_MTRS]; /* Memory Technlogy Reg */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) u16 b0_ambpresent0; /* Branch 0, Channel 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) u16 b0_ambpresent1; /* Brnach 0, Channel 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) u16 b1_mtr[NUM_MTRS]; /* Memory Technlogy Reg */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) u16 b1_ambpresent0; /* Branch 1, Channel 8 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) u16 b1_ambpresent1; /* Branch 1, Channel 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) /* DIMM information matrix, allocating architecture maximums */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) struct i5000_dimm_info dimm_info[MAX_CSROWS][MAX_CHANNELS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) /* Actual values for this controller */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) int maxch; /* Max channels */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) int maxdimmperch; /* Max DIMMs per channel */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) /* I5000 MCH error information retrieved from Hardware */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) struct i5000_error_info {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) /* These registers are always read from the MC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) u32 ferr_fat_fbd; /* First Errors Fatal */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) u32 nerr_fat_fbd; /* Next Errors Fatal */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) u32 ferr_nf_fbd; /* First Errors Non-Fatal */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) u32 nerr_nf_fbd; /* Next Errors Non-Fatal */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) /* These registers are input ONLY if there was a Recoverable Error */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) u32 redmemb; /* Recoverable Mem Data Error log B */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) u16 recmema; /* Recoverable Mem Error log A */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) u32 recmemb; /* Recoverable Mem Error log B */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) /* These registers are input ONLY if there was a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) * Non-Recoverable Error */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) u16 nrecmema; /* Non-Recoverable Mem log A */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) u32 nrecmemb; /* Non-Recoverable Mem log B */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) static struct edac_pci_ctl_info *i5000_pci;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) * i5000_get_error_info Retrieve the hardware error information from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) * the hardware and cache it in the 'info'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) * structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) static void i5000_get_error_info(struct mem_ctl_info *mci,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) struct i5000_error_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) struct i5000_pvt *pvt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) u32 value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) pvt = mci->pvt_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) /* read in the 1st FATAL error register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) pci_read_config_dword(pvt->branchmap_werrors, FERR_FAT_FBD, &value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) /* Mask only the bits that the doc says are valid
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) value &= (FERR_FAT_FBDCHAN | FERR_FAT_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) /* If there is an error, then read in the */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) /* NEXT FATAL error register and the Memory Error Log Register A */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) if (value & FERR_FAT_MASK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) info->ferr_fat_fbd = value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) /* harvest the various error data we need */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) pci_read_config_dword(pvt->branchmap_werrors,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) NERR_FAT_FBD, &info->nerr_fat_fbd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) pci_read_config_word(pvt->branchmap_werrors,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) NRECMEMA, &info->nrecmema);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) pci_read_config_dword(pvt->branchmap_werrors,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) NRECMEMB, &info->nrecmemb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) /* Clear the error bits, by writing them back */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) pci_write_config_dword(pvt->branchmap_werrors,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) FERR_FAT_FBD, value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) info->ferr_fat_fbd = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) info->nerr_fat_fbd = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) info->nrecmema = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) info->nrecmemb = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) /* read in the 1st NON-FATAL error register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) pci_read_config_dword(pvt->branchmap_werrors, FERR_NF_FBD, &value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) /* If there is an error, then read in the 1st NON-FATAL error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) * register as well */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) if (value & FERR_NF_MASK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) info->ferr_nf_fbd = value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) /* harvest the various error data we need */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) pci_read_config_dword(pvt->branchmap_werrors,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) NERR_NF_FBD, &info->nerr_nf_fbd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) pci_read_config_word(pvt->branchmap_werrors,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) RECMEMA, &info->recmema);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) pci_read_config_dword(pvt->branchmap_werrors,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) RECMEMB, &info->recmemb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) pci_read_config_dword(pvt->branchmap_werrors,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) REDMEMB, &info->redmemb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) /* Clear the error bits, by writing them back */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) pci_write_config_dword(pvt->branchmap_werrors,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) FERR_NF_FBD, value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) info->ferr_nf_fbd = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) info->nerr_nf_fbd = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) info->recmema = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) info->recmemb = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) info->redmemb = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) * i5000_process_fatal_error_info(struct mem_ctl_info *mci,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) * struct i5000_error_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) * int handle_errors);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) * handle the Intel FATAL errors, if any
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) static void i5000_process_fatal_error_info(struct mem_ctl_info *mci,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) struct i5000_error_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) int handle_errors)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) char msg[EDAC_MC_LABEL_LEN + 1 + 160];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) char *specific = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) u32 allErrors;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) int channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) int bank;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) int rank;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) int rdwr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) int ras, cas;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) /* mask off the Error bits that are possible */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) allErrors = (info->ferr_fat_fbd & FERR_FAT_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) if (!allErrors)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) return; /* if no error, return now */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) channel = EXTRACT_FBDCHAN_INDX(info->ferr_fat_fbd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) /* Use the NON-Recoverable macros to extract data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) bank = NREC_BANK(info->nrecmema);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) rank = NREC_RANK(info->nrecmema);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) rdwr = NREC_RDWR(info->nrecmema);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) ras = NREC_RAS(info->nrecmemb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) cas = NREC_CAS(info->nrecmemb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) edac_dbg(0, "\t\tCSROW= %d Channel= %d (DRAM Bank= %d rdwr= %s ras= %d cas= %d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) rank, channel, bank,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) rdwr ? "Write" : "Read", ras, cas);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) /* Only 1 bit will be on */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) switch (allErrors) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) case FERR_FAT_M1ERR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) specific = "Alert on non-redundant retry or fast "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) "reset timeout";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) case FERR_FAT_M2ERR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) specific = "Northbound CRC error on non-redundant "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) "retry";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) case FERR_FAT_M3ERR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) static int done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) * This error is generated to inform that the intelligent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) * throttling is disabled and the temperature passed the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) * specified middle point. Since this is something the BIOS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) * should take care of, we'll warn only once to avoid
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) * worthlessly flooding the log.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) if (done)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) done++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) specific = ">Tmid Thermal event with intelligent "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) "throttling disabled";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) /* Form out message */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) snprintf(msg, sizeof(msg),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) "Bank=%d RAS=%d CAS=%d FATAL Err=0x%x (%s)",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) bank, ras, cas, allErrors, specific);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) /* Call the helper to output message */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) edac_mc_handle_error(HW_EVENT_ERR_FATAL, mci, 1, 0, 0, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) channel >> 1, channel & 1, rank,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) rdwr ? "Write error" : "Read error",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) * i5000_process_fatal_error_info(struct mem_ctl_info *mci,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) * struct i5000_error_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) * int handle_errors);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) * handle the Intel NON-FATAL errors, if any
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) static void i5000_process_nonfatal_error_info(struct mem_ctl_info *mci,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) struct i5000_error_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) int handle_errors)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) char msg[EDAC_MC_LABEL_LEN + 1 + 170];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) char *specific = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) u32 allErrors;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) u32 ue_errors;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) u32 ce_errors;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) u32 misc_errors;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) int branch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) int channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) int bank;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) int rank;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) int rdwr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) int ras, cas;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) /* mask off the Error bits that are possible */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) allErrors = (info->ferr_nf_fbd & FERR_NF_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) if (!allErrors)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) return; /* if no error, return now */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) /* ONLY ONE of the possible error bits will be set, as per the docs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) ue_errors = allErrors & FERR_NF_UNCORRECTABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) if (ue_errors) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) edac_dbg(0, "\tUncorrected bits= 0x%x\n", ue_errors);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) branch = EXTRACT_FBDCHAN_INDX(info->ferr_nf_fbd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) * According with i5000 datasheet, bit 28 has no significance
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) * for errors M4Err-M12Err and M17Err-M21Err, on FERR_NF_FBD
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) channel = branch & 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) bank = NREC_BANK(info->nrecmema);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) rank = NREC_RANK(info->nrecmema);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) rdwr = NREC_RDWR(info->nrecmema);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) ras = NREC_RAS(info->nrecmemb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) cas = NREC_CAS(info->nrecmemb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) edac_dbg(0, "\t\tCSROW= %d Channels= %d,%d (Branch= %d DRAM Bank= %d rdwr= %s ras= %d cas= %d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) rank, channel, channel + 1, branch >> 1, bank,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) rdwr ? "Write" : "Read", ras, cas);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) switch (ue_errors) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) case FERR_NF_M12ERR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) specific = "Non-Aliased Uncorrectable Patrol Data ECC";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) case FERR_NF_M11ERR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) specific = "Non-Aliased Uncorrectable Spare-Copy "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) "Data ECC";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) case FERR_NF_M10ERR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) specific = "Non-Aliased Uncorrectable Mirrored Demand "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) "Data ECC";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) case FERR_NF_M9ERR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) specific = "Non-Aliased Uncorrectable Non-Mirrored "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) "Demand Data ECC";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) case FERR_NF_M8ERR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) specific = "Aliased Uncorrectable Patrol Data ECC";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) case FERR_NF_M7ERR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) specific = "Aliased Uncorrectable Spare-Copy Data ECC";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) case FERR_NF_M6ERR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) specific = "Aliased Uncorrectable Mirrored Demand "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) "Data ECC";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) case FERR_NF_M5ERR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) specific = "Aliased Uncorrectable Non-Mirrored Demand "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) "Data ECC";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) case FERR_NF_M4ERR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) specific = "Uncorrectable Data ECC on Replay";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) /* Form out message */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) snprintf(msg, sizeof(msg),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) "Rank=%d Bank=%d RAS=%d CAS=%d, UE Err=0x%x (%s)",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) rank, bank, ras, cas, ue_errors, specific);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) /* Call the helper to output message */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, 0, 0, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) channel >> 1, -1, rank,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) rdwr ? "Write error" : "Read error",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) /* Check correctable errors */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) ce_errors = allErrors & FERR_NF_CORRECTABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) if (ce_errors) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) edac_dbg(0, "\tCorrected bits= 0x%x\n", ce_errors);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) branch = EXTRACT_FBDCHAN_INDX(info->ferr_nf_fbd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) channel = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) if (REC_ECC_LOCATOR_ODD(info->redmemb))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) channel = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) /* Convert channel to be based from zero, instead of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) * from branch base of 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) channel += branch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) bank = REC_BANK(info->recmema);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) rank = REC_RANK(info->recmema);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) rdwr = REC_RDWR(info->recmema);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) ras = REC_RAS(info->recmemb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) cas = REC_CAS(info->recmemb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) edac_dbg(0, "\t\tCSROW= %d Channel= %d (Branch %d DRAM Bank= %d rdwr= %s ras= %d cas= %d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) rank, channel, branch >> 1, bank,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) rdwr ? "Write" : "Read", ras, cas);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) switch (ce_errors) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) case FERR_NF_M17ERR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) specific = "Correctable Non-Mirrored Demand Data ECC";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) case FERR_NF_M18ERR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) specific = "Correctable Mirrored Demand Data ECC";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) case FERR_NF_M19ERR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) specific = "Correctable Spare-Copy Data ECC";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) case FERR_NF_M20ERR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) specific = "Correctable Patrol Data ECC";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) /* Form out message */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) snprintf(msg, sizeof(msg),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) "Rank=%d Bank=%d RDWR=%s RAS=%d "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) "CAS=%d, CE Err=0x%x (%s))", branch >> 1, bank,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) rdwr ? "Write" : "Read", ras, cas, ce_errors,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) specific);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) /* Call the helper to output message */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1, 0, 0, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) channel >> 1, channel % 2, rank,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) rdwr ? "Write error" : "Read error",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) if (!misc_messages)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) misc_errors = allErrors & (FERR_NF_NON_RETRY | FERR_NF_NORTH_CRC |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) FERR_NF_SPD_PROTOCOL | FERR_NF_DIMM_SPARE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) if (misc_errors) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) switch (misc_errors) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) case FERR_NF_M13ERR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) specific = "Non-Retry or Redundant Retry FBD Memory "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) "Alert or Redundant Fast Reset Timeout";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) case FERR_NF_M14ERR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) specific = "Non-Retry or Redundant Retry FBD "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) "Configuration Alert";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) case FERR_NF_M15ERR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) specific = "Non-Retry or Redundant Retry FBD "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) "Northbound CRC error on read data";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) case FERR_NF_M21ERR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) specific = "FBD Northbound CRC error on "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) "FBD Sync Status";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) case FERR_NF_M22ERR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) specific = "SPD protocol error";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) case FERR_NF_M27ERR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) specific = "DIMM-spare copy started";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) case FERR_NF_M28ERR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) specific = "DIMM-spare copy completed";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) branch = EXTRACT_FBDCHAN_INDX(info->ferr_nf_fbd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) /* Form out message */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) snprintf(msg, sizeof(msg),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) "Err=%#x (%s)", misc_errors, specific);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) /* Call the helper to output message */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1, 0, 0, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) branch >> 1, -1, -1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) "Misc error", msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) * i5000_process_error_info Process the error info that is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) * in the 'info' structure, previously retrieved from hardware
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) static void i5000_process_error_info(struct mem_ctl_info *mci,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) struct i5000_error_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) int handle_errors)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) /* First handle any fatal errors that occurred */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) i5000_process_fatal_error_info(mci, info, handle_errors);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) /* now handle any non-fatal errors that occurred */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) i5000_process_nonfatal_error_info(mci, info, handle_errors);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) * i5000_clear_error Retrieve any error from the hardware
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) * but do NOT process that error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) * Used for 'clearing' out of previous errors
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) * Called by the Core module.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) static void i5000_clear_error(struct mem_ctl_info *mci)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) struct i5000_error_info info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) i5000_get_error_info(mci, &info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) * i5000_check_error Retrieve and process errors reported by the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) * hardware. Called by the Core module.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) static void i5000_check_error(struct mem_ctl_info *mci)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) struct i5000_error_info info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) edac_dbg(4, "MC%d\n", mci->mc_idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) i5000_get_error_info(mci, &info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) i5000_process_error_info(mci, &info, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) * i5000_get_devices Find and perform 'get' operation on the MCH's
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) * device/functions we want to reference for this driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) * Need to 'get' device 16 func 1 and func 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) static int i5000_get_devices(struct mem_ctl_info *mci, int dev_idx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) //const struct i5000_dev_info *i5000_dev = &i5000_devs[dev_idx];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) struct i5000_pvt *pvt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) struct pci_dev *pdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) pvt = mci->pvt_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) /* Attempt to 'get' the MCH register we want */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) pdev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) while (1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) PCI_DEVICE_ID_INTEL_I5000_DEV16, pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) /* End of list, leave */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) if (pdev == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) i5000_printk(KERN_ERR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) "'system address,Process Bus' "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) "device not found:"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) "vendor 0x%x device 0x%x FUNC 1 "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) "(broken BIOS?)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) PCI_VENDOR_ID_INTEL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) PCI_DEVICE_ID_INTEL_I5000_DEV16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) /* Scan for device 16 func 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) if (PCI_FUNC(pdev->devfn) == 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) pvt->branchmap_werrors = pdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) /* Attempt to 'get' the MCH register we want */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) pdev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) while (1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) PCI_DEVICE_ID_INTEL_I5000_DEV16, pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) if (pdev == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) i5000_printk(KERN_ERR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) "MC: 'branchmap,control,errors' "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) "device not found:"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) "vendor 0x%x device 0x%x Func 2 "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) "(broken BIOS?)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) PCI_VENDOR_ID_INTEL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) PCI_DEVICE_ID_INTEL_I5000_DEV16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) pci_dev_put(pvt->branchmap_werrors);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) /* Scan for device 16 func 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) if (PCI_FUNC(pdev->devfn) == 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) pvt->fsb_error_regs = pdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) edac_dbg(1, "System Address, processor bus- PCI Bus ID: %s %x:%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) pci_name(pvt->system_address),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) pvt->system_address->vendor, pvt->system_address->device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) edac_dbg(1, "Branchmap, control and errors - PCI Bus ID: %s %x:%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) pci_name(pvt->branchmap_werrors),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) pvt->branchmap_werrors->vendor,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) pvt->branchmap_werrors->device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) edac_dbg(1, "FSB Error Regs - PCI Bus ID: %s %x:%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) pci_name(pvt->fsb_error_regs),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) pvt->fsb_error_regs->vendor, pvt->fsb_error_regs->device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) pdev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) PCI_DEVICE_ID_I5000_BRANCH_0, pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) if (pdev == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) i5000_printk(KERN_ERR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) "MC: 'BRANCH 0' device not found:"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) "vendor 0x%x device 0x%x Func 0 (broken BIOS?)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_I5000_BRANCH_0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) pci_dev_put(pvt->branchmap_werrors);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) pci_dev_put(pvt->fsb_error_regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) pvt->branch_0 = pdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) /* If this device claims to have more than 2 channels then
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) * fetch Branch 1's information
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) if (pvt->maxch >= CHANNELS_PER_BRANCH) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) pdev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) PCI_DEVICE_ID_I5000_BRANCH_1, pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) if (pdev == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) i5000_printk(KERN_ERR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) "MC: 'BRANCH 1' device not found:"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) "vendor 0x%x device 0x%x Func 0 "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) "(broken BIOS?)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) PCI_VENDOR_ID_INTEL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) PCI_DEVICE_ID_I5000_BRANCH_1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) pci_dev_put(pvt->branchmap_werrors);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) pci_dev_put(pvt->fsb_error_regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) pci_dev_put(pvt->branch_0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) pvt->branch_1 = pdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) * i5000_put_devices 'put' all the devices that we have
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) * reserved via 'get'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) static void i5000_put_devices(struct mem_ctl_info *mci)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) struct i5000_pvt *pvt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) pvt = mci->pvt_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) pci_dev_put(pvt->branchmap_werrors); /* FUNC 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) pci_dev_put(pvt->fsb_error_regs); /* FUNC 2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) pci_dev_put(pvt->branch_0); /* DEV 21 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) /* Only if more than 2 channels do we release the second branch */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) if (pvt->maxch >= CHANNELS_PER_BRANCH)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) pci_dev_put(pvt->branch_1); /* DEV 22 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) * determine_amb_resent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) * the information is contained in NUM_MTRS different registers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) * determineing which of the NUM_MTRS requires knowing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) * which channel is in question
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) * 2 branches, each with 2 channels
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) * b0_ambpresent0 for channel '0'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) * b0_ambpresent1 for channel '1'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) * b1_ambpresent0 for channel '2'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) * b1_ambpresent1 for channel '3'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) static int determine_amb_present_reg(struct i5000_pvt *pvt, int channel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) int amb_present;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) if (channel < CHANNELS_PER_BRANCH) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) if (channel & 0x1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) amb_present = pvt->b0_ambpresent1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) amb_present = pvt->b0_ambpresent0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) if (channel & 0x1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) amb_present = pvt->b1_ambpresent1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) amb_present = pvt->b1_ambpresent0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) return amb_present;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) * determine_mtr(pvt, csrow, channel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) * return the proper MTR register as determine by the csrow and channel desired
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) static int determine_mtr(struct i5000_pvt *pvt, int slot, int channel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) int mtr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) if (channel < CHANNELS_PER_BRANCH)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) mtr = pvt->b0_mtr[slot];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) mtr = pvt->b1_mtr[slot];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) return mtr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) static void decode_mtr(int slot_row, u16 mtr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) int ans;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) ans = MTR_DIMMS_PRESENT(mtr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) edac_dbg(2, "\tMTR%d=0x%x: DIMMs are %sPresent\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) slot_row, mtr, ans ? "" : "NOT ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) if (!ans)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) edac_dbg(2, "\t\tWIDTH: x%d\n", MTR_DRAM_WIDTH(mtr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) edac_dbg(2, "\t\tNUMBANK: %d bank(s)\n", MTR_DRAM_BANKS(mtr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) edac_dbg(2, "\t\tNUMRANK: %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) MTR_DIMM_RANK(mtr) ? "double" : "single");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) edac_dbg(2, "\t\tNUMROW: %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) MTR_DIMM_ROWS(mtr) == 0 ? "8,192 - 13 rows" :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) MTR_DIMM_ROWS(mtr) == 1 ? "16,384 - 14 rows" :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) MTR_DIMM_ROWS(mtr) == 2 ? "32,768 - 15 rows" :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) "reserved");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) edac_dbg(2, "\t\tNUMCOL: %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) MTR_DIMM_COLS(mtr) == 0 ? "1,024 - 10 columns" :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) MTR_DIMM_COLS(mtr) == 1 ? "2,048 - 11 columns" :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) MTR_DIMM_COLS(mtr) == 2 ? "4,096 - 12 columns" :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) "reserved");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) static void handle_channel(struct i5000_pvt *pvt, int slot, int channel,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) struct i5000_dimm_info *dinfo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) int mtr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) int amb_present_reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) int addrBits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) mtr = determine_mtr(pvt, slot, channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) if (MTR_DIMMS_PRESENT(mtr)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) amb_present_reg = determine_amb_present_reg(pvt, channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) /* Determine if there is a DIMM present in this DIMM slot */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) if (amb_present_reg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) dinfo->dual_rank = MTR_DIMM_RANK(mtr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) /* Start with the number of bits for a Bank
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) * on the DRAM */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) addrBits = MTR_DRAM_BANKS_ADDR_BITS(mtr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) /* Add the number of ROW bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) addrBits += MTR_DIMM_ROWS_ADDR_BITS(mtr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) /* add the number of COLUMN bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) addrBits += MTR_DIMM_COLS_ADDR_BITS(mtr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) /* Dual-rank memories have twice the size */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) if (dinfo->dual_rank)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) addrBits++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) addrBits += 6; /* add 64 bits per DIMM */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) addrBits -= 20; /* divide by 2^^20 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) addrBits -= 3; /* 8 bits per bytes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) dinfo->megabytes = 1 << addrBits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) * calculate_dimm_size
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) * also will output a DIMM matrix map, if debug is enabled, for viewing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) * how the DIMMs are populated
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) static void calculate_dimm_size(struct i5000_pvt *pvt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) struct i5000_dimm_info *dinfo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) int slot, channel, branch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) char *p, *mem_buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) int space, n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) /* ================= Generate some debug output ================= */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) space = PAGE_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) mem_buffer = p = kmalloc(space, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) if (p == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) i5000_printk(KERN_ERR, "MC: %s:%s() kmalloc() failed\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) __FILE__, __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) /* Scan all the actual slots
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) * and calculate the information for each DIMM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) * Start with the highest slot first, to display it first
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) * and work toward the 0th slot
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) for (slot = pvt->maxdimmperch - 1; slot >= 0; slot--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) /* on an odd slot, first output a 'boundary' marker,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) * then reset the message buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) if (slot & 0x1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) n = snprintf(p, space, "--------------------------"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) "--------------------------------");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) p += n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) space -= n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) edac_dbg(2, "%s\n", mem_buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) p = mem_buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) space = PAGE_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) n = snprintf(p, space, "slot %2d ", slot);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) p += n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) space -= n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) for (channel = 0; channel < pvt->maxch; channel++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) dinfo = &pvt->dimm_info[slot][channel];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) handle_channel(pvt, slot, channel, dinfo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) if (dinfo->megabytes)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) n = snprintf(p, space, "%4d MB %dR| ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) dinfo->megabytes, dinfo->dual_rank + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) n = snprintf(p, space, "%4d MB | ", 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) p += n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) space -= n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) p += n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) space -= n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) edac_dbg(2, "%s\n", mem_buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) p = mem_buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) space = PAGE_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) /* Output the last bottom 'boundary' marker */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) n = snprintf(p, space, "--------------------------"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) "--------------------------------");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) p += n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) space -= n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) edac_dbg(2, "%s\n", mem_buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) p = mem_buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) space = PAGE_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) /* now output the 'channel' labels */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) n = snprintf(p, space, " ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) p += n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) space -= n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) for (channel = 0; channel < pvt->maxch; channel++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) n = snprintf(p, space, "channel %d | ", channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) p += n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) space -= n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) edac_dbg(2, "%s\n", mem_buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) p = mem_buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) space = PAGE_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) n = snprintf(p, space, " ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) p += n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) for (branch = 0; branch < MAX_BRANCHES; branch++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) n = snprintf(p, space, " branch %d | ", branch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) p += n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) space -= n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) /* output the last message and free buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) edac_dbg(2, "%s\n", mem_buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) kfree(mem_buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) * i5000_get_mc_regs read in the necessary registers and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) * cache locally
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) * Fills in the private data members
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) static void i5000_get_mc_regs(struct mem_ctl_info *mci)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) struct i5000_pvt *pvt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) u32 actual_tolm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) u16 limit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) int slot_row;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) int way0, way1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) pvt = mci->pvt_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) pci_read_config_dword(pvt->system_address, AMBASE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) &pvt->u.ambase_bottom);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) pci_read_config_dword(pvt->system_address, AMBASE + sizeof(u32),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) &pvt->u.ambase_top);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) edac_dbg(2, "AMBASE= 0x%lx MAXCH= %d MAX-DIMM-Per-CH= %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) (long unsigned int)pvt->ambase, pvt->maxch, pvt->maxdimmperch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) /* Get the Branch Map regs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) pci_read_config_word(pvt->branchmap_werrors, TOLM, &pvt->tolm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) pvt->tolm >>= 12;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) edac_dbg(2, "TOLM (number of 256M regions) =%u (0x%x)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) pvt->tolm, pvt->tolm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) actual_tolm = pvt->tolm << 28;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) edac_dbg(2, "Actual TOLM byte addr=%u (0x%x)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) actual_tolm, actual_tolm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) pci_read_config_word(pvt->branchmap_werrors, MIR0, &pvt->mir0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) pci_read_config_word(pvt->branchmap_werrors, MIR1, &pvt->mir1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) pci_read_config_word(pvt->branchmap_werrors, MIR2, &pvt->mir2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) /* Get the MIR[0-2] regs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) limit = (pvt->mir0 >> 4) & 0x0FFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) way0 = pvt->mir0 & 0x1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) way1 = pvt->mir0 & 0x2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) edac_dbg(2, "MIR0: limit= 0x%x WAY1= %u WAY0= %x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) limit, way1, way0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) limit = (pvt->mir1 >> 4) & 0x0FFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) way0 = pvt->mir1 & 0x1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) way1 = pvt->mir1 & 0x2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) edac_dbg(2, "MIR1: limit= 0x%x WAY1= %u WAY0= %x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) limit, way1, way0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) limit = (pvt->mir2 >> 4) & 0x0FFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) way0 = pvt->mir2 & 0x1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) way1 = pvt->mir2 & 0x2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) edac_dbg(2, "MIR2: limit= 0x%x WAY1= %u WAY0= %x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) limit, way1, way0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) /* Get the MTR[0-3] regs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) for (slot_row = 0; slot_row < NUM_MTRS; slot_row++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) int where = MTR0 + (slot_row * sizeof(u32));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) pci_read_config_word(pvt->branch_0, where,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) &pvt->b0_mtr[slot_row]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) edac_dbg(2, "MTR%d where=0x%x B0 value=0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) slot_row, where, pvt->b0_mtr[slot_row]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) if (pvt->maxch >= CHANNELS_PER_BRANCH) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) pci_read_config_word(pvt->branch_1, where,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) &pvt->b1_mtr[slot_row]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) edac_dbg(2, "MTR%d where=0x%x B1 value=0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) slot_row, where, pvt->b1_mtr[slot_row]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) pvt->b1_mtr[slot_row] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) /* Read and dump branch 0's MTRs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) edac_dbg(2, "Memory Technology Registers:\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) edac_dbg(2, " Branch 0:\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) for (slot_row = 0; slot_row < NUM_MTRS; slot_row++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) decode_mtr(slot_row, pvt->b0_mtr[slot_row]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) pci_read_config_word(pvt->branch_0, AMB_PRESENT_0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) &pvt->b0_ambpresent0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) edac_dbg(2, "\t\tAMB-Branch 0-present0 0x%x:\n", pvt->b0_ambpresent0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) pci_read_config_word(pvt->branch_0, AMB_PRESENT_1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) &pvt->b0_ambpresent1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) edac_dbg(2, "\t\tAMB-Branch 0-present1 0x%x:\n", pvt->b0_ambpresent1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) /* Only if we have 2 branchs (4 channels) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) if (pvt->maxch < CHANNELS_PER_BRANCH) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) pvt->b1_ambpresent0 = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) pvt->b1_ambpresent1 = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) /* Read and dump branch 1's MTRs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) edac_dbg(2, " Branch 1:\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) for (slot_row = 0; slot_row < NUM_MTRS; slot_row++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) decode_mtr(slot_row, pvt->b1_mtr[slot_row]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) pci_read_config_word(pvt->branch_1, AMB_PRESENT_0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) &pvt->b1_ambpresent0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) edac_dbg(2, "\t\tAMB-Branch 1-present0 0x%x:\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) pvt->b1_ambpresent0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) pci_read_config_word(pvt->branch_1, AMB_PRESENT_1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) &pvt->b1_ambpresent1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) edac_dbg(2, "\t\tAMB-Branch 1-present1 0x%x:\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) pvt->b1_ambpresent1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) /* Go and determine the size of each DIMM and place in an
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) * orderly matrix */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) calculate_dimm_size(pvt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) * i5000_init_csrows Initialize the 'csrows' table within
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) * the mci control structure with the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) * addressing of memory.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) * return:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) * 0 success
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) * 1 no actual memory found on this MC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) static int i5000_init_csrows(struct mem_ctl_info *mci)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) struct i5000_pvt *pvt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) struct dimm_info *dimm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) int empty;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) int max_csrows;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) int mtr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) int csrow_megs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) int channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) int slot;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) pvt = mci->pvt_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) max_csrows = pvt->maxdimmperch * 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) empty = 1; /* Assume NO memory */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) * FIXME: The memory layout used to map slot/channel into the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) * real memory architecture is weird: branch+slot are "csrows"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) * and channel is channel. That required an extra array (dimm_info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) * to map the dimms. A good cleanup would be to remove this array,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) * and do a loop here with branch, channel, slot
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) for (slot = 0; slot < max_csrows; slot++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) for (channel = 0; channel < pvt->maxch; channel++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) mtr = determine_mtr(pvt, slot, channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) if (!MTR_DIMMS_PRESENT(mtr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) dimm = edac_get_dimm(mci, channel / MAX_BRANCHES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) channel % MAX_BRANCHES, slot);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) csrow_megs = pvt->dimm_info[slot][channel].megabytes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) dimm->grain = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) /* Assume DDR2 for now */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) dimm->mtype = MEM_FB_DDR2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) /* ask what device type on this row */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) if (MTR_DRAM_WIDTH(mtr) == 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) dimm->dtype = DEV_X8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) dimm->dtype = DEV_X4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) dimm->edac_mode = EDAC_S8ECD8ED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) dimm->nr_pages = csrow_megs << 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) empty = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) return empty;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) * i5000_enable_error_reporting
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) * Turn on the memory reporting features of the hardware
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) static void i5000_enable_error_reporting(struct mem_ctl_info *mci)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) struct i5000_pvt *pvt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) u32 fbd_error_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) pvt = mci->pvt_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) /* Read the FBD Error Mask Register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) pci_read_config_dword(pvt->branchmap_werrors, EMASK_FBD,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) &fbd_error_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) /* Enable with a '0' */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) fbd_error_mask &= ~(ENABLE_EMASK_ALL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) pci_write_config_dword(pvt->branchmap_werrors, EMASK_FBD,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) fbd_error_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) * i5000_get_dimm_and_channel_counts(pdev, &nr_csrows, &num_channels)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) * ask the device how many channels are present and how many CSROWS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) * as well
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) static void i5000_get_dimm_and_channel_counts(struct pci_dev *pdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) int *num_dimms_per_channel,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) int *num_channels)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) u8 value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) /* Need to retrieve just how many channels and dimms per channel are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) * supported on this memory controller
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) pci_read_config_byte(pdev, MAXDIMMPERCH, &value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) *num_dimms_per_channel = (int)value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) pci_read_config_byte(pdev, MAXCH, &value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) *num_channels = (int)value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) * i5000_probe1 Probe for ONE instance of device to see if it is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) * present.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) * return:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) * 0 for FOUND a device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) * < 0 for error code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) static int i5000_probe1(struct pci_dev *pdev, int dev_idx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) struct mem_ctl_info *mci;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) struct edac_mc_layer layers[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) struct i5000_pvt *pvt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) int num_channels;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) int num_dimms_per_channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) edac_dbg(0, "MC: pdev bus %u dev=0x%x fn=0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) pdev->bus->number,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) /* We only are looking for func 0 of the set */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) if (PCI_FUNC(pdev->devfn) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) /* Ask the devices for the number of CSROWS and CHANNELS so
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) * that we can calculate the memory resources, etc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) * The Chipset will report what it can handle which will be greater
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) * or equal to what the motherboard manufacturer will implement.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) * As we don't have a motherboard identification routine to determine
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) * actual number of slots/dimms per channel, we thus utilize the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) * resource as specified by the chipset. Thus, we might have
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) * have more DIMMs per channel than actually on the mobo, but this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) * allows the driver to support up to the chipset max, without
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) * some fancy mobo determination.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) i5000_get_dimm_and_channel_counts(pdev, &num_dimms_per_channel,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) &num_channels);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) edac_dbg(0, "MC: Number of Branches=2 Channels= %d DIMMS= %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) num_channels, num_dimms_per_channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) /* allocate a new MC control structure */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) layers[0].type = EDAC_MC_LAYER_BRANCH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) layers[0].size = MAX_BRANCHES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) layers[0].is_virt_csrow = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) layers[1].type = EDAC_MC_LAYER_CHANNEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) layers[1].size = num_channels / MAX_BRANCHES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) layers[1].is_virt_csrow = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) layers[2].type = EDAC_MC_LAYER_SLOT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) layers[2].size = num_dimms_per_channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) layers[2].is_virt_csrow = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) mci = edac_mc_alloc(0, ARRAY_SIZE(layers), layers, sizeof(*pvt));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) if (mci == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) edac_dbg(0, "MC: mci = %p\n", mci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) mci->pdev = &pdev->dev; /* record ptr to the generic device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) pvt = mci->pvt_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) pvt->system_address = pdev; /* Record this device in our private */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) pvt->maxch = num_channels;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) pvt->maxdimmperch = num_dimms_per_channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) /* 'get' the pci devices we want to reserve for our use */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) if (i5000_get_devices(mci, dev_idx))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) goto fail0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) /* Time to get serious */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) i5000_get_mc_regs(mci); /* retrieve the hardware registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) mci->mc_idx = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) mci->mtype_cap = MEM_FLAG_FB_DDR2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) mci->edac_ctl_cap = EDAC_FLAG_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) mci->edac_cap = EDAC_FLAG_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) mci->mod_name = "i5000_edac.c";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) mci->ctl_name = i5000_devs[dev_idx].ctl_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) mci->dev_name = pci_name(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) mci->ctl_page_to_phys = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) /* Set the function pointer to an actual operation function */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) mci->edac_check = i5000_check_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) /* initialize the MC control structure 'csrows' table
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) * with the mapping and control information */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) if (i5000_init_csrows(mci)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) edac_dbg(0, "MC: Setting mci->edac_cap to EDAC_FLAG_NONE because i5000_init_csrows() returned nonzero value\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) mci->edac_cap = EDAC_FLAG_NONE; /* no csrows found */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) edac_dbg(1, "MC: Enable error reporting now\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) i5000_enable_error_reporting(mci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) /* add this new MC control structure to EDAC's list of MCs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) if (edac_mc_add_mc(mci)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) edac_dbg(0, "MC: failed edac_mc_add_mc()\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) /* FIXME: perhaps some code should go here that disables error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) * reporting if we just enabled it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) goto fail1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) i5000_clear_error(mci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) /* allocating generic PCI control info */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) i5000_pci = edac_pci_create_generic_ctl(&pdev->dev, EDAC_MOD_STR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) if (!i5000_pci) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) printk(KERN_WARNING
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) "%s(): Unable to create PCI control\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) printk(KERN_WARNING
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) "%s(): PCI error report via EDAC not setup\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) /* Error exit unwinding stack */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) fail1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469) i5000_put_devices(mci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) fail0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) edac_mc_free(mci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) * i5000_init_one constructor for one instance of device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479) * returns:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480) * negative on error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) * count (>= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483) static int i5000_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487) edac_dbg(0, "MC:\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489) /* wake up device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490) rc = pci_enable_device(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494) /* now probe and enable the device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495) return i5000_probe1(pdev, id->driver_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499) * i5000_remove_one destructor for one instance of device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) static void i5000_remove_one(struct pci_dev *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504) struct mem_ctl_info *mci;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506) edac_dbg(0, "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) if (i5000_pci)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) edac_pci_release_generic_ctl(i5000_pci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511) if ((mci = edac_mc_del_mc(&pdev->dev)) == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514) /* retrieve references to resources, and free those resources */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515) i5000_put_devices(mci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516) edac_mc_free(mci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520) * pci_device_id table for which devices we are looking for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522) * The "E500P" device is the first device supported.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524) static const struct pci_device_id i5000_pci_tbl[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525) {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_I5000_DEV16),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526) .driver_data = I5000P},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528) {0,} /* 0 terminated list. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531) MODULE_DEVICE_TABLE(pci, i5000_pci_tbl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534) * i5000_driver pci_driver structure for this module
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537) static struct pci_driver i5000_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538) .name = KBUILD_BASENAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539) .probe = i5000_init_one,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540) .remove = i5000_remove_one,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541) .id_table = i5000_pci_tbl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545) * i5000_init Module entry function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546) * Try to initialize this module for its devices
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548) static int __init i5000_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550) int pci_rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552) edac_dbg(2, "MC:\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554) /* Ensure that the OPSTATE is set correctly for POLL or NMI */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555) opstate_init();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557) pci_rc = pci_register_driver(&i5000_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559) return (pci_rc < 0) ? pci_rc : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563) * i5000_exit() Module exit function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564) * Unregister the driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566) static void __exit i5000_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568) edac_dbg(2, "MC:\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569) pci_unregister_driver(&i5000_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1571)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1572) module_init(i5000_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1573) module_exit(i5000_exit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1574)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1575) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1576) MODULE_AUTHOR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1577) ("Linux Networx (http://lnxi.com) Doug Thompson <norsk5@xmission.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1578) MODULE_DESCRIPTION("MC Driver for Intel I5000 memory controllers - "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1579) I5000_REVISION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1580)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1581) module_param(edac_op_state, int, 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1582) MODULE_PARM_DESC(edac_op_state, "EDAC Error Reporting state: 0=Poll,1=NMI");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1583) module_param(misc_messages, int, 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1584) MODULE_PARM_DESC(misc_messages, "Log miscellaneous non fatal messages");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1585)