提交 8da8533d 编写于 作者: L Linus Torvalds

Merge git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-edac

Pull EDAC patches from Mauro Carvalho Chehab:

 - the second part of the EDAC rework:
    - Add the sysfs nodes that exports the real memory layout, instead
      of the fake one (needed to properly represent Intel memory
      controllers since 2002)
    - convert EDAC MC to use "struct device" instead of creating the
      sysfs nodes via the kobj API
    - adds a tracepoint to represent memory errors

 - some cleanup patches

 - some fixes at i5000, i5400 and EDAC core

 - a new EDAC driver for Caldera.

* git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-edac: (33 commits)
  edac i5000, i5400: fix pointer math in i5000_get_mc_regs()
  edac: allow specifying the error count with fake_inject
  edac: add support for Calxeda highbank L2 cache ecc
  edac: add support for Calxeda highbank memory controller
  edac: create top-level debugfs directory
  sb_edac: properly handle error count
  i7core_edac: properly handle error count
  edac: edac_mc_handle_error(): add an error_count parameter
  edac: remove arch-specific parameter for the error handler
  amd64_edac: Don't pass driver name as an error parameter
  edac_mc: check for allocation failure in edac_mc_alloc()
  edac: Increase version to 3.0.0
  edac_mc: Cleanup per-dimm_info debug messages
  edac: Convert debugfX to edac_dbg(X,
  edac: Use more normal debugging macro style
  edac: Don't add __func__ or __FILE__ for debugf[0-9] msgs
  Edac: Add ABI Documentation for the new device nodes
  edac: move documentation ABI to ABI/testing/sysfs-devices-edac
  i7core_edac: change the mem allocation scheme to make Documentation/kobject.txt happy
  edac: change the mem allocation scheme to make Documentation/kobject.txt happy
  ...
What: /sys/devices/system/edac/mc/mc*/reset_counters
Date: January 2006
Contact: linux-edac@vger.kernel.org
Description: This write-only control file will zero all the statistical
counters for UE and CE errors on the given memory controller.
Zeroing the counters will also reset the timer indicating how
long since the last counter were reset. This is useful for
computing errors/time. Since the counters are always reset
at driver initialization time, no module/kernel parameter
is available.
What: /sys/devices/system/edac/mc/mc*/seconds_since_reset
Date: January 2006
Contact: linux-edac@vger.kernel.org
Description: This attribute file displays how many seconds have elapsed
since the last counter reset. This can be used with the error
counters to measure error rates.
What: /sys/devices/system/edac/mc/mc*/mc_name
Date: January 2006
Contact: linux-edac@vger.kernel.org
Description: This attribute file displays the type of memory controller
that is being utilized.
What: /sys/devices/system/edac/mc/mc*/size_mb
Date: January 2006
Contact: linux-edac@vger.kernel.org
Description: This attribute file displays, in count of megabytes, of memory
that this memory controller manages.
What: /sys/devices/system/edac/mc/mc*/ue_count
Date: January 2006
Contact: linux-edac@vger.kernel.org
Description: This attribute file displays the total count of uncorrectable
errors that have occurred on this memory controller. If
panic_on_ue is set, this counter will not have a chance to
increment, since EDAC will panic the system
What: /sys/devices/system/edac/mc/mc*/ue_noinfo_count
Date: January 2006
Contact: linux-edac@vger.kernel.org
Description: This attribute file displays the number of UEs that have
occurred on this memory controller with no information as to
which DIMM slot is having errors.
What: /sys/devices/system/edac/mc/mc*/ce_count
Date: January 2006
Contact: linux-edac@vger.kernel.org
Description: This attribute file displays the total count of correctable
errors that have occurred on this memory controller. This
count is very important to examine. CEs provide early
indications that a DIMM is beginning to fail. This count
field should be monitored for non-zero values and report
such information to the system administrator.
What: /sys/devices/system/edac/mc/mc*/ce_noinfo_count
Date: January 2006
Contact: linux-edac@vger.kernel.org
Description: This attribute file displays the number of CEs that
have occurred on this memory controller wherewith no
information as to which DIMM slot is having errors. Memory is
handicapped, but operational, yet no information is available
to indicate which slot the failing memory is in. This count
field should be also be monitored for non-zero values.
What: /sys/devices/system/edac/mc/mc*/sdram_scrub_rate
Date: February 2007
Contact: linux-edac@vger.kernel.org
Description: Read/Write attribute file that controls memory scrubbing.
The scrubbing rate used by the memory controller is set by
writing a minimum bandwidth in bytes/sec to the attribute file.
The rate will be translated to an internal value that gives at
least the specified rate.
Reading the file will return the actual scrubbing rate employed.
If configuration fails or memory scrubbing is not implemented,
the value of the attribute file will be -1.
What: /sys/devices/system/edac/mc/mc*/max_location
Date: April 2012
Contact: Mauro Carvalho Chehab <mchehab@redhat.com>
linux-edac@vger.kernel.org
Description: This attribute file displays the information about the last
available memory slot in this memory controller. It is used by
userspace tools in order to display the memory filling layout.
What: /sys/devices/system/edac/mc/mc*/(dimm|rank)*/size
Date: April 2012
Contact: Mauro Carvalho Chehab <mchehab@redhat.com>
linux-edac@vger.kernel.org
Description: This attribute file will display the size of dimm or rank.
For dimm*/size, this is the size, in MB of the DIMM memory
stick. For rank*/size, this is the size, in MB for one rank
of the DIMM memory stick. On single rank memories (1R), this
is also the total size of the dimm. On dual rank (2R) memories,
this is half the size of the total DIMM memories.
What: /sys/devices/system/edac/mc/mc*/(dimm|rank)*/dimm_dev_type
Date: April 2012
Contact: Mauro Carvalho Chehab <mchehab@redhat.com>
linux-edac@vger.kernel.org
Description: This attribute file will display what type of DRAM device is
being utilized on this DIMM (x1, x2, x4, x8, ...).
What: /sys/devices/system/edac/mc/mc*/(dimm|rank)*/dimm_edac_mode
Date: April 2012
Contact: Mauro Carvalho Chehab <mchehab@redhat.com>
linux-edac@vger.kernel.org
Description: This attribute file will display what type of Error detection
and correction is being utilized. For example: S4ECD4ED would
mean a Chipkill with x4 DRAM.
What: /sys/devices/system/edac/mc/mc*/(dimm|rank)*/dimm_label
Date: April 2012
Contact: Mauro Carvalho Chehab <mchehab@redhat.com>
linux-edac@vger.kernel.org
Description: This control file allows this DIMM to have a label assigned
to it. With this label in the module, when errors occur
the output can provide the DIMM label in the system log.
This becomes vital for panic events to isolate the
cause of the UE event.
DIMM Labels must be assigned after booting, with information
that correctly identifies the physical slot with its
silk screen label. This information is currently very
motherboard specific and determination of this information
must occur in userland at this time.
What: /sys/devices/system/edac/mc/mc*/(dimm|rank)*/dimm_location
Date: April 2012
Contact: Mauro Carvalho Chehab <mchehab@redhat.com>
linux-edac@vger.kernel.org
Description: This attribute file will display the location (csrow/channel,
branch/channel/slot or channel/slot) of the dimm or rank.
What: /sys/devices/system/edac/mc/mc*/(dimm|rank)*/dimm_mem_type
Date: April 2012
Contact: Mauro Carvalho Chehab <mchehab@redhat.com>
linux-edac@vger.kernel.org
Description: This attribute file will display what type of memory is
currently on this csrow. Normally, either buffered or
unbuffered memory (for example, Unbuffered-DDR3).
Calxeda Highbank L2 cache ECC
Properties:
- compatible : Should be "calxeda,hb-sregs-l2-ecc"
- reg : Address and size for ECC error interrupt clear registers.
- interrupts : Should be single bit error interrupt, then double bit error
interrupt.
Example:
sregs@fff3c200 {
compatible = "calxeda,hb-sregs-l2-ecc";
reg = <0xfff3c200 0x100>;
interrupts = <0 71 4 0 72 4>;
};
Calxeda DDR memory controller
Properties:
- compatible : Should be "calxeda,hb-ddr-ctrl"
- reg : Address and size for DDR controller registers.
- interrupts : Interrupt for DDR controller.
Example:
memory-controller@fff00000 {
compatible = "calxeda,hb-ddr-ctrl";
reg = <0xfff00000 0x1000>;
interrupts = <0 91 4>;
};
......@@ -232,116 +232,20 @@ EDAC control and attribute files.
In 'mcX' directories are EDAC control and attribute files for
this 'X' instance of the memory controllers:
Counter reset control file:
'reset_counters'
This write-only control file will zero all the statistical counters
for UE and CE errors. Zeroing the counters will also reset the timer
indicating how long since the last counter zero. This is useful
for computing errors/time. Since the counters are always reset at
driver initialization time, no module/kernel parameter is available.
RUN TIME: echo "anything" >/sys/devices/system/edac/mc/mc0/counter_reset
This resets the counters on memory controller 0
Seconds since last counter reset control file:
'seconds_since_reset'
This attribute file displays how many seconds have elapsed since the
last counter reset. This can be used with the error counters to
measure error rates.
Memory Controller name attribute file:
'mc_name'
This attribute file displays the type of memory controller
that is being utilized.
Total memory managed by this memory controller attribute file:
'size_mb'
This attribute file displays, in count of megabytes, of memory
that this instance of memory controller manages.
Total Uncorrectable Errors count attribute file:
'ue_count'
This attribute file displays the total count of uncorrectable
errors that have occurred on this memory controller. If panic_on_ue
is set this counter will not have a chance to increment,
since EDAC will panic the system.
Total UE count that had no information attribute fileY:
'ue_noinfo_count'
This attribute file displays the number of UEs that have occurred
with no information as to which DIMM slot is having errors.
Total Correctable Errors count attribute file:
'ce_count'
This attribute file displays the total count of correctable
errors that have occurred on this memory controller. This
count is very important to examine. CEs provide early
indications that a DIMM is beginning to fail. This count
field should be monitored for non-zero values and report
such information to the system administrator.
Total Correctable Errors count attribute file:
'ce_noinfo_count'
This attribute file displays the number of CEs that
have occurred wherewith no information as to which DIMM slot
is having errors. Memory is handicapped, but operational,
yet no information is available to indicate which slot
the failing memory is in. This count field should be also
be monitored for non-zero values.
Device Symlink:
'device'
Symlink to the memory controller device.
Sdram memory scrubbing rate:
'sdram_scrub_rate'
Read/Write attribute file that controls memory scrubbing. The scrubbing
rate is set by writing a minimum bandwidth in bytes/sec to the attribute
file. The rate will be translated to an internal value that gives at
least the specified rate.
Reading the file will return the actual scrubbing rate employed.
If configuration fails or memory scrubbing is not implemented, accessing
that attribute will fail.
this 'X' instance of the memory controllers.
For a description of the sysfs API, please see:
Documentation/ABI/testing/sysfs/devices-edac
============================================================================
'csrowX' DIRECTORIES
When CONFIG_EDAC_LEGACY_SYSFS is enabled, the sysfs will contain the
csrowX directories. As this API doesn't work properly for Rambus, FB-DIMMs
and modern Intel Memory Controllers, this is being deprecated in favor
of dimmX directories.
In the 'csrowX' directories are EDAC control and attribute files for
this 'X' instance of csrow:
......
......@@ -130,6 +130,12 @@
clocks = <&eclk>;
};
memory-controller@fff00000 {
compatible = "calxeda,hb-ddr-ctrl";
reg = <0xfff00000 0x1000>;
interrupts = <0 91 4>;
};
ipc@fff20000 {
compatible = "arm,pl320", "arm,primecell";
reg = <0xfff20000 0x1000>;
......@@ -275,6 +281,12 @@
};
};
sregs@fff3c200 {
compatible = "calxeda,hb-sregs-l2-ecc";
reg = <0xfff3c200 0x100>;
interrupts = <0 71 4 0 72 4>;
};
dma@fff3d000 {
compatible = "arm,pl330", "arm,primecell";
reg = <0xfff3d000 0x1000>;
......
......@@ -7,7 +7,7 @@
menuconfig EDAC
bool "EDAC (Error Detection And Correction) reporting"
depends on HAS_IOMEM
depends on X86 || PPC || TILE
depends on X86 || PPC || TILE || ARM
help
EDAC is designed to report errors in the core system.
These are low-level errors that are reported in the CPU or
......@@ -31,6 +31,14 @@ if EDAC
comment "Reporting subsystems"
config EDAC_LEGACY_SYSFS
bool "EDAC legacy sysfs"
default y
help
Enable the compatibility sysfs nodes.
Use 'Y' if your edac utilities aren't ported to work with the newer
structures.
config EDAC_DEBUG
bool "Debugging"
help
......@@ -294,4 +302,18 @@ config EDAC_TILE
Support for error detection and correction on the
Tilera memory controller.
config EDAC_HIGHBANK_MC
tristate "Highbank Memory Controller"
depends on EDAC_MM_EDAC && ARCH_HIGHBANK
help
Support for error detection and correction on the
Calxeda Highbank memory controller.
config EDAC_HIGHBANK_L2
tristate "Highbank L2 Cache"
depends on EDAC_MM_EDAC && ARCH_HIGHBANK
help
Support for error detection and correction on the
Calxeda Highbank memory controller.
endif # EDAC
......@@ -55,3 +55,6 @@ obj-$(CONFIG_EDAC_AMD8111) += amd8111_edac.o
obj-$(CONFIG_EDAC_AMD8131) += amd8131_edac.o
obj-$(CONFIG_EDAC_TILE) += tile_edac.o
obj-$(CONFIG_EDAC_HIGHBANK_MC) += highbank_mc_edac.o
obj-$(CONFIG_EDAC_HIGHBANK_L2) += highbank_l2_edac.o
此差异已折叠。
......@@ -413,20 +413,33 @@ struct ecc_settings {
};
#ifdef CONFIG_EDAC_DEBUG
#define NUM_DBG_ATTRS 5
int amd64_create_sysfs_dbg_files(struct mem_ctl_info *mci);
void amd64_remove_sysfs_dbg_files(struct mem_ctl_info *mci);
#else
#define NUM_DBG_ATTRS 0
static inline int amd64_create_sysfs_dbg_files(struct mem_ctl_info *mci)
{
return 0;
}
static void inline amd64_remove_sysfs_dbg_files(struct mem_ctl_info *mci)
{
}
#endif
#ifdef CONFIG_EDAC_AMD64_ERROR_INJECTION
#define NUM_INJ_ATTRS 5
int amd64_create_sysfs_inject_files(struct mem_ctl_info *mci);
void amd64_remove_sysfs_inject_files(struct mem_ctl_info *mci);
#else
#define NUM_INJ_ATTRS 0
static inline int amd64_create_sysfs_inject_files(struct mem_ctl_info *mci)
{
return 0;
}
static inline void amd64_remove_sysfs_inject_files(struct mem_ctl_info *mci)
{
}
#endif
extern struct mcidev_sysfs_attribute amd64_dbg_attrs[NUM_DBG_ATTRS],
amd64_inj_attrs[NUM_INJ_ATTRS];
/*
* Each of the PCI Device IDs types have their own set of hardware accessor
* functions and per device encoding/decoding logic.
......@@ -460,3 +473,5 @@ int __amd64_write_pci_cfg_dword(struct pci_dev *pdev, int offset,
int amd64_get_dram_hole_info(struct mem_ctl_info *mci, u64 *hole_base,
u64 *hole_offset, u64 *hole_size);
#define to_mci(k) container_of(k, struct mem_ctl_info, dev)
#include "amd64_edac.h"
#define EDAC_DCT_ATTR_SHOW(reg) \
static ssize_t amd64_##reg##_show(struct mem_ctl_info *mci, char *data) \
static ssize_t amd64_##reg##_show(struct device *dev, \
struct device_attribute *mattr, \
char *data) \
{ \
struct mem_ctl_info *mci = to_mci(dev); \
struct amd64_pvt *pvt = mci->pvt_info; \
return sprintf(data, "0x%016llx\n", (u64)pvt->reg); \
}
......@@ -12,8 +15,12 @@ EDAC_DCT_ATTR_SHOW(dbam0);
EDAC_DCT_ATTR_SHOW(top_mem);
EDAC_DCT_ATTR_SHOW(top_mem2);
static ssize_t amd64_hole_show(struct mem_ctl_info *mci, char *data)
static ssize_t amd64_hole_show(struct device *dev,
struct device_attribute *mattr,
char *data)
{
struct mem_ctl_info *mci = to_mci(dev);
u64 hole_base = 0;
u64 hole_offset = 0;
u64 hole_size = 0;
......@@ -27,46 +34,40 @@ static ssize_t amd64_hole_show(struct mem_ctl_info *mci, char *data)
/*
* update NUM_DBG_ATTRS in case you add new members
*/
struct mcidev_sysfs_attribute amd64_dbg_attrs[] = {
static DEVICE_ATTR(dhar, S_IRUGO, amd64_dhar_show, NULL);
static DEVICE_ATTR(dbam, S_IRUGO, amd64_dbam0_show, NULL);
static DEVICE_ATTR(topmem, S_IRUGO, amd64_top_mem_show, NULL);
static DEVICE_ATTR(topmem2, S_IRUGO, amd64_top_mem2_show, NULL);
static DEVICE_ATTR(dram_hole, S_IRUGO, amd64_hole_show, NULL);
int amd64_create_sysfs_dbg_files(struct mem_ctl_info *mci)
{
int rc;
rc = device_create_file(&mci->dev, &dev_attr_dhar);
if (rc < 0)
return rc;
rc = device_create_file(&mci->dev, &dev_attr_dbam);
if (rc < 0)
return rc;
rc = device_create_file(&mci->dev, &dev_attr_topmem);
if (rc < 0)
return rc;
rc = device_create_file(&mci->dev, &dev_attr_topmem2);
if (rc < 0)
return rc;
rc = device_create_file(&mci->dev, &dev_attr_dram_hole);
if (rc < 0)
return rc;
{
.attr = {
.name = "dhar",
.mode = (S_IRUGO)
},
.show = amd64_dhar_show,
.store = NULL,
},
{
.attr = {
.name = "dbam",
.mode = (S_IRUGO)
},
.show = amd64_dbam0_show,
.store = NULL,
},
{
.attr = {
.name = "topmem",
.mode = (S_IRUGO)
},
.show = amd64_top_mem_show,
.store = NULL,
},
{
.attr = {
.name = "topmem2",
.mode = (S_IRUGO)
},
.show = amd64_top_mem2_show,
.store = NULL,
},
{
.attr = {
.name = "dram_hole",
.mode = (S_IRUGO)
},
.show = amd64_hole_show,
.store = NULL,
},
};
return 0;
}
void amd64_remove_sysfs_dbg_files(struct mem_ctl_info *mci)
{
device_remove_file(&mci->dev, &dev_attr_dhar);
device_remove_file(&mci->dev, &dev_attr_dbam);
device_remove_file(&mci->dev, &dev_attr_topmem);
device_remove_file(&mci->dev, &dev_attr_topmem2);
device_remove_file(&mci->dev, &dev_attr_dram_hole);
}
#include "amd64_edac.h"
static ssize_t amd64_inject_section_show(struct mem_ctl_info *mci, char *buf)
static ssize_t amd64_inject_section_show(struct device *dev,
struct device_attribute *mattr,
char *buf)
{
struct mem_ctl_info *mci = to_mci(dev);
struct amd64_pvt *pvt = mci->pvt_info;
return sprintf(buf, "0x%x\n", pvt->injection.section);
}
......@@ -12,9 +15,11 @@ static ssize_t amd64_inject_section_show(struct mem_ctl_info *mci, char *buf)
*
* range: 0..3
*/
static ssize_t amd64_inject_section_store(struct mem_ctl_info *mci,
static ssize_t amd64_inject_section_store(struct device *dev,
struct device_attribute *mattr,
const char *data, size_t count)
{
struct mem_ctl_info *mci = to_mci(dev);
struct amd64_pvt *pvt = mci->pvt_info;
unsigned long value;
int ret = 0;
......@@ -33,8 +38,11 @@ static ssize_t amd64_inject_section_store(struct mem_ctl_info *mci,
return ret;
}
static ssize_t amd64_inject_word_show(struct mem_ctl_info *mci, char *buf)
static ssize_t amd64_inject_word_show(struct device *dev,
struct device_attribute *mattr,
char *buf)
{
struct mem_ctl_info *mci = to_mci(dev);
struct amd64_pvt *pvt = mci->pvt_info;
return sprintf(buf, "0x%x\n", pvt->injection.word);
}
......@@ -45,9 +53,11 @@ static ssize_t amd64_inject_word_show(struct mem_ctl_info *mci, char *buf)
*
* range: 0..8
*/
static ssize_t amd64_inject_word_store(struct mem_ctl_info *mci,
const char *data, size_t count)
static ssize_t amd64_inject_word_store(struct device *dev,
struct device_attribute *mattr,
const char *data, size_t count)
{
struct mem_ctl_info *mci = to_mci(dev);
struct amd64_pvt *pvt = mci->pvt_info;
unsigned long value;
int ret = 0;
......@@ -66,8 +76,11 @@ static ssize_t amd64_inject_word_store(struct mem_ctl_info *mci,
return ret;
}
static ssize_t amd64_inject_ecc_vector_show(struct mem_ctl_info *mci, char *buf)
static ssize_t amd64_inject_ecc_vector_show(struct device *dev,
struct device_attribute *mattr,
char *buf)
{
struct mem_ctl_info *mci = to_mci(dev);
struct amd64_pvt *pvt = mci->pvt_info;
return sprintf(buf, "0x%x\n", pvt->injection.bit_map);
}
......@@ -77,9 +90,11 @@ static ssize_t amd64_inject_ecc_vector_show(struct mem_ctl_info *mci, char *buf)
* corresponding bit within the error injection word above. When used during a
* DRAM ECC read, it holds the contents of the of the DRAM ECC bits.
*/
static ssize_t amd64_inject_ecc_vector_store(struct mem_ctl_info *mci,
const char *data, size_t count)
static ssize_t amd64_inject_ecc_vector_store(struct device *dev,
struct device_attribute *mattr,
const char *data, size_t count)
{
struct mem_ctl_info *mci = to_mci(dev);
struct amd64_pvt *pvt = mci->pvt_info;
unsigned long value;
int ret = 0;
......@@ -103,9 +118,11 @@ static ssize_t amd64_inject_ecc_vector_store(struct mem_ctl_info *mci,
* Do a DRAM ECC read. Assemble staged values in the pvt area, format into
* fields needed by the injection registers and read the NB Array Data Port.
*/
static ssize_t amd64_inject_read_store(struct mem_ctl_info *mci,
const char *data, size_t count)
static ssize_t amd64_inject_read_store(struct device *dev,
struct device_attribute *mattr,
const char *data, size_t count)
{
struct mem_ctl_info *mci = to_mci(dev);
struct amd64_pvt *pvt = mci->pvt_info;
unsigned long value;
u32 section, word_bits;
......@@ -125,7 +142,8 @@ static ssize_t amd64_inject_read_store(struct mem_ctl_info *mci,
/* Issue 'word' and 'bit' along with the READ request */
amd64_write_pci_cfg(pvt->F3, F10_NB_ARRAY_DATA, word_bits);
debugf0("section=0x%x word_bits=0x%x\n", section, word_bits);
edac_dbg(0, "section=0x%x word_bits=0x%x\n",
section, word_bits);
return count;
}
......@@ -136,9 +154,11 @@ static ssize_t amd64_inject_read_store(struct mem_ctl_info *mci,
* Do a DRAM ECC write. Assemble staged values in the pvt area and format into
* fields needed by the injection registers.
*/
static ssize_t amd64_inject_write_store(struct mem_ctl_info *mci,
static ssize_t amd64_inject_write_store(struct device *dev,
struct device_attribute *mattr,
const char *data, size_t count)
{
struct mem_ctl_info *mci = to_mci(dev);
struct amd64_pvt *pvt = mci->pvt_info;
unsigned long value;
u32 section, word_bits;
......@@ -158,7 +178,8 @@ static ssize_t amd64_inject_write_store(struct mem_ctl_info *mci,
/* Issue 'word' and 'bit' along with the READ request */
amd64_write_pci_cfg(pvt->F3, F10_NB_ARRAY_DATA, word_bits);
debugf0("section=0x%x word_bits=0x%x\n", section, word_bits);
edac_dbg(0, "section=0x%x word_bits=0x%x\n",
section, word_bits);
return count;
}
......@@ -168,46 +189,47 @@ static ssize_t amd64_inject_write_store(struct mem_ctl_info *mci,
/*
* update NUM_INJ_ATTRS in case you add new members
*/
struct mcidev_sysfs_attribute amd64_inj_attrs[] = {
{
.attr = {
.name = "inject_section",
.mode = (S_IRUGO | S_IWUSR)
},
.show = amd64_inject_section_show,
.store = amd64_inject_section_store,
},
{
.attr = {
.name = "inject_word",
.mode = (S_IRUGO | S_IWUSR)
},
.show = amd64_inject_word_show,
.store = amd64_inject_word_store,
},
{
.attr = {
.name = "inject_ecc_vector",
.mode = (S_IRUGO | S_IWUSR)
},
.show = amd64_inject_ecc_vector_show,
.store = amd64_inject_ecc_vector_store,
},
{
.attr = {
.name = "inject_write",
.mode = (S_IRUGO | S_IWUSR)
},
.show = NULL,
.store = amd64_inject_write_store,
},
{
.attr = {
.name = "inject_read",
.mode = (S_IRUGO | S_IWUSR)
},
.show = NULL,
.store = amd64_inject_read_store,
},
};
static DEVICE_ATTR(inject_section, S_IRUGO | S_IWUSR,
amd64_inject_section_show, amd64_inject_section_store);
static DEVICE_ATTR(inject_word, S_IRUGO | S_IWUSR,
amd64_inject_word_show, amd64_inject_word_store);
static DEVICE_ATTR(inject_ecc_vector, S_IRUGO | S_IWUSR,
amd64_inject_ecc_vector_show, amd64_inject_ecc_vector_store);
static DEVICE_ATTR(inject_write, S_IRUGO | S_IWUSR,
NULL, amd64_inject_write_store);
static DEVICE_ATTR(inject_read, S_IRUGO | S_IWUSR,
NULL, amd64_inject_read_store);
int amd64_create_sysfs_inject_files(struct mem_ctl_info *mci)
{
int rc;
rc = device_create_file(&mci->dev, &dev_attr_inject_section);
if (rc < 0)
return rc;
rc = device_create_file(&mci->dev, &dev_attr_inject_word);
if (rc < 0)
return rc;
rc = device_create_file(&mci->dev, &dev_attr_inject_ecc_vector);
if (rc < 0)
return rc;
rc = device_create_file(&mci->dev, &dev_attr_inject_write);
if (rc < 0)
return rc;
rc = device_create_file(&mci->dev, &dev_attr_inject_read);
if (rc < 0)
return rc;
return 0;
}
void amd64_remove_sysfs_inject_files(struct mem_ctl_info *mci)
{
device_remove_file(&mci->dev, &dev_attr_inject_section);
device_remove_file(&mci->dev, &dev_attr_inject_word);
device_remove_file(&mci->dev, &dev_attr_inject_ecc_vector);
device_remove_file(&mci->dev, &dev_attr_inject_write);
device_remove_file(&mci->dev, &dev_attr_inject_read);
}
......@@ -105,7 +105,7 @@ static void amd76x_get_error_info(struct mem_ctl_info *mci,
{
struct pci_dev *pdev;
pdev = to_pci_dev(mci->dev);
pdev = to_pci_dev(mci->pdev);
pci_read_config_dword(pdev, AMD76X_ECC_MODE_STATUS,
&info->ecc_mode_status);
......@@ -145,10 +145,10 @@ static int amd76x_process_error_info(struct mem_ctl_info *mci,
if (handle_errors) {
row = (info->ecc_mode_status >> 4) & 0xf;
edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci,
mci->csrows[row].first_page, 0, 0,
edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1,
mci->csrows[row]->first_page, 0, 0,
row, 0, -1,
mci->ctl_name, "", NULL);
mci->ctl_name, "");
}
}
......@@ -160,10 +160,10 @@ static int amd76x_process_error_info(struct mem_ctl_info *mci,
if (handle_errors) {
row = info->ecc_mode_status & 0xf;
edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci,
mci->csrows[row].first_page, 0, 0,
edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1,
mci->csrows[row]->first_page, 0, 0,
row, 0, -1,
mci->ctl_name, "", NULL);
mci->ctl_name, "");
}
}
......@@ -180,7 +180,7 @@ static int amd76x_process_error_info(struct mem_ctl_info *mci,
static void amd76x_check(struct mem_ctl_info *mci)
{
struct amd76x_error_info info;
debugf3("%s()\n", __func__);
edac_dbg(3, "\n");
amd76x_get_error_info(mci, &info);
amd76x_process_error_info(mci, &info, 1);
}
......@@ -194,8 +194,8 @@ static void amd76x_init_csrows(struct mem_ctl_info *mci, struct pci_dev *pdev,
int index;
for (index = 0; index < mci->nr_csrows; index++) {
csrow = &mci->csrows[index];
dimm = csrow->channels[0].dimm;
csrow = mci->csrows[index];
dimm = csrow->channels[0]->dimm;
/* find the DRAM Chip Select Base address and mask */
pci_read_config_dword(pdev,
......@@ -241,7 +241,7 @@ static int amd76x_probe1(struct pci_dev *pdev, int dev_idx)
u32 ems_mode;
struct amd76x_error_info discard;
debugf0("%s()\n", __func__);
edac_dbg(0, "\n");
pci_read_config_dword(pdev, AMD76X_ECC_MODE_STATUS, &ems);
ems_mode = (ems >> 10) & 0x3;
......@@ -256,8 +256,8 @@ static int amd76x_probe1(struct pci_dev *pdev, int dev_idx)
if (mci == NULL)
return -ENOMEM;
debugf0("%s(): mci = %p\n", __func__, mci);
mci->dev = &pdev->dev;
edac_dbg(0, "mci = %p\n", mci);
mci->pdev = &pdev->dev;
mci->mtype_cap = MEM_FLAG_RDDR;
mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_EC | EDAC_FLAG_SECDED;
mci->edac_cap = ems_mode ?
......@@ -276,7 +276,7 @@ static int amd76x_probe1(struct pci_dev *pdev, int dev_idx)
* type of memory controller. The ID is therefore hardcoded to 0.
*/
if (edac_mc_add_mc(mci)) {
debugf3("%s(): failed edac_mc_add_mc()\n", __func__);
edac_dbg(3, "failed edac_mc_add_mc()\n");
goto fail;
}
......@@ -292,7 +292,7 @@ static int amd76x_probe1(struct pci_dev *pdev, int dev_idx)
}
/* get this far and it's successful */
debugf3("%s(): success\n", __func__);
edac_dbg(3, "success\n");
return 0;
fail:
......@@ -304,7 +304,7 @@ static int amd76x_probe1(struct pci_dev *pdev, int dev_idx)
static int __devinit amd76x_init_one(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
debugf0("%s()\n", __func__);
edac_dbg(0, "\n");
/* don't need to call pci_enable_device() */
return amd76x_probe1(pdev, ent->driver_data);
......@@ -322,7 +322,7 @@ static void __devexit amd76x_remove_one(struct pci_dev *pdev)
{
struct mem_ctl_info *mci;
debugf0("%s()\n", __func__);
edac_dbg(0, "\n");
if (amd76x_pci)
edac_pci_release_generic_ctl(amd76x_pci);
......
......@@ -33,10 +33,10 @@ struct cell_edac_priv
static void cell_edac_count_ce(struct mem_ctl_info *mci, int chan, u64 ar)
{
struct cell_edac_priv *priv = mci->pvt_info;
struct csrow_info *csrow = &mci->csrows[0];
struct csrow_info *csrow = mci->csrows[0];
unsigned long address, pfn, offset, syndrome;
dev_dbg(mci->dev, "ECC CE err on node %d, channel %d, ar = 0x%016llx\n",
dev_dbg(mci->pdev, "ECC CE err on node %d, channel %d, ar = 0x%016llx\n",
priv->node, chan, ar);
/* Address decoding is likely a bit bogus, to dbl check */
......@@ -48,18 +48,18 @@ static void cell_edac_count_ce(struct mem_ctl_info *mci, int chan, u64 ar)
syndrome = (ar & 0x000000001fe00000ul) >> 21;
/* TODO: Decoding of the error address */
edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci,
edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1,
csrow->first_page + pfn, offset, syndrome,
0, chan, -1, "", "", NULL);
0, chan, -1, "", "");
}
static void cell_edac_count_ue(struct mem_ctl_info *mci, int chan, u64 ar)
{
struct cell_edac_priv *priv = mci->pvt_info;
struct csrow_info *csrow = &mci->csrows[0];
struct csrow_info *csrow = mci->csrows[0];
unsigned long address, pfn, offset;
dev_dbg(mci->dev, "ECC UE err on node %d, channel %d, ar = 0x%016llx\n",
dev_dbg(mci->pdev, "ECC UE err on node %d, channel %d, ar = 0x%016llx\n",
priv->node, chan, ar);
/* Address decoding is likely a bit bogus, to dbl check */
......@@ -70,9 +70,9 @@ static void cell_edac_count_ue(struct mem_ctl_info *mci, int chan, u64 ar)
offset = address & ~PAGE_MASK;
/* TODO: Decoding of the error address */
edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci,
edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1,
csrow->first_page + pfn, offset, 0,
0, chan, -1, "", "", NULL);
0, chan, -1, "", "");
}
static void cell_edac_check(struct mem_ctl_info *mci)
......@@ -83,7 +83,7 @@ static void cell_edac_check(struct mem_ctl_info *mci)
fir = in_be64(&priv->regs->mic_fir);
#ifdef DEBUG
if (fir != priv->prev_fir) {
dev_dbg(mci->dev, "fir change : 0x%016lx\n", fir);
dev_dbg(mci->pdev, "fir change : 0x%016lx\n", fir);
priv->prev_fir = fir;
}
#endif
......@@ -119,14 +119,14 @@ static void cell_edac_check(struct mem_ctl_info *mci)
mb(); /* sync up */
#ifdef DEBUG
fir = in_be64(&priv->regs->mic_fir);
dev_dbg(mci->dev, "fir clear : 0x%016lx\n", fir);
dev_dbg(mci->pdev, "fir clear : 0x%016lx\n", fir);
#endif
}
}
static void __devinit cell_edac_init_csrows(struct mem_ctl_info *mci)
{
struct csrow_info *csrow = &mci->csrows[0];
struct csrow_info *csrow = mci->csrows[0];
struct dimm_info *dimm;
struct cell_edac_priv *priv = mci->pvt_info;
struct device_node *np;
......@@ -150,12 +150,12 @@ static void __devinit cell_edac_init_csrows(struct mem_ctl_info *mci)
csrow->last_page = csrow->first_page + nr_pages - 1;
for (j = 0; j < csrow->nr_channels; j++) {
dimm = csrow->channels[j].dimm;
dimm = csrow->channels[j]->dimm;
dimm->mtype = MEM_XDR;
dimm->edac_mode = EDAC_SECDED;
dimm->nr_pages = nr_pages / csrow->nr_channels;
}
dev_dbg(mci->dev,
dev_dbg(mci->pdev,
"Initialized on node %d, chanmask=0x%x,"
" first_page=0x%lx, nr_pages=0x%x\n",
priv->node, priv->chanmask,
......@@ -212,7 +212,7 @@ static int __devinit cell_edac_probe(struct platform_device *pdev)
priv->regs = regs;
priv->node = pdev->id;
priv->chanmask = chanmask;
mci->dev = &pdev->dev;
mci->pdev = &pdev->dev;
mci->mtype_cap = MEM_FLAG_XDR;
mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_EC | EDAC_FLAG_SECDED;
mci->edac_cap = EDAC_FLAG_EC | EDAC_FLAG_SECDED;
......
......@@ -316,13 +316,12 @@ static void get_total_mem(struct cpc925_mc_pdata *pdata)
reg += aw;
size = of_read_number(reg, sw);
reg += sw;
debugf1("%s: start 0x%lx, size 0x%lx\n", __func__,
start, size);
edac_dbg(1, "start 0x%lx, size 0x%lx\n", start, size);
pdata->total_mem += size;
} while (reg < reg_end);
of_node_put(np);
debugf0("%s: total_mem 0x%lx\n", __func__, pdata->total_mem);
edac_dbg(0, "total_mem 0x%lx\n", pdata->total_mem);
}
static void cpc925_init_csrows(struct mem_ctl_info *mci)
......@@ -330,8 +329,9 @@ static void cpc925_init_csrows(struct mem_ctl_info *mci)
struct cpc925_mc_pdata *pdata = mci->pvt_info;
struct csrow_info *csrow;
struct dimm_info *dimm;
enum dev_type dtype;
int index, j;
u32 mbmr, mbbar, bba;
u32 mbmr, mbbar, bba, grain;
unsigned long row_size, nr_pages, last_nr_pages = 0;
get_total_mem(pdata);
......@@ -347,7 +347,7 @@ static void cpc925_init_csrows(struct mem_ctl_info *mci)
if (bba == 0)
continue; /* not populated */
csrow = &mci->csrows[index];
csrow = mci->csrows[index];
row_size = bba * (1UL << 28); /* 256M */
csrow->first_page = last_nr_pages;
......@@ -355,37 +355,36 @@ static void cpc925_init_csrows(struct mem_ctl_info *mci)
csrow->last_page = csrow->first_page + nr_pages - 1;
last_nr_pages = csrow->last_page + 1;
switch (csrow->nr_channels) {
case 1: /* Single channel */
grain = 32; /* four-beat burst of 32 bytes */
break;
case 2: /* Dual channel */
default:
grain = 64; /* four-beat burst of 64 bytes */
break;
}
switch ((mbmr & MBMR_MODE_MASK) >> MBMR_MODE_SHIFT) {
case 6: /* 0110, no way to differentiate X8 VS X16 */
case 5: /* 0101 */
case 8: /* 1000 */
dtype = DEV_X16;
break;
case 7: /* 0111 */
case 9: /* 1001 */
dtype = DEV_X8;
break;
default:
dtype = DEV_UNKNOWN;
break;
}
for (j = 0; j < csrow->nr_channels; j++) {
dimm = csrow->channels[j].dimm;
dimm = csrow->channels[j]->dimm;
dimm->nr_pages = nr_pages / csrow->nr_channels;
dimm->mtype = MEM_RDDR;
dimm->edac_mode = EDAC_SECDED;
switch (csrow->nr_channels) {
case 1: /* Single channel */
dimm->grain = 32; /* four-beat burst of 32 bytes */
break;
case 2: /* Dual channel */
default:
dimm->grain = 64; /* four-beat burst of 64 bytes */
break;
}
switch ((mbmr & MBMR_MODE_MASK) >> MBMR_MODE_SHIFT) {
case 6: /* 0110, no way to differentiate X8 VS X16 */
case 5: /* 0101 */
case 8: /* 1000 */
dimm->dtype = DEV_X16;
break;
case 7: /* 0111 */
case 9: /* 1001 */
dimm->dtype = DEV_X8;
break;
default:
dimm->dtype = DEV_UNKNOWN;
break;
}
dimm->grain = grain;
dimm->dtype = dtype;
}
}
}
......@@ -463,7 +462,7 @@ static void cpc925_mc_get_pfn(struct mem_ctl_info *mci, u32 mear,
*csrow = rank;
#ifdef CONFIG_EDAC_DEBUG
if (mci->csrows[rank].first_page == 0) {
if (mci->csrows[rank]->first_page == 0) {
cpc925_mc_printk(mci, KERN_ERR, "ECC occurs in a "
"non-populated csrow, broken hardware?\n");
return;
......@@ -471,7 +470,7 @@ static void cpc925_mc_get_pfn(struct mem_ctl_info *mci, u32 mear,
#endif
/* Revert csrow number */
pa = mci->csrows[rank].first_page << PAGE_SHIFT;
pa = mci->csrows[rank]->first_page << PAGE_SHIFT;
/* Revert column address */
col += bcnt;
......@@ -512,7 +511,7 @@ static void cpc925_mc_get_pfn(struct mem_ctl_info *mci, u32 mear,
*offset = pa & (PAGE_SIZE - 1);
*pfn = pa >> PAGE_SHIFT;
debugf0("%s: ECC physical address 0x%lx\n", __func__, pa);
edac_dbg(0, "ECC physical address 0x%lx\n", pa);
}
static int cpc925_mc_find_channel(struct mem_ctl_info *mci, u16 syndrome)
......@@ -555,18 +554,18 @@ static void cpc925_mc_check(struct mem_ctl_info *mci)
if (apiexcp & CECC_EXCP_DETECTED) {
cpc925_mc_printk(mci, KERN_INFO, "DRAM CECC Fault\n");
channel = cpc925_mc_find_channel(mci, syndrome);
edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci,
edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1,
pfn, offset, syndrome,
csrow, channel, -1,
mci->ctl_name, "", NULL);
mci->ctl_name, "");
}
if (apiexcp & UECC_EXCP_DETECTED) {
cpc925_mc_printk(mci, KERN_INFO, "DRAM UECC Fault\n");
edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci,
edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1,
pfn, offset, 0,
csrow, -1, -1,
mci->ctl_name, "", NULL);
mci->ctl_name, "");
}
cpc925_mc_printk(mci, KERN_INFO, "Dump registers:\n");
......@@ -852,8 +851,8 @@ static void cpc925_add_edac_devices(void __iomem *vbase)
goto err2;
}
debugf0("%s: Successfully added edac device for %s\n",
__func__, dev_info->ctl_name);
edac_dbg(0, "Successfully added edac device for %s\n",
dev_info->ctl_name);
continue;
......@@ -884,8 +883,8 @@ static void cpc925_del_edac_devices(void)
if (dev_info->exit)
dev_info->exit(dev_info);
debugf0("%s: Successfully deleted edac device for %s\n",
__func__, dev_info->ctl_name);
edac_dbg(0, "Successfully deleted edac device for %s\n",
dev_info->ctl_name);
}
}
......@@ -900,7 +899,7 @@ static int cpc925_get_sdram_scrub_rate(struct mem_ctl_info *mci)
mscr = __raw_readl(pdata->vbase + REG_MSCR_OFFSET);
si = (mscr & MSCR_SI_MASK) >> MSCR_SI_SHIFT;
debugf0("%s, Mem Scrub Ctrl Register 0x%x\n", __func__, mscr);
edac_dbg(0, "Mem Scrub Ctrl Register 0x%x\n", mscr);
if (((mscr & MSCR_SCRUB_MOD_MASK) != MSCR_BACKGR_SCRUB) ||
(si == 0)) {
......@@ -928,8 +927,7 @@ static int cpc925_mc_get_channels(void __iomem *vbase)
((mbcr & MBCR_64BITBUS_MASK) == 0))
dual = 1;
debugf0("%s: %s channel\n", __func__,
(dual > 0) ? "Dual" : "Single");
edac_dbg(0, "%s channel\n", (dual > 0) ? "Dual" : "Single");
return dual;
}
......@@ -944,7 +942,7 @@ static int __devinit cpc925_probe(struct platform_device *pdev)
struct resource *r;
int res = 0, nr_channels;
debugf0("%s: %s platform device found!\n", __func__, pdev->name);
edac_dbg(0, "%s platform device found!\n", pdev->name);
if (!devres_open_group(&pdev->dev, cpc925_probe, GFP_KERNEL)) {
res = -ENOMEM;
......@@ -995,7 +993,7 @@ static int __devinit cpc925_probe(struct platform_device *pdev)
pdata->edac_idx = edac_mc_idx++;
pdata->name = pdev->name;
mci->dev = &pdev->dev;
mci->pdev = &pdev->dev;
platform_set_drvdata(pdev, mci);
mci->dev_name = dev_name(&pdev->dev);
mci->mtype_cap = MEM_FLAG_RDDR | MEM_FLAG_DDR;
......@@ -1026,7 +1024,7 @@ static int __devinit cpc925_probe(struct platform_device *pdev)
cpc925_add_edac_devices(vbase);
/* get this far and it's successful */
debugf0("%s: success\n", __func__);
edac_dbg(0, "success\n");
res = 0;
goto out;
......
......@@ -309,7 +309,7 @@ static unsigned long ctl_page_to_phys(struct mem_ctl_info *mci,
u32 remap;
struct e752x_pvt *pvt = (struct e752x_pvt *)mci->pvt_info;
debugf3("%s()\n", __func__);
edac_dbg(3, "\n");
if (page < pvt->tolm)
return page;
......@@ -335,7 +335,7 @@ static void do_process_ce(struct mem_ctl_info *mci, u16 error_one,
int i;
struct e752x_pvt *pvt = (struct e752x_pvt *)mci->pvt_info;
debugf3("%s()\n", __func__);
edac_dbg(3, "\n");
/* convert the addr to 4k page */
page = sec1_add >> (PAGE_SHIFT - 4);
......@@ -371,10 +371,10 @@ static void do_process_ce(struct mem_ctl_info *mci, u16 error_one,
channel = !(error_one & 1);
/* e752x mc reads 34:6 of the DRAM linear address */
edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci,
edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1,
page, offset_in_page(sec1_add << 4), sec1_syndrome,
row, channel, -1,
"e752x CE", "", NULL);
"e752x CE", "");
}
static inline void process_ce(struct mem_ctl_info *mci, u16 error_one,
......@@ -394,7 +394,7 @@ static void do_process_ue(struct mem_ctl_info *mci, u16 error_one,
int row;
struct e752x_pvt *pvt = (struct e752x_pvt *)mci->pvt_info;
debugf3("%s()\n", __func__);
edac_dbg(3, "\n");
if (error_one & 0x0202) {
error_2b = ded_add;
......@@ -408,11 +408,11 @@ static void do_process_ue(struct mem_ctl_info *mci, u16 error_one,
edac_mc_find_csrow_by_page(mci, block_page);
/* e752x mc reads 34:6 of the DRAM linear address */
edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci,
edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1,
block_page,
offset_in_page(error_2b << 4), 0,
row, -1, -1,
"e752x UE from Read", "", NULL);
"e752x UE from Read", "");
}
if (error_one & 0x0404) {
......@@ -427,11 +427,11 @@ static void do_process_ue(struct mem_ctl_info *mci, u16 error_one,
edac_mc_find_csrow_by_page(mci, block_page);
/* e752x mc reads 34:6 of the DRAM linear address */
edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci,
edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1,
block_page,
offset_in_page(error_2b << 4), 0,
row, -1, -1,
"e752x UE from Scruber", "", NULL);
"e752x UE from Scruber", "");
}
}
......@@ -453,10 +453,10 @@ static inline void process_ue_no_info_wr(struct mem_ctl_info *mci,
if (!handle_error)
return;
debugf3("%s()\n", __func__);
edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 0, 0, 0,
edac_dbg(3, "\n");
edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, 0, 0, 0,
-1, -1, -1,
"e752x UE log memory write", "", NULL);
"e752x UE log memory write", "");
}
static void do_process_ded_retry(struct mem_ctl_info *mci, u16 error,
......@@ -982,7 +982,7 @@ static void e752x_check(struct mem_ctl_info *mci)
{
struct e752x_error_info info;
debugf3("%s()\n", __func__);
edac_dbg(3, "\n");
e752x_get_error_info(mci, &info);
e752x_process_error_info(mci, &info, 1);
}
......@@ -1069,6 +1069,7 @@ static void e752x_init_csrows(struct mem_ctl_info *mci, struct pci_dev *pdev,
u16 ddrcsr)
{
struct csrow_info *csrow;
enum edac_type edac_mode;
unsigned long last_cumul_size;
int index, mem_dev, drc_chan;
int drc_drbg; /* DRB granularity 0=64mb, 1=128mb */
......@@ -1095,14 +1096,13 @@ static void e752x_init_csrows(struct mem_ctl_info *mci, struct pci_dev *pdev,
for (last_cumul_size = index = 0; index < mci->nr_csrows; index++) {
/* mem_dev 0=x8, 1=x4 */
mem_dev = (dra >> (index * 4 + 2)) & 0x3;
csrow = &mci->csrows[remap_csrow_index(mci, index)];
csrow = mci->csrows[remap_csrow_index(mci, index)];
mem_dev = (mem_dev == 2);
pci_read_config_byte(pdev, E752X_DRB + index, &value);
/* convert a 128 or 64 MiB DRB to a page size. */
cumul_size = value << (25 + drc_drbg - PAGE_SHIFT);
debugf3("%s(): (%d) cumul_size 0x%x\n", __func__, index,
cumul_size);
edac_dbg(3, "(%d) cumul_size 0x%x\n", index, cumul_size);
if (cumul_size == last_cumul_size)
continue; /* not populated */
......@@ -1111,29 +1111,29 @@ static void e752x_init_csrows(struct mem_ctl_info *mci, struct pci_dev *pdev,
nr_pages = cumul_size - last_cumul_size;
last_cumul_size = cumul_size;
/*
* if single channel or x8 devices then SECDED
* if dual channel and x4 then S4ECD4ED
*/
if (drc_ddim) {
if (drc_chan && mem_dev) {
edac_mode = EDAC_S4ECD4ED;
mci->edac_cap |= EDAC_FLAG_S4ECD4ED;
} else {
edac_mode = EDAC_SECDED;
mci->edac_cap |= EDAC_FLAG_SECDED;
}
} else
edac_mode = EDAC_NONE;
for (i = 0; i < csrow->nr_channels; i++) {
struct dimm_info *dimm = csrow->channels[i].dimm;
struct dimm_info *dimm = csrow->channels[i]->dimm;
debugf3("Initializing rank at (%i,%i)\n", index, i);
edac_dbg(3, "Initializing rank at (%i,%i)\n", index, i);
dimm->nr_pages = nr_pages / csrow->nr_channels;
dimm->grain = 1 << 12; /* 4KiB - resolution of CELOG */
dimm->mtype = MEM_RDDR; /* only one type supported */
dimm->dtype = mem_dev ? DEV_X4 : DEV_X8;
/*
* if single channel or x8 devices then SECDED
* if dual channel and x4 then S4ECD4ED
*/
if (drc_ddim) {
if (drc_chan && mem_dev) {
dimm->edac_mode = EDAC_S4ECD4ED;
mci->edac_cap |= EDAC_FLAG_S4ECD4ED;
} else {
dimm->edac_mode = EDAC_SECDED;
mci->edac_cap |= EDAC_FLAG_SECDED;
}
} else
dimm->edac_mode = EDAC_NONE;
dimm->edac_mode = edac_mode;
}
}
}
......@@ -1269,8 +1269,8 @@ static int e752x_probe1(struct pci_dev *pdev, int dev_idx)
int drc_chan; /* Number of channels 0=1chan,1=2chan */
struct e752x_error_info discard;
debugf0("%s(): mci\n", __func__);
debugf0("Starting Probe1\n");
edac_dbg(0, "mci\n");
edac_dbg(0, "Starting Probe1\n");
/* check to see if device 0 function 1 is enabled; if it isn't, we
* assume the BIOS has reserved it for a reason and is expecting
......@@ -1300,7 +1300,7 @@ static int e752x_probe1(struct pci_dev *pdev, int dev_idx)
if (mci == NULL)
return -ENOMEM;
debugf3("%s(): init mci\n", __func__);
edac_dbg(3, "init mci\n");
mci->mtype_cap = MEM_FLAG_RDDR;
/* 3100 IMCH supports SECDEC only */
mci->edac_ctl_cap = (dev_idx == I3100) ? EDAC_FLAG_SECDED :
......@@ -1308,9 +1308,9 @@ static int e752x_probe1(struct pci_dev *pdev, int dev_idx)
/* FIXME - what if different memory types are in different csrows? */
mci->mod_name = EDAC_MOD_STR;
mci->mod_ver = E752X_REVISION;
mci->dev = &pdev->dev;
mci->pdev = &pdev->dev;
debugf3("%s(): init pvt\n", __func__);
edac_dbg(3, "init pvt\n");
pvt = (struct e752x_pvt *)mci->pvt_info;
pvt->dev_info = &e752x_devs[dev_idx];
pvt->mc_symmetric = ((ddrcsr & 0x10) != 0);
......@@ -1320,7 +1320,7 @@ static int e752x_probe1(struct pci_dev *pdev, int dev_idx)
return -ENODEV;
}
debugf3("%s(): more mci init\n", __func__);
edac_dbg(3, "more mci init\n");
mci->ctl_name = pvt->dev_info->ctl_name;
mci->dev_name = pci_name(pdev);
mci->edac_check = e752x_check;
......@@ -1342,7 +1342,7 @@ static int e752x_probe1(struct pci_dev *pdev, int dev_idx)
mci->edac_cap = EDAC_FLAG_SECDED; /* the only mode supported */
else
mci->edac_cap |= EDAC_FLAG_NONE;
debugf3("%s(): tolm, remapbase, remaplimit\n", __func__);
edac_dbg(3, "tolm, remapbase, remaplimit\n");
/* load the top of low memory, remap base, and remap limit vars */
pci_read_config_word(pdev, E752X_TOLM, &pci_data);
......@@ -1359,7 +1359,7 @@ static int e752x_probe1(struct pci_dev *pdev, int dev_idx)
* type of memory controller. The ID is therefore hardcoded to 0.
*/
if (edac_mc_add_mc(mci)) {
debugf3("%s(): failed edac_mc_add_mc()\n", __func__);
edac_dbg(3, "failed edac_mc_add_mc()\n");
goto fail;
}
......@@ -1377,7 +1377,7 @@ static int e752x_probe1(struct pci_dev *pdev, int dev_idx)
}
/* get this far and it's successful */
debugf3("%s(): success\n", __func__);
edac_dbg(3, "success\n");
return 0;
fail:
......@@ -1393,7 +1393,7 @@ static int e752x_probe1(struct pci_dev *pdev, int dev_idx)
static int __devinit e752x_init_one(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
debugf0("%s()\n", __func__);
edac_dbg(0, "\n");
/* wake up and enable device */
if (pci_enable_device(pdev) < 0)
......@@ -1407,7 +1407,7 @@ static void __devexit e752x_remove_one(struct pci_dev *pdev)
struct mem_ctl_info *mci;
struct e752x_pvt *pvt;
debugf0("%s()\n", __func__);
edac_dbg(0, "\n");
if (e752x_pci)
edac_pci_release_generic_ctl(e752x_pci);
......@@ -1453,7 +1453,7 @@ static int __init e752x_init(void)
{
int pci_rc;
debugf3("%s()\n", __func__);
edac_dbg(3, "\n");
/* Ensure that the OPSTATE is set correctly for POLL or NMI */
opstate_init();
......@@ -1464,7 +1464,7 @@ static int __init e752x_init(void)
static void __exit e752x_exit(void)
{
debugf3("%s()\n", __func__);
edac_dbg(3, "\n");
pci_unregister_driver(&e752x_driver);
}
......
......@@ -166,7 +166,7 @@ static const struct e7xxx_dev_info e7xxx_devs[] = {
/* FIXME - is this valid for both SECDED and S4ECD4ED? */
static inline int e7xxx_find_channel(u16 syndrome)
{
debugf3("%s()\n", __func__);
edac_dbg(3, "\n");
if ((syndrome & 0xff00) == 0)
return 0;
......@@ -186,7 +186,7 @@ static unsigned long ctl_page_to_phys(struct mem_ctl_info *mci,
u32 remap;
struct e7xxx_pvt *pvt = (struct e7xxx_pvt *)mci->pvt_info;
debugf3("%s()\n", __func__);
edac_dbg(3, "\n");
if ((page < pvt->tolm) ||
((page >= 0x100000) && (page < pvt->remapbase)))
......@@ -208,7 +208,7 @@ static void process_ce(struct mem_ctl_info *mci, struct e7xxx_error_info *info)
int row;
int channel;
debugf3("%s()\n", __func__);
edac_dbg(3, "\n");
/* read the error address */
error_1b = info->dram_celog_add;
/* FIXME - should use PAGE_SHIFT */
......@@ -219,15 +219,15 @@ static void process_ce(struct mem_ctl_info *mci, struct e7xxx_error_info *info)
row = edac_mc_find_csrow_by_page(mci, page);
/* convert syndrome to channel */
channel = e7xxx_find_channel(syndrome);
edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, page, 0, syndrome,
row, channel, -1, "e7xxx CE", "", NULL);
edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1, page, 0, syndrome,
row, channel, -1, "e7xxx CE", "");
}
static void process_ce_no_info(struct mem_ctl_info *mci)
{
debugf3("%s()\n", __func__);
edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 0, 0, 0, -1, -1, -1,
"e7xxx CE log register overflow", "", NULL);
edac_dbg(3, "\n");
edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, 0, 0, 0, -1, -1, -1,
"e7xxx CE log register overflow", "");
}
static void process_ue(struct mem_ctl_info *mci, struct e7xxx_error_info *info)
......@@ -235,23 +235,23 @@ static void process_ue(struct mem_ctl_info *mci, struct e7xxx_error_info *info)
u32 error_2b, block_page;
int row;
debugf3("%s()\n", __func__);
edac_dbg(3, "\n");
/* read the error address */
error_2b = info->dram_uelog_add;
/* FIXME - should use PAGE_SHIFT */
block_page = error_2b >> 6; /* convert to 4k address */
row = edac_mc_find_csrow_by_page(mci, block_page);
edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, block_page, 0, 0,
row, -1, -1, "e7xxx UE", "", NULL);
edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, block_page, 0, 0,
row, -1, -1, "e7xxx UE", "");
}
static void process_ue_no_info(struct mem_ctl_info *mci)
{
debugf3("%s()\n", __func__);
edac_dbg(3, "\n");
edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 0, 0, 0, -1, -1, -1,
"e7xxx UE log register overflow", "", NULL);
edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, 0, 0, 0, -1, -1, -1,
"e7xxx UE log register overflow", "");
}
static void e7xxx_get_error_info(struct mem_ctl_info *mci,
......@@ -334,7 +334,7 @@ static void e7xxx_check(struct mem_ctl_info *mci)
{
struct e7xxx_error_info info;
debugf3("%s()\n", __func__);
edac_dbg(3, "\n");
e7xxx_get_error_info(mci, &info);
e7xxx_process_error_info(mci, &info, 1);
}
......@@ -362,6 +362,7 @@ static void e7xxx_init_csrows(struct mem_ctl_info *mci, struct pci_dev *pdev,
int drc_chan, drc_drbg, drc_ddim, mem_dev;
struct csrow_info *csrow;
struct dimm_info *dimm;
enum edac_type edac_mode;
pci_read_config_dword(pdev, E7XXX_DRA, &dra);
drc_chan = dual_channel_active(drc, dev_idx);
......@@ -377,13 +378,12 @@ static void e7xxx_init_csrows(struct mem_ctl_info *mci, struct pci_dev *pdev,
for (index = 0; index < mci->nr_csrows; index++) {
/* mem_dev 0=x8, 1=x4 */
mem_dev = (dra >> (index * 4 + 3)) & 0x1;
csrow = &mci->csrows[index];
csrow = mci->csrows[index];
pci_read_config_byte(pdev, E7XXX_DRB + index, &value);
/* convert a 64 or 32 MiB DRB to a page size. */
cumul_size = value << (25 + drc_drbg - PAGE_SHIFT);
debugf3("%s(): (%d) cumul_size 0x%x\n", __func__, index,
cumul_size);
edac_dbg(3, "(%d) cumul_size 0x%x\n", index, cumul_size);
if (cumul_size == last_cumul_size)
continue; /* not populated */
......@@ -392,28 +392,29 @@ static void e7xxx_init_csrows(struct mem_ctl_info *mci, struct pci_dev *pdev,
nr_pages = cumul_size - last_cumul_size;
last_cumul_size = cumul_size;
/*
* if single channel or x8 devices then SECDED
* if dual channel and x4 then S4ECD4ED
*/
if (drc_ddim) {
if (drc_chan && mem_dev) {
edac_mode = EDAC_S4ECD4ED;
mci->edac_cap |= EDAC_FLAG_S4ECD4ED;
} else {
edac_mode = EDAC_SECDED;
mci->edac_cap |= EDAC_FLAG_SECDED;
}
} else
edac_mode = EDAC_NONE;
for (j = 0; j < drc_chan + 1; j++) {
dimm = csrow->channels[j].dimm;
dimm = csrow->channels[j]->dimm;
dimm->nr_pages = nr_pages / (drc_chan + 1);
dimm->grain = 1 << 12; /* 4KiB - resolution of CELOG */
dimm->mtype = MEM_RDDR; /* only one type supported */
dimm->dtype = mem_dev ? DEV_X4 : DEV_X8;
/*
* if single channel or x8 devices then SECDED
* if dual channel and x4 then S4ECD4ED
*/
if (drc_ddim) {
if (drc_chan && mem_dev) {
dimm->edac_mode = EDAC_S4ECD4ED;
mci->edac_cap |= EDAC_FLAG_S4ECD4ED;
} else {
dimm->edac_mode = EDAC_SECDED;
mci->edac_cap |= EDAC_FLAG_SECDED;
}
} else
dimm->edac_mode = EDAC_NONE;
dimm->edac_mode = edac_mode;
}
}
}
......@@ -428,7 +429,7 @@ static int e7xxx_probe1(struct pci_dev *pdev, int dev_idx)
int drc_chan;
struct e7xxx_error_info discard;
debugf0("%s(): mci\n", __func__);
edac_dbg(0, "mci\n");
pci_read_config_dword(pdev, E7XXX_DRC, &drc);
......@@ -451,15 +452,15 @@ static int e7xxx_probe1(struct pci_dev *pdev, int dev_idx)
if (mci == NULL)
return -ENOMEM;
debugf3("%s(): init mci\n", __func__);
edac_dbg(3, "init mci\n");
mci->mtype_cap = MEM_FLAG_RDDR;
mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED |
EDAC_FLAG_S4ECD4ED;
/* FIXME - what if different memory types are in different csrows? */
mci->mod_name = EDAC_MOD_STR;
mci->mod_ver = E7XXX_REVISION;
mci->dev = &pdev->dev;
debugf3("%s(): init pvt\n", __func__);
mci->pdev = &pdev->dev;
edac_dbg(3, "init pvt\n");
pvt = (struct e7xxx_pvt *)mci->pvt_info;
pvt->dev_info = &e7xxx_devs[dev_idx];
pvt->bridge_ck = pci_get_device(PCI_VENDOR_ID_INTEL,
......@@ -472,14 +473,14 @@ static int e7xxx_probe1(struct pci_dev *pdev, int dev_idx)
goto fail0;
}
debugf3("%s(): more mci init\n", __func__);
edac_dbg(3, "more mci init\n");
mci->ctl_name = pvt->dev_info->ctl_name;
mci->dev_name = pci_name(pdev);
mci->edac_check = e7xxx_check;
mci->ctl_page_to_phys = ctl_page_to_phys;
e7xxx_init_csrows(mci, pdev, dev_idx, drc);
mci->edac_cap |= EDAC_FLAG_NONE;
debugf3("%s(): tolm, remapbase, remaplimit\n", __func__);
edac_dbg(3, "tolm, remapbase, remaplimit\n");
/* load the top of low memory, remap base, and remap limit vars */
pci_read_config_word(pdev, E7XXX_TOLM, &pci_data);
pvt->tolm = ((u32) pci_data) << 4;
......@@ -498,7 +499,7 @@ static int e7xxx_probe1(struct pci_dev *pdev, int dev_idx)
* type of memory controller. The ID is therefore hardcoded to 0.
*/
if (edac_mc_add_mc(mci)) {
debugf3("%s(): failed edac_mc_add_mc()\n", __func__);
edac_dbg(3, "failed edac_mc_add_mc()\n");
goto fail1;
}
......@@ -514,7 +515,7 @@ static int e7xxx_probe1(struct pci_dev *pdev, int dev_idx)
}
/* get this far and it's successful */
debugf3("%s(): success\n", __func__);
edac_dbg(3, "success\n");
return 0;
fail1:
......@@ -530,7 +531,7 @@ static int e7xxx_probe1(struct pci_dev *pdev, int dev_idx)
static int __devinit e7xxx_init_one(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
debugf0("%s()\n", __func__);
edac_dbg(0, "\n");
/* wake up and enable device */
return pci_enable_device(pdev) ?
......@@ -542,7 +543,7 @@ static void __devexit e7xxx_remove_one(struct pci_dev *pdev)
struct mem_ctl_info *mci;
struct e7xxx_pvt *pvt;
debugf0("%s()\n", __func__);
edac_dbg(0, "\n");
if (e7xxx_pci)
edac_pci_release_generic_ctl(e7xxx_pci);
......
......@@ -71,26 +71,21 @@ extern const char *edac_mem_types[];
#ifdef CONFIG_EDAC_DEBUG
extern int edac_debug_level;
#define edac_debug_printk(level, fmt, arg...) \
do { \
if (level <= edac_debug_level) \
edac_printk(KERN_DEBUG, EDAC_DEBUG, \
"%s: " fmt, __func__, ##arg); \
} while (0)
#define debugf0( ... ) edac_debug_printk(0, __VA_ARGS__ )
#define debugf1( ... ) edac_debug_printk(1, __VA_ARGS__ )
#define debugf2( ... ) edac_debug_printk(2, __VA_ARGS__ )
#define debugf3( ... ) edac_debug_printk(3, __VA_ARGS__ )
#define debugf4( ... ) edac_debug_printk(4, __VA_ARGS__ )
#define edac_dbg(level, fmt, ...) \
do { \
if (level <= edac_debug_level) \
edac_printk(KERN_DEBUG, EDAC_DEBUG, \
"%s: " fmt, __func__, ##__VA_ARGS__); \
} while (0)
#else /* !CONFIG_EDAC_DEBUG */
#define debugf0( ... )
#define debugf1( ... )
#define debugf2( ... )
#define debugf3( ... )
#define debugf4( ... )
#define edac_dbg(level, fmt, ...) \
do { \
if (0) \
edac_printk(KERN_DEBUG, EDAC_DEBUG, \
"%s: " fmt, __func__, ##__VA_ARGS__); \
} while (0)
#endif /* !CONFIG_EDAC_DEBUG */
......@@ -460,15 +455,15 @@ extern int edac_mc_find_csrow_by_page(struct mem_ctl_info *mci,
unsigned long page);
void edac_mc_handle_error(const enum hw_event_mc_err_type type,
struct mem_ctl_info *mci,
const u16 error_count,
const unsigned long page_frame_number,
const unsigned long offset_in_page,
const unsigned long syndrome,
const int layer0,
const int layer1,
const int layer2,
const int top_layer,
const int mid_layer,
const int low_layer,
const char *msg,
const char *other_detail,
const void *mcelog);
const char *other_detail);
/*
* edac_device APIs
......
......@@ -40,12 +40,13 @@ static LIST_HEAD(edac_device_list);
#ifdef CONFIG_EDAC_DEBUG
static void edac_device_dump_device(struct edac_device_ctl_info *edac_dev)
{
debugf3("\tedac_dev = %p dev_idx=%d \n", edac_dev, edac_dev->dev_idx);
debugf4("\tedac_dev->edac_check = %p\n", edac_dev->edac_check);
debugf3("\tdev = %p\n", edac_dev->dev);
debugf3("\tmod_name:ctl_name = %s:%s\n",
edac_dev->mod_name, edac_dev->ctl_name);
debugf3("\tpvt_info = %p\n\n", edac_dev->pvt_info);
edac_dbg(3, "\tedac_dev = %p dev_idx=%d\n",
edac_dev, edac_dev->dev_idx);
edac_dbg(4, "\tedac_dev->edac_check = %p\n", edac_dev->edac_check);
edac_dbg(3, "\tdev = %p\n", edac_dev->dev);
edac_dbg(3, "\tmod_name:ctl_name = %s:%s\n",
edac_dev->mod_name, edac_dev->ctl_name);
edac_dbg(3, "\tpvt_info = %p\n\n", edac_dev->pvt_info);
}
#endif /* CONFIG_EDAC_DEBUG */
......@@ -82,8 +83,7 @@ struct edac_device_ctl_info *edac_device_alloc_ctl_info(
void *pvt, *p;
int err;
debugf4("%s() instances=%d blocks=%d\n",
__func__, nr_instances, nr_blocks);
edac_dbg(4, "instances=%d blocks=%d\n", nr_instances, nr_blocks);
/* Calculate the size of memory we need to allocate AND
* determine the offsets of the various item arrays
......@@ -156,8 +156,8 @@ struct edac_device_ctl_info *edac_device_alloc_ctl_info(
/* Name of this edac device */
snprintf(dev_ctl->name,sizeof(dev_ctl->name),"%s",edac_device_name);
debugf4("%s() edac_dev=%p next after end=%p\n",
__func__, dev_ctl, pvt + sz_private );
edac_dbg(4, "edac_dev=%p next after end=%p\n",
dev_ctl, pvt + sz_private);
/* Initialize every Instance */
for (instance = 0; instance < nr_instances; instance++) {
......@@ -178,10 +178,8 @@ struct edac_device_ctl_info *edac_device_alloc_ctl_info(
snprintf(blk->name, sizeof(blk->name),
"%s%d", edac_block_name, block+offset_value);
debugf4("%s() instance=%d inst_p=%p block=#%d "
"block_p=%p name='%s'\n",
__func__, instance, inst, block,
blk, blk->name);
edac_dbg(4, "instance=%d inst_p=%p block=#%d block_p=%p name='%s'\n",
instance, inst, block, blk, blk->name);
/* if there are NO attributes OR no attribute pointer
* then continue on to next block iteration
......@@ -194,8 +192,8 @@ struct edac_device_ctl_info *edac_device_alloc_ctl_info(
attrib_p = &dev_attrib[block*nr_instances*nr_attrib];
blk->block_attributes = attrib_p;
debugf4("%s() THIS BLOCK_ATTRIB=%p\n",
__func__, blk->block_attributes);
edac_dbg(4, "THIS BLOCK_ATTRIB=%p\n",
blk->block_attributes);
/* Initialize every user specified attribute in this
* block with the data the caller passed in
......@@ -214,11 +212,10 @@ struct edac_device_ctl_info *edac_device_alloc_ctl_info(
attrib->block = blk; /* up link */
debugf4("%s() alloc-attrib=%p attrib_name='%s' "
"attrib-spec=%p spec-name=%s\n",
__func__, attrib, attrib->attr.name,
&attrib_spec[attr],
attrib_spec[attr].attr.name
edac_dbg(4, "alloc-attrib=%p attrib_name='%s' attrib-spec=%p spec-name=%s\n",
attrib, attrib->attr.name,
&attrib_spec[attr],
attrib_spec[attr].attr.name
);
}
}
......@@ -273,7 +270,7 @@ static struct edac_device_ctl_info *find_edac_device_by_dev(struct device *dev)
struct edac_device_ctl_info *edac_dev;
struct list_head *item;
debugf0("%s()\n", __func__);
edac_dbg(0, "\n");
list_for_each(item, &edac_device_list) {
edac_dev = list_entry(item, struct edac_device_ctl_info, link);
......@@ -408,7 +405,7 @@ static void edac_device_workq_function(struct work_struct *work_req)
void edac_device_workq_setup(struct edac_device_ctl_info *edac_dev,
unsigned msec)
{
debugf0("%s()\n", __func__);
edac_dbg(0, "\n");
/* take the arg 'msec' and set it into the control structure
* to used in the time period calculation
......@@ -496,7 +493,7 @@ EXPORT_SYMBOL_GPL(edac_device_alloc_index);
*/
int edac_device_add_device(struct edac_device_ctl_info *edac_dev)
{
debugf0("%s()\n", __func__);
edac_dbg(0, "\n");
#ifdef CONFIG_EDAC_DEBUG
if (edac_debug_level >= 3)
......@@ -570,7 +567,7 @@ struct edac_device_ctl_info *edac_device_del_device(struct device *dev)
{
struct edac_device_ctl_info *edac_dev;
debugf0("%s()\n", __func__);
edac_dbg(0, "\n");
mutex_lock(&device_ctls_mutex);
......
......@@ -202,7 +202,7 @@ static void edac_device_ctrl_master_release(struct kobject *kobj)
{
struct edac_device_ctl_info *edac_dev = to_edacdev(kobj);
debugf4("%s() control index=%d\n", __func__, edac_dev->dev_idx);
edac_dbg(4, "control index=%d\n", edac_dev->dev_idx);
/* decrement the EDAC CORE module ref count */
module_put(edac_dev->owner);
......@@ -233,12 +233,12 @@ int edac_device_register_sysfs_main_kobj(struct edac_device_ctl_info *edac_dev)
struct bus_type *edac_subsys;
int err;
debugf1("%s()\n", __func__);
edac_dbg(1, "\n");
/* get the /sys/devices/system/edac reference */
edac_subsys = edac_get_sysfs_subsys();
if (edac_subsys == NULL) {
debugf1("%s() no edac_subsys error\n", __func__);
edac_dbg(1, "no edac_subsys error\n");
err = -ENODEV;
goto err_out;
}
......@@ -264,8 +264,8 @@ int edac_device_register_sysfs_main_kobj(struct edac_device_ctl_info *edac_dev)
&edac_subsys->dev_root->kobj,
"%s", edac_dev->name);
if (err) {
debugf1("%s()Failed to register '.../edac/%s'\n",
__func__, edac_dev->name);
edac_dbg(1, "Failed to register '.../edac/%s'\n",
edac_dev->name);
goto err_kobj_reg;
}
kobject_uevent(&edac_dev->kobj, KOBJ_ADD);
......@@ -274,8 +274,7 @@ int edac_device_register_sysfs_main_kobj(struct edac_device_ctl_info *edac_dev)
* edac_device_unregister_sysfs_main_kobj() must be used
*/
debugf4("%s() Registered '.../edac/%s' kobject\n",
__func__, edac_dev->name);
edac_dbg(4, "Registered '.../edac/%s' kobject\n", edac_dev->name);
return 0;
......@@ -296,9 +295,8 @@ int edac_device_register_sysfs_main_kobj(struct edac_device_ctl_info *edac_dev)
*/
void edac_device_unregister_sysfs_main_kobj(struct edac_device_ctl_info *dev)
{
debugf0("%s()\n", __func__);
debugf4("%s() name of kobject is: %s\n",
__func__, kobject_name(&dev->kobj));
edac_dbg(0, "\n");
edac_dbg(4, "name of kobject is: %s\n", kobject_name(&dev->kobj));
/*
* Unregister the edac device's kobject and
......@@ -336,7 +334,7 @@ static void edac_device_ctrl_instance_release(struct kobject *kobj)
{
struct edac_device_instance *instance;
debugf1("%s()\n", __func__);
edac_dbg(1, "\n");
/* map from this kobj to the main control struct
* and then dec the main kobj count
......@@ -442,7 +440,7 @@ static void edac_device_ctrl_block_release(struct kobject *kobj)
{
struct edac_device_block *block;
debugf1("%s()\n", __func__);
edac_dbg(1, "\n");
/* get the container of the kobj */
block = to_block(kobj);
......@@ -524,10 +522,10 @@ static int edac_device_create_block(struct edac_device_ctl_info *edac_dev,
struct edac_dev_sysfs_block_attribute *sysfs_attrib;
struct kobject *main_kobj;
debugf4("%s() Instance '%s' inst_p=%p block '%s' block_p=%p\n",
__func__, instance->name, instance, block->name, block);
debugf4("%s() block kobj=%p block kobj->parent=%p\n",
__func__, &block->kobj, &block->kobj.parent);
edac_dbg(4, "Instance '%s' inst_p=%p block '%s' block_p=%p\n",
instance->name, instance, block->name, block);
edac_dbg(4, "block kobj=%p block kobj->parent=%p\n",
&block->kobj, &block->kobj.parent);
/* init this block's kobject */
memset(&block->kobj, 0, sizeof(struct kobject));
......@@ -546,8 +544,7 @@ static int edac_device_create_block(struct edac_device_ctl_info *edac_dev,
&instance->kobj,
"%s", block->name);
if (err) {
debugf1("%s() Failed to register instance '%s'\n",
__func__, block->name);
edac_dbg(1, "Failed to register instance '%s'\n", block->name);
kobject_put(main_kobj);
err = -ENODEV;
goto err_out;
......@@ -560,11 +557,9 @@ static int edac_device_create_block(struct edac_device_ctl_info *edac_dev,
if (sysfs_attrib && block->nr_attribs) {
for (i = 0; i < block->nr_attribs; i++, sysfs_attrib++) {
debugf4("%s() creating block attrib='%s' "
"attrib->%p to kobj=%p\n",
__func__,
sysfs_attrib->attr.name,
sysfs_attrib, &block->kobj);
edac_dbg(4, "creating block attrib='%s' attrib->%p to kobj=%p\n",
sysfs_attrib->attr.name,
sysfs_attrib, &block->kobj);
/* Create each block_attribute file */
err = sysfs_create_file(&block->kobj,
......@@ -647,14 +642,14 @@ static int edac_device_create_instance(struct edac_device_ctl_info *edac_dev,
err = kobject_init_and_add(&instance->kobj, &ktype_instance_ctrl,
&edac_dev->kobj, "%s", instance->name);
if (err != 0) {
debugf2("%s() Failed to register instance '%s'\n",
__func__, instance->name);
edac_dbg(2, "Failed to register instance '%s'\n",
instance->name);
kobject_put(main_kobj);
goto err_out;
}
debugf4("%s() now register '%d' blocks for instance %d\n",
__func__, instance->nr_blocks, idx);
edac_dbg(4, "now register '%d' blocks for instance %d\n",
instance->nr_blocks, idx);
/* register all blocks of this instance */
for (i = 0; i < instance->nr_blocks; i++) {
......@@ -670,8 +665,8 @@ static int edac_device_create_instance(struct edac_device_ctl_info *edac_dev,
}
kobject_uevent(&instance->kobj, KOBJ_ADD);
debugf4("%s() Registered instance %d '%s' kobject\n",
__func__, idx, instance->name);
edac_dbg(4, "Registered instance %d '%s' kobject\n",
idx, instance->name);
return 0;
......@@ -715,7 +710,7 @@ static int edac_device_create_instances(struct edac_device_ctl_info *edac_dev)
int i, j;
int err;
debugf0("%s()\n", __func__);
edac_dbg(0, "\n");
/* iterate over creation of the instances */
for (i = 0; i < edac_dev->nr_instances; i++) {
......@@ -817,12 +812,12 @@ int edac_device_create_sysfs(struct edac_device_ctl_info *edac_dev)
int err;
struct kobject *edac_kobj = &edac_dev->kobj;
debugf0("%s() idx=%d\n", __func__, edac_dev->dev_idx);
edac_dbg(0, "idx=%d\n", edac_dev->dev_idx);
/* go create any main attributes callers wants */
err = edac_device_add_main_sysfs_attributes(edac_dev);
if (err) {
debugf0("%s() failed to add sysfs attribs\n", __func__);
edac_dbg(0, "failed to add sysfs attribs\n");
goto err_out;
}
......@@ -832,8 +827,7 @@ int edac_device_create_sysfs(struct edac_device_ctl_info *edac_dev)
err = sysfs_create_link(edac_kobj,
&edac_dev->dev->kobj, EDAC_DEVICE_SYMLINK);
if (err) {
debugf0("%s() sysfs_create_link() returned err= %d\n",
__func__, err);
edac_dbg(0, "sysfs_create_link() returned err= %d\n", err);
goto err_remove_main_attribs;
}
......@@ -843,14 +837,13 @@ int edac_device_create_sysfs(struct edac_device_ctl_info *edac_dev)
*/
err = edac_device_create_instances(edac_dev);
if (err) {
debugf0("%s() edac_device_create_instances() "
"returned err= %d\n", __func__, err);
edac_dbg(0, "edac_device_create_instances() returned err= %d\n",
err);
goto err_remove_link;
}
debugf4("%s() create-instances done, idx=%d\n",
__func__, edac_dev->dev_idx);
edac_dbg(4, "create-instances done, idx=%d\n", edac_dev->dev_idx);
return 0;
......@@ -873,7 +866,7 @@ int edac_device_create_sysfs(struct edac_device_ctl_info *edac_dev)
*/
void edac_device_remove_sysfs(struct edac_device_ctl_info *edac_dev)
{
debugf0("%s()\n", __func__);
edac_dbg(0, "\n");
/* remove any main attributes for this device */
edac_device_remove_main_sysfs_attributes(edac_dev);
......
此差异已折叠。
此差异已折叠。
......@@ -15,7 +15,7 @@
#include "edac_core.h"
#include "edac_module.h"
#define EDAC_VERSION "Ver: 2.1.0"
#define EDAC_VERSION "Ver: 3.0.0"
#ifdef CONFIG_EDAC_DEBUG
/* Values of 0 to 4 will generate output */
......@@ -90,26 +90,21 @@ static int __init edac_init(void)
*/
edac_pci_clear_parity_errors();
/*
* now set up the mc_kset under the edac class object
*/
err = edac_sysfs_setup_mc_kset();
err = edac_mc_sysfs_init();
if (err)
goto error;
edac_debugfs_init();
/* Setup/Initialize the workq for this core */
err = edac_workqueue_setup();
if (err) {
edac_printk(KERN_ERR, EDAC_MC, "init WorkQueue failure\n");
goto workq_fail;
goto error;
}
return 0;
/* Error teardown stack */
workq_fail:
edac_sysfs_teardown_mc_kset();
error:
return err;
}
......@@ -120,11 +115,12 @@ static int __init edac_init(void)
*/
static void __exit edac_exit(void)
{
debugf0("%s()\n", __func__);
edac_dbg(0, "\n");
/* tear down the various subsystems */
edac_workqueue_teardown();
edac_sysfs_teardown_mc_kset();
edac_mc_sysfs_exit();
edac_debugfs_exit();
}
/*
......
......@@ -19,12 +19,12 @@
*
* edac_mc objects
*/
extern int edac_sysfs_setup_mc_kset(void);
extern void edac_sysfs_teardown_mc_kset(void);
extern int edac_mc_register_sysfs_main_kobj(struct mem_ctl_info *mci);
extern void edac_mc_unregister_sysfs_main_kobj(struct mem_ctl_info *mci);
/* on edac_mc_sysfs.c */
int edac_mc_sysfs_init(void);
void edac_mc_sysfs_exit(void);
extern int edac_create_sysfs_mci_device(struct mem_ctl_info *mci);
extern void edac_remove_sysfs_mci_device(struct mem_ctl_info *mci);
void edac_unregister_sysfs(struct mem_ctl_info *mci);
extern int edac_get_log_ue(void);
extern int edac_get_log_ce(void);
extern int edac_get_panic_on_ue(void);
......@@ -34,6 +34,10 @@ extern int edac_mc_get_panic_on_ue(void);
extern int edac_get_poll_msec(void);
extern int edac_mc_get_poll_msec(void);
unsigned edac_dimm_info_location(struct dimm_info *dimm, char *buf,
unsigned len);
/* on edac_device.c */
extern int edac_device_register_sysfs_main_kobj(
struct edac_device_ctl_info *edac_dev);
extern void edac_device_unregister_sysfs_main_kobj(
......@@ -52,6 +56,20 @@ extern void edac_mc_reset_delay_period(int value);
extern void *edac_align_ptr(void **p, unsigned size, int n_elems);
/*
* EDAC debugfs functions
*/
#ifdef CONFIG_EDAC_DEBUG
int edac_debugfs_init(void);
void edac_debugfs_exit(void);
#else
static inline int edac_debugfs_init(void)
{
return -ENODEV;
}
static inline void edac_debugfs_exit(void) {}
#endif
/*
* EDAC PCI functions
*/
......
......@@ -45,7 +45,7 @@ struct edac_pci_ctl_info *edac_pci_alloc_ctl_info(unsigned int sz_pvt,
void *p = NULL, *pvt;
unsigned int size;
debugf1("%s()\n", __func__);
edac_dbg(1, "\n");
pci = edac_align_ptr(&p, sizeof(*pci), 1);
pvt = edac_align_ptr(&p, 1, sz_pvt);
......@@ -80,7 +80,7 @@ EXPORT_SYMBOL_GPL(edac_pci_alloc_ctl_info);
*/
void edac_pci_free_ctl_info(struct edac_pci_ctl_info *pci)
{
debugf1("%s()\n", __func__);
edac_dbg(1, "\n");
edac_pci_remove_sysfs(pci);
}
......@@ -97,7 +97,7 @@ static struct edac_pci_ctl_info *find_edac_pci_by_dev(struct device *dev)
struct edac_pci_ctl_info *pci;
struct list_head *item;
debugf1("%s()\n", __func__);
edac_dbg(1, "\n");
list_for_each(item, &edac_pci_list) {
pci = list_entry(item, struct edac_pci_ctl_info, link);
......@@ -122,7 +122,7 @@ static int add_edac_pci_to_global_list(struct edac_pci_ctl_info *pci)
struct list_head *item, *insert_before;
struct edac_pci_ctl_info *rover;
debugf1("%s()\n", __func__);
edac_dbg(1, "\n");
insert_before = &edac_pci_list;
......@@ -226,7 +226,7 @@ static void edac_pci_workq_function(struct work_struct *work_req)
int msec;
unsigned long delay;
debugf3("%s() checking\n", __func__);
edac_dbg(3, "checking\n");
mutex_lock(&edac_pci_ctls_mutex);
......@@ -261,7 +261,7 @@ static void edac_pci_workq_function(struct work_struct *work_req)
static void edac_pci_workq_setup(struct edac_pci_ctl_info *pci,
unsigned int msec)
{
debugf0("%s()\n", __func__);
edac_dbg(0, "\n");
INIT_DELAYED_WORK(&pci->work, edac_pci_workq_function);
queue_delayed_work(edac_workqueue, &pci->work,
......@@ -276,7 +276,7 @@ static void edac_pci_workq_teardown(struct edac_pci_ctl_info *pci)
{
int status;
debugf0("%s()\n", __func__);
edac_dbg(0, "\n");
status = cancel_delayed_work(&pci->work);
if (status == 0)
......@@ -293,7 +293,7 @@ static void edac_pci_workq_teardown(struct edac_pci_ctl_info *pci)
void edac_pci_reset_delay_period(struct edac_pci_ctl_info *pci,
unsigned long value)
{
debugf0("%s()\n", __func__);
edac_dbg(0, "\n");
edac_pci_workq_teardown(pci);
......@@ -333,7 +333,7 @@ EXPORT_SYMBOL_GPL(edac_pci_alloc_index);
*/
int edac_pci_add_device(struct edac_pci_ctl_info *pci, int edac_idx)
{
debugf0("%s()\n", __func__);
edac_dbg(0, "\n");
pci->pci_idx = edac_idx;
pci->start_time = jiffies;
......@@ -393,7 +393,7 @@ struct edac_pci_ctl_info *edac_pci_del_device(struct device *dev)
{
struct edac_pci_ctl_info *pci;
debugf0("%s()\n", __func__);
edac_dbg(0, "\n");
mutex_lock(&edac_pci_ctls_mutex);
......@@ -430,7 +430,7 @@ EXPORT_SYMBOL_GPL(edac_pci_del_device);
*/
static void edac_pci_generic_check(struct edac_pci_ctl_info *pci)
{
debugf4("%s()\n", __func__);
edac_dbg(4, "\n");
edac_pci_do_parity_check();
}
......@@ -475,7 +475,7 @@ struct edac_pci_ctl_info *edac_pci_create_generic_ctl(struct device *dev,
pdata->edac_idx = edac_pci_idx++;
if (edac_pci_add_device(pci, pdata->edac_idx) > 0) {
debugf3("%s(): failed edac_pci_add_device()\n", __func__);
edac_dbg(3, "failed edac_pci_add_device()\n");
edac_pci_free_ctl_info(pci);
return NULL;
}
......@@ -491,7 +491,7 @@ EXPORT_SYMBOL_GPL(edac_pci_create_generic_ctl);
*/
void edac_pci_release_generic_ctl(struct edac_pci_ctl_info *pci)
{
debugf0("%s() pci mod=%s\n", __func__, pci->mod_name);
edac_dbg(0, "pci mod=%s\n", pci->mod_name);
edac_pci_del_device(pci->dev);
edac_pci_free_ctl_info(pci);
......
......@@ -78,7 +78,7 @@ static void edac_pci_instance_release(struct kobject *kobj)
{
struct edac_pci_ctl_info *pci;
debugf0("%s()\n", __func__);
edac_dbg(0, "\n");
/* Form pointer to containing struct, the pci control struct */
pci = to_instance(kobj);
......@@ -161,7 +161,7 @@ static int edac_pci_create_instance_kobj(struct edac_pci_ctl_info *pci, int idx)
struct kobject *main_kobj;
int err;
debugf0("%s()\n", __func__);
edac_dbg(0, "\n");
/* First bump the ref count on the top main kobj, which will
* track the number of PCI instances we have, and thus nest
......@@ -177,14 +177,13 @@ static int edac_pci_create_instance_kobj(struct edac_pci_ctl_info *pci, int idx)
err = kobject_init_and_add(&pci->kobj, &ktype_pci_instance,
edac_pci_top_main_kobj, "pci%d", idx);
if (err != 0) {
debugf2("%s() failed to register instance pci%d\n",
__func__, idx);
edac_dbg(2, "failed to register instance pci%d\n", idx);
kobject_put(edac_pci_top_main_kobj);
goto error_out;
}
kobject_uevent(&pci->kobj, KOBJ_ADD);
debugf1("%s() Register instance 'pci%d' kobject\n", __func__, idx);
edac_dbg(1, "Register instance 'pci%d' kobject\n", idx);
return 0;
......@@ -201,7 +200,7 @@ static int edac_pci_create_instance_kobj(struct edac_pci_ctl_info *pci, int idx)
static void edac_pci_unregister_sysfs_instance_kobj(
struct edac_pci_ctl_info *pci)
{
debugf0("%s()\n", __func__);
edac_dbg(0, "\n");
/* Unregister the instance kobject and allow its release
* function release the main reference count and then
......@@ -317,7 +316,7 @@ static struct edac_pci_dev_attribute *edac_pci_attr[] = {
*/
static void edac_pci_release_main_kobj(struct kobject *kobj)
{
debugf0("%s() here to module_put(THIS_MODULE)\n", __func__);
edac_dbg(0, "here to module_put(THIS_MODULE)\n");
kfree(kobj);
......@@ -345,7 +344,7 @@ static int edac_pci_main_kobj_setup(void)
int err;
struct bus_type *edac_subsys;
debugf0("%s()\n", __func__);
edac_dbg(0, "\n");
/* check and count if we have already created the main kobject */
if (atomic_inc_return(&edac_pci_sysfs_refcount) != 1)
......@@ -356,7 +355,7 @@ static int edac_pci_main_kobj_setup(void)
*/
edac_subsys = edac_get_sysfs_subsys();
if (edac_subsys == NULL) {
debugf1("%s() no edac_subsys\n", __func__);
edac_dbg(1, "no edac_subsys\n");
err = -ENODEV;
goto decrement_count_fail;
}
......@@ -366,14 +365,14 @@ static int edac_pci_main_kobj_setup(void)
* level main kobj for EDAC PCI
*/
if (!try_module_get(THIS_MODULE)) {
debugf1("%s() try_module_get() failed\n", __func__);
edac_dbg(1, "try_module_get() failed\n");
err = -ENODEV;
goto mod_get_fail;
}
edac_pci_top_main_kobj = kzalloc(sizeof(struct kobject), GFP_KERNEL);
if (!edac_pci_top_main_kobj) {
debugf1("Failed to allocate\n");
edac_dbg(1, "Failed to allocate\n");
err = -ENOMEM;
goto kzalloc_fail;
}
......@@ -383,7 +382,7 @@ static int edac_pci_main_kobj_setup(void)
&ktype_edac_pci_main_kobj,
&edac_subsys->dev_root->kobj, "pci");
if (err) {
debugf1("Failed to register '.../edac/pci'\n");
edac_dbg(1, "Failed to register '.../edac/pci'\n");
goto kobject_init_and_add_fail;
}
......@@ -392,7 +391,7 @@ static int edac_pci_main_kobj_setup(void)
* must be used, for resources to be cleaned up properly
*/
kobject_uevent(edac_pci_top_main_kobj, KOBJ_ADD);
debugf1("Registered '.../edac/pci' kobject\n");
edac_dbg(1, "Registered '.../edac/pci' kobject\n");
return 0;
......@@ -421,15 +420,14 @@ static int edac_pci_main_kobj_setup(void)
*/
static void edac_pci_main_kobj_teardown(void)
{
debugf0("%s()\n", __func__);
edac_dbg(0, "\n");
/* Decrement the count and only if no more controller instances
* are connected perform the unregisteration of the top level
* main kobj
*/
if (atomic_dec_return(&edac_pci_sysfs_refcount) == 0) {
debugf0("%s() called kobject_put on main kobj\n",
__func__);
edac_dbg(0, "called kobject_put on main kobj\n");
kobject_put(edac_pci_top_main_kobj);
}
edac_put_sysfs_subsys();
......@@ -446,7 +444,7 @@ int edac_pci_create_sysfs(struct edac_pci_ctl_info *pci)
int err;
struct kobject *edac_kobj = &pci->kobj;
debugf0("%s() idx=%d\n", __func__, pci->pci_idx);
edac_dbg(0, "idx=%d\n", pci->pci_idx);
/* create the top main EDAC PCI kobject, IF needed */
err = edac_pci_main_kobj_setup();
......@@ -460,8 +458,7 @@ int edac_pci_create_sysfs(struct edac_pci_ctl_info *pci)
err = sysfs_create_link(edac_kobj, &pci->dev->kobj, EDAC_PCI_SYMLINK);
if (err) {
debugf0("%s() sysfs_create_link() returned err= %d\n",
__func__, err);
edac_dbg(0, "sysfs_create_link() returned err= %d\n", err);
goto symlink_fail;
}
......@@ -484,7 +481,7 @@ int edac_pci_create_sysfs(struct edac_pci_ctl_info *pci)
*/
void edac_pci_remove_sysfs(struct edac_pci_ctl_info *pci)
{
debugf0("%s() index=%d\n", __func__, pci->pci_idx);
edac_dbg(0, "index=%d\n", pci->pci_idx);
/* Remove the symlink */
sysfs_remove_link(&pci->kobj, EDAC_PCI_SYMLINK);
......@@ -496,7 +493,7 @@ void edac_pci_remove_sysfs(struct edac_pci_ctl_info *pci)
* if this 'pci' is the last instance.
* If it is, the main kobject will be unregistered as a result
*/
debugf0("%s() calling edac_pci_main_kobj_teardown()\n", __func__);
edac_dbg(0, "calling edac_pci_main_kobj_teardown()\n");
edac_pci_main_kobj_teardown();
}
......@@ -572,7 +569,7 @@ static void edac_pci_dev_parity_test(struct pci_dev *dev)
local_irq_restore(flags);
debugf4("PCI STATUS= 0x%04x %s\n", status, dev_name(&dev->dev));
edac_dbg(4, "PCI STATUS= 0x%04x %s\n", status, dev_name(&dev->dev));
/* check the status reg for errors on boards NOT marked as broken
* if broken, we cannot trust any of the status bits
......@@ -603,13 +600,15 @@ static void edac_pci_dev_parity_test(struct pci_dev *dev)
}
debugf4("PCI HEADER TYPE= 0x%02x %s\n", header_type, dev_name(&dev->dev));
edac_dbg(4, "PCI HEADER TYPE= 0x%02x %s\n",
header_type, dev_name(&dev->dev));
if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) {
/* On bridges, need to examine secondary status register */
status = get_pci_parity_status(dev, 1);
debugf4("PCI SEC_STATUS= 0x%04x %s\n", status, dev_name(&dev->dev));
edac_dbg(4, "PCI SEC_STATUS= 0x%04x %s\n",
status, dev_name(&dev->dev));
/* check the secondary status reg for errors,
* on NOT broken boards
......@@ -671,7 +670,7 @@ void edac_pci_do_parity_check(void)
{
int before_count;
debugf3("%s()\n", __func__);
edac_dbg(3, "\n");
/* if policy has PCI check off, leave now */
if (!check_pci_errors)
......
/*
* Copyright 2011-2012 Calxeda, Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/ctype.h>
#include <linux/edac.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/of_platform.h>
#include "edac_core.h"
#include "edac_module.h"
#define SR_CLR_SB_ECC_INTR 0x0
#define SR_CLR_DB_ECC_INTR 0x4
struct hb_l2_drvdata {
void __iomem *base;
int sb_irq;
int db_irq;
};
static irqreturn_t highbank_l2_err_handler(int irq, void *dev_id)
{
struct edac_device_ctl_info *dci = dev_id;
struct hb_l2_drvdata *drvdata = dci->pvt_info;
if (irq == drvdata->sb_irq) {
writel(1, drvdata->base + SR_CLR_SB_ECC_INTR);
edac_device_handle_ce(dci, 0, 0, dci->ctl_name);
}
if (irq == drvdata->db_irq) {
writel(1, drvdata->base + SR_CLR_DB_ECC_INTR);
edac_device_handle_ue(dci, 0, 0, dci->ctl_name);
}
return IRQ_HANDLED;
}
static int __devinit highbank_l2_err_probe(struct platform_device *pdev)
{
struct edac_device_ctl_info *dci;
struct hb_l2_drvdata *drvdata;
struct resource *r;
int res = 0;
dci = edac_device_alloc_ctl_info(sizeof(*drvdata), "cpu",
1, "L", 1, 2, NULL, 0, 0);
if (!dci)
return -ENOMEM;
drvdata = dci->pvt_info;
dci->dev = &pdev->dev;
platform_set_drvdata(pdev, dci);
if (!devres_open_group(&pdev->dev, NULL, GFP_KERNEL))
return -ENOMEM;
r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!r) {
dev_err(&pdev->dev, "Unable to get mem resource\n");
res = -ENODEV;
goto err;
}
if (!devm_request_mem_region(&pdev->dev, r->start,
resource_size(r), dev_name(&pdev->dev))) {
dev_err(&pdev->dev, "Error while requesting mem region\n");
res = -EBUSY;
goto err;
}
drvdata->base = devm_ioremap(&pdev->dev, r->start, resource_size(r));
if (!drvdata->base) {
dev_err(&pdev->dev, "Unable to map regs\n");
res = -ENOMEM;
goto err;
}
drvdata->db_irq = platform_get_irq(pdev, 0);
res = devm_request_irq(&pdev->dev, drvdata->db_irq,
highbank_l2_err_handler,
0, dev_name(&pdev->dev), dci);
if (res < 0)
goto err;
drvdata->sb_irq = platform_get_irq(pdev, 1);
res = devm_request_irq(&pdev->dev, drvdata->sb_irq,
highbank_l2_err_handler,
0, dev_name(&pdev->dev), dci);
if (res < 0)
goto err;
dci->mod_name = dev_name(&pdev->dev);
dci->dev_name = dev_name(&pdev->dev);
if (edac_device_add_device(dci))
goto err;
devres_close_group(&pdev->dev, NULL);
return 0;
err:
devres_release_group(&pdev->dev, NULL);
edac_device_free_ctl_info(dci);
return res;
}
static int highbank_l2_err_remove(struct platform_device *pdev)
{
struct edac_device_ctl_info *dci = platform_get_drvdata(pdev);
edac_device_del_device(&pdev->dev);
edac_device_free_ctl_info(dci);
return 0;
}
static const struct of_device_id hb_l2_err_of_match[] = {
{ .compatible = "calxeda,hb-sregs-l2-ecc", },
{},
};
MODULE_DEVICE_TABLE(of, hb_l2_err_of_match);
static struct platform_driver highbank_l2_edac_driver = {
.probe = highbank_l2_err_probe,
.remove = highbank_l2_err_remove,
.driver = {
.name = "hb_l2_edac",
.of_match_table = hb_l2_err_of_match,
},
};
module_platform_driver(highbank_l2_edac_driver);
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Calxeda, Inc.");
MODULE_DESCRIPTION("EDAC Driver for Calxeda Highbank L2 Cache");
/*
* Copyright 2011-2012 Calxeda, Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/ctype.h>
#include <linux/edac.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/of_platform.h>
#include <linux/uaccess.h>
#include "edac_core.h"
#include "edac_module.h"
/* DDR Ctrlr Error Registers */
#define HB_DDR_ECC_OPT 0x128
#define HB_DDR_ECC_U_ERR_ADDR 0x130
#define HB_DDR_ECC_U_ERR_STAT 0x134
#define HB_DDR_ECC_U_ERR_DATAL 0x138
#define HB_DDR_ECC_U_ERR_DATAH 0x13c
#define HB_DDR_ECC_C_ERR_ADDR 0x140
#define HB_DDR_ECC_C_ERR_STAT 0x144
#define HB_DDR_ECC_C_ERR_DATAL 0x148
#define HB_DDR_ECC_C_ERR_DATAH 0x14c
#define HB_DDR_ECC_INT_STATUS 0x180
#define HB_DDR_ECC_INT_ACK 0x184
#define HB_DDR_ECC_U_ERR_ID 0x424
#define HB_DDR_ECC_C_ERR_ID 0x428
#define HB_DDR_ECC_INT_STAT_CE 0x8
#define HB_DDR_ECC_INT_STAT_DOUBLE_CE 0x10
#define HB_DDR_ECC_INT_STAT_UE 0x20
#define HB_DDR_ECC_INT_STAT_DOUBLE_UE 0x40
#define HB_DDR_ECC_OPT_MODE_MASK 0x3
#define HB_DDR_ECC_OPT_FWC 0x100
#define HB_DDR_ECC_OPT_XOR_SHIFT 16
struct hb_mc_drvdata {
void __iomem *mc_vbase;
};
static irqreturn_t highbank_mc_err_handler(int irq, void *dev_id)
{
struct mem_ctl_info *mci = dev_id;
struct hb_mc_drvdata *drvdata = mci->pvt_info;
u32 status, err_addr;
/* Read the interrupt status register */
status = readl(drvdata->mc_vbase + HB_DDR_ECC_INT_STATUS);
if (status & HB_DDR_ECC_INT_STAT_UE) {
err_addr = readl(drvdata->mc_vbase + HB_DDR_ECC_U_ERR_ADDR);
edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1,
err_addr >> PAGE_SHIFT,
err_addr & ~PAGE_MASK, 0,
0, 0, -1,
mci->ctl_name, "");
}
if (status & HB_DDR_ECC_INT_STAT_CE) {
u32 syndrome = readl(drvdata->mc_vbase + HB_DDR_ECC_C_ERR_STAT);
syndrome = (syndrome >> 8) & 0xff;
err_addr = readl(drvdata->mc_vbase + HB_DDR_ECC_C_ERR_ADDR);
edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1,
err_addr >> PAGE_SHIFT,
err_addr & ~PAGE_MASK, syndrome,
0, 0, -1,
mci->ctl_name, "");
}
/* clear the error, clears the interrupt */
writel(status, drvdata->mc_vbase + HB_DDR_ECC_INT_ACK);
return IRQ_HANDLED;
}
#ifdef CONFIG_EDAC_DEBUG
static ssize_t highbank_mc_err_inject_write(struct file *file,
const char __user *data,
size_t count, loff_t *ppos)
{
struct mem_ctl_info *mci = file->private_data;
struct hb_mc_drvdata *pdata = mci->pvt_info;
char buf[32];
size_t buf_size;
u32 reg;
u8 synd;
buf_size = min(count, (sizeof(buf)-1));
if (copy_from_user(buf, data, buf_size))
return -EFAULT;
buf[buf_size] = 0;
if (!kstrtou8(buf, 16, &synd)) {
reg = readl(pdata->mc_vbase + HB_DDR_ECC_OPT);
reg &= HB_DDR_ECC_OPT_MODE_MASK;
reg |= (synd << HB_DDR_ECC_OPT_XOR_SHIFT) | HB_DDR_ECC_OPT_FWC;
writel(reg, pdata->mc_vbase + HB_DDR_ECC_OPT);
}
return count;
}
static int debugfs_open(struct inode *inode, struct file *file)
{
file->private_data = inode->i_private;
return 0;
}
static const struct file_operations highbank_mc_debug_inject_fops = {
.open = debugfs_open,
.write = highbank_mc_err_inject_write,
.llseek = generic_file_llseek,
};
static void __devinit highbank_mc_create_debugfs_nodes(struct mem_ctl_info *mci)
{
if (mci->debugfs)
debugfs_create_file("inject_ctrl", S_IWUSR, mci->debugfs, mci,
&highbank_mc_debug_inject_fops);
;
}
#else
static void __devinit highbank_mc_create_debugfs_nodes(struct mem_ctl_info *mci)
{}
#endif
static int __devinit highbank_mc_probe(struct platform_device *pdev)
{
struct edac_mc_layer layers[2];
struct mem_ctl_info *mci;
struct hb_mc_drvdata *drvdata;
struct dimm_info *dimm;
struct resource *r;
u32 control;
int irq;
int res = 0;
layers[0].type = EDAC_MC_LAYER_CHIP_SELECT;
layers[0].size = 1;
layers[0].is_virt_csrow = true;
layers[1].type = EDAC_MC_LAYER_CHANNEL;
layers[1].size = 1;
layers[1].is_virt_csrow = false;
mci = edac_mc_alloc(0, ARRAY_SIZE(layers), layers,
sizeof(struct hb_mc_drvdata));
if (!mci)
return -ENOMEM;
mci->pdev = &pdev->dev;
drvdata = mci->pvt_info;
platform_set_drvdata(pdev, mci);
if (!devres_open_group(&pdev->dev, NULL, GFP_KERNEL))
return -ENOMEM;
r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!r) {
dev_err(&pdev->dev, "Unable to get mem resource\n");
res = -ENODEV;
goto err;
}
if (!devm_request_mem_region(&pdev->dev, r->start,
resource_size(r), dev_name(&pdev->dev))) {
dev_err(&pdev->dev, "Error while requesting mem region\n");
res = -EBUSY;
goto err;
}
drvdata->mc_vbase = devm_ioremap(&pdev->dev,
r->start, resource_size(r));
if (!drvdata->mc_vbase) {
dev_err(&pdev->dev, "Unable to map regs\n");
res = -ENOMEM;
goto err;
}
control = readl(drvdata->mc_vbase + HB_DDR_ECC_OPT) & 0x3;
if (!control || (control == 0x2)) {
dev_err(&pdev->dev, "No ECC present, or ECC disabled\n");
res = -ENODEV;
goto err;
}
irq = platform_get_irq(pdev, 0);
res = devm_request_irq(&pdev->dev, irq, highbank_mc_err_handler,
0, dev_name(&pdev->dev), mci);
if (res < 0) {
dev_err(&pdev->dev, "Unable to request irq %d\n", irq);
goto err;
}
mci->mtype_cap = MEM_FLAG_DDR3;
mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED;
mci->edac_cap = EDAC_FLAG_SECDED;
mci->mod_name = dev_name(&pdev->dev);
mci->mod_ver = "1";
mci->ctl_name = dev_name(&pdev->dev);
mci->scrub_mode = SCRUB_SW_SRC;
/* Only a single 4GB DIMM is supported */
dimm = *mci->dimms;
dimm->nr_pages = (~0UL >> PAGE_SHIFT) + 1;
dimm->grain = 8;
dimm->dtype = DEV_X8;
dimm->mtype = MEM_DDR3;
dimm->edac_mode = EDAC_SECDED;
res = edac_mc_add_mc(mci);
if (res < 0)
goto err;
highbank_mc_create_debugfs_nodes(mci);
devres_close_group(&pdev->dev, NULL);
return 0;
err:
devres_release_group(&pdev->dev, NULL);
edac_mc_free(mci);
return res;
}
static int highbank_mc_remove(struct platform_device *pdev)
{
struct mem_ctl_info *mci = platform_get_drvdata(pdev);
edac_mc_del_mc(&pdev->dev);
edac_mc_free(mci);
return 0;
}
static const struct of_device_id hb_ddr_ctrl_of_match[] = {
{ .compatible = "calxeda,hb-ddr-ctrl", },
{},
};
MODULE_DEVICE_TABLE(of, hb_ddr_ctrl_of_match);
static struct platform_driver highbank_mc_edac_driver = {
.probe = highbank_mc_probe,
.remove = highbank_mc_remove,
.driver = {
.name = "hb_mc_edac",
.of_match_table = hb_ddr_ctrl_of_match,
},
};
module_platform_driver(highbank_mc_edac_driver);
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Calxeda, Inc.");
MODULE_DESCRIPTION("EDAC Driver for Calxeda Highbank");
......@@ -194,7 +194,7 @@ static void i3000_get_error_info(struct mem_ctl_info *mci,
{
struct pci_dev *pdev;
pdev = to_pci_dev(mci->dev);
pdev = to_pci_dev(mci->pdev);
/*
* This is a mess because there is no atomic way to read all the
......@@ -236,7 +236,7 @@ static int i3000_process_error_info(struct mem_ctl_info *mci,
int row, multi_chan, channel;
unsigned long pfn, offset;
multi_chan = mci->csrows[0].nr_channels - 1;
multi_chan = mci->csrows[0]->nr_channels - 1;
if (!(info->errsts & I3000_ERRSTS_BITS))
return 0;
......@@ -245,9 +245,9 @@ static int i3000_process_error_info(struct mem_ctl_info *mci,
return 1;
if ((info->errsts ^ info->errsts2) & I3000_ERRSTS_BITS) {
edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 0, 0, 0,
edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, 0, 0, 0,
-1, -1, -1,
"UE overwrote CE", "", NULL);
"UE overwrote CE", "");
info->errsts = info->errsts2;
}
......@@ -258,15 +258,15 @@ static int i3000_process_error_info(struct mem_ctl_info *mci,
row = edac_mc_find_csrow_by_page(mci, pfn);
if (info->errsts & I3000_ERRSTS_UE)
edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci,
edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1,
pfn, offset, 0,
row, -1, -1,
"i3000 UE", "", NULL);
"i3000 UE", "");
else
edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci,
edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1,
pfn, offset, info->derrsyn,
row, multi_chan ? channel : 0, -1,
"i3000 CE", "", NULL);
"i3000 CE", "");
return 1;
}
......@@ -275,7 +275,7 @@ static void i3000_check(struct mem_ctl_info *mci)
{
struct i3000_error_info info;
debugf1("MC%d: %s()\n", mci->mc_idx, __func__);
edac_dbg(1, "MC%d\n", mci->mc_idx);
i3000_get_error_info(mci, &info);
i3000_process_error_info(mci, &info, 1);
}
......@@ -322,7 +322,7 @@ static int i3000_probe1(struct pci_dev *pdev, int dev_idx)
unsigned long mchbar;
void __iomem *window;
debugf0("MC: %s()\n", __func__);
edac_dbg(0, "MC:\n");
pci_read_config_dword(pdev, I3000_MCHBAR, (u32 *) & mchbar);
mchbar &= I3000_MCHBAR_MASK;
......@@ -366,9 +366,9 @@ static int i3000_probe1(struct pci_dev *pdev, int dev_idx)
if (!mci)
return -ENOMEM;
debugf3("MC: %s(): init mci\n", __func__);
edac_dbg(3, "MC: init mci\n");
mci->dev = &pdev->dev;
mci->pdev = &pdev->dev;
mci->mtype_cap = MEM_FLAG_DDR2;
mci->edac_ctl_cap = EDAC_FLAG_SECDED;
......@@ -393,14 +393,13 @@ static int i3000_probe1(struct pci_dev *pdev, int dev_idx)
for (last_cumul_size = i = 0; i < mci->nr_csrows; i++) {
u8 value;
u32 cumul_size;
struct csrow_info *csrow = &mci->csrows[i];
struct csrow_info *csrow = mci->csrows[i];
value = drb[i];
cumul_size = value << (I3000_DRB_SHIFT - PAGE_SHIFT);
if (interleaved)
cumul_size <<= 1;
debugf3("MC: %s(): (%d) cumul_size 0x%x\n",
__func__, i, cumul_size);
edac_dbg(3, "MC: (%d) cumul_size 0x%x\n", i, cumul_size);
if (cumul_size == last_cumul_size)
continue;
......@@ -410,7 +409,7 @@ static int i3000_probe1(struct pci_dev *pdev, int dev_idx)
last_cumul_size = cumul_size;
for (j = 0; j < nr_channels; j++) {
struct dimm_info *dimm = csrow->channels[j].dimm;
struct dimm_info *dimm = csrow->channels[j]->dimm;
dimm->nr_pages = nr_pages / nr_channels;
dimm->grain = I3000_DEAP_GRAIN;
......@@ -429,7 +428,7 @@ static int i3000_probe1(struct pci_dev *pdev, int dev_idx)
rc = -ENODEV;
if (edac_mc_add_mc(mci)) {
debugf3("MC: %s(): failed edac_mc_add_mc()\n", __func__);
edac_dbg(3, "MC: failed edac_mc_add_mc()\n");
goto fail;
}
......@@ -445,7 +444,7 @@ static int i3000_probe1(struct pci_dev *pdev, int dev_idx)
}
/* get this far and it's successful */
debugf3("MC: %s(): success\n", __func__);
edac_dbg(3, "MC: success\n");
return 0;
fail:
......@@ -461,7 +460,7 @@ static int __devinit i3000_init_one(struct pci_dev *pdev,
{
int rc;
debugf0("MC: %s()\n", __func__);
edac_dbg(0, "MC:\n");
if (pci_enable_device(pdev) < 0)
return -EIO;
......@@ -477,7 +476,7 @@ static void __devexit i3000_remove_one(struct pci_dev *pdev)
{
struct mem_ctl_info *mci;
debugf0("%s()\n", __func__);
edac_dbg(0, "\n");
if (i3000_pci)
edac_pci_release_generic_ctl(i3000_pci);
......@@ -511,7 +510,7 @@ static int __init i3000_init(void)
{
int pci_rc;
debugf3("MC: %s()\n", __func__);
edac_dbg(3, "MC:\n");
/* Ensure that the OPSTATE is set correctly for POLL or NMI */
opstate_init();
......@@ -525,14 +524,14 @@ static int __init i3000_init(void)
mci_pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
PCI_DEVICE_ID_INTEL_3000_HB, NULL);
if (!mci_pdev) {
debugf0("i3000 pci_get_device fail\n");
edac_dbg(0, "i3000 pci_get_device fail\n");
pci_rc = -ENODEV;
goto fail1;
}
pci_rc = i3000_init_one(mci_pdev, i3000_pci_tbl);
if (pci_rc < 0) {
debugf0("i3000 init fail\n");
edac_dbg(0, "i3000 init fail\n");
pci_rc = -ENODEV;
goto fail1;
}
......@@ -552,7 +551,7 @@ static int __init i3000_init(void)
static void __exit i3000_exit(void)
{
debugf3("MC: %s()\n", __func__);
edac_dbg(3, "MC:\n");
pci_unregister_driver(&i3000_driver);
if (!i3000_registered) {
......
......@@ -110,10 +110,10 @@ static int how_many_channels(struct pci_dev *pdev)
pci_read_config_byte(pdev, I3200_CAPID0 + 8, &capid0_8b);
if (capid0_8b & 0x20) { /* check DCD: Dual Channel Disable */
debugf0("In single channel mode.\n");
edac_dbg(0, "In single channel mode\n");
return 1;
} else {
debugf0("In dual channel mode.\n");
edac_dbg(0, "In dual channel mode\n");
return 2;
}
}
......@@ -159,7 +159,7 @@ static void i3200_clear_error_info(struct mem_ctl_info *mci)
{
struct pci_dev *pdev;
pdev = to_pci_dev(mci->dev);
pdev = to_pci_dev(mci->pdev);
/*
* Clear any error bits.
......@@ -176,7 +176,7 @@ static void i3200_get_and_clear_error_info(struct mem_ctl_info *mci,
struct i3200_priv *priv = mci->pvt_info;
void __iomem *window = priv->window;
pdev = to_pci_dev(mci->dev);
pdev = to_pci_dev(mci->pdev);
/*
* This is a mess because there is no atomic way to read all the
......@@ -218,25 +218,25 @@ static void i3200_process_error_info(struct mem_ctl_info *mci,
return;
if ((info->errsts ^ info->errsts2) & I3200_ERRSTS_BITS) {
edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 0, 0, 0,
-1, -1, -1, "UE overwrote CE", "", NULL);
edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, 0, 0, 0,
-1, -1, -1, "UE overwrote CE", "");
info->errsts = info->errsts2;
}
for (channel = 0; channel < nr_channels; channel++) {
log = info->eccerrlog[channel];
if (log & I3200_ECCERRLOG_UE) {
edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci,
edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1,
0, 0, 0,
eccerrlog_row(channel, log),
-1, -1,
"i3000 UE", "", NULL);
"i3000 UE", "");
} else if (log & I3200_ECCERRLOG_CE) {
edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci,
edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1,
0, 0, eccerrlog_syndrome(log),
eccerrlog_row(channel, log),
-1, -1,
"i3000 UE", "", NULL);
"i3000 UE", "");
}
}
}
......@@ -245,7 +245,7 @@ static void i3200_check(struct mem_ctl_info *mci)
{
struct i3200_error_info info;
debugf1("MC%d: %s()\n", mci->mc_idx, __func__);
edac_dbg(1, "MC%d\n", mci->mc_idx);
i3200_get_and_clear_error_info(mci, &info);
i3200_process_error_info(mci, &info);
}
......@@ -332,7 +332,7 @@ static int i3200_probe1(struct pci_dev *pdev, int dev_idx)
void __iomem *window;
struct i3200_priv *priv;
debugf0("MC: %s()\n", __func__);
edac_dbg(0, "MC:\n");
window = i3200_map_mchbar(pdev);
if (!window)
......@@ -352,9 +352,9 @@ static int i3200_probe1(struct pci_dev *pdev, int dev_idx)
if (!mci)
return -ENOMEM;
debugf3("MC: %s(): init mci\n", __func__);
edac_dbg(3, "MC: init mci\n");
mci->dev = &pdev->dev;
mci->pdev = &pdev->dev;
mci->mtype_cap = MEM_FLAG_DDR2;
mci->edac_ctl_cap = EDAC_FLAG_SECDED;
......@@ -379,7 +379,7 @@ static int i3200_probe1(struct pci_dev *pdev, int dev_idx)
*/
for (i = 0; i < mci->nr_csrows; i++) {
unsigned long nr_pages;
struct csrow_info *csrow = &mci->csrows[i];
struct csrow_info *csrow = mci->csrows[i];
nr_pages = drb_to_nr_pages(drbs, stacked,
i / I3200_RANKS_PER_CHANNEL,
......@@ -389,7 +389,7 @@ static int i3200_probe1(struct pci_dev *pdev, int dev_idx)
continue;
for (j = 0; j < nr_channels; j++) {
struct dimm_info *dimm = csrow->channels[j].dimm;
struct dimm_info *dimm = csrow->channels[j]->dimm;
dimm->nr_pages = nr_pages / nr_channels;
dimm->grain = nr_pages << PAGE_SHIFT;
......@@ -403,12 +403,12 @@ static int i3200_probe1(struct pci_dev *pdev, int dev_idx)
rc = -ENODEV;
if (edac_mc_add_mc(mci)) {
debugf3("MC: %s(): failed edac_mc_add_mc()\n", __func__);
edac_dbg(3, "MC: failed edac_mc_add_mc()\n");
goto fail;
}
/* get this far and it's successful */
debugf3("MC: %s(): success\n", __func__);
edac_dbg(3, "MC: success\n");
return 0;
fail:
......@@ -424,7 +424,7 @@ static int __devinit i3200_init_one(struct pci_dev *pdev,
{
int rc;
debugf0("MC: %s()\n", __func__);
edac_dbg(0, "MC:\n");
if (pci_enable_device(pdev) < 0)
return -EIO;
......@@ -441,7 +441,7 @@ static void __devexit i3200_remove_one(struct pci_dev *pdev)
struct mem_ctl_info *mci;
struct i3200_priv *priv;
debugf0("%s()\n", __func__);
edac_dbg(0, "\n");
mci = edac_mc_del_mc(&pdev->dev);
if (!mci)
......@@ -475,7 +475,7 @@ static int __init i3200_init(void)
{
int pci_rc;
debugf3("MC: %s()\n", __func__);
edac_dbg(3, "MC:\n");
/* Ensure that the OPSTATE is set correctly for POLL or NMI */
opstate_init();
......@@ -489,14 +489,14 @@ static int __init i3200_init(void)
mci_pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
PCI_DEVICE_ID_INTEL_3200_HB, NULL);
if (!mci_pdev) {
debugf0("i3200 pci_get_device fail\n");
edac_dbg(0, "i3200 pci_get_device fail\n");
pci_rc = -ENODEV;
goto fail1;
}
pci_rc = i3200_init_one(mci_pdev, i3200_pci_tbl);
if (pci_rc < 0) {
debugf0("i3200 init fail\n");
edac_dbg(0, "i3200 init fail\n");
pci_rc = -ENODEV;
goto fail1;
}
......@@ -516,7 +516,7 @@ static int __init i3200_init(void)
static void __exit i3200_exit(void)
{
debugf3("MC: %s()\n", __func__);
edac_dbg(3, "MC:\n");
pci_unregister_driver(&i3200_driver);
if (!i3200_registered) {
......
此差异已折叠。
......@@ -431,10 +431,10 @@ static void i5100_handle_ce(struct mem_ctl_info *mci,
"bank %u, cas %u, ras %u\n",
bank, cas, ras);
edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci,
edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1,
0, 0, syndrome,
chan, rank, -1,
msg, detail, NULL);
msg, detail);
}
static void i5100_handle_ue(struct mem_ctl_info *mci,
......@@ -453,10 +453,10 @@ static void i5100_handle_ue(struct mem_ctl_info *mci,
"bank %u, cas %u, ras %u\n",
bank, cas, ras);
edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci,
edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1,
0, 0, syndrome,
chan, rank, -1,
msg, detail, NULL);
msg, detail);
}
static void i5100_read_log(struct mem_ctl_info *mci, int chan,
......@@ -859,8 +859,8 @@ static void __devinit i5100_init_csrows(struct mem_ctl_info *mci)
i5100_rank_to_slot(mci, chan, rank));
}
debugf2("dimm channel %d, rank %d, size %ld\n",
chan, rank, (long)PAGES_TO_MiB(npages));
edac_dbg(2, "dimm channel %d, rank %d, size %ld\n",
chan, rank, (long)PAGES_TO_MiB(npages));
}
}
......@@ -943,7 +943,7 @@ static int __devinit i5100_init_one(struct pci_dev *pdev,
goto bail_disable_ch1;
}
mci->dev = &pdev->dev;
mci->pdev = &pdev->dev;
priv = mci->pvt_info;
priv->ranksperchan = ranksperch;
......
此差异已折叠。
......@@ -182,24 +182,6 @@ static const u16 mtr_regs[MAX_SLOTS] = {
#define MTR_DIMM_COLS(mtr) ((mtr) & 0x3)
#define MTR_DIMM_COLS_ADDR_BITS(mtr) (MTR_DIMM_COLS(mtr) + 10)
#ifdef CONFIG_EDAC_DEBUG
/* MTR NUMROW */
static const char *numrow_toString[] = {
"8,192 - 13 rows",
"16,384 - 14 rows",
"32,768 - 15 rows",
"65,536 - 16 rows"
};
/* MTR NUMCOL */
static const char *numcol_toString[] = {
"1,024 - 10 columns",
"2,048 - 11 columns",
"4,096 - 12 columns",
"reserved"
};
#endif
/************************************************
* i7300 Register definitions for error detection
************************************************/
......@@ -467,10 +449,10 @@ static void i7300_process_fbd_error(struct mem_ctl_info *mci)
"Bank=%d RAS=%d CAS=%d Err=0x%lx (%s))",
bank, ras, cas, errors, specific);
edac_mc_handle_error(HW_EVENT_ERR_FATAL, mci, 0, 0, 0,
edac_mc_handle_error(HW_EVENT_ERR_FATAL, mci, 1, 0, 0, 0,
branch, -1, rank,
is_wr ? "Write error" : "Read error",
pvt->tmp_prt_buffer, NULL);
pvt->tmp_prt_buffer);
}
......@@ -513,11 +495,11 @@ static void i7300_process_fbd_error(struct mem_ctl_info *mci)
"DRAM-Bank=%d RAS=%d CAS=%d, Err=0x%lx (%s))",
bank, ras, cas, errors, specific);
edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 0, 0,
edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1, 0, 0,
syndrome,
branch >> 1, channel % 2, rank,
is_wr ? "Write error" : "Read error",
pvt->tmp_prt_buffer, NULL);
pvt->tmp_prt_buffer);
}
return;
}
......@@ -614,9 +596,8 @@ static int decode_mtr(struct i7300_pvt *pvt,
mtr = pvt->mtr[slot][branch];
ans = MTR_DIMMS_PRESENT(mtr) ? 1 : 0;
debugf2("\tMTR%d CH%d: DIMMs are %s (mtr)\n",
slot, channel,
ans ? "Present" : "NOT Present");
edac_dbg(2, "\tMTR%d CH%d: DIMMs are %sPresent (mtr)\n",
slot, channel, ans ? "" : "NOT ");
/* Determine if there is a DIMM present in this DIMM slot */
if (!ans)
......@@ -638,16 +619,25 @@ static int decode_mtr(struct i7300_pvt *pvt,
dinfo->megabytes = 1 << addrBits;
debugf2("\t\tWIDTH: x%d\n", MTR_DRAM_WIDTH(mtr));
debugf2("\t\tELECTRICAL THROTTLING is %s\n",
MTR_DIMMS_ETHROTTLE(mtr) ? "enabled" : "disabled");
debugf2("\t\tNUMBANK: %d bank(s)\n", MTR_DRAM_BANKS(mtr));
debugf2("\t\tNUMRANK: %s\n", MTR_DIMM_RANKS(mtr) ? "double" : "single");
debugf2("\t\tNUMROW: %s\n", numrow_toString[MTR_DIMM_ROWS(mtr)]);
debugf2("\t\tNUMCOL: %s\n", numcol_toString[MTR_DIMM_COLS(mtr)]);
debugf2("\t\tSIZE: %d MB\n", dinfo->megabytes);
edac_dbg(2, "\t\tWIDTH: x%d\n", MTR_DRAM_WIDTH(mtr));
edac_dbg(2, "\t\tELECTRICAL THROTTLING is %s\n",
MTR_DIMMS_ETHROTTLE(mtr) ? "enabled" : "disabled");
edac_dbg(2, "\t\tNUMBANK: %d bank(s)\n", MTR_DRAM_BANKS(mtr));
edac_dbg(2, "\t\tNUMRANK: %s\n",
MTR_DIMM_RANKS(mtr) ? "double" : "single");
edac_dbg(2, "\t\tNUMROW: %s\n",
MTR_DIMM_ROWS(mtr) == 0 ? "8,192 - 13 rows" :
MTR_DIMM_ROWS(mtr) == 1 ? "16,384 - 14 rows" :
MTR_DIMM_ROWS(mtr) == 2 ? "32,768 - 15 rows" :
"65,536 - 16 rows");
edac_dbg(2, "\t\tNUMCOL: %s\n",
MTR_DIMM_COLS(mtr) == 0 ? "1,024 - 10 columns" :
MTR_DIMM_COLS(mtr) == 1 ? "2,048 - 11 columns" :
MTR_DIMM_COLS(mtr) == 2 ? "4,096 - 12 columns" :
"reserved");
edac_dbg(2, "\t\tSIZE: %d MB\n", dinfo->megabytes);
/*
* The type of error detection actually depends of the
......@@ -663,9 +653,9 @@ static int decode_mtr(struct i7300_pvt *pvt,
dimm->mtype = MEM_FB_DDR2;
if (IS_SINGLE_MODE(pvt->mc_settings_a)) {
dimm->edac_mode = EDAC_SECDED;
debugf2("\t\tECC code is 8-byte-over-32-byte SECDED+ code\n");
edac_dbg(2, "\t\tECC code is 8-byte-over-32-byte SECDED+ code\n");
} else {
debugf2("\t\tECC code is on Lockstep mode\n");
edac_dbg(2, "\t\tECC code is on Lockstep mode\n");
if (MTR_DRAM_WIDTH(mtr) == 8)
dimm->edac_mode = EDAC_S8ECD8ED;
else
......@@ -674,9 +664,9 @@ static int decode_mtr(struct i7300_pvt *pvt,
/* ask what device type on this row */
if (MTR_DRAM_WIDTH(mtr) == 8) {
debugf2("\t\tScrub algorithm for x8 is on %s mode\n",
IS_SCRBALGO_ENHANCED(pvt->mc_settings) ?
"enhanced" : "normal");
edac_dbg(2, "\t\tScrub algorithm for x8 is on %s mode\n",
IS_SCRBALGO_ENHANCED(pvt->mc_settings) ?
"enhanced" : "normal");
dimm->dtype = DEV_X8;
} else
......@@ -710,14 +700,14 @@ static void print_dimm_size(struct i7300_pvt *pvt)
p += n;
space -= n;
}
debugf2("%s\n", pvt->tmp_prt_buffer);
edac_dbg(2, "%s\n", pvt->tmp_prt_buffer);
p = pvt->tmp_prt_buffer;
space = PAGE_SIZE;
n = snprintf(p, space, "-------------------------------"
"------------------------------");
p += n;
space -= n;
debugf2("%s\n", pvt->tmp_prt_buffer);
edac_dbg(2, "%s\n", pvt->tmp_prt_buffer);
p = pvt->tmp_prt_buffer;
space = PAGE_SIZE;
......@@ -733,7 +723,7 @@ static void print_dimm_size(struct i7300_pvt *pvt)
space -= n;
}
debugf2("%s\n", pvt->tmp_prt_buffer);
edac_dbg(2, "%s\n", pvt->tmp_prt_buffer);
p = pvt->tmp_prt_buffer;
space = PAGE_SIZE;
}
......@@ -742,7 +732,7 @@ static void print_dimm_size(struct i7300_pvt *pvt)
"------------------------------");
p += n;
space -= n;
debugf2("%s\n", pvt->tmp_prt_buffer);
edac_dbg(2, "%s\n", pvt->tmp_prt_buffer);
p = pvt->tmp_prt_buffer;
space = PAGE_SIZE;
#endif
......@@ -765,7 +755,7 @@ static int i7300_init_csrows(struct mem_ctl_info *mci)
pvt = mci->pvt_info;
debugf2("Memory Technology Registers:\n");
edac_dbg(2, "Memory Technology Registers:\n");
/* Get the AMB present registers for the four channels */
for (branch = 0; branch < MAX_BRANCHES; branch++) {
......@@ -774,15 +764,15 @@ static int i7300_init_csrows(struct mem_ctl_info *mci)
pci_read_config_word(pvt->pci_dev_2x_0_fbd_branch[branch],
AMBPRESENT_0,
&pvt->ambpresent[channel]);
debugf2("\t\tAMB-present CH%d = 0x%x:\n",
channel, pvt->ambpresent[channel]);
edac_dbg(2, "\t\tAMB-present CH%d = 0x%x:\n",
channel, pvt->ambpresent[channel]);
channel = to_channel(1, branch);
pci_read_config_word(pvt->pci_dev_2x_0_fbd_branch[branch],
AMBPRESENT_1,
&pvt->ambpresent[channel]);
debugf2("\t\tAMB-present CH%d = 0x%x:\n",
channel, pvt->ambpresent[channel]);
edac_dbg(2, "\t\tAMB-present CH%d = 0x%x:\n",
channel, pvt->ambpresent[channel]);
}
/* Get the set of MTR[0-7] regs by each branch */
......@@ -824,12 +814,11 @@ static int i7300_init_csrows(struct mem_ctl_info *mci)
static void decode_mir(int mir_no, u16 mir[MAX_MIR])
{
if (mir[mir_no] & 3)
debugf2("MIR%d: limit= 0x%x Branch(es) that participate:"
" %s %s\n",
mir_no,
(mir[mir_no] >> 4) & 0xfff,
(mir[mir_no] & 1) ? "B0" : "",
(mir[mir_no] & 2) ? "B1" : "");
edac_dbg(2, "MIR%d: limit= 0x%x Branch(es) that participate: %s %s\n",
mir_no,
(mir[mir_no] >> 4) & 0xfff,
(mir[mir_no] & 1) ? "B0" : "",
(mir[mir_no] & 2) ? "B1" : "");
}
/**
......@@ -849,17 +838,17 @@ static int i7300_get_mc_regs(struct mem_ctl_info *mci)
pci_read_config_dword(pvt->pci_dev_16_0_fsb_ctlr, AMBASE,
(u32 *) &pvt->ambase);
debugf2("AMBASE= 0x%lx\n", (long unsigned int)pvt->ambase);
edac_dbg(2, "AMBASE= 0x%lx\n", (long unsigned int)pvt->ambase);
/* Get the Branch Map regs */
pci_read_config_word(pvt->pci_dev_16_1_fsb_addr_map, TOLM, &pvt->tolm);
pvt->tolm >>= 12;
debugf2("TOLM (number of 256M regions) =%u (0x%x)\n", pvt->tolm,
pvt->tolm);
edac_dbg(2, "TOLM (number of 256M regions) =%u (0x%x)\n",
pvt->tolm, pvt->tolm);
actual_tolm = (u32) ((1000l * pvt->tolm) >> (30 - 28));
debugf2("Actual TOLM byte addr=%u.%03u GB (0x%x)\n",
actual_tolm/1000, actual_tolm % 1000, pvt->tolm << 28);
edac_dbg(2, "Actual TOLM byte addr=%u.%03u GB (0x%x)\n",
actual_tolm/1000, actual_tolm % 1000, pvt->tolm << 28);
/* Get memory controller settings */
pci_read_config_dword(pvt->pci_dev_16_1_fsb_addr_map, MC_SETTINGS,
......@@ -868,15 +857,15 @@ static int i7300_get_mc_regs(struct mem_ctl_info *mci)
&pvt->mc_settings_a);
if (IS_SINGLE_MODE(pvt->mc_settings_a))
debugf0("Memory controller operating on single mode\n");
edac_dbg(0, "Memory controller operating on single mode\n");
else
debugf0("Memory controller operating on %s mode\n",
IS_MIRRORED(pvt->mc_settings) ? "mirrored" : "non-mirrored");
edac_dbg(0, "Memory controller operating on %smirrored mode\n",
IS_MIRRORED(pvt->mc_settings) ? "" : "non-");
debugf0("Error detection is %s\n",
IS_ECC_ENABLED(pvt->mc_settings) ? "enabled" : "disabled");
debugf0("Retry is %s\n",
IS_RETRY_ENABLED(pvt->mc_settings) ? "enabled" : "disabled");
edac_dbg(0, "Error detection is %s\n",
IS_ECC_ENABLED(pvt->mc_settings) ? "enabled" : "disabled");
edac_dbg(0, "Retry is %s\n",
IS_RETRY_ENABLED(pvt->mc_settings) ? "enabled" : "disabled");
/* Get Memory Interleave Range registers */
pci_read_config_word(pvt->pci_dev_16_1_fsb_addr_map, MIR0,
......@@ -970,18 +959,18 @@ static int __devinit i7300_get_devices(struct mem_ctl_info *mci)
}
}
debugf1("System Address, processor bus- PCI Bus ID: %s %x:%x\n",
pci_name(pvt->pci_dev_16_0_fsb_ctlr),
pvt->pci_dev_16_0_fsb_ctlr->vendor,
pvt->pci_dev_16_0_fsb_ctlr->device);
debugf1("Branchmap, control and errors - PCI Bus ID: %s %x:%x\n",
pci_name(pvt->pci_dev_16_1_fsb_addr_map),
pvt->pci_dev_16_1_fsb_addr_map->vendor,
pvt->pci_dev_16_1_fsb_addr_map->device);
debugf1("FSB Error Regs - PCI Bus ID: %s %x:%x\n",
pci_name(pvt->pci_dev_16_2_fsb_err_regs),
pvt->pci_dev_16_2_fsb_err_regs->vendor,
pvt->pci_dev_16_2_fsb_err_regs->device);
edac_dbg(1, "System Address, processor bus- PCI Bus ID: %s %x:%x\n",
pci_name(pvt->pci_dev_16_0_fsb_ctlr),
pvt->pci_dev_16_0_fsb_ctlr->vendor,
pvt->pci_dev_16_0_fsb_ctlr->device);
edac_dbg(1, "Branchmap, control and errors - PCI Bus ID: %s %x:%x\n",
pci_name(pvt->pci_dev_16_1_fsb_addr_map),
pvt->pci_dev_16_1_fsb_addr_map->vendor,
pvt->pci_dev_16_1_fsb_addr_map->device);
edac_dbg(1, "FSB Error Regs - PCI Bus ID: %s %x:%x\n",
pci_name(pvt->pci_dev_16_2_fsb_err_regs),
pvt->pci_dev_16_2_fsb_err_regs->vendor,
pvt->pci_dev_16_2_fsb_err_regs->device);
pvt->pci_dev_2x_0_fbd_branch[0] = pci_get_device(PCI_VENDOR_ID_INTEL,
PCI_DEVICE_ID_INTEL_I7300_MCH_FB0,
......@@ -1032,10 +1021,9 @@ static int __devinit i7300_init_one(struct pci_dev *pdev,
if (rc == -EIO)
return rc;
debugf0("MC: " __FILE__ ": %s(), pdev bus %u dev=0x%x fn=0x%x\n",
__func__,
pdev->bus->number,
PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn));
edac_dbg(0, "MC: pdev bus %u dev=0x%x fn=0x%x\n",
pdev->bus->number,
PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn));
/* We only are looking for func 0 of the set */
if (PCI_FUNC(pdev->devfn) != 0)
......@@ -1055,9 +1043,9 @@ static int __devinit i7300_init_one(struct pci_dev *pdev,
if (mci == NULL)
return -ENOMEM;
debugf0("MC: " __FILE__ ": %s(): mci = %p\n", __func__, mci);
edac_dbg(0, "MC: mci = %p\n", mci);
mci->dev = &pdev->dev; /* record ptr to the generic device */
mci->pdev = &pdev->dev; /* record ptr to the generic device */
pvt = mci->pvt_info;
pvt->pci_dev_16_0_fsb_ctlr = pdev; /* Record this device in our private */
......@@ -1088,19 +1076,16 @@ static int __devinit i7300_init_one(struct pci_dev *pdev,
/* initialize the MC control structure 'csrows' table
* with the mapping and control information */
if (i7300_get_mc_regs(mci)) {
debugf0("MC: Setting mci->edac_cap to EDAC_FLAG_NONE\n"
" because i7300_init_csrows() returned nonzero "
"value\n");
edac_dbg(0, "MC: Setting mci->edac_cap to EDAC_FLAG_NONE because i7300_init_csrows() returned nonzero value\n");
mci->edac_cap = EDAC_FLAG_NONE; /* no csrows found */
} else {
debugf1("MC: Enable error reporting now\n");
edac_dbg(1, "MC: Enable error reporting now\n");
i7300_enable_error_reporting(mci);
}
/* add this new MC control structure to EDAC's list of MCs */
if (edac_mc_add_mc(mci)) {
debugf0("MC: " __FILE__
": %s(): failed edac_mc_add_mc()\n", __func__);
edac_dbg(0, "MC: failed edac_mc_add_mc()\n");
/* FIXME: perhaps some code should go here that disables error
* reporting if we just enabled it
*/
......@@ -1142,7 +1127,7 @@ static void __devexit i7300_remove_one(struct pci_dev *pdev)
struct mem_ctl_info *mci;
char *tmp;
debugf0(__FILE__ ": %s()\n", __func__);
edac_dbg(0, "\n");
if (i7300_pci)
edac_pci_release_generic_ctl(i7300_pci);
......@@ -1189,7 +1174,7 @@ static int __init i7300_init(void)
{
int pci_rc;
debugf2("MC: " __FILE__ ": %s()\n", __func__);
edac_dbg(2, "\n");
/* Ensure that the OPSTATE is set correctly for POLL or NMI */
opstate_init();
......@@ -1204,7 +1189,7 @@ static int __init i7300_init(void)
*/
static void __exit i7300_exit(void)
{
debugf2("MC: " __FILE__ ": %s()\n", __func__);
edac_dbg(2, "\n");
pci_unregister_driver(&i7300_driver);
}
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
......@@ -69,12 +69,12 @@ static void tile_edac_check(struct mem_ctl_info *mci)
/* Check if the current error count is different from the saved one. */
if (mem_error.sbe_count != priv->ce_count) {
dev_dbg(mci->dev, "ECC CE err on node %d\n", priv->node);
dev_dbg(mci->pdev, "ECC CE err on node %d\n", priv->node);
priv->ce_count = mem_error.sbe_count;
edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci,
edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1,
0, 0, 0,
0, 0, -1,
mci->ctl_name, "", NULL);
mci->ctl_name, "");
}
}
......@@ -84,10 +84,10 @@ static void tile_edac_check(struct mem_ctl_info *mci)
*/
static int __devinit tile_edac_init_csrows(struct mem_ctl_info *mci)
{
struct csrow_info *csrow = &mci->csrows[0];
struct csrow_info *csrow = mci->csrows[0];
struct tile_edac_priv *priv = mci->pvt_info;
struct mshim_mem_info mem_info;
struct dimm_info *dimm = csrow->channels[0].dimm;
struct dimm_info *dimm = csrow->channels[0]->dimm;
if (hv_dev_pread(priv->hv_devhdl, 0, (HV_VirtAddr)&mem_info,
sizeof(struct mshim_mem_info), MSHIM_MEM_INFO_OFF) !=
......@@ -149,7 +149,7 @@ static int __devinit tile_edac_mc_probe(struct platform_device *pdev)
priv->node = pdev->id;
priv->hv_devhdl = hv_devhdl;
mci->dev = &pdev->dev;
mci->pdev = &pdev->dev;
mci->mtype_cap = MEM_FLAG_DDR2;
mci->edac_ctl_cap = EDAC_FLAG_SECDED;
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册