^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Intel 7300 class Memory Controllers kernel module (Clarksboro)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (c) 2010 by:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Mauro Carvalho Chehab
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Red Hat Inc. https://www.redhat.com
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * Intel 7300 Chipset Memory Controller Hub (MCH) - Datasheet
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * http://www.intel.com/Assets/PDF/datasheet/318082.pdf
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * TODO: The chipset allow checking for PCI Express errors also. Currently,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * the driver covers only memory error errors
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * This driver uses "csrows" EDAC attribute to represent DIMM slot#
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/pci.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/pci_ids.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/edac.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/mmzone.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include "edac_module.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) * Alter this version for the I7300 module when modifications are made
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define I7300_REVISION " Ver: 1.0.0"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #define EDAC_MOD_STR "i7300_edac"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #define i7300_printk(level, fmt, arg...) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) edac_printk(level, "i7300", fmt, ##arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #define i7300_mc_printk(mci, level, fmt, arg...) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) edac_mc_chipset_printk(mci, level, "i7300", fmt, ##arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) /***********************************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) * i7300 Limit constants Structs and static vars
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) ***********************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) * Memory topology is organized as:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) * Branch 0 - 2 channels: channels 0 and 1 (FDB0 PCI dev 21.0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) * Branch 1 - 2 channels: channels 2 and 3 (FDB1 PCI dev 22.0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) * Each channel can have to 8 DIMM sets (called as SLOTS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) * Slots should generally be filled in pairs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) * Except on Single Channel mode of operation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) * just slot 0/channel0 filled on this mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) * On normal operation mode, the two channels on a branch should be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) * filled together for the same SLOT#
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) * When in mirrored mode, Branch 1 replicate memory at Branch 0, so, the four
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) * channels on both branches should be filled
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) /* Limits for i7300 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) #define MAX_SLOTS 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) #define MAX_BRANCHES 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) #define MAX_CH_PER_BRANCH 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) #define MAX_CHANNELS (MAX_CH_PER_BRANCH * MAX_BRANCHES)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) #define MAX_MIR 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) #define to_channel(ch, branch) ((((branch)) << 1) | (ch))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) #define to_csrow(slot, ch, branch) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) (to_channel(ch, branch) | ((slot) << 2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) /* Device name and register DID (Device ID) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) struct i7300_dev_info {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) const char *ctl_name; /* name for this device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) u16 fsb_mapping_errors; /* DID for the branchmap,control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) /* Table of devices attributes supported by this driver */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) static const struct i7300_dev_info i7300_devs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) .ctl_name = "I7300",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) .fsb_mapping_errors = PCI_DEVICE_ID_INTEL_I7300_MCH_ERR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) struct i7300_dimm_info {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) int megabytes; /* size, 0 means not present */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) /* driver private data structure */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) struct i7300_pvt {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) struct pci_dev *pci_dev_16_0_fsb_ctlr; /* 16.0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) struct pci_dev *pci_dev_16_1_fsb_addr_map; /* 16.1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) struct pci_dev *pci_dev_16_2_fsb_err_regs; /* 16.2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) struct pci_dev *pci_dev_2x_0_fbd_branch[MAX_BRANCHES]; /* 21.0 and 22.0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) u16 tolm; /* top of low memory */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) u64 ambase; /* AMB BAR */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) u32 mc_settings; /* Report several settings */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) u32 mc_settings_a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) u16 mir[MAX_MIR]; /* Memory Interleave Reg*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) u16 mtr[MAX_SLOTS][MAX_BRANCHES]; /* Memory Technlogy Reg */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) u16 ambpresent[MAX_CHANNELS]; /* AMB present regs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) /* DIMM information matrix, allocating architecture maximums */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) struct i7300_dimm_info dimm_info[MAX_SLOTS][MAX_CHANNELS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) /* Temporary buffer for use when preparing error messages */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) char *tmp_prt_buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) /* FIXME: Why do we need to have this static? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) static struct edac_pci_ctl_info *i7300_pci;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) /***************************************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) * i7300 Register definitions for memory enumeration
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) ***************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) * Device 16,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) * Function 0: System Address (not documented)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) * Function 1: Memory Branch Map, Control, Errors Register
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) /* OFFSETS for Function 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) #define AMBASE 0x48 /* AMB Mem Mapped Reg Region Base */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) #define MAXCH 0x56 /* Max Channel Number */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) #define MAXDIMMPERCH 0x57 /* Max DIMM PER Channel Number */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) /* OFFSETS for Function 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) #define MC_SETTINGS 0x40
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) #define IS_MIRRORED(mc) ((mc) & (1 << 16))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) #define IS_ECC_ENABLED(mc) ((mc) & (1 << 5))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) #define IS_RETRY_ENABLED(mc) ((mc) & (1 << 31))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) #define IS_SCRBALGO_ENHANCED(mc) ((mc) & (1 << 8))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) #define MC_SETTINGS_A 0x58
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) #define IS_SINGLE_MODE(mca) ((mca) & (1 << 14))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) #define TOLM 0x6C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) #define MIR0 0x80
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) #define MIR1 0x84
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) #define MIR2 0x88
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) * Note: Other Intel EDAC drivers use AMBPRESENT to identify if the available
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) * memory. From datasheet item 7.3.1 (FB-DIMM technology & organization), it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) * seems that we cannot use this information directly for the same usage.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) * Each memory slot may have up to 2 AMB interfaces, one for income and another
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) * for outcome interface to the next slot.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) * For now, the driver just stores the AMB present registers, but rely only at
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) * the MTR info to detect memory.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) * Datasheet is also not clear about how to map each AMBPRESENT registers to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) * one of the 4 available channels.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) #define AMBPRESENT_0 0x64
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) #define AMBPRESENT_1 0x66
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) static const u16 mtr_regs[MAX_SLOTS] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 0x80, 0x84, 0x88, 0x8c,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 0x82, 0x86, 0x8a, 0x8e
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) * Defines to extract the vaious fields from the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) * MTRx - Memory Technology Registers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) #define MTR_DIMMS_PRESENT(mtr) ((mtr) & (1 << 8))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) #define MTR_DIMMS_ETHROTTLE(mtr) ((mtr) & (1 << 7))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) #define MTR_DRAM_WIDTH(mtr) (((mtr) & (1 << 6)) ? 8 : 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) #define MTR_DRAM_BANKS(mtr) (((mtr) & (1 << 5)) ? 8 : 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) #define MTR_DIMM_RANKS(mtr) (((mtr) & (1 << 4)) ? 1 : 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) #define MTR_DIMM_ROWS(mtr) (((mtr) >> 2) & 0x3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) #define MTR_DRAM_BANKS_ADDR_BITS 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) #define MTR_DIMM_ROWS_ADDR_BITS(mtr) (MTR_DIMM_ROWS(mtr) + 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) #define MTR_DIMM_COLS(mtr) ((mtr) & 0x3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) #define MTR_DIMM_COLS_ADDR_BITS(mtr) (MTR_DIMM_COLS(mtr) + 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) /************************************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) * i7300 Register definitions for error detection
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) ************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) * Device 16.1: FBD Error Registers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) #define FERR_FAT_FBD 0x98
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) static const char *ferr_fat_fbd_name[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) [22] = "Non-Redundant Fast Reset Timeout",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) [2] = ">Tmid Thermal event with intelligent throttling disabled",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) [1] = "Memory or FBD configuration CRC read error",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) [0] = "Memory Write error on non-redundant retry or "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) "FBD configuration Write error on retry",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) #define GET_FBD_FAT_IDX(fbderr) (((fbderr) >> 28) & 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) #define FERR_FAT_FBD_ERR_MASK ((1 << 0) | (1 << 1) | (1 << 2) | (1 << 22))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) #define FERR_NF_FBD 0xa0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) static const char *ferr_nf_fbd_name[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) [24] = "DIMM-Spare Copy Completed",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) [23] = "DIMM-Spare Copy Initiated",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) [22] = "Redundant Fast Reset Timeout",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) [21] = "Memory Write error on redundant retry",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) [18] = "SPD protocol Error",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) [17] = "FBD Northbound parity error on FBD Sync Status",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) [16] = "Correctable Patrol Data ECC",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) [15] = "Correctable Resilver- or Spare-Copy Data ECC",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) [14] = "Correctable Mirrored Demand Data ECC",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) [13] = "Correctable Non-Mirrored Demand Data ECC",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) [11] = "Memory or FBD configuration CRC read error",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) [10] = "FBD Configuration Write error on first attempt",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) [9] = "Memory Write error on first attempt",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) [8] = "Non-Aliased Uncorrectable Patrol Data ECC",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) [7] = "Non-Aliased Uncorrectable Resilver- or Spare-Copy Data ECC",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) [6] = "Non-Aliased Uncorrectable Mirrored Demand Data ECC",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) [5] = "Non-Aliased Uncorrectable Non-Mirrored Demand Data ECC",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) [4] = "Aliased Uncorrectable Patrol Data ECC",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) [3] = "Aliased Uncorrectable Resilver- or Spare-Copy Data ECC",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) [2] = "Aliased Uncorrectable Mirrored Demand Data ECC",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) [1] = "Aliased Uncorrectable Non-Mirrored Demand Data ECC",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) [0] = "Uncorrectable Data ECC on Replay",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) #define GET_FBD_NF_IDX(fbderr) (((fbderr) >> 28) & 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) #define FERR_NF_FBD_ERR_MASK ((1 << 24) | (1 << 23) | (1 << 22) | (1 << 21) |\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) (1 << 18) | (1 << 17) | (1 << 16) | (1 << 15) |\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) (1 << 14) | (1 << 13) | (1 << 11) | (1 << 10) |\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) (1 << 9) | (1 << 8) | (1 << 7) | (1 << 6) |\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) (1 << 5) | (1 << 4) | (1 << 3) | (1 << 2) |\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) (1 << 1) | (1 << 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) #define EMASK_FBD 0xa8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) #define EMASK_FBD_ERR_MASK ((1 << 27) | (1 << 26) | (1 << 25) | (1 << 24) |\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) (1 << 22) | (1 << 21) | (1 << 20) | (1 << 19) |\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) (1 << 18) | (1 << 17) | (1 << 16) | (1 << 14) |\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) (1 << 13) | (1 << 12) | (1 << 11) | (1 << 10) |\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) (1 << 9) | (1 << 8) | (1 << 7) | (1 << 6) |\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) (1 << 5) | (1 << 4) | (1 << 3) | (1 << 2) |\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) (1 << 1) | (1 << 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) * Device 16.2: Global Error Registers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) #define FERR_GLOBAL_HI 0x48
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) static const char *ferr_global_hi_name[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) [3] = "FSB 3 Fatal Error",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) [2] = "FSB 2 Fatal Error",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) [1] = "FSB 1 Fatal Error",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) [0] = "FSB 0 Fatal Error",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) #define ferr_global_hi_is_fatal(errno) 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) #define FERR_GLOBAL_LO 0x40
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) static const char *ferr_global_lo_name[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) [31] = "Internal MCH Fatal Error",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) [30] = "Intel QuickData Technology Device Fatal Error",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) [29] = "FSB1 Fatal Error",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) [28] = "FSB0 Fatal Error",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) [27] = "FBD Channel 3 Fatal Error",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) [26] = "FBD Channel 2 Fatal Error",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) [25] = "FBD Channel 1 Fatal Error",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) [24] = "FBD Channel 0 Fatal Error",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) [23] = "PCI Express Device 7Fatal Error",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) [22] = "PCI Express Device 6 Fatal Error",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) [21] = "PCI Express Device 5 Fatal Error",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) [20] = "PCI Express Device 4 Fatal Error",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) [19] = "PCI Express Device 3 Fatal Error",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) [18] = "PCI Express Device 2 Fatal Error",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) [17] = "PCI Express Device 1 Fatal Error",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) [16] = "ESI Fatal Error",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) [15] = "Internal MCH Non-Fatal Error",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) [14] = "Intel QuickData Technology Device Non Fatal Error",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) [13] = "FSB1 Non-Fatal Error",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) [12] = "FSB 0 Non-Fatal Error",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) [11] = "FBD Channel 3 Non-Fatal Error",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) [10] = "FBD Channel 2 Non-Fatal Error",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) [9] = "FBD Channel 1 Non-Fatal Error",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) [8] = "FBD Channel 0 Non-Fatal Error",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) [7] = "PCI Express Device 7 Non-Fatal Error",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) [6] = "PCI Express Device 6 Non-Fatal Error",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) [5] = "PCI Express Device 5 Non-Fatal Error",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) [4] = "PCI Express Device 4 Non-Fatal Error",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) [3] = "PCI Express Device 3 Non-Fatal Error",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) [2] = "PCI Express Device 2 Non-Fatal Error",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) [1] = "PCI Express Device 1 Non-Fatal Error",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) [0] = "ESI Non-Fatal Error",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) #define ferr_global_lo_is_fatal(errno) ((errno < 16) ? 0 : 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) #define NRECMEMA 0xbe
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) #define NRECMEMA_BANK(v) (((v) >> 12) & 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) #define NRECMEMA_RANK(v) (((v) >> 8) & 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) #define NRECMEMB 0xc0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) #define NRECMEMB_IS_WR(v) ((v) & (1 << 31))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) #define NRECMEMB_CAS(v) (((v) >> 16) & 0x1fff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) #define NRECMEMB_RAS(v) ((v) & 0xffff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) #define REDMEMA 0xdc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) #define REDMEMB 0x7c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) #define RECMEMA 0xe0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) #define RECMEMA_BANK(v) (((v) >> 12) & 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) #define RECMEMA_RANK(v) (((v) >> 8) & 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) #define RECMEMB 0xe4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) #define RECMEMB_IS_WR(v) ((v) & (1 << 31))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) #define RECMEMB_CAS(v) (((v) >> 16) & 0x1fff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) #define RECMEMB_RAS(v) ((v) & 0xffff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) /********************************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) * i7300 Functions related to error detection
^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) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) * get_err_from_table() - Gets the error message from a table
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) * @table: table name (array of char *)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) * @size: number of elements at the table
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) * @pos: position of the element to be returned
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) * This is a small routine that gets the pos-th element of a table. If the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) * element doesn't exist (or it is empty), it returns "reserved".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) * Instead of calling it directly, the better is to call via the macro
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) * GET_ERR_FROM_TABLE(), that automatically checks the table size via
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) * ARRAY_SIZE() macro
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) static const char *get_err_from_table(const char *table[], int size, int pos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) if (unlikely(pos >= size))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) return "Reserved";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) if (unlikely(!table[pos]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) return "Reserved";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) return table[pos];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) #define GET_ERR_FROM_TABLE(table, pos) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) get_err_from_table(table, ARRAY_SIZE(table), pos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) * i7300_process_error_global() - Retrieve the hardware error information from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) * the hardware global error registers and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) * sends it to dmesg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) * @mci: struct mem_ctl_info pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) static void i7300_process_error_global(struct mem_ctl_info *mci)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) struct i7300_pvt *pvt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) u32 errnum, error_reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) unsigned long errors;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) const char *specific;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) bool is_fatal;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) pvt = mci->pvt_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) /* read in the 1st FATAL error register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) pci_read_config_dword(pvt->pci_dev_16_2_fsb_err_regs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) FERR_GLOBAL_HI, &error_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) if (unlikely(error_reg)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) errors = error_reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) errnum = find_first_bit(&errors,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) ARRAY_SIZE(ferr_global_hi_name));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) specific = GET_ERR_FROM_TABLE(ferr_global_hi_name, errnum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) is_fatal = ferr_global_hi_is_fatal(errnum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) /* Clear the error bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) pci_write_config_dword(pvt->pci_dev_16_2_fsb_err_regs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) FERR_GLOBAL_HI, error_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) goto error_global;
^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) pci_read_config_dword(pvt->pci_dev_16_2_fsb_err_regs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) FERR_GLOBAL_LO, &error_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) if (unlikely(error_reg)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) errors = error_reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) errnum = find_first_bit(&errors,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) ARRAY_SIZE(ferr_global_lo_name));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) specific = GET_ERR_FROM_TABLE(ferr_global_lo_name, errnum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) is_fatal = ferr_global_lo_is_fatal(errnum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) /* Clear the error bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) pci_write_config_dword(pvt->pci_dev_16_2_fsb_err_regs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) FERR_GLOBAL_LO, error_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) goto error_global;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) error_global:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) i7300_mc_printk(mci, KERN_EMERG, "%s misc error: %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) is_fatal ? "Fatal" : "NOT fatal", specific);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) * i7300_process_fbd_error() - Retrieve the hardware error information from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) * the FBD error registers and sends it via
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) * EDAC error API calls
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) * @mci: struct mem_ctl_info pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) static void i7300_process_fbd_error(struct mem_ctl_info *mci)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) struct i7300_pvt *pvt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) u32 errnum, value, error_reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) u16 val16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) unsigned branch, channel, bank, rank, cas, ras;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) u32 syndrome;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) unsigned long errors;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) const char *specific;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) bool is_wr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) pvt = mci->pvt_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) /* read in the 1st FATAL error register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) pci_read_config_dword(pvt->pci_dev_16_1_fsb_addr_map,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) FERR_FAT_FBD, &error_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) if (unlikely(error_reg & FERR_FAT_FBD_ERR_MASK)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) errors = error_reg & FERR_FAT_FBD_ERR_MASK ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) errnum = find_first_bit(&errors,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) ARRAY_SIZE(ferr_fat_fbd_name));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) specific = GET_ERR_FROM_TABLE(ferr_fat_fbd_name, errnum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) branch = (GET_FBD_FAT_IDX(error_reg) == 2) ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) pci_read_config_word(pvt->pci_dev_16_1_fsb_addr_map,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) NRECMEMA, &val16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) bank = NRECMEMA_BANK(val16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) rank = NRECMEMA_RANK(val16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) pci_read_config_dword(pvt->pci_dev_16_1_fsb_addr_map,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) NRECMEMB, &value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) is_wr = NRECMEMB_IS_WR(value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) cas = NRECMEMB_CAS(value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) ras = NRECMEMB_RAS(value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) /* Clean the error register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) pci_write_config_dword(pvt->pci_dev_16_1_fsb_addr_map,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) FERR_FAT_FBD, error_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) snprintf(pvt->tmp_prt_buffer, PAGE_SIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) "Bank=%d RAS=%d CAS=%d Err=0x%lx (%s))",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) bank, ras, cas, errors, specific);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) edac_mc_handle_error(HW_EVENT_ERR_FATAL, mci, 1, 0, 0, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) branch, -1, rank,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) is_wr ? "Write error" : "Read error",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) pvt->tmp_prt_buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) /* read in the 1st NON-FATAL error register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) pci_read_config_dword(pvt->pci_dev_16_1_fsb_addr_map,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) FERR_NF_FBD, &error_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) if (unlikely(error_reg & FERR_NF_FBD_ERR_MASK)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) errors = error_reg & FERR_NF_FBD_ERR_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) errnum = find_first_bit(&errors,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) ARRAY_SIZE(ferr_nf_fbd_name));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) specific = GET_ERR_FROM_TABLE(ferr_nf_fbd_name, errnum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) branch = (GET_FBD_NF_IDX(error_reg) == 2) ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) pci_read_config_dword(pvt->pci_dev_16_1_fsb_addr_map,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) REDMEMA, &syndrome);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) pci_read_config_word(pvt->pci_dev_16_1_fsb_addr_map,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) RECMEMA, &val16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) bank = RECMEMA_BANK(val16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) rank = RECMEMA_RANK(val16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) pci_read_config_dword(pvt->pci_dev_16_1_fsb_addr_map,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) RECMEMB, &value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) is_wr = RECMEMB_IS_WR(value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) cas = RECMEMB_CAS(value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) ras = RECMEMB_RAS(value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) pci_read_config_dword(pvt->pci_dev_16_1_fsb_addr_map,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) REDMEMB, &value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) channel = (branch << 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) /* Second channel ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) channel += !!(value & BIT(17));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) /* Clear the error bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) pci_write_config_dword(pvt->pci_dev_16_1_fsb_addr_map,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) FERR_NF_FBD, error_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) /* Form out message */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) snprintf(pvt->tmp_prt_buffer, PAGE_SIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) "DRAM-Bank=%d RAS=%d CAS=%d, Err=0x%lx (%s))",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) bank, ras, cas, errors, specific);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1, 0, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) syndrome,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) branch >> 1, channel % 2, rank,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) is_wr ? "Write error" : "Read error",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) pvt->tmp_prt_buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) }
^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) * i7300_check_error() - Calls the error checking subroutines
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) * @mci: struct mem_ctl_info pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) static void i7300_check_error(struct mem_ctl_info *mci)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) i7300_process_error_global(mci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) i7300_process_fbd_error(mci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) * i7300_clear_error() - Clears the error registers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) * @mci: struct mem_ctl_info pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) static void i7300_clear_error(struct mem_ctl_info *mci)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) struct i7300_pvt *pvt = mci->pvt_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) u32 value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) * All error values are RWC - we need to read and write 1 to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) * bit that we want to cleanup
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) /* Clear global error registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) pci_read_config_dword(pvt->pci_dev_16_2_fsb_err_regs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) FERR_GLOBAL_HI, &value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) pci_write_config_dword(pvt->pci_dev_16_2_fsb_err_regs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) FERR_GLOBAL_HI, value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) pci_read_config_dword(pvt->pci_dev_16_2_fsb_err_regs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) FERR_GLOBAL_LO, &value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) pci_write_config_dword(pvt->pci_dev_16_2_fsb_err_regs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) FERR_GLOBAL_LO, value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) /* Clear FBD error registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) pci_read_config_dword(pvt->pci_dev_16_1_fsb_addr_map,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) FERR_FAT_FBD, &value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) pci_write_config_dword(pvt->pci_dev_16_1_fsb_addr_map,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) FERR_FAT_FBD, value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) pci_read_config_dword(pvt->pci_dev_16_1_fsb_addr_map,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) FERR_NF_FBD, &value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) pci_write_config_dword(pvt->pci_dev_16_1_fsb_addr_map,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) FERR_NF_FBD, value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) * i7300_enable_error_reporting() - Enable the memory reporting logic at the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) * hardware
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) * @mci: struct mem_ctl_info pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) static void i7300_enable_error_reporting(struct mem_ctl_info *mci)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) struct i7300_pvt *pvt = mci->pvt_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) u32 fbd_error_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) /* Read the FBD Error Mask Register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) pci_read_config_dword(pvt->pci_dev_16_1_fsb_addr_map,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) EMASK_FBD, &fbd_error_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) /* Enable with a '0' */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) fbd_error_mask &= ~(EMASK_FBD_ERR_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) pci_write_config_dword(pvt->pci_dev_16_1_fsb_addr_map,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) EMASK_FBD, fbd_error_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) /************************************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) * i7300 Functions related to memory enumberation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) ************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) * decode_mtr() - Decodes the MTR descriptor, filling the edac structs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) * @pvt: pointer to the private data struct used by i7300 driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) * @slot: DIMM slot (0 to 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) * @ch: Channel number within the branch (0 or 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) * @branch: Branch number (0 or 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) * @dinfo: Pointer to DIMM info where dimm size is stored
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) * @dimm: Pointer to the struct dimm_info that corresponds to that element
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) static int decode_mtr(struct i7300_pvt *pvt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) int slot, int ch, int branch,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) struct i7300_dimm_info *dinfo,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) struct dimm_info *dimm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) int mtr, ans, addrBits, channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) channel = to_channel(ch, branch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) mtr = pvt->mtr[slot][branch];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) ans = MTR_DIMMS_PRESENT(mtr) ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) edac_dbg(2, "\tMTR%d CH%d: DIMMs are %sPresent (mtr)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) slot, channel, ans ? "" : "NOT ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) /* Determine if there is a DIMM present in this DIMM slot */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) if (!ans)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) /* Start with the number of bits for a Bank
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) * on the DRAM */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) addrBits = MTR_DRAM_BANKS_ADDR_BITS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) /* Add thenumber of ROW bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) addrBits += MTR_DIMM_ROWS_ADDR_BITS(mtr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) /* add the number of COLUMN bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) addrBits += MTR_DIMM_COLS_ADDR_BITS(mtr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) /* add the number of RANK bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) addrBits += MTR_DIMM_RANKS(mtr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) addrBits += 6; /* add 64 bits per DIMM */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) addrBits -= 20; /* divide by 2^^20 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) addrBits -= 3; /* 8 bits per bytes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) dinfo->megabytes = 1 << addrBits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) edac_dbg(2, "\t\tWIDTH: x%d\n", MTR_DRAM_WIDTH(mtr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) edac_dbg(2, "\t\tELECTRICAL THROTTLING is %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) MTR_DIMMS_ETHROTTLE(mtr) ? "enabled" : "disabled");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) edac_dbg(2, "\t\tNUMBANK: %d bank(s)\n", MTR_DRAM_BANKS(mtr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) edac_dbg(2, "\t\tNUMRANK: %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) MTR_DIMM_RANKS(mtr) ? "double" : "single");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) edac_dbg(2, "\t\tNUMROW: %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) MTR_DIMM_ROWS(mtr) == 0 ? "8,192 - 13 rows" :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) MTR_DIMM_ROWS(mtr) == 1 ? "16,384 - 14 rows" :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) MTR_DIMM_ROWS(mtr) == 2 ? "32,768 - 15 rows" :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) "65,536 - 16 rows");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) edac_dbg(2, "\t\tNUMCOL: %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) MTR_DIMM_COLS(mtr) == 0 ? "1,024 - 10 columns" :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) MTR_DIMM_COLS(mtr) == 1 ? "2,048 - 11 columns" :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) MTR_DIMM_COLS(mtr) == 2 ? "4,096 - 12 columns" :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) "reserved");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) edac_dbg(2, "\t\tSIZE: %d MB\n", dinfo->megabytes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) * The type of error detection actually depends of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) * mode of operation. When it is just one single memory chip, at
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) * socket 0, channel 0, it uses 8-byte-over-32-byte SECDED+ code.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) * In normal or mirrored mode, it uses Lockstep mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) * with the possibility of using an extended algorithm for x8 memories
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) * See datasheet Sections 7.3.6 to 7.3.8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) dimm->nr_pages = MiB_TO_PAGES(dinfo->megabytes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) dimm->grain = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) dimm->mtype = MEM_FB_DDR2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) if (IS_SINGLE_MODE(pvt->mc_settings_a)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) dimm->edac_mode = EDAC_SECDED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) edac_dbg(2, "\t\tECC code is 8-byte-over-32-byte SECDED+ code\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) edac_dbg(2, "\t\tECC code is on Lockstep mode\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) if (MTR_DRAM_WIDTH(mtr) == 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) dimm->edac_mode = EDAC_S8ECD8ED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) dimm->edac_mode = EDAC_S4ECD4ED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) /* ask what device type on this row */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) if (MTR_DRAM_WIDTH(mtr) == 8) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) edac_dbg(2, "\t\tScrub algorithm for x8 is on %s mode\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) IS_SCRBALGO_ENHANCED(pvt->mc_settings) ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) "enhanced" : "normal");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) dimm->dtype = DEV_X8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) dimm->dtype = DEV_X4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) return mtr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) * print_dimm_size() - Prints dump of the memory organization
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) * @pvt: pointer to the private data struct used by i7300 driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) * Useful for debug. If debug is disabled, this routine do nothing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) static void print_dimm_size(struct i7300_pvt *pvt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) #ifdef CONFIG_EDAC_DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) struct i7300_dimm_info *dinfo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) char *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) int space, n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) int channel, slot;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) space = PAGE_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) p = pvt->tmp_prt_buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) n = snprintf(p, space, " ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) p += n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) space -= n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) for (channel = 0; channel < MAX_CHANNELS; channel++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) n = snprintf(p, space, "channel %d | ", channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) p += n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) space -= n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) edac_dbg(2, "%s\n", pvt->tmp_prt_buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) p = pvt->tmp_prt_buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) space = PAGE_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) n = snprintf(p, space, "-------------------------------"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) "------------------------------");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) p += n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) space -= n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) edac_dbg(2, "%s\n", pvt->tmp_prt_buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) p = pvt->tmp_prt_buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) space = PAGE_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) for (slot = 0; slot < MAX_SLOTS; slot++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) n = snprintf(p, space, "csrow/SLOT %d ", slot);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) p += n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) space -= n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) for (channel = 0; channel < MAX_CHANNELS; channel++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) dinfo = &pvt->dimm_info[slot][channel];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) n = snprintf(p, space, "%4d MB | ", dinfo->megabytes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) p += n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) space -= n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) edac_dbg(2, "%s\n", pvt->tmp_prt_buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) p = pvt->tmp_prt_buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) space = PAGE_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) n = snprintf(p, space, "-------------------------------"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) "------------------------------");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) p += n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) space -= n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) edac_dbg(2, "%s\n", pvt->tmp_prt_buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) p = pvt->tmp_prt_buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) space = PAGE_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) * i7300_init_csrows() - Initialize the 'csrows' table within
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) * the mci control structure with the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) * addressing of memory.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) * @mci: struct mem_ctl_info pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) static int i7300_init_csrows(struct mem_ctl_info *mci)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) struct i7300_pvt *pvt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) struct i7300_dimm_info *dinfo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) int rc = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) int mtr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) int ch, branch, slot, channel, max_channel, max_branch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) struct dimm_info *dimm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) pvt = mci->pvt_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) edac_dbg(2, "Memory Technology Registers:\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) if (IS_SINGLE_MODE(pvt->mc_settings_a)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) max_branch = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) max_channel = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) max_branch = MAX_BRANCHES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) max_channel = MAX_CH_PER_BRANCH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) /* Get the AMB present registers for the four channels */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) for (branch = 0; branch < max_branch; branch++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) /* Read and dump branch 0's MTRs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) channel = to_channel(0, branch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) pci_read_config_word(pvt->pci_dev_2x_0_fbd_branch[branch],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) AMBPRESENT_0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) &pvt->ambpresent[channel]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) edac_dbg(2, "\t\tAMB-present CH%d = 0x%x:\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) channel, pvt->ambpresent[channel]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) if (max_channel == 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) channel = to_channel(1, branch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) pci_read_config_word(pvt->pci_dev_2x_0_fbd_branch[branch],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) AMBPRESENT_1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) &pvt->ambpresent[channel]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) edac_dbg(2, "\t\tAMB-present CH%d = 0x%x:\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) channel, pvt->ambpresent[channel]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) /* Get the set of MTR[0-7] regs by each branch */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) for (slot = 0; slot < MAX_SLOTS; slot++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) int where = mtr_regs[slot];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) for (branch = 0; branch < max_branch; branch++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) pci_read_config_word(pvt->pci_dev_2x_0_fbd_branch[branch],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) where,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) &pvt->mtr[slot][branch]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) for (ch = 0; ch < max_channel; ch++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) int channel = to_channel(ch, branch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) dimm = edac_get_dimm(mci, branch, ch, slot);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) dinfo = &pvt->dimm_info[slot][channel];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) mtr = decode_mtr(pvt, slot, ch, branch,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) dinfo, dimm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) /* if no DIMMS on this row, continue */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) if (!MTR_DIMMS_PRESENT(mtr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) rc = 0;
^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) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) * decode_mir() - Decodes Memory Interleave Register (MIR) info
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) * @mir_no: number of the MIR register to decode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) * @mir: array with the MIR data cached on the driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) static void decode_mir(int mir_no, u16 mir[MAX_MIR])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) if (mir[mir_no] & 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) edac_dbg(2, "MIR%d: limit= 0x%x Branch(es) that participate: %s %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) mir_no,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) (mir[mir_no] >> 4) & 0xfff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) (mir[mir_no] & 1) ? "B0" : "",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) (mir[mir_no] & 2) ? "B1" : "");
^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) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) * i7300_get_mc_regs() - Get the contents of the MC enumeration registers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) * @mci: struct mem_ctl_info pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) * Data read is cached internally for its usage when needed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) static int i7300_get_mc_regs(struct mem_ctl_info *mci)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) struct i7300_pvt *pvt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) u32 actual_tolm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) int i, rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) pvt = mci->pvt_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) pci_read_config_dword(pvt->pci_dev_16_0_fsb_ctlr, AMBASE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) (u32 *) &pvt->ambase);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) edac_dbg(2, "AMBASE= 0x%lx\n", (long unsigned int)pvt->ambase);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) /* Get the Branch Map regs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) pci_read_config_word(pvt->pci_dev_16_1_fsb_addr_map, TOLM, &pvt->tolm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) pvt->tolm >>= 12;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) edac_dbg(2, "TOLM (number of 256M regions) =%u (0x%x)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) pvt->tolm, pvt->tolm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) actual_tolm = (u32) ((1000l * pvt->tolm) >> (30 - 28));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) edac_dbg(2, "Actual TOLM byte addr=%u.%03u GB (0x%x)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) actual_tolm/1000, actual_tolm % 1000, pvt->tolm << 28);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) /* Get memory controller settings */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) pci_read_config_dword(pvt->pci_dev_16_1_fsb_addr_map, MC_SETTINGS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) &pvt->mc_settings);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) pci_read_config_dword(pvt->pci_dev_16_1_fsb_addr_map, MC_SETTINGS_A,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) &pvt->mc_settings_a);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) if (IS_SINGLE_MODE(pvt->mc_settings_a))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) edac_dbg(0, "Memory controller operating on single mode\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) edac_dbg(0, "Memory controller operating on %smirrored mode\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) IS_MIRRORED(pvt->mc_settings) ? "" : "non-");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) edac_dbg(0, "Error detection is %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) IS_ECC_ENABLED(pvt->mc_settings) ? "enabled" : "disabled");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) edac_dbg(0, "Retry is %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) IS_RETRY_ENABLED(pvt->mc_settings) ? "enabled" : "disabled");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) /* Get Memory Interleave Range registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) pci_read_config_word(pvt->pci_dev_16_1_fsb_addr_map, MIR0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) &pvt->mir[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) pci_read_config_word(pvt->pci_dev_16_1_fsb_addr_map, MIR1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) &pvt->mir[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) pci_read_config_word(pvt->pci_dev_16_1_fsb_addr_map, MIR2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) &pvt->mir[2]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) /* Decode the MIR regs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) for (i = 0; i < MAX_MIR; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) decode_mir(i, pvt->mir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) rc = i7300_init_csrows(mci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) /* Go and determine the size of each DIMM and place in an
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) * orderly matrix */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) print_dimm_size(pvt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) /*************************************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) * i7300 Functions related to device probe/release
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) *************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) * i7300_put_devices() - Release the PCI devices
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) * @mci: struct mem_ctl_info pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) static void i7300_put_devices(struct mem_ctl_info *mci)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) struct i7300_pvt *pvt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) int branch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) pvt = mci->pvt_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) /* Decrement usage count for devices */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) for (branch = 0; branch < MAX_CH_PER_BRANCH; branch++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) pci_dev_put(pvt->pci_dev_2x_0_fbd_branch[branch]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) pci_dev_put(pvt->pci_dev_16_2_fsb_err_regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) pci_dev_put(pvt->pci_dev_16_1_fsb_addr_map);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) * i7300_get_devices() - Find and perform 'get' operation on the MCH's
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) * device/functions we want to reference for this driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) * @mci: struct mem_ctl_info pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) * Access and prepare the several devices for usage:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) * I7300 devices used by this driver:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) * Device 16, functions 0,1 and 2: PCI_DEVICE_ID_INTEL_I7300_MCH_ERR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) * Device 21 function 0: PCI_DEVICE_ID_INTEL_I7300_MCH_FB0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) * Device 22 function 0: PCI_DEVICE_ID_INTEL_I7300_MCH_FB1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) static int i7300_get_devices(struct mem_ctl_info *mci)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) struct i7300_pvt *pvt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) struct pci_dev *pdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) pvt = mci->pvt_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) /* Attempt to 'get' the MCH register we want */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) pdev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) while ((pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) PCI_DEVICE_ID_INTEL_I7300_MCH_ERR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) pdev))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) /* Store device 16 funcs 1 and 2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) switch (PCI_FUNC(pdev->devfn)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) if (!pvt->pci_dev_16_1_fsb_addr_map)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) pvt->pci_dev_16_1_fsb_addr_map =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) pci_dev_get(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) if (!pvt->pci_dev_16_2_fsb_err_regs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) pvt->pci_dev_16_2_fsb_err_regs =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) pci_dev_get(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) if (!pvt->pci_dev_16_1_fsb_addr_map ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) !pvt->pci_dev_16_2_fsb_err_regs) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) /* At least one device was not found */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) i7300_printk(KERN_ERR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) "'system address,Process Bus' device not found:"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) "vendor 0x%x device 0x%x ERR funcs (broken BIOS?)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) PCI_VENDOR_ID_INTEL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) PCI_DEVICE_ID_INTEL_I7300_MCH_ERR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) edac_dbg(1, "System Address, processor bus- PCI Bus ID: %s %x:%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) pci_name(pvt->pci_dev_16_0_fsb_ctlr),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) pvt->pci_dev_16_0_fsb_ctlr->vendor,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) pvt->pci_dev_16_0_fsb_ctlr->device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) edac_dbg(1, "Branchmap, control and errors - PCI Bus ID: %s %x:%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) pci_name(pvt->pci_dev_16_1_fsb_addr_map),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) pvt->pci_dev_16_1_fsb_addr_map->vendor,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) pvt->pci_dev_16_1_fsb_addr_map->device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) edac_dbg(1, "FSB Error Regs - PCI Bus ID: %s %x:%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) pci_name(pvt->pci_dev_16_2_fsb_err_regs),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) pvt->pci_dev_16_2_fsb_err_regs->vendor,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) pvt->pci_dev_16_2_fsb_err_regs->device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) pvt->pci_dev_2x_0_fbd_branch[0] = pci_get_device(PCI_VENDOR_ID_INTEL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) PCI_DEVICE_ID_INTEL_I7300_MCH_FB0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) if (!pvt->pci_dev_2x_0_fbd_branch[0]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) i7300_printk(KERN_ERR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) "MC: 'BRANCH 0' device not found:"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) "vendor 0x%x device 0x%x Func 0 (broken BIOS?)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_I7300_MCH_FB0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) pvt->pci_dev_2x_0_fbd_branch[1] = pci_get_device(PCI_VENDOR_ID_INTEL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) PCI_DEVICE_ID_INTEL_I7300_MCH_FB1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) if (!pvt->pci_dev_2x_0_fbd_branch[1]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) i7300_printk(KERN_ERR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) "MC: 'BRANCH 1' device not found:"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) "vendor 0x%x device 0x%x Func 0 "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) "(broken BIOS?)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) PCI_VENDOR_ID_INTEL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) PCI_DEVICE_ID_INTEL_I7300_MCH_FB1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) i7300_put_devices(mci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) * i7300_init_one() - Probe for one instance of the device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) * @pdev: struct pci_dev pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) * @id: struct pci_device_id pointer - currently unused
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) static int i7300_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) struct mem_ctl_info *mci;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) struct edac_mc_layer layers[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) struct i7300_pvt *pvt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) /* wake up device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) rc = pci_enable_device(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) if (rc == -EIO)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) edac_dbg(0, "MC: pdev bus %u dev=0x%x fn=0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) pdev->bus->number,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) /* We only are looking for func 0 of the set */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) if (PCI_FUNC(pdev->devfn) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) /* allocate a new MC control structure */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) layers[0].type = EDAC_MC_LAYER_BRANCH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) layers[0].size = MAX_BRANCHES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) layers[0].is_virt_csrow = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) layers[1].type = EDAC_MC_LAYER_CHANNEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) layers[1].size = MAX_CH_PER_BRANCH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) layers[1].is_virt_csrow = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) layers[2].type = EDAC_MC_LAYER_SLOT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) layers[2].size = MAX_SLOTS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) layers[2].is_virt_csrow = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) mci = edac_mc_alloc(0, ARRAY_SIZE(layers), layers, sizeof(*pvt));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) if (mci == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) edac_dbg(0, "MC: mci = %p\n", mci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) mci->pdev = &pdev->dev; /* record ptr to the generic device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) pvt = mci->pvt_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) pvt->pci_dev_16_0_fsb_ctlr = pdev; /* Record this device in our private */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) pvt->tmp_prt_buffer = kmalloc(PAGE_SIZE, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) if (!pvt->tmp_prt_buffer) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) edac_mc_free(mci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) /* 'get' the pci devices we want to reserve for our use */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) if (i7300_get_devices(mci))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) goto fail0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) mci->mc_idx = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) mci->mtype_cap = MEM_FLAG_FB_DDR2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) mci->edac_ctl_cap = EDAC_FLAG_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) mci->edac_cap = EDAC_FLAG_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) mci->mod_name = "i7300_edac.c";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) mci->ctl_name = i7300_devs[0].ctl_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) mci->dev_name = pci_name(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) mci->ctl_page_to_phys = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) /* Set the function pointer to an actual operation function */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) mci->edac_check = i7300_check_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) /* initialize the MC control structure 'csrows' table
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) * with the mapping and control information */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) if (i7300_get_mc_regs(mci)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) edac_dbg(0, "MC: Setting mci->edac_cap to EDAC_FLAG_NONE because i7300_init_csrows() returned nonzero value\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) mci->edac_cap = EDAC_FLAG_NONE; /* no csrows found */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) edac_dbg(1, "MC: Enable error reporting now\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) i7300_enable_error_reporting(mci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) /* add this new MC control structure to EDAC's list of MCs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) if (edac_mc_add_mc(mci)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) edac_dbg(0, "MC: failed edac_mc_add_mc()\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) /* FIXME: perhaps some code should go here that disables error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) * reporting if we just enabled it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) goto fail1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) i7300_clear_error(mci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) /* allocating generic PCI control info */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) i7300_pci = edac_pci_create_generic_ctl(&pdev->dev, EDAC_MOD_STR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) if (!i7300_pci) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) printk(KERN_WARNING
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) "%s(): Unable to create PCI control\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) printk(KERN_WARNING
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) "%s(): PCI error report via EDAC not setup\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) /* Error exit unwinding stack */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) fail1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) i7300_put_devices(mci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) fail0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) kfree(pvt->tmp_prt_buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) edac_mc_free(mci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) * i7300_remove_one() - Remove the driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) * @pdev: struct pci_dev pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) static void i7300_remove_one(struct pci_dev *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) struct mem_ctl_info *mci;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) char *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) edac_dbg(0, "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) if (i7300_pci)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) edac_pci_release_generic_ctl(i7300_pci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) mci = edac_mc_del_mc(&pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) if (!mci)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) tmp = ((struct i7300_pvt *)mci->pvt_info)->tmp_prt_buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) /* retrieve references to resources, and free those resources */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) i7300_put_devices(mci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) kfree(tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) edac_mc_free(mci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) * pci_device_id: table for which devices we are looking for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) * Has only 8086:360c PCI ID
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) static const struct pci_device_id i7300_pci_tbl[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_I7300_MCH_ERR)},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) {0,} /* 0 terminated list. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) MODULE_DEVICE_TABLE(pci, i7300_pci_tbl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) * i7300_driver: pci_driver structure for this module
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) static struct pci_driver i7300_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) .name = "i7300_edac",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) .probe = i7300_init_one,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) .remove = i7300_remove_one,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) .id_table = i7300_pci_tbl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) * i7300_init() - Registers the driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) static int __init i7300_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) int pci_rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) edac_dbg(2, "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) /* Ensure that the OPSTATE is set correctly for POLL or NMI */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) opstate_init();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) pci_rc = pci_register_driver(&i7300_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) return (pci_rc < 0) ? pci_rc : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) * i7300_init() - Unregisters the driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) static void __exit i7300_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) edac_dbg(2, "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) pci_unregister_driver(&i7300_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) module_init(i7300_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) module_exit(i7300_exit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) MODULE_AUTHOR("Mauro Carvalho Chehab");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) MODULE_AUTHOR("Red Hat Inc. (https://www.redhat.com)");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) MODULE_DESCRIPTION("MC Driver for Intel I7300 memory controllers - "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) I7300_REVISION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) module_param(edac_op_state, int, 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) MODULE_PARM_DESC(edac_op_state, "EDAC Error Reporting state: 0=Poll,1=NMI");