From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932097AbVJKOpA (ORCPT ); Tue, 11 Oct 2005 10:45:00 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S932102AbVJKOpA (ORCPT ); Tue, 11 Oct 2005 10:45:00 -0400 Received: from clock-tower.bc.nu ([81.2.110.250]:50911 "EHLO lxorguk.ukuu.org.uk") by vger.kernel.org with ESMTP id S932097AbVJKOo6 (ORCPT ); Tue, 11 Oct 2005 10:44:58 -0400 Subject: [RFC PATCH] 1/2 EDAC (Core Code) From: Alan Cox To: linux-kernel@vger.kernel.org Content-Type: text/plain Content-Transfer-Encoding: 7bit Date: Tue, 11 Oct 2005 16:13:43 +0100 Message-Id: <1129043623.23677.75.camel@localhost.localdomain> Mime-Version: 1.0 X-Mailer: Evolution 2.2.3 (2.2.3-2.fc4) Sender: linux-kernel-owner@vger.kernel.org X-Mailing-List: linux-kernel@vger.kernel.org This is a pair of patches that add the basic ECC and related chipset handling to the kernel. Various "interesting" patches have kicked around since Dan Hollis original work some years ago. Since then many people have picked up the code and improved on it. The current code (bluesmoke.sf.net) has some very fancy NMI handling features and other complex open issues with NMI during a PCI transaction and the like. This code is a subset and the maintainer agrees this is the best approach to merging. >>From the original repository - 2.4 and other compatibility code removed - Some commenting added - A couple of 32bit isms cleaned up - Move several drivers from pci_find to pci_get - Remove all the NMI layer handling so that the code requires no core changes - Rename from bluesmoke to EDAC (Correct name for the whole field of ECC and friends) to avoid confusion I don't think its yet merge ready but getting there so I'd appreciate other folks comments and views on what else needs fixing before generating a submission for Andrew. diff -u --new-file --recursive --exclude-from /usr/src/exclude ../linux.vanilla-2.6.14-rc2-mm1/drivers/edac/edac_mc.c ./drivers/edac/edac_mc.c --- ../linux.vanilla-2.6.14-rc2-mm1/drivers/edac/edac_mc.c 1970-01-01 01:00:00.000000000 +0100 +++ ./drivers/edac/edac_mc.c 2005-10-07 17:13:51.000000000 +0100 @@ -0,0 +1,1409 @@ +/* + * edac_mc kernel module + * (C) 2003 Linux Networx (http://lnxi.com) + * This file may be distributed under the terms of the + * GNU General Public License. + * + * Written by Thayne Harbaugh + * Based on work by Dan Hollis and others. + * http://www.anime.net/~goemon/linux-ecc/ + * + * NMI handling support added by + * Dave Peterson + * + * $Id: edac_mc.c,v 1.7.2.19 2005/10/05 22:01:42 dsp_llnl Exp $ + * + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "edac_mc.h" + + +#define EDAC_MC_VERSION "edac_mc Ver: 2.0.0.devel " __DATE__ + +#ifndef pfn_to_page +#define pfn_to_page(pfn) (mem_map + (pfn)) +#endif /* pfn_to_page */ + +#ifdef CONFIG_EDAC_DEBUG +int edac_debug_level = 0; +EXPORT_SYMBOL(edac_debug_level); +#endif + +#define MC_PROC_DIR "mc" +#define EDAC_THREAD_NAME "kedac" + + +/* /proc/mc dir */ +static struct proc_dir_entry *proc_mc; + +/* Setable by module parameter and sysctl */ +static int panic_on_ue = 1; +static int check_pci_parity = 1; /* default YES check PCI parity */ +static int panic_on_pci_parity = 0; /* default no panic on PCI Parity */ +static int log_ue = 1; +static int log_ce = 1; +static int poll_msec = 1000; + +static u32 pci_parity_count = 0; + + +/* lock to memory controller's control array */ +static DECLARE_MUTEX(mem_ctls_mutex); + +static struct list_head mc_devices = LIST_HEAD_INIT(mc_devices); + +static struct mem_ctl_info * find_mc_by_idx (int idx) +{ + struct list_head *item; + struct mem_ctl_info *mci; + + list_for_each(item, &mc_devices) { + mci = list_entry(item, struct mem_ctl_info, link); + + if (mci->mc_idx >= idx) { + if (mci->mc_idx == idx) + return mci; + + break; + } + } + + return NULL; +} + +#ifdef CONFIG_SYSCTL +static void dimm_labels(char *buf, void *data) +{ + int mcidx, ridx, chidx; + char *mcstr, *rstr, *chstr, *lstr, *p; + struct mem_ctl_info *mci; + + lstr = buf; + + mcstr = strsep(&lstr, "."); + if (!lstr) + return; + mcidx = simple_strtol(mcstr, &p, 0); + if (*p) + return; + if ((mci = find_mc_by_idx(mcidx)) == NULL) + return; + rstr = strsep(&lstr, "."); + if (!lstr) + return; + ridx = simple_strtol(rstr, &p, 0); + if (*p) + return; + if ((ridx >= mci->nr_csrows) || !mci->csrows) + return; + + chstr = strsep(&lstr, ":"); + if (!lstr) + return; + chidx = simple_strtol(chstr, &p, 0); + if (*p) + return; + if ((chidx >= mci->csrows[ridx].nr_channels) || + !mci->csrows[ridx].channels) + return; + + debugf1("%d:%d.%d:%s\n", mcidx, ridx, chidx, lstr); + + strncpy(mci->csrows[ridx].channels[chidx].label, lstr, + EDAC_MC_LABEL_LEN + 1); + /* + * no need to NULL terminate label since + * get_user_tok() NULL terminates. + */ +} + + +static void counter_reset(char *buf, void *data) +{ + char *p = buf; + int mcidx, row, chan; + struct mem_ctl_info *mci; + + pci_parity_count = 0; + + mcidx = simple_strtol(buf, &p, 0); + if (*p) + return; + + down(&mem_ctls_mutex); + mci = find_mc_by_idx(mcidx); + + if (mci == NULL) + goto out; + + mci->ue_noinfo_count = 0; + mci->ce_noinfo_count = 0; + mci->ue_count = 0; + mci->ce_count = 0; + for (row = 0; row < mci->nr_csrows; row++) { + struct csrow_info *ri = &mci->csrows[row]; + + ri->ue_count = 0; + ri->ce_count = 0; + for (chan = 0; chan < ri->nr_channels; chan++) + ri->channels[chan].ce_count = 0; + } + mci->start_time = jiffies; +out: + up(&mem_ctls_mutex); +} + + +struct actionvec_info { + void (*action) (char *str, void *data); + char separator; + char *usage; + void *data; +}; + + +static struct actionvec_info dimm_labels_avi = { + .action = dimm_labels, + .separator = ',', + .usage = "..: