public inbox for linux-ia64@vger.kernel.org
 help / color / mirror / Atom feed
* [patch] 2.6.0-test9 pal/sal/salinfo/mca
@ 2003-11-25  8:37 Keith Owens
  0 siblings, 0 replies; 9+ messages in thread
From: Keith Owens @ 2003-11-25  8:37 UTC (permalink / raw)
  To: linux-ia64

Forward port the recent changes to pal.h, sal.h, mca.h, salinfo.c and
mca.c from 2.4.23-rc2 to 2.6.0-test9.

This converts 2.6 to use salinfo instead of printing CMC/CPE/MCA/INIT
records in the kernel.  It makes the two kernel versions as close
together as possible.


Index: 9.2/include/asm-ia64/sal.h
--- 9.2/include/asm-ia64/sal.h Sun, 24 Aug 2003 10:59:40 +1000 kaos (linux-2.6-test/u/c/36_sal.h 1.3 644)
+++ 9.4/include/asm-ia64/sal.h Tue, 25 Nov 2003 19:23:21 +1100 kaos (linux-2.6-test/u/c/36_sal.h 1.4 644)
@@ -725,14 +725,16 @@ ia64_sal_mc_rendez (void)
  * Allow the OS to specify the interrupt number to be used by SAL to interrupt OS during
  * the machine check rendezvous sequence as well as the mechanism to wake up the
  * non-monarch processor at the end of machine check processing.
+ * Returns the complete ia64_sal_retval because some calls return more than just a status
+ * value.
  */
-static inline s64
+static inline struct ia64_sal_retval
 ia64_sal_mc_set_params (u64 param_type, u64 i_or_m, u64 i_or_m_val, u64 timeout, u64 rz_always)
 {
 	struct ia64_sal_retval isrv;
 	SAL_CALL(isrv, SAL_MC_SET_PARAMS, param_type, i_or_m, i_or_m_val,
 		 timeout, rz_always, 0, 0);
-	return isrv.status;
+	return isrv;
 }
 
 /* Read from PCI configuration space */
@@ -804,10 +806,12 @@ ia64_sal_update_pal (u64 param_buf, u64 
 
 extern unsigned long sal_platform_features;
 
+extern int (*salinfo_platform_oemdata)(const u8 *, u8 **, u64 *);
+
 struct sal_ret_values {
 	long r8; long r9; long r10; long r11;
 };
 
 #endif /* __ASSEMBLY__ */
 
-#endif /* _ASM_IA64_PAL_H */
+#endif /* _ASM_IA64_SAL_H */
Index: 9.2/include/asm-ia64/pal.h
--- 9.2/include/asm-ia64/pal.h Mon, 20 Oct 2003 11:16:44 +1000 kaos (linux-2.6-test/v/c/12_pal.h 1.3 644)
+++ 9.4/include/asm-ia64/pal.h Tue, 25 Nov 2003 19:23:21 +1100 kaos (linux-2.6-test/v/c/12_pal.h 1.4 644)
@@ -461,23 +461,13 @@ typedef struct pal_process_state_info_s 
 } pal_processor_state_info_t;
 
 typedef struct pal_cache_check_info_s {
-	u64		reserved1	: 16,
-			way		: 5,	/* Way in which the
-						 * error occurred
-						 */
-			reserved2	: 1,
-			mc		: 1,	/* Machine check corrected */
-			tv		: 1,	/* Target address
-						 * structure is valid
-						 */
-
-			wv		: 1,	/* Way field valid */
-			op		: 3,	/* Type of cache
+	u64		op		: 4,	/* Type of cache
 						 * operation that
 						 * caused the machine
 						 * check.
 						 */
-
+			level		: 2,	/* Cache level */
+			reserved1	: 2,
 			dl		: 1,	/* Failure in data part
 						 * of cache line
 						 */
@@ -486,11 +476,34 @@ typedef struct pal_cache_check_info_s {
 						 */
 			dc		: 1,	/* Failure in dcache */
 			ic		: 1,	/* Failure in icache */
-			index		: 24,	/* Cache line index */
-			mv		: 1,	/* mesi valid */
 			mesi		: 3,	/* Cache line state */
-			level		: 4;	/* Cache level */
+			mv		: 1,	/* mesi valid */
+			way		: 5,	/* Way in which the
+						 * error occurred
+						 */
+			wiv		: 1,	/* Way field valid */
+			reserved2	: 10,
+
+			index		: 20,	/* Cache line index */
+			reserved3	: 2,
 
+			is		: 1,	/* instruction set (1 = ia32) */
+			iv		: 1,	/* instruction set field valid */
+			pl		: 2,	/* privilege level */
+			pv		: 1,	/* privilege level field valid */
+			mcc		: 1,	/* Machine check corrected */
+			tv		: 1,	/* Target address
+						 * structure is valid
+						 */
+			rq		: 1,	/* Requester identifier
+						 * structure is valid
+						 */
+			rp		: 1,	/* Responder identifier
+						 * structure is valid
+						 */
+			pi		: 1;	/* Precise instruction pointer
+						 * structure is valid
+						 */
 } pal_cache_check_info_t;
 
 typedef struct pal_tlb_check_info_s {
@@ -498,18 +511,38 @@ typedef struct pal_tlb_check_info_s {
 	u64		tr_slot		: 8,	/* Slot# of TR where
 						 * error occurred
 						 */
-			reserved2	: 8,
+			trv		: 1,	/* tr_slot field is valid */
+			reserved1	: 1,
+			level		: 2,	/* TLB level where failure occurred */
+			reserved2	: 4,
 			dtr		: 1,	/* Fail in data TR */
 			itr		: 1,	/* Fail in inst TR */
 			dtc		: 1,	/* Fail in data TC */
 			itc		: 1,	/* Fail in inst. TC */
-			mc		: 1,	/* Machine check corrected */
-			reserved1	: 43;
+			op		: 4,	/* Cache operation */
+			reserved3	: 30,
 
+			is		: 1,	/* instruction set (1 = ia32) */
+			iv		: 1,	/* instruction set field valid */
+			pl		: 2,	/* privilege level */
+			pv		: 1,	/* privilege level field valid */
+			mcc		: 1,	/* Machine check corrected */
+			tv		: 1,	/* Target address
+						 * structure is valid
+						 */
+			rq		: 1,	/* Requester identifier
+						 * structure is valid
+						 */
+			rp		: 1,	/* Responder identifier
+						 * structure is valid
+						 */
+			pi		: 1;	/* Precise instruction pointer
+						 * structure is valid
+						 */
 } pal_tlb_check_info_t;
 
 typedef struct pal_bus_check_info_s {
-	u64		size		: 5,	/* Xaction size*/
+	u64		size		: 5,	/* Xaction size */
 			ib		: 1,	/* Internal bus error */
 			eb		: 1,	/* External bus error */
 			cc		: 1,	/* Error occurred
@@ -518,22 +551,99 @@ typedef struct pal_bus_check_info_s {
 						 */
 			type		: 8,	/* Bus xaction type*/
 			sev		: 5,	/* Bus error severity*/
-			tv		: 1,	/* Targ addr valid */
-			rp		: 1,	/* Resp addr valid */
-			rq		: 1,	/* Req addr valid */
+			hier		: 2,	/* Bus hierarchy level */
+			reserved1	: 1,
 			bsi		: 8,	/* Bus error status
 						 * info
 						 */
-			mc		: 1,	/* Machine check corrected */
-			reserved1	: 31;
+			reserved2	: 22,
+
+			is		: 1,	/* instruction set (1 = ia32) */
+			iv		: 1,	/* instruction set field valid */
+			pl		: 2,	/* privilege level */
+			pv		: 1,	/* privilege level field valid */
+			mcc		: 1,	/* Machine check corrected */
+			tv		: 1,	/* Target address
+						 * structure is valid
+						 */
+			rq		: 1,	/* Requester identifier
+						 * structure is valid
+						 */
+			rp		: 1,	/* Responder identifier
+						 * structure is valid
+						 */
+			pi		: 1;	/* Precise instruction pointer
+						 * structure is valid
+						 */
 } pal_bus_check_info_t;
 
+typedef struct pal_reg_file_check_info_s {
+	u64		id		: 4,	/* Register file identifier */
+			op		: 4,	/* Type of register
+						 * operation that
+						 * caused the machine
+						 * check.
+						 */
+			reg_num		: 7,	/* Register number */
+			rnv		: 1,	/* reg_num valid */
+			reserved2	: 38,
+
+			is		: 1,	/* instruction set (1 = ia32) */
+			iv		: 1,	/* instruction set field valid */
+			pl		: 2,	/* privilege level */
+			pv		: 1,	/* privilege level field valid */
+			mcc		: 1,	/* Machine check corrected */
+			reserved3	: 3,
+			pi		: 1;	/* Precise instruction pointer
+						 * structure is valid
+						 */
+} pal_reg_file_check_info_t;
+
+typedef struct pal_uarch_check_info_s {
+	u64		sid		: 5,	/* Structure identification */
+			level		: 3,	/* Level of failure */
+			array_id	: 4,	/* Array identification */
+			op		: 4,	/* Type of
+						 * operation that
+						 * caused the machine
+						 * check.
+						 */
+			way		: 6,	/* Way of structure */
+			wv		: 1,	/* way valid */
+			xv		: 1,	/* index valid */
+			reserved1	: 8,
+			index		: 8,	/* Index or set of the uarch
+						 * structure that failed.
+						 */
+			reserved2	: 24,
+
+			is		: 1,	/* instruction set (1 = ia32) */
+			iv		: 1,	/* instruction set field valid */
+			pl		: 2,	/* privilege level */
+			pv		: 1,	/* privilege level field valid */
+			mcc		: 1,	/* Machine check corrected */
+			tv		: 1,	/* Target address
+						 * structure is valid
+						 */
+			rq		: 1,	/* Requester identifier
+						 * structure is valid
+						 */
+			rp		: 1,	/* Responder identifier
+						 * structure is valid
+						 */
+			pi		: 1;	/* Precise instruction pointer
+						 * structure is valid
+						 */
+} pal_uarch_check_info_t;
+
 typedef union pal_mc_error_info_u {
 	u64				pmei_data;
 	pal_processor_state_info_t	pme_processor;
 	pal_cache_check_info_t		pme_cache;
 	pal_tlb_check_info_t		pme_tlb;
 	pal_bus_check_info_t		pme_bus;
+	pal_reg_file_check_info_t	pme_reg_file;
+	pal_uarch_check_info_t		pme_uarch;
 } pal_mc_error_info_t;
 
 #define pmci_proc_unknown_check			pme_processor.uc
Index: 9.2/include/asm-ia64/mca.h
--- 9.2/include/asm-ia64/mca.h Mon, 20 Oct 2003 11:16:44 +1000 kaos (linux-2.6-test/w/c/12_mca.h 1.3 644)
+++ 9.4/include/asm-ia64/mca.h Tue, 25 Nov 2003 19:23:21 +1100 kaos (linux-2.6-test/w/c/12_mca.h 1.4 644)
@@ -141,7 +141,6 @@ extern irqreturn_t ia64_mca_cpe_int_call
 extern int  ia64_log_print(int,prfunc_t);
 extern void ia64_mca_cmc_vector_setup(void);
 extern int  ia64_mca_check_errors(void);
-extern u64  ia64_log_get(int, prfunc_t);
 
 #define PLATFORM_CALL(fn, args)	printk("Platform call TBD\n")
 
Index: 9.2/arch/ia64/Kconfig
--- 9.2/arch/ia64/Kconfig Tue, 21 Oct 2003 18:45:55 +1000 kaos (linux-2.6-test/F/e/0_Kconfig 1.6 644)
+++ 9.4/arch/ia64/Kconfig Tue, 25 Nov 2003 19:23:21 +1100 kaos (linux-2.6-test/F/e/0_Kconfig 1.7 644)
@@ -394,16 +394,6 @@ config IA64_PALINFO
 	  To use this option, you have to ensure that the "/proc file system
 	  support" (CONFIG_PROC_FS) is enabled, too.
 
-config IA64_SALINFO
-	tristate "/proc/sal support"
-	help
-	  The /proc/sal directory exports the SAL (system abstraction layer)
-	  feature bits, like whether the platform is subject to ITC drift.  It
-	  is intended to be used by user programs that care about such things.
-
-	  To use this option, you have to ensure that the "/proc file system
-	  support" (CONFIG_PROC_FS) is enabled, too.
-
 config EFI_VARS
 	tristate "/proc/efi/vars support"
 	help
Index: 9.2/arch/ia64/kernel/Makefile
--- 9.2/arch/ia64/kernel/Makefile Mon, 29 Sep 2003 13:13:55 +1000 kaos (linux-2.6-test/I/e/3_Makefile 1.3 644)
+++ 9.4/arch/ia64/kernel/Makefile Tue, 25 Nov 2003 19:23:21 +1100 kaos (linux-2.6-test/I/e/3_Makefile 1.4 644)
@@ -6,7 +6,7 @@ extra-y	:= head.o init_task.o vmlinux.ld
 
 obj-y := acpi.o entry.o efi.o efi_stub.o gate-data.o fsys.o ia64_ksyms.o irq.o irq_ia64.o	\
 	 irq_lsapic.o ivt.o machvec.o pal.o patch.o process.o perfmon.o ptrace.o sal.o		\
-	 semaphore.o setup.o signal.o sys_ia64.o time.o traps.o unaligned.o unwind.o
+	 salinfo.o semaphore.o setup.o signal.o sys_ia64.o time.o traps.o unaligned.o unwind.o
 
 obj-$(CONFIG_EFI_VARS)		+= efivars.o
 obj-$(CONFIG_IA64_BRL_EMU)	+= brl_emu.o
@@ -14,7 +14,6 @@ obj-$(CONFIG_IA64_GENERIC)	+= acpi-ext.o
 obj-$(CONFIG_IA64_HP_ZX1)	+= acpi-ext.o
 obj-$(CONFIG_IA64_MCA)		+= mca.o mca_asm.o
 obj-$(CONFIG_IA64_PALINFO)	+= palinfo.o
-obj-$(CONFIG_IA64_SALINFO)	+= salinfo.o
 obj-$(CONFIG_IOSAPIC)		+= iosapic.o
 obj-$(CONFIG_MODULES)		+= module.o
 obj-$(CONFIG_SMP)		+= smp.o smpboot.o
Index: 9.2/arch/ia64/kernel/salinfo.c
--- 9.2/arch/ia64/kernel/salinfo.c Mon, 29 Sep 2003 13:13:55 +1000 kaos (linux-2.6-test/I/e/22_salinfo.c 1.2 644)
+++ 9.4/arch/ia64/kernel/salinfo.c Tue, 25 Nov 2003 19:23:21 +1100 kaos (linux-2.6-test/I/e/22_salinfo.c 1.3 644)
@@ -3,18 +3,31 @@
  *
  * Creates entries in /proc/sal for various system features.
  *
- * Copyright (c) 2001 Silicon Graphics, Inc.  All rights reserved.
+ * Copyright (c) 2003 Silicon Graphics, Inc.  All rights reserved.
+ * Copyright (c) 2003 Hewlett-Packard Co
+ *	Bjorn Helgaas <bjorn.helgaas@hp.com>
  *
- * 09/11/2003	jbarnes@sgi.com		updated for 2.6
  * 10/30/2001	jbarnes@sgi.com		copied much of Stephane's palinfo
  *					code to create this file
+ * Oct 23 2003	kaos@sgi.com
+ *   Replace IPI with set_cpus_allowed() to read a record from the required cpu.
+ *   Redesign salinfo log processing to separate interrupt and user space
+ *   contexts.
+ *   Cache the record across multi-block reads from user space.
+ *   Support > 64 cpus.
+ *   Delete module_exit and MOD_INC/DEC_COUNT, salinfo cannot be a module.
  */
 
 #include <linux/types.h>
 #include <linux/proc_fs.h>
 #include <linux/module.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/vmalloc.h>
 
+#include <asm/semaphore.h>
 #include <asm/sal.h>
+#include <asm/uaccess.h>
 
 MODULE_AUTHOR("Jesse Barnes <jbarnes@sgi.com>");
 MODULE_DESCRIPTION("/proc interface to IA-64 SAL features");
@@ -41,42 +54,511 @@ static salinfo_entry_t salinfo_entries[]
 
 #define NR_SALINFO_ENTRIES ARRAY_SIZE(salinfo_entries)
 
-/*
- * One for each feature and one more for the directory entry...
+static char *salinfo_log_name[] = {
+	"mca",
+	"init",
+	"cmc",
+	"cpe",
+};
+
+static struct proc_dir_entry *salinfo_proc_entries[
+	ARRAY_SIZE(salinfo_entries) +			/* /proc/sal/bus_lock */
+	ARRAY_SIZE(salinfo_log_name) +			/* /proc/sal/{mca,...} */
+	(2 * ARRAY_SIZE(salinfo_log_name)) +		/* /proc/sal/mca/{event,data} */
+	1];						/* /proc/sal */
+
+/* Some records we get ourselves, some are accessed as saved data in buffers
+ * that are owned by mca.c.
+ */
+struct salinfo_data_saved {
+	u8*			buffer;
+	u64			size;
+	u64			id;
+	int			cpu;
+};
+
+/* State transitions.  Actions are :-
+ *   Write "read <cpunum>" to the data file.
+ *   Write "clear <cpunum>" to the data file.
+ *   Write "oemdata <cpunum> <offset> to the data file.
+ *   Read from the data file.
+ *   Close the data file.
+ *
+ * Start state is NO_DATA.
+ *
+ * NO_DATA
+ *    write "read <cpunum>" -> NO_DATA or LOG_RECORD.
+ *    write "clear <cpunum>" -> NO_DATA or LOG_RECORD.
+ *    write "oemdata <cpunum> <offset> -> return -EINVAL.
+ *    read data -> return EOF.
+ *    close -> unchanged.  Free record areas.
+ *
+ * LOG_RECORD
+ *    write "read <cpunum>" -> NO_DATA or LOG_RECORD.
+ *    write "clear <cpunum>" -> NO_DATA or LOG_RECORD.
+ *    write "oemdata <cpunum> <offset> -> format the oem data, goto OEMDATA.
+ *    read data -> return the INIT/MCA/CMC/CPE record.
+ *    close -> unchanged.  Keep record areas.
+ *
+ * OEMDATA
+ *    write "read <cpunum>" -> NO_DATA or LOG_RECORD.
+ *    write "clear <cpunum>" -> NO_DATA or LOG_RECORD.
+ *    write "oemdata <cpunum> <offset> -> format the oem data, goto OEMDATA.
+ *    read data -> return the formatted oemdata.
+ *    close -> unchanged.  Keep record areas.
+ *
+ * Closing the data file does not change the state.  This allows shell scripts
+ * to manipulate salinfo data, each shell redirection opens the file, does one
+ * action then closes it again.  The record areas are only freed at close when
+ * the state is NO_DATA.
+ */
+enum salinfo_state {
+	STATE_NO_DATA,
+	STATE_LOG_RECORD,
+	STATE_OEMDATA,
+};
+
+struct salinfo_data {
+	volatile cpumask_t	cpu_event;	/* which cpus have outstanding events */
+	struct semaphore	sem;		/* count of cpus with outstanding events (bits set in cpu_event) */
+	u8			*log_buffer;
+	u64			log_size;
+	u8			*oemdata;	/* decoded oem data */
+	u64			oemdata_size;
+	int			open;		/* single-open to prevent races */
+	u8			type;
+	u8			saved_num;	/* using a saved record? */
+	enum salinfo_state	state :8;	/* processing state */
+	u8			padding;
+	int			cpu_check;	/* next CPU to check */
+	struct salinfo_data_saved data_saved[5];/* save last 5 records from mca.c, must be < 255 */
+};
+
+static struct salinfo_data salinfo_data[ARRAY_SIZE(salinfo_log_name)];
+
+static spinlock_t data_lock, data_saved_lock;
+
+/** salinfo_platform_oemdata - optional callback to decode oemdata from an error
+ * record.
+ * @sect_header: pointer to the start of the section to decode.
+ * @oemdata: returns vmalloc area containing the decded output.
+ * @oemdata_size: returns length of decoded output (strlen).
+ *
+ * Description: If user space asks for oem data to be decoded by the kernel
+ * and/or prom and the platform has set salinfo_platform_oemdata to the address
+ * of a platform specific routine then call that routine.  salinfo_platform_oemdata
+ * vmalloc's and formats its output area, returning the address of the text
+ * and its strlen.  Returns 0 for success, -ve for error.  The callback is
+ * invoked on the cpu that generated the error record.
  */
-static struct proc_dir_entry *salinfo_proc_entries[NR_SALINFO_ENTRIES + 1];
+int (*salinfo_platform_oemdata)(const u8 *sect_header, u8 **oemdata, u64 *oemdata_size);
+
+struct salinfo_platform_oemdata_parms {
+	const u8 *efi_guid;
+	u8 **oemdata;
+	u64 *oemdata_size;
+	int ret;
+};
+
+static void
+salinfo_platform_oemdata_cpu(void *context)
+{
+	struct salinfo_platform_oemdata_parms *parms = context;
+	parms->ret = salinfo_platform_oemdata(parms->efi_guid, parms->oemdata, parms->oemdata_size);
+}
+
+static void
+shift1_data_saved (struct salinfo_data *data, int shift)
+{
+	memcpy(data->data_saved+shift, data->data_saved+shift+1,
+	       (ARRAY_SIZE(data->data_saved) - (shift+1)) * sizeof(data->data_saved[0]));
+	memset(data->data_saved + ARRAY_SIZE(data->data_saved) - 1, 0,
+	       sizeof(data->data_saved[0]));
+}
+
+/* This routine is invoked in interrupt context.  Note: mca.c enables
+ * interrupts before calling this code for CMC/CPE.  MCA and INIT events are
+ * not irq safe, do not call any routines that use spinlocks, they may deadlock.
+ *
+ * The buffer passed from mca.c points to the output from ia64_log_get. This is
+ * a persistent buffer but its contents can change between the interrupt and
+ * when user space processes the record.  Save the record id to identify
+ * changes.
+ */
+void
+salinfo_log_wakeup(int type, u8 *buffer, u64 size)
+{
+	struct salinfo_data *data = salinfo_data + type;
+	struct salinfo_data_saved *data_saved;
+	unsigned long flags = 0;
+	int i, irqsafe = type != SAL_INFO_TYPE_MCA && type != SAL_INFO_TYPE_INIT;
+	int saved_size = ARRAY_SIZE(data->data_saved);
+
+	BUG_ON(type >= ARRAY_SIZE(salinfo_log_name));
+
+	if (irqsafe)
+		spin_lock_irqsave(&data_saved_lock, flags);
+	for (i = 0, data_saved = data->data_saved; i < saved_size; ++i, ++data_saved) {
+		if (!data_saved->buffer)
+			break;
+	}
+	if (i = saved_size) {
+		if (!data->saved_num) {
+			shift1_data_saved(data, 0);
+			data_saved = data->data_saved + saved_size - 1;
+		} else
+			data_saved = NULL;
+	}
+	if (data_saved) {
+		data_saved->cpu = smp_processor_id();
+		data_saved->id = ((sal_log_record_header_t *)buffer)->id;
+		data_saved->size = size;
+		data_saved->buffer = buffer;
+	}
+	if (irqsafe)
+		spin_unlock_irqrestore(&data_saved_lock, flags);
+
+	if (!test_and_set_bit(smp_processor_id(), &data->cpu_event)) {
+		if (irqsafe)
+			up(&data->sem);
+	}
+}
+
+static int
+salinfo_event_open(struct inode *inode, struct file *file)
+{
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+	return 0;
+}
+
+static ssize_t
+salinfo_event_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
+{
+	struct inode *inode = file->f_dentry->d_inode;
+	struct proc_dir_entry *entry = PDE(inode);
+	struct salinfo_data *data = entry->data;
+	char cmd[32];
+	size_t size;
+	int i, n, cpu = -1;
+
+retry:
+	if (down_trylock(&data->sem)) {
+		if (file->f_flags & O_NONBLOCK)
+			return -EAGAIN;
+		if (down_interruptible(&data->sem))
+			return -ERESTARTSYS;
+	}
+
+	n = data->cpu_check;
+	for (i = 0; i < NR_CPUS; i++) {
+		if (test_bit(n, &data->cpu_event)) {
+			cpu = n;
+			break;
+		}
+		if (++n = NR_CPUS)
+			n = 0;
+	}
+
+	if (cpu = -1)
+		goto retry;
+
+	/* events are sticky until the user says "clear" */
+	up(&data->sem);
+
+	/* for next read, start checking at next CPU */
+	data->cpu_check = cpu;
+	if (++data->cpu_check = NR_CPUS)
+		data->cpu_check = 0;
+
+	snprintf(cmd, sizeof(cmd), "read %d\n", cpu);
+
+	size = strlen(cmd);
+	if (size > count)
+		size = count;
+	if (copy_to_user(buffer, cmd, size))
+		return -EFAULT;
+
+	return size;
+}
+
+static struct file_operations salinfo_event_fops = {
+	.open  = salinfo_event_open,
+	.read  = salinfo_event_read,
+};
+
+static int
+salinfo_log_open(struct inode *inode, struct file *file)
+{
+	struct proc_dir_entry *entry = PDE(inode);
+	struct salinfo_data *data = entry->data;
+
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+
+	spin_lock(&data_lock);
+	if (data->open) {
+		spin_unlock(&data_lock);
+		return -EBUSY;
+	}
+	data->open = 1;
+	spin_unlock(&data_lock);
+
+	if (data->state = STATE_NO_DATA &&
+	    !(data->log_buffer = vmalloc(ia64_sal_get_state_info_size(data->type)))) {
+		data->open = 0;
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
+static int
+salinfo_log_release(struct inode *inode, struct file *file)
+{
+	struct proc_dir_entry *entry = PDE(inode);
+	struct salinfo_data *data = entry->data;
+
+	if (data->state = STATE_NO_DATA) {
+		vfree(data->log_buffer);
+		vfree(data->oemdata);
+		data->log_buffer = NULL;
+		data->oemdata = NULL;
+	}
+	spin_lock(&data_lock);
+	data->open = 0;
+	spin_unlock(&data_lock);
+	return 0;
+}
+
+static void
+call_on_cpu(int cpu, void (*fn)(void *), void *arg)
+{
+	cpumask_t save_cpus_allowed, new_cpus_allowed;
+	memcpy(&save_cpus_allowed, &current->cpus_allowed, sizeof(save_cpus_allowed));
+	memset(&new_cpus_allowed, 0, sizeof(new_cpus_allowed));
+	set_bit(cpu, &new_cpus_allowed);
+	set_cpus_allowed(current, new_cpus_allowed);
+	(*fn)(arg);
+	set_cpus_allowed(current, save_cpus_allowed);
+}
+
+static void
+salinfo_log_read_cpu(void *context)
+{
+	struct salinfo_data *data = context;
+	data->log_size = ia64_sal_get_state_info(data->type, (u64 *) data->log_buffer);
+}
+
+static void
+salinfo_log_new_read(int cpu, struct salinfo_data *data)
+{
+	struct salinfo_data_saved *data_saved;
+	unsigned long flags;
+	int i;
+	int saved_size = ARRAY_SIZE(data->data_saved);
+
+	data->saved_num = 0;
+	spin_lock_irqsave(&data_saved_lock, flags);
+retry:
+	for (i = 0, data_saved = data->data_saved; i < saved_size; ++i, ++data_saved) {
+		if (data_saved->buffer && data_saved->cpu = cpu) {
+			sal_log_record_header_t *rh = (sal_log_record_header_t *)(data_saved->buffer);
+			data->log_size = data_saved->size;
+			memcpy(data->log_buffer, rh, data->log_size);
+			barrier();	/* id check must not be moved */
+			if (rh->id = data_saved->id) {
+				data->saved_num = i+1;
+				break;
+			}
+			/* saved record changed by mca.c since interrupt, discard it */
+			shift1_data_saved(data, i);
+			goto retry;
+		}
+	}
+	spin_unlock_irqrestore(&data_saved_lock, flags);
+
+	if (!data->saved_num)
+		call_on_cpu(cpu, salinfo_log_read_cpu, data);
+	data->state = data->log_size ? STATE_LOG_RECORD : STATE_NO_DATA;
+}
+
+static ssize_t
+salinfo_log_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
+{
+	struct inode *inode = file->f_dentry->d_inode;
+	struct proc_dir_entry *entry = PDE(inode);
+	struct salinfo_data *data = entry->data;
+	void *saldata;
+	size_t size;
+	u8 *buf;
+	u64 bufsize;
+
+	if (data->state = STATE_LOG_RECORD) {
+		buf = data->log_buffer;
+		bufsize = data->log_size;
+	} else if (data->state = STATE_OEMDATA) {
+		buf = data->oemdata;
+		bufsize = data->oemdata_size;
+	} else {
+		buf = NULL;
+		bufsize = 0;
+	}
+	if (*ppos >= bufsize)
+		return 0;
+
+	saldata = buf + file->f_pos;
+	size = bufsize - file->f_pos;
+	if (size > count)
+		size = count;
+	if (copy_to_user(buffer, saldata, size))
+		return -EFAULT;
+
+	*ppos += size;
+	return size;
+}
+
+static void
+salinfo_log_clear_cpu(void *context)
+{
+	struct salinfo_data *data = context;
+	ia64_sal_clear_state_info(data->type);
+}
+
+static int
+salinfo_log_clear(struct salinfo_data *data, int cpu)
+{
+	data->state = STATE_NO_DATA;
+	if (!test_bit(cpu, &data->cpu_event))
+		return 0;
+	down(&data->sem);
+	clear_bit(cpu, &data->cpu_event);
+	if (data->saved_num) {
+		unsigned long flags;
+		spin_lock_irqsave(&data_saved_lock, flags);
+		shift1_data_saved(data, data->saved_num - 1 );
+		data->saved_num = 0;
+		spin_unlock_irqrestore(&data_saved_lock, flags);
+	}
+	call_on_cpu(cpu, salinfo_log_clear_cpu, data);
+
+	/* clearing a record may make a new record visible */
+	salinfo_log_new_read(cpu, data);
+	if (data->state = STATE_LOG_RECORD &&
+	    !test_and_set_bit(cpu,  &data->cpu_event))
+		up(&data->sem);
+	return 0;
+}
+
+static ssize_t
+salinfo_log_write(struct file *file, const char *buffer, size_t count, loff_t *ppos)
+{
+	struct inode *inode = file->f_dentry->d_inode;
+	struct proc_dir_entry *entry = PDE(inode);
+	struct salinfo_data *data = entry->data;
+	char cmd[32];
+	size_t size;
+	u32 offset;
+	int cpu;
+
+	size = sizeof(cmd);
+	if (count < size)
+		size = count;
+	if (copy_from_user(cmd, buffer, size))
+		return -EFAULT;
+
+	if (sscanf(cmd, "read %d", &cpu) = 1) {
+		salinfo_log_new_read(cpu, data);
+	} else if (sscanf(cmd, "clear %d", &cpu) = 1) {
+		int ret;
+		if ((ret = salinfo_log_clear(data, cpu)))
+			count = ret;
+	} else if (sscanf(cmd, "oemdata %d %d", &cpu, &offset) = 2) {
+		if (data->state != STATE_LOG_RECORD && data->state != STATE_OEMDATA)
+			return -EINVAL;
+		if (offset > data->log_size - sizeof(efi_guid_t))
+			return -EINVAL;
+		data->state = STATE_OEMDATA;
+		if (salinfo_platform_oemdata) {
+			struct salinfo_platform_oemdata_parms parms = {
+				.efi_guid = data->log_buffer + offset,
+				.oemdata = &data->oemdata,
+				.oemdata_size = &data->oemdata_size
+			};
+			call_on_cpu(cpu, salinfo_platform_oemdata_cpu, &parms);
+			if (parms.ret)
+				count = parms.ret;
+		} else
+			data->oemdata_size = 0;
+	} else
+		return -EINVAL;
+
+	return count;
+}
+
+static struct file_operations salinfo_data_fops = {
+	.open    = salinfo_log_open,
+	.release = salinfo_log_release,
+	.read    = salinfo_log_read,
+	.write   = salinfo_log_write,
+};
 
 static int __init
 salinfo_init(void)
 {
 	struct proc_dir_entry *salinfo_dir; /* /proc/sal dir entry */
 	struct proc_dir_entry **sdir = salinfo_proc_entries; /* keeps track of every entry */
-	int i;
+	struct proc_dir_entry *dir, *entry;
+	struct salinfo_data *data;
+	int i, j, online;
 
 	salinfo_dir = proc_mkdir("sal", NULL);
+	if (!salinfo_dir)
+		return 0;
 
 	for (i=0; i < NR_SALINFO_ENTRIES; i++) {
 		/* pass the feature bit in question as misc data */
-		*sdir = create_proc_read_entry (salinfo_entries[i].name, 0, salinfo_dir,
+		*sdir++ = create_proc_read_entry (salinfo_entries[i].name, 0, salinfo_dir,
 						  salinfo_read, (void *)salinfo_entries[i].feature);
-		if (*sdir)
-			(*sdir)->owner = THIS_MODULE;
-		sdir++;
 	}
-	*sdir++ = salinfo_dir;
-
-	return 0;
-}
 
-static void __exit
-salinfo_exit(void)
-{
-	int i = 0;
+	for (i = 0; i < ARRAY_SIZE(salinfo_log_name); i++) {
+		data = salinfo_data + i;
+		data->type = i;
+		sema_init(&data->sem, 0);
+		dir = proc_mkdir(salinfo_log_name[i], salinfo_dir);
+		if (!dir)
+			continue;
+
+		entry = create_proc_entry("event", S_IRUSR, dir);
+		if (!entry)
+			continue;
+		entry->data = data;
+		entry->proc_fops = &salinfo_event_fops;
+		*sdir++ = entry;
+
+		entry = create_proc_entry("data", S_IRUSR | S_IWUSR, dir);
+		if (!entry)
+			continue;
+		entry->data = data;
+		entry->proc_fops = &salinfo_data_fops;
+		*sdir++ = entry;
+
+		/* we missed any events before now */
+		online = 0;
+		for (j = 0; j < NR_CPUS; j++)
+			if (cpu_online(j)) {
+				set_bit(j, &data->cpu_event);
+				++online;
+			}
+		sema_init(&data->sem, online);
 
-	for (i = 0; i < NR_SALINFO_ENTRIES ; i++) {
-		if (salinfo_proc_entries[i])
-			remove_proc_entry (salinfo_proc_entries[i]->name, NULL);
+		*sdir++ = dir;
 	}
+
+	*sdir++ = salinfo_dir;
+
+	return 0;
 }
 
 /*
@@ -102,4 +584,3 @@ salinfo_read(char *page, char **start, o
 }
 
 module_init(salinfo_init);
-module_exit(salinfo_exit);
Index: 9.2/arch/ia64/kernel/mca.c
--- 9.2/arch/ia64/kernel/mca.c Mon, 20 Oct 2003 11:16:44 +1000 kaos (linux-2.6-test/I/e/30_mca.c 1.2.1.4 644)
+++ 9.4/arch/ia64/kernel/mca.c Tue, 25 Nov 2003 19:30:04 +1100 kaos (linux-2.6-test/I/e/30_mca.c 1.2.1.6 644)
@@ -87,6 +87,7 @@ static void			ia64_mca_wakeup_all(void);
 static void			ia64_log_init(int);
 extern void			ia64_monarch_init_handler (void);
 extern void			ia64_slave_init_handler (void);
+static u64			ia64_log_get(int sal_info_type, u8 **buffer);
 extern struct hw_interrupt_type	irq_type_iosapic_level;
 
 static struct irqaction cmci_irqaction = {
@@ -149,12 +150,14 @@ static int cmc_polling_enabled = 1;
  */
 static int cpe_poll_enabled = 1;
 
+extern void salinfo_log_wakeup(int type, u8 *buffer, u64 size);
+
 /*
  *  ia64_mca_log_sal_error_record
  *
- *  This function retrieves a specified error record type from SAL, sends it to
- *  the system log, and notifies SALs to clear the record from its non-volatile
- *  memory.
+ *  This function retrieves a specified error record type from SAL,
+ *  wakes up any processes waiting for error records, and sends it to
+ *  the system log.
  *
  *  Inputs  :   sal_info_type   (Type of error record MCA/CMC/CPE/INIT)
  *  Outputs :   platform error status
@@ -162,11 +165,13 @@ static int cpe_poll_enabled = 1;
 int
 ia64_mca_log_sal_error_record(int sal_info_type, int called_from_init)
 {
-	int platform_err = 0;
+	u8 *buffer;
+	u64 size;
+	int platform_err;
 
-	/* Get the MCA error record */
-	if (!ia64_log_get(sal_info_type, (prfunc_t)printk))
-		return platform_err;		/* no record retrieved */
+	size = ia64_log_get(sal_info_type, &buffer);
+	if (!size)
+		return 0;
 
 	/* TODO:
 	 * 1. analyze error logs to determine recoverability
@@ -174,10 +179,10 @@ ia64_mca_log_sal_error_record(int sal_in
 	 * 3. set ia64_os_mca_recovery_successful flag, if applicable
 	 */
 
+	salinfo_log_wakeup(sal_info_type, buffer, size);
 	platform_err = ia64_log_print(sal_info_type, (prfunc_t)printk);
-	/* temporary: only clear SAL logs on hardware-corrected errors
-		or if we're logging an error after an MCA-initiated reboot */
-	if ((sal_info_type > 1) || (called_from_init))
+	/* Clear logs from corrected errors in case there's no user-level logger */
+	if (sal_info_type = SAL_INFO_TYPE_CPE || sal_info_type = SAL_INFO_TYPE_CMC)
 		ia64_sal_clear_state_info(sal_info_type);
 
 	return platform_err;
@@ -450,7 +455,10 @@ static void
 ia64_mca_register_cpev (int cpev)
 {
 	/* Register the CPE interrupt vector with SAL */
-	if (ia64_sal_mc_set_params(SAL_MC_PARAM_CPE_INT, SAL_MC_PARAM_MECHANISM_INT, cpev, 0, 0)) {
+	struct ia64_sal_retval isrv;
+
+	isrv = ia64_sal_mc_set_params(SAL_MC_PARAM_CPE_INT, SAL_MC_PARAM_MECHANISM_INT, cpev, 0, 0);
+	if (isrv.status) {
 		printk(KERN_ERR "ia64_mca_platform_init: failed to register Corrected "
 		       "Platform Error interrupt vector with SAL.\n");
 		return;
@@ -629,6 +637,8 @@ ia64_mca_init(void)
 	ia64_fptr_t *mca_hldlr_ptr = (ia64_fptr_t *)ia64_os_mca_dispatch;
 	int i;
 	s64 rc;
+	struct ia64_sal_retval isrv;
+	u64 timeout = IA64_MCA_RENDEZ_TIMEOUT;	/* platform specific */
 
 	IA64_MCA_DEBUG("ia64_mca_init: begin\n");
 
@@ -644,23 +654,33 @@ ia64_mca_init(void)
 	 */
 
 	/* Register the rendezvous interrupt vector with SAL */
-	if ((rc = ia64_sal_mc_set_params(SAL_MC_PARAM_RENDEZ_INT,
-					 SAL_MC_PARAM_MECHANISM_INT,
-					 IA64_MCA_RENDEZ_VECTOR,
-					 IA64_MCA_RENDEZ_TIMEOUT,
-					 SAL_MC_PARAM_RZ_ALWAYS)))
-	{
+	while (1) {
+		isrv = ia64_sal_mc_set_params(SAL_MC_PARAM_RENDEZ_INT,
+					      SAL_MC_PARAM_MECHANISM_INT,
+					      IA64_MCA_RENDEZ_VECTOR,
+					      timeout,
+					      SAL_MC_PARAM_RZ_ALWAYS);
+		rc = isrv.status;
+		if (rc = 0)
+			break;
+		if (rc = -2) {
+			printk(KERN_INFO "ia64_mca_init: increasing MCA rendezvous timeout from "
+				"%ld to %ld\n", timeout, isrv.v0);
+			timeout = isrv.v0;
+			continue;
+		}
 		printk(KERN_ERR "ia64_mca_init: Failed to register rendezvous interrupt "
 		       "with SAL.  rc = %ld\n", rc);
 		return;
 	}
 
 	/* Register the wakeup interrupt vector with SAL */
-	if ((rc = ia64_sal_mc_set_params(SAL_MC_PARAM_RENDEZ_WAKEUP,
-					 SAL_MC_PARAM_MECHANISM_INT,
-					 IA64_MCA_WAKEUP_VECTOR,
-					 0, 0)))
-	{
+	isrv = ia64_sal_mc_set_params(SAL_MC_PARAM_RENDEZ_WAKEUP,
+				      SAL_MC_PARAM_MECHANISM_INT,
+				      IA64_MCA_WAKEUP_VECTOR,
+				      0, 0);
+	rc = isrv.status;
+	if (rc) {
 		printk(KERN_ERR "ia64_mca_init: Failed to register wakeup interrupt with SAL.  "
 		       "rc = %ld\n", rc);
 		return;
@@ -1399,12 +1419,12 @@ ia64_log_init(int sal_info_type)
  *	Get the current MCA log from SAL and copy it into the OS log buffer.
  *
  *  Inputs  :   info_type   (SAL_INFO_TYPE_{MCA,INIT,CMC,CPE})
- *              prfunc      (fn ptr of log output function)
  *  Outputs :   size        (total record length)
+ *              *buffer     (ptr to error record)
  *
  */
-u64
-ia64_log_get(int sal_info_type, prfunc_t prfunc)
+static u64
+ia64_log_get(int sal_info_type, u8 **buffer)
 {
 	sal_log_record_header_t     *log_buffer;
 	u64                         total_len = 0;
@@ -1422,6 +1442,7 @@ ia64_log_get(int sal_info_type, prfunc_t
 		IA64_LOG_UNLOCK(sal_info_type);
 		IA64_MCA_DEBUG("ia64_log_get: SAL error record type %d retrieved. "
 			       "Record length = %ld\n", sal_info_type, total_len);
+		*buffer = (u8 *) log_buffer;
 		return total_len;
 	} else {
 		IA64_LOG_UNLOCK(sal_info_type);
@@ -1466,7 +1487,7 @@ ia64_log_prt_oem_data (int header_len, i
 void
 ia64_log_rec_header_print (sal_log_record_header_t *lh, prfunc_t prfunc)
 {
-	prfunc("+Err Record ID: %d    SAL Rev: %2x.%02x\n", lh->id,
+	prfunc("+Err Record ID: %ld    SAL Rev: %2x.%02x\n", lh->id,
 			lh->revision.major, lh->revision.minor);
 	prfunc("+Time: %02x/%02x/%02x%02x %02x:%02x:%02x    Severity %d\n",
 			lh->timestamp.slh_month, lh->timestamp.slh_day,
@@ -1589,13 +1610,13 @@ ia64_log_cache_check_info_print (int    
 	if (info->dl)
 		prfunc(" Line: Data,");
 	prfunc(" Operation: %s,", pal_cache_op[info->op]);
-	if (info->wv)
+	if (info->wiv)
 		prfunc(" Way: %d,", info->way);
 	if (cache_check_info->valid.target_identifier)
 		/* Hope target address is saved in target_identifier */
 		if (info->tv)
 			prfunc(" Target Addr: 0x%lx,", target_addr);
-	if (info->mc)
+	if (info->mcc)
 		prfunc(" MC: Corrected");
 	prfunc("\n");
 }
@@ -1631,13 +1652,13 @@ ia64_log_tlb_check_info_print (int      
 		prfunc("  Failure: Data Translation Cache");
 	if (info->itr) {
 		prfunc("  Failure: Instruction Translation Register");
-		prfunc(" ,Slot: %d", info->tr_slot);
+		prfunc(" ,Slot: %ld", info->tr_slot);
 	}
 	if (info->dtr) {
 		prfunc("  Failure: Data Translation Register");
-		prfunc(" ,Slot: %d", info->tr_slot);
+		prfunc(" ,Slot: %ld", info->tr_slot);
 	}
-	if (info->mc)
+	if (info->mcc)
 		prfunc(" ,MC: Corrected");
 	prfunc("\n");
 }
@@ -1683,7 +1704,7 @@ ia64_log_bus_check_info_print (int      
 		prfunc(" ,Error: Internal");
 	if (info->eb)
 		prfunc(" ,Error: External");
-	if (info->mc)
+	if (info->mcc)
 		prfunc(" ,MC: Corrected");
 	if (info->tv)
 		prfunc(" ,Target Address: 0x%lx", targ_addr);
@@ -1970,9 +1991,9 @@ ia64_log_plat_specific_err_info_print (s
 		ia64_log_prt_guid(&psei->guid, prfunc);
 	}
 	if (psei->valid.oem_data) {
-		platform_plat_specific_err_print((int)psei->header.len,
-				      (int)sizeof(sal_log_plat_specific_err_info_t) - 1,
-				      &(psei->oem_data[0]), prfunc);
+		platform_plat_specific_err_print((int) psei->header.len,
+				      (char *) psei->oem_data - (char *) psei,
+				      &psei->oem_data[0], prfunc);
 	}
 	prfunc("\n");
 }
@@ -2352,13 +2373,12 @@ ia64_log_print(int sal_info_type, prfunc
 
 	switch(sal_info_type) {
 	      case SAL_INFO_TYPE_MCA:
-		prfunc("+BEGIN HARDWARE ERROR STATE AT MCA\n");
-		platform_err = ia64_log_platform_info_print(IA64_LOG_CURR_BUFFER(sal_info_type),
-							    prfunc);
-		prfunc("+END HARDWARE ERROR STATE AT MCA\n");
+		prfunc("+CPU %d: SAL log contains MCA error record\n", smp_processor_id());
+		ia64_log_rec_header_print(IA64_LOG_CURR_BUFFER(sal_info_type), prfunc);
 		break;
 	      case SAL_INFO_TYPE_INIT:
-		prfunc("+MCA INIT ERROR LOG (UNIMPLEMENTED)\n");
+		prfunc("+CPU %d: SAL log contains INIT error record\n", smp_processor_id());
+		ia64_log_rec_header_print(IA64_LOG_CURR_BUFFER(sal_info_type), prfunc);
 		break;
 	      case SAL_INFO_TYPE_CMC:
 		prfunc("+BEGIN HARDWARE ERROR STATE AT CMC\n");


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [patch] 2.6.0-test9 pal/sal/salinfo/mca
@ 2003-11-25 18:20 David Mosberger
  2003-11-25 22:06 ` Keith Owens
                   ` (6 more replies)
  0 siblings, 7 replies; 9+ messages in thread
From: David Mosberger @ 2003-11-25 18:20 UTC (permalink / raw)
  To: linux-ia64


  Keith> This converts 2.6 to use salinfo instead of printing
  Keith> CMC/CPE/MCA/INIT records in the kernel.  It makes the two
  Keith> kernel versions as close together as possible.

The patch is fine with me, but given it's size, it's 2.6.1 material.

	--david

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [patch] 2.6.0-test9 pal/sal/salinfo/mca
  2003-11-25 18:20 [patch] 2.6.0-test9 pal/sal/salinfo/mca David Mosberger
@ 2003-11-25 22:06 ` Keith Owens
  2003-12-04  1:38 ` Ben Woodard
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 9+ messages in thread
From: Keith Owens @ 2003-11-25 22:06 UTC (permalink / raw)
  To: linux-ia64

On Tue, 25 Nov 2003 10:20:27 -0800, 
David Mosberger <davidm@napali.hpl.hp.com> wrote:
>
>  Keith> This converts 2.6 to use salinfo instead of printing
>  Keith> CMC/CPE/MCA/INIT records in the kernel.  It makes the two
>  Keith> kernel versions as close together as possible.
>
>The patch is fine with me, but given it's size, it's 2.6.1 material.

Agreed, I just wanted it up for review.


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [patch] 2.6.0-test9 pal/sal/salinfo/mca
  2003-11-25 18:20 [patch] 2.6.0-test9 pal/sal/salinfo/mca David Mosberger
  2003-11-25 22:06 ` Keith Owens
@ 2003-12-04  1:38 ` Ben Woodard
  2003-12-04  2:05 ` Keith Owens
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 9+ messages in thread
From: Ben Woodard @ 2003-12-04  1:38 UTC (permalink / raw)
  To: linux-ia64

On Tue, 2003-11-25 at 00:37, Keith Owens wrote:
> Forward port the recent changes to pal.h, sal.h, mca.h, salinfo.c and
> mca.c from 2.4.23-rc2 to 2.6.0-test9.
> 
> This converts 2.6 to use salinfo instead of printing CMC/CPE/MCA/INIT
> records in the kernel.  It makes the two kernel versions as close
> together as possible.

I'd like to inquire a bit more into the state of MCA in 2.4 and 2.6. We
are assembling a 1000 node ia64 cluster out of intel Tiger 4 servers and
we want to make sure that MCA works well enough that we can at least get
a good count of the ECC SBE's and panic if we get a MBE. 

We are currently basing our kernel off of the Red Hat Enterprise Linux 3
kernel and we discovered that the implementation of MCA included with it
does not work for us. The most obvious problem is that it never calls
ia64_sal_clear_state_info after fetching a SAL record. Thus the CPE
reasserts itself and the machine effectively locks up infinitely
printing out the same CPE to the console.

So what we are trying to do is improve the state of the MCA handling in
our kernel. I managed a backport of the MCA code from 2.6.0-test9 to 2.4
and it works much better. However, there are a couple of problems with
it that could probably be sorted out by someone who understands the code
better. Keith your message sort of hints that the possibility that the
2.4 kernel's MCA code is further advanced than the 2.6 code. This led us
initially to believe that we could backport the 2.4.23 kernel's MCA code
and have it work. However, taking a look at the 2.4.23 kernel from
kernel.org, it is quickly evident that it doesn't make the needed call
to sal_clear_state_info.

So my question is: should we continue forward with our backport of the
2.6 MCA code or is the 2.4 code actually functional enough to support
our needs and we are missing something in our quick inspection of the
code.

Also if the 2.6 backport is the way to go, would other people be
interested in having the 2.6 MCA code backport made available? Once we
get it working satisfactorily here, I'm going to push for it to be
integrated into the Red Hat kernel. Is this something that, would be
worthwhile to push upstream?

-ben




^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [patch] 2.6.0-test9 pal/sal/salinfo/mca
  2003-11-25 18:20 [patch] 2.6.0-test9 pal/sal/salinfo/mca David Mosberger
  2003-11-25 22:06 ` Keith Owens
  2003-12-04  1:38 ` Ben Woodard
@ 2003-12-04  2:05 ` Keith Owens
  2003-12-04  6:23 ` Stephane Eranian
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 9+ messages in thread
From: Keith Owens @ 2003-12-04  2:05 UTC (permalink / raw)
  To: linux-ia64

On 03 Dec 2003 17:38:19 -0800, 
Ben Woodard <woodard@redhat.com> wrote:
>On Tue, 2003-11-25 at 00:37, Keith Owens wrote:
>> Forward port the recent changes to pal.h, sal.h, mca.h, salinfo.c and
>> mca.c from 2.4.23-rc2 to 2.6.0-test9.
>> 
>> This converts 2.6 to use salinfo instead of printing CMC/CPE/MCA/INIT
>> records in the kernel.  It makes the two kernel versions as close
>> together as possible.
>
>I'd like to inquire a bit more into the state of MCA in 2.4 and 2.6. We
>are assembling a 1000 node ia64 cluster out of intel Tiger 4 servers and
>we want to make sure that MCA works well enough that we can at least get
>a good count of the ECC SBE's and panic if we get a MBE. 
>
>We are currently basing our kernel off of the Red Hat Enterprise Linux 3
>kernel and we discovered that the implementation of MCA included with it
>does not work for us. The most obvious problem is that it never calls
>ia64_sal_clear_state_info after fetching a SAL record. Thus the CPE
>reasserts itself and the machine effectively locks up infinitely
>printing out the same CPE to the console.

2.4.23 ia64 BK tree has these lines in ia64_mca_log_sal_error_record().

        salinfo_log_wakeup(sal_info_type, buffer, size);
        platform_err = ia64_log_print(sal_info_type, (prfunc_t)printk);
        /* Clear logs from corrected errors in case there's no user-level logger */
        if (sal_info_type = SAL_INFO_TYPE_CPE || sal_info_type = SAL_INFO_TYPE_CMC)
                ia64_sal_clear_state_info(sal_info_type);

so you should be clearing CPE records immediately.  AS 3.0 is probably
out of date in its MCA handling.

>So what we are trying to do is improve the state of the MCA handling in
>our kernel. I managed a backport of the MCA code from 2.6.0-test9 to 2.4
>and it works much better. However, there are a couple of problems with
>it that could probably be sorted out by someone who understands the code
>better. Keith your message sort of hints that the possibility that the
>2.4 kernel's MCA code is further advanced than the 2.6 code.

With my 2.6 patch of 2003-11-25, 2.4 and 2.6 MCA handling is the same,
and it works for CPE.  Grab these files from ia64 2.4 BK and merge them
with the AS 3.0 files, if there is ay doubt, use the ia64 2.4 BK
version.

include/asm-ia64/sal.h
include/asm-ia64/pal.h
include/asm-ia64/mca.h
arch/ia64/Kconfig
arch/ia64/kernel/Makefile
arch/ia64/kernel/salinfo.c
arch/ia64/kernel/mca.c


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [patch] 2.6.0-test9 pal/sal/salinfo/mca
  2003-11-25 18:20 [patch] 2.6.0-test9 pal/sal/salinfo/mca David Mosberger
                   ` (2 preceding siblings ...)
  2003-12-04  2:05 ` Keith Owens
@ 2003-12-04  6:23 ` Stephane Eranian
  2003-12-04 17:45 ` Bjorn Helgaas
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 9+ messages in thread
From: Stephane Eranian @ 2003-12-04  6:23 UTC (permalink / raw)
  To: linux-ia64

Ben,

On Wed, Dec 03, 2003 at 05:38:19PM -0800, Ben Woodard wrote:
> 
> Also if the 2.6 backport is the way to go, would other people be
> interested in having the 2.6 MCA code backport made available? Once we

Yes, it is important to have the full MCA support in RHEL kernel. For
instance, the MCA INIT handler is a very useful piece of code to debug
deadlocks when it is coupled to the kernel stack unwinder (which is 
th default on 2.6). I wish I had this feature today in RHEL-3.0.

-- 
-Stephane

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [patch] 2.6.0-test9 pal/sal/salinfo/mca
  2003-11-25 18:20 [patch] 2.6.0-test9 pal/sal/salinfo/mca David Mosberger
                   ` (3 preceding siblings ...)
  2003-12-04  6:23 ` Stephane Eranian
@ 2003-12-04 17:45 ` Bjorn Helgaas
  2003-12-04 19:44 ` Luck, Tony
  2003-12-04 20:05 ` Bjorn Helgaas
  6 siblings, 0 replies; 9+ messages in thread
From: Bjorn Helgaas @ 2003-12-04 17:45 UTC (permalink / raw)
  To: linux-ia64

On Wednesday 03 December 2003 6:38 pm, Ben Woodard wrote:
> We are currently basing our kernel off of the Red Hat Enterprise Linux 3
> kernel and we discovered that the implementation of MCA included with it
> does not work for us. The most obvious problem is that it never calls
> ia64_sal_clear_state_info after fetching a SAL record. Thus the CPE
> reasserts itself and the machine effectively locks up infinitely
> printing out the same CPE to the console.

I believe this is bug #104667 in the Red Hat bugzilla.  The patch
should be attached to the bug report.  I can't get bugzilla to show
me the report, so I don't know the current status.

> So my question is: should we continue forward with our backport of the
> 2.6 MCA code or is the 2.4 code actually functional enough to support
> our needs and we are missing something in our quick inspection of the
> code.

As Keith mentioned, the current 2.4 and 2.6 MCA code should be
essentially identical.

Bjorn


^ permalink raw reply	[flat|nested] 9+ messages in thread

* RE: [patch] 2.6.0-test9 pal/sal/salinfo/mca
  2003-11-25 18:20 [patch] 2.6.0-test9 pal/sal/salinfo/mca David Mosberger
                   ` (4 preceding siblings ...)
  2003-12-04 17:45 ` Bjorn Helgaas
@ 2003-12-04 19:44 ` Luck, Tony
  2003-12-04 20:05 ` Bjorn Helgaas
  6 siblings, 0 replies; 9+ messages in thread
From: Luck, Tony @ 2003-12-04 19:44 UTC (permalink / raw)
  To: linux-ia64


> As Keith mentioned, the current 2.4 and 2.6 MCA code should be
> essentially identical.

David deferred Keith's last MCA patch for 2.6.1 ... so the current
checked in 2.6 code doesn't have the latest goodies.

Keith's patch can be found here:
 http://marc.theaimsgroup.com/?l=linux-ia64&m\x106974968032730&w=2

Don't forget these all require a user level daemon to pick
up CMC and CPE reports and log them in all their glory.

Keith: did you post salinfo-0.4 yet?  I haven't seen it.

-Tony

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [patch] 2.6.0-test9 pal/sal/salinfo/mca
  2003-11-25 18:20 [patch] 2.6.0-test9 pal/sal/salinfo/mca David Mosberger
                   ` (5 preceding siblings ...)
  2003-12-04 19:44 ` Luck, Tony
@ 2003-12-04 20:05 ` Bjorn Helgaas
  6 siblings, 0 replies; 9+ messages in thread
From: Bjorn Helgaas @ 2003-12-04 20:05 UTC (permalink / raw)
  To: linux-ia64

On Thursday 04 December 2003 12:44 pm, Luck, Tony wrote:
> 
> > As Keith mentioned, the current 2.4 and 2.6 MCA code should be
> > essentially identical.
> 
> David deferred Keith's last MCA patch for 2.6.1 ... so the current
> checked in 2.6 code doesn't have the latest goodies.

Oops, you're right.  I forgot about that.

> Keith's patch can be found here:
>  http://marc.theaimsgroup.com/?l=linux-ia64&m\x106974968032730&w=2
> 
> Don't forget these all require a user level daemon to pick
> up CMC and CPE reports and log them in all their glory.
> 
> Keith: did you post salinfo-0.4 yet?  I haven't seen it.

He sent it to me last week, and I just now dropped it here:

	ftp://ftp.kernel.org/pub/linux/kernel/people/helgaas/salinfo-0.4.tar.gz

(Keith, this includes the patch you sent me on Tuesday).  Keith's done
some Red Hat packaging, too; anybody want to contribute Debian
packaging?

Bjorn


^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2003-12-04 20:05 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2003-11-25 18:20 [patch] 2.6.0-test9 pal/sal/salinfo/mca David Mosberger
2003-11-25 22:06 ` Keith Owens
2003-12-04  1:38 ` Ben Woodard
2003-12-04  2:05 ` Keith Owens
2003-12-04  6:23 ` Stephane Eranian
2003-12-04 17:45 ` Bjorn Helgaas
2003-12-04 19:44 ` Luck, Tony
2003-12-04 20:05 ` Bjorn Helgaas
  -- strict thread matches above, loose matches on Subject: below --
2003-11-25  8:37 Keith Owens

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox