Blame view

drivers/edac/i82860_edac.c 9.17 KB
0d88a10e5   Alan Cox   [PATCH] EDAC: dri...
1
2
3
4
5
6
7
8
9
10
  /*
   * Intel 82860 Memory Controller kernel module
   * (C) 2005 Red Hat (http://www.redhat.com)
   * This file may be distributed under the terms of the
   * GNU General Public License.
   *
   * Written by Ben Woodard <woodard@redhat.com>
   * shamelessly copied from and based upon the edac_i82875 driver
   * by Thayne Harbaugh of Linux Networx. (http://lnxi.com)
   */
0d88a10e5   Alan Cox   [PATCH] EDAC: dri...
11
12
13
14
  #include <linux/module.h>
  #include <linux/init.h>
  #include <linux/pci.h>
  #include <linux/pci_ids.h>
c3c52bce6   Hitoshi Mitake   edac: fix module ...
15
  #include <linux/edac.h>
78d88e8a3   Mauro Carvalho Chehab   edac: rename edac...
16
  #include "edac_module.h"
0d88a10e5   Alan Cox   [PATCH] EDAC: dri...
17

152ba3942   Michal Marek   edac: Drop __DATE...
18
  #define  I82860_REVISION " Ver: 2.0.2"
929a40ec3   Doug Thompson   [PATCH] EDAC: fix...
19
  #define EDAC_MOD_STR	"i82860_edac"
37f04581a   Doug Thompson   [PATCH] EDAC: PCI...
20

537fba289   Dave Peterson   [PATCH] EDAC: pri...
21
  #define i82860_printk(level, fmt, arg...) \
e7ecd8910   Dave Peterson   [PATCH] EDAC: for...
22
  	edac_printk(level, "i82860", fmt, ##arg)
537fba289   Dave Peterson   [PATCH] EDAC: pri...
23
24
  
  #define i82860_mc_printk(mci, level, fmt, arg...) \
e7ecd8910   Dave Peterson   [PATCH] EDAC: for...
25
  	edac_mc_chipset_printk(mci, level, "i82860", fmt, ##arg)
537fba289   Dave Peterson   [PATCH] EDAC: pri...
26

0d88a10e5   Alan Cox   [PATCH] EDAC: dri...
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
  #ifndef PCI_DEVICE_ID_INTEL_82860_0
  #define PCI_DEVICE_ID_INTEL_82860_0	0x2531
  #endif				/* PCI_DEVICE_ID_INTEL_82860_0 */
  
  #define I82860_MCHCFG 0x50
  #define I82860_GBA 0x60
  #define I82860_GBA_MASK 0x7FF
  #define I82860_GBA_SHIFT 24
  #define I82860_ERRSTS 0xC8
  #define I82860_EAP 0xE4
  #define I82860_DERRCTL_STS 0xE2
  
  enum i82860_chips {
  	I82860 = 0,
  };
  
  struct i82860_dev_info {
  	const char *ctl_name;
  };
  
  struct i82860_error_info {
  	u16 errsts;
  	u32 eap;
  	u16 derrsyn;
  	u16 errsts2;
  };
  
  static const struct i82860_dev_info i82860_devs[] = {
  	[I82860] = {
052dfb45c   Douglas Thompson   drivers/edac: cle...
56
  		.ctl_name = "i82860"},
0d88a10e5   Alan Cox   [PATCH] EDAC: dri...
57
  };
f044091ca   Douglas Thompson   drivers/edac: rem...
58
  static struct pci_dev *mci_pdev;	/* init dev: in case that AGP code
e7ecd8910   Dave Peterson   [PATCH] EDAC: for...
59
60
  					 * has already registered driver
  					 */
456a2f955   Dave Jiang   drivers/edac: dri...
61
  static struct edac_pci_ctl_info *i82860_pci;
0d88a10e5   Alan Cox   [PATCH] EDAC: dri...
62

e7ecd8910   Dave Peterson   [PATCH] EDAC: for...
63
  static void i82860_get_error_info(struct mem_ctl_info *mci,
052dfb45c   Douglas Thompson   drivers/edac: cle...
64
  				struct i82860_error_info *info)
0d88a10e5   Alan Cox   [PATCH] EDAC: dri...
65
  {
37f04581a   Doug Thompson   [PATCH] EDAC: PCI...
66
  	struct pci_dev *pdev;
fd687502d   Mauro Carvalho Chehab   edac: Rename the ...
67
  	pdev = to_pci_dev(mci->pdev);
37f04581a   Doug Thompson   [PATCH] EDAC: PCI...
68

0d88a10e5   Alan Cox   [PATCH] EDAC: dri...
69
70
71
72
73
  	/*
  	 * This is a mess because there is no atomic way to read all the
  	 * registers at once and the registers can transition from CE being
  	 * overwritten by UE.
  	 */
37f04581a   Doug Thompson   [PATCH] EDAC: PCI...
74
75
76
77
  	pci_read_config_word(pdev, I82860_ERRSTS, &info->errsts);
  	pci_read_config_dword(pdev, I82860_EAP, &info->eap);
  	pci_read_config_word(pdev, I82860_DERRCTL_STS, &info->derrsyn);
  	pci_read_config_word(pdev, I82860_ERRSTS, &info->errsts2);
0d88a10e5   Alan Cox   [PATCH] EDAC: dri...
78

37f04581a   Doug Thompson   [PATCH] EDAC: PCI...
79
  	pci_write_bits16(pdev, I82860_ERRSTS, 0x0003, 0x0003);
0d88a10e5   Alan Cox   [PATCH] EDAC: dri...
80
81
82
83
84
85
86
87
  
  	/*
  	 * If the error is the same for both reads then the first set of reads
  	 * is valid.  If there is a change then there is a CE no info and the
  	 * second set of reads is valid and should be UE info.
  	 */
  	if (!(info->errsts2 & 0x0003))
  		return;
e7ecd8910   Dave Peterson   [PATCH] EDAC: for...
88

0d88a10e5   Alan Cox   [PATCH] EDAC: dri...
89
  	if ((info->errsts ^ info->errsts2) & 0x0003) {
37f04581a   Doug Thompson   [PATCH] EDAC: PCI...
90
  		pci_read_config_dword(pdev, I82860_EAP, &info->eap);
b4e8b3720   Dave Jiang   drivers/edac: Lin...
91
  		pci_read_config_word(pdev, I82860_DERRCTL_STS, &info->derrsyn);
0d88a10e5   Alan Cox   [PATCH] EDAC: dri...
92
93
  	}
  }
e7ecd8910   Dave Peterson   [PATCH] EDAC: for...
94
  static int i82860_process_error_info(struct mem_ctl_info *mci,
052dfb45c   Douglas Thompson   drivers/edac: cle...
95
96
  				struct i82860_error_info *info,
  				int handle_errors)
0d88a10e5   Alan Cox   [PATCH] EDAC: dri...
97
  {
84c3a6840   Mauro Carvalho Chehab   i82860_edac: conv...
98
  	struct dimm_info *dimm;
0d88a10e5   Alan Cox   [PATCH] EDAC: dri...
99
100
101
102
103
104
105
106
107
  	int row;
  
  	if (!(info->errsts2 & 0x0003))
  		return 0;
  
  	if (!handle_errors)
  		return 1;
  
  	if ((info->errsts ^ info->errsts2) & 0x0003) {
9eb07a7fb   Mauro Carvalho Chehab   edac: edac_mc_han...
108
  		edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, 0, 0, 0,
03f7eae80   Mauro Carvalho Chehab   edac: remove arch...
109
  				     -1, -1, -1, "UE overwrote CE", "");
0d88a10e5   Alan Cox   [PATCH] EDAC: dri...
110
111
112
113
114
  		info->errsts = info->errsts2;
  	}
  
  	info->eap >>= PAGE_SHIFT;
  	row = edac_mc_find_csrow_by_page(mci, info->eap);
de3910eb7   Mauro Carvalho Chehab   edac: change the ...
115
  	dimm = mci->csrows[row]->channels[0]->dimm;
0d88a10e5   Alan Cox   [PATCH] EDAC: dri...
116
117
  
  	if (info->errsts & 0x0002)
9eb07a7fb   Mauro Carvalho Chehab   edac: edac_mc_han...
118
  		edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1,
84c3a6840   Mauro Carvalho Chehab   i82860_edac: conv...
119
120
  				     info->eap, 0, 0,
  				     dimm->location[0], dimm->location[1], -1,
03f7eae80   Mauro Carvalho Chehab   edac: remove arch...
121
  				     "i82860 UE", "");
0d88a10e5   Alan Cox   [PATCH] EDAC: dri...
122
  	else
ab0543de6   Jason Baron   i82860_edac: Repo...
123
  		edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1,
84c3a6840   Mauro Carvalho Chehab   i82860_edac: conv...
124
125
  				     info->eap, 0, info->derrsyn,
  				     dimm->location[0], dimm->location[1], -1,
03f7eae80   Mauro Carvalho Chehab   edac: remove arch...
126
  				     "i82860 CE", "");
0d88a10e5   Alan Cox   [PATCH] EDAC: dri...
127
128
129
130
131
132
133
  
  	return 1;
  }
  
  static void i82860_check(struct mem_ctl_info *mci)
  {
  	struct i82860_error_info info;
956b9ba15   Joe Perches   edac: Convert deb...
134
135
  	edac_dbg(1, "MC%d
  ", mci->mc_idx);
0d88a10e5   Alan Cox   [PATCH] EDAC: dri...
136
137
138
  	i82860_get_error_info(mci, &info);
  	i82860_process_error_info(mci, &info, 1);
  }
131895251   Doug Thompson   [PATCH] EDAC: pro...
139
  static void i82860_init_csrows(struct mem_ctl_info *mci, struct pci_dev *pdev)
0d88a10e5   Alan Cox   [PATCH] EDAC: dri...
140
  {
0d88a10e5   Alan Cox   [PATCH] EDAC: dri...
141
  	unsigned long last_cumul_size;
b4e8b3720   Dave Jiang   drivers/edac: Lin...
142
  	u16 mchcfg_ddim;	/* DRAM Data Integrity Mode 0=none, 2=edac */
131895251   Doug Thompson   [PATCH] EDAC: pro...
143
144
145
  	u16 value;
  	u32 cumul_size;
  	struct csrow_info *csrow;
084a4fcce   Mauro Carvalho Chehab   edac: move dimm p...
146
  	struct dimm_info *dimm;
131895251   Doug Thompson   [PATCH] EDAC: pro...
147
148
149
150
151
152
153
154
155
156
157
158
  	int index;
  
  	pci_read_config_word(pdev, I82860_MCHCFG, &mchcfg_ddim);
  	mchcfg_ddim = mchcfg_ddim & 0x180;
  	last_cumul_size = 0;
  
  	/* The group row boundary (GRA) reg values are boundary address
  	 * for each DRAM row with a granularity of 16MB.  GRA regs are
  	 * cumulative; therefore GRA15 will contain the total memory contained
  	 * in all eight rows.
  	 */
  	for (index = 0; index < mci->nr_csrows; index++) {
de3910eb7   Mauro Carvalho Chehab   edac: change the ...
159
160
  		csrow = mci->csrows[index];
  		dimm = csrow->channels[0]->dimm;
084a4fcce   Mauro Carvalho Chehab   edac: move dimm p...
161

131895251   Doug Thompson   [PATCH] EDAC: pro...
162
163
  		pci_read_config_word(pdev, I82860_GBA + index * 2, &value);
  		cumul_size = (value & I82860_GBA_MASK) <<
052dfb45c   Douglas Thompson   drivers/edac: cle...
164
  			(I82860_GBA_SHIFT - PAGE_SHIFT);
956b9ba15   Joe Perches   edac: Convert deb...
165
166
  		edac_dbg(3, "(%d) cumul_size 0x%x
  ", index, cumul_size);
0d88a10e5   Alan Cox   [PATCH] EDAC: dri...
167

131895251   Doug Thompson   [PATCH] EDAC: pro...
168
169
170
171
172
  		if (cumul_size == last_cumul_size)
  			continue;	/* not populated */
  
  		csrow->first_page = last_cumul_size;
  		csrow->last_page = cumul_size - 1;
a895bf8b1   Mauro Carvalho Chehab   edac: move nr_pag...
173
  		dimm->nr_pages = cumul_size - last_cumul_size;
131895251   Doug Thompson   [PATCH] EDAC: pro...
174
  		last_cumul_size = cumul_size;
084a4fcce   Mauro Carvalho Chehab   edac: move dimm p...
175
176
177
178
  		dimm->grain = 1 << 12;	/* I82860_EAP has 4KiB reolution */
  		dimm->mtype = MEM_RMBS;
  		dimm->dtype = DEV_UNKNOWN;
  		dimm->edac_mode = mchcfg_ddim ? EDAC_SECDED : EDAC_NONE;
131895251   Doug Thompson   [PATCH] EDAC: pro...
179
180
181
182
183
184
  	}
  }
  
  static int i82860_probe1(struct pci_dev *pdev, int dev_idx)
  {
  	struct mem_ctl_info *mci;
84c3a6840   Mauro Carvalho Chehab   i82860_edac: conv...
185
  	struct edac_mc_layer layers[2];
131895251   Doug Thompson   [PATCH] EDAC: pro...
186
  	struct i82860_error_info discard;
0d88a10e5   Alan Cox   [PATCH] EDAC: dri...
187

84c3a6840   Mauro Carvalho Chehab   i82860_edac: conv...
188
189
190
191
192
193
194
195
196
  	/*
  	 * RDRAM has channels but these don't map onto the csrow abstraction.
  	 * According with the datasheet, there are 2 Rambus channels, supporting
  	 * up to 16 direct RDRAM devices.
  	 * The device groups from the GRA registers seem to map reasonably
  	 * well onto the notion of a chip select row.
  	 * There are 16 GRA registers and since the name is associated with
  	 * the channel and the GRA registers map to physical devices so we are
  	 * going to make 1 channel for group.
0d88a10e5   Alan Cox   [PATCH] EDAC: dri...
197
  	 */
84c3a6840   Mauro Carvalho Chehab   i82860_edac: conv...
198
199
200
201
202
203
  	layers[0].type = EDAC_MC_LAYER_CHANNEL;
  	layers[0].size = 2;
  	layers[0].is_virt_csrow = true;
  	layers[1].type = EDAC_MC_LAYER_SLOT;
  	layers[1].size = 8;
  	layers[1].is_virt_csrow = true;
ca0907b9e   Mauro Carvalho Chehab   edac: Remove the ...
204
  	mci = edac_mc_alloc(0, ARRAY_SIZE(layers), layers, 0);
0d88a10e5   Alan Cox   [PATCH] EDAC: dri...
205
206
  	if (!mci)
  		return -ENOMEM;
956b9ba15   Joe Perches   edac: Convert deb...
207
208
  	edac_dbg(3, "init mci
  ");
fd687502d   Mauro Carvalho Chehab   edac: Rename the ...
209
  	mci->pdev = &pdev->dev;
0d88a10e5   Alan Cox   [PATCH] EDAC: dri...
210
  	mci->mtype_cap = MEM_FLAG_DDR;
0d88a10e5   Alan Cox   [PATCH] EDAC: dri...
211
212
213
  	mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED;
  	/* I"m not sure about this but I think that all RDRAM is SECDED */
  	mci->edac_cap = EDAC_FLAG_SECDED;
680cbbbb0   Dave Peterson   [PATCH] EDAC: nam...
214
  	mci->mod_name = EDAC_MOD_STR;
37f04581a   Doug Thompson   [PATCH] EDAC: PCI...
215
  	mci->mod_ver = I82860_REVISION;
0d88a10e5   Alan Cox   [PATCH] EDAC: dri...
216
  	mci->ctl_name = i82860_devs[dev_idx].ctl_name;
c4192705f   Dave Jiang   drivers/edac: add...
217
  	mci->dev_name = pci_name(pdev);
0d88a10e5   Alan Cox   [PATCH] EDAC: dri...
218
219
  	mci->edac_check = i82860_check;
  	mci->ctl_page_to_phys = NULL;
131895251   Doug Thompson   [PATCH] EDAC: pro...
220
  	i82860_init_csrows(mci, pdev);
b4e8b3720   Dave Jiang   drivers/edac: Lin...
221
  	i82860_get_error_info(mci, &discard);	/* clear counters */
0d88a10e5   Alan Cox   [PATCH] EDAC: dri...
222

2d7bbb91c   Doug Thompson   [PATCH] EDAC: mc ...
223
224
225
  	/* Here we assume that we will never see multiple instances of this
  	 * type of memory controller.  The ID is therefore hardcoded to 0.
  	 */
b8f6f9755   Doug Thompson   drivers/edac: fix...
226
  	if (edac_mc_add_mc(mci)) {
956b9ba15   Joe Perches   edac: Convert deb...
227
228
  		edac_dbg(3, "failed edac_mc_add_mc()
  ");
131895251   Doug Thompson   [PATCH] EDAC: pro...
229
  		goto fail;
0d88a10e5   Alan Cox   [PATCH] EDAC: dri...
230
  	}
e7ecd8910   Dave Peterson   [PATCH] EDAC: for...
231

456a2f955   Dave Jiang   drivers/edac: dri...
232
233
234
235
236
237
238
239
240
241
242
243
  	/* allocating generic PCI control info */
  	i82860_pci = edac_pci_create_generic_ctl(&pdev->dev, EDAC_MOD_STR);
  	if (!i82860_pci) {
  		printk(KERN_WARNING
  			"%s(): Unable to create PCI control
  ",
  			__func__);
  		printk(KERN_WARNING
  			"%s(): PCI error report via EDAC not setup
  ",
  			__func__);
  	}
131895251   Doug Thompson   [PATCH] EDAC: pro...
244
  	/* get this far and it's successful */
956b9ba15   Joe Perches   edac: Convert deb...
245
246
  	edac_dbg(3, "success
  ");
131895251   Doug Thompson   [PATCH] EDAC: pro...
247
248
  
  	return 0;
052dfb45c   Douglas Thompson   drivers/edac: cle...
249
  fail:
131895251   Doug Thompson   [PATCH] EDAC: pro...
250
251
  	edac_mc_free(mci);
  	return -ENODEV;
0d88a10e5   Alan Cox   [PATCH] EDAC: dri...
252
253
254
  }
  
  /* returns count (>= 0), or negative on error */
9b3c6e85c   Greg Kroah-Hartman   Drivers: edac: re...
255
256
  static int i82860_init_one(struct pci_dev *pdev,
  			   const struct pci_device_id *ent)
0d88a10e5   Alan Cox   [PATCH] EDAC: dri...
257
258
  {
  	int rc;
956b9ba15   Joe Perches   edac: Convert deb...
259
260
  	edac_dbg(0, "
  ");
537fba289   Dave Peterson   [PATCH] EDAC: pri...
261
262
  	i82860_printk(KERN_INFO, "i82860 init one
  ");
e7ecd8910   Dave Peterson   [PATCH] EDAC: for...
263
264
  
  	if (pci_enable_device(pdev) < 0)
0d88a10e5   Alan Cox   [PATCH] EDAC: dri...
265
  		return -EIO;
e7ecd8910   Dave Peterson   [PATCH] EDAC: for...
266

0d88a10e5   Alan Cox   [PATCH] EDAC: dri...
267
  	rc = i82860_probe1(pdev, ent->driver_data);
e7ecd8910   Dave Peterson   [PATCH] EDAC: for...
268
269
  
  	if (rc == 0)
0d88a10e5   Alan Cox   [PATCH] EDAC: dri...
270
  		mci_pdev = pci_dev_get(pdev);
e7ecd8910   Dave Peterson   [PATCH] EDAC: for...
271

0d88a10e5   Alan Cox   [PATCH] EDAC: dri...
272
273
  	return rc;
  }
9b3c6e85c   Greg Kroah-Hartman   Drivers: edac: re...
274
  static void i82860_remove_one(struct pci_dev *pdev)
0d88a10e5   Alan Cox   [PATCH] EDAC: dri...
275
276
  {
  	struct mem_ctl_info *mci;
956b9ba15   Joe Perches   edac: Convert deb...
277
278
  	edac_dbg(0, "
  ");
0d88a10e5   Alan Cox   [PATCH] EDAC: dri...
279

456a2f955   Dave Jiang   drivers/edac: dri...
280
281
  	if (i82860_pci)
  		edac_pci_release_generic_ctl(i82860_pci);
37f04581a   Doug Thompson   [PATCH] EDAC: PCI...
282
  	if ((mci = edac_mc_del_mc(&pdev->dev)) == NULL)
18dbc337a   Dave Peterson   [PATCH] EDAC: pro...
283
284
285
  		return;
  
  	edac_mc_free(mci);
0d88a10e5   Alan Cox   [PATCH] EDAC: dri...
286
  }
ba935f409   Jingoo Han   EDAC: Remove DEFI...
287
  static const struct pci_device_id i82860_pci_tbl[] = {
e7ecd8910   Dave Peterson   [PATCH] EDAC: for...
288
  	{
b4e8b3720   Dave Jiang   drivers/edac: Lin...
289
290
  	 PCI_VEND_DEV(INTEL, 82860_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
  	 I82860},
e7ecd8910   Dave Peterson   [PATCH] EDAC: for...
291
  	{
b4e8b3720   Dave Jiang   drivers/edac: Lin...
292
293
  	 0,
  	 }			/* 0 terminated list. */
0d88a10e5   Alan Cox   [PATCH] EDAC: dri...
294
295
296
297
298
  };
  
  MODULE_DEVICE_TABLE(pci, i82860_pci_tbl);
  
  static struct pci_driver i82860_driver = {
680cbbbb0   Dave Peterson   [PATCH] EDAC: nam...
299
  	.name = EDAC_MOD_STR,
0d88a10e5   Alan Cox   [PATCH] EDAC: dri...
300
  	.probe = i82860_init_one,
9b3c6e85c   Greg Kroah-Hartman   Drivers: edac: re...
301
  	.remove = i82860_remove_one,
0d88a10e5   Alan Cox   [PATCH] EDAC: dri...
302
303
  	.id_table = i82860_pci_tbl,
  };
da9bb1d27   Alan Cox   [PATCH] EDAC: cor...
304
  static int __init i82860_init(void)
0d88a10e5   Alan Cox   [PATCH] EDAC: dri...
305
306
  {
  	int pci_rc;
956b9ba15   Joe Perches   edac: Convert deb...
307
308
  	edac_dbg(3, "
  ");
e7ecd8910   Dave Peterson   [PATCH] EDAC: for...
309

c3c52bce6   Hitoshi Mitake   edac: fix module ...
310
311
         /* Ensure that the OPSTATE is set correctly for POLL or NMI */
         opstate_init();
0d88a10e5   Alan Cox   [PATCH] EDAC: dri...
312
  	if ((pci_rc = pci_register_driver(&i82860_driver)) < 0)
e8a491b40   Dave Peterson   [PATCH] EDAC: i82...
313
  		goto fail0;
0d88a10e5   Alan Cox   [PATCH] EDAC: dri...
314
315
  
  	if (!mci_pdev) {
0d88a10e5   Alan Cox   [PATCH] EDAC: dri...
316
  		mci_pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
052dfb45c   Douglas Thompson   drivers/edac: cle...
317
  					PCI_DEVICE_ID_INTEL_82860_0, NULL);
e7ecd8910   Dave Peterson   [PATCH] EDAC: for...
318

0d88a10e5   Alan Cox   [PATCH] EDAC: dri...
319
  		if (mci_pdev == NULL) {
956b9ba15   Joe Perches   edac: Convert deb...
320
321
  			edac_dbg(0, "860 pci_get_device fail
  ");
e8a491b40   Dave Peterson   [PATCH] EDAC: i82...
322
323
  			pci_rc = -ENODEV;
  			goto fail1;
0d88a10e5   Alan Cox   [PATCH] EDAC: dri...
324
  		}
e7ecd8910   Dave Peterson   [PATCH] EDAC: for...
325

0d88a10e5   Alan Cox   [PATCH] EDAC: dri...
326
  		pci_rc = i82860_init_one(mci_pdev, i82860_pci_tbl);
e7ecd8910   Dave Peterson   [PATCH] EDAC: for...
327

0d88a10e5   Alan Cox   [PATCH] EDAC: dri...
328
  		if (pci_rc < 0) {
956b9ba15   Joe Perches   edac: Convert deb...
329
330
  			edac_dbg(0, "860 init fail
  ");
e8a491b40   Dave Peterson   [PATCH] EDAC: i82...
331
332
  			pci_rc = -ENODEV;
  			goto fail1;
0d88a10e5   Alan Cox   [PATCH] EDAC: dri...
333
334
  		}
  	}
e7ecd8910   Dave Peterson   [PATCH] EDAC: for...
335

0d88a10e5   Alan Cox   [PATCH] EDAC: dri...
336
  	return 0;
e8a491b40   Dave Peterson   [PATCH] EDAC: i82...
337

052dfb45c   Douglas Thompson   drivers/edac: cle...
338
  fail1:
e8a491b40   Dave Peterson   [PATCH] EDAC: i82...
339
  	pci_unregister_driver(&i82860_driver);
052dfb45c   Douglas Thompson   drivers/edac: cle...
340
  fail0:
726019459   Markus Elfring   EDAC: Delete unne...
341
  	pci_dev_put(mci_pdev);
e8a491b40   Dave Peterson   [PATCH] EDAC: i82...
342
  	return pci_rc;
0d88a10e5   Alan Cox   [PATCH] EDAC: dri...
343
344
345
346
  }
  
  static void __exit i82860_exit(void)
  {
956b9ba15   Joe Perches   edac: Convert deb...
347
348
  	edac_dbg(3, "
  ");
0d88a10e5   Alan Cox   [PATCH] EDAC: dri...
349
  	pci_unregister_driver(&i82860_driver);
726019459   Markus Elfring   EDAC: Delete unne...
350
  	pci_dev_put(mci_pdev);
0d88a10e5   Alan Cox   [PATCH] EDAC: dri...
351
352
353
354
355
356
  }
  
  module_init(i82860_init);
  module_exit(i82860_exit);
  
  MODULE_LICENSE("GPL");
e7ecd8910   Dave Peterson   [PATCH] EDAC: for...
357
  MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com) "
052dfb45c   Douglas Thompson   drivers/edac: cle...
358
  		"Ben Woodard <woodard@redhat.com>");
0d88a10e5   Alan Cox   [PATCH] EDAC: dri...
359
  MODULE_DESCRIPTION("ECC support for Intel 82860 memory hub controllers");
c3c52bce6   Hitoshi Mitake   edac: fix module ...
360
361
362
  
  module_param(edac_op_state, int, 0444);
  MODULE_PARM_DESC(edac_op_state, "EDAC Error Reporting state: 0=Poll,1=NMI");