aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBorislav Petkov <borislav.petkov@amd.com>2010-05-25 12:21:07 -0400
committerBorislav Petkov <borislav.petkov@amd.com>2010-08-03 10:14:06 -0400
commiteba042a81edd6baaff44831b2d719b14a6d21e58 (patch)
treea1e768aadf18708114e2d6c4d4a54b3af49e42e9
parentbc57117856cf1e581135810b37d3b75f9d1749f5 (diff)
edac, mc: Improve scrub rate handling
Fortify the interface to not accept negative values, remove memctrl_int_store() as a result. Also, sanitize bandwidth setting by making the argument a simple u32 instead of strange u32 pointer being passed around for no obvious reason. Then, fix error handling and teach it to return proper error values. Finally, make code more readable, simplify debug messages. Cc: Mauro Carvalho Chehab <mchehab@redhat.com> Cc: Arthur Jones <ajones@riverbed.com> Signed-off-by: Borislav Petkov <borislav.petkov@amd.com> Acked-by: Doug Thompson <dougthompson@xmission.com>
-rw-r--r--drivers/edac/amd64_edac.c6
-rw-r--r--drivers/edac/e752x_edac.c4
-rw-r--r--drivers/edac/edac_core.h2
-rw-r--r--drivers/edac/edac_mc_sysfs.c86
-rw-r--r--drivers/edac/i5100_edac.c7
5 files changed, 46 insertions, 59 deletions
diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c
index cdf457925f03..0106d343a681 100644
--- a/drivers/edac/amd64_edac.c
+++ b/drivers/edac/amd64_edac.c
@@ -160,7 +160,7 @@ static int amd64_search_set_scrub_rate(struct pci_dev *ctl, u32 new_bw,
160 return 0; 160 return 0;
161} 161}
162 162
163static int amd64_set_scrub_rate(struct mem_ctl_info *mci, u32 *bandwidth) 163static int amd64_set_scrub_rate(struct mem_ctl_info *mci, u32 bandwidth)
164{ 164{
165 struct amd64_pvt *pvt = mci->pvt_info; 165 struct amd64_pvt *pvt = mci->pvt_info;
166 u32 min_scrubrate = 0x0; 166 u32 min_scrubrate = 0x0;
@@ -180,8 +180,8 @@ static int amd64_set_scrub_rate(struct mem_ctl_info *mci, u32 *bandwidth)
180 amd64_printk(KERN_ERR, "Unsupported family!\n"); 180 amd64_printk(KERN_ERR, "Unsupported family!\n");
181 return -EINVAL; 181 return -EINVAL;
182 } 182 }
183 return amd64_search_set_scrub_rate(pvt->misc_f3_ctl, *bandwidth, 183 return amd64_search_set_scrub_rate(pvt->misc_f3_ctl, bandwidth,
184 min_scrubrate); 184 min_scrubrate);
185} 185}
186 186
187static int amd64_get_scrub_rate(struct mem_ctl_info *mci, u32 *bw) 187static int amd64_get_scrub_rate(struct mem_ctl_info *mci, u32 *bw)
diff --git a/drivers/edac/e752x_edac.c b/drivers/edac/e752x_edac.c
index ae3f80c54198..073f5a06d238 100644
--- a/drivers/edac/e752x_edac.c
+++ b/drivers/edac/e752x_edac.c
@@ -958,7 +958,7 @@ static void e752x_check(struct mem_ctl_info *mci)
958} 958}
959 959
960/* Program byte/sec bandwidth scrub rate to hardware */ 960/* Program byte/sec bandwidth scrub rate to hardware */
961static int set_sdram_scrub_rate(struct mem_ctl_info *mci, u32 *new_bw) 961static int set_sdram_scrub_rate(struct mem_ctl_info *mci, u32 new_bw)
962{ 962{
963 const struct scrubrate *scrubrates; 963 const struct scrubrate *scrubrates;
964 struct e752x_pvt *pvt = (struct e752x_pvt *) mci->pvt_info; 964 struct e752x_pvt *pvt = (struct e752x_pvt *) mci->pvt_info;
@@ -975,7 +975,7 @@ static int set_sdram_scrub_rate(struct mem_ctl_info *mci, u32 *new_bw)
975 * desired rate and program the cooresponding register value. 975 * desired rate and program the cooresponding register value.
976 */ 976 */
977 for (i = 0; scrubrates[i].bandwidth != SDRATE_EOT; i++) 977 for (i = 0; scrubrates[i].bandwidth != SDRATE_EOT; i++)
978 if (scrubrates[i].bandwidth >= *new_bw) 978 if (scrubrates[i].bandwidth >= new_bw)
979 break; 979 break;
980 980
981 if (scrubrates[i].bandwidth == SDRATE_EOT) 981 if (scrubrates[i].bandwidth == SDRATE_EOT)
diff --git a/drivers/edac/edac_core.h b/drivers/edac/edac_core.h
index ade4f1d70539..ce7146677e9b 100644
--- a/drivers/edac/edac_core.h
+++ b/drivers/edac/edac_core.h
@@ -378,7 +378,7 @@ struct mem_ctl_info {
378 internal representation and configures whatever else needs 378 internal representation and configures whatever else needs
379 to be configured. 379 to be configured.
380 */ 380 */
381 int (*set_sdram_scrub_rate) (struct mem_ctl_info * mci, u32 * bw); 381 int (*set_sdram_scrub_rate) (struct mem_ctl_info * mci, u32 bw);
382 382
383 /* Get the current sdram memory scrub rate from the internal 383 /* Get the current sdram memory scrub rate from the internal
384 representation and converts it to the closest matching 384 representation and converts it to the closest matching
diff --git a/drivers/edac/edac_mc_sysfs.c b/drivers/edac/edac_mc_sysfs.c
index c200c2fd43ea..8aad94d10c0c 100644
--- a/drivers/edac/edac_mc_sysfs.c
+++ b/drivers/edac/edac_mc_sysfs.c
@@ -124,19 +124,6 @@ static const char *edac_caps[] = {
124 [EDAC_S16ECD16ED] = "S16ECD16ED" 124 [EDAC_S16ECD16ED] = "S16ECD16ED"
125}; 125};
126 126
127
128
129static ssize_t memctrl_int_store(void *ptr, const char *buffer, size_t count)
130{
131 int *value = (int *)ptr;
132
133 if (isdigit(*buffer))
134 *value = simple_strtoul(buffer, NULL, 0);
135
136 return count;
137}
138
139
140/* EDAC sysfs CSROW data structures and methods 127/* EDAC sysfs CSROW data structures and methods
141 */ 128 */
142 129
@@ -450,53 +437,54 @@ static ssize_t mci_reset_counters_store(struct mem_ctl_info *mci,
450 437
451/* memory scrubbing */ 438/* memory scrubbing */
452static ssize_t mci_sdram_scrub_rate_store(struct mem_ctl_info *mci, 439static ssize_t mci_sdram_scrub_rate_store(struct mem_ctl_info *mci,
453 const char *data, size_t count) 440 const char *data, size_t count)
454{ 441{
455 u32 bandwidth = -1; 442 unsigned long bandwidth = 0;
443 int err;
456 444
457 if (mci->set_sdram_scrub_rate) { 445 if (!mci->set_sdram_scrub_rate) {
446 edac_printk(KERN_WARNING, EDAC_MC,
447 "Memory scrub rate setting not implemented!\n");
448 return -EINVAL;
449 }
458 450
459 memctrl_int_store(&bandwidth, data, count); 451 if (strict_strtoul(data, 10, &bandwidth) < 0)
452 return -EINVAL;
460 453
461 if (!(*mci->set_sdram_scrub_rate) (mci, &bandwidth)) { 454 err = mci->set_sdram_scrub_rate(mci, (u32)bandwidth);
462 edac_printk(KERN_DEBUG, EDAC_MC, 455 if (err) {
463 "Scrub rate set successfully, applied: %d\n", 456 edac_printk(KERN_DEBUG, EDAC_MC,
464 bandwidth); 457 "Failed setting scrub rate to %lu\n", bandwidth);
465 } else { 458 return -EINVAL;
466 /* FIXME: error codes maybe? */ 459 }
467 edac_printk(KERN_DEBUG, EDAC_MC, 460 else {
468 "Scrub rate set FAILED, could not apply: %d\n", 461 edac_printk(KERN_DEBUG, EDAC_MC,
469 bandwidth); 462 "Scrub rate set to: %lu\n", bandwidth);
470 } 463 return count;
471 } else {
472 /* FIXME: produce "not implemented" ERROR for user-side. */
473 edac_printk(KERN_WARNING, EDAC_MC,
474 "Memory scrubbing 'set'control is not implemented!\n");
475 } 464 }
476 return count;
477} 465}
478 466
479static ssize_t mci_sdram_scrub_rate_show(struct mem_ctl_info *mci, char *data) 467static ssize_t mci_sdram_scrub_rate_show(struct mem_ctl_info *mci, char *data)
480{ 468{
481 u32 bandwidth = -1; 469 u32 bandwidth = 0;
482 470 int err;
483 if (mci->get_sdram_scrub_rate) { 471
484 if (!(*mci->get_sdram_scrub_rate) (mci, &bandwidth)) { 472 if (!mci->get_sdram_scrub_rate) {
485 edac_printk(KERN_DEBUG, EDAC_MC,
486 "Scrub rate successfully, fetched: %d\n",
487 bandwidth);
488 } else {
489 /* FIXME: error codes maybe? */
490 edac_printk(KERN_DEBUG, EDAC_MC,
491 "Scrub rate fetch FAILED, got: %d\n",
492 bandwidth);
493 }
494 } else {
495 /* FIXME: produce "not implemented" ERROR for user-side. */
496 edac_printk(KERN_WARNING, EDAC_MC, 473 edac_printk(KERN_WARNING, EDAC_MC,
497 "Memory scrubbing 'get' control is not implemented\n"); 474 "Memory scrub rate reading not implemented\n");
475 return -EINVAL;
476 }
477
478 err = mci->get_sdram_scrub_rate(mci, &bandwidth);
479 if (err) {
480 edac_printk(KERN_DEBUG, EDAC_MC, "Error reading scrub rate\n");
481 return err;
482 }
483 else {
484 edac_printk(KERN_DEBUG, EDAC_MC,
485 "Read scrub rate: %d\n", bandwidth);
486 return sprintf(data, "%d\n", bandwidth);
498 } 487 }
499 return sprintf(data, "%d\n", bandwidth);
500} 488}
501 489
502/* 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 ee9753cf362c..f459a6c0886b 100644
--- a/drivers/edac/i5100_edac.c
+++ b/drivers/edac/i5100_edac.c
@@ -589,14 +589,13 @@ static void i5100_refresh_scrubbing(struct work_struct *work)
589/* 589/*
590 * The bandwidth is based on experimentation, feel free to refine it. 590 * The bandwidth is based on experimentation, feel free to refine it.
591 */ 591 */
592static int i5100_set_scrub_rate(struct mem_ctl_info *mci, 592static int i5100_set_scrub_rate(struct mem_ctl_info *mci, u32 bandwidth)
593 u32 *bandwidth)
594{ 593{
595 struct i5100_priv *priv = mci->pvt_info; 594 struct i5100_priv *priv = mci->pvt_info;
596 u32 dw; 595 u32 dw;
597 596
598 pci_read_config_dword(priv->mc, I5100_MC, &dw); 597 pci_read_config_dword(priv->mc, I5100_MC, &dw);
599 if (*bandwidth) { 598 if (bandwidth) {
600 priv->scrub_enable = 1; 599 priv->scrub_enable = 1;
601 dw |= I5100_MC_SCRBEN_MASK; 600 dw |= I5100_MC_SCRBEN_MASK;
602 schedule_delayed_work(&(priv->i5100_scrubbing), 601 schedule_delayed_work(&(priv->i5100_scrubbing),
@@ -610,7 +609,7 @@ static int i5100_set_scrub_rate(struct mem_ctl_info *mci,
610 609
611 pci_read_config_dword(priv->mc, I5100_MC, &dw); 610 pci_read_config_dword(priv->mc, I5100_MC, &dw);
612 611
613 *bandwidth = 5900000 * i5100_mc_scrben(dw); 612 bandwidth = 5900000 * i5100_mc_scrben(dw);
614 613
615 return 0; 614 return 0;
616} 615}