瀏覽代碼

Merge branch 'edac-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/bp/bp

* 'edac-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/bp/bp:
  amd64_edac: Disable DRAM ECC injection on K8
  EDAC: Fixup scrubrate manipulation
  amd64_edac: Remove two-stage initialization
  amd64_edac: Check ECC capabilities initially
  amd64_edac: Carve out ECC-related hw settings
  amd64_edac: Remove PCI ECS enabling functions
  amd64_edac: Remove explicit Kconfig PCI dependency
  amd64_edac: Allocate driver instances dynamically
  amd64_edac: Rework printk macros
  amd64_edac: Rename CPU PCI devices
  amd64_edac: Concentrate per-family init even more
  amd64_edac: Cleanup the CPU PCI device reservation
  amd64_edac: Simplify CPU family detection
  amd64_edac: Add per-family init function
  amd64_edac: Use cached extended CPU model
  amd64_edac: Remove F11h support
Linus Torvalds 14 年之前
父節點
當前提交
442d1ba237

+ 4 - 4
drivers/edac/Kconfig

@@ -75,11 +75,11 @@ config EDAC_MCE
 	bool
 	bool
 
 
 config EDAC_AMD64
 config EDAC_AMD64
-	tristate "AMD64 (Opteron, Athlon64) K8, F10h, F11h"
-	depends on EDAC_MM_EDAC && AMD_NB && X86_64 && PCI && EDAC_DECODE_MCE
+	tristate "AMD64 (Opteron, Athlon64) K8, F10h"
+	depends on EDAC_MM_EDAC && AMD_NB && X86_64 && EDAC_DECODE_MCE
 	help
 	help
-	  Support for error detection and correction on the AMD 64
-	  Families of Memory Controllers (K8, F10h and F11h)
+	  Support for error detection and correction of DRAM ECC errors on
+	  the AMD64 families of memory controllers (K8 and F10h)
 
 
 config EDAC_AMD64_ERROR_INJECTION
 config EDAC_AMD64_ERROR_INJECTION
 	bool "Sysfs HW Error injection facilities"
 	bool "Sysfs HW Error injection facilities"

File diff suppressed because it is too large
+ 187 - 331
drivers/edac/amd64_edac.c


+ 39 - 47
drivers/edac/amd64_edac.h

@@ -74,11 +74,26 @@
 #include "edac_core.h"
 #include "edac_core.h"
 #include "mce_amd.h"
 #include "mce_amd.h"
 
 
-#define amd64_printk(level, fmt, arg...) \
-	edac_printk(level, "amd64", fmt, ##arg)
+#define amd64_debug(fmt, arg...) \
+	edac_printk(KERN_DEBUG, "amd64", fmt, ##arg)
 
 
-#define amd64_mc_printk(mci, level, fmt, arg...) \
-	edac_mc_chipset_printk(mci, level, "amd64", fmt, ##arg)
+#define amd64_info(fmt, arg...) \
+	edac_printk(KERN_INFO, "amd64", fmt, ##arg)
+
+#define amd64_notice(fmt, arg...) \
+	edac_printk(KERN_NOTICE, "amd64", fmt, ##arg)
+
+#define amd64_warn(fmt, arg...) \
+	edac_printk(KERN_WARNING, "amd64", fmt, ##arg)
+
+#define amd64_err(fmt, arg...) \
+	edac_printk(KERN_ERR, "amd64", fmt, ##arg)
+
+#define amd64_mc_warn(mci, fmt, arg...) \
+	edac_mc_chipset_printk(mci, KERN_WARNING, "amd64", fmt, ##arg)
+
+#define amd64_mc_err(mci, fmt, arg...) \
+	edac_mc_chipset_printk(mci, KERN_ERR, "amd64", fmt, ##arg)
 
 
 /*
 /*
  * Throughout the comments in this code, the following terms are used:
  * Throughout the comments in this code, the following terms are used:
@@ -129,11 +144,9 @@
  *         sections 3.5.4 and 3.5.5 for more information.
  *         sections 3.5.4 and 3.5.5 for more information.
  */
  */
 
 
-#define EDAC_AMD64_VERSION		" Ver: 3.3.0 " __DATE__
+#define EDAC_AMD64_VERSION		"v3.3.0"
 #define EDAC_MOD_STR			"amd64_edac"
 #define EDAC_MOD_STR			"amd64_edac"
 
 
-#define EDAC_MAX_NUMNODES		8
-
 /* Extended Model from CPUID, for CPU Revision numbers */
 /* Extended Model from CPUID, for CPU Revision numbers */
 #define K8_REV_D			1
 #define K8_REV_D			1
 #define K8_REV_E			2
 #define K8_REV_E			2
@@ -322,9 +335,6 @@
 #define K8_SCRCTRL			0x58
 #define K8_SCRCTRL			0x58
 
 
 #define F10_NB_CFG_LOW			0x88
 #define F10_NB_CFG_LOW			0x88
-#define	F10_NB_CFG_LOW_ENABLE_EXT_CFG	BIT(14)
-
-#define F10_NB_CFG_HIGH			0x8C
 
 
 #define F10_ONLINE_SPARE		0xB0
 #define F10_ONLINE_SPARE		0xB0
 #define F10_ONLINE_SPARE_SWAPDONE0(x)	((x) & BIT(1))
 #define F10_ONLINE_SPARE_SWAPDONE0(x)	((x) & BIT(1))
@@ -373,7 +383,6 @@ static inline int get_node_id(struct pci_dev *pdev)
 enum amd64_chipset_families {
 enum amd64_chipset_families {
 	K8_CPUS = 0,
 	K8_CPUS = 0,
 	F10_CPUS,
 	F10_CPUS,
-	F11_CPUS,
 };
 };
 
 
 /* Error injection control structure */
 /* Error injection control structure */
@@ -384,16 +393,13 @@ struct error_injection {
 };
 };
 
 
 struct amd64_pvt {
 struct amd64_pvt {
+	struct low_ops *ops;
+
 	/* pci_device handles which we utilize */
 	/* pci_device handles which we utilize */
-	struct pci_dev *addr_f1_ctl;
-	struct pci_dev *dram_f2_ctl;
-	struct pci_dev *misc_f3_ctl;
+	struct pci_dev *F1, *F2, *F3;
 
 
 	int mc_node_id;		/* MC index of this MC node */
 	int mc_node_id;		/* MC index of this MC node */
 	int ext_model;		/* extended model value of this node */
 	int ext_model;		/* extended model value of this node */
-
-	struct low_ops *ops;	/* pointer to per PCI Device ID func table */
-
 	int channel_count;
 	int channel_count;
 
 
 	/* Raw registers */
 	/* Raw registers */
@@ -455,27 +461,27 @@ struct amd64_pvt {
 	/* place to store error injection parameters prior to issue */
 	/* place to store error injection parameters prior to issue */
 	struct error_injection injection;
 	struct error_injection injection;
 
 
-	/* Save old hw registers' values before we modified them */
-	u32 nbctl_mcgctl_saved;		/* When true, following 2 are valid */
-	u32 old_nbctl;
+	/* DCT per-family scrubrate setting */
+	u32 min_scrubrate;
 
 
-	/* MC Type Index value: socket F vs Family 10h */
-	u32 mc_type_index;
+	/* family name this instance is running on */
+	const char *ctl_name;
+
+};
+
+/*
+ * per-node ECC settings descriptor
+ */
+struct ecc_settings {
+	u32 old_nbctl;
+	bool nbctl_valid;
 
 
-	/* misc settings */
 	struct flags {
 	struct flags {
-		unsigned long cf8_extcfg:1;
 		unsigned long nb_mce_enable:1;
 		unsigned long nb_mce_enable:1;
 		unsigned long nb_ecc_prev:1;
 		unsigned long nb_ecc_prev:1;
 	} flags;
 	} flags;
 };
 };
 
 
-struct scrubrate {
-       u32 scrubval;           /* bit pattern for scrub rate */
-       u32 bandwidth;          /* bandwidth consumed (bytes/sec) */
-};
-
-extern struct scrubrate scrubrates[23];
 extern const char *tt_msgs[4];
 extern const char *tt_msgs[4];
 extern const char *ll_msgs[4];
 extern const char *ll_msgs[4];
 extern const char *rrrr_msgs[16];
 extern const char *rrrr_msgs[16];
@@ -517,23 +523,10 @@ struct low_ops {
 
 
 struct amd64_family_type {
 struct amd64_family_type {
 	const char *ctl_name;
 	const char *ctl_name;
-	u16 addr_f1_ctl;
-	u16 misc_f3_ctl;
+	u16 f1_id, f3_id;
 	struct low_ops ops;
 	struct low_ops ops;
 };
 };
 
 
-static struct amd64_family_type amd64_family_types[];
-
-static inline const char *get_amd_family_name(int index)
-{
-	return amd64_family_types[index].ctl_name;
-}
-
-static inline struct low_ops *family_ops(int index)
-{
-	return &amd64_family_types[index].ops;
-}
-
 static inline int amd64_read_pci_cfg_dword(struct pci_dev *pdev, int offset,
 static inline int amd64_read_pci_cfg_dword(struct pci_dev *pdev, int offset,
 					   u32 *val, const char *func)
 					   u32 *val, const char *func)
 {
 {
@@ -541,8 +534,8 @@ static inline int amd64_read_pci_cfg_dword(struct pci_dev *pdev, int offset,
 
 
 	err = pci_read_config_dword(pdev, offset, val);
 	err = pci_read_config_dword(pdev, offset, val);
 	if (err)
 	if (err)
-		amd64_printk(KERN_WARNING, "%s: error reading F%dx%x.\n",
-			     func, PCI_FUNC(pdev->devfn), offset);
+		amd64_warn("%s: error reading F%dx%x.\n",
+			   func, PCI_FUNC(pdev->devfn), offset);
 
 
 	return err;
 	return err;
 }
 }
@@ -556,7 +549,6 @@ static inline int amd64_read_pci_cfg_dword(struct pci_dev *pdev, int offset,
  */
  */
 #define K8_MIN_SCRUB_RATE_BITS	0x0
 #define K8_MIN_SCRUB_RATE_BITS	0x0
 #define F10_MIN_SCRUB_RATE_BITS	0x5
 #define F10_MIN_SCRUB_RATE_BITS	0x5
-#define F11_MIN_SCRUB_RATE_BITS	0x6
 
 
 int amd64_get_dram_hole_info(struct mem_ctl_info *mci, u64 *hole_base,
 int amd64_get_dram_hole_info(struct mem_ctl_info *mci, u64 *hole_base,
 			     u64 *hole_offset, u64 *hole_size);
 			     u64 *hole_offset, u64 *hole_size);

+ 8 - 17
drivers/edac/amd64_edac_inj.c

@@ -23,9 +23,7 @@ static ssize_t amd64_inject_section_store(struct mem_ctl_info *mci,
 	if (ret != -EINVAL) {
 	if (ret != -EINVAL) {
 
 
 		if (value > 3) {
 		if (value > 3) {
-			amd64_printk(KERN_WARNING,
-				     "%s: invalid section 0x%lx\n",
-				     __func__, value);
+			amd64_warn("%s: invalid section 0x%lx\n", __func__, value);
 			return -EINVAL;
 			return -EINVAL;
 		}
 		}
 
 
@@ -58,9 +56,7 @@ static ssize_t amd64_inject_word_store(struct mem_ctl_info *mci,
 	if (ret != -EINVAL) {
 	if (ret != -EINVAL) {
 
 
 		if (value > 8) {
 		if (value > 8) {
-			amd64_printk(KERN_WARNING,
-				     "%s: invalid word 0x%lx\n",
-				     __func__, value);
+			amd64_warn("%s: invalid word 0x%lx\n", __func__, value);
 			return -EINVAL;
 			return -EINVAL;
 		}
 		}
 
 
@@ -92,9 +88,8 @@ static ssize_t amd64_inject_ecc_vector_store(struct mem_ctl_info *mci,
 	if (ret != -EINVAL) {
 	if (ret != -EINVAL) {
 
 
 		if (value & 0xFFFF0000) {
 		if (value & 0xFFFF0000) {
-			amd64_printk(KERN_WARNING,
-				     "%s: invalid EccVector: 0x%lx\n",
-				     __func__, value);
+			amd64_warn("%s: invalid EccVector: 0x%lx\n",
+				   __func__, value);
 			return -EINVAL;
 			return -EINVAL;
 		}
 		}
 
 
@@ -122,15 +117,13 @@ static ssize_t amd64_inject_read_store(struct mem_ctl_info *mci,
 		/* Form value to choose 16-byte section of cacheline */
 		/* Form value to choose 16-byte section of cacheline */
 		section = F10_NB_ARRAY_DRAM_ECC |
 		section = F10_NB_ARRAY_DRAM_ECC |
 				SET_NB_ARRAY_ADDRESS(pvt->injection.section);
 				SET_NB_ARRAY_ADDRESS(pvt->injection.section);
-		pci_write_config_dword(pvt->misc_f3_ctl,
-					F10_NB_ARRAY_ADDR, section);
+		pci_write_config_dword(pvt->F3, F10_NB_ARRAY_ADDR, section);
 
 
 		word_bits = SET_NB_DRAM_INJECTION_READ(pvt->injection.word,
 		word_bits = SET_NB_DRAM_INJECTION_READ(pvt->injection.word,
 						pvt->injection.bit_map);
 						pvt->injection.bit_map);
 
 
 		/* Issue 'word' and 'bit' along with the READ request */
 		/* Issue 'word' and 'bit' along with the READ request */
-		pci_write_config_dword(pvt->misc_f3_ctl,
-					F10_NB_ARRAY_DATA, word_bits);
+		pci_write_config_dword(pvt->F3, F10_NB_ARRAY_DATA, word_bits);
 
 
 		debugf0("section=0x%x word_bits=0x%x\n", section, word_bits);
 		debugf0("section=0x%x word_bits=0x%x\n", section, word_bits);
 
 
@@ -157,15 +150,13 @@ static ssize_t amd64_inject_write_store(struct mem_ctl_info *mci,
 		/* Form value to choose 16-byte section of cacheline */
 		/* Form value to choose 16-byte section of cacheline */
 		section = F10_NB_ARRAY_DRAM_ECC |
 		section = F10_NB_ARRAY_DRAM_ECC |
 				SET_NB_ARRAY_ADDRESS(pvt->injection.section);
 				SET_NB_ARRAY_ADDRESS(pvt->injection.section);
-		pci_write_config_dword(pvt->misc_f3_ctl,
-					F10_NB_ARRAY_ADDR, section);
+		pci_write_config_dword(pvt->F3, F10_NB_ARRAY_ADDR, section);
 
 
 		word_bits = SET_NB_DRAM_INJECTION_WRITE(pvt->injection.word,
 		word_bits = SET_NB_DRAM_INJECTION_WRITE(pvt->injection.word,
 						pvt->injection.bit_map);
 						pvt->injection.bit_map);
 
 
 		/* Issue 'word' and 'bit' along with the READ request */
 		/* Issue 'word' and 'bit' along with the READ request */
-		pci_write_config_dword(pvt->misc_f3_ctl,
-					F10_NB_ARRAY_DATA, word_bits);
+		pci_write_config_dword(pvt->F3, F10_NB_ARRAY_DATA, word_bits);
 
 
 		debugf0("section=0x%x word_bits=0x%x\n", section, word_bits);
 		debugf0("section=0x%x word_bits=0x%x\n", section, word_bits);
 
 

+ 5 - 4
drivers/edac/cpc925_edac.c

@@ -818,9 +818,10 @@ static void cpc925_del_edac_devices(void)
 }
 }
 
 
 /* Convert current back-ground scrub rate into byte/sec bandwith */
 /* Convert current back-ground scrub rate into byte/sec bandwith */
-static int cpc925_get_sdram_scrub_rate(struct mem_ctl_info *mci, u32 *bw)
+static int cpc925_get_sdram_scrub_rate(struct mem_ctl_info *mci)
 {
 {
 	struct cpc925_mc_pdata *pdata = mci->pvt_info;
 	struct cpc925_mc_pdata *pdata = mci->pvt_info;
+	int bw;
 	u32 mscr;
 	u32 mscr;
 	u8 si;
 	u8 si;
 
 
@@ -832,11 +833,11 @@ static int cpc925_get_sdram_scrub_rate(struct mem_ctl_info *mci, u32 *bw)
 	if (((mscr & MSCR_SCRUB_MOD_MASK) != MSCR_BACKGR_SCRUB) ||
 	if (((mscr & MSCR_SCRUB_MOD_MASK) != MSCR_BACKGR_SCRUB) ||
 	    (si == 0)) {
 	    (si == 0)) {
 		cpc925_mc_printk(mci, KERN_INFO, "Scrub mode not enabled\n");
 		cpc925_mc_printk(mci, KERN_INFO, "Scrub mode not enabled\n");
-		*bw = 0;
+		bw = 0;
 	} else
 	} else
-		*bw = CPC925_SCRUB_BLOCK_SIZE * 0xFA67 / si;
+		bw = CPC925_SCRUB_BLOCK_SIZE * 0xFA67 / si;
 
 
-	return 0;
+	return bw;
 }
 }
 
 
 /* Return 0 for single channel; 1 for dual channel */
 /* Return 0 for single channel; 1 for dual channel */

+ 3 - 5
drivers/edac/e752x_edac.c

@@ -983,11 +983,11 @@ static int set_sdram_scrub_rate(struct mem_ctl_info *mci, u32 new_bw)
 
 
 	pci_write_config_word(pdev, E752X_MCHSCRB, scrubrates[i].scrubval);
 	pci_write_config_word(pdev, E752X_MCHSCRB, scrubrates[i].scrubval);
 
 
-	return 0;
+	return scrubrates[i].bandwidth;
 }
 }
 
 
 /* Convert current scrub rate value into byte/sec bandwidth */
 /* Convert current scrub rate value into byte/sec bandwidth */
-static int get_sdram_scrub_rate(struct mem_ctl_info *mci, u32 *bw)
+static int get_sdram_scrub_rate(struct mem_ctl_info *mci)
 {
 {
 	const struct scrubrate *scrubrates;
 	const struct scrubrate *scrubrates;
 	struct e752x_pvt *pvt = (struct e752x_pvt *) mci->pvt_info;
 	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)
 			"Invalid sdram scrub control value: 0x%x\n", scrubval);
 			"Invalid sdram scrub control value: 0x%x\n", scrubval);
 		return -1;
 		return -1;
 	}
 	}
+	return scrubrates[i].bandwidth;
 
 
-	*bw = scrubrates[i].bandwidth;
-
-	return 0;
 }
 }
 
 
 /* Return 1 if dual channel mode is active.  Else return 0. */
 /* Return 1 if dual channel mode is active.  Else return 0. */

+ 3 - 2
drivers/edac/edac_core.h

@@ -68,9 +68,10 @@
 #define EDAC_PCI "PCI"
 #define EDAC_PCI "PCI"
 #define EDAC_DEBUG "DEBUG"
 #define EDAC_DEBUG "DEBUG"
 
 
+extern const char *edac_mem_types[];
+
 #ifdef CONFIG_EDAC_DEBUG
 #ifdef CONFIG_EDAC_DEBUG
 extern int edac_debug_level;
 extern int edac_debug_level;
-extern const char *edac_mem_types[];
 
 
 #define edac_debug_printk(level, fmt, arg...)                           \
 #define edac_debug_printk(level, fmt, arg...)                           \
 	do {                                                            \
 	do {                                                            \
@@ -386,7 +387,7 @@ struct mem_ctl_info {
 	   representation and converts it to the closest matching
 	   representation and converts it to the closest matching
 	   bandwith in bytes/sec.
 	   bandwith in bytes/sec.
 	 */
 	 */
-	int (*get_sdram_scrub_rate) (struct mem_ctl_info * mci, u32 * bw);
+	int (*get_sdram_scrub_rate) (struct mem_ctl_info * mci);
 
 
 
 
 	/* pointer to edac checking routine */
 	/* pointer to edac checking routine */

+ 2 - 2
drivers/edac/edac_mc.c

@@ -76,6 +76,8 @@ static void edac_mc_dump_mci(struct mem_ctl_info *mci)
 	debugf3("\tpvt_info = %p\n\n", mci->pvt_info);
 	debugf3("\tpvt_info = %p\n\n", mci->pvt_info);
 }
 }
 
 
+#endif				/* CONFIG_EDAC_DEBUG */
+
 /*
 /*
  * keep those in sync with the enum mem_type
  * keep those in sync with the enum mem_type
  */
  */
@@ -100,8 +102,6 @@ const char *edac_mem_types[] = {
 };
 };
 EXPORT_SYMBOL_GPL(edac_mem_types);
 EXPORT_SYMBOL_GPL(edac_mem_types);
 
 
-#endif				/* CONFIG_EDAC_DEBUG */
-
 /* 'ptr' points to a possibly unaligned item X such that sizeof(X) is 'size'.
 /* 'ptr' points to a possibly unaligned item X such that sizeof(X) is 'size'.
  * Adjust 'ptr' so that its alignment is at least as stringent as what the
  * Adjust 'ptr' so that its alignment is at least as stringent as what the
  * compiler would provide for X and return the aligned result.
  * compiler would provide for X and return the aligned result.

+ 28 - 29
drivers/edac/edac_mc_sysfs.c

@@ -436,56 +436,55 @@ static ssize_t mci_reset_counters_store(struct mem_ctl_info *mci,
 	return count;
 	return count;
 }
 }
 
 
-/* memory scrubbing */
+/* Memory scrubbing interface:
+ *
+ * A MC driver can limit the scrubbing bandwidth based on the CPU type.
+ * Therefore, ->set_sdram_scrub_rate should be made to return the actual
+ * bandwidth that is accepted or 0 when scrubbing is to be disabled.
+ *
+ * Negative value still means that an error has occurred while setting
+ * the scrub rate.
+ */
 static ssize_t mci_sdram_scrub_rate_store(struct mem_ctl_info *mci,
 static ssize_t mci_sdram_scrub_rate_store(struct mem_ctl_info *mci,
 					  const char *data, size_t count)
 					  const char *data, size_t count)
 {
 {
 	unsigned long bandwidth = 0;
 	unsigned long bandwidth = 0;
-	int err;
+	int new_bw = 0;
 
 
-	if (!mci->set_sdram_scrub_rate) {
-		edac_printk(KERN_WARNING, EDAC_MC,
-			    "Memory scrub rate setting not implemented!\n");
+	if (!mci->set_sdram_scrub_rate)
 		return -EINVAL;
 		return -EINVAL;
-	}
 
 
 	if (strict_strtoul(data, 10, &bandwidth) < 0)
 	if (strict_strtoul(data, 10, &bandwidth) < 0)
 		return -EINVAL;
 		return -EINVAL;
 
 
-	err = mci->set_sdram_scrub_rate(mci, (u32)bandwidth);
-	if (err) {
-		edac_printk(KERN_DEBUG, EDAC_MC,
-			    "Failed setting scrub rate to %lu\n", bandwidth);
-		return -EINVAL;
-	}
-	else {
-		edac_printk(KERN_DEBUG, EDAC_MC,
-			    "Scrub rate set to: %lu\n", bandwidth);
+	new_bw = mci->set_sdram_scrub_rate(mci, bandwidth);
+	if (new_bw >= 0) {
+		edac_printk(KERN_DEBUG, EDAC_MC, "Scrub rate set to %d\n", new_bw);
 		return count;
 		return count;
 	}
 	}
+
+	edac_printk(KERN_DEBUG, EDAC_MC, "Error setting scrub rate to: %lu\n", bandwidth);
+	return -EINVAL;
 }
 }
 
 
+/*
+ * ->get_sdram_scrub_rate() return value semantics same as above.
+ */
 static ssize_t mci_sdram_scrub_rate_show(struct mem_ctl_info *mci, char *data)
 static ssize_t mci_sdram_scrub_rate_show(struct mem_ctl_info *mci, char *data)
 {
 {
-	u32 bandwidth = 0;
-	int err;
+	int bandwidth = 0;
 
 
-	if (!mci->get_sdram_scrub_rate) {
-		edac_printk(KERN_WARNING, EDAC_MC,
-			    "Memory scrub rate reading not implemented\n");
+	if (!mci->get_sdram_scrub_rate)
 		return -EINVAL;
 		return -EINVAL;
-	}
 
 
-	err = mci->get_sdram_scrub_rate(mci, &bandwidth);
-	if (err) {
+	bandwidth = mci->get_sdram_scrub_rate(mci);
+	if (bandwidth < 0) {
 		edac_printk(KERN_DEBUG, EDAC_MC, "Error reading scrub rate\n");
 		edac_printk(KERN_DEBUG, EDAC_MC, "Error reading scrub rate\n");
-		return err;
-	}
-	else {
-		edac_printk(KERN_DEBUG, EDAC_MC,
-			    "Read scrub rate: %d\n", bandwidth);
-		return sprintf(data, "%d\n", bandwidth);
+		return bandwidth;
 	}
 	}
+
+	edac_printk(KERN_DEBUG, EDAC_MC, "Read scrub rate: %d\n", bandwidth);
+	return sprintf(data, "%d\n", bandwidth);
 }
 }
 
 
 /* default attribute files for the MCI object */
 /* default attribute files for the MCI object */

+ 3 - 6
drivers/edac/i5100_edac.c

@@ -611,20 +611,17 @@ static int i5100_set_scrub_rate(struct mem_ctl_info *mci, u32 bandwidth)
 
 
 	bandwidth = 5900000 * i5100_mc_scrben(dw);
 	bandwidth = 5900000 * i5100_mc_scrben(dw);
 
 
-	return 0;
+	return bandwidth;
 }
 }
 
 
-static int i5100_get_scrub_rate(struct mem_ctl_info *mci,
-				u32 *bandwidth)
+static int i5100_get_scrub_rate(struct mem_ctl_info *mci)
 {
 {
 	struct i5100_priv *priv = mci->pvt_info;
 	struct i5100_priv *priv = mci->pvt_info;
 	u32 dw;
 	u32 dw;
 
 
 	pci_read_config_dword(priv->mc, I5100_MC, &dw);
 	pci_read_config_dword(priv->mc, I5100_MC, &dw);
 
 
-	*bandwidth = 5900000 * i5100_mc_scrben(dw);
-
-	return 0;
+	return 5900000 * i5100_mc_scrben(dw);
 }
 }
 
 
 static struct pci_dev *pci_get_device_func(unsigned vendor,
 static struct pci_dev *pci_get_device_func(unsigned vendor,

Some files were not shown because too many files changed in this diff