aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/edac
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/edac')
-rw-r--r--drivers/edac/amd64_edac.c46
-rw-r--r--drivers/edac/i5100_edac.c252
2 files changed, 199 insertions, 99 deletions
diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c
index 5fdd6daa40ea..df5b68433f34 100644
--- a/drivers/edac/amd64_edac.c
+++ b/drivers/edac/amd64_edac.c
@@ -13,6 +13,8 @@ module_param(report_gart_errors, int, 0644);
13static int ecc_enable_override; 13static int ecc_enable_override;
14module_param(ecc_enable_override, int, 0644); 14module_param(ecc_enable_override, int, 0644);
15 15
16static struct msr *msrs;
17
16/* Lookup table for all possible MC control instances */ 18/* Lookup table for all possible MC control instances */
17struct amd64_pvt; 19struct amd64_pvt;
18static struct mem_ctl_info *mci_lookup[EDAC_MAX_NUMNODES]; 20static struct mem_ctl_info *mci_lookup[EDAC_MAX_NUMNODES];
@@ -2495,8 +2497,7 @@ static void get_cpus_on_this_dct_cpumask(struct cpumask *mask, int nid)
2495static bool amd64_nb_mce_bank_enabled_on_node(int nid) 2497static bool amd64_nb_mce_bank_enabled_on_node(int nid)
2496{ 2498{
2497 cpumask_var_t mask; 2499 cpumask_var_t mask;
2498 struct msr *msrs; 2500 int cpu, nbe;
2499 int cpu, nbe, idx = 0;
2500 bool ret = false; 2501 bool ret = false;
2501 2502
2502 if (!zalloc_cpumask_var(&mask, GFP_KERNEL)) { 2503 if (!zalloc_cpumask_var(&mask, GFP_KERNEL)) {
@@ -2507,32 +2508,22 @@ static bool amd64_nb_mce_bank_enabled_on_node(int nid)
2507 2508
2508 get_cpus_on_this_dct_cpumask(mask, nid); 2509 get_cpus_on_this_dct_cpumask(mask, nid);
2509 2510
2510 msrs = kzalloc(sizeof(struct msr) * cpumask_weight(mask), GFP_KERNEL);
2511 if (!msrs) {
2512 amd64_printk(KERN_WARNING, "%s: error allocating msrs\n",
2513 __func__);
2514 free_cpumask_var(mask);
2515 return false;
2516 }
2517
2518 rdmsr_on_cpus(mask, MSR_IA32_MCG_CTL, msrs); 2511 rdmsr_on_cpus(mask, MSR_IA32_MCG_CTL, msrs);
2519 2512
2520 for_each_cpu(cpu, mask) { 2513 for_each_cpu(cpu, mask) {
2521 nbe = msrs[idx].l & K8_MSR_MCGCTL_NBE; 2514 struct msr *reg = per_cpu_ptr(msrs, cpu);
2515 nbe = reg->l & K8_MSR_MCGCTL_NBE;
2522 2516
2523 debugf0("core: %u, MCG_CTL: 0x%llx, NB MSR is %s\n", 2517 debugf0("core: %u, MCG_CTL: 0x%llx, NB MSR is %s\n",
2524 cpu, msrs[idx].q, 2518 cpu, reg->q,
2525 (nbe ? "enabled" : "disabled")); 2519 (nbe ? "enabled" : "disabled"));
2526 2520
2527 if (!nbe) 2521 if (!nbe)
2528 goto out; 2522 goto out;
2529
2530 idx++;
2531 } 2523 }
2532 ret = true; 2524 ret = true;
2533 2525
2534out: 2526out:
2535 kfree(msrs);
2536 free_cpumask_var(mask); 2527 free_cpumask_var(mask);
2537 return ret; 2528 return ret;
2538} 2529}
@@ -2540,8 +2531,7 @@ out:
2540static int amd64_toggle_ecc_err_reporting(struct amd64_pvt *pvt, bool on) 2531static int amd64_toggle_ecc_err_reporting(struct amd64_pvt *pvt, bool on)
2541{ 2532{
2542 cpumask_var_t cmask; 2533 cpumask_var_t cmask;
2543 struct msr *msrs = NULL; 2534 int cpu;
2544 int cpu, idx = 0;
2545 2535
2546 if (!zalloc_cpumask_var(&cmask, GFP_KERNEL)) { 2536 if (!zalloc_cpumask_var(&cmask, GFP_KERNEL)) {
2547 amd64_printk(KERN_WARNING, "%s: error allocating mask\n", 2537 amd64_printk(KERN_WARNING, "%s: error allocating mask\n",
@@ -2551,34 +2541,27 @@ static int amd64_toggle_ecc_err_reporting(struct amd64_pvt *pvt, bool on)
2551 2541
2552 get_cpus_on_this_dct_cpumask(cmask, pvt->mc_node_id); 2542 get_cpus_on_this_dct_cpumask(cmask, pvt->mc_node_id);
2553 2543
2554 msrs = kzalloc(sizeof(struct msr) * cpumask_weight(cmask), GFP_KERNEL);
2555 if (!msrs) {
2556 amd64_printk(KERN_WARNING, "%s: error allocating msrs\n",
2557 __func__);
2558 return -ENOMEM;
2559 }
2560
2561 rdmsr_on_cpus(cmask, MSR_IA32_MCG_CTL, msrs); 2544 rdmsr_on_cpus(cmask, MSR_IA32_MCG_CTL, msrs);
2562 2545
2563 for_each_cpu(cpu, cmask) { 2546 for_each_cpu(cpu, cmask) {
2564 2547
2548 struct msr *reg = per_cpu_ptr(msrs, cpu);
2549
2565 if (on) { 2550 if (on) {
2566 if (msrs[idx].l & K8_MSR_MCGCTL_NBE) 2551 if (reg->l & K8_MSR_MCGCTL_NBE)
2567 pvt->flags.ecc_report = 1; 2552 pvt->flags.ecc_report = 1;
2568 2553
2569 msrs[idx].l |= K8_MSR_MCGCTL_NBE; 2554 reg->l |= K8_MSR_MCGCTL_NBE;
2570 } else { 2555 } else {
2571 /* 2556 /*
2572 * Turn off ECC reporting only when it was off before 2557 * Turn off ECC reporting only when it was off before
2573 */ 2558 */
2574 if (!pvt->flags.ecc_report) 2559 if (!pvt->flags.ecc_report)
2575 msrs[idx].l &= ~K8_MSR_MCGCTL_NBE; 2560 reg->l &= ~K8_MSR_MCGCTL_NBE;
2576 } 2561 }
2577 idx++;
2578 } 2562 }
2579 wrmsr_on_cpus(cmask, MSR_IA32_MCG_CTL, msrs); 2563 wrmsr_on_cpus(cmask, MSR_IA32_MCG_CTL, msrs);
2580 2564
2581 kfree(msrs);
2582 free_cpumask_var(cmask); 2565 free_cpumask_var(cmask);
2583 2566
2584 return 0; 2567 return 0;
@@ -3036,6 +3019,8 @@ static int __init amd64_edac_init(void)
3036 if (cache_k8_northbridges() < 0) 3019 if (cache_k8_northbridges() < 0)
3037 return err; 3020 return err;
3038 3021
3022 msrs = msrs_alloc();
3023
3039 err = pci_register_driver(&amd64_pci_driver); 3024 err = pci_register_driver(&amd64_pci_driver);
3040 if (err) 3025 if (err)
3041 return err; 3026 return err;
@@ -3071,6 +3056,9 @@ static void __exit amd64_edac_exit(void)
3071 edac_pci_release_generic_ctl(amd64_ctl_pci); 3056 edac_pci_release_generic_ctl(amd64_ctl_pci);
3072 3057
3073 pci_unregister_driver(&amd64_pci_driver); 3058 pci_unregister_driver(&amd64_pci_driver);
3059
3060 msrs_free(msrs);
3061 msrs = NULL;
3074} 3062}
3075 3063
3076module_init(amd64_edac_init); 3064module_init(amd64_edac_init);
diff --git a/drivers/edac/i5100_edac.c b/drivers/edac/i5100_edac.c
index 22db05a67bfb..7785d8ffa404 100644
--- a/drivers/edac/i5100_edac.c
+++ b/drivers/edac/i5100_edac.c
@@ -9,6 +9,11 @@
9 * Intel 5100X Chipset Memory Controller Hub (MCH) - Datasheet 9 * Intel 5100X Chipset Memory Controller Hub (MCH) - Datasheet
10 * http://download.intel.com/design/chipsets/datashts/318378.pdf 10 * http://download.intel.com/design/chipsets/datashts/318378.pdf
11 * 11 *
12 * The intel 5100 has two independent channels. EDAC core currently
13 * can not reflect this configuration so instead the chip-select
14 * rows for each respective channel are layed out one after another,
15 * the first half belonging to channel 0, the second half belonging
16 * to channel 1.
12 */ 17 */
13#include <linux/module.h> 18#include <linux/module.h>
14#include <linux/init.h> 19#include <linux/init.h>
@@ -25,6 +30,8 @@
25 30
26/* device 16, func 1 */ 31/* device 16, func 1 */
27#define I5100_MC 0x40 /* Memory Control Register */ 32#define I5100_MC 0x40 /* Memory Control Register */
33#define I5100_MC_SCRBEN_MASK (1 << 7)
34#define I5100_MC_SCRBDONE_MASK (1 << 4)
28#define I5100_MS 0x44 /* Memory Status Register */ 35#define I5100_MS 0x44 /* Memory Status Register */
29#define I5100_SPDDATA 0x48 /* Serial Presence Detect Status Reg */ 36#define I5100_SPDDATA 0x48 /* Serial Presence Detect Status Reg */
30#define I5100_SPDCMD 0x4c /* Serial Presence Detect Command Reg */ 37#define I5100_SPDCMD 0x4c /* Serial Presence Detect Command Reg */
@@ -72,11 +79,21 @@
72 79
73/* bit field accessors */ 80/* bit field accessors */
74 81
82static inline u32 i5100_mc_scrben(u32 mc)
83{
84 return mc >> 7 & 1;
85}
86
75static inline u32 i5100_mc_errdeten(u32 mc) 87static inline u32 i5100_mc_errdeten(u32 mc)
76{ 88{
77 return mc >> 5 & 1; 89 return mc >> 5 & 1;
78} 90}
79 91
92static inline u32 i5100_mc_scrbdone(u32 mc)
93{
94 return mc >> 4 & 1;
95}
96
80static inline u16 i5100_spddata_rdo(u16 a) 97static inline u16 i5100_spddata_rdo(u16 a)
81{ 98{
82 return a >> 15 & 1; 99 return a >> 15 & 1;
@@ -265,42 +282,43 @@ static inline u32 i5100_recmemb_ras(u32 a)
265} 282}
266 283
267/* some generic limits */ 284/* some generic limits */
268#define I5100_MAX_RANKS_PER_CTLR 6 285#define I5100_MAX_RANKS_PER_CHAN 6
269#define I5100_MAX_CTLRS 2 286#define I5100_CHANNELS 2
270#define I5100_MAX_RANKS_PER_DIMM 4 287#define I5100_MAX_RANKS_PER_DIMM 4
271#define I5100_DIMM_ADDR_LINES (6 - 3) /* 64 bits / 8 bits per byte */ 288#define I5100_DIMM_ADDR_LINES (6 - 3) /* 64 bits / 8 bits per byte */
272#define I5100_MAX_DIMM_SLOTS_PER_CTLR 4 289#define I5100_MAX_DIMM_SLOTS_PER_CHAN 4
273#define I5100_MAX_RANK_INTERLEAVE 4 290#define I5100_MAX_RANK_INTERLEAVE 4
274#define I5100_MAX_DMIRS 5 291#define I5100_MAX_DMIRS 5
292#define I5100_SCRUB_REFRESH_RATE (5 * 60 * HZ)
275 293
276struct i5100_priv { 294struct i5100_priv {
277 /* ranks on each dimm -- 0 maps to not present -- obtained via SPD */ 295 /* ranks on each dimm -- 0 maps to not present -- obtained via SPD */
278 int dimm_numrank[I5100_MAX_CTLRS][I5100_MAX_DIMM_SLOTS_PER_CTLR]; 296 int dimm_numrank[I5100_CHANNELS][I5100_MAX_DIMM_SLOTS_PER_CHAN];
279 297
280 /* 298 /*
281 * mainboard chip select map -- maps i5100 chip selects to 299 * mainboard chip select map -- maps i5100 chip selects to
282 * DIMM slot chip selects. In the case of only 4 ranks per 300 * DIMM slot chip selects. In the case of only 4 ranks per
283 * controller, the mapping is fairly obvious but not unique. 301 * channel, the mapping is fairly obvious but not unique.
284 * we map -1 -> NC and assume both controllers use the same 302 * we map -1 -> NC and assume both channels use the same
285 * map... 303 * map...
286 * 304 *
287 */ 305 */
288 int dimm_csmap[I5100_MAX_DIMM_SLOTS_PER_CTLR][I5100_MAX_RANKS_PER_DIMM]; 306 int dimm_csmap[I5100_MAX_DIMM_SLOTS_PER_CHAN][I5100_MAX_RANKS_PER_DIMM];
289 307
290 /* memory interleave range */ 308 /* memory interleave range */
291 struct { 309 struct {
292 u64 limit; 310 u64 limit;
293 unsigned way[2]; 311 unsigned way[2];
294 } mir[I5100_MAX_CTLRS]; 312 } mir[I5100_CHANNELS];
295 313
296 /* adjusted memory interleave range register */ 314 /* adjusted memory interleave range register */
297 unsigned amir[I5100_MAX_CTLRS]; 315 unsigned amir[I5100_CHANNELS];
298 316
299 /* dimm interleave range */ 317 /* dimm interleave range */
300 struct { 318 struct {
301 unsigned rank[I5100_MAX_RANK_INTERLEAVE]; 319 unsigned rank[I5100_MAX_RANK_INTERLEAVE];
302 u64 limit; 320 u64 limit;
303 } dmir[I5100_MAX_CTLRS][I5100_MAX_DMIRS]; 321 } dmir[I5100_CHANNELS][I5100_MAX_DMIRS];
304 322
305 /* memory technology registers... */ 323 /* memory technology registers... */
306 struct { 324 struct {
@@ -310,30 +328,33 @@ struct i5100_priv {
310 unsigned numbank; /* 2 or 3 lines */ 328 unsigned numbank; /* 2 or 3 lines */
311 unsigned numrow; /* 13 .. 16 lines */ 329 unsigned numrow; /* 13 .. 16 lines */
312 unsigned numcol; /* 11 .. 12 lines */ 330 unsigned numcol; /* 11 .. 12 lines */
313 } mtr[I5100_MAX_CTLRS][I5100_MAX_RANKS_PER_CTLR]; 331 } mtr[I5100_CHANNELS][I5100_MAX_RANKS_PER_CHAN];
314 332
315 u64 tolm; /* top of low memory in bytes */ 333 u64 tolm; /* top of low memory in bytes */
316 unsigned ranksperctlr; /* number of ranks per controller */ 334 unsigned ranksperchan; /* number of ranks per channel */
317 335
318 struct pci_dev *mc; /* device 16 func 1 */ 336 struct pci_dev *mc; /* device 16 func 1 */
319 struct pci_dev *ch0mm; /* device 21 func 0 */ 337 struct pci_dev *ch0mm; /* device 21 func 0 */
320 struct pci_dev *ch1mm; /* device 22 func 0 */ 338 struct pci_dev *ch1mm; /* device 22 func 0 */
339
340 struct delayed_work i5100_scrubbing;
341 int scrub_enable;
321}; 342};
322 343
323/* map a rank/ctlr to a slot number on the mainboard */ 344/* map a rank/chan to a slot number on the mainboard */
324static int i5100_rank_to_slot(const struct mem_ctl_info *mci, 345static int i5100_rank_to_slot(const struct mem_ctl_info *mci,
325 int ctlr, int rank) 346 int chan, int rank)
326{ 347{
327 const struct i5100_priv *priv = mci->pvt_info; 348 const struct i5100_priv *priv = mci->pvt_info;
328 int i; 349 int i;
329 350
330 for (i = 0; i < I5100_MAX_DIMM_SLOTS_PER_CTLR; i++) { 351 for (i = 0; i < I5100_MAX_DIMM_SLOTS_PER_CHAN; i++) {
331 int j; 352 int j;
332 const int numrank = priv->dimm_numrank[ctlr][i]; 353 const int numrank = priv->dimm_numrank[chan][i];
333 354
334 for (j = 0; j < numrank; j++) 355 for (j = 0; j < numrank; j++)
335 if (priv->dimm_csmap[i][j] == rank) 356 if (priv->dimm_csmap[i][j] == rank)
336 return i * 2 + ctlr; 357 return i * 2 + chan;
337 } 358 }
338 359
339 return -1; 360 return -1;
@@ -374,32 +395,32 @@ static const char *i5100_err_msg(unsigned err)
374 return "none"; 395 return "none";
375} 396}
376 397
377/* convert csrow index into a rank (per controller -- 0..5) */ 398/* convert csrow index into a rank (per channel -- 0..5) */
378static int i5100_csrow_to_rank(const struct mem_ctl_info *mci, int csrow) 399static int i5100_csrow_to_rank(const struct mem_ctl_info *mci, int csrow)
379{ 400{
380 const struct i5100_priv *priv = mci->pvt_info; 401 const struct i5100_priv *priv = mci->pvt_info;
381 402
382 return csrow % priv->ranksperctlr; 403 return csrow % priv->ranksperchan;
383} 404}
384 405
385/* convert csrow index into a controller (0..1) */ 406/* convert csrow index into a channel (0..1) */
386static int i5100_csrow_to_cntlr(const struct mem_ctl_info *mci, int csrow) 407static int i5100_csrow_to_chan(const struct mem_ctl_info *mci, int csrow)
387{ 408{
388 const struct i5100_priv *priv = mci->pvt_info; 409 const struct i5100_priv *priv = mci->pvt_info;
389 410
390 return csrow / priv->ranksperctlr; 411 return csrow / priv->ranksperchan;
391} 412}
392 413
393static unsigned i5100_rank_to_csrow(const struct mem_ctl_info *mci, 414static unsigned i5100_rank_to_csrow(const struct mem_ctl_info *mci,
394 int ctlr, int rank) 415 int chan, int rank)
395{ 416{
396 const struct i5100_priv *priv = mci->pvt_info; 417 const struct i5100_priv *priv = mci->pvt_info;
397 418
398 return ctlr * priv->ranksperctlr + rank; 419 return chan * priv->ranksperchan + rank;
399} 420}
400 421
401static void i5100_handle_ce(struct mem_ctl_info *mci, 422static void i5100_handle_ce(struct mem_ctl_info *mci,
402 int ctlr, 423 int chan,
403 unsigned bank, 424 unsigned bank,
404 unsigned rank, 425 unsigned rank,
405 unsigned long syndrome, 426 unsigned long syndrome,
@@ -407,12 +428,12 @@ static void i5100_handle_ce(struct mem_ctl_info *mci,
407 unsigned ras, 428 unsigned ras,
408 const char *msg) 429 const char *msg)
409{ 430{
410 const int csrow = i5100_rank_to_csrow(mci, ctlr, rank); 431 const int csrow = i5100_rank_to_csrow(mci, chan, rank);
411 432
412 printk(KERN_ERR 433 printk(KERN_ERR
413 "CE ctlr %d, bank %u, rank %u, syndrome 0x%lx, " 434 "CE chan %d, bank %u, rank %u, syndrome 0x%lx, "
414 "cas %u, ras %u, csrow %u, label \"%s\": %s\n", 435 "cas %u, ras %u, csrow %u, label \"%s\": %s\n",
415 ctlr, bank, rank, syndrome, cas, ras, 436 chan, bank, rank, syndrome, cas, ras,
416 csrow, mci->csrows[csrow].channels[0].label, msg); 437 csrow, mci->csrows[csrow].channels[0].label, msg);
417 438
418 mci->ce_count++; 439 mci->ce_count++;
@@ -421,7 +442,7 @@ static void i5100_handle_ce(struct mem_ctl_info *mci,
421} 442}
422 443
423static void i5100_handle_ue(struct mem_ctl_info *mci, 444static void i5100_handle_ue(struct mem_ctl_info *mci,
424 int ctlr, 445 int chan,
425 unsigned bank, 446 unsigned bank,
426 unsigned rank, 447 unsigned rank,
427 unsigned long syndrome, 448 unsigned long syndrome,
@@ -429,23 +450,23 @@ static void i5100_handle_ue(struct mem_ctl_info *mci,
429 unsigned ras, 450 unsigned ras,
430 const char *msg) 451 const char *msg)
431{ 452{
432 const int csrow = i5100_rank_to_csrow(mci, ctlr, rank); 453 const int csrow = i5100_rank_to_csrow(mci, chan, rank);
433 454
434 printk(KERN_ERR 455 printk(KERN_ERR
435 "UE ctlr %d, bank %u, rank %u, syndrome 0x%lx, " 456 "UE chan %d, bank %u, rank %u, syndrome 0x%lx, "
436 "cas %u, ras %u, csrow %u, label \"%s\": %s\n", 457 "cas %u, ras %u, csrow %u, label \"%s\": %s\n",
437 ctlr, bank, rank, syndrome, cas, ras, 458 chan, bank, rank, syndrome, cas, ras,
438 csrow, mci->csrows[csrow].channels[0].label, msg); 459 csrow, mci->csrows[csrow].channels[0].label, msg);
439 460
440 mci->ue_count++; 461 mci->ue_count++;
441 mci->csrows[csrow].ue_count++; 462 mci->csrows[csrow].ue_count++;
442} 463}
443 464
444static void i5100_read_log(struct mem_ctl_info *mci, int ctlr, 465static void i5100_read_log(struct mem_ctl_info *mci, int chan,
445 u32 ferr, u32 nerr) 466 u32 ferr, u32 nerr)
446{ 467{
447 struct i5100_priv *priv = mci->pvt_info; 468 struct i5100_priv *priv = mci->pvt_info;
448 struct pci_dev *pdev = (ctlr) ? priv->ch1mm : priv->ch0mm; 469 struct pci_dev *pdev = (chan) ? priv->ch1mm : priv->ch0mm;
449 u32 dw; 470 u32 dw;
450 u32 dw2; 471 u32 dw2;
451 unsigned syndrome = 0; 472 unsigned syndrome = 0;
@@ -484,7 +505,7 @@ static void i5100_read_log(struct mem_ctl_info *mci, int ctlr,
484 else 505 else
485 msg = i5100_err_msg(nerr); 506 msg = i5100_err_msg(nerr);
486 507
487 i5100_handle_ce(mci, ctlr, bank, rank, syndrome, cas, ras, msg); 508 i5100_handle_ce(mci, chan, bank, rank, syndrome, cas, ras, msg);
488 } 509 }
489 510
490 if (i5100_validlog_nrecmemvalid(dw)) { 511 if (i5100_validlog_nrecmemvalid(dw)) {
@@ -506,7 +527,7 @@ static void i5100_read_log(struct mem_ctl_info *mci, int ctlr,
506 else 527 else
507 msg = i5100_err_msg(nerr); 528 msg = i5100_err_msg(nerr);
508 529
509 i5100_handle_ue(mci, ctlr, bank, rank, syndrome, cas, ras, msg); 530 i5100_handle_ue(mci, chan, bank, rank, syndrome, cas, ras, msg);
510 } 531 }
511 532
512 pci_write_config_dword(pdev, I5100_VALIDLOG, dw); 533 pci_write_config_dword(pdev, I5100_VALIDLOG, dw);
@@ -534,6 +555,80 @@ static void i5100_check_error(struct mem_ctl_info *mci)
534 } 555 }
535} 556}
536 557
558/* The i5100 chipset will scrub the entire memory once, then
559 * set a done bit. Continuous scrubbing is achieved by enqueing
560 * delayed work to a workqueue, checking every few minutes if
561 * the scrubbing has completed and if so reinitiating it.
562 */
563
564static void i5100_refresh_scrubbing(struct work_struct *work)
565{
566 struct delayed_work *i5100_scrubbing = container_of(work,
567 struct delayed_work,
568 work);
569 struct i5100_priv *priv = container_of(i5100_scrubbing,
570 struct i5100_priv,
571 i5100_scrubbing);
572 u32 dw;
573
574 pci_read_config_dword(priv->mc, I5100_MC, &dw);
575
576 if (priv->scrub_enable) {
577
578 pci_read_config_dword(priv->mc, I5100_MC, &dw);
579
580 if (i5100_mc_scrbdone(dw)) {
581 dw |= I5100_MC_SCRBEN_MASK;
582 pci_write_config_dword(priv->mc, I5100_MC, dw);
583 pci_read_config_dword(priv->mc, I5100_MC, &dw);
584 }
585
586 schedule_delayed_work(&(priv->i5100_scrubbing),
587 I5100_SCRUB_REFRESH_RATE);
588 }
589}
590/*
591 * The bandwidth is based on experimentation, feel free to refine it.
592 */
593static int i5100_set_scrub_rate(struct mem_ctl_info *mci,
594 u32 *bandwidth)
595{
596 struct i5100_priv *priv = mci->pvt_info;
597 u32 dw;
598
599 pci_read_config_dword(priv->mc, I5100_MC, &dw);
600 if (*bandwidth) {
601 priv->scrub_enable = 1;
602 dw |= I5100_MC_SCRBEN_MASK;
603 schedule_delayed_work(&(priv->i5100_scrubbing),
604 I5100_SCRUB_REFRESH_RATE);
605 } else {
606 priv->scrub_enable = 0;
607 dw &= ~I5100_MC_SCRBEN_MASK;
608 cancel_delayed_work(&(priv->i5100_scrubbing));
609 }
610 pci_write_config_dword(priv->mc, I5100_MC, dw);
611
612 pci_read_config_dword(priv->mc, I5100_MC, &dw);
613
614 *bandwidth = 5900000 * i5100_mc_scrben(dw);
615
616 return 0;
617}
618
619static int i5100_get_scrub_rate(struct mem_ctl_info *mci,
620 u32 *bandwidth)
621{
622 struct i5100_priv *priv = mci->pvt_info;
623 u32 dw;
624
625 pci_read_config_dword(priv->mc, I5100_MC, &dw);
626
627 *bandwidth = 5900000 * i5100_mc_scrben(dw);
628
629 return 0;
630}
631
537static struct pci_dev *pci_get_device_func(unsigned vendor, 632static struct pci_dev *pci_get_device_func(unsigned vendor,
538 unsigned device, 633 unsigned device,
539 unsigned func) 634 unsigned func)
@@ -557,19 +652,19 @@ static unsigned long __devinit i5100_npages(struct mem_ctl_info *mci,
557 int csrow) 652 int csrow)
558{ 653{
559 struct i5100_priv *priv = mci->pvt_info; 654 struct i5100_priv *priv = mci->pvt_info;
560 const unsigned ctlr_rank = i5100_csrow_to_rank(mci, csrow); 655 const unsigned chan_rank = i5100_csrow_to_rank(mci, csrow);
561 const unsigned ctlr = i5100_csrow_to_cntlr(mci, csrow); 656 const unsigned chan = i5100_csrow_to_chan(mci, csrow);
562 unsigned addr_lines; 657 unsigned addr_lines;
563 658
564 /* dimm present? */ 659 /* dimm present? */
565 if (!priv->mtr[ctlr][ctlr_rank].present) 660 if (!priv->mtr[chan][chan_rank].present)
566 return 0ULL; 661 return 0ULL;
567 662
568 addr_lines = 663 addr_lines =
569 I5100_DIMM_ADDR_LINES + 664 I5100_DIMM_ADDR_LINES +
570 priv->mtr[ctlr][ctlr_rank].numcol + 665 priv->mtr[chan][chan_rank].numcol +
571 priv->mtr[ctlr][ctlr_rank].numrow + 666 priv->mtr[chan][chan_rank].numrow +
572 priv->mtr[ctlr][ctlr_rank].numbank; 667 priv->mtr[chan][chan_rank].numbank;
573 668
574 return (unsigned long) 669 return (unsigned long)
575 ((unsigned long long) (1ULL << addr_lines) / PAGE_SIZE); 670 ((unsigned long long) (1ULL << addr_lines) / PAGE_SIZE);
@@ -581,11 +676,11 @@ static void __devinit i5100_init_mtr(struct mem_ctl_info *mci)
581 struct pci_dev *mms[2] = { priv->ch0mm, priv->ch1mm }; 676 struct pci_dev *mms[2] = { priv->ch0mm, priv->ch1mm };
582 int i; 677 int i;
583 678
584 for (i = 0; i < I5100_MAX_CTLRS; i++) { 679 for (i = 0; i < I5100_CHANNELS; i++) {
585 int j; 680 int j;
586 struct pci_dev *pdev = mms[i]; 681 struct pci_dev *pdev = mms[i];
587 682
588 for (j = 0; j < I5100_MAX_RANKS_PER_CTLR; j++) { 683 for (j = 0; j < I5100_MAX_RANKS_PER_CHAN; j++) {
589 const unsigned addr = 684 const unsigned addr =
590 (j < 4) ? I5100_MTR_0 + j * 2 : 685 (j < 4) ? I5100_MTR_0 + j * 2 :
591 I5100_MTR_4 + (j - 4) * 2; 686 I5100_MTR_4 + (j - 4) * 2;
@@ -644,7 +739,6 @@ static int i5100_read_spd_byte(const struct mem_ctl_info *mci,
644 * fill dimm chip select map 739 * fill dimm chip select map
645 * 740 *
646 * FIXME: 741 * FIXME:
647 * o only valid for 4 ranks per controller
648 * o not the only way to may chip selects to dimm slots 742 * o not the only way to may chip selects to dimm slots
649 * o investigate if there is some way to obtain this map from the bios 743 * o investigate if there is some way to obtain this map from the bios
650 */ 744 */
@@ -653,9 +747,7 @@ static void __devinit i5100_init_dimm_csmap(struct mem_ctl_info *mci)
653 struct i5100_priv *priv = mci->pvt_info; 747 struct i5100_priv *priv = mci->pvt_info;
654 int i; 748 int i;
655 749
656 WARN_ON(priv->ranksperctlr != 4); 750 for (i = 0; i < I5100_MAX_DIMM_SLOTS_PER_CHAN; i++) {
657
658 for (i = 0; i < I5100_MAX_DIMM_SLOTS_PER_CTLR; i++) {
659 int j; 751 int j;
660 752
661 for (j = 0; j < I5100_MAX_RANKS_PER_DIMM; j++) 753 for (j = 0; j < I5100_MAX_RANKS_PER_DIMM; j++)
@@ -663,12 +755,21 @@ static void __devinit i5100_init_dimm_csmap(struct mem_ctl_info *mci)
663 } 755 }
664 756
665 /* only 2 chip selects per slot... */ 757 /* only 2 chip selects per slot... */
666 priv->dimm_csmap[0][0] = 0; 758 if (priv->ranksperchan == 4) {
667 priv->dimm_csmap[0][1] = 3; 759 priv->dimm_csmap[0][0] = 0;
668 priv->dimm_csmap[1][0] = 1; 760 priv->dimm_csmap[0][1] = 3;
669 priv->dimm_csmap[1][1] = 2; 761 priv->dimm_csmap[1][0] = 1;
670 priv->dimm_csmap[2][0] = 2; 762 priv->dimm_csmap[1][1] = 2;
671 priv->dimm_csmap[3][0] = 3; 763 priv->dimm_csmap[2][0] = 2;
764 priv->dimm_csmap[3][0] = 3;
765 } else {
766 priv->dimm_csmap[0][0] = 0;
767 priv->dimm_csmap[0][1] = 1;
768 priv->dimm_csmap[1][0] = 2;
769 priv->dimm_csmap[1][1] = 3;
770 priv->dimm_csmap[2][0] = 4;
771 priv->dimm_csmap[2][1] = 5;
772 }
672} 773}
673 774
674static void __devinit i5100_init_dimm_layout(struct pci_dev *pdev, 775static void __devinit i5100_init_dimm_layout(struct pci_dev *pdev,
@@ -677,10 +778,10 @@ static void __devinit i5100_init_dimm_layout(struct pci_dev *pdev,
677 struct i5100_priv *priv = mci->pvt_info; 778 struct i5100_priv *priv = mci->pvt_info;
678 int i; 779 int i;
679 780
680 for (i = 0; i < I5100_MAX_CTLRS; i++) { 781 for (i = 0; i < I5100_CHANNELS; i++) {
681 int j; 782 int j;
682 783
683 for (j = 0; j < I5100_MAX_DIMM_SLOTS_PER_CTLR; j++) { 784 for (j = 0; j < I5100_MAX_DIMM_SLOTS_PER_CHAN; j++) {
684 u8 rank; 785 u8 rank;
685 786
686 if (i5100_read_spd_byte(mci, i, j, 5, &rank) < 0) 787 if (i5100_read_spd_byte(mci, i, j, 5, &rank) < 0)
@@ -720,7 +821,7 @@ static void __devinit i5100_init_interleaving(struct pci_dev *pdev,
720 pci_read_config_word(pdev, I5100_AMIR_1, &w); 821 pci_read_config_word(pdev, I5100_AMIR_1, &w);
721 priv->amir[1] = w; 822 priv->amir[1] = w;
722 823
723 for (i = 0; i < I5100_MAX_CTLRS; i++) { 824 for (i = 0; i < I5100_CHANNELS; i++) {
724 int j; 825 int j;
725 826
726 for (j = 0; j < 5; j++) { 827 for (j = 0; j < 5; j++) {
@@ -747,7 +848,7 @@ static void __devinit i5100_init_csrows(struct mem_ctl_info *mci)
747 848
748 for (i = 0; i < mci->nr_csrows; i++) { 849 for (i = 0; i < mci->nr_csrows; i++) {
749 const unsigned long npages = i5100_npages(mci, i); 850 const unsigned long npages = i5100_npages(mci, i);
750 const unsigned cntlr = i5100_csrow_to_cntlr(mci, i); 851 const unsigned chan = i5100_csrow_to_chan(mci, i);
751 const unsigned rank = i5100_csrow_to_rank(mci, i); 852 const unsigned rank = i5100_csrow_to_rank(mci, i);
752 853
753 if (!npages) 854 if (!npages)
@@ -765,7 +866,7 @@ static void __devinit i5100_init_csrows(struct mem_ctl_info *mci)
765 mci->csrows[i].grain = 32; 866 mci->csrows[i].grain = 32;
766 mci->csrows[i].csrow_idx = i; 867 mci->csrows[i].csrow_idx = i;
767 mci->csrows[i].dtype = 868 mci->csrows[i].dtype =
768 (priv->mtr[cntlr][rank].width == 4) ? DEV_X4 : DEV_X8; 869 (priv->mtr[chan][rank].width == 4) ? DEV_X4 : DEV_X8;
769 mci->csrows[i].ue_count = 0; 870 mci->csrows[i].ue_count = 0;
770 mci->csrows[i].ce_count = 0; 871 mci->csrows[i].ce_count = 0;
771 mci->csrows[i].mtype = MEM_RDDR2; 872 mci->csrows[i].mtype = MEM_RDDR2;
@@ -777,7 +878,7 @@ static void __devinit i5100_init_csrows(struct mem_ctl_info *mci)
777 mci->csrows[i].channels[0].csrow = mci->csrows + i; 878 mci->csrows[i].channels[0].csrow = mci->csrows + i;
778 snprintf(mci->csrows[i].channels[0].label, 879 snprintf(mci->csrows[i].channels[0].label,
779 sizeof(mci->csrows[i].channels[0].label), 880 sizeof(mci->csrows[i].channels[0].label),
780 "DIMM%u", i5100_rank_to_slot(mci, cntlr, rank)); 881 "DIMM%u", i5100_rank_to_slot(mci, chan, rank));
781 882
782 total_pages += npages; 883 total_pages += npages;
783 } 884 }
@@ -815,13 +916,6 @@ static int __devinit i5100_init_one(struct pci_dev *pdev,
815 pci_read_config_dword(pdev, I5100_MS, &dw); 916 pci_read_config_dword(pdev, I5100_MS, &dw);
816 ranksperch = !!(dw & (1 << 8)) * 2 + 4; 917 ranksperch = !!(dw & (1 << 8)) * 2 + 4;
817 918
818 if (ranksperch != 4) {
819 /* FIXME: get 6 ranks / controller to work - need hw... */
820 printk(KERN_INFO "i5100_edac: unsupported configuration.\n");
821 ret = -ENODEV;
822 goto bail_pdev;
823 }
824
825 /* enable error reporting... */ 919 /* enable error reporting... */
826 pci_read_config_dword(pdev, I5100_EMASK_MEM, &dw); 920 pci_read_config_dword(pdev, I5100_EMASK_MEM, &dw);
827 dw &= ~I5100_FERR_NF_MEM_ANY_MASK; 921 dw &= ~I5100_FERR_NF_MEM_ANY_MASK;
@@ -864,11 +958,21 @@ static int __devinit i5100_init_one(struct pci_dev *pdev,
864 mci->dev = &pdev->dev; 958 mci->dev = &pdev->dev;
865 959
866 priv = mci->pvt_info; 960 priv = mci->pvt_info;
867 priv->ranksperctlr = ranksperch; 961 priv->ranksperchan = ranksperch;
868 priv->mc = pdev; 962 priv->mc = pdev;
869 priv->ch0mm = ch0mm; 963 priv->ch0mm = ch0mm;
870 priv->ch1mm = ch1mm; 964 priv->ch1mm = ch1mm;
871 965
966 INIT_DELAYED_WORK(&(priv->i5100_scrubbing), i5100_refresh_scrubbing);
967
968 /* If scrubbing was already enabled by the bios, start maintaining it */
969 pci_read_config_dword(pdev, I5100_MC, &dw);
970 if (i5100_mc_scrben(dw)) {
971 priv->scrub_enable = 1;
972 schedule_delayed_work(&(priv->i5100_scrubbing),
973 I5100_SCRUB_REFRESH_RATE);
974 }
975
872 i5100_init_dimm_layout(pdev, mci); 976 i5100_init_dimm_layout(pdev, mci);
873 i5100_init_interleaving(pdev, mci); 977 i5100_init_interleaving(pdev, mci);
874 978
@@ -882,6 +986,8 @@ static int __devinit i5100_init_one(struct pci_dev *pdev,
882 mci->ctl_page_to_phys = NULL; 986 mci->ctl_page_to_phys = NULL;
883 987
884 mci->edac_check = i5100_check_error; 988 mci->edac_check = i5100_check_error;
989 mci->set_sdram_scrub_rate = i5100_set_scrub_rate;
990 mci->get_sdram_scrub_rate = i5100_get_scrub_rate;
885 991
886 i5100_init_csrows(mci); 992 i5100_init_csrows(mci);
887 993
@@ -897,12 +1003,14 @@ static int __devinit i5100_init_one(struct pci_dev *pdev,
897 1003
898 if (edac_mc_add_mc(mci)) { 1004 if (edac_mc_add_mc(mci)) {
899 ret = -ENODEV; 1005 ret = -ENODEV;
900 goto bail_mc; 1006 goto bail_scrub;
901 } 1007 }
902 1008
903 return ret; 1009 return ret;
904 1010
905bail_mc: 1011bail_scrub:
1012 priv->scrub_enable = 0;
1013 cancel_delayed_work_sync(&(priv->i5100_scrubbing));
906 edac_mc_free(mci); 1014 edac_mc_free(mci);
907 1015
908bail_disable_ch1: 1016bail_disable_ch1:
@@ -935,6 +1043,10 @@ static void __devexit i5100_remove_one(struct pci_dev *pdev)
935 return; 1043 return;
936 1044
937 priv = mci->pvt_info; 1045 priv = mci->pvt_info;
1046
1047 priv->scrub_enable = 0;
1048 cancel_delayed_work_sync(&(priv->i5100_scrubbing));
1049
938 pci_disable_device(pdev); 1050 pci_disable_device(pdev);
939 pci_disable_device(priv->ch0mm); 1051 pci_disable_device(priv->ch0mm);
940 pci_disable_device(priv->ch1mm); 1052 pci_disable_device(priv->ch1mm);