diff options
author | eric wollesen <ericw@xmtp.net> | 2007-02-12 00:53:08 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-02-12 09:48:32 -0800 |
commit | 9794f33ddedd878dd92fcf8b4834391840366919 (patch) | |
tree | b64ed2488fe95a1217d14704422cc467193f34a3 /drivers/edac/edac_mc.c | |
parent | 4f423ddf56e5ecb1fb2eac83b8e228e3d0aae0f6 (diff) | |
download | blackbird-op-linux-9794f33ddedd878dd92fcf8b4834391840366919.tar.gz blackbird-op-linux-9794f33ddedd878dd92fcf8b4834391840366919.zip |
[PATCH] EDAC: Add Fully-Buffered DIMM APIs to core
Eric Wollesen ported the Bluesmoke Memory Controller driver for the Intel
5000X/V/P (Blackford/Greencreek) chipset to the in kernel EDAC model.
This patch incorporates those required changes to the edac_mc.c and edac_mc.h
core files by added new Fully Buffered DIMM interface to the EDAC Core module.
Signed-off-by: eric wollesen <ericw@xmtp.net>
Signed-off-by: doug thompson <norsk5@xmission.com>
Acked-by: Alan Cox <alan@redhat.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/edac/edac_mc.c')
-rw-r--r-- | drivers/edac/edac_mc.c | 120 |
1 files changed, 115 insertions, 5 deletions
diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c index 1df8c0c5d40a..7b622300d0e5 100644 --- a/drivers/edac/edac_mc.c +++ b/drivers/edac/edac_mc.c @@ -1497,11 +1497,11 @@ int edac_mc_add_mc(struct mem_ctl_info *mci, int mc_idx) /* set load time so that error rate can be tracked */ mci->start_time = jiffies; - if (edac_create_sysfs_mci_device(mci)) { - edac_mc_printk(mci, KERN_WARNING, + if (edac_create_sysfs_mci_device(mci)) { + edac_mc_printk(mci, KERN_WARNING, "failed to create sysfs device\n"); - goto fail1; - } + goto fail1; + } /* Report action taken */ edac_mc_printk(mci, KERN_INFO, "Giving out device to %s %s: DEV %s\n", @@ -1758,6 +1758,116 @@ void edac_mc_handle_ue_no_info(struct mem_ctl_info *mci, const char *msg) EXPORT_SYMBOL_GPL(edac_mc_handle_ue_no_info); +/************************************************************* + * On Fully Buffered DIMM modules, this help function is + * called to process UE events + */ +void edac_mc_handle_fbd_ue(struct mem_ctl_info *mci, + unsigned int csrow, + unsigned int channela, + unsigned int channelb, + char *msg) +{ + int len = EDAC_MC_LABEL_LEN * 4; + char labels[len + 1]; + char *pos = labels; + int chars; + + if (csrow >= mci->nr_csrows) { + /* something is wrong */ + edac_mc_printk(mci, KERN_ERR, + "INTERNAL ERROR: row out of range (%d >= %d)\n", + csrow, mci->nr_csrows); + edac_mc_handle_ue_no_info(mci, "INTERNAL ERROR"); + return; + } + + if (channela >= mci->csrows[csrow].nr_channels) { + /* something is wrong */ + edac_mc_printk(mci, KERN_ERR, + "INTERNAL ERROR: channel-a out of range " + "(%d >= %d)\n", + channela, mci->csrows[csrow].nr_channels); + edac_mc_handle_ue_no_info(mci, "INTERNAL ERROR"); + return; + } + + if (channelb >= mci->csrows[csrow].nr_channels) { + /* something is wrong */ + edac_mc_printk(mci, KERN_ERR, + "INTERNAL ERROR: channel-b out of range " + "(%d >= %d)\n", + channelb, mci->csrows[csrow].nr_channels); + edac_mc_handle_ue_no_info(mci, "INTERNAL ERROR"); + return; + } + + mci->ue_count++; + mci->csrows[csrow].ue_count++; + + /* Generate the DIMM labels from the specified channels */ + chars = snprintf(pos, len + 1, "%s", + mci->csrows[csrow].channels[channela].label); + len -= chars; pos += chars; + chars = snprintf(pos, len + 1, "-%s", + mci->csrows[csrow].channels[channelb].label); + + if (log_ue) + edac_mc_printk(mci, KERN_EMERG, + "UE row %d, channel-a= %d channel-b= %d " + "labels \"%s\": %s\n", csrow, channela, channelb, + labels, msg); + + if (panic_on_ue) + panic("UE row %d, channel-a= %d channel-b= %d " + "labels \"%s\": %s\n", csrow, channela, + channelb, labels, msg); +} +EXPORT_SYMBOL(edac_mc_handle_fbd_ue); + +/************************************************************* + * On Fully Buffered DIMM modules, this help function is + * called to process CE events + */ +void edac_mc_handle_fbd_ce(struct mem_ctl_info *mci, + unsigned int csrow, + unsigned int channel, + char *msg) +{ + + /* Ensure boundary values */ + if (csrow >= mci->nr_csrows) { + /* something is wrong */ + edac_mc_printk(mci, KERN_ERR, + "INTERNAL ERROR: row out of range (%d >= %d)\n", + csrow, mci->nr_csrows); + edac_mc_handle_ce_no_info(mci, "INTERNAL ERROR"); + return; + } + if (channel >= mci->csrows[csrow].nr_channels) { + /* something is wrong */ + edac_mc_printk(mci, KERN_ERR, + "INTERNAL ERROR: channel out of range (%d >= %d)\n", + channel, mci->csrows[csrow].nr_channels); + edac_mc_handle_ce_no_info(mci, "INTERNAL ERROR"); + return; + } + + if (log_ce) + /* FIXME - put in DIMM location */ + edac_mc_printk(mci, KERN_WARNING, + "CE row %d, channel %d, label \"%s\": %s\n", + csrow, channel, + mci->csrows[csrow].channels[channel].label, + msg); + + mci->ce_count++; + mci->csrows[csrow].ce_count++; + mci->csrows[csrow].channels[channel].ce_count++; +} +EXPORT_SYMBOL(edac_mc_handle_fbd_ce); + + /* * Iterate over all MC instances and check for ECC, et al, errors */ @@ -1861,7 +1971,7 @@ static void __exit edac_mc_exit(void) debugf0("%s()\n", __func__); kthread_stop(edac_thread); - /* tear down the sysfs device */ + /* tear down the sysfs device */ edac_sysfs_memctrl_teardown(); edac_sysfs_pci_teardown(); } |