1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18#include <linux/module.h>
19#include <linux/init.h>
20#include <linux/pci.h>
21#include <linux/pci_ids.h>
22#include <linux/edac.h>
23#include "edac_module.h"
24
25#define EDAC_MOD_STR "r82600_edac"
26
27#define r82600_printk(level, fmt, arg...) \
28 edac_printk(level, "r82600", fmt, ##arg)
29
30#define r82600_mc_printk(mci, level, fmt, arg...) \
31 edac_mc_chipset_printk(mci, level, "r82600", fmt, ##arg)
32
33
34
35
36
37
38
39
40
41
42
43#define R82600_NR_CSROWS 4
44#define R82600_NR_CHANS 1
45#define R82600_NR_DIMMS 4
46
47#define R82600_BRIDGE_ID 0x8200
48
49
50#define R82600_DRAMC 0x57
51
52
53
54
55
56
57
58
59
60
61
62
63
64#define R82600_SDRAMC 0x76
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88#define R82600_EAP 0x80
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122#define R82600_DRBA 0x60
123
124
125
126
127
128
129struct r82600_error_info {
130 u32 eapr;
131};
132
133static bool disable_hardware_scrub;
134
135static struct edac_pci_ctl_info *r82600_pci;
136
137static void r82600_get_error_info(struct mem_ctl_info *mci,
138 struct r82600_error_info *info)
139{
140 struct pci_dev *pdev;
141
142 pdev = to_pci_dev(mci->pdev);
143 pci_read_config_dword(pdev, R82600_EAP, &info->eapr);
144
145 if (info->eapr & BIT(0))
146
147 pci_write_bits32(pdev, R82600_EAP,
148 ((u32) BIT(0) & (u32) BIT(1)),
149 ((u32) BIT(0) & (u32) BIT(1)));
150
151 if (info->eapr & BIT(1))
152
153 pci_write_bits32(pdev, R82600_EAP,
154 ((u32) BIT(0) & (u32) BIT(1)),
155 ((u32) BIT(0) & (u32) BIT(1)));
156}
157
158static int r82600_process_error_info(struct mem_ctl_info *mci,
159 struct r82600_error_info *info,
160 int handle_errors)
161{
162 int error_found;
163 u32 eapaddr, page;
164 u32 syndrome;
165
166 error_found = 0;
167
168
169 eapaddr = ((info->eapr >> 12) & 0x7FFF) << 13;
170
171 syndrome = (info->eapr >> 4) & 0xFF;
172
173
174
175 page = eapaddr >> PAGE_SHIFT;
176
177 if (info->eapr & BIT(0)) {
178 error_found = 1;
179
180 if (handle_errors)
181 edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1,
182 page, 0, syndrome,
183 edac_mc_find_csrow_by_page(mci, page),
184 0, -1,
185 mci->ctl_name, "");
186 }
187
188 if (info->eapr & BIT(1)) {
189 error_found = 1;
190
191 if (handle_errors)
192
193 edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1,
194 page, 0, 0,
195 edac_mc_find_csrow_by_page(mci, page),
196 0, -1,
197 mci->ctl_name, "");
198 }
199
200 return error_found;
201}
202
203static void r82600_check(struct mem_ctl_info *mci)
204{
205 struct r82600_error_info info;
206
207 r82600_get_error_info(mci, &info);
208 r82600_process_error_info(mci, &info, 1);
209}
210
211static inline int ecc_enabled(u8 dramcr)
212{
213 return dramcr & BIT(5);
214}
215
216static void r82600_init_csrows(struct mem_ctl_info *mci, struct pci_dev *pdev,
217 u8 dramcr)
218{
219 struct csrow_info *csrow;
220 struct dimm_info *dimm;
221 int index;
222 u8 drbar;
223 u32 row_high_limit, row_high_limit_last;
224 u32 reg_sdram, ecc_on, row_base;
225
226 ecc_on = ecc_enabled(dramcr);
227 reg_sdram = dramcr & BIT(4);
228 row_high_limit_last = 0;
229
230 for (index = 0; index < mci->nr_csrows; index++) {
231 csrow = mci->csrows[index];
232 dimm = csrow->channels[0]->dimm;
233
234
235 pci_read_config_byte(pdev, R82600_DRBA + index, &drbar);
236
237 edac_dbg(1, "Row=%d DRBA = %#0x\n", index, drbar);
238
239 row_high_limit = ((u32) drbar << 24);
240
241
242 edac_dbg(1, "Row=%d, Boundary Address=%#0x, Last = %#0x\n",
243 index, row_high_limit, row_high_limit_last);
244
245
246 if (row_high_limit == row_high_limit_last)
247 continue;
248
249 row_base = row_high_limit_last;
250
251 csrow->first_page = row_base >> PAGE_SHIFT;
252 csrow->last_page = (row_high_limit >> PAGE_SHIFT) - 1;
253
254 dimm->nr_pages = csrow->last_page - csrow->first_page + 1;
255
256
257 dimm->grain = 1 << 14;
258 dimm->mtype = reg_sdram ? MEM_RDDR : MEM_DDR;
259
260 dimm->dtype = DEV_UNKNOWN;
261
262
263 dimm->edac_mode = ecc_on ? EDAC_SECDED : EDAC_NONE;
264 row_high_limit_last = row_high_limit;
265 }
266}
267
268static int r82600_probe1(struct pci_dev *pdev, int dev_idx)
269{
270 struct mem_ctl_info *mci;
271 struct edac_mc_layer layers[2];
272 u8 dramcr;
273 u32 eapr;
274 u32 scrub_disabled;
275 u32 sdram_refresh_rate;
276 struct r82600_error_info discard;
277
278 edac_dbg(0, "\n");
279 pci_read_config_byte(pdev, R82600_DRAMC, &dramcr);
280 pci_read_config_dword(pdev, R82600_EAP, &eapr);
281 scrub_disabled = eapr & BIT(31);
282 sdram_refresh_rate = dramcr & (BIT(0) | BIT(1));
283 edac_dbg(2, "sdram refresh rate = %#0x\n", sdram_refresh_rate);
284 edac_dbg(2, "DRAMC register = %#0x\n", dramcr);
285 layers[0].type = EDAC_MC_LAYER_CHIP_SELECT;
286 layers[0].size = R82600_NR_CSROWS;
287 layers[0].is_virt_csrow = true;
288 layers[1].type = EDAC_MC_LAYER_CHANNEL;
289 layers[1].size = R82600_NR_CHANS;
290 layers[1].is_virt_csrow = false;
291 mci = edac_mc_alloc(0, ARRAY_SIZE(layers), layers, 0);
292 if (mci == NULL)
293 return -ENOMEM;
294
295 edac_dbg(0, "mci = %p\n", mci);
296 mci->pdev = &pdev->dev;
297 mci->mtype_cap = MEM_FLAG_RDDR | MEM_FLAG_DDR;
298 mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_EC | EDAC_FLAG_SECDED;
299
300
301
302
303
304
305
306
307 mci->edac_cap = EDAC_FLAG_NONE | EDAC_FLAG_EC | EDAC_FLAG_SECDED;
308
309 if (ecc_enabled(dramcr)) {
310 if (scrub_disabled)
311 edac_dbg(3, "mci = %p - Scrubbing disabled! EAP: %#0x\n",
312 mci, eapr);
313 } else
314 mci->edac_cap = EDAC_FLAG_NONE;
315
316 mci->mod_name = EDAC_MOD_STR;
317 mci->ctl_name = "R82600";
318 mci->dev_name = pci_name(pdev);
319 mci->edac_check = r82600_check;
320 mci->ctl_page_to_phys = NULL;
321 r82600_init_csrows(mci, pdev, dramcr);
322 r82600_get_error_info(mci, &discard);
323
324
325
326
327 if (edac_mc_add_mc(mci)) {
328 edac_dbg(3, "failed edac_mc_add_mc()\n");
329 goto fail;
330 }
331
332
333
334 if (disable_hardware_scrub) {
335 edac_dbg(3, "Disabling Hardware Scrub (scrub on error)\n");
336 pci_write_bits32(pdev, R82600_EAP, BIT(31), BIT(31));
337 }
338
339
340 r82600_pci = edac_pci_create_generic_ctl(&pdev->dev, EDAC_MOD_STR);
341 if (!r82600_pci) {
342 printk(KERN_WARNING
343 "%s(): Unable to create PCI control\n",
344 __func__);
345 printk(KERN_WARNING
346 "%s(): PCI error report via EDAC not setup\n",
347 __func__);
348 }
349
350 edac_dbg(3, "success\n");
351 return 0;
352
353fail:
354 edac_mc_free(mci);
355 return -ENODEV;
356}
357
358
359static int r82600_init_one(struct pci_dev *pdev,
360 const struct pci_device_id *ent)
361{
362 edac_dbg(0, "\n");
363
364
365 return r82600_probe1(pdev, ent->driver_data);
366}
367
368static void r82600_remove_one(struct pci_dev *pdev)
369{
370 struct mem_ctl_info *mci;
371
372 edac_dbg(0, "\n");
373
374 if (r82600_pci)
375 edac_pci_release_generic_ctl(r82600_pci);
376
377 if ((mci = edac_mc_del_mc(&pdev->dev)) == NULL)
378 return;
379
380 edac_mc_free(mci);
381}
382
383static const struct pci_device_id r82600_pci_tbl[] = {
384 {
385 PCI_DEVICE(PCI_VENDOR_ID_RADISYS, R82600_BRIDGE_ID)
386 },
387 {
388 0,
389 }
390};
391
392MODULE_DEVICE_TABLE(pci, r82600_pci_tbl);
393
394static struct pci_driver r82600_driver = {
395 .name = EDAC_MOD_STR,
396 .probe = r82600_init_one,
397 .remove = r82600_remove_one,
398 .id_table = r82600_pci_tbl,
399};
400
401static int __init r82600_init(void)
402{
403
404 opstate_init();
405
406 return pci_register_driver(&r82600_driver);
407}
408
409static void __exit r82600_exit(void)
410{
411 pci_unregister_driver(&r82600_driver);
412}
413
414module_init(r82600_init);
415module_exit(r82600_exit);
416
417MODULE_LICENSE("GPL");
418MODULE_AUTHOR("Tim Small <tim@buttersideup.com> - WPAD Ltd. "
419 "on behalf of EADS Astrium");
420MODULE_DESCRIPTION("MC support for Radisys 82600 memory controllers");
421
422module_param(disable_hardware_scrub, bool, 0644);
423MODULE_PARM_DESC(disable_hardware_scrub,
424 "If set, disable the chipset's automatic scrub for CEs");
425
426module_param(edac_op_state, int, 0444);
427MODULE_PARM_DESC(edac_op_state, "EDAC Error Reporting state: 0=Poll,1=NMI");
428