Blame view

drivers/edac/amd76x_edac.c 9.31 KB
806c35f50   Alan Cox   [PATCH] EDAC: dri...
1
2
3
4
5
6
7
8
9
10
11
12
13
  /*
   * AMD 76x Memory Controller kernel module
   * (C) 2003 Linux Networx (http://lnxi.com)
   * This file may be distributed under the terms of the
   * GNU General Public License.
   *
   * Written by Thayne Harbaugh
   * Based on work by Dan Hollis <goemon at anime dot net> and others.
   *	http://www.anime.net/~goemon/linux-ecc/
   *
   * $Id: edac_amd76x.c,v 1.4.2.5 2005/10/05 00:43:44 dsp_llnl Exp $
   *
   */
806c35f50   Alan Cox   [PATCH] EDAC: dri...
14
15
  #include <linux/module.h>
  #include <linux/init.h>
806c35f50   Alan Cox   [PATCH] EDAC: dri...
16
17
  #include <linux/pci.h>
  #include <linux/pci_ids.h>
c3c52bce6   Hitoshi Mitake   edac: fix module ...
18
  #include <linux/edac.h>
78d88e8a3   Mauro Carvalho Chehab   edac: rename edac...
19
  #include "edac_module.h"
806c35f50   Alan Cox   [PATCH] EDAC: dri...
20

929a40ec3   Doug Thompson   [PATCH] EDAC: fix...
21
  #define EDAC_MOD_STR	"amd76x_edac"
37f04581a   Doug Thompson   [PATCH] EDAC: PCI...
22

537fba289   Dave Peterson   [PATCH] EDAC: pri...
23
  #define amd76x_printk(level, fmt, arg...) \
e7ecd8910   Dave Peterson   [PATCH] EDAC: for...
24
  	edac_printk(level, "amd76x", fmt, ##arg)
537fba289   Dave Peterson   [PATCH] EDAC: pri...
25
26
  
  #define amd76x_mc_printk(mci, level, fmt, arg...) \
e7ecd8910   Dave Peterson   [PATCH] EDAC: for...
27
  	edac_mc_chipset_printk(mci, level, "amd76x", fmt, ##arg)
537fba289   Dave Peterson   [PATCH] EDAC: pri...
28

806c35f50   Alan Cox   [PATCH] EDAC: dri...
29
  #define AMD76X_NR_CSROWS 8
806c35f50   Alan Cox   [PATCH] EDAC: dri...
30
  #define AMD76X_NR_DIMMS  4
806c35f50   Alan Cox   [PATCH] EDAC: dri...
31
  /* AMD 76x register addresses - device 0 function 0 - PCI bridge */
e7ecd8910   Dave Peterson   [PATCH] EDAC: for...
32

806c35f50   Alan Cox   [PATCH] EDAC: dri...
33
34
35
36
37
38
39
40
41
42
43
  #define AMD76X_ECC_MODE_STATUS	0x48	/* Mode and status of ECC (32b)
  					 *
  					 * 31:16 reserved
  					 * 15:14 SERR enabled: x1=ue 1x=ce
  					 * 13    reserved
  					 * 12    diag: disabled, enabled
  					 * 11:10 mode: dis, EC, ECC, ECC+scrub
  					 *  9:8  status: x1=ue 1x=ce
  					 *  7:4  UE cs row
  					 *  3:0  CE cs row
  					 */
e7ecd8910   Dave Peterson   [PATCH] EDAC: for...
44

806c35f50   Alan Cox   [PATCH] EDAC: dri...
45
46
47
48
49
50
51
52
53
54
55
56
57
58
  #define AMD76X_DRAM_MODE_STATUS	0x58	/* DRAM Mode and status (32b)
  					 *
  					 * 31:26 clock disable 5 - 0
  					 * 25    SDRAM init
  					 * 24    reserved
  					 * 23    mode register service
  					 * 22:21 suspend to RAM
  					 * 20    burst refresh enable
  					 * 19    refresh disable
  					 * 18    reserved
  					 * 17:16 cycles-per-refresh
  					 * 15:8  reserved
  					 *  7:0  x4 mode enable 7 - 0
  					 */
e7ecd8910   Dave Peterson   [PATCH] EDAC: for...
59

806c35f50   Alan Cox   [PATCH] EDAC: dri...
60
61
62
63
64
65
66
67
68
  #define AMD76X_MEM_BASE_ADDR	0xC0	/* Memory base address (8 x 32b)
  					 *
  					 * 31:23 chip-select base
  					 * 22:16 reserved
  					 * 15:7  chip-select mask
  					 *  6:3  reserved
  					 *  2:1  address mode
  					 *  0    chip-select enable
  					 */
806c35f50   Alan Cox   [PATCH] EDAC: dri...
69
70
71
  struct amd76x_error_info {
  	u32 ecc_mode_status;
  };
806c35f50   Alan Cox   [PATCH] EDAC: dri...
72
73
74
75
  enum amd76x_chips {
  	AMD761 = 0,
  	AMD762
  };
806c35f50   Alan Cox   [PATCH] EDAC: dri...
76
77
78
  struct amd76x_dev_info {
  	const char *ctl_name;
  };
806c35f50   Alan Cox   [PATCH] EDAC: dri...
79
  static const struct amd76x_dev_info amd76x_devs[] = {
e7ecd8910   Dave Peterson   [PATCH] EDAC: for...
80
  	[AMD761] = {
052dfb45c   Douglas Thompson   drivers/edac: cle...
81
  		.ctl_name = "AMD761"},
e7ecd8910   Dave Peterson   [PATCH] EDAC: for...
82
  	[AMD762] = {
052dfb45c   Douglas Thompson   drivers/edac: cle...
83
  		.ctl_name = "AMD762"},
806c35f50   Alan Cox   [PATCH] EDAC: dri...
84
  };
456a2f955   Dave Jiang   drivers/edac: dri...
85
  static struct edac_pci_ctl_info *amd76x_pci;
806c35f50   Alan Cox   [PATCH] EDAC: dri...
86
87
88
89
90
91
92
93
  /**
   *	amd76x_get_error_info	-	fetch error information
   *	@mci: Memory controller
   *	@info: Info to fill in
   *
   *	Fetch and store the AMD76x ECC status. Clear pending status
   *	on the chip so that further errors will be reported
   */
e7ecd8910   Dave Peterson   [PATCH] EDAC: for...
94
  static void amd76x_get_error_info(struct mem_ctl_info *mci,
052dfb45c   Douglas Thompson   drivers/edac: cle...
95
  				struct amd76x_error_info *info)
806c35f50   Alan Cox   [PATCH] EDAC: dri...
96
  {
37f04581a   Doug Thompson   [PATCH] EDAC: PCI...
97
  	struct pci_dev *pdev;
fd687502d   Mauro Carvalho Chehab   edac: Rename the ...
98
  	pdev = to_pci_dev(mci->pdev);
37f04581a   Doug Thompson   [PATCH] EDAC: PCI...
99
  	pci_read_config_dword(pdev, AMD76X_ECC_MODE_STATUS,
052dfb45c   Douglas Thompson   drivers/edac: cle...
100
  			&info->ecc_mode_status);
806c35f50   Alan Cox   [PATCH] EDAC: dri...
101
102
  
  	if (info->ecc_mode_status & BIT(8))
37f04581a   Doug Thompson   [PATCH] EDAC: PCI...
103
  		pci_write_bits32(pdev, AMD76X_ECC_MODE_STATUS,
67cb2b612   Douglas Thompson   drivers/edac: Lin...
104
  				 (u32) BIT(8), (u32) BIT(8));
806c35f50   Alan Cox   [PATCH] EDAC: dri...
105
106
  
  	if (info->ecc_mode_status & BIT(9))
37f04581a   Doug Thompson   [PATCH] EDAC: PCI...
107
  		pci_write_bits32(pdev, AMD76X_ECC_MODE_STATUS,
67cb2b612   Douglas Thompson   drivers/edac: Lin...
108
  				 (u32) BIT(9), (u32) BIT(9));
806c35f50   Alan Cox   [PATCH] EDAC: dri...
109
  }
806c35f50   Alan Cox   [PATCH] EDAC: dri...
110
111
112
113
114
115
116
117
118
119
  /**
   *	amd76x_process_error_info	-	Error check
   *	@mci: Memory controller
   *	@info: Previously fetched information from chip
   *	@handle_errors: 1 if we should do recovery
   *
   *	Process the chip state and decide if an error has occurred.
   *	A return of 1 indicates an error. Also if handle_errors is true
   *	then attempt to handle and clean up after the error
   */
e7ecd8910   Dave Peterson   [PATCH] EDAC: for...
120
  static int amd76x_process_error_info(struct mem_ctl_info *mci,
052dfb45c   Douglas Thompson   drivers/edac: cle...
121
122
  				struct amd76x_error_info *info,
  				int handle_errors)
806c35f50   Alan Cox   [PATCH] EDAC: dri...
123
124
125
126
127
128
129
  {
  	int error_found;
  	u32 row;
  
  	error_found = 0;
  
  	/*
67cb2b612   Douglas Thompson   drivers/edac: Lin...
130
  	 *      Check for an uncorrectable error
806c35f50   Alan Cox   [PATCH] EDAC: dri...
131
132
133
134
135
136
  	 */
  	if (info->ecc_mode_status & BIT(8)) {
  		error_found = 1;
  
  		if (handle_errors) {
  			row = (info->ecc_mode_status >> 4) & 0xf;
9eb07a7fb   Mauro Carvalho Chehab   edac: edac_mc_han...
137
  			edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1,
de3910eb7   Mauro Carvalho Chehab   edac: change the ...
138
  					     mci->csrows[row]->first_page, 0, 0,
d8c34af4d   Mauro Carvalho Chehab   amd76x_edac: conv...
139
  					     row, 0, -1,
03f7eae80   Mauro Carvalho Chehab   edac: remove arch...
140
  					     mci->ctl_name, "");
806c35f50   Alan Cox   [PATCH] EDAC: dri...
141
142
143
144
  		}
  	}
  
  	/*
67cb2b612   Douglas Thompson   drivers/edac: Lin...
145
  	 *      Check for a correctable error
806c35f50   Alan Cox   [PATCH] EDAC: dri...
146
147
148
149
150
151
  	 */
  	if (info->ecc_mode_status & BIT(9)) {
  		error_found = 1;
  
  		if (handle_errors) {
  			row = info->ecc_mode_status & 0xf;
9eb07a7fb   Mauro Carvalho Chehab   edac: edac_mc_han...
152
  			edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1,
de3910eb7   Mauro Carvalho Chehab   edac: change the ...
153
  					     mci->csrows[row]->first_page, 0, 0,
d8c34af4d   Mauro Carvalho Chehab   amd76x_edac: conv...
154
  					     row, 0, -1,
03f7eae80   Mauro Carvalho Chehab   edac: remove arch...
155
  					     mci->ctl_name, "");
806c35f50   Alan Cox   [PATCH] EDAC: dri...
156
157
  		}
  	}
e7ecd8910   Dave Peterson   [PATCH] EDAC: for...
158

806c35f50   Alan Cox   [PATCH] EDAC: dri...
159
160
161
162
163
164
165
166
167
168
  	return error_found;
  }
  
  /**
   *	amd76x_check	-	Poll the controller
   *	@mci: Memory controller
   *
   *	Called by the poll handlers this function reads the status
   *	from the controller and checks for errors.
   */
806c35f50   Alan Cox   [PATCH] EDAC: dri...
169
170
171
  static void amd76x_check(struct mem_ctl_info *mci)
  {
  	struct amd76x_error_info info;
956b9ba15   Joe Perches   edac: Convert deb...
172
173
  	edac_dbg(3, "
  ");
806c35f50   Alan Cox   [PATCH] EDAC: dri...
174
175
176
  	amd76x_get_error_info(mci, &info);
  	amd76x_process_error_info(mci, &info, 1);
  }
131895251   Doug Thompson   [PATCH] EDAC: pro...
177
  static void amd76x_init_csrows(struct mem_ctl_info *mci, struct pci_dev *pdev,
052dfb45c   Douglas Thompson   drivers/edac: cle...
178
  			enum edac_type edac_mode)
131895251   Doug Thompson   [PATCH] EDAC: pro...
179
180
  {
  	struct csrow_info *csrow;
084a4fcce   Mauro Carvalho Chehab   edac: move dimm p...
181
  	struct dimm_info *dimm;
131895251   Doug Thompson   [PATCH] EDAC: pro...
182
183
184
185
  	u32 mba, mba_base, mba_mask, dms;
  	int index;
  
  	for (index = 0; index < mci->nr_csrows; index++) {
de3910eb7   Mauro Carvalho Chehab   edac: change the ...
186
187
  		csrow = mci->csrows[index];
  		dimm = csrow->channels[0]->dimm;
131895251   Doug Thompson   [PATCH] EDAC: pro...
188
189
190
  
  		/* find the DRAM Chip Select Base address and mask */
  		pci_read_config_dword(pdev,
052dfb45c   Douglas Thompson   drivers/edac: cle...
191
  				AMD76X_MEM_BASE_ADDR + (index * 4), &mba);
131895251   Doug Thompson   [PATCH] EDAC: pro...
192
193
194
195
196
197
198
199
  
  		if (!(mba & BIT(0)))
  			continue;
  
  		mba_base = mba & 0xff800000UL;
  		mba_mask = ((mba & 0xff80) << 16) | 0x7fffffUL;
  		pci_read_config_dword(pdev, AMD76X_DRAM_MODE_STATUS, &dms);
  		csrow->first_page = mba_base >> PAGE_SHIFT;
a895bf8b1   Mauro Carvalho Chehab   edac: move nr_pag...
200
201
  		dimm->nr_pages = (mba_mask + 1) >> PAGE_SHIFT;
  		csrow->last_page = csrow->first_page + dimm->nr_pages - 1;
131895251   Doug Thompson   [PATCH] EDAC: pro...
202
  		csrow->page_mask = mba_mask >> PAGE_SHIFT;
a895bf8b1   Mauro Carvalho Chehab   edac: move nr_pag...
203
  		dimm->grain = dimm->nr_pages << PAGE_SHIFT;
084a4fcce   Mauro Carvalho Chehab   edac: move dimm p...
204
205
206
  		dimm->mtype = MEM_RDDR;
  		dimm->dtype = ((dms >> index) & 0x1) ? DEV_X4 : DEV_UNKNOWN;
  		dimm->edac_mode = edac_mode;
131895251   Doug Thompson   [PATCH] EDAC: pro...
207
208
  	}
  }
806c35f50   Alan Cox   [PATCH] EDAC: dri...
209
210
211
212
213
214
215
216
217
  /**
   *	amd76x_probe1	-	Perform set up for detected device
   *	@pdev; PCI device detected
   *	@dev_idx: Device type index
   *
   *	We have found an AMD76x and now need to set up the memory
   *	controller status reporting. We configure and set up the
   *	memory controller reporting and claim the device.
   */
806c35f50   Alan Cox   [PATCH] EDAC: dri...
218
219
  static int amd76x_probe1(struct pci_dev *pdev, int dev_idx)
  {
131895251   Doug Thompson   [PATCH] EDAC: pro...
220
  	static const enum edac_type ems_modes[] = {
806c35f50   Alan Cox   [PATCH] EDAC: dri...
221
222
223
224
225
  		EDAC_NONE,
  		EDAC_EC,
  		EDAC_SECDED,
  		EDAC_SECDED
  	};
d8c34af4d   Mauro Carvalho Chehab   amd76x_edac: conv...
226
227
  	struct mem_ctl_info *mci;
  	struct edac_mc_layer layers[2];
806c35f50   Alan Cox   [PATCH] EDAC: dri...
228
229
  	u32 ems;
  	u32 ems_mode;
749ede574   Dave Peterson   [PATCH] EDAC: cle...
230
  	struct amd76x_error_info discard;
806c35f50   Alan Cox   [PATCH] EDAC: dri...
231

956b9ba15   Joe Perches   edac: Convert deb...
232
233
  	edac_dbg(0, "
  ");
806c35f50   Alan Cox   [PATCH] EDAC: dri...
234
235
  	pci_read_config_dword(pdev, AMD76X_ECC_MODE_STATUS, &ems);
  	ems_mode = (ems >> 10) & 0x3;
806c35f50   Alan Cox   [PATCH] EDAC: dri...
236

d8c34af4d   Mauro Carvalho Chehab   amd76x_edac: conv...
237
238
239
240
241
242
  	layers[0].type = EDAC_MC_LAYER_CHIP_SELECT;
  	layers[0].size = AMD76X_NR_CSROWS;
  	layers[0].is_virt_csrow = true;
  	layers[1].type = EDAC_MC_LAYER_CHANNEL;
  	layers[1].size = 1;
  	layers[1].is_virt_csrow = false;
ca0907b9e   Mauro Carvalho Chehab   edac: Remove the ...
243
  	mci = edac_mc_alloc(0, ARRAY_SIZE(layers), layers, 0);
d8c34af4d   Mauro Carvalho Chehab   amd76x_edac: conv...
244
245
  
  	if (mci == NULL)
131895251   Doug Thompson   [PATCH] EDAC: pro...
246
  		return -ENOMEM;
806c35f50   Alan Cox   [PATCH] EDAC: dri...
247

956b9ba15   Joe Perches   edac: Convert deb...
248
249
  	edac_dbg(0, "mci = %p
  ", mci);
fd687502d   Mauro Carvalho Chehab   edac: Rename the ...
250
  	mci->pdev = &pdev->dev;
806c35f50   Alan Cox   [PATCH] EDAC: dri...
251
  	mci->mtype_cap = MEM_FLAG_RDDR;
806c35f50   Alan Cox   [PATCH] EDAC: dri...
252
253
  	mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_EC | EDAC_FLAG_SECDED;
  	mci->edac_cap = ems_mode ?
052dfb45c   Douglas Thompson   drivers/edac: cle...
254
  		(EDAC_FLAG_EC | EDAC_FLAG_SECDED) : EDAC_FLAG_NONE;
680cbbbb0   Dave Peterson   [PATCH] EDAC: nam...
255
  	mci->mod_name = EDAC_MOD_STR;
806c35f50   Alan Cox   [PATCH] EDAC: dri...
256
  	mci->ctl_name = amd76x_devs[dev_idx].ctl_name;
c4192705f   Dave Jiang   drivers/edac: add...
257
  	mci->dev_name = pci_name(pdev);
806c35f50   Alan Cox   [PATCH] EDAC: dri...
258
259
  	mci->edac_check = amd76x_check;
  	mci->ctl_page_to_phys = NULL;
131895251   Doug Thompson   [PATCH] EDAC: pro...
260
  	amd76x_init_csrows(mci, pdev, ems_modes[ems_mode]);
67cb2b612   Douglas Thompson   drivers/edac: Lin...
261
  	amd76x_get_error_info(mci, &discard);	/* clear counters */
806c35f50   Alan Cox   [PATCH] EDAC: dri...
262

2d7bbb91c   Doug Thompson   [PATCH] EDAC: mc ...
263
264
265
  	/* 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...
266
  	if (edac_mc_add_mc(mci)) {
956b9ba15   Joe Perches   edac: Convert deb...
267
268
  		edac_dbg(3, "failed edac_mc_add_mc()
  ");
806c35f50   Alan Cox   [PATCH] EDAC: dri...
269
270
  		goto fail;
  	}
456a2f955   Dave Jiang   drivers/edac: dri...
271
272
273
274
275
276
277
278
279
280
281
282
  	/* allocating generic PCI control info */
  	amd76x_pci = edac_pci_create_generic_ctl(&pdev->dev, EDAC_MOD_STR);
  	if (!amd76x_pci) {
  		printk(KERN_WARNING
  			"%s(): Unable to create PCI control
  ",
  			__func__);
  		printk(KERN_WARNING
  			"%s(): PCI error report via EDAC not setup
  ",
  			__func__);
  	}
806c35f50   Alan Cox   [PATCH] EDAC: dri...
283
  	/* get this far and it's successful */
956b9ba15   Joe Perches   edac: Convert deb...
284
285
  	edac_dbg(3, "success
  ");
806c35f50   Alan Cox   [PATCH] EDAC: dri...
286
  	return 0;
052dfb45c   Douglas Thompson   drivers/edac: cle...
287
  fail:
131895251   Doug Thompson   [PATCH] EDAC: pro...
288
289
  	edac_mc_free(mci);
  	return -ENODEV;
806c35f50   Alan Cox   [PATCH] EDAC: dri...
290
291
292
  }
  
  /* returns count (>= 0), or negative on error */
9b3c6e85c   Greg Kroah-Hartman   Drivers: edac: re...
293
294
  static int amd76x_init_one(struct pci_dev *pdev,
  			   const struct pci_device_id *ent)
806c35f50   Alan Cox   [PATCH] EDAC: dri...
295
  {
956b9ba15   Joe Perches   edac: Convert deb...
296
297
  	edac_dbg(0, "
  ");
806c35f50   Alan Cox   [PATCH] EDAC: dri...
298

ee6583f6e   Roman Fietze   PCI: fix typos pc...
299
  	/* don't need to call pci_enable_device() */
806c35f50   Alan Cox   [PATCH] EDAC: dri...
300
301
  	return amd76x_probe1(pdev, ent->driver_data);
  }
806c35f50   Alan Cox   [PATCH] EDAC: dri...
302
303
304
305
306
307
308
309
  /**
   *	amd76x_remove_one	-	driver shutdown
   *	@pdev: PCI device being handed back
   *
   *	Called when the driver is unloaded. Find the matching mci
   *	structure for the device then delete the mci and free the
   *	resources.
   */
9b3c6e85c   Greg Kroah-Hartman   Drivers: edac: re...
310
  static void amd76x_remove_one(struct pci_dev *pdev)
806c35f50   Alan Cox   [PATCH] EDAC: dri...
311
312
  {
  	struct mem_ctl_info *mci;
956b9ba15   Joe Perches   edac: Convert deb...
313
314
  	edac_dbg(0, "
  ");
806c35f50   Alan Cox   [PATCH] EDAC: dri...
315

456a2f955   Dave Jiang   drivers/edac: dri...
316
317
  	if (amd76x_pci)
  		edac_pci_release_generic_ctl(amd76x_pci);
37f04581a   Doug Thompson   [PATCH] EDAC: PCI...
318
  	if ((mci = edac_mc_del_mc(&pdev->dev)) == NULL)
806c35f50   Alan Cox   [PATCH] EDAC: dri...
319
  		return;
18dbc337a   Dave Peterson   [PATCH] EDAC: pro...
320

806c35f50   Alan Cox   [PATCH] EDAC: dri...
321
322
  	edac_mc_free(mci);
  }
ba935f409   Jingoo Han   EDAC: Remove DEFI...
323
  static const struct pci_device_id amd76x_pci_tbl[] = {
e7ecd8910   Dave Peterson   [PATCH] EDAC: for...
324
  	{
67cb2b612   Douglas Thompson   drivers/edac: Lin...
325
326
  	 PCI_VEND_DEV(AMD, FE_GATE_700C), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
  	 AMD762},
e7ecd8910   Dave Peterson   [PATCH] EDAC: for...
327
  	{
67cb2b612   Douglas Thompson   drivers/edac: Lin...
328
329
  	 PCI_VEND_DEV(AMD, FE_GATE_700E), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
  	 AMD761},
e7ecd8910   Dave Peterson   [PATCH] EDAC: for...
330
  	{
67cb2b612   Douglas Thompson   drivers/edac: Lin...
331
332
  	 0,
  	 }			/* 0 terminated list. */
806c35f50   Alan Cox   [PATCH] EDAC: dri...
333
334
335
  };
  
  MODULE_DEVICE_TABLE(pci, amd76x_pci_tbl);
806c35f50   Alan Cox   [PATCH] EDAC: dri...
336
  static struct pci_driver amd76x_driver = {
680cbbbb0   Dave Peterson   [PATCH] EDAC: nam...
337
  	.name = EDAC_MOD_STR,
806c35f50   Alan Cox   [PATCH] EDAC: dri...
338
  	.probe = amd76x_init_one,
9b3c6e85c   Greg Kroah-Hartman   Drivers: edac: re...
339
  	.remove = amd76x_remove_one,
806c35f50   Alan Cox   [PATCH] EDAC: dri...
340
341
  	.id_table = amd76x_pci_tbl,
  };
da9bb1d27   Alan Cox   [PATCH] EDAC: cor...
342
  static int __init amd76x_init(void)
806c35f50   Alan Cox   [PATCH] EDAC: dri...
343
  {
c3c52bce6   Hitoshi Mitake   edac: fix module ...
344
345
         /* Ensure that the OPSTATE is set correctly for POLL or NMI */
         opstate_init();
806c35f50   Alan Cox   [PATCH] EDAC: dri...
346
347
348
349
350
351
352
353
354
355
356
357
358
359
  	return pci_register_driver(&amd76x_driver);
  }
  
  static void __exit amd76x_exit(void)
  {
  	pci_unregister_driver(&amd76x_driver);
  }
  
  module_init(amd76x_init);
  module_exit(amd76x_exit);
  
  MODULE_LICENSE("GPL");
  MODULE_AUTHOR("Linux Networx (http://lnxi.com) Thayne Harbaugh");
  MODULE_DESCRIPTION("MC support for AMD 76x memory 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");