Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/drivers/edac/i82860_edac.c
15109 views
1
/*
2
* Intel 82860 Memory Controller kernel module
3
* (C) 2005 Red Hat (http://www.redhat.com)
4
* This file may be distributed under the terms of the
5
* GNU General Public License.
6
*
7
* Written by Ben Woodard <[email protected]>
8
* shamelessly copied from and based upon the edac_i82875 driver
9
* by Thayne Harbaugh of Linux Networx. (http://lnxi.com)
10
*/
11
12
#include <linux/module.h>
13
#include <linux/init.h>
14
#include <linux/pci.h>
15
#include <linux/pci_ids.h>
16
#include <linux/edac.h>
17
#include "edac_core.h"
18
19
#define I82860_REVISION " Ver: 2.0.2"
20
#define EDAC_MOD_STR "i82860_edac"
21
22
#define i82860_printk(level, fmt, arg...) \
23
edac_printk(level, "i82860", fmt, ##arg)
24
25
#define i82860_mc_printk(mci, level, fmt, arg...) \
26
edac_mc_chipset_printk(mci, level, "i82860", fmt, ##arg)
27
28
#ifndef PCI_DEVICE_ID_INTEL_82860_0
29
#define PCI_DEVICE_ID_INTEL_82860_0 0x2531
30
#endif /* PCI_DEVICE_ID_INTEL_82860_0 */
31
32
#define I82860_MCHCFG 0x50
33
#define I82860_GBA 0x60
34
#define I82860_GBA_MASK 0x7FF
35
#define I82860_GBA_SHIFT 24
36
#define I82860_ERRSTS 0xC8
37
#define I82860_EAP 0xE4
38
#define I82860_DERRCTL_STS 0xE2
39
40
enum i82860_chips {
41
I82860 = 0,
42
};
43
44
struct i82860_dev_info {
45
const char *ctl_name;
46
};
47
48
struct i82860_error_info {
49
u16 errsts;
50
u32 eap;
51
u16 derrsyn;
52
u16 errsts2;
53
};
54
55
static const struct i82860_dev_info i82860_devs[] = {
56
[I82860] = {
57
.ctl_name = "i82860"},
58
};
59
60
static struct pci_dev *mci_pdev; /* init dev: in case that AGP code
61
* has already registered driver
62
*/
63
static struct edac_pci_ctl_info *i82860_pci;
64
65
static void i82860_get_error_info(struct mem_ctl_info *mci,
66
struct i82860_error_info *info)
67
{
68
struct pci_dev *pdev;
69
70
pdev = to_pci_dev(mci->dev);
71
72
/*
73
* This is a mess because there is no atomic way to read all the
74
* registers at once and the registers can transition from CE being
75
* overwritten by UE.
76
*/
77
pci_read_config_word(pdev, I82860_ERRSTS, &info->errsts);
78
pci_read_config_dword(pdev, I82860_EAP, &info->eap);
79
pci_read_config_word(pdev, I82860_DERRCTL_STS, &info->derrsyn);
80
pci_read_config_word(pdev, I82860_ERRSTS, &info->errsts2);
81
82
pci_write_bits16(pdev, I82860_ERRSTS, 0x0003, 0x0003);
83
84
/*
85
* If the error is the same for both reads then the first set of reads
86
* is valid. If there is a change then there is a CE no info and the
87
* second set of reads is valid and should be UE info.
88
*/
89
if (!(info->errsts2 & 0x0003))
90
return;
91
92
if ((info->errsts ^ info->errsts2) & 0x0003) {
93
pci_read_config_dword(pdev, I82860_EAP, &info->eap);
94
pci_read_config_word(pdev, I82860_DERRCTL_STS, &info->derrsyn);
95
}
96
}
97
98
static int i82860_process_error_info(struct mem_ctl_info *mci,
99
struct i82860_error_info *info,
100
int handle_errors)
101
{
102
int row;
103
104
if (!(info->errsts2 & 0x0003))
105
return 0;
106
107
if (!handle_errors)
108
return 1;
109
110
if ((info->errsts ^ info->errsts2) & 0x0003) {
111
edac_mc_handle_ce_no_info(mci, "UE overwrote CE");
112
info->errsts = info->errsts2;
113
}
114
115
info->eap >>= PAGE_SHIFT;
116
row = edac_mc_find_csrow_by_page(mci, info->eap);
117
118
if (info->errsts & 0x0002)
119
edac_mc_handle_ue(mci, info->eap, 0, row, "i82860 UE");
120
else
121
edac_mc_handle_ce(mci, info->eap, 0, info->derrsyn, row, 0,
122
"i82860 UE");
123
124
return 1;
125
}
126
127
static void i82860_check(struct mem_ctl_info *mci)
128
{
129
struct i82860_error_info info;
130
131
debugf1("MC%d: %s()\n", mci->mc_idx, __func__);
132
i82860_get_error_info(mci, &info);
133
i82860_process_error_info(mci, &info, 1);
134
}
135
136
static void i82860_init_csrows(struct mem_ctl_info *mci, struct pci_dev *pdev)
137
{
138
unsigned long last_cumul_size;
139
u16 mchcfg_ddim; /* DRAM Data Integrity Mode 0=none, 2=edac */
140
u16 value;
141
u32 cumul_size;
142
struct csrow_info *csrow;
143
int index;
144
145
pci_read_config_word(pdev, I82860_MCHCFG, &mchcfg_ddim);
146
mchcfg_ddim = mchcfg_ddim & 0x180;
147
last_cumul_size = 0;
148
149
/* The group row boundary (GRA) reg values are boundary address
150
* for each DRAM row with a granularity of 16MB. GRA regs are
151
* cumulative; therefore GRA15 will contain the total memory contained
152
* in all eight rows.
153
*/
154
for (index = 0; index < mci->nr_csrows; index++) {
155
csrow = &mci->csrows[index];
156
pci_read_config_word(pdev, I82860_GBA + index * 2, &value);
157
cumul_size = (value & I82860_GBA_MASK) <<
158
(I82860_GBA_SHIFT - PAGE_SHIFT);
159
debugf3("%s(): (%d) cumul_size 0x%x\n", __func__, index,
160
cumul_size);
161
162
if (cumul_size == last_cumul_size)
163
continue; /* not populated */
164
165
csrow->first_page = last_cumul_size;
166
csrow->last_page = cumul_size - 1;
167
csrow->nr_pages = cumul_size - last_cumul_size;
168
last_cumul_size = cumul_size;
169
csrow->grain = 1 << 12; /* I82860_EAP has 4KiB reolution */
170
csrow->mtype = MEM_RMBS;
171
csrow->dtype = DEV_UNKNOWN;
172
csrow->edac_mode = mchcfg_ddim ? EDAC_SECDED : EDAC_NONE;
173
}
174
}
175
176
static int i82860_probe1(struct pci_dev *pdev, int dev_idx)
177
{
178
struct mem_ctl_info *mci;
179
struct i82860_error_info discard;
180
181
/* RDRAM has channels but these don't map onto the abstractions that
182
edac uses.
183
The device groups from the GRA registers seem to map reasonably
184
well onto the notion of a chip select row.
185
There are 16 GRA registers and since the name is associated with
186
the channel and the GRA registers map to physical devices so we are
187
going to make 1 channel for group.
188
*/
189
mci = edac_mc_alloc(0, 16, 1, 0);
190
191
if (!mci)
192
return -ENOMEM;
193
194
debugf3("%s(): init mci\n", __func__);
195
mci->dev = &pdev->dev;
196
mci->mtype_cap = MEM_FLAG_DDR;
197
mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED;
198
/* I"m not sure about this but I think that all RDRAM is SECDED */
199
mci->edac_cap = EDAC_FLAG_SECDED;
200
mci->mod_name = EDAC_MOD_STR;
201
mci->mod_ver = I82860_REVISION;
202
mci->ctl_name = i82860_devs[dev_idx].ctl_name;
203
mci->dev_name = pci_name(pdev);
204
mci->edac_check = i82860_check;
205
mci->ctl_page_to_phys = NULL;
206
i82860_init_csrows(mci, pdev);
207
i82860_get_error_info(mci, &discard); /* clear counters */
208
209
/* Here we assume that we will never see multiple instances of this
210
* type of memory controller. The ID is therefore hardcoded to 0.
211
*/
212
if (edac_mc_add_mc(mci)) {
213
debugf3("%s(): failed edac_mc_add_mc()\n", __func__);
214
goto fail;
215
}
216
217
/* allocating generic PCI control info */
218
i82860_pci = edac_pci_create_generic_ctl(&pdev->dev, EDAC_MOD_STR);
219
if (!i82860_pci) {
220
printk(KERN_WARNING
221
"%s(): Unable to create PCI control\n",
222
__func__);
223
printk(KERN_WARNING
224
"%s(): PCI error report via EDAC not setup\n",
225
__func__);
226
}
227
228
/* get this far and it's successful */
229
debugf3("%s(): success\n", __func__);
230
231
return 0;
232
233
fail:
234
edac_mc_free(mci);
235
return -ENODEV;
236
}
237
238
/* returns count (>= 0), or negative on error */
239
static int __devinit i82860_init_one(struct pci_dev *pdev,
240
const struct pci_device_id *ent)
241
{
242
int rc;
243
244
debugf0("%s()\n", __func__);
245
i82860_printk(KERN_INFO, "i82860 init one\n");
246
247
if (pci_enable_device(pdev) < 0)
248
return -EIO;
249
250
rc = i82860_probe1(pdev, ent->driver_data);
251
252
if (rc == 0)
253
mci_pdev = pci_dev_get(pdev);
254
255
return rc;
256
}
257
258
static void __devexit i82860_remove_one(struct pci_dev *pdev)
259
{
260
struct mem_ctl_info *mci;
261
262
debugf0("%s()\n", __func__);
263
264
if (i82860_pci)
265
edac_pci_release_generic_ctl(i82860_pci);
266
267
if ((mci = edac_mc_del_mc(&pdev->dev)) == NULL)
268
return;
269
270
edac_mc_free(mci);
271
}
272
273
static const struct pci_device_id i82860_pci_tbl[] __devinitdata = {
274
{
275
PCI_VEND_DEV(INTEL, 82860_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
276
I82860},
277
{
278
0,
279
} /* 0 terminated list. */
280
};
281
282
MODULE_DEVICE_TABLE(pci, i82860_pci_tbl);
283
284
static struct pci_driver i82860_driver = {
285
.name = EDAC_MOD_STR,
286
.probe = i82860_init_one,
287
.remove = __devexit_p(i82860_remove_one),
288
.id_table = i82860_pci_tbl,
289
};
290
291
static int __init i82860_init(void)
292
{
293
int pci_rc;
294
295
debugf3("%s()\n", __func__);
296
297
/* Ensure that the OPSTATE is set correctly for POLL or NMI */
298
opstate_init();
299
300
if ((pci_rc = pci_register_driver(&i82860_driver)) < 0)
301
goto fail0;
302
303
if (!mci_pdev) {
304
mci_pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
305
PCI_DEVICE_ID_INTEL_82860_0, NULL);
306
307
if (mci_pdev == NULL) {
308
debugf0("860 pci_get_device fail\n");
309
pci_rc = -ENODEV;
310
goto fail1;
311
}
312
313
pci_rc = i82860_init_one(mci_pdev, i82860_pci_tbl);
314
315
if (pci_rc < 0) {
316
debugf0("860 init fail\n");
317
pci_rc = -ENODEV;
318
goto fail1;
319
}
320
}
321
322
return 0;
323
324
fail1:
325
pci_unregister_driver(&i82860_driver);
326
327
fail0:
328
if (mci_pdev != NULL)
329
pci_dev_put(mci_pdev);
330
331
return pci_rc;
332
}
333
334
static void __exit i82860_exit(void)
335
{
336
debugf3("%s()\n", __func__);
337
338
pci_unregister_driver(&i82860_driver);
339
340
if (mci_pdev != NULL)
341
pci_dev_put(mci_pdev);
342
}
343
344
module_init(i82860_init);
345
module_exit(i82860_exit);
346
347
MODULE_LICENSE("GPL");
348
MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com) "
349
"Ben Woodard <[email protected]>");
350
MODULE_DESCRIPTION("ECC support for Intel 82860 memory hub controllers");
351
352
module_param(edac_op_state, int, 0444);
353
MODULE_PARM_DESC(edac_op_state, "EDAC Error Reporting state: 0=Poll,1=NMI");
354
355