Blame view

drivers/edac/i82860_edac.c 9.1 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

929a40ec3   Doug Thompson   [PATCH] EDAC: fix...
18
  #define EDAC_MOD_STR	"i82860_edac"
37f04581a   Doug Thompson   [PATCH] EDAC: PCI...
19

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

0d88a10e5   Alan Cox   [PATCH] EDAC: dri...
26
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
  #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...
55
  		.ctl_name = "i82860"},
0d88a10e5   Alan Cox   [PATCH] EDAC: dri...
56
  };
f044091ca   Douglas Thompson   drivers/edac: rem...
57
  static struct pci_dev *mci_pdev;	/* init dev: in case that AGP code
e7ecd8910   Dave Peterson   [PATCH] EDAC: for...
58
59
  					 * has already registered driver
  					 */
456a2f955   Dave Jiang   drivers/edac: dri...
60
  static struct edac_pci_ctl_info *i82860_pci;
0d88a10e5   Alan Cox   [PATCH] EDAC: dri...
61

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

0d88a10e5   Alan Cox   [PATCH] EDAC: dri...
68
69
70
71
72
  	/*
  	 * 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...
73
74
75
76
  	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...
77

37f04581a   Doug Thompson   [PATCH] EDAC: PCI...
78
  	pci_write_bits16(pdev, I82860_ERRSTS, 0x0003, 0x0003);
0d88a10e5   Alan Cox   [PATCH] EDAC: dri...
79
80
81
82
83
84
85
86
  
  	/*
  	 * 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...
87

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

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

131895251   Doug Thompson   [PATCH] EDAC: pro...
167
168
169
170
171
  		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...
172
  		dimm->nr_pages = cumul_size - last_cumul_size;
131895251   Doug Thompson   [PATCH] EDAC: pro...
173
  		last_cumul_size = cumul_size;
084a4fcce   Mauro Carvalho Chehab   edac: move dimm p...
174
175
176
177
  		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...
178
179
180
181
182
183
  	}
  }
  
  static int i82860_probe1(struct pci_dev *pdev, int dev_idx)
  {
  	struct mem_ctl_info *mci;
84c3a6840   Mauro Carvalho Chehab   i82860_edac: conv...
184
  	struct edac_mc_layer layers[2];
131895251   Doug Thompson   [PATCH] EDAC: pro...
185
  	struct i82860_error_info discard;
0d88a10e5   Alan Cox   [PATCH] EDAC: dri...
186

84c3a6840   Mauro Carvalho Chehab   i82860_edac: conv...
187
188
189
190
191
192
193
194
195
  	/*
  	 * 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...
196
  	 */
84c3a6840   Mauro Carvalho Chehab   i82860_edac: conv...
197
198
199
200
201
202
  	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 ...
203
  	mci = edac_mc_alloc(0, ARRAY_SIZE(layers), layers, 0);
0d88a10e5   Alan Cox   [PATCH] EDAC: dri...
204
205
  	if (!mci)
  		return -ENOMEM;
956b9ba15   Joe Perches   edac: Convert deb...
206
207
  	edac_dbg(3, "init mci
  ");
fd687502d   Mauro Carvalho Chehab   edac: Rename the ...
208
  	mci->pdev = &pdev->dev;
0d88a10e5   Alan Cox   [PATCH] EDAC: dri...
209
  	mci->mtype_cap = MEM_FLAG_DDR;
0d88a10e5   Alan Cox   [PATCH] EDAC: dri...
210
211
212
  	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...
213
  	mci->mod_name = EDAC_MOD_STR;
0d88a10e5   Alan Cox   [PATCH] EDAC: dri...
214
  	mci->ctl_name = i82860_devs[dev_idx].ctl_name;
c4192705f   Dave Jiang   drivers/edac: add...
215
  	mci->dev_name = pci_name(pdev);
0d88a10e5   Alan Cox   [PATCH] EDAC: dri...
216
217
  	mci->edac_check = i82860_check;
  	mci->ctl_page_to_phys = NULL;
131895251   Doug Thompson   [PATCH] EDAC: pro...
218
  	i82860_init_csrows(mci, pdev);
b4e8b3720   Dave Jiang   drivers/edac: Lin...
219
  	i82860_get_error_info(mci, &discard);	/* clear counters */
0d88a10e5   Alan Cox   [PATCH] EDAC: dri...
220

2d7bbb91c   Doug Thompson   [PATCH] EDAC: mc ...
221
222
223
  	/* 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...
224
  	if (edac_mc_add_mc(mci)) {
956b9ba15   Joe Perches   edac: Convert deb...
225
226
  		edac_dbg(3, "failed edac_mc_add_mc()
  ");
131895251   Doug Thompson   [PATCH] EDAC: pro...
227
  		goto fail;
0d88a10e5   Alan Cox   [PATCH] EDAC: dri...
228
  	}
e7ecd8910   Dave Peterson   [PATCH] EDAC: for...
229

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

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

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

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

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

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

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

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

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

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