aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBorislav Petkov <borislav.petkov@amd.com>2010-11-24 13:52:09 -0500
committerBorislav Petkov <borislav.petkov@amd.com>2011-01-07 05:38:31 -0500
commit390944439f746824faec51b576f50cb5ef18745b (patch)
tree5fd15e75e8e5e5d3dc1e176c655829f9d0f83aa9
parent360b7f3c602ed80ce8c6b2585dcb76883a440c17 (diff)
EDAC: Fixup scrubrate manipulation
Make the ->{get|set}_sdram_scrub_rate return the actual scrub rate bandwidth it succeeded setting and remove superfluous arg pointer used for that. A negative value returned still means that an error occurred while setting the scrubrate. Document this for future reference. Signed-off-by: Borislav Petkov <borislav.petkov@amd.com>
-rw-r--r--drivers/edac/amd64_edac.c24
-rw-r--r--drivers/edac/amd64_edac.h6
-rw-r--r--drivers/edac/cpc925_edac.c9
-rw-r--r--drivers/edac/e752x_edac.c8
-rw-r--r--drivers/edac/edac_core.h2
-rw-r--r--drivers/edac/edac_mc_sysfs.c57
-rw-r--r--drivers/edac/i5100_edac.c9
7 files changed, 52 insertions, 63 deletions
diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c
index f621aa8becee..8c176fb8a8fb 100644
--- a/drivers/edac/amd64_edac.c
+++ b/drivers/edac/amd64_edac.c
@@ -77,7 +77,11 @@ static int ddr3_dbam[] = { [0] = -1,
77 *FIXME: Produce a better mapping/linearisation. 77 *FIXME: Produce a better mapping/linearisation.
78 */ 78 */
79 79
80struct scrubrate scrubrates[] = { 80
81struct scrubrate {
82 u32 scrubval; /* bit pattern for scrub rate */
83 u32 bandwidth; /* bandwidth consumed (bytes/sec) */
84} scrubrates[] = {
81 { 0x01, 1600000000UL}, 85 { 0x01, 1600000000UL},
82 { 0x02, 800000000UL}, 86 { 0x02, 800000000UL},
83 { 0x03, 400000000UL}, 87 { 0x03, 400000000UL},
@@ -151,14 +155,12 @@ static int __amd64_set_scrub_rate(struct pci_dev *ctl, u32 new_bw, u32 min_rate)
151 } 155 }
152 156
153 scrubval = scrubrates[i].scrubval; 157 scrubval = scrubrates[i].scrubval;
154 if (scrubval)
155 amd64_info("Setting scrub rate bandwidth: %u\n",
156 scrubrates[i].bandwidth);
157 else
158 amd64_info("Turning scrubbing off.\n");
159 158
160 pci_write_bits32(ctl, K8_SCRCTRL, scrubval, 0x001F); 159 pci_write_bits32(ctl, K8_SCRCTRL, scrubval, 0x001F);
161 160
161 if (scrubval)
162 return scrubrates[i].bandwidth;
163
162 return 0; 164 return 0;
163} 165}
164 166
@@ -169,11 +171,11 @@ static int amd64_set_scrub_rate(struct mem_ctl_info *mci, u32 bw)
169 return __amd64_set_scrub_rate(pvt->F3, bw, pvt->min_scrubrate); 171 return __amd64_set_scrub_rate(pvt->F3, bw, pvt->min_scrubrate);
170} 172}
171 173
172static int amd64_get_scrub_rate(struct mem_ctl_info *mci, u32 *bw) 174static int amd64_get_scrub_rate(struct mem_ctl_info *mci)
173{ 175{
174 struct amd64_pvt *pvt = mci->pvt_info; 176 struct amd64_pvt *pvt = mci->pvt_info;
175 u32 scrubval = 0; 177 u32 scrubval = 0;
176 int status = -1, i; 178 int i, retval = -EINVAL;
177 179
178 amd64_read_pci_cfg(pvt->F3, K8_SCRCTRL, &scrubval); 180 amd64_read_pci_cfg(pvt->F3, K8_SCRCTRL, &scrubval);
179 181
@@ -183,13 +185,11 @@ static int amd64_get_scrub_rate(struct mem_ctl_info *mci, u32 *bw)
183 185
184 for (i = 0; i < ARRAY_SIZE(scrubrates); i++) { 186 for (i = 0; i < ARRAY_SIZE(scrubrates); i++) {
185 if (scrubrates[i].scrubval == scrubval) { 187 if (scrubrates[i].scrubval == scrubval) {
186 *bw = scrubrates[i].bandwidth; 188 retval = scrubrates[i].bandwidth;
187 status = 0;
188 break; 189 break;
189 } 190 }
190 } 191 }
191 192 return retval;
192 return status;
193} 193}
194 194
195/* Map from a CSROW entry to the mask entry that operates on it */ 195/* Map from a CSROW entry to the mask entry that operates on it */
diff --git a/drivers/edac/amd64_edac.h b/drivers/edac/amd64_edac.h
index b76dce96e8e6..613ec72b0f65 100644
--- a/drivers/edac/amd64_edac.h
+++ b/drivers/edac/amd64_edac.h
@@ -482,12 +482,6 @@ struct ecc_settings {
482 } flags; 482 } flags;
483}; 483};
484 484
485struct scrubrate {
486 u32 scrubval; /* bit pattern for scrub rate */
487 u32 bandwidth; /* bandwidth consumed (bytes/sec) */
488};
489
490extern struct scrubrate scrubrates[23];
491extern const char *tt_msgs[4]; 485extern const char *tt_msgs[4];
492extern const char *ll_msgs[4]; 486extern const char *ll_msgs[4];
493extern const char *rrrr_msgs[16]; 487extern const char *rrrr_msgs[16];
diff --git a/drivers/edac/cpc925_edac.c b/drivers/edac/cpc925_edac.c
index 1609a19df495..b9a781c47e3c 100644
--- a/drivers/edac/cpc925_edac.c
+++ b/drivers/edac/cpc925_edac.c
@@ -818,9 +818,10 @@ static void cpc925_del_edac_devices(void)
818} 818}
819 819
820/* Convert current back-ground scrub rate into byte/sec bandwith */ 820/* Convert current back-ground scrub rate into byte/sec bandwith */
821static int cpc925_get_sdram_scrub_rate(struct mem_ctl_info *mci, u32 *bw) 821static int cpc925_get_sdram_scrub_rate(struct mem_ctl_info *mci)
822{ 822{
823 struct cpc925_mc_pdata *pdata = mci->pvt_info; 823 struct cpc925_mc_pdata *pdata = mci->pvt_info;
824 int bw;
824 u32 mscr; 825 u32 mscr;
825 u8 si; 826 u8 si;
826 827
@@ -832,11 +833,11 @@ static int cpc925_get_sdram_scrub_rate(struct mem_ctl_info *mci, u32 *bw)
832 if (((mscr & MSCR_SCRUB_MOD_MASK) != MSCR_BACKGR_SCRUB) || 833 if (((mscr & MSCR_SCRUB_MOD_MASK) != MSCR_BACKGR_SCRUB) ||
833 (si == 0)) { 834 (si == 0)) {
834 cpc925_mc_printk(mci, KERN_INFO, "Scrub mode not enabled\n"); 835 cpc925_mc_printk(mci, KERN_INFO, "Scrub mode not enabled\n");
835 *bw = 0; 836 bw = 0;
836 } else 837 } else
837 *bw = CPC925_SCRUB_BLOCK_SIZE * 0xFA67 / si; 838 bw = CPC925_SCRUB_BLOCK_SIZE * 0xFA67 / si;
838 839
839 return 0; 840 return bw;
840} 841}
841 842
842/* Return 0 for single channel; 1 for dual channel */ 843/* Return 0 for single channel; 1 for dual channel */
diff --git a/drivers/edac/e752x_edac.c b/drivers/edac/e752x_edac.c
index 073f5a06d238..ec302d426589 100644
--- a/drivers/edac/e752x_edac.c
+++ b/drivers/edac/e752x_edac.c
@@ -983,11 +983,11 @@ static int set_sdram_scrub_rate(struct mem_ctl_info *mci, u32 new_bw)
983 983
984 pci_write_config_word(pdev, E752X_MCHSCRB, scrubrates[i].scrubval); 984 pci_write_config_word(pdev, E752X_MCHSCRB, scrubrates[i].scrubval);
985 985
986 return 0; 986 return scrubrates[i].bandwidth;
987} 987}
988 988
989/* Convert current scrub rate value into byte/sec bandwidth */ 989/* Convert current scrub rate value into byte/sec bandwidth */
990static int get_sdram_scrub_rate(struct mem_ctl_info *mci, u32 *bw) 990static int get_sdram_scrub_rate(struct mem_ctl_info *mci)
991{ 991{
992 const struct scrubrate *scrubrates; 992 const struct scrubrate *scrubrates;
993 struct e752x_pvt *pvt = (struct e752x_pvt *) mci->pvt_info; 993 struct e752x_pvt *pvt = (struct e752x_pvt *) mci->pvt_info;
@@ -1013,10 +1013,8 @@ static int get_sdram_scrub_rate(struct mem_ctl_info *mci, u32 *bw)
1013 "Invalid sdram scrub control value: 0x%x\n", scrubval); 1013 "Invalid sdram scrub control value: 0x%x\n", scrubval);
1014 return -1; 1014 return -1;
1015 } 1015 }
1016 return scrubrates[i].bandwidth;
1016 1017
1017 *bw = scrubrates[i].bandwidth;
1018
1019 return 0;
1020} 1018}
1021 1019
1022/* Return 1 if dual channel mode is active. Else return 0. */ 1020/* Return 1 if dual channel mode is active. Else return 0. */
diff --git a/drivers/edac/edac_core.h b/drivers/edac/edac_core.h
index e8d3dd0b5e9c..ff1eb7bb26c6 100644
--- a/drivers/edac/edac_core.h
+++ b/drivers/edac/edac_core.h
@@ -387,7 +387,7 @@ struct mem_ctl_info {
387 representation and converts it to the closest matching 387 representation and converts it to the closest matching
388 bandwith in bytes/sec. 388 bandwith in bytes/sec.
389 */ 389 */
390 int (*get_sdram_scrub_rate) (struct mem_ctl_info * mci, u32 * bw); 390 int (*get_sdram_scrub_rate) (struct mem_ctl_info * mci);
391 391
392 392
393 /* pointer to edac checking routine */ 393 /* pointer to edac checking routine */
diff --git a/drivers/edac/edac_mc_sysfs.c b/drivers/edac/edac_mc_sysfs.c
index dce61f7ba38b..39d97cfdf58c 100644
--- a/drivers/edac/edac_mc_sysfs.c
+++ b/drivers/edac/edac_mc_sysfs.c
@@ -436,56 +436,55 @@ static ssize_t mci_reset_counters_store(struct mem_ctl_info *mci,
436 return count; 436 return count;
437} 437}
438 438
439/* memory scrubbing */ 439/* Memory scrubbing interface:
440 *
441 * A MC driver can limit the scrubbing bandwidth based on the CPU type.
442 * Therefore, ->set_sdram_scrub_rate should be made to return the actual
443 * bandwidth that is accepted or 0 when scrubbing is to be disabled.
444 *
445 * Negative value still means that an error has occurred while setting
446 * the scrub rate.
447 */
440static ssize_t mci_sdram_scrub_rate_store(struct mem_ctl_info *mci, 448static ssize_t mci_sdram_scrub_rate_store(struct mem_ctl_info *mci,
441 const char *data, size_t count) 449 const char *data, size_t count)
442{ 450{
443 unsigned long bandwidth = 0; 451 unsigned long bandwidth = 0;
444 int err; 452 int new_bw = 0;
445 453
446 if (!mci->set_sdram_scrub_rate) { 454 if (!mci->set_sdram_scrub_rate)
447 edac_printk(KERN_WARNING, EDAC_MC,
448 "Memory scrub rate setting not implemented!\n");
449 return -EINVAL; 455 return -EINVAL;
450 }
451 456
452 if (strict_strtoul(data, 10, &bandwidth) < 0) 457 if (strict_strtoul(data, 10, &bandwidth) < 0)
453 return -EINVAL; 458 return -EINVAL;
454 459
455 err = mci->set_sdram_scrub_rate(mci, (u32)bandwidth); 460 new_bw = mci->set_sdram_scrub_rate(mci, bandwidth);
456 if (err) { 461 if (new_bw >= 0) {
457 edac_printk(KERN_DEBUG, EDAC_MC, 462 edac_printk(KERN_DEBUG, EDAC_MC, "Scrub rate set to %d\n", new_bw);
458 "Failed setting scrub rate to %lu\n", bandwidth);
459 return -EINVAL;
460 }
461 else {
462 edac_printk(KERN_DEBUG, EDAC_MC,
463 "Scrub rate set to: %lu\n", bandwidth);
464 return count; 463 return count;
465 } 464 }
465
466 edac_printk(KERN_DEBUG, EDAC_MC, "Error setting scrub rate to: %lu\n", bandwidth);
467 return -EINVAL;
466} 468}
467 469
470/*
471 * ->get_sdram_scrub_rate() return value semantics same as above.
472 */
468static ssize_t mci_sdram_scrub_rate_show(struct mem_ctl_info *mci, char *data) 473static ssize_t mci_sdram_scrub_rate_show(struct mem_ctl_info *mci, char *data)
469{ 474{
470 u32 bandwidth = 0; 475 int bandwidth = 0;
471 int err;
472 476
473 if (!mci->get_sdram_scrub_rate) { 477 if (!mci->get_sdram_scrub_rate)
474 edac_printk(KERN_WARNING, EDAC_MC,
475 "Memory scrub rate reading not implemented\n");
476 return -EINVAL; 478 return -EINVAL;
477 }
478 479
479 err = mci->get_sdram_scrub_rate(mci, &bandwidth); 480 bandwidth = mci->get_sdram_scrub_rate(mci);
480 if (err) { 481 if (bandwidth < 0) {
481 edac_printk(KERN_DEBUG, EDAC_MC, "Error reading scrub rate\n"); 482 edac_printk(KERN_DEBUG, EDAC_MC, "Error reading scrub rate\n");
482 return err; 483 return bandwidth;
483 }
484 else {
485 edac_printk(KERN_DEBUG, EDAC_MC,
486 "Read scrub rate: %d\n", bandwidth);
487 return sprintf(data, "%d\n", bandwidth);
488 } 484 }
485
486 edac_printk(KERN_DEBUG, EDAC_MC, "Read scrub rate: %d\n", bandwidth);
487 return sprintf(data, "%d\n", bandwidth);
489} 488}
490 489
491/* default attribute files for the MCI object */ 490/* default attribute files for the MCI object */
diff --git a/drivers/edac/i5100_edac.c b/drivers/edac/i5100_edac.c
index f459a6c0886b..0448da0af75d 100644
--- a/drivers/edac/i5100_edac.c
+++ b/drivers/edac/i5100_edac.c
@@ -611,20 +611,17 @@ static int i5100_set_scrub_rate(struct mem_ctl_info *mci, u32 bandwidth)
611 611
612 bandwidth = 5900000 * i5100_mc_scrben(dw); 612 bandwidth = 5900000 * i5100_mc_scrben(dw);
613 613
614 return 0; 614 return bandwidth;
615} 615}
616 616
617static int i5100_get_scrub_rate(struct mem_ctl_info *mci, 617static int i5100_get_scrub_rate(struct mem_ctl_info *mci)
618 u32 *bandwidth)
619{ 618{
620 struct i5100_priv *priv = mci->pvt_info; 619 struct i5100_priv *priv = mci->pvt_info;
621 u32 dw; 620 u32 dw;
622 621
623 pci_read_config_dword(priv->mc, I5100_MC, &dw); 622 pci_read_config_dword(priv->mc, I5100_MC, &dw);
624 623
625 *bandwidth = 5900000 * i5100_mc_scrben(dw); 624 return 5900000 * i5100_mc_scrben(dw);
626
627 return 0;
628} 625}
629 626
630static struct pci_dev *pci_get_device_func(unsigned vendor, 627static struct pci_dev *pci_get_device_func(unsigned vendor,