^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) * Intel 82443BX/GX (440BX/GX chipset) Memory Controller EDAC kernel
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * module (C) 2006 Tim Small
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * This file may be distributed under the terms of the GNU General
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Public License.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Written by Tim Small <tim@buttersideup.com>, based on work by Linux
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Networx, Thayne Harbaugh, Dan Hollis <goemon at anime dot net> and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * others.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * 440GX fix by Jason Uhlenkott <juhlenko@akamai.com>.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * Written with reference to 82443BX Host Bridge Datasheet:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * http://download.intel.com/design/chipsets/datashts/29063301.pdf
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * references to this document given in [].
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * This module doesn't support the 440LX, but it may be possible to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * make it do so (the 440LX's register definitions are different, but
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * not completely so - I haven't studied them in enough detail to know
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * how easy this would be).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <linux/pci.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <linux/pci_ids.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include <linux/edac.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #include "edac_module.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #define EDAC_MOD_STR "i82443bxgx_edac"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) /* The 82443BX supports SDRAM, or EDO (EDO for mobile only), "Memory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) * Size: 8 MB to 512 MB (1GB with Registered DIMMs) with eight memory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) * rows" "The 82443BX supports multiple-bit error detection and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) * single-bit error correction when ECC mode is enabled and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) * single/multi-bit error detection when correction is disabled.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) * During writes to the DRAM, the 82443BX generates ECC for the data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) * on a QWord basis. Partial QWord writes require a read-modify-write
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) * cycle when ECC is enabled."
^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) /* "Additionally, the 82443BX ensures that the data is corrected in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) * main memory so that accumulation of errors is prevented. Another
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) * error within the same QWord would result in a double-bit error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) * which is unrecoverable. This is known as hardware scrubbing since
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) * it requires no software intervention to correct the data in memory."
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) /* [Also see page 100 (section 4.3), "DRAM Interface"]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) * [Also see page 112 (section 4.6.1.4), ECC]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) #define I82443BXGX_NR_CSROWS 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #define I82443BXGX_NR_CHANS 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) #define I82443BXGX_NR_DIMMS 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) /* 82443 PCI Device 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) #define I82443BXGX_NBXCFG 0x50 /* 32bit register starting at this PCI
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) * config space offset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) #define I82443BXGX_NBXCFG_OFFSET_NON_ECCROW 24 /* Array of bits, zero if
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) * row is non-ECC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) #define I82443BXGX_NBXCFG_OFFSET_DRAM_FREQ 12 /* 2 bits,00=100MHz,10=66 MHz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) #define I82443BXGX_NBXCFG_OFFSET_DRAM_INTEGRITY 7 /* 2 bits: */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) #define I82443BXGX_NBXCFG_INTEGRITY_NONE 0x0 /* 00 = Non-ECC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) #define I82443BXGX_NBXCFG_INTEGRITY_EC 0x1 /* 01 = EC (only) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) #define I82443BXGX_NBXCFG_INTEGRITY_ECC 0x2 /* 10 = ECC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) #define I82443BXGX_NBXCFG_INTEGRITY_SCRUB 0x3 /* 11 = ECC + HW Scrub */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) #define I82443BXGX_NBXCFG_OFFSET_ECC_DIAG_ENABLE 6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) /* 82443 PCI Device 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) #define I82443BXGX_EAP 0x80 /* 32bit register starting at this PCI
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) * config space offset, Error Address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) * Pointer Register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) #define I82443BXGX_EAP_OFFSET_EAP 12 /* High 20 bits of error address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) #define I82443BXGX_EAP_OFFSET_MBE BIT(1) /* Err at EAP was multi-bit (W1TC) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) #define I82443BXGX_EAP_OFFSET_SBE BIT(0) /* Err at EAP was single-bit (W1TC) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) #define I82443BXGX_ERRCMD 0x90 /* 8bit register starting at this PCI
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) * config space offset. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) #define I82443BXGX_ERRCMD_OFFSET_SERR_ON_MBE BIT(1) /* 1 = enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) #define I82443BXGX_ERRCMD_OFFSET_SERR_ON_SBE BIT(0) /* 1 = enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) #define I82443BXGX_ERRSTS 0x91 /* 16bit register starting at this PCI
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) * config space offset. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) #define I82443BXGX_ERRSTS_OFFSET_MBFRE 5 /* 3 bits - first err row multibit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) #define I82443BXGX_ERRSTS_OFFSET_MEF BIT(4) /* 1 = MBE occurred */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) #define I82443BXGX_ERRSTS_OFFSET_SBFRE 1 /* 3 bits - first err row singlebit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) #define I82443BXGX_ERRSTS_OFFSET_SEF BIT(0) /* 1 = SBE occurred */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) #define I82443BXGX_DRAMC 0x57 /* 8bit register starting at this PCI
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) * config space offset. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) #define I82443BXGX_DRAMC_OFFSET_DT 3 /* 2 bits, DRAM Type */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) #define I82443BXGX_DRAMC_DRAM_IS_EDO 0 /* 00 = EDO */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) #define I82443BXGX_DRAMC_DRAM_IS_SDRAM 1 /* 01 = SDRAM */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) #define I82443BXGX_DRAMC_DRAM_IS_RSDRAM 2 /* 10 = Registered SDRAM */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) #define I82443BXGX_DRB 0x60 /* 8x 8bit registers starting at this PCI
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) * config space offset. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) /* FIXME - don't poll when ECC disabled? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) struct i82443bxgx_edacmc_error_info {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) u32 eap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) static struct edac_pci_ctl_info *i82443bxgx_pci;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) static struct pci_dev *mci_pdev; /* init dev: in case that AGP code has
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) * already registered driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) static int i82443bxgx_registered = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) static void i82443bxgx_edacmc_get_error_info(struct mem_ctl_info *mci,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) struct i82443bxgx_edacmc_error_info
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) struct pci_dev *pdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) pdev = to_pci_dev(mci->pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) pci_read_config_dword(pdev, I82443BXGX_EAP, &info->eap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) if (info->eap & I82443BXGX_EAP_OFFSET_SBE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) /* Clear error to allow next error to be reported [p.61] */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) pci_write_bits32(pdev, I82443BXGX_EAP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) I82443BXGX_EAP_OFFSET_SBE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) I82443BXGX_EAP_OFFSET_SBE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) if (info->eap & I82443BXGX_EAP_OFFSET_MBE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) /* Clear error to allow next error to be reported [p.61] */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) pci_write_bits32(pdev, I82443BXGX_EAP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) I82443BXGX_EAP_OFFSET_MBE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) I82443BXGX_EAP_OFFSET_MBE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) static int i82443bxgx_edacmc_process_error_info(struct mem_ctl_info *mci,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) struct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) i82443bxgx_edacmc_error_info
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) *info, int handle_errors)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) int error_found = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) u32 eapaddr, page, pageoffset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) /* bits 30:12 hold the 4kb block in which the error occurred
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) * [p.61] */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) eapaddr = (info->eap & 0xfffff000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) page = eapaddr >> PAGE_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) pageoffset = eapaddr - (page << PAGE_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) if (info->eap & I82443BXGX_EAP_OFFSET_SBE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) error_found = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) if (handle_errors)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) page, pageoffset, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) edac_mc_find_csrow_by_page(mci, page),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 0, -1, mci->ctl_name, "");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) if (info->eap & I82443BXGX_EAP_OFFSET_MBE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) error_found = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) if (handle_errors)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) page, pageoffset, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) edac_mc_find_csrow_by_page(mci, page),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 0, -1, mci->ctl_name, "");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) return error_found;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) static void i82443bxgx_edacmc_check(struct mem_ctl_info *mci)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) struct i82443bxgx_edacmc_error_info info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) edac_dbg(1, "MC%d\n", mci->mc_idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) i82443bxgx_edacmc_get_error_info(mci, &info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) i82443bxgx_edacmc_process_error_info(mci, &info, 1);
^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) static void i82443bxgx_init_csrows(struct mem_ctl_info *mci,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) struct pci_dev *pdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) enum edac_type edac_mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) enum mem_type mtype)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) struct csrow_info *csrow;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) struct dimm_info *dimm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) int index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) u8 drbar, dramc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) u32 row_base, row_high_limit, row_high_limit_last;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) pci_read_config_byte(pdev, I82443BXGX_DRAMC, &dramc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) row_high_limit_last = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) for (index = 0; index < mci->nr_csrows; index++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) csrow = mci->csrows[index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) dimm = csrow->channels[0]->dimm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) pci_read_config_byte(pdev, I82443BXGX_DRB + index, &drbar);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) edac_dbg(1, "MC%d: Row=%d DRB = %#0x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) mci->mc_idx, index, drbar);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) row_high_limit = ((u32) drbar << 23);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) /* find the DRAM Chip Select Base address and mask */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) edac_dbg(1, "MC%d: Row=%d, Boundary Address=%#0x, Last = %#0x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) mci->mc_idx, index, row_high_limit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) row_high_limit_last);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) /* 440GX goes to 2GB, represented with a DRB of 0. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) if (row_high_limit_last && !row_high_limit)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) row_high_limit = 1UL << 31;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) /* This row is empty [p.49] */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) if (row_high_limit == row_high_limit_last)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) row_base = row_high_limit_last;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) csrow->first_page = row_base >> PAGE_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) csrow->last_page = (row_high_limit >> PAGE_SHIFT) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) dimm->nr_pages = csrow->last_page - csrow->first_page + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) /* EAP reports in 4kilobyte granularity [61] */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) dimm->grain = 1 << 12;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) dimm->mtype = mtype;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) /* I don't think 440BX can tell you device type? FIXME? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) dimm->dtype = DEV_UNKNOWN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) /* Mode is global to all rows on 440BX */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) dimm->edac_mode = edac_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) row_high_limit_last = row_high_limit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) static int i82443bxgx_edacmc_probe1(struct pci_dev *pdev, int dev_idx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) struct mem_ctl_info *mci;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) struct edac_mc_layer layers[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) u8 dramc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) u32 nbxcfg, ecc_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) enum mem_type mtype;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) enum edac_type edac_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) edac_dbg(0, "MC:\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) /* Something is really hosed if PCI config space reads from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) * the MC aren't working.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) if (pci_read_config_dword(pdev, I82443BXGX_NBXCFG, &nbxcfg))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) layers[0].type = EDAC_MC_LAYER_CHIP_SELECT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) layers[0].size = I82443BXGX_NR_CSROWS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) layers[0].is_virt_csrow = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) layers[1].type = EDAC_MC_LAYER_CHANNEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) layers[1].size = I82443BXGX_NR_CHANS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) layers[1].is_virt_csrow = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) mci = edac_mc_alloc(0, ARRAY_SIZE(layers), layers, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) if (mci == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) edac_dbg(0, "MC: mci = %p\n", mci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) mci->pdev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) mci->mtype_cap = MEM_FLAG_EDO | MEM_FLAG_SDR | MEM_FLAG_RDR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_EC | EDAC_FLAG_SECDED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) pci_read_config_byte(pdev, I82443BXGX_DRAMC, &dramc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) switch ((dramc >> I82443BXGX_DRAMC_OFFSET_DT) & (BIT(0) | BIT(1))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) case I82443BXGX_DRAMC_DRAM_IS_EDO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) mtype = MEM_EDO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) case I82443BXGX_DRAMC_DRAM_IS_SDRAM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) mtype = MEM_SDR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) case I82443BXGX_DRAMC_DRAM_IS_RSDRAM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) mtype = MEM_RDR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) edac_dbg(0, "Unknown/reserved DRAM type value in DRAMC register!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) mtype = -MEM_UNKNOWN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) if ((mtype == MEM_SDR) || (mtype == MEM_RDR))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) mci->edac_cap = mci->edac_ctl_cap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) mci->edac_cap = EDAC_FLAG_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) mci->scrub_cap = SCRUB_FLAG_HW_SRC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) pci_read_config_dword(pdev, I82443BXGX_NBXCFG, &nbxcfg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) ecc_mode = ((nbxcfg >> I82443BXGX_NBXCFG_OFFSET_DRAM_INTEGRITY) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) (BIT(0) | BIT(1)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) mci->scrub_mode = (ecc_mode == I82443BXGX_NBXCFG_INTEGRITY_SCRUB)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) ? SCRUB_HW_SRC : SCRUB_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) switch (ecc_mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) case I82443BXGX_NBXCFG_INTEGRITY_NONE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) edac_mode = EDAC_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) case I82443BXGX_NBXCFG_INTEGRITY_EC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) edac_mode = EDAC_EC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) case I82443BXGX_NBXCFG_INTEGRITY_ECC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) case I82443BXGX_NBXCFG_INTEGRITY_SCRUB:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) edac_mode = EDAC_SECDED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) edac_dbg(0, "Unknown/reserved ECC state in NBXCFG register!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) edac_mode = EDAC_UNKNOWN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) i82443bxgx_init_csrows(mci, pdev, edac_mode, mtype);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) /* Many BIOSes don't clear error flags on boot, so do this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) * here, or we get "phantom" errors occurring at module-load
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) * time. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) pci_write_bits32(pdev, I82443BXGX_EAP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) (I82443BXGX_EAP_OFFSET_SBE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) I82443BXGX_EAP_OFFSET_MBE),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) (I82443BXGX_EAP_OFFSET_SBE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) I82443BXGX_EAP_OFFSET_MBE));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) mci->mod_name = EDAC_MOD_STR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) mci->ctl_name = "I82443BXGX";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) mci->dev_name = pci_name(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) mci->edac_check = i82443bxgx_edacmc_check;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) mci->ctl_page_to_phys = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) if (edac_mc_add_mc(mci)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) edac_dbg(3, "failed edac_mc_add_mc()\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) /* allocating generic PCI control info */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) i82443bxgx_pci = edac_pci_create_generic_ctl(&pdev->dev, EDAC_MOD_STR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) if (!i82443bxgx_pci) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) printk(KERN_WARNING
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) "%s(): Unable to create PCI control\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) printk(KERN_WARNING
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) "%s(): PCI error report via EDAC not setup\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) __func__);
^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) edac_dbg(3, "MC: success\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) edac_mc_free(mci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) /* returns count (>= 0), or negative on error */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) static int i82443bxgx_edacmc_init_one(struct pci_dev *pdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) const struct pci_device_id *ent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) edac_dbg(0, "MC:\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) /* don't need to call pci_enable_device() */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) rc = i82443bxgx_edacmc_probe1(pdev, ent->driver_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) if (mci_pdev == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) mci_pdev = pci_dev_get(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) static void i82443bxgx_edacmc_remove_one(struct pci_dev *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) struct mem_ctl_info *mci;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) edac_dbg(0, "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) if (i82443bxgx_pci)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) edac_pci_release_generic_ctl(i82443bxgx_pci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) if ((mci = edac_mc_del_mc(&pdev->dev)) == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) edac_mc_free(mci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) static const struct pci_device_id i82443bxgx_pci_tbl[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443BX_0)},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443BX_2)},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443GX_0)},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443GX_2)},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) {0,} /* 0 terminated list. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) MODULE_DEVICE_TABLE(pci, i82443bxgx_pci_tbl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) static struct pci_driver i82443bxgx_edacmc_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) .name = EDAC_MOD_STR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) .probe = i82443bxgx_edacmc_init_one,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) .remove = i82443bxgx_edacmc_remove_one,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) .id_table = i82443bxgx_pci_tbl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) static int __init i82443bxgx_edacmc_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) int pci_rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) /* Ensure that the OPSTATE is set correctly for POLL or NMI */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) opstate_init();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) pci_rc = pci_register_driver(&i82443bxgx_edacmc_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) if (pci_rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) goto fail0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) if (mci_pdev == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) const struct pci_device_id *id = &i82443bxgx_pci_tbl[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) int i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) i82443bxgx_registered = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) while (mci_pdev == NULL && id->vendor != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) mci_pdev = pci_get_device(id->vendor,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) id->device, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) i++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) id = &i82443bxgx_pci_tbl[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) if (!mci_pdev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) edac_dbg(0, "i82443bxgx pci_get_device fail\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) pci_rc = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) goto fail1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) pci_rc = i82443bxgx_edacmc_init_one(mci_pdev, i82443bxgx_pci_tbl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) if (pci_rc < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) edac_dbg(0, "i82443bxgx init fail\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) pci_rc = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) goto fail1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) fail1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) pci_unregister_driver(&i82443bxgx_edacmc_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) fail0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) pci_dev_put(mci_pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) return pci_rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) static void __exit i82443bxgx_edacmc_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) pci_unregister_driver(&i82443bxgx_edacmc_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) if (!i82443bxgx_registered)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) i82443bxgx_edacmc_remove_one(mci_pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) pci_dev_put(mci_pdev);
^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) module_init(i82443bxgx_edacmc_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) module_exit(i82443bxgx_edacmc_exit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) MODULE_AUTHOR("Tim Small <tim@buttersideup.com> - WPAD");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) MODULE_DESCRIPTION("EDAC MC support for Intel 82443BX/GX memory controllers");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) module_param(edac_op_state, int, 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) MODULE_PARM_DESC(edac_op_state, "EDAC Error Reporting state: 0=Poll,1=NMI");