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